root/trunk/AWT/AWT_canvas.cxx

Revision 8725, 25.3 KB (checked in by westram, 13 days ago)
  • comments cleanup
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : AWT_canvas.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#include "awt.hxx"
13
14#include <aw_root.hxx>
15#include <aw_msg.hxx>
16#include <arbdbt.h>
17
18#include <algorithm>
19
20using namespace std;
21using namespace AW;
22
23void AWT_graphic_exports::clear() {
24    zoom_reset       = 0;
25    resize           = 0;
26    refresh          = 0;
27    save             = 0;
28    structure_change = 0;
29}
30
31void AWT_graphic_exports::init() {
32    clear();
33    padding.clear();
34
35    zoom_mode = AWT_ZOOM_BOTH;
36    fit_mode  = AWT_FIT_LARGER;
37
38    dont_scroll = 0;
39}
40
41inline void AWT_canvas::push_transaction() const { if (gb_main) GB_push_transaction(gb_main); }
42inline void AWT_canvas::pop_transaction() const { if (gb_main) GB_pop_transaction(gb_main); }
43
44void AWT_canvas::set_horizontal_scrollbar_position(AW_window *, int pos) {
45    int maxpos = int(worldsize.r-rect.r)-1;
46    if (pos>maxpos) pos = maxpos;
47    if (pos<0) pos = 0;
48    aww->set_horizontal_scrollbar_position(pos);
49}
50
51void AWT_canvas::set_vertical_scrollbar_position(AW_window *, int pos) {
52    int maxpos = int(worldsize.b-rect.b)-1;
53    if (pos>maxpos) pos = maxpos;
54    if (pos<0) pos = 0;
55    aww->set_vertical_scrollbar_position(pos);
56}
57
58void AWT_canvas::set_scrollbars() {
59    AW_pos width  = this->worldinfo.r - this->worldinfo.l;
60    AW_pos height = this->worldinfo.b - this->worldinfo.t;
61
62    worldsize.l = 0;
63    worldsize.t = 0;
64
65    AW::Vector zv = gfx->exports.zoomVector(trans_to_fit);
66
67    worldsize.r = width *zv.x() + gfx->exports.get_x_padding();
68    worldsize.b = height*zv.y() + gfx->exports.get_y_padding();
69
70    aww->tell_scrolled_picture_size(worldsize);
71
72    aww->calculate_scrollbars();
73
74    this->old_hor_scroll_pos = (int)((-this->worldinfo.l -
75                                      this->shift_x_to_fit)*
76                                     this->trans_to_fit +
77                                     gfx->exports.get_left_padding());
78    this->set_horizontal_scrollbar_position(this->aww, old_hor_scroll_pos);
79
80    this->old_vert_scroll_pos = (int)((-this->worldinfo.t -
81                                       this->shift_y_to_fit)*
82                                      this->trans_to_fit+
83                                      gfx->exports.get_top_padding());
84
85    this->set_vertical_scrollbar_position(this->aww, old_vert_scroll_pos);
86}
87
88void AWT_canvas::init_device(AW_device *device) {
89    device->reset();
90    device->shift(AW::Vector(shift_x_to_fit, shift_y_to_fit));
91    device->zoom(this->trans_to_fit);
92}
93
94void AWT_canvas::recalc_size(bool adjust_scrollbars) {
95    GB_transaction  dummy(this->gb_main);
96    AW_device_size *size_device = aww->get_size_device(AW_MIDDLE_AREA);
97
98    size_device->set_filter(AW_SIZE|(consider_text_for_size ? AW_SIZE_UNSCALED : 0));
99    size_device->reset();
100
101    gfx->show(size_device);
102
103    if (consider_text_for_size) {
104        gfx->exports.set_extra_text_padding(size_device->get_unscaleable_overlap());
105    }
106
107    size_device->get_size_information(&(this->worldinfo));
108    rect = size_device->get_area_size();   // real world size (no offset)
109
110    if (adjust_scrollbars) set_scrollbars();
111}
112
113void AWT_canvas::zoom_reset() {
114    recalc_size(false);
115
116    AW_pos width  = this->worldinfo.r - this->worldinfo.l;
117    AW_pos height = this->worldinfo.b - this->worldinfo.t;
118
119    AW_pos net_window_width  = rect.r - rect.l - gfx->exports.get_x_padding();
120    AW_pos net_window_height = rect.b - rect.t - gfx->exports.get_y_padding();
121   
122    if (net_window_width<AWT_MIN_WIDTH) net_window_width   = AWT_MIN_WIDTH;
123    if (net_window_height<AWT_MIN_WIDTH) net_window_height = AWT_MIN_WIDTH;
124
125    if (width <EPS) width   = EPS;
126    if (height <EPS) height = EPS;
127
128    AW_pos x_scale = net_window_width/width;
129    AW_pos y_scale = net_window_height/height;
130
131    trans_to_fit = -1;
132    switch (gfx->exports.fit_mode) {
133        case AWT_FIT_NEVER:   trans_to_fit = 1.0; break;
134        case AWT_FIT_X:       trans_to_fit = x_scale; break;
135        case AWT_FIT_Y:       trans_to_fit = y_scale; break;
136        case AWT_FIT_LARGER:  trans_to_fit = std::min(x_scale, y_scale); break;
137        case AWT_FIT_SMALLER: trans_to_fit = std::max(x_scale, y_scale); break;
138    }
139    aw_assert(trans_to_fit > 0);
140
141    AW_pos center_shift_x = 0;
142    AW_pos center_shift_y = 0;
143
144    if (gfx->exports.zoom_mode&AWT_ZOOM_X) center_shift_x = (net_window_width /trans_to_fit - width)/2;
145    if (gfx->exports.zoom_mode&AWT_ZOOM_Y) center_shift_y = (net_window_height/trans_to_fit - height)/2;
146
147    // complete, upper left corner
148    this->shift_x_to_fit = - this->worldinfo.l + gfx->exports.get_left_padding()/trans_to_fit + center_shift_x;
149    this->shift_y_to_fit = - this->worldinfo.t + gfx->exports.get_top_padding()/trans_to_fit  + center_shift_y;
150
151    this->old_hor_scroll_pos  = 0;
152    this->old_vert_scroll_pos = 0;
153
154    // scale
155
156    this->set_scrollbars();
157}
158
159void AWT_canvas::zoom(AW_device *device, bool zoomIn, const Rectangle& wanted_part, const Rectangle& current_part, int percent) {
160    // zooms the device.
161    //
162    // zoomIn == true -> wanted_part is zoomed to current_part
163    // zoomIn == false -> current_part is zoomed to wanted_part
164    //
165    // If wanted_part is very small -> assume mistake (act like single click)
166    // Single click zooms by 'percent' % centering on click position
167
168    init_device(device);
169
170    if (!gfx) {
171        awt_assert(0); // we have no display - does this occur?
172                       // if yes, pls inform devel@arb-home.de about circumstances
173        return;
174    }
175
176    AW_pos width  = worldinfo.r-worldinfo.l;
177    AW_pos height = worldinfo.b-worldinfo.t;
178
179    if (width<EPS) width = EPS;
180    if (height<EPS) height = EPS;
181
182    AWT_zoom_mode zoom_mode = gfx->exports.zoom_mode;
183    if (zoom_mode == AWT_ZOOM_NEVER) {
184        aw_message("Zoom does not work in this mode");
185        return;
186    }
187
188    Rectangle current(device->rtransform(current_part));
189    Rectangle wanted;
190
191    bool isClick = false;
192    switch (zoom_mode) {
193        case AWT_ZOOM_BOTH: isClick = wanted_part.line_vector().length()<40.0; break;
194        case AWT_ZOOM_X:    isClick = wanted_part.width()<30.0;                break;
195        case AWT_ZOOM_Y:    isClick = wanted_part.height()<30.0;               break;
196
197        case AWT_ZOOM_NEVER: awt_assert(0); break;
198    }
199
200    if (isClick) { // very small part or single click
201        // -> zoom by 'percent' % on click position
202        Position clickPos = device->rtransform(wanted_part.centroid());
203
204        Vector click2UpperLeft  = current.upper_left_corner()-clickPos;
205        Vector click2LowerRight = current.lower_right_corner()-clickPos;
206
207        double scale = (100-percent)/100.0;
208
209        wanted = Rectangle(clickPos+scale*click2UpperLeft, clickPos+scale*click2LowerRight);
210    }
211    else {
212        wanted = Rectangle(device->rtransform(wanted_part));
213    }
214
215    if (!zoomIn) {
216        // calculate big rectangle (outside of viewport), which is zoomed into viewport
217
218        if (zoom_mode == AWT_ZOOM_BOTH) {
219            double    factor = current.diagonal().length()/wanted.diagonal().length();
220            Vector    curr2wanted(current.upper_left_corner(), wanted.upper_left_corner());
221            Rectangle big(current.upper_left_corner()+(curr2wanted*-factor), current.diagonal()*factor);
222
223            wanted = big;
224        }
225        else {
226            double factor;
227            if (zoom_mode == AWT_ZOOM_X) {
228                factor = current.width()/wanted.width();
229            }
230            else {
231                awt_assert(zoom_mode == AWT_ZOOM_Y);
232                factor = current.height()/wanted.height();
233            }
234            Vector    curr2wanted_start(current.upper_left_corner(), wanted.upper_left_corner());
235            Vector    curr2wanted_end(current.lower_right_corner(), wanted.lower_right_corner());
236            Rectangle big(current.upper_left_corner()+(curr2wanted_start*-factor),
237                          current.lower_right_corner()+(curr2wanted_end*-factor));
238
239            wanted = big;
240        }
241    }
242
243    // scroll
244    shift_x_to_fit = (zoom_mode&AWT_ZOOM_X) ? -wanted.start().xpos() : (shift_x_to_fit+worldinfo.l)*trans_to_fit;
245    shift_y_to_fit = (zoom_mode&AWT_ZOOM_Y) ? -wanted.start().ypos() : (shift_y_to_fit+worldinfo.t)*trans_to_fit;
246
247    // scale
248    if ((rect.r-rect.l)<EPS) rect.r = rect.l+1;
249    if ((rect.b-rect.t)<EPS) rect.b = rect.t+1;
250
251    AW_pos max_trans_to_fit;
252   
253    switch (zoom_mode) {
254        case AWT_ZOOM_BOTH:
255            trans_to_fit     = max((rect.r-rect.l)/wanted.width(), (rect.b-rect.t)/wanted.height());
256            max_trans_to_fit = 32000.0/max(width, height);
257            break;
258
259        case AWT_ZOOM_X:
260            trans_to_fit     = (rect.r-rect.l)/wanted.width();
261            max_trans_to_fit = 32000.0/width;
262            break;
263
264        case AWT_ZOOM_Y:
265            trans_to_fit     = (rect.b-rect.t)/wanted.height();
266            max_trans_to_fit = 32000.0/height;
267            break;
268
269        case AWT_ZOOM_NEVER: awt_assert(0); break;
270    }
271    trans_to_fit = std::min(trans_to_fit, max_trans_to_fit);
272
273    // correct scrolling for "dont_fit"-direction
274    if (zoom_mode == AWT_ZOOM_Y) shift_x_to_fit = (shift_x_to_fit/trans_to_fit)-worldinfo.l;
275    if (zoom_mode == AWT_ZOOM_X) shift_y_to_fit = (shift_y_to_fit/trans_to_fit)-worldinfo.t;
276
277    set_scrollbars();
278}
279
280inline void nt_draw_zoom_box(AW_device *device, int gc, AW_pos x1, AW_pos y1, AW_pos x2, AW_pos y2) {
281    device->box(gc, false, x1, y1, x2-x1, y2-y1);
282}
283inline void nt_draw_zoom_box(AW_device *device, AWT_canvas *scr) {
284    nt_draw_zoom_box(device, scr->drag_gc,
285                     scr->zoom_drag_sx, scr->zoom_drag_sy,
286                     scr->zoom_drag_ex, scr->zoom_drag_ey);
287}
288
289static void clip_expose(AW_window *aww, AWT_canvas *scr,
290                        int left_border, int right_border,
291                        int top_border, int bottom_border,
292                        int hor_overlap, int ver_overlap)
293{
294    AW_device *device = aww->get_device (AW_MIDDLE_AREA);
295    device->set_filter(AW_SCREEN);
296    device->reset();
297
298    device->set_top_clip_border(top_border);
299    device->set_bottom_clip_border(bottom_border);
300    device->set_left_clip_border(left_border);
301    device->set_right_clip_border(right_border);
302
303    device->clear_part(left_border, top_border, right_border-left_border,
304                       bottom_border-top_border, -1);
305
306    GB_transaction dummy(scr->gb_main);
307
308    if (scr->gfx->check_update(scr->gb_main)>0) {
309        scr->zoom_reset();
310    }
311
312    scr->init_device(device);
313
314    if (hor_overlap> 0.0) {
315        device->set_right_clip_border(right_border + hor_overlap);
316    }
317    if (hor_overlap< 0.0) {
318        device->set_left_clip_border(left_border + hor_overlap);
319    }
320    if (ver_overlap> 0.0) {
321        device->set_bottom_clip_border(bottom_border + ver_overlap);
322    }
323    if (ver_overlap< 0.0) {
324        device->set_top_clip_border(top_border + ver_overlap);
325    }
326    scr->gfx->show(device);
327}
328
329void AWT_expose_cb(AW_window *, AWT_canvas *scr, AW_CL) {
330    scr->refresh();
331}
332
333void AWT_canvas::refresh() {
334    AW_device *device = this->aww->get_device (AW_MIDDLE_AREA);
335    device->clear(-1);
336    clip_expose(this->aww, this, this->rect.l, this->rect.r,
337                this->rect.t, this->rect.b, 0, 0);
338}
339
340void AWT_resize_cb(AW_window *, AWT_canvas *scr, AW_CL) {
341    scr->zoom_reset();
342    AWT_expose_cb(scr->aww, scr, 0);
343}
344
345
346static void canvas_focus_cb(AW_window *, AWT_canvas *scr) {
347    if (scr->gb_main) {
348        scr->push_transaction();
349
350        int flags = scr->gfx->check_update(scr->gb_main);
351        if (flags) scr->recalc_size_and_refresh();
352
353        scr->pop_transaction();
354    }
355}
356
357const int ZOOM_SPEED_CLICK = 10;
358const int ZOOM_SPEED_WHEEL = 4;
359
360static bool handleZoomEvent(AWT_canvas *scr, AW_device *device, const AW_event& event, int percent) {
361    bool handled = false;
362    bool zoomIn  = true;
363
364    if      (event.button == AW_BUTTON_LEFT)  { handled = true; }
365    else if (event.button == AW_BUTTON_RIGHT) { handled = true; zoomIn  = false; }
366
367    if (handled) {
368        if (event.type == AW_Mouse_Press) {
369            scr->drag = 1;
370            scr->zoom_drag_sx = scr->zoom_drag_ex = event.x;
371            scr->zoom_drag_sy = scr->zoom_drag_ey = event.y;
372        }
373        else {
374            // delete last box
375            nt_draw_zoom_box(device, scr);
376            scr->drag = 0;
377
378            Rectangle screen(scr->rect, INCLUSIVE_OUTLINE);
379            Rectangle drag(scr->zoom_drag_sx, scr->zoom_drag_sy, scr->zoom_drag_ex, scr->zoom_drag_ey);
380
381            scr->zoom(device, zoomIn, drag, screen, percent);
382            AWT_expose_cb(scr->aww, scr, 0);
383        }
384    }
385    return handled;
386}
387
388bool AWT_canvas::handleWheelEvent(AW_device *device, const AW_event& event) {
389    if (event.button != AW_WHEEL_UP && event.button != AW_WHEEL_DOWN)  {
390        return false; // not handled
391    }
392    if (event.type == AW_Mouse_Press) {
393        if (event.keymodifier & AW_KEYMODE_CONTROL) {
394            AW_event faked = event;
395
396            faked.button = (event.button == AW_WHEEL_UP) ? AW_BUTTON_LEFT : AW_BUTTON_RIGHT;
397            handleZoomEvent(this, device, faked, ZOOM_SPEED_WHEEL);
398            faked.type   = AW_Mouse_Release;
399            handleZoomEvent(this, device, faked, ZOOM_SPEED_WHEEL);
400        }
401        else {
402            bool horizontal = event.keymodifier & AW_KEYMODE_ALT;
403
404            int viewport_size = horizontal ? (rect.r-rect.l+1) : (rect.b-rect.t+1);
405            int gfx_size      = horizontal ? (worldsize.r-worldsize.l) : (worldsize.b-worldsize.t);
406           
407            // scroll 10% of screen or 10% of graphic size (whichever is smaller):
408            int dist      = std::min(viewport_size / 20, gfx_size / 30);
409            int direction = event.button == AW_WHEEL_UP ? -dist : dist;
410
411            int dx = horizontal ? direction : 0;
412            int dy = horizontal ? 0 : direction;
413
414            scroll(dx, dy);
415        }
416    }
417    return true;
418}
419
420static void input_event(AW_window *aww, AWT_canvas *scr, AW_CL /*cd2*/) {
421    awt_assert(aww = scr->aww);
422
423    AW_event event;
424    aww->get_event(&event);
425   
426    AW_device *device = aww->get_device(AW_MIDDLE_AREA);
427    device->set_filter(AW_SCREEN);
428    device->reset();
429
430    scr->gfx->exports.clear();
431    scr->push_transaction();
432
433    scr->gfx->check_update(scr->gb_main);
434
435    bool event_handled = false;
436
437    if (scr->mode == AWT_MODE_ZOOM) { // zoom mode is identical for all applications, so handle it here
438        event_handled = handleZoomEvent(scr, device, event, ZOOM_SPEED_CLICK);
439    }
440
441    if (!event_handled) {
442        event_handled = scr->handleWheelEvent(device, event);
443    }
444
445    if (!event_handled) {
446        AW_device_click *click_device = aww->get_click_device(AW_MIDDLE_AREA, event.x, event.y, AWT_CATCH_LINE, AWT_CATCH_TEXT, 0);
447        click_device->set_filter(AW_CLICK);
448        device->set_filter(AW_SCREEN);
449
450        scr->init_device(click_device);
451        scr->init_device(device);
452
453        scr->gfx->show(click_device);
454        click_device->get_clicked_line(&scr->clicked_line);
455        click_device->get_clicked_text(&scr->clicked_text);
456
457        scr->gfx->command(device, scr->mode,
458                                event.button, event.keymodifier, event.keycode, event.character,
459                                event.type, event.x,
460                                event.y, &scr->clicked_line,
461                                &scr->clicked_text);
462        if (scr->gfx->exports.save) {
463            // save it
464            GB_ERROR error = scr->gfx->save(scr->gb_main, 0, 0, 0);
465            if (error) {
466                aw_message(error);
467                scr->gfx->load(scr->gb_main, 0, 0, 0);
468            }
469        }
470        if (scr->gb_main) {
471            scr->gfx->update(scr->gb_main);
472        }
473        scr->refresh_by_exports();
474    }
475
476    scr->zoom_drag_ex = event.x;
477    scr->zoom_drag_ey = event.y;
478    scr->pop_transaction();
479}
480
481
482void AWT_canvas::set_dragEndpoint(int dragx, int dragy) {
483    switch (gfx->exports.zoom_mode) {
484        case AWT_ZOOM_NEVER: {
485            awt_assert(0);
486            break;
487        }
488        case AWT_ZOOM_X: {
489            zoom_drag_sy = rect.t;
490            zoom_drag_ey = rect.b-1;
491            zoom_drag_ex = dragx;
492            break;
493        }
494        case AWT_ZOOM_Y: {
495            zoom_drag_sx = rect.l;
496            zoom_drag_ex = rect.r-1;
497            zoom_drag_ey = dragy;
498            break;
499        }
500        case AWT_ZOOM_BOTH: {
501            zoom_drag_ex = dragx;
502            zoom_drag_ey = dragy;
503
504            int drag_sx = zoom_drag_ex-zoom_drag_sx;
505            int drag_sy = zoom_drag_ey-zoom_drag_sy;
506
507            bool   correct_x = false;
508            bool   correct_y = false;
509            double factor;
510
511            int scr_sx = rect.r-rect.l;
512            int scr_sy = rect.b-rect.t;
513
514            if (drag_sx == 0) {
515                if (drag_sy != 0) { factor = double(drag_sy)/scr_sy; correct_x = true; }
516            }
517            else {
518                if (drag_sy == 0) { factor = double(drag_sx)/scr_sx; correct_y = true; }
519                else {
520                    double facx = double(drag_sx)/scr_sx;
521                    double facy = double(drag_sy)/scr_sy;
522
523                    if (fabs(facx)>fabs(facy)) { factor = facx; correct_y = true; }
524                    else                       { factor = facy; correct_x = true; }
525                }
526            }
527
528            if (correct_x) {
529                int width    = int(scr_sx*factor) * ((drag_sx*drag_sy) < 0 ? -1 : 1);
530                zoom_drag_ex = zoom_drag_sx+width;
531            }
532            else if (correct_y) {
533                int height = int(scr_sy*factor) * ((drag_sx*drag_sy) < 0 ? -1 : 1);
534                zoom_drag_ey = zoom_drag_sy+height;
535            }
536            break;
537        }
538    }
539}
540
541static void motion_event(AW_window *aww, AWT_canvas *scr, AW_CL /*cd2*/) {
542    AW_device *device = aww->get_device(AW_MIDDLE_AREA);
543    device->reset();
544    device->set_filter(AW_SCREEN);
545
546    scr->push_transaction();
547
548    AW_event event;
549    aww->get_event(&event);
550
551    if (event.button == AW_BUTTON_MIDDLE) {
552        // shift display in ALL modes
553        int dx = event.x - scr->zoom_drag_ex;
554        int dy = event.y - scr->zoom_drag_ey;
555
556        scr->zoom_drag_ex = event.x;
557        scr->zoom_drag_ey = event.y;
558
559        // display
560        scr->scroll(-dx*3, -dy*3);
561    }
562    else {
563        bool run_command = true;
564
565        if (event.button == AW_BUTTON_LEFT || event.button == AW_BUTTON_RIGHT) {
566            switch (scr->mode) {
567                case AWT_MODE_ZOOM:
568                    nt_draw_zoom_box(device, scr);
569                    scr->set_dragEndpoint(event.x, event.y);
570                    nt_draw_zoom_box(device, scr);
571                    run_command = false;
572                    break;
573
574                case AWT_MODE_SWAP2:
575                    if (event.button == AW_BUTTON_RIGHT) break;
576                    // fall-through
577                case AWT_MODE_MOVE: {
578                    scr->init_device(device);
579                    AW_device_click *click_device = aww->get_click_device(AW_MIDDLE_AREA,
580                                                                          event.x, event.y, AWT_CATCH_LINE,
581                                                                          AWT_CATCH_TEXT, 0);
582                    click_device->set_filter(AW_CLICK_DRAG);
583                    scr->init_device(click_device);
584                    scr->gfx->show(click_device);
585                    click_device->get_clicked_line(&scr->clicked_line);
586                    click_device->get_clicked_text(&scr->clicked_text);
587                    run_command  = false;
588                    break;
589                }
590                default:
591                    break;
592            }
593        }
594
595        if (run_command) {
596            scr->init_device(device);
597            scr->gfx->command(device, scr->mode,
598                                    event.button, event.keymodifier, event.keycode, event.character, AW_Mouse_Drag, event.x,
599                                    event.y, &scr->clicked_line,
600                                    &scr->clicked_text);
601            if (scr->gb_main) {
602                scr->gfx->update(scr->gb_main);
603            }
604        }
605    }
606
607    scr->refresh_by_exports();
608    scr->pop_transaction();
609}
610
611void AWT_canvas::scroll(int dx, int dy, bool dont_update_scrollbars) {
612    int csx, cdx, cwidth, csy, cdy, cheight;
613    AW_device *device;
614    if (!dont_update_scrollbars) {
615        this->old_hor_scroll_pos += dx;
616        this->set_horizontal_scrollbar_position(aww, this->old_hor_scroll_pos);
617        this->old_vert_scroll_pos += dy;
618        this->set_vertical_scrollbar_position(aww, this->old_vert_scroll_pos);
619    }
620    device = aww->get_device (AW_MIDDLE_AREA);
621    device->set_filter(AW_SCREEN);
622    device->reset();
623    int screenwidth = this->rect.r-this->rect.l;
624    int screenheight = this->rect.b-this->rect.t;
625
626    // compute move area params
627
628    if (dx>0) {
629        csx = dx;
630        cdx = 0;
631        cwidth = screenwidth-dx;
632    }
633    else {
634        csx = 0;
635        cdx = -dx;
636        cwidth = screenwidth+dx;
637    }
638    if (dy>0) {
639        csy = dy;
640        cdy = 0;
641        cheight = screenheight-dy;
642    }
643    else {
644        csy = 0;
645        cdy = -dy;
646        cheight = screenheight+dy;
647    }
648
649    // move area
650    if (!gfx->exports.dont_scroll) {
651        device->move_region(csx, csy, cwidth, cheight, cdx, cdy);
652        // redraw stripes
653        this->shift_x_to_fit -= dx/this->trans_to_fit;
654        this->shift_y_to_fit -= dy/this->trans_to_fit;
655
656        // x-stripe
657        if ((int)dx>0) {
658            clip_expose(aww, this,
659                        screenwidth-dx, screenwidth, 0, screenheight,
660                        -CLIP_OVERLAP,  0);
661        }
662        if ((int)dx<0) {
663            clip_expose(aww, this,
664                        0, -dx, 0, screenheight,
665                        CLIP_OVERLAP, 0);
666        }
667
668        // y-stripe
669        if ((int)dy>0) {
670            clip_expose(aww, this,
671                        0, screenwidth, screenheight-dy, screenheight,
672                        0, -CLIP_OVERLAP);
673        }
674        if ((int)dy<0) {
675            clip_expose(aww, this,
676                        0, screenwidth, 0,  -dy,
677                        0,  CLIP_OVERLAP);
678        }
679    }
680    else {          // redraw everything
681        // redraw stripes
682        this->shift_x_to_fit -= dx/this->trans_to_fit;
683        this->shift_y_to_fit -= dy/this->trans_to_fit;
684        AWT_expose_cb(aww, this,  0);
685    }
686    this->refresh();
687}
688
689static void scroll_vert_cb(AW_window *aww, AWT_canvas* scr, AW_CL /*cl1*/) {
690    int new_vert       = aww->slider_pos_vertical;
691    int delta_screen_y = (new_vert - scr->old_vert_scroll_pos);
692
693    scr->scroll(0, delta_screen_y, true);
694    scr->old_vert_scroll_pos = new_vert;
695}
696
697static void scroll_hor_cb(AW_window *aww, AWT_canvas* scr, AW_CL /*cl1*/) {
698    int new_hor        = aww->slider_pos_horizontal;
699    int delta_screen_x = (new_hor - scr->old_hor_scroll_pos);
700
701    scr->scroll(delta_screen_x, 0, true);
702    scr->old_hor_scroll_pos = new_hor;
703}
704
705
706AWT_canvas::AWT_canvas(GBDATA *gb_maini, AW_window *awwi, AWT_graphic *awd, AW_gc_manager &set_gc_manager, const char *user_awari)
707    : consider_text_for_size(true) 
708    , user_awar(strdup(user_awari))
709    , shift_x_to_fit(0)
710    , shift_y_to_fit(0)
711    , gb_main(gb_maini)
712    , aww(awwi)
713    , awr(aww->get_root())
714    , gfx(awd)
715    , gc_manager(gfx->init_devices(aww, aww->get_device (AW_MIDDLE_AREA), this, (AW_CL)0))
716    , drag_gc(aww->main_drag_gc)
717    , mode(AWT_MODE_NONE)
718{
719    gfx->drag_gc   = drag_gc;
720    set_gc_manager = gc_manager;
721
722    memset((char *)&clicked_line, 0, sizeof(clicked_line));
723    memset((char *)&clicked_text, 0, sizeof(clicked_text));
724
725    AWT_resize_cb(aww, this, 0);
726
727    aww->set_expose_callback(AW_MIDDLE_AREA, (AW_CB)AWT_expose_cb, (AW_CL)this, 0);
728    aww->set_resize_callback(AW_MIDDLE_AREA, (AW_CB)AWT_resize_cb, (AW_CL)this, 0);
729    aww->set_input_callback(AW_MIDDLE_AREA, (AW_CB)input_event, (AW_CL)this, 0);
730    aww->set_focus_callback((AW_CB)canvas_focus_cb, (AW_CL)this, 0);
731
732    aww->set_motion_callback(AW_MIDDLE_AREA, (AW_CB)motion_event, (AW_CL)this, 0);
733    aww->set_horizontal_change_callback((AW_CB)scroll_hor_cb, (AW_CL)this, 0);
734    aww->set_vertical_change_callback((AW_CB)scroll_vert_cb, (AW_CL)this, 0);
735}
736
737// --------------------
738//      AWT_graphic
739
740void AWT_graphic::command(AW_device *, AWT_COMMAND_MODE, int, AW_key_mod, AW_key_code, char,
741                          AW_event_type, AW_pos, AW_pos, AW_clicked_line *, AW_clicked_text *)
742{
743}
744
745void AWT_graphic::text(AW_device * /* device */, char * /* text */) {
746}
747
748// --------------------------
749//      AWT_nonDB_graphic
750
751GB_ERROR AWT_nonDB_graphic::load(GBDATA *, const char *, AW_CL, AW_CL) {
752    return "AWT_nonDB_graphic cannot be loaded";
753}
754
755GB_ERROR AWT_nonDB_graphic::save(GBDATA *, const char *, AW_CL, AW_CL) {
756    return "AWT_nonDB_graphic cannot be saved";
757}
758
759int AWT_nonDB_graphic::check_update(GBDATA *) {
760#if defined(DEBUG)
761    printf("AWT_nonDB_graphic can't be check for update\n");
762#endif // DEBUG
763    return -1;
764}
765void AWT_nonDB_graphic::update(GBDATA *) {
766#if defined(DEBUG)
767    printf("AWT_nonDB_graphic can't be updated\n");
768#endif // DEBUG
769}
Note: See TracBrowser for help on using the browser.