source: tags/ms_r16q2/AWT/AWT_canio.cxx

Last change on this file was 14731, checked in by westram, 8 years ago
  • mark code binding callbacks to non-button-widgets (probably incomplete; see #559 for details)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.3 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : AWT_canio.cxx                                      //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Institute of Microbiology (Technical University Munich)        //
7//   http://www.arb-home.de/                                        //
8//                                                                  //
9// ================================================================ //
10
11#include "awt_canvas.hxx"
12
13#include <aw_file.hxx>
14#include <aw_awar.hxx>
15#include <aw_msg.hxx>
16#include <arb_progress.h>
17#include <aw_root.hxx>
18#include <arbdbt.h>
19#include <arb_defs.h>
20#include <arb_strbuf.h>
21#include <arb_file.h>
22
23using namespace AW;
24
25#define awt_assert(cond) arb_assert(cond)
26
27// --------------------------------------------------------------------------------
28
29#define AWAR_CANIO                 "NT/print/"
30#define AWAR_CANIO_LANDSCAPE       AWAR_CANIO "landscape"
31#define AWAR_CANIO_CLIP            AWAR_CANIO "clip"
32#define AWAR_CANIO_HANDLES         AWAR_CANIO "handles"
33#define AWAR_CANIO_COLOR           AWAR_CANIO "color"
34#define AWAR_CANIO_DEST            AWAR_CANIO "dest"
35#define AWAR_CANIO_PRINTER         AWAR_CANIO "printer"
36#define AWAR_CANIO_OVERLAP_WANTED  AWAR_CANIO "overlap"
37#define AWAR_CANIO_OVERLAP_PERCENT AWAR_CANIO "operc"
38#define AWAR_CANIO_BORDERSIZE      AWAR_CANIO "border"
39#define AWAR_CANIO_PAPER           AWAR_CANIO "paper"
40#define AWAR_CANIO_PAPER_USABLE    AWAR_CANIO "useable"
41#define AWAR_CANIO_F2DBUG          AWAR_CANIO "f2dbug"
42#define AWAR_CANIO_PAGES           AWAR_CANIO "pages"
43#define AWAR_CANIO_PAGELOCK        AWAR_CANIO "plock"
44
45#define AWAR_CANIO_TMP "tmp/" AWAR_CANIO
46
47#define AWAR_CANIO_MAGNIFICATION AWAR_CANIO_TMP "magnification"
48#define AWAR_CANIO_OVERLAP       AWAR_CANIO_TMP "overlap"
49#define AWAR_CANIO_GFX_SX        AWAR_CANIO_TMP "gsizex" // graphic size in inch
50#define AWAR_CANIO_GFX_SY        AWAR_CANIO_TMP "gsizey"
51#define AWAR_CANIO_OUT_SX        AWAR_CANIO_TMP "osizex" // output size in inch
52#define AWAR_CANIO_OUT_SY        AWAR_CANIO_TMP "osizey"
53#define AWAR_CANIO_PAPER_SX      AWAR_CANIO_TMP "psizex" // paper size in inch
54#define AWAR_CANIO_PAPER_SY      AWAR_CANIO_TMP "psizey"
55#define AWAR_CANIO_PAGE_SX       AWAR_CANIO_TMP "sizex"  // size in pages
56#define AWAR_CANIO_PAGE_SY       AWAR_CANIO_TMP "sizey"
57
58#define AWAR_CANIO_FILE_BASE   AWAR_CANIO_TMP "file"
59#define AWAR_CANIO_FILE_NAME   AWAR_CANIO_FILE_BASE "/file_name"
60#define AWAR_CANIO_FILE_DIR    AWAR_CANIO_FILE_BASE "/directory"
61#define AWAR_CANIO_FILE_FILTER AWAR_CANIO_FILE_BASE "/filter"
62
63// --------------------------------------------------------------------------------
64
65enum PrintDest {
66    PDEST_PRINTER    = 0,
67    PDEST_POSTSCRIPT = 1,
68    PDEST_PREVIEW    = 2,
69};
70
71// --------------------------------------------------------------------------------
72
73enum LengthUnit { INCH, MM };
74
75static const float mm_per_inch = 25.4;
76inline float inch2mm(float inches) { return inches*mm_per_inch; }
77inline float mm2inch(float mms) { return mms/mm_per_inch; }
78
79class PaperFormat {
80    const char *description;
81    const char *fig2dev_val;
82    LengthUnit  unit;
83    float      shortSide, longSide;
84
85public:
86    PaperFormat(const char *name, LengthUnit lu, float shortSide_, float longSide_)
87        : description(name),
88          fig2dev_val(name),
89          unit(lu),
90          shortSide(shortSide_),
91          longSide(longSide_)
92    {
93        awt_assert(shortSide<longSide);
94    }
95    PaperFormat(const char *aname, const char *fname, LengthUnit lu, float shortSide_, float longSide_)
96        : description(aname),
97          fig2dev_val(fname),
98          unit(lu),
99          shortSide(shortSide_),
100          longSide(longSide_)
101    {
102        awt_assert(shortSide<longSide);
103    }
104
105    float short_inch() const { return unit == INCH ? shortSide : mm2inch(shortSide); }
106    float long_inch()  const { return unit == INCH ? longSide : mm2inch(longSide); }
107
108    const char *get_description() const { return description; }
109    const char *get_fig2dev_val() const { return fig2dev_val; }
110};
111
112// (c&p from fig2dev:)
113//  Available paper sizes are:
114//      "Letter" (8.5" x 11" also "A"),
115//      "Legal" (11" x 14")
116//      "Ledger" (11" x 17"),
117//      "Tabloid" (17" x 11", really Ledger in Landscape mode),
118//      "A" (8.5" x 11" also "Letter"),
119//      "B" (11" x 17" also "Ledger"),
120//      "C" (17" x 22"),
121//      "D" (22" x 34"),
122//      "E" (34" x 44"),
123//      "A4" (21  cm x  29.7cm),
124//      "A3" (29.7cm x  42  cm),
125//      "A2" (42  cm x  59.4cm),
126//      "A1" (59.4cm x  84.1cm),
127//      "A0" (84.1cm x 118.9cm),
128//      and "B5" (18.2cm x 25.7cm).
129
130static PaperFormat knownPaperFormat[] = {
131    PaperFormat("A4", MM, 210, 297), // first is the default
132    PaperFormat("A3", MM, 297, 420),
133    PaperFormat("A2", MM, 420, 594),
134    PaperFormat("A1", MM, 594, 841),
135    PaperFormat("A0", MM, 841, 1189),
136    PaperFormat("B5", MM, 182, 257),
137   
138    PaperFormat("A (Letter)", "A", INCH, 8.5, 11),
139    PaperFormat("Legal",           INCH, 11, 14),
140    PaperFormat("B (Ledger)", "B", INCH, 11, 17),
141    PaperFormat("C",          "C", INCH, 17, 22),
142    PaperFormat("D",          "D", INCH, 22, 34),
143    PaperFormat("E",          "E", INCH, 34, 44),
144};
145
146// --------------------------------------------------------------------------------
147
148static Rectangle get_drawsize(AWT_canvas *scr, bool draw_all) {
149    // returns size of drawn graphic in screen-coordinates
150   
151    Rectangle       drawsize;
152    GB_transaction  ta(scr->gb_main);
153    AW_device_size *size_device = scr->aww->get_size_device(AW_MIDDLE_AREA);
154
155    if (draw_all) {
156        size_device->reset();
157        size_device->zoom(scr->trans_to_fit);
158        size_device->set_filter(AW_PRINTER|AW_PRINTER_EXT);
159        scr->gfx->show(size_device);
160        drawsize = size_device->get_size_information();
161    }
162    else {
163        drawsize = Rectangle(size_device->get_area_size(), INCLUSIVE_OUTLINE);
164    }
165
166    return drawsize;
167}
168
169static Rectangle add_border_to_drawsize(const Rectangle& drawsize, float border_percent) {
170    float  borderratio     = border_percent*.01;
171    float  draw2bordersize = -borderratio/(borderratio-1.0);
172    Vector bordersize      = drawsize.diagonal() * (draw2bordersize*0.5);
173
174    return Rectangle(drawsize.upper_left_corner()-bordersize,
175                     drawsize.lower_right_corner()+bordersize);
176}
177
178static void awt_print_tree_check_size(UNFIXED, AWT_canvas *scr) {
179    AW_root   *awr         = scr->awr;
180    long       draw_all    = awr->awar(AWAR_CANIO_CLIP)->read_int();
181    float      border      = awr->awar(AWAR_CANIO_BORDERSIZE)->read_float();
182    Rectangle  drawsize    = get_drawsize(scr, draw_all);
183    Rectangle  with_border = add_border_to_drawsize(drawsize, border);
184
185    awr->awar(AWAR_CANIO_GFX_SX)->write_float(with_border.width()/DPI_SCREEN);
186    awr->awar(AWAR_CANIO_GFX_SY)->write_float(with_border.height()/DPI_SCREEN);
187}
188
189inline int xy2pages(float sx, float sy) {
190    return (int(sx+0.99)*int(sy+0.99));
191}
192
193static bool allow_page_size_check_cb = true;
194static bool allow_overlap_toggled_cb = true;
195
196inline void set_paper_size_xy(AW_root *awr, float px, float py) {
197    // modify papersize but perform only one callback
198
199    bool old_allow           = allow_page_size_check_cb;
200    allow_page_size_check_cb = false;
201    awr->awar(AWAR_CANIO_PAPER_SX)->write_float(px);
202    allow_page_size_check_cb = old_allow;
203    awr->awar(AWAR_CANIO_PAPER_SY)->write_float(py);
204}
205
206static void overlap_toggled_cb(AW_root *awr) {
207    if (allow_overlap_toggled_cb) {
208        int new_val = awr->awar(AWAR_CANIO_OVERLAP)->read_int();
209        awr->awar(AWAR_CANIO_OVERLAP_WANTED)->write_int(new_val);
210    }
211}
212
213static long calc_mag_from_psize(AW_root *awr, float papersize, float gfxsize, float wantedpages, bool use_x) {
214    bool  wantOverlap = awr->awar(AWAR_CANIO_OVERLAP_WANTED)->read_int();
215    float usableSize  = 0;
216
217    if (wantOverlap && wantedpages>1) {
218        float overlapPercent = awr->awar(AWAR_CANIO_OVERLAP_PERCENT)->read_float();
219        float usableRatio    = (100.0-overlapPercent)/100.0;
220
221        // See also fig2devbug in page_size_check_cb()
222        bool fig2devbug = !use_x && awr->awar(AWAR_CANIO_F2DBUG)->read_int();
223        if (fig2devbug) {
224            bool landscape = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
225            fig2devbug     = fig2devbug && !landscape; // only occurs in portrait mode
226        }
227
228        if (fig2devbug) {
229            usableSize = wantedpages*papersize*usableRatio;
230        }
231        else {
232            usableSize = (papersize*usableRatio)*(wantedpages-1)+papersize;
233        }
234    }
235    else {
236        usableSize = wantedpages*papersize;
237    }
238
239    return usableSize*100/gfxsize; // always "round" to floor
240}
241
242static void set_mag_from_psize(AW_root *awr, bool use_x) {
243    const char *papersize_name   = use_x ? AWAR_CANIO_PAPER_SX : AWAR_CANIO_PAPER_SY;
244    const char *gfxsize_name     = use_x ? AWAR_CANIO_GFX_SX : AWAR_CANIO_GFX_SY;
245    const char *wantedpages_name = use_x ? AWAR_CANIO_PAGE_SX : AWAR_CANIO_PAGE_SY;
246
247    float papersize   = awr->awar(papersize_name)->read_float();
248    float gfxsize     = awr->awar(gfxsize_name)->read_float();
249    float wantedpages = awr->awar(wantedpages_name)->read_float();
250    long  mag         = calc_mag_from_psize(awr, papersize, gfxsize, wantedpages, use_x);
251
252    awr->awar(AWAR_CANIO_MAGNIFICATION)->write_int(mag);
253}
254
255static void fit_pages(AW_root *awr, int wanted_pages, bool allow_orientation_change) {
256    int         best_orientation    = -1;
257    const char *best_zoom_awar_name = 0;
258    float       best_zoom           = 0;
259    int         best_magnification  = 0;
260    int         best_pages          = 0;
261
262    bool lockpages = awr->awar(AWAR_CANIO_PAGELOCK)->read_int();
263    awr->awar(AWAR_CANIO_PAGELOCK)->write_int(0);
264
265    if (!allow_orientation_change) {
266        best_orientation = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
267    }
268
269    for (int o = 0; o <= 1; ++o) {
270        if (!allow_orientation_change && o != best_orientation) continue;
271
272        awr->awar(AWAR_CANIO_LANDSCAPE)->write_int(o); // set orientation (calls page_size_check_cb)
273
274        for (int xy = 0; xy <= 1; ++xy) {
275            const char *awar_name = xy == 0 ? AWAR_CANIO_PAGE_SX : AWAR_CANIO_PAGE_SY;
276
277            for (int pcount = 1; pcount <= wanted_pages; pcount++) {
278                float zoom = pcount*1.0;
279                awr->awar(awar_name)->write_float(zoom); // set zoom (x or y)
280
281                set_mag_from_psize(awr, xy == 0);
282
283                float sx    = awr->awar(AWAR_CANIO_PAGE_SX)->read_float();
284                float sy    = awr->awar(AWAR_CANIO_PAGE_SY)->read_float();
285                int   pages = xy2pages(sx, sy);
286
287                if (pages>wanted_pages) break; // pcount-loop
288
289                if (pages <= wanted_pages && pages >= best_pages) {
290                    int magnification = awr->awar(AWAR_CANIO_MAGNIFICATION)->read_int();    // read calculated magnification
291                    if (magnification>best_magnification) {
292                        // fits on wanted_pages and is best result yet
293                        best_magnification  = magnification;
294                        best_orientation    = o;
295                        best_zoom_awar_name = awar_name;
296                        best_zoom           = zoom;
297                        best_pages          = pages;
298                    }
299                }
300            }
301        }
302    }
303
304    if (best_zoom_awar_name) {
305        // take the best found values :
306        awr->awar(AWAR_CANIO_LANDSCAPE)->write_int(best_orientation);
307        awr->awar(best_zoom_awar_name)->write_float(best_zoom);
308        awr->awar(AWAR_CANIO_PAGES)->write_int(best_pages);
309        awr->awar(AWAR_CANIO_MAGNIFICATION)->write_int(best_magnification); 
310
311        if (best_pages != wanted_pages) {
312            aw_message(GBS_global_string("That didn't fit on %i page(s) - using %i page(s)",
313                                         wanted_pages, best_pages));
314        }
315    }
316    else {
317        aw_message(GBS_global_string("That didn't fit on %i page(s) - impossible settings", wanted_pages));
318    }
319   
320    awr->awar(AWAR_CANIO_PAGELOCK)->write_int(lockpages);
321}
322
323static void page_size_check_cb(AW_root *awr) {
324    if (!allow_page_size_check_cb) return;
325
326    bool landscape    = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
327    bool lockpages    = awr->awar(AWAR_CANIO_PAGELOCK)->read_int();
328    int  locked_pages = awr->awar(AWAR_CANIO_PAGES)->read_int();
329
330    float px = awr->awar(AWAR_CANIO_PAPER_SX)->read_float(); // paper-size
331    float py = awr->awar(AWAR_CANIO_PAPER_SY)->read_float();
332
333    if (landscape != (px>py)) {
334        set_paper_size_xy(awr, py, px); // recalls this function
335        return;
336    }
337
338    long magnification = awr->awar(AWAR_CANIO_MAGNIFICATION)->read_int();
339   
340    float gx = awr->awar(AWAR_CANIO_GFX_SX)->read_float(); // graphic size
341    float gy = awr->awar(AWAR_CANIO_GFX_SY)->read_float();
342
343    // output size
344    float ox = (gx*magnification)/100; // resulting size of output in inches
345    float oy = (gy*magnification)/100;
346    awr->awar(AWAR_CANIO_OUT_SX)->write_float(ox);
347    awr->awar(AWAR_CANIO_OUT_SY)->write_float(oy);
348
349    bool wantOverlap = awr->awar(AWAR_CANIO_OVERLAP_WANTED)->read_int();
350    bool useOverlap  = awr->awar(AWAR_CANIO_OVERLAP)->read_int();
351
352    float sx = 0.0; // resulting pages
353    float sy = 0.0;
354
355    bool fits_on_one_page = (ox <= px && oy <= py);
356
357    if (wantOverlap && !fits_on_one_page) {
358        float overlapPercent = awr->awar(AWAR_CANIO_OVERLAP_PERCENT)->read_float();
359        float pageRatio      = (100.0-overlapPercent)/100.0;
360
361        float rpx = px*pageRatio; // usable page-size (due to overlap)
362        float rpy = py*pageRatio;
363
364        while (ox>px) { ox -= rpx; sx += 1.0; }
365        sx += ox/px;
366
367        bool fig2devbug = !landscape;
368        if (fig2devbug) fig2devbug = awr->awar(AWAR_CANIO_F2DBUG)->read_int();
369
370        if (fig2devbug) {
371            // fig2dev has a bug with printing multiple portrait pages with overlap:
372            // Regardless of whether there is a needed overlapping in y-direction
373            // it prints a empty border at top of all top-row-pages and then clips
374            // the fig in the bottom-row (even if there is only one row).
375            // See also fig2devbug in calc_mag_from_psize()
376            sy += oy/rpy;
377        }
378        else {
379            while (oy>py) { oy -= rpy; sy += 1.0; }
380            sy += oy/py;
381        }
382    }
383    else {
384        sx = ox/px;
385        sy = oy/py;
386    }
387
388    // write amount of pages needed
389    awr->awar(AWAR_CANIO_PAGE_SX)->write_float(sx);
390    awr->awar(AWAR_CANIO_PAGE_SY)->write_float(sy);
391
392    int pages = xy2pages(sx, sy);
393    if (lockpages) {
394        fit_pages(awr, locked_pages, false); // Note: recurses with !lockpages
395        return;
396    }
397
398    awr->awar(AWAR_CANIO_PAGES)->write_int(pages);
399
400    // correct DISPLAYED overlapping..
401    bool willUseOverlap = wantOverlap && (pages != 1);
402    if (willUseOverlap != useOverlap) {
403        bool old_allow           = allow_overlap_toggled_cb;
404        allow_overlap_toggled_cb = false; // ..but do not modify wanted overlapping
405
406        awr->awar(AWAR_CANIO_OVERLAP)->write_int(willUseOverlap);
407
408        allow_overlap_toggled_cb = old_allow;
409    }
410}
411
412inline double round_psize(double psize) { return AW_INT(psize*10)/10.0; }
413
414static void paper_changed_cb(AW_root *awr) {
415    int                paper     = awr->awar(AWAR_CANIO_PAPER)->read_int();
416    const PaperFormat& format    = knownPaperFormat[paper];
417    bool               landscape = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
418    float              useable   = awr->awar(AWAR_CANIO_PAPER_USABLE)->read_float()/100.0;
419
420    if (landscape) {
421        set_paper_size_xy(awr, useable*format.long_inch(), useable*format.short_inch());
422    }
423    else {
424        set_paper_size_xy(awr, useable*format.short_inch(), useable*format.long_inch());
425    }
426}
427
428// --------------------------------------------------------------------------------
429
430static bool export_awars_created = false;
431static bool print_awars_created = false;
432
433static void create_export_awars(AW_root *awr) {
434    if (!export_awars_created) {
435        AW_default def = AW_ROOT_DEFAULT;
436
437        awr->awar_int(AWAR_CANIO_CLIP, 0, def);
438        awr->awar_int(AWAR_CANIO_HANDLES, 1, def);
439        awr->awar_int(AWAR_CANIO_COLOR, 1, def);
440
441        awr->awar_string(AWAR_CANIO_FILE_NAME, "print.fig", def);
442        awr->awar_string(AWAR_CANIO_FILE_DIR, "", def);
443        awr->awar_string(AWAR_CANIO_FILE_FILTER, "fig", def);
444
445        awr->awar_int(AWAR_CANIO_LANDSCAPE, 0, def);
446        awr->awar_int(AWAR_CANIO_MAGNIFICATION, 100, def);
447
448        // constraints:
449
450        awr->awar(AWAR_CANIO_MAGNIFICATION)->set_minmax(1, 10000);
451
452        export_awars_created = true;
453    }
454}
455
456static void resetFiletype(AW_root *awr, const char *filter, const char *defaultFilename) {
457    AW_awar *awar_filter    = awr->awar(AWAR_CANIO_FILE_FILTER);
458    char    *current_filter = awar_filter->read_string();
459
460    if (strcmp(current_filter, filter) != 0) {
461        awar_filter->write_string(filter);
462        awr->awar(AWAR_CANIO_FILE_NAME)->write_string(defaultFilename);
463    }
464    free(current_filter);
465}
466
467static void create_print_awars(AW_root *awr, AWT_canvas *scr) {
468    create_export_awars(awr);
469
470    if (!print_awars_created) {
471        AW_default def = AW_ROOT_DEFAULT;
472
473        awr->awar_int(AWAR_CANIO_PAGES, 1, def);
474        awr->awar_int(AWAR_CANIO_PAGELOCK, 1, def);
475
476        awr->awar_int(AWAR_CANIO_OVERLAP_WANTED, 1, def);
477        awr->awar_int(AWAR_CANIO_OVERLAP, 1, def)->add_callback(overlap_toggled_cb);
478        awr->awar_float(AWAR_CANIO_OVERLAP_PERCENT, 13.0, def); // determined
479
480        awr->awar_int(AWAR_CANIO_F2DBUG, 1, def); // bug still exists in most recent version (3.2 5d from July 23, 2010)
481
482        awr->awar_float(AWAR_CANIO_BORDERSIZE, 0.0, def);
483
484        awr->awar_float(AWAR_CANIO_GFX_SX);
485        awr->awar_float(AWAR_CANIO_GFX_SY);
486
487        awr->awar_float(AWAR_CANIO_OUT_SX);
488        awr->awar_float(AWAR_CANIO_OUT_SY);
489
490        awr->awar_float(AWAR_CANIO_PAPER_SX);
491        awr->awar_float(AWAR_CANIO_PAPER_SY);
492
493        awr->awar_int(AWAR_CANIO_PAPER, 0)->add_callback(paper_changed_cb); // sets first format (A4)
494        awr->awar_float(AWAR_CANIO_PAPER_USABLE, 95)->add_callback(paper_changed_cb); // 95% of paper are usable
495
496        awr->awar_float(AWAR_CANIO_PAGE_SX);
497        awr->awar_float(AWAR_CANIO_PAGE_SY);
498
499        awr->awar_int(AWAR_CANIO_DEST);
500
501        {
502            char *print_command;
503            if (getenv("PRINTER")) {
504                print_command = GBS_eval_env("lpr -h -P$(PRINTER)");
505            } else   print_command = strdup("lpr -h");
506
507            awr->awar_string(AWAR_CANIO_PRINTER, print_command, def);
508            free(print_command);
509        }
510
511        // constraints and automatics:
512
513        awr->awar(AWAR_CANIO_PAPER_SX)->set_minmax(0.1, 100);
514        awr->awar(AWAR_CANIO_PAPER_SY)->set_minmax(0.1, 100);
515
516
517        RootCallback checkSizeCb = makeRootCallback(awt_print_tree_check_size, scr);
518        checkSizeCb(NULL);
519        awr->awar(AWAR_CANIO_CLIP)      ->add_callback(checkSizeCb);
520        awr->awar(AWAR_CANIO_BORDERSIZE)->add_callback(checkSizeCb);
521
522        { // add callbacks for page recalculation
523            const char *checked_awars[] = {
524                AWAR_CANIO_MAGNIFICATION,
525                AWAR_CANIO_LANDSCAPE,
526                AWAR_CANIO_BORDERSIZE,
527                AWAR_CANIO_OVERLAP_WANTED, AWAR_CANIO_OVERLAP_PERCENT,
528                AWAR_CANIO_F2DBUG, 
529                AWAR_CANIO_PAPER_SX,         AWAR_CANIO_PAPER_SY,
530                AWAR_CANIO_GFX_SX,         AWAR_CANIO_GFX_SY,
531                0
532            };
533            for (int ca = 0; checked_awars[ca]; ca++) {
534                awr->awar(checked_awars[ca])->add_callback(page_size_check_cb);
535            }
536        }
537
538        paper_changed_cb(awr); // also calls page_size_check_cb
539        print_awars_created = true;
540    }
541}
542
543// --------------------------------------------------------------------------------
544
545static GB_ERROR canvas_to_xfig(AWT_canvas *scr, const char *xfig_name, bool add_invisibles, float border) {
546    // if 'add_invisibles' is true => print 2 invisible dots to make fig2dev center correctly
547
548    GB_transaction  ta(scr->gb_main);
549    AW_root        *awr = scr->awr;
550
551    bool draw_all  = awr->awar(AWAR_CANIO_CLIP)->read_int();
552    bool handles   = awr->awar(AWAR_CANIO_HANDLES)->read_int();
553    bool use_color = awr->awar(AWAR_CANIO_COLOR)->read_int();
554
555    AW_device_print *device = scr->aww->get_print_device(AW_MIDDLE_AREA);
556
557    device->reset();
558    device->set_color_mode(use_color);
559#ifdef ARB_GTK
560    GB_ERROR error = NULL;
561#else
562    GB_ERROR error = device->open(xfig_name);
563#endif
564
565    if (!error) {
566        Rectangle drawsize = get_drawsize(scr, draw_all);
567        Rectangle world_drawsize;
568
569        if (draw_all) {
570            Rectangle with_border = add_border_to_drawsize(drawsize, border);
571
572            double zoom = scr->trans_to_fit;
573            device->zoom(zoom); // same zoom as used by get_drawsize above
574
575            world_drawsize = device->rtransform(drawsize);
576
577            Vector ulc2origin = Origin-with_border.upper_left_corner();
578            Vector offset     = device->rtransform(ulc2origin)*device->get_unscale();
579
580            device->set_offset(offset);
581
582            device->set_bottom_clip_border((int)(with_border.height()+1), true);
583            device->set_right_clip_border((int)(with_border.width()+1), true);
584        }
585        else {
586            scr->init_device(device);
587            world_drawsize = device->rtransform(drawsize);
588        }
589
590        AW_bitset filter       = AW_PRINTER;
591        if (handles) filter   |= AW_PRINTER_EXT;
592        if (!draw_all) filter |= AW_PRINTER_CLIP;
593
594        device->set_filter(filter);
595#ifdef ARB_GTK
596        error = device->open(xfig_name);
597        if (error) return error;
598#endif     
599        scr->gfx->show(device);
600
601        if (add_invisibles) {
602            Position ul = world_drawsize.upper_left_corner();
603            Position lr = world_drawsize.lower_right_corner();
604
605            // move invisible points towards center (in case they are clipped away)
606            Vector stepInside = device->rtransform(Vector(1, 1));
607            int maxloop = 10;
608
609            bool drawnUL = false;
610            bool drawnLR = false;
611
612            while (!(drawnLR && drawnUL) && maxloop-->0) {
613                if (!drawnUL) {
614                    drawnUL  = device->invisible(ul);
615                    ul      += stepInside;
616                }
617                if (!drawnLR) {
618                    drawnLR  = device->invisible(lr);
619                    lr      -= stepInside;
620                }
621            }
622            awt_assert(drawnLR && drawnUL);
623        }
624
625        device->close();
626    }
627    return error;
628}
629
630// --------------------------------------------------------------------------------
631
632static void canvas_to_xfig_and_run_xfig(AW_window *aww, AWT_canvas *scr) {
633    AW_root *awr  = aww->get_root();
634    char    *xfig = AW_get_selected_fullname(awr, AWAR_CANIO_FILE_BASE);
635
636    GB_ERROR error = NULL;
637    if (xfig[0] == 0) {
638        error = "Please enter a file name";
639    }
640    else {
641        error = canvas_to_xfig(scr, xfig, true, 0.0);
642        if (!error) {
643            awr->awar(AWAR_CANIO_FILE_DIR)->touch(); // reload dir to show created xfig
644            char *quotedXfig = GBK_singlequote(xfig);
645
646#if defined(ARB_GTK)
647            error = GBK_system(GBS_global_string("evince %s &", quotedXfig));
648#else
649            error = GBK_system(GBS_global_string("xfig %s &", quotedXfig));
650#endif
651            free(quotedXfig);
652        }
653    }
654    if (error) aw_message(error);
655    free(xfig);
656}
657
658static void canvas_to_printer(AW_window *aww, AWT_canvas *scr) {
659    GB_transaction  ta(scr->gb_main);
660    AW_root        *awr       = aww->get_root();
661    GB_ERROR        error     = 0;
662    char           *dest      = 0;
663    PrintDest       printdest = (PrintDest)awr->awar(AWAR_CANIO_DEST)->read_int();
664
665    switch (printdest) {
666        case PDEST_POSTSCRIPT: {
667            dest = AW_get_selected_fullname(awr, AWAR_CANIO_FILE_BASE);
668            FILE *out = fopen(dest, "w");
669            if (!out) error = GB_export_IO_error("writing", dest);
670            else fclose(out);
671            break;
672        }
673        default: {
674            char *name = GB_unique_filename("arb_print", "ps");
675            dest       = GB_create_tempfile(name);
676            free(name);
677
678            if (!dest) error = GB_await_error();
679            break;
680        }
681    }
682
683    if (!error) {
684        char *quotedDest = GBK_singlequote(dest);
685        char *xfig;
686        {
687            char *name = GB_unique_filename("arb_print", "xfig");
688            xfig       = GB_create_tempfile(name);
689            free(name);
690        }
691
692        arb_progress progress("Printing");
693        progress.subtitle("Exporting Data");
694
695        if (!xfig) error = GB_await_error();
696        if (!error) {
697            float border = awr->awar(AWAR_CANIO_BORDERSIZE)->read_float();
698            error        = canvas_to_xfig(scr, xfig, true, border);
699        }
700
701        if (!error) {
702            awt_assert(GB_is_privatefile(xfig, true));
703
704            // ----------------------------------------
705            progress.subtitle("Converting to Postscript");
706
707            {
708                bool   landscape     = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
709                bool   useOverlap    = awr->awar(AWAR_CANIO_OVERLAP)->read_int();
710                double magnification = awr->awar(AWAR_CANIO_MAGNIFICATION)->read_int() * 0.01;
711                int    paper         = awr->awar(AWAR_CANIO_PAPER)->read_int();
712
713                const PaperFormat& format = knownPaperFormat[paper];
714
715                GBS_strstruct cmd(500);
716                cmd.cat("fig2dev");
717
718                cmd.cat(" -L ps"); // postscript output
719                if (useOverlap) {
720                    cmd.cat(" -M"); // generate multiple pages if needed
721                    cmd.cat(" -O"); // generate overlap (if printing to multiple pages)
722                }
723                cmd.nprintf(20, " -m %f", magnification);
724                cmd.cat(landscape ? " -l 0" : " -p 0");              // landscape or portrait
725
726                cmd.cat(" -z "); cmd.cat(format.get_fig2dev_val()); // paperformat
727
728                cmd.put(' '); cmd.cat(xfig);       // input
729                cmd.put(' '); cmd.cat(quotedDest); // output
730
731                error = GBK_system(cmd.get_data());
732            }
733
734            // if user saves to .ps -> no special file permissions are required
735            awt_assert(printdest == PDEST_POSTSCRIPT || GB_is_privatefile(dest, false));
736
737            if (!error) {
738                progress.subtitle("Printing");
739
740                switch (printdest) {
741                    case PDEST_PREVIEW: {
742                        GB_CSTR gs      = GB_getenvARB_GS();
743                        GB_CSTR command = GBS_global_string("(%s %s;rm -f %s) &", gs, dest, dest);
744                        error           = GBK_system(command);
745                        break;
746                    }
747                    case PDEST_POSTSCRIPT:
748                        break;
749
750                    case PDEST_PRINTER: {
751                        char *prt = awr->awar(AWAR_CANIO_PRINTER)->read_string();
752                        error     = GBK_system(GBS_global_string("%s %s", prt, dest));
753                        free(prt);
754                        GB_unlink_or_warn(dest, &error);
755                        break;
756                    }
757                }
758            }
759        }
760        if (xfig) {
761#if defined(DEBUG) && 0
762            // show intermediate xfig and unlink it
763            GBK_system(GBS_global_string("( xfig %s; rm %s) &", xfig, xfig));
764#else // !defined(DEBUG)
765            GB_unlink_or_warn(xfig, &error);
766#endif
767            free(xfig);
768        }
769        free(quotedDest);
770    }
771
772    free(dest);
773
774    if (error) aw_message(error);
775}
776
777// --------------------------------------------------------------------------------
778
779void AWT_popup_tree_export_window(AW_window *parent_win, AWT_canvas *scr) {
780    static AW_window_simple *aws = 0;
781
782    AW_root *awr = parent_win->get_root();
783    create_export_awars(awr);
784#if defined(ARB_GTK)
785    resetFiletype(awr, "pdf", "print.pdf");
786#else
787    resetFiletype(awr, "fig", "print.fig");
788#endif
789
790    if (!aws) {
791        aws = new AW_window_simple;
792        aws->init(awr, "EXPORT_TREE_AS_XFIG", "EXPORT TREE TO XFIG");
793        aws->load_xfig("awt/export.fig");
794
795        aws->at("close"); aws->callback(AW_POPDOWN);
796        aws->create_button("CLOSE", "CLOSE", "C");
797
798        aws->at("help"); aws->callback(makeHelpCallback("tree2file.hlp"));
799        aws->create_button("HELP", "HELP", "H");
800
801        aws->label_length(15);
802
803        AW_create_standard_fileselection(aws, AWAR_CANIO_FILE_BASE);
804
805        aws->at("what");
806        aws->label("Clip at Screen");
807        aws->create_toggle_field(AWAR_CANIO_CLIP, 1);
808        aws->insert_toggle("#print/clipscreen.xpm", "S", 0);
809        aws->insert_toggle("#print/clipall.xpm", "A", 1);
810        aws->update_toggle_field();
811
812        aws->at("remove_root");
813        aws->label("Show Handles");
814        aws->create_toggle_field(AWAR_CANIO_HANDLES, 1);
815        aws->insert_toggle("#print/nohandles.xpm", "S", 0);
816        aws->insert_toggle("#print/handles.xpm", "A", 1);
817        aws->update_toggle_field();
818
819        aws->at("color");
820        aws->label("Export colors");
821        aws->create_toggle(AWAR_CANIO_COLOR);
822
823        aws->at("xfig"); aws->callback(makeWindowCallback(canvas_to_xfig_and_run_xfig, scr));
824        aws->create_autosize_button("START_XFIG", "EXPORT to XFIG", "X");
825    }
826
827    aws->activate();
828}
829
830void AWT_popup_sec_export_window(AW_window *parent_win, AWT_canvas *scr) {
831    static AW_window_simple *aws = 0;
832
833    AW_root *awr = parent_win->get_root();
834    create_export_awars(awr);
835    resetFiletype(awr, "fig", "print.fig");
836
837    if (!aws) {
838        aws = new AW_window_simple;
839        aws->init(awr, "EXPORT_TREE_AS_XFIG", "EXPORT STRUCTURE TO XFIG");
840        aws->load_xfig("awt/secExport.fig");
841
842        aws->at("close");
843        aws->callback(AW_POPDOWN);
844        aws->create_button("CLOSE", "CLOSE", "C");
845
846        aws->at("help");
847        aws->callback(makeHelpCallback("tree2file.hlp"));
848        aws->create_button("HELP", "HELP", "H");
849
850        aws->label_length(15);
851        AW_create_standard_fileselection(aws, AWAR_CANIO_FILE_BASE);
852
853        aws->at("what");
854        aws->label("Clip Options");
855        aws->create_option_menu(AWAR_CANIO_CLIP, true);
856        aws->insert_option("Export screen only", "s", 0);
857        aws->insert_default_option("Export complete structure", "c", 1);
858        aws->update_option_menu();
859
860        aws->at("color");
861        aws->label("Export colors");
862        aws->create_toggle(AWAR_CANIO_COLOR);
863
864        aws->at("xfig");
865        aws->callback(makeWindowCallback(canvas_to_xfig_and_run_xfig, scr));
866        aws->create_autosize_button("START_XFIG", "EXPORT to XFIG", "X");
867    }
868
869    aws->activate();
870}
871
872static void columns_changed_cb(AW_window *aww) { set_mag_from_psize(aww->get_root(), true); }
873static void rows_changed_cb(AW_window *aww) { set_mag_from_psize(aww->get_root(), false); }
874
875static void fit_pages_cb(AW_window *aww, int wanted_pages) {
876    AW_root *awr = aww->get_root();
877    if (wanted_pages<=0) {
878        wanted_pages = awr->awar(AWAR_CANIO_PAGES)->read_int();
879    }
880    fit_pages(awr, wanted_pages, true);
881}
882
883void AWT_popup_print_window(AW_window *parent_win, AWT_canvas *scr) {
884    AW_root                 *awr = parent_win->get_root();
885    static AW_window_simple *aws = 0;
886
887    create_print_awars(awr, scr);
888    resetFiletype(awr, "ps", "print.ps");
889
890    if (!aws) {
891        aws = new AW_window_simple;
892        aws->init(awr, "PRINT_CANVAS", "PRINT GRAPHIC");
893        aws->load_xfig("awt/print.fig");
894
895        aws->at("close"); aws->callback(AW_POPDOWN);
896        aws->create_button("CLOSE", "CLOSE", "C");
897
898        aws->at("help"); aws->callback(makeHelpCallback("tree2prt.hlp"));
899        aws->create_button("HELP", "HELP", "H");
900
901        // -----------------------------
902        //      select what to print
903
904        aws->label_length(15);
905
906        aws->at("what");
907        aws->label("Clip at Screen");
908        aws->create_toggle_field(AWAR_CANIO_CLIP, 1);
909        aws->insert_toggle("#print/clipscreen.xpm", "S", 0);
910        aws->insert_toggle("#print/clipall.xpm", "A", 1);
911        aws->update_toggle_field();
912
913        aws->at("remove_root");
914        aws->label("Show Handles");
915        aws->create_toggle_field(AWAR_CANIO_HANDLES, 1);
916        aws->insert_toggle("#print/nohandles.xpm", "S", 0);
917        aws->insert_toggle("#print/handles.xpm", "A", 1);
918        aws->update_toggle_field();
919
920        aws->at("color");
921        aws->label("Export colors");
922        aws->create_toggle(AWAR_CANIO_COLOR);
923
924        // --------------------
925        //      page layout
926
927        aws->at("getsize");
928        aws->callback(makeWindowCallback(awt_print_tree_check_size, scr));
929        aws->create_autosize_button(0, "Get Graphic Size");
930
931        aws->button_length(6);
932        aws->at("gsizex"); aws->create_button(0, AWAR_CANIO_GFX_SX);
933        aws->at("gsizey"); aws->create_button(0, AWAR_CANIO_GFX_SY);
934        aws->at("osizex"); aws->create_button(0, AWAR_CANIO_OUT_SX);
935        aws->at("osizey"); aws->create_button(0, AWAR_CANIO_OUT_SY);
936
937        aws->at("magnification");
938        aws->create_input_field(AWAR_CANIO_MAGNIFICATION, 4);
939
940        aws->label_length(0);
941        aws->at("orientation");
942        aws->create_toggle_field(AWAR_CANIO_LANDSCAPE, 1);
943        aws->insert_toggle("#print/landscape.xpm", "L", 1);
944        aws->insert_toggle("#print/portrait.xpm",  "P", 0);
945        aws->update_toggle_field();
946
947        aws->at("bsize"); aws->create_input_field(AWAR_CANIO_BORDERSIZE, 4);
948
949        // -------------------
950        //      paper size
951
952        aws->at("psizex"); aws->create_input_field(AWAR_CANIO_PAPER_SX, 5);
953        aws->at("psizey"); aws->create_input_field(AWAR_CANIO_PAPER_SY, 5);
954
955        aws->at("paper");
956        aws->create_option_menu(AWAR_CANIO_PAPER, true);
957        aws->insert_default_option(knownPaperFormat[0].get_description(), "", 0);
958        for (int f = 1; f<int(ARRAY_ELEMS(knownPaperFormat)); ++f) {
959            const PaperFormat& format = knownPaperFormat[f];
960            aws->insert_option(format.get_description(), "", f);
961        }
962        aws->update_option_menu();
963
964        aws->at("usize"); aws->create_input_field(AWAR_CANIO_PAPER_USABLE, 4);
965
966
967        // -----------------------
968        //      multiple pages
969
970        aws->at("sizex");
971        aws->callback(columns_changed_cb); // @@@ used as INPUTFIELD_CB (see #559)
972        aws->create_input_field(AWAR_CANIO_PAGE_SX, 4);
973        aws->at("sizey");
974        aws->callback(rows_changed_cb); // @@@ used as INPUTFIELD_CB (see #559)
975        aws->create_input_field(AWAR_CANIO_PAGE_SY, 4);
976
977        aws->at("best_fit");
978        aws->callback(makeWindowCallback(fit_pages_cb, 0));
979        aws->create_autosize_button("fit_on", "Fit on");
980
981        aws->at("pages");
982        aws->create_input_field(AWAR_CANIO_PAGES, 3);
983
984        aws->at("plock");
985        aws->create_toggle(AWAR_CANIO_PAGELOCK);
986       
987        aws->button_length(1);
988        {
989            char name[] = "p0";
990            for (int p = 1; p <= 9; ++p) {
991                name[1] = '0'+p; // at-label, macro-name and button-text
992                if (aws->at_ifdef(name)) {
993                    aws->at(name);
994                    aws->callback(makeWindowCallback(fit_pages_cb, p));
995                    aws->create_button(name, name+1);
996                }
997            }
998        }
999
1000        aws->at("overlap");
1001        aws->create_toggle(AWAR_CANIO_OVERLAP);
1002        aws->at("amount");
1003        aws->create_input_field(AWAR_CANIO_OVERLAP_PERCENT, 4);
1004
1005        aws->at("f2dbug");
1006        aws->create_toggle(AWAR_CANIO_F2DBUG);
1007
1008        // --------------------
1009        //      destination
1010
1011        aws->at("printto");
1012        aws->label_length(12);
1013        aws->label("Destination");
1014        aws->create_toggle_field(AWAR_CANIO_DEST);
1015        aws->insert_toggle("Printer",           "P", PDEST_PRINTER);
1016        aws->insert_toggle("File (Postscript)", "F", PDEST_POSTSCRIPT);
1017        aws->insert_toggle("Preview",           "V", PDEST_PREVIEW);
1018        aws->update_toggle_field();
1019
1020        aws->at("printer");
1021        aws->create_input_field(AWAR_CANIO_PRINTER, 16);
1022
1023        aws->at("filename");
1024        aws->create_input_field(AWAR_CANIO_FILE_NAME, 16);
1025
1026        aws->at("go");
1027        aws->highlight();
1028        aws->callback(makeWindowCallback(canvas_to_printer, scr));
1029        aws->create_autosize_button("PRINT", "PRINT", "P");
1030    }
1031
1032    awt_print_tree_check_size(NULL, scr);
1033    aws->activate();
1034}
Note: See TracBrowser for help on using the repository browser.