source: tags/arb-6.0.4/SL/TREEDISP/TreeDisplay.hxx

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