source: branches/profile/SL/TREEDISP/irstree_display.cxx

Last change on this file was 11492, checked in by westram, 11 years ago
  • fix several doxygen issues (doxygen 1.6.3)
    • force macro expansion for IF_ASSERTION_USED
    • fixed changed param names
    • named some anonymous (nested) structs
    • remove/quote several '#' (triggering unknown commands)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : irstree_display.cxx                               //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "TreeDisplay.hxx"
12
13#include <nds.h>
14
15using namespace AW;
16
17// *********************** paint sub tree ************************
18
19const int tipBoxSize = 3;
20
21struct IRS_data {
22    bool   draw_separator;
23    AW_pos y;
24    AW_pos min_y;    // ypos of folding line
25    AW_pos max_y;
26    AW_pos step_y;
27    AW_pos halfstep_y;
28    AW_pos onePixel;
29    AW_pos fold_x1, fold_x2;
30
31    int    group_closed;
32    double x_scale;
33
34    Vector adjust_text;
35    AW_pos tree_depth;
36
37    AW_pos gap; // between group frame and (box or text)
38    AW_pos openGroupExtra; // extra y-size of unfolded groups
39
40    AW_bitset sep_filter;
41   
42    bool is_size_device;
43
44    void draw_top_separator_once(AW_device *device) {
45        if (draw_separator) {
46            if (!is_size_device) {
47                device->set_line_attributes(AWT_GC_GROUPS, 4, AW_SOLID);
48                device->line(AWT_GC_GROUPS, fold_x1, min_y, fold_x2, min_y, sep_filter);
49            }
50            draw_separator = false;
51        }
52    }
53
54   
55};
56static IRS_data IRS;
57
58AW_pos AWT_graphic_tree::paint_irs_sub_tree(AP_tree *node, AW_pos x_offset) {
59    if (!IRS.is_size_device) {
60        // check clipping rectangle
61        if (IRS.y > IRS.max_y) {
62            return IRS.max_y;
63        }
64        AW_pos height_of_subtree = IRS.step_y*node->gr.view_sum;
65        if (IRS.y + height_of_subtree < IRS.min_y) {
66            IRS.y += height_of_subtree;
67            return IRS.min_y;
68        }
69    }
70
71    if (node->is_leaf) {
72        IRS.y+=IRS.step_y;
73        IRS.draw_top_separator_once(disp_device);
74
75        Position leaf(x_offset, IRS.y);
76
77        if (node->hasName(species_name)) {
78            cursor = leaf;
79            if (IRS.is_size_device) {
80                // hack to fix calculated cursor position:
81                // - IRS tree reports different cursor positions in AW_SIZE and normal draw modes.
82                // - the main reason for the difference is the number of open groups clipped away
83                //   above the separator line.
84                // - There is still some unhandled difference mostlikely caused by the number of
85                //   open groups on the screen, but in most cases the cursor position is inside view now.
86               
87                double correctionPerGroup = IRS.openGroupExtra; // depends on size of marked-species-font
88                double cursorCorrection   = -IRS.group_closed * correctionPerGroup;
89                cursor.movey(cursorCorrection);
90            }
91        }
92
93        AW_click_cd cd(disp_device, (AW_CL)node);
94       
95        int gc = node->gr.gc;
96        if (node->gb_node && GB_read_flag(node->gb_node)) {
97            set_line_attributes_for(node);
98            filled_box(gc, leaf, NT_BOX_WIDTH);
99        }
100
101        Position    textpos  = leaf+IRS.adjust_text;
102        const char *specinfo = make_node_text_nds(gb_main, node->gb_node, NDS_OUTPUT_LEAFTEXT, node, tree_static->get_tree_name());
103        disp_device->text(gc, specinfo, textpos);
104
105        return IRS.y;
106    }
107
108    const char *group_name  = NULL;
109    AW_pos      frame_width = -1;
110
111    if (node->gb_node) {
112        if (!node->father) { // root node - don't try to get taxonomy
113            group_name = tree_static->get_tree_name();
114        }
115        else {
116            group_name = make_node_text_nds(gb_main, node->gb_node, NDS_OUTPUT_LEAFTEXT, node, tree_static->get_tree_name());
117        }
118        frame_width = node->gr.max_tree_depth * IRS.x_scale;
119    }
120
121    if (node->gr.grouped) { // folded group
122        AW_pos y_center;
123
124        AW_pos frame_height = node->gr.view_sum * IRS.step_y;
125        AW_pos frame_y1     = IRS.y+IRS.halfstep_y+IRS.gap;
126        AW_pos frame_y2     = frame_y1 + frame_height;
127
128        if (frame_y2 >= IRS.min_y) {
129            if (frame_y1 < IRS.min_y) { // shift folded groups into the folding area (disappears when completely inside)
130                frame_y1  = IRS.min_y;
131                IRS.min_y += IRS.halfstep_y+IRS.gap;
132            }
133
134            AW_pos    visible_frame_height = frame_y2-frame_y1;
135            Rectangle frame(Position(x_offset, frame_y1), Vector(frame_width, visible_frame_height));
136
137            // draw group frame (unclosed on right hand):
138            AW_click_cd cd(disp_device, (AW_CL)node);
139
140            int gc = AWT_GC_GROUPS;
141            disp_device->set_line_attributes(gc, 1, AW_SOLID);
142            disp_device->line(gc, frame.upper_edge());
143            disp_device->line(gc, frame.left_edge());
144            disp_device->line(gc, frame.lower_edge());
145
146            gc = node->gr.gc;
147            disp_device->set_grey_level(gc, grey_level);
148            set_line_attributes_for(node);
149            filled_box(gc, frame.upper_left_corner(), tipBoxSize);
150
151            Vector    frame2box(IRS.gap, IRS.gap);
152            Rectangle gbox(frame.upper_left_corner()+frame2box, Vector(frame.width()*.5, frame.height()-2*IRS.gap));
153
154            disp_device->box(gc, true, gbox);
155
156            Position box_rcenter = gbox.right_edge().centroid();
157
158            if (group_name) { //  a node name should be displayed
159                const char *groupinfo = GBS_global_string("%s (%u)", group_name, node->gr.leaf_sum);
160                disp_device->text(gc, groupinfo, box_rcenter+IRS.adjust_text);
161            }
162
163            IRS.draw_top_separator_once(disp_device);
164
165            IRS.y    += frame_height + 2*IRS.gap;
166            y_center  = box_rcenter.ypos();
167        }
168        else {
169            IRS.y    += frame_height + 2*IRS.gap;
170            y_center  = IRS.min_y;
171
172            if (IRS.y > IRS.min_y) {
173                IRS.y = IRS.min_y;
174            }
175        }
176        return y_center;
177    }
178
179    AW_pos group_y1 = IRS.y;
180
181    if (group_name != NULL) { // unfolded group
182        if (group_y1 >= IRS.min_y) {
183            IRS.draw_top_separator_once(disp_device);
184            group_y1 = IRS.y + IRS.halfstep_y+IRS.gap;
185        }
186        else {
187            group_y1   = IRS.min_y;
188            IRS.min_y += IRS.openGroupExtra;
189        }
190        IRS.y += IRS.openGroupExtra;
191
192        int         gc = AWT_GC_GROUPS;
193        AW_click_cd cd(disp_device, (AW_CL)node);
194        disp_device->set_line_attributes(gc, 1, AW_DOTTED);
195        disp_device->line(gc, x_offset-IRS.onePixel, group_y1, x_offset+frame_width, group_y1); // opened-group-frame
196
197        const char *groupinfo = GBS_global_string("%s (%u)", group_name, node->gr.leaf_sum);
198        disp_device->text(node->gr.gc, groupinfo, x_offset-IRS.onePixel + IRS.gap, group_y1 + 2*IRS.adjust_text.y() + IRS.gap);
199    }
200
201    // draw subtrees
202    AW_pos left_x = x_offset + IRS.x_scale * node->leftlen;
203    AW_pos left_y = paint_irs_sub_tree(node->get_leftson(), left_x);
204
205    AW_pos right_x = x_offset + IRS.x_scale * node->rightlen;
206    AW_pos right_y = paint_irs_sub_tree(node->get_rightson(), right_x);
207
208    if (group_name != NULL) IRS.group_closed++;
209
210    // draw structure
211    if (left_y > IRS.min_y) {
212        if (left_y < IRS.max_y) { // clip y on top border
213            AW_click_cd cd(disp_device, (AW_CL)node->leftson);
214            if (node->leftson->get_remark()) {
215                AWT_show_branch_remark(disp_device, node->leftson->get_remark(), node->leftson->is_leaf, left_x, left_y, 1, remark_text_filter);
216            }
217            set_line_attributes_for(node->get_leftson()); 
218            draw_branch_line(node->get_leftson()->gr.gc, Position(x_offset, left_y), Position(left_x, left_y), line_filter);
219        }
220    }
221    else {
222        left_y = IRS.min_y;
223    }
224
225    AW_pos y_center = (left_y + right_y)*0.5;
226
227    if (right_y > IRS.min_y && right_y < IRS.max_y) { // visible right branch in lower part of display
228        AW_click_cd cd(disp_device, (AW_CL)node->rightson);
229        if (node->rightson->get_remark()) {
230            AWT_show_branch_remark(disp_device, node->rightson->get_remark(), node->rightson->is_leaf, right_x, right_y, 1, remark_text_filter);
231        }
232        set_line_attributes_for(node->get_rightson()); 
233        draw_branch_line(node->get_rightson()->gr.gc, Position(x_offset, right_y), Position(right_x,  right_y), line_filter);
234    }
235
236    AW_click_cd cd(disp_device, (AW_CL)node);
237    set_line_attributes_for(node->get_leftson());
238    disp_device->line(node->get_leftson()->gr.gc, x_offset, y_center, x_offset, left_y);
239
240    set_line_attributes_for(node->get_rightson());
241    disp_device->line(node->get_rightson()->gr.gc, x_offset, y_center, x_offset, right_y);
242
243    if (group_name != NULL) { // close unfolded group brackets and draw tipbox
244        IRS.+= IRS.halfstep_y+IRS.gap;
245
246        int gc = AWT_GC_GROUPS;
247        disp_device->set_line_attributes(gc, 1, AW_DOTTED);
248        disp_device->line(gc, x_offset-IRS.onePixel, IRS.y, x_offset+frame_width, IRS.y); // opened-group-frame
249        disp_device->line(gc, x_offset-IRS.onePixel, group_y1, x_offset-IRS.onePixel,  IRS.y); // opened-group-frame
250       
251        gc = node->gr.gc;
252        disp_device->set_grey_level(gc, grey_level);
253        set_line_attributes_for(node);
254        filled_box(gc, Position(x_offset-IRS.onePixel, group_y1), tipBoxSize);
255    }
256    return y_center;
257}
258
259void AWT_graphic_tree::show_irs_tree(AP_tree *at, double height) {
260
261    IRS.draw_separator = true;
262    IRS.y              = 0;
263    IRS.step_y         = height;
264    IRS.halfstep_y     = IRS.step_y*0.5;
265    IRS.x_scale        = 200.0;      // @@@ should not have any effect, since display gets x-scaled. But if it's to low (e.g. 1.0) scaling on zoom-reset does not work
266
267    const AW_font_limits& limits = disp_device->get_font_limits(AWT_GC_SELECTED, 0);
268
269    IRS.adjust_text    = disp_device->rtransform(Vector(NT_BOX_WIDTH, limits.ascent*0.5));
270    IRS.onePixel       = disp_device->rtransform_size(1.0);
271    IRS.gap            = 3*IRS.onePixel;
272    IRS.group_closed   = 0;
273    IRS.tree_depth     = at->gr.max_tree_depth;
274    IRS.openGroupExtra = IRS.step_y+IRS.gap;
275    IRS.sep_filter     = AW_SCREEN|AW_PRINTER_CLIP;
276
277    IRS.is_size_device = disp_device->type() == AW_DEVICE_SIZE;
278
279    Position  corner = disp_device->rtransform(Origin);   // real world coordinates of left/upper screen corner
280    Rectangle rclip  = disp_device->get_rtransformed_cliprect();
281
282    // the following values currently contain nonsense for size device @@@
283    IRS.min_y   = corner.ypos();
284    IRS.max_y   = rclip.bottom();
285    IRS.fold_x1 = rclip.left();
286    IRS.fold_x2 = rclip.right();
287
288    list_tree_ruler_y           = paint_irs_sub_tree(at, 0);
289    irs_tree_ruler_scale_factor = IRS.x_scale;
290   
291    disp_device->invisible(corner); // @@@ remove when size-dev works
292}
Note: See TracBrowser for help on using the repository browser.