source: tags/testbuild/SL/TREEDISP/TreeDisplay.hxx

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