source: tags/ms_r16q2/AWT/awt_canvas.hxx

Last change on this file was 14952, checked in by westram, 8 years ago
  • fix canvas resize/zoom-reset
    • replaced calls to AWT_expose_cb by AWT_canvas::refresh
    • replaced calls to AWT_resize_cb by AWT_canvas::zoom_reset_and_refresh
    • fixed double refresh in AWT_canvas::scroll
    • fixed recalc_size(true)
      • if canvas is scrolled out at top or left side ⇒ fix resulting scroll-offset according to size-change
    • instead of zoom_reset do recalc_size when
      • jumping to species in folded group (or outside logical subtree)
      • changing vertical branch distance or group scales (in "Tree Settings")
      • changing font(size)
    • never trigger zoom-reset in AWT_graphic_tree::check_update
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1#ifndef AWT_CANVAS_HXX
2#define AWT_CANVAS_HXX
3
4#ifndef AW_WINDOW_HXX
5#include <aw_window.hxx>
6#endif
7#ifndef AW_DEVICE_HXX
8#include <aw_device.hxx>
9#endif
10#ifndef AW_DEVICE_CLICK_HXX
11#include <aw_device_click.hxx>
12#endif
13#ifndef ATTRIBUTES_H
14#include <attributes.h>
15#endif
16#ifndef ARB_ASSERT_H
17#include <arb_assert.h>
18#endif
19
20class AWT_canvas;
21class AW_device;
22
23enum AWT_COMMAND_MODE {
24    AWT_MODE_NONE,
25    AWT_MODE_EMPTY, // placeholder (currently used in PARSIMONY)
26
27    // NTREE, PARSIMONY, GENEMAP and SECEDIT:
28    AWT_MODE_ZOOM,
29
30    // NTREE, PARSIMONY and GENEMAP:
31    AWT_MODE_SELECT,
32
33    // NTREE, PARSIMONY and SECEDIT:
34    AWT_MODE_SETROOT,
35
36    // NTREE and GENEMAP:
37    AWT_MODE_INFO,
38
39    // NTREE and PARSIMONY:
40    AWT_MODE_MOVE,
41    AWT_MODE_MARK,
42    AWT_MODE_GROUP,
43    AWT_MODE_LZOOM,
44    AWT_MODE_SWAP,
45
46    // NTREE and SECEDIT:
47    AWT_MODE_ROTATE,
48
49    // NTREE only:
50    AWT_MODE_LINE,
51    AWT_MODE_WWW,
52    AWT_MODE_SPREAD,
53    AWT_MODE_LENGTH,
54    AWT_MODE_MULTIFURC,
55
56    // PARSIMONY only:
57    AWT_MODE_KERNINGHAN,
58    AWT_MODE_NNI,
59    AWT_MODE_OPTIMIZE,
60
61    // SECEDIT only:
62    AWT_MODE_FOLD,
63    AWT_MODE_CURSOR,
64    AWT_MODE_EDIT,
65    AWT_MODE_PINFO,
66    AWT_MODE_STRETCH,
67    AWT_MODE_SET_CURSOR
68};
69
70#define STANDARD_PADDING 10
71
72// --------------------------------------------------------------------------------
73// AWT_zoom_mode + AWT_fit_mode are correlated, but not strictly coupled
74
75enum AWT_zoom_mode { // bit values!
76    AWT_ZOOM_NEVER = 0,
77    AWT_ZOOM_X     = 1,
78    AWT_ZOOM_Y     = 2,
79    AWT_ZOOM_BOTH  = 3,
80};
81
82enum AWT_fit_mode {
83    AWT_FIT_NEVER,
84    AWT_FIT_LARGER, 
85    AWT_FIT_SMALLER, 
86    AWT_FIT_X, 
87    AWT_FIT_Y, 
88};
89
90// used combinations are:
91// AWT_ZOOM_NEVER + AWT_FIT_NEVER (NDS list, others)
92// AWT_ZOOM_X + AWT_FIT_X (dendrogram tree)
93// AWT_ZOOM_Y + AWT_FIT_Y
94// AWT_ZOOM_BOTH + AWT_FIT_LARGER (radial tree/gene-map; secedit)
95// AWT_ZOOM_BOTH + AWT_FIT_SMALLER (book-style gene-map)
96//
97// other combinations may work as well. some combinations make no sense.
98// --------------------------------------------------------------------------------
99
100
101class AWT_graphic_exports {
102    AW_borders default_padding;
103    AW_borders padding;
104
105public:
106    unsigned int refresh : 1;          // 1 -> do a refresh
107    unsigned int resize : 1;           // 1 -> size of graphic might have changed (implies refresh)
108    unsigned int structure_change : 1; // 1 -> call update_structure (implies resize) // @@@ rename -> need_reload
109    unsigned int zoom_reset : 1;       // 1 -> do a zoom-reset (implies resize)
110    unsigned int save : 1;             // 1 -> save structure to DB (implies structure_change)
111
112
113    AWT_zoom_mode zoom_mode;
114    AWT_fit_mode  fit_mode;
115
116    unsigned int dont_scroll : 1; // normally 0 (1 for IRS tree)
117
118    void init();     // like clear, but resets fit, scroll state and padding
119    void clear();
120
121    void set_default_padding(int t, int b, int l, int r) {
122        default_padding.t = t;
123        default_padding.b = b;
124        default_padding.l = l;
125        default_padding.r = r;
126
127        padding = default_padding;
128    }
129
130    void set_equilateral_default_padding(int pad) { set_default_padding(pad, pad, pad, pad); }
131    void set_standard_default_padding() { set_equilateral_default_padding(STANDARD_PADDING); }
132
133    void set_extra_text_padding(const AW_borders& text_padding) {
134        padding.t = default_padding.t + text_padding.t;
135        padding.b = default_padding.b + text_padding.b;
136        padding.l = default_padding.l + text_padding.l;
137        padding.r = default_padding.r + text_padding.r;
138    }
139
140    int get_x_padding() const { return padding.l+padding.r; }
141    int get_y_padding() const { return padding.t+padding.b; }
142    int get_top_padding() const { return padding.t; }
143    int get_left_padding() const { return padding.l; }
144
145    AW::Vector zoomVector(double transToFit) const {
146        return AW::Vector(zoom_mode&AWT_ZOOM_X ? transToFit : 1.0,
147                          zoom_mode&AWT_ZOOM_Y ? transToFit : 1.0);
148    }
149};
150
151class AWT_graphic_event : virtual Noncopyable {
152    AWT_COMMAND_MODE M_cmd;  // currently active mode
153
154    AW_MouseButton M_button;
155    AW_key_mod     M_key_modifier;
156    AW_key_code    M_key_code;
157    char           M_key_char;
158    AW_event_type  M_type;
159
160    AW::Position mousepos;
161
162    AW_device_click *click_dev;
163
164public:
165    AWT_graphic_event(AWT_COMMAND_MODE cmd_, const AW_event& event, bool is_drag, AW_device_click *click_dev_)
166        : M_cmd(cmd_),
167          M_button(event.button),
168          M_key_modifier(event.keymodifier),
169          M_key_code(event.keycode),
170          M_key_char(event.character),
171          M_type(is_drag ? AW_Mouse_Drag : event.type),
172          mousepos(event.x, event.y),
173          click_dev(click_dev_)
174    {}
175
176    AWT_COMMAND_MODE cmd() const { return M_cmd; }
177    AW_MouseButton button() const { return M_button; }
178
179    AW_key_mod key_modifier() const { return M_key_modifier; }
180    AW_key_code key_code() const { return M_key_code; }
181    char key_char() const { return M_key_char; }
182
183    AW_event_type type() const { return M_type; }
184
185    const AW::Position& position() const { return mousepos; } // screen-coordinates
186
187    const AW_clicked_element *best_click(AW_device_click::ClickPreference prefer = AW_device_click::PREFER_NEARER) {
188        return click_dev ? click_dev->best_click(prefer) : NULL;
189    }
190};
191
192class AWT_graphic {
193    friend class AWT_canvas;
194
195    void refresh_by_exports(AWT_canvas *scr);
196    void postevent_handler(GBDATA *gb_main);
197
198    bool detect_drag_target;
199
200protected:
201    int drag_gc;
202
203public:
204    AWT_graphic_exports exports;
205
206    AWT_graphic() { exports.init(); }
207    virtual ~AWT_graphic() {}
208
209    // pure virtual interface (methods implemented by AWT_nonDB_graphic)
210
211    virtual GB_ERROR load(GBDATA *gb_main, const char *name) = 0;
212    virtual GB_ERROR save(GBDATA *gb_main, const char *name) = 0;
213    virtual int  check_update(GBDATA *gb_main)               = 0; // check whether anything changed
214    virtual void update(GBDATA *gb_main)                     = 0; // mark the database
215
216    // pure virtual interface (rest)
217
218    virtual void show(AW_device *device) = 0;
219
220    virtual AW_gc_manager *init_devices(AW_window *, AW_device *, AWT_canvas *scr) = 0; /* init gcs, if any gc is changed AWT_GC_changed_cb() is called */
221
222    virtual void handle_command(AW_device *device, AWT_graphic_event& event) = 0;
223    virtual void update_structure()                                          = 0; // called when exports.structure_change == 1
224
225    bool wants_drag_target() const { return detect_drag_target; }
226    void drag_target_detection(bool detect) { detect_drag_target = detect; }
227
228    int get_drag_gc() const { return drag_gc; }
229};
230
231class AWT_nonDB_graphic : public AWT_graphic { // @@@ check AWT_nonDB_graphic
232    void update_structure() {}
233    // a partly implementation of AWT_graphic
234public:
235    AWT_nonDB_graphic() {}
236    virtual ~AWT_nonDB_graphic() OVERRIDE {}
237
238    // dummy functions, only spittings out warnings:
239    GB_ERROR load(GBDATA *gb_main, const char *name) OVERRIDE __ATTR__USERESULT;
240    GB_ERROR save(GBDATA *gb_main, const char *name) OVERRIDE __ATTR__USERESULT;
241    int  check_update(GBDATA *gb_main) OVERRIDE;
242    void update(GBDATA *gb_main) OVERRIDE;
243};
244
245
246#define EPS               0.0001 // div zero check
247#define CLIP_OVERLAP      15
248#define AWT_ZOOM_OUT_STEP 40    // (pixel) rand um screen
249#define AWT_MIN_WIDTH     100   // Minimum center screen (= screen-offset)
250
251enum {
252    AWT_d_screen = 1
253};
254
255class AWT_canvas : virtual Noncopyable {
256    bool consider_text_for_size;
257    char *gc_base_name;
258
259public:
260    // too many callbacks -> public
261    // in fact: private
262    // (in real fact: needs rewrite)
263
264    char   *user_awar; // contains name of awar (awar contains name of tree displayed in canvas)
265    void    init_device(AW_device *device);
266    AW_pos  trans_to_fit;
267    AW_pos  shift_x_to_fit;
268    AW_pos  shift_y_to_fit;
269
270    int old_hor_scroll_pos;
271    int old_vert_scroll_pos;
272    AW_screen_area rect;  // screen coordinates
273    AW_world worldinfo; // real coordinates without transform.
274    AW_world worldsize;
275    int zoom_drag_sx;
276    int zoom_drag_sy;
277    int zoom_drag_ex;
278    int zoom_drag_ey;
279    int drag;
280
281    void set_scrollbars();
282    void set_dragEndpoint(int x, int y);
283
284    void set_horizontal_scrollbar_position(AW_window *aww, int pos);
285    void set_vertical_scrollbar_position(AW_window *aww, int pos);
286
287
288    // public (read only)
289
290    GBDATA      *gb_main;
291    AW_window   *aww;
292    AW_root     *awr;
293    AWT_graphic *gfx;
294
295    AW_gc_manager *gc_manager;
296
297    AWT_COMMAND_MODE mode;
298
299    // real public
300
301    AWT_canvas(GBDATA *gb_main, AW_window *aww, const char *gc_base_name_, AWT_graphic *awd, const char *user_awar);
302
303    inline void push_transaction() const;
304    inline void pop_transaction() const;
305
306    void refresh();
307
308    void recalc_size(bool adjust_scrollbars);
309    void recalc_size_and_refresh() { recalc_size(true); refresh(); }
310
311    void zoom_reset();
312    void zoom_reset_and_refresh() { zoom_reset(); refresh(); }
313
314    void set_consider_text_for_zoom_reset(bool consider) { consider_text_for_size = consider; }
315
316    void zoom(AW_device *device, bool zoomIn, const AW::Rectangle& wanted_part, const AW::Rectangle& current_part, int percent);
317
318    void set_mode(AWT_COMMAND_MODE mo) { mode = mo; }
319
320    void scroll(int delta_x, int delta_y, bool dont_update_scrollbars = false);
321    void scroll(const AW::Vector& delta, bool dont_update_scrollbars = false) {
322        scroll(int(delta.x()), int(delta.y()), dont_update_scrollbars);
323    }
324
325    bool handleWheelEvent(AW_device *device, const AW_event& event);
326
327    const char *get_gc_base_name() const { return gc_base_name; }
328
329    void postevent_handler();
330};
331
332inline void AWT_graphic::refresh_by_exports(AWT_canvas *scr) {
333    if (exports.zoom_reset)   scr->zoom_reset_and_refresh();
334    else if (exports.resize)  scr->recalc_size_and_refresh();
335    else if (exports.refresh) scr->refresh();
336}
337
338void AWT_expose_cb(UNFIXED, AWT_canvas *scr);
339void AWT_resize_cb(UNFIXED, AWT_canvas *scr);
340void AWT_GC_changed_cb(GcChange whatChanged, AWT_canvas *scr);
341
342void AWT_popup_tree_export_window(AW_window *parent_win, AWT_canvas *scr);
343void AWT_popup_sec_export_window (AW_window *parent_win, AWT_canvas *scr);
344void AWT_popup_print_window      (AW_window *parent_win, AWT_canvas *scr);
345
346
347#endif
Note: See TracBrowser for help on using the repository browser.