source: branches/profile/SL/TREEDISP/TreeDisplay.hxx

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