source: tags/ms_r16q3/SL/TREEDISP/irstree_display.cxx

Last change on this file was 15317, checked in by westram, 8 years ago
  • explicitely specify CL_NODE for AW_click_cds
  • use switch to check click-types
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 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#include <AP_TreeColors.hxx>
13
14#include <nds.h>
15
16using namespace AW;
17
18// *********************** paint sub tree ************************
19
20const int TIP_BOX_SIZE = 3;
21
22struct IRS_data {
23    bool   draw_separator;
24    AW_pos y;
25    AW_pos min_y;    // ypos of folding line
26    AW_pos max_y;
27    AW_pos step_y;
28    AW_pos halfstep_y;
29    AW_pos onePixel;
30    AW_pos fold_x1, fold_x2;
31
32    int    group_closed;
33    double x_scale;
34
35    Vector adjust_text;
36    AW_pos tree_depth;
37
38    AW_pos gap; // between group frame and (box or text)
39    AW_pos openGroupExtra; // extra y-size of unfolded groups
40
41    AW_bitset sep_filter;
42   
43    bool is_size_device;
44
45    void draw_top_separator_once(AW_device *device) {
46        if (draw_separator) {
47            if (!is_size_device) {
48                device->set_line_attributes(AWT_GC_IRS_GROUP_BOX, 4, AW_SOLID);
49                device->line(AWT_GC_IRS_GROUP_BOX, fold_x1, min_y, fold_x2, min_y, sep_filter);
50            }
51            draw_separator = false;
52        }
53    }
54
55   
56};
57static IRS_data IRS;
58
59AW_pos AWT_graphic_tree::paint_irs_sub_tree(AP_tree *node, AW_pos x_offset) {
60    if (!IRS.is_size_device) {
61        // check clipping rectangle
62        if (IRS.y > IRS.max_y) {
63            return IRS.max_y;
64        }
65        AW_pos height_of_subtree = IRS.step_y*node->gr.view_sum;
66        if (IRS.y + height_of_subtree < IRS.min_y) {
67            IRS.y += height_of_subtree;
68            return IRS.min_y;
69        }
70    }
71
72    if (node->is_leaf) {
73        IRS.y+=IRS.step_y;
74        IRS.draw_top_separator_once(disp_device);
75
76        Position leaf(x_offset, IRS.y);
77
78        if (node->hasName(species_name)) {
79            cursor = leaf;
80            if (IRS.is_size_device) {
81                // hack to fix calculated cursor position:
82                // - IRS tree reports different cursor positions in AW_SIZE and normal draw modes.
83                // - the main reason for the difference is the number of open groups clipped away
84                //   above the separator line.
85                // - There is still some unhandled difference mostlikely caused by the number of
86                //   open groups on the screen, but in most cases the cursor position is inside view now.
87               
88                double correctionPerGroup = IRS.openGroupExtra; // depends on size of marked-species-font
89                double cursorCorrection   = -IRS.group_closed * correctionPerGroup;
90                cursor.movey(cursorCorrection);
91            }
92        }
93
94        AW_click_cd cd(disp_device, (AW_CL)node, CL_NODE);
95       
96        int gc = node->gr.gc;
97        if (node->gb_node && GB_read_flag(node->gb_node)) {
98            set_line_attributes_for(node);
99            filled_box(gc, leaf, NT_BOX_WIDTH);
100        }
101
102        Position    textpos  = leaf+IRS.adjust_text;
103        const char *specinfo = make_node_text_nds(gb_main, node->gb_node, NDS_OUTPUT_LEAFTEXT, node, tree_static->get_tree_name());
104        disp_device->text(gc, specinfo, textpos);
105
106        return IRS.y;
107    }
108
109    AW_pos frame_width = NAN;
110    AW_pos group_y1    = NAN;
111
112    if (node->is_named_group()) {
113        frame_width = node->gr.max_tree_depth * IRS.x_scale;
114
115        if (node->gr.grouped) { // folded group
116            AW_pos y_center;
117
118            AW_pos frame_height = node->gr.view_sum * IRS.step_y;
119            AW_pos frame_y1     = IRS.y+IRS.halfstep_y+IRS.gap;
120            AW_pos frame_y2     = frame_y1 + frame_height;
121
122            if (frame_y2 >= IRS.min_y) {
123                if (frame_y1 < IRS.min_y) { // shift folded groups into the folding area (disappears when completely inside)
124                    frame_y1  = IRS.min_y;
125                    IRS.min_y += IRS.halfstep_y+IRS.gap;
126                }
127
128                AW_pos    visible_frame_height = frame_y2-frame_y1;
129                Rectangle frame(Position(x_offset, frame_y1), Vector(frame_width, visible_frame_height));
130
131                // draw group frame (unclosed on right hand):
132                AW_click_cd cd(disp_device, (AW_CL)node, CL_NODE);
133
134                {
135                    const int gc = AWT_GC_IRS_GROUP_BOX;
136                    disp_device->set_line_attributes(gc, 1, AW_SOLID);
137                    disp_device->line(gc, frame.upper_edge());
138                    disp_device->line(gc, frame.left_edge());
139                    disp_device->line(gc, frame.lower_edge());
140                }
141
142                const int gc = node->gr.gc;
143                set_line_attributes_for(node);
144                filled_box(gc, frame.upper_left_corner(), TIP_BOX_SIZE);
145
146                Vector    frame2box(IRS.gap, IRS.gap);
147                Rectangle gbox(frame.upper_left_corner()+frame2box, Vector(frame.width()*.5, frame.height()-2*IRS.gap));
148
149                disp_device->set_grey_level(gc, group_greylevel);
150                disp_device->box(gc, AW::FillStyle::SHADED_WITH_BORDER, gbox);
151
152                Position box_rcenter = gbox.right_edge().centroid();
153
154                const GroupInfo& info = get_group_info(node, group_info_pos == GIP_SEPARATED ? GI_SEPARATED : GI_COMBINED, group_info_pos == GIP_OVERLAYED);
155                if (info.name) { //  a node name should be displayed
156                    disp_device->text(gc, info.name, box_rcenter+IRS.adjust_text, 0.0, AW_ALL_DEVICES_UNSCALED, info.name_len);
157                }
158                if (info.count) {
159                    Position box_lcenter = gbox.left_edge().centroid();
160                    disp_device->text(gc, info.count, box_lcenter+IRS.adjust_text, 0.0, AW_ALL_DEVICES_UNSCALED, info.count_len);
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        // -----------------------------------
180        //      otherwise: unfolded group
181
182        group_y1 = IRS.y;
183        if (group_y1 >= IRS.min_y) {
184            IRS.draw_top_separator_once(disp_device);
185            group_y1 = IRS.y + IRS.halfstep_y+IRS.gap;
186        }
187        else {
188            group_y1   = IRS.min_y;
189            IRS.min_y += IRS.openGroupExtra;
190        }
191        IRS.y += IRS.openGroupExtra;
192
193        const int   gc = AWT_GC_IRS_GROUP_BOX;
194        AW_click_cd cd(disp_device, (AW_CL)node, CL_NODE);
195        disp_device->set_line_attributes(gc, 1, AW_DOTTED);
196        disp_device->line(gc, x_offset-IRS.onePixel, group_y1, x_offset+frame_width, group_y1); // opened-group-frame
197
198        const GroupInfo& info = get_group_info(node, GI_COMBINED);
199
200        td_assert(info.name); // if fails -> maybe skip whole headerline
201        disp_device->text(node->gr.gc,
202                          info.name,
203                          x_offset-IRS.onePixel + IRS.gap,
204                          group_y1 + 2*IRS.adjust_text.y() + IRS.gap,
205                          0.0,
206                          AW_ALL_DEVICES_UNSCALED,
207                          info.name_len);
208    }
209
210    // draw subtrees
211    AW_pos left_x = x_offset + IRS.x_scale * node->leftlen;
212    AW_pos left_y = paint_irs_sub_tree(node->get_leftson(), left_x);
213
214    AW_pos right_x = x_offset + IRS.x_scale * node->rightlen;
215    AW_pos right_y = paint_irs_sub_tree(node->get_rightson(), right_x);
216
217    if (node->is_named_group()) IRS.group_closed++;
218
219    // draw structure
220    if (left_y > IRS.min_y) {
221        if (left_y < IRS.max_y) { // clip y on top border
222            AW_click_cd cd(disp_device, (AW_CL)node->leftson, CL_NODE);
223            Position    left(left_x, left_y);
224            if (node->leftson->get_remark()) {
225                TREE_show_branch_remark(disp_device, node->leftson->get_remark(), node->leftson->is_leaf, left, 1, remark_text_filter, bootstrap_min);
226            }
227            set_line_attributes_for(node->get_leftson());
228            draw_branch_line(node->get_leftson()->gr.gc, Position(x_offset, left_y), left, line_filter);
229        }
230    }
231    else {
232        left_y = IRS.min_y;
233    }
234
235    AW_pos y_center = (left_y + right_y)*0.5;
236
237    if (right_y > IRS.min_y && right_y < IRS.max_y) { // visible right branch in lower part of display
238        AW_click_cd cd(disp_device, (AW_CL)node->rightson, CL_NODE);
239        Position    right(right_x, right_y);
240        if (node->rightson->get_remark()) {
241            TREE_show_branch_remark(disp_device, node->rightson->get_remark(), node->rightson->is_leaf, right, 1, remark_text_filter, bootstrap_min);
242        }
243        set_line_attributes_for(node->get_rightson());
244        draw_branch_line(node->get_rightson()->gr.gc, Position(x_offset, right_y), right, line_filter);
245    }
246
247    AW_click_cd cd(disp_device, (AW_CL)node, CL_NODE);
248    set_line_attributes_for(node->get_leftson());
249    disp_device->line(node->get_leftson()->gr.gc, x_offset, y_center, x_offset, left_y);
250
251    set_line_attributes_for(node->get_rightson());
252    disp_device->line(node->get_rightson()->gr.gc, x_offset, y_center, x_offset, right_y);
253
254    if (node->is_named_group()) { // close unfolded group brackets and draw tipbox
255        IRS.+= IRS.halfstep_y+IRS.gap;
256
257        {
258            const int gc = AWT_GC_IRS_GROUP_BOX;
259            disp_device->set_line_attributes(gc, 1, AW_DOTTED);
260            disp_device->line(gc, x_offset-IRS.onePixel, IRS.y, x_offset+frame_width, IRS.y); // opened-group-frame
261            disp_device->line(gc, x_offset-IRS.onePixel, group_y1, x_offset-IRS.onePixel,  IRS.y); // opened-group-frame
262        }
263       
264        const int gc = node->gr.gc;
265        set_line_attributes_for(node);
266        filled_box(gc, Position(x_offset-IRS.onePixel, group_y1), TIP_BOX_SIZE);
267    }
268    return y_center;
269}
270
271void AWT_graphic_tree::show_irs_tree(AP_tree *at, double height) {
272
273    IRS.draw_separator = true;
274    IRS.y              = 0;
275    IRS.step_y         = height;
276    IRS.halfstep_y     = IRS.step_y*0.5;
277    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
278
279    const AW_font_limits& limits = disp_device->get_font_limits(AWT_GC_ALL_MARKED, 0);
280
281    IRS.adjust_text    = disp_device->rtransform(Vector(NT_BOX_WIDTH, limits.ascent*0.5));
282    IRS.onePixel       = disp_device->rtransform_size(1.0);
283    IRS.gap            = 3*IRS.onePixel;
284    IRS.group_closed   = 0;
285    IRS.tree_depth     = at->gr.max_tree_depth;
286    IRS.openGroupExtra = IRS.step_y+IRS.gap;
287    IRS.sep_filter     = AW_SCREEN|AW_PRINTER_CLIP;
288
289    IRS.is_size_device = disp_device->type() == AW_DEVICE_SIZE;
290
291    Position  corner = disp_device->rtransform(Origin);   // real world coordinates of left/upper screen corner
292    Rectangle rclip  = disp_device->get_rtransformed_cliprect();
293
294    // the following values currently contain nonsense for size device @@@
295    IRS.min_y   = corner.ypos();
296    IRS.max_y   = rclip.bottom();
297    IRS.fold_x1 = rclip.left();
298    IRS.fold_x2 = rclip.right();
299
300    list_tree_ruler_y           = paint_irs_sub_tree(at, 0);
301    irs_tree_ruler_scale_factor = IRS.x_scale;
302   
303    disp_device->invisible(corner); // @@@ remove when size-dev works
304}
Note: See TracBrowser for help on using the repository browser.