| 1 | #include <stdio.h> |
|---|
| 2 | |
|---|
| 3 | #include <math.h> |
|---|
| 4 | #include <string.h> |
|---|
| 5 | #include <arbdb.h> |
|---|
| 6 | #include <arbdbt.h> |
|---|
| 7 | #include <aw_root.hxx> |
|---|
| 8 | #include <aw_device.hxx> |
|---|
| 9 | #include <aw_window.hxx> |
|---|
| 10 | |
|---|
| 11 | #include <awt_canvas.hxx> |
|---|
| 12 | #include <awt_nds.hxx> |
|---|
| 13 | #include "awt_tree.hxx" |
|---|
| 14 | #include "awt_dtree.hxx" |
|---|
| 15 | #include "awt_irstree.hxx" |
|---|
| 16 | #include <aw_awars.hxx> |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | /* *********************** paint sub tree ************************ */ |
|---|
| 20 | /* *********************** paint sub tree ************************ */ |
|---|
| 21 | /* *********************** paint sub tree ************************ */ |
|---|
| 22 | #define IS_HIDDEN(node) (type == AWT_IRS_HIDDEN_TREE && node->gr.gc>0) |
|---|
| 23 | |
|---|
| 24 | const int MAXSHOWNNODES = 5000; // Something like max screen height/minimum font size |
|---|
| 25 | const int tipBoxSize = 4; |
|---|
| 26 | const int nodeBoxWidth = 5; |
|---|
| 27 | |
|---|
| 28 | static struct { |
|---|
| 29 | GB_BOOL ftrst_species; |
|---|
| 30 | int y; |
|---|
| 31 | int min_y; |
|---|
| 32 | int max_y; |
|---|
| 33 | int min_x; |
|---|
| 34 | int max_x; |
|---|
| 35 | int step_y; |
|---|
| 36 | double x_scale; |
|---|
| 37 | AW_device *device; |
|---|
| 38 | int nodes_xpos[MAXSHOWNNODES]; // needed for Query results drawing |
|---|
| 39 | int nodes_ypos[MAXSHOWNNODES]; |
|---|
| 40 | AP_tree *nodes_id[MAXSHOWNNODES]; |
|---|
| 41 | int nodes_ntip; // counts the tips stored in nodes_xx |
|---|
| 42 | int nodes_nnnodes; // counts the inner nodes (reverse counter !!!) |
|---|
| 43 | int font_height_2; |
|---|
| 44 | enum IRS_PRUNE_LEVEL pruneLevel; |
|---|
| 45 | int is_size_device; |
|---|
| 46 | } irs_gl; |
|---|
| 47 | |
|---|
| 48 | void draw_top_seperator(){ |
|---|
| 49 | int gc = AWT_GC_GROUPS; |
|---|
| 50 | int y; |
|---|
| 51 | irs_gl.ftrst_species = GB_FALSE; |
|---|
| 52 | if (!irs_gl.is_size_device){ |
|---|
| 53 | for (y = irs_gl.min_y; y< irs_gl.min_y+4;y++){ |
|---|
| 54 | irs_gl.device->line(gc,-10000,y,10000,y,-1,(AW_CL)0,(AW_CL)0); |
|---|
| 55 | } |
|---|
| 56 | } |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | int AWT_graphic_tree::paint_sub_tree(AP_tree *node, int x_offset, int type){ |
|---|
| 60 | |
|---|
| 61 | int left_y; |
|---|
| 62 | int left_x; |
|---|
| 63 | int right_y; |
|---|
| 64 | int right_x; |
|---|
| 65 | |
|---|
| 66 | |
|---|
| 67 | /* *********************** Check clipping rectangle ************************ */ |
|---|
| 68 | if (!irs_gl.is_size_device){ |
|---|
| 69 | if (irs_gl.y > irs_gl.max_y){ |
|---|
| 70 | return irs_gl.max_y; |
|---|
| 71 | } |
|---|
| 72 | int height_of_subtree = irs_gl.step_y*node->gr.view_sum; |
|---|
| 73 | if (irs_gl.y + height_of_subtree < irs_gl.min_y) { |
|---|
| 74 | irs_gl.y+= height_of_subtree; |
|---|
| 75 | return irs_gl.min_y; |
|---|
| 76 | } |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | |
|---|
| 81 | /* *********************** i'm a leaf ************************ */ |
|---|
| 82 | if (node->is_leaf) { |
|---|
| 83 | irs_gl.y+=irs_gl.step_y; |
|---|
| 84 | if (irs_gl.ftrst_species) { |
|---|
| 85 | draw_top_seperator(); |
|---|
| 86 | } |
|---|
| 87 | int x = x_offset; |
|---|
| 88 | int y = irs_gl.y + irs_gl.font_height_2; |
|---|
| 89 | int gc = node->gr.gc; |
|---|
| 90 | |
|---|
| 91 | |
|---|
| 92 | |
|---|
| 93 | if (node->name && node->name[0] == this->species_name[0] && |
|---|
| 94 | !strcmp(node->name,this->species_name)) { |
|---|
| 95 | x_cursor = x; y_cursor = irs_gl.y; |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | const char *str = 0; |
|---|
| 99 | if (!irs_gl.is_size_device){ |
|---|
| 100 | if (node->gb_node && GB_read_flag(node->gb_node)){ |
|---|
| 101 | NT_scalebox(gc,x, irs_gl.y, (int)NT_BOX_WIDTH); |
|---|
| 102 | } |
|---|
| 103 | str = make_node_text_nds(gb_main,node->gb_node,0,node->get_gbt_tree()); |
|---|
| 104 | irs_gl.device->text(gc,str, x, y,0.0,-1, (AW_CL)node,0); |
|---|
| 105 | } |
|---|
| 106 | return irs_gl.y; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | /* *********************** i'm a grouped subtree ************************ */ |
|---|
| 110 | int last_y = irs_gl.y; |
|---|
| 111 | const char *node_string = 0; |
|---|
| 112 | if (node->gb_node){ |
|---|
| 113 | if (!irs_gl.is_size_device){ |
|---|
| 114 | node_string = make_node_text_nds(gb_main,node->gb_node,0,node->get_gbt_tree()); |
|---|
| 115 | }else{ |
|---|
| 116 | node_string = "0123456789"; |
|---|
| 117 | } |
|---|
| 118 | } |
|---|
| 119 | if (node->gr.grouped) { // no recursion here just a group symbol !!! |
|---|
| 120 | int vsize = node->gr.view_sum * irs_gl.step_y; |
|---|
| 121 | int y_center = irs_gl.y + (vsize>>1) + irs_gl.step_y; |
|---|
| 122 | if ( irs_gl.y >= irs_gl.min_y) { |
|---|
| 123 | if (irs_gl.ftrst_species) { // A name of a group just under the seperator |
|---|
| 124 | draw_top_seperator(); |
|---|
| 125 | } |
|---|
| 126 | int topy = irs_gl.y+irs_gl.step_y - 2; |
|---|
| 127 | int boty = irs_gl.y+irs_gl.step_y+ vsize + 2; |
|---|
| 128 | int rx = x_offset + vsize + vsize; |
|---|
| 129 | int gc = AWT_GC_GROUPS; |
|---|
| 130 | irs_gl.device->line(gc,x_offset, topy, rx, topy, -1,(AW_CL)node,0); |
|---|
| 131 | |
|---|
| 132 | irs_gl.device->box(node->gr.gc,x_offset - (tipBoxSize>>1), topy - (tipBoxSize>>1), |
|---|
| 133 | tipBoxSize, tipBoxSize, -1, (AW_CL)node,0); |
|---|
| 134 | |
|---|
| 135 | irs_gl.device->line(gc,x_offset, topy, x_offset, boty, -1, (AW_CL)node,0); |
|---|
| 136 | irs_gl.device->line(gc,x_offset, boty, rx, boty, -1, (AW_CL)node,0); |
|---|
| 137 | |
|---|
| 138 | irs_gl.device->box(node->gr.gc,x_offset+2,irs_gl.y+irs_gl.step_y,vsize,vsize, -1,(AW_CL)node,0); |
|---|
| 139 | |
|---|
| 140 | irs_gl.y += vsize + 2*irs_gl.step_y ; |
|---|
| 141 | if (node_string) { |
|---|
| 142 | const char *s = GBS_global_string("%s (%i:%i)",node_string,node->gr.leave_sum,0); |
|---|
| 143 | irs_gl.device->text(node->gr.gc,s,x_offset + vsize + 10 + nodeBoxWidth, |
|---|
| 144 | y_center + (irs_gl.step_y>>1),0.0, // A node name should be displayed |
|---|
| 145 | -1, (AW_CL)node, 0); |
|---|
| 146 | } |
|---|
| 147 | }else{ |
|---|
| 148 | irs_gl.y+= vsize; |
|---|
| 149 | y_center = irs_gl.min_y; |
|---|
| 150 | if ( irs_gl.y > irs_gl.min_y) { |
|---|
| 151 | irs_gl.y = irs_gl.min_y; |
|---|
| 152 | } |
|---|
| 153 | } |
|---|
| 154 | return y_center; |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | if ( irs_gl.pruneLevel != IRS_NOPRUNE ){ |
|---|
| 158 | node_string = 0; |
|---|
| 159 | } |
|---|
| 160 | |
|---|
| 161 | /* *********************** i'm a labeled node ************************ */ |
|---|
| 162 | /* If I have only one child + pruneLevel != MAXPRUNE -> no labeling */ |
|---|
| 163 | |
|---|
| 164 | if (node_string != NULL) { // A node name should be displayed |
|---|
| 165 | if (last_y >= irs_gl.min_y) { |
|---|
| 166 | if (irs_gl.ftrst_species) { // A name of a group just under the seperator |
|---|
| 167 | draw_top_seperator(); |
|---|
| 168 | } |
|---|
| 169 | last_y = irs_gl.y + irs_gl.step_y; |
|---|
| 170 | }else{ |
|---|
| 171 | last_y = irs_gl.min_y; |
|---|
| 172 | irs_gl.min_y += int(irs_gl.step_y * 1.8); |
|---|
| 173 | } |
|---|
| 174 | irs_gl.y+=int(irs_gl.step_y * 1.8); |
|---|
| 175 | int gc = AWT_GC_GROUPS; |
|---|
| 176 | irs_gl.device->line(gc,x_offset,last_y, x_offset+400, last_y, -1, (AW_CL)node,0); |
|---|
| 177 | |
|---|
| 178 | irs_gl.device->box(node->gr.gc,x_offset- (tipBoxSize>>1), last_y- (tipBoxSize>>1), |
|---|
| 179 | tipBoxSize,tipBoxSize, |
|---|
| 180 | -1, (AW_CL)node,0); |
|---|
| 181 | const char *s = GBS_global_string("%s (%i:%i)",node_string,node->gr.leave_sum,0); |
|---|
| 182 | irs_gl.device->text(node->gr.gc,s, x_offset + 10 + nodeBoxWidth, last_y + irs_gl.step_y + 1,0.0, |
|---|
| 183 | -1, (AW_CL)node,0); |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | /* *********************** connect two nodes == draw branches ************************ */ |
|---|
| 187 | int y_center; |
|---|
| 188 | left_x = (int)(x_offset + 0.9 + irs_gl.x_scale * node->leftlen); |
|---|
| 189 | left_y = paint_sub_tree(node->leftson, left_x, type); |
|---|
| 190 | |
|---|
| 191 | right_x = int(x_offset + 0.9 + irs_gl.x_scale * node->rightlen); |
|---|
| 192 | right_y = paint_sub_tree(node->rightson, right_x, type); |
|---|
| 193 | |
|---|
| 194 | |
|---|
| 195 | /* *********************** draw structure ************************ */ |
|---|
| 196 | |
|---|
| 197 | if (left_y > irs_gl.min_y){ |
|---|
| 198 | if (left_y < irs_gl.max_y){ // clip y on top border |
|---|
| 199 | if (node->leftson->remark_branch ) { |
|---|
| 200 | disp_device->text(AWT_GC_BRANCH_REMARK, node->leftson->remark_branch , |
|---|
| 201 | (AW_pos) left_x,(AW_pos) left_y, |
|---|
| 202 | (AW_pos) 1 , text_filter, |
|---|
| 203 | (AW_CL) node->leftson , (AW_CL) 0 ); |
|---|
| 204 | } |
|---|
| 205 | irs_gl.device->line(node->gr.gc,x_offset,left_y, left_x, left_y, -1, (AW_CL)node->leftson,0); |
|---|
| 206 | } |
|---|
| 207 | }else{ |
|---|
| 208 | left_y = irs_gl.min_y; |
|---|
| 209 | } |
|---|
| 210 | |
|---|
| 211 | y_center = (left_y + right_y) / 2; // clip conter on bottom border |
|---|
| 212 | if (right_y > irs_gl.min_y && right_y < irs_gl.max_y) { |
|---|
| 213 | if (node->rightson->remark_branch ) { |
|---|
| 214 | disp_device->text(AWT_GC_BRANCH_REMARK, node->rightson->remark_branch , |
|---|
| 215 | (AW_pos) right_x,(AW_pos) right_y, |
|---|
| 216 | (AW_pos) 1 , text_filter, |
|---|
| 217 | (AW_CL) node->rightson , (AW_CL) 0 ); |
|---|
| 218 | } |
|---|
| 219 | irs_gl.device->line(node->gr.gc,x_offset,right_y, right_x, right_y, -1, (AW_CL)node->rightson,0); |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | irs_gl.device->line(node->gr.gc,x_offset,left_y,x_offset, right_y, -1, (AW_CL)node,0); |
|---|
| 223 | |
|---|
| 224 | if (node_string != 0) { // A node name should be displayed |
|---|
| 225 | irs_gl.y+=irs_gl.step_y /2; |
|---|
| 226 | int gc = AWT_GC_GROUPS; |
|---|
| 227 | irs_gl.device->line(gc,x_offset-1,irs_gl.y, x_offset+400, irs_gl.y, -1,(AW_CL)node,0); |
|---|
| 228 | irs_gl.device->line(gc,x_offset-1,last_y, x_offset-1, irs_gl.y, -1,(AW_CL)node,0); |
|---|
| 229 | } |
|---|
| 230 | if (0 && !irs_gl.is_size_device){ |
|---|
| 231 | if (irs_gl.nodes_nnnodes>irs_gl.nodes_ntip+1){ |
|---|
| 232 | irs_gl.nodes_nnnodes--; |
|---|
| 233 | irs_gl.nodes_xpos[irs_gl.nodes_nnnodes] = x_offset; |
|---|
| 234 | irs_gl.nodes_ypos[irs_gl.nodes_nnnodes] = y_center; |
|---|
| 235 | irs_gl.nodes_id[irs_gl.nodes_nnnodes] = node; |
|---|
| 236 | } |
|---|
| 237 | } |
|---|
| 238 | return y_center; |
|---|
| 239 | } |
|---|
| 240 | |
|---|
| 241 | int AWT_graphic_tree::draw_slot(int x_offset, GB_BOOL draw_at_tips){ |
|---|
| 242 | int maxx = x_offset; |
|---|
| 243 | int i; |
|---|
| 244 | int no_compress = 0; |
|---|
| 245 | if (!draw_at_tips) no_compress = 1; |
|---|
| 246 | for (i=0;i<irs_gl.nodes_ntip;i++){ |
|---|
| 247 | AP_tree *tip = irs_gl.nodes_id[i]; |
|---|
| 248 | const char *str = make_node_text_nds(gb_main,tip->gb_node,no_compress,tip->get_gbt_tree()); |
|---|
| 249 | int len = irs_gl.device->get_string_size(tip->gr.gc,str,0); |
|---|
| 250 | int x = 0; |
|---|
| 251 | int y = irs_gl.nodes_ypos[i]+ irs_gl.font_height_2; |
|---|
| 252 | if (draw_at_tips) { |
|---|
| 253 | x = x_offset + irs_gl.nodes_xpos[i]; |
|---|
| 254 | }else{ |
|---|
| 255 | irs_gl.device->text(tip->gr.gc,str,x,irs_gl.nodes_ypos[i],0,-1,(AW_CL)tip,0); |
|---|
| 256 | } |
|---|
| 257 | if (x + len > maxx) maxx = x+len; |
|---|
| 258 | irs_gl.device->text(tip->gr.gc,str, x, y,0.0,-1, (AW_CL)tip,0); |
|---|
| 259 | } |
|---|
| 260 | return maxx; |
|---|
| 261 | } |
|---|
| 262 | |
|---|
| 263 | |
|---|
| 264 | void AWT_graphic_tree::show_irs(AP_tree *at,AW_device *device, int height){ |
|---|
| 265 | device->push_clip_scale(); |
|---|
| 266 | int x; |
|---|
| 267 | int y; |
|---|
| 268 | AW_font_information *font_info = device->get_font_information(AWT_GC_SELECTED,0); |
|---|
| 269 | device->rtransform(0,0,x,y); // berechne reale Welkoordinaten des linken oberen Bildschirmrands |
|---|
| 270 | int clipped_l,clipped_t; |
|---|
| 271 | int clipped_r,clipped_b; |
|---|
| 272 | device->rtransform(device->clip_rect.l,device->clip_rect.t,clipped_l,clipped_t); |
|---|
| 273 | device->rtransform(device->clip_rect.r,device->clip_rect.b,clipped_r,clipped_b); |
|---|
| 274 | |
|---|
| 275 | irs_gl.nodes_nnnodes = MAXSHOWNNODES; |
|---|
| 276 | irs_gl.nodes_ntip = 0; |
|---|
| 277 | irs_gl.font_height_2 = font_info->max_letter_ascent/2; |
|---|
| 278 | irs_gl.device = device; |
|---|
| 279 | irs_gl.ftrst_species = GB_TRUE; |
|---|
| 280 | irs_gl.y = 0; |
|---|
| 281 | irs_gl.min_x = x; |
|---|
| 282 | irs_gl.max_x = 100; |
|---|
| 283 | irs_gl.min_y = y; |
|---|
| 284 | irs_gl.max_y = clipped_b; |
|---|
| 285 | irs_gl.step_y = height; |
|---|
| 286 | irs_gl.x_scale = 600.0 / at->gr.tree_depth; |
|---|
| 287 | irs_gl.is_size_device = 0; |
|---|
| 288 | if (irs_gl.device->type() == AW_DEVICE_SIZE){ |
|---|
| 289 | irs_gl.is_size_device = 1; |
|---|
| 290 | } |
|---|
| 291 | |
|---|
| 292 | this->paint_sub_tree(at,0,AWT_IRS_NORMAL_TREE ); |
|---|
| 293 | if (irs_gl.is_size_device){ |
|---|
| 294 | irs_gl.device->invisible(0,irs_gl.min_x,irs_gl.y + (irs_gl.min_y-y) + 200,-1,0,0); |
|---|
| 295 | } |
|---|
| 296 | device->pop_clip_scale(); |
|---|
| 297 | } |
|---|