source: tags/arb-6.0-rc1/SL/TREEDISP/TreeDisplay.hxx

Last change on this file was 11888, checked in by westram, 11 years ago
  • highlight differences in production code triggered by build-flag 'UNIT_TESTS'
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : TreeDisplay.hxx                                   //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#ifndef TREEDISPLAY_HXX
12#define TREEDISPLAY_HXX
13
14#ifndef AP_TREE_HXX
15#include <AP_Tree.hxx>
16#endif
17#ifndef AWT_CANVAS_HXX
18#include <awt_canvas.hxx>
19#endif
20
21#define td_assert(cond) arb_assert(cond)
22
23#define AWAR_DTREE_BASELINEWIDTH   "awt/dtree/baselinewidth"
24#define AWAR_DTREE_VERICAL_DIST    "awt/dtree/verticaldist"
25#define AWAR_DTREE_AUTO_JUMP       "awt/dtree/autojump"
26#define AWAR_DTREE_SHOW_CIRCLE     "awt/dtree/show_circle"
27#define AWAR_DTREE_SHOW_BRACKETS   "awt/dtree/show_brackets"
28#define AWAR_DTREE_CIRCLE_ZOOM     "awt/dtree/circle_zoom"
29#define AWAR_DTREE_CIRCLE_MAX_SIZE "awt/dtree/max_size"
30#define AWAR_DTREE_USE_ELLIPSE     "awt/dtree/ellipse"
31#define AWAR_DTREE_GREY_LEVEL      "awt/dtree/greylevel"
32
33#define AWAR_DTREE_RADIAL_ZOOM_TEXT "awt/dtree/radial/zoomtext"
34#define AWAR_DTREE_RADIAL_XPAD      "awt/dtree/radial/xpadding"
35
36#define AWAR_DTREE_DENDRO_ZOOM_TEXT "awt/dtree/dendro/zoomtext"
37#define AWAR_DTREE_DENDRO_XPAD      "awt/dtree/dendro/xpadding"
38
39void awt_create_dtree_awars(AW_root *aw_root, AW_default db);
40
41#define NT_BOX_WIDTH      7 // pixel
42#define NT_ROOT_WIDTH     9
43#define NT_SELECTED_WIDTH 11
44
45#define AWT_TREE(ntw) DOWNCAST(AWT_graphic_tree*, (ntw)->gfx)
46
47
48enum AP_tree_display_type {
49    AP_TREE_NORMAL, // normal tree display (dendrogram)
50    AP_TREE_RADIAL, // radial tree display
51    AP_TREE_IRS, // like AP_TREE_NORMAL, with folding line
52    AP_LIST_NDS,
53    AP_LIST_SIMPLE // simple display only showing name (used at startup to avoid NDS error messages)
54};
55
56enum AP_tree_jump_type { // bit-values
57    AP_JUMP_UNFOLD_GROUPS     = 1,
58    AP_JUMP_CENTER_IF_VISIBLE = 2, // if already visible -> center (normally only done if IRS-mode or selected was invisible)
59    AP_JUMP_BE_VERBOOSE       = 4, // tell why nothing happened etc.
60
61    // convenience defs:
62    AP_JUMP_AUTO      = 0,
63    AP_JUMP_BY_BUTTON = AP_JUMP_UNFOLD_GROUPS|AP_JUMP_CENTER_IF_VISIBLE|AP_JUMP_BE_VERBOOSE,
64};
65
66inline bool sort_is_list_style(AP_tree_display_type sort) { return sort == AP_LIST_NDS || sort == AP_LIST_SIMPLE; }
67inline bool sort_is_tree_style(AP_tree_display_type sort) { return !sort_is_list_style(sort); }
68
69
70class AWT_graphic_tree_group_state;
71
72struct AWT_scaled_font_limits {
73    double ascent;
74    double descent;
75    double height;
76    double width;
77
78    void init(const AW_font_limits& font_limits, double factor) {
79        ascent  = font_limits.ascent*factor;
80        descent = font_limits.descent*factor;
81        height  = font_limits.height*factor;
82        width   = font_limits.width*factor;
83    }
84};
85
86enum AD_MAP_VIEWER_TYPE {
87    ADMVT_INFO,
88    ADMVT_WWW,
89    ADMVT_SELECT
90};
91
92typedef void (*AD_map_viewer_cb)(GBDATA *gbd, AD_MAP_VIEWER_TYPE type);
93
94struct DendroSubtreeLimits {
95    double y_branch;                                // ypos of branch to subtree
96    double y_top;                                   // top ypos of whole subtree
97    double y_bot;                                   // bottom ypos of whole subtree
98    double x_right;                                 // rightmost xpos of whole subtree
99
100    void combine(const DendroSubtreeLimits& other) {
101        y_top   = std::min(y_top, other.y_top);
102        y_bot   = std::max(y_bot, other.y_bot);
103        x_right = std::max(x_right, other.x_right);
104    }
105};
106
107struct AWT_command_data {
108    /*! any kind of data which has to be stored between different events (e.g. to support drag&drop)
109     * Purpose of this class is to allow to delete such data w/o knowing anything else.
110     */
111    virtual ~AWT_command_data() {}
112};
113
114class AWT_graphic_tree : public AWT_graphic, virtual Noncopyable {
115    char         *species_name;
116    AW::Position  cursor;
117
118    int    baselinewidth;
119    int    show_brackets;
120    int    show_circle;
121    int    use_ellipse;
122    float  circle_zoom_factor;
123    float  circle_max_size;
124
125    int zombies; // # of zombies during last load()
126    int duplicates; // # of duplicates during last load()
127
128    AW_pos paint_irs_sub_tree(AP_tree *node, AW_pos x_offset); // returns y pos
129
130    void unload();
131
132    // variables - tree compatibility
133
134    AP_tree * tree_proto;
135    bool link_to_database; // link on load ?
136
137    double list_tree_ruler_y;
138    double irs_tree_ruler_scale_factor;
139
140    AWT_scaled_font_limits scaled_font;
141    double                 scaled_branch_distance; // vertical distance between branches (may be extra-scaled in options)
142
143    AW_pos grey_level;
144
145    AW_device *disp_device; // device for recursive functions
146
147    const AW_bitset line_filter, vert_line_filter, mark_filter, group_bracket_filter, bs_circle_filter;
148    const AW_bitset leaf_text_filter, group_text_filter, remark_text_filter, other_text_filter;
149    const AW_bitset ruler_filter, root_filter;
150
151    bool nds_show_all;
152
153    AD_map_viewer_cb  map_viewer_cb;
154    AWT_command_data  *cmd_data;
155
156    void scale_text_koordinaten(AW_device *device, int gc, double& x, double& y, double orientation, int flag);
157
158    // functions to compute displayinformation
159
160    void show_dendrogram(AP_tree *at, AW::Position& pen, DendroSubtreeLimits& limits);
161
162    void show_radial_tree(AP_tree *at,
163                          double   x_center,
164                          double   y_center,
165                          double   tree_sprad,
166                          double   tree_orientation,
167                          double   x_root,
168                          double   y_root);
169
170    void show_nds_list(GBDATA * gb_main, bool use_nds);
171    void show_irs_tree(AP_tree *at, double height);
172
173    void box(int gc, const AW::Position& pos, int pixel_width, bool filled);
174    void filled_box(int gc, const AW::Position& pos, int pixel_width) { box(gc, pos, pixel_width, true); }
175    void empty_box(int gc, const AW::Position& pos, int pixel_width) { box(gc, pos, pixel_width, false); }
176    void diamond(int gc, const AW::Position& pos, int pixel_width);
177
178    const char *ruler_awar(const char *name);
179
180    void set_line_attributes_for(AP_tree *at) const {
181        disp_device->set_line_attributes(at->gr.gc, at->get_linewidth()+baselinewidth, AW_SOLID);
182    }
183
184    virtual void read_tree_settings();
185    void update_structure() { get_root_node()->compute_tree(); }
186    void apply_zoom_settings_for_treetype(AWT_canvas *ntw);
187
188    int draw_branch_line(int gc, const AW::Position& root, const AW::Position& leaf, AW_bitset filter) {
189        const AW_click_cd *old = disp_device->get_click_cd();
190        td_assert(old && old->get_cd1() && !old->get_cd2()); // cd1 should be the node
191
192        AW_click_cd branch(disp_device, old->get_cd1(), (AW_CL)"branch");
193        return disp_device->line(gc, root, leaf, filter);
194    }
195
196    bool warn_inappropriate_mode(AWT_COMMAND_MODE mode);
197
198protected:
199    void store_command_data(AWT_command_data *new_cmd_data) {
200        delete cmd_data;
201        cmd_data = new_cmd_data;
202    }
203    AWT_command_data *get_command_data() { return cmd_data; }
204
205public:
206
207    // *********** read only variables !!!
208
209    AW_root      *aw_root;
210    AP_tree_display_type  tree_sort;
211    AP_tree      *displayed_root; // root node of shown (sub-)tree; differs from real root if tree is zoomed logically
212    AP_tree_root *tree_static;
213    GBDATA       *gb_main;
214
215    // *********** public section
216
217    AWT_graphic_tree(AW_root *aw_root, GBDATA *gb_main, AD_map_viewer_cb map_viewer_cb);
218    ~AWT_graphic_tree() OVERRIDE;
219
220    AP_tree *get_root_node() { return tree_static ? tree_static->get_root_node() : NULL; }
221    bool is_logically_zoomed() { return displayed_root != get_root_node(); }
222
223    void init(RootedTreeNodeFactory *nodeMaker_, AliView *aliview, AP_sequence *seq_prototype, bool link_to_database_, bool insert_delete_cbs);
224    AW_gc_manager init_devices(AW_window *, AW_device *, AWT_canvas *ntw) OVERRIDE;
225
226    void show(AW_device *device) OVERRIDE;
227    const AW::Position& get_cursor() const { return cursor; }
228
229    void info(AW_device *device, AW_pos x, AW_pos y, AW_clicked_line *cl, AW_clicked_text *ct) OVERRIDE;
230
231private:
232    void handle_key(AW_device *device, AWT_graphic_event& event);
233public:
234    void handle_command(AW_device *device, AWT_graphic_event& event) OVERRIDE;
235
236    void mark_species_in_tree(AP_tree *at, int mark);
237    void mark_species_in_tree_that(AP_tree *at, int mark, int (*condition)(GBDATA*, void*), void *cd);
238
239    void mark_species_in_rest_of_tree(AP_tree *at, int mark);
240    void mark_species_in_rest_of_tree_that(AP_tree *at, int mark, int (*condition)(GBDATA*, void*), void *cd);
241
242    bool tree_has_marks(AP_tree *at);
243    bool rest_tree_has_marks(AP_tree *at);
244
245    void detect_group_state(AP_tree *at, AWT_graphic_tree_group_state *state, AP_tree *skip_this_son);
246
247    int      group_tree(AP_tree *at, int mode, int color_group);
248    void     group_rest_tree(AP_tree *at, int mode, int color_group);
249    void     reorder_tree(TreeOrder mode);
250    GB_ERROR create_group(AP_tree * at) __ATTR__USERESULT;
251    void     toggle_group(AP_tree * at);
252    GB_ERROR load(GBDATA *gb_main, const char *name, AW_CL,  AW_CL) OVERRIDE __ATTR__USERESULT;
253    GB_ERROR save(GBDATA *gb_main, const char *name, AW_CL cd1, AW_CL cd2) OVERRIDE __ATTR__USERESULT;
254    int      check_update(GBDATA *gb_main) OVERRIDE;         // reload tree if needed
255    void     update(GBDATA *gb_main) OVERRIDE;
256    void     set_tree_type(AP_tree_display_type type, AWT_canvas *ntw);
257
258    double get_irs_tree_ruler_scale_factor() const { return irs_tree_ruler_scale_factor; }
259    void show_ruler(AW_device *device, int gc);
260    void get_zombies_and_duplicates(int& zomb, int& dups) const { zomb = zombies; dups = duplicates; }
261
262#if defined(UNIT_TESTS) // UT_DIFF
263    friend class fake_AWT_graphic_tree;
264#endif
265};
266
267class ClickedTarget {
268    /*! Represents any target corresponding to some (mouse-)position in the tree display.
269     *
270     * The target is e.g. used as target for keystrokes or mouse clicks.
271     *
272     * For AP_LIST_NDS, this only represents the species (w/o any tree information).
273     * For other tree display modes, this represents a specific tree node.
274     *
275     * The space outside the tree does represent the whole tree (aka the root-node).
276     * (the necessary distance to the tree-structure/-text is defined by AWT_CATCH)
277     */
278
279    AP_tree *tree_node;
280    GBDATA  *gb_species;
281    bool     ruler;
282    bool     branch;
283
284    const AW_clicked_element *elem;
285
286    void init() {
287        tree_node  = NULL;
288        gb_species = NULL;
289        ruler      = false;
290        branch     = false;
291    }
292
293    void identify(AWT_graphic_tree *agt) {
294        init();
295        if (elem && elem->exists) {
296            const char *what = (const char*)elem->cd2();
297
298            if (what) {
299                if (strcmp(what, "species") == 0) { // entry in NDS list
300                    gb_species = (GBDATA*)elem->cd1();
301                    td_assert(gb_species);
302                }
303                else if (strcmp(what, "ruler") == 0) {
304                    ruler = !elem->cd1();
305                }
306                else if (strcmp(what, "branch") == 0) {
307                    branch = true; // indicates that a line really IS the branch (opposed to other branch-related lines like e.g. group-brackets)
308                }
309                else {
310                    td_assert(0); // unknown element type
311                }
312            }
313
314            if (!(gb_species || ruler)) {
315                tree_node = (AP_tree*)elem->cd1();
316                td_assert(branch || !what);
317            }
318        }
319        else { // use whole tree if mouse does not point to a subtree
320            tree_node = agt ? agt->get_root_node() : NULL;
321        }
322        td_assert(implicated(branch, tree_node));
323    }
324
325public:
326
327    ClickedTarget(AWT_graphic_tree *agt, const AW_clicked_element *clicked) : elem(clicked) {
328        // uses root of tree as target, when a position outside of the tree is selected
329        // (e.g. used for key-commands)
330        identify(agt);
331    }
332    ClickedTarget(const AW_clicked_element *clicked) : elem(clicked) {
333        // accept only normal branches as targets
334        identify(NULL);
335    }
336
337    const AW_clicked_element *element() const { return elem; }
338    AP_tree *node() const { return tree_node; }
339    GBDATA *species() const { return gb_species; }
340
341    bool is_text() const { return elem && elem->is_text(); }
342    bool is_line() const { return elem && elem->is_line(); }
343    bool is_branch() const { return branch; }
344    bool is_ruler() const { return ruler; }
345
346    double get_rel_attach() const {
347        // return [0..1] according to exact position where element is dropped
348        if (is_line() && (is_branch() || ruler)) return elem->get_rel_pos();
349        return 0.5; // act like "drop on branch-center"
350    }
351};
352
353AWT_graphic_tree *NT_generate_tree(AW_root *root, GBDATA *gb_main, AD_map_viewer_cb map_viewer_cb);
354bool AWT_show_branch_remark(AW_device *device, const char *remark_branch, bool is_leaf, AW_pos x, AW_pos y, AW_pos alignment, AW_bitset filteri);
355
356#else
357#error TreeDisplay.hxx included twice
358#endif // TREEDISPLAY_HXX
Note: See TracBrowser for help on using the repository browser.