10
#include <aw_root.hxx>
11
#include <aw_device.hxx>
12
#include <aw_keysym.hxx>
13
#include <aw_window.hxx>
15
#include <awt_canvas.hxx>
16
#include <awt_nds.hxx>
17
#include <aw_preset.hxx>
18
#include <aw_awars.hxx>
20
#include "awt_tree.hxx"
21
#include "awt_dtree.hxx"
22
#include "awt_attributes.hxx"
24
/***************************
26
****************************/
30
AW_gc_manager AWT_graphic_tree::init_devices(AW_window *aww, AW_device *device, AWT_canvas* ntw, AW_CL cd2)
32
AW_gc_manager preset_window =
33
AW_manage_GC(aww,device,AWT_GC_CURSOR, AWT_GC_MAX, AW_GCM_DATA_AREA,
34
(AW_CB)AWT_resize_cb, (AW_CL)ntw, cd2,
35
true, // define color groups
39
// Many gc indices are shared between ABR_NTREE and ARB_PARSIMONY
40
// e.g. the tree drawing routines use same gc's for drawing both trees
41
// (check PARS_dtree.cxx AWT_graphic_parsimony::init_devices)
44
"Branch remarks$#b6ffb6",
45
"+-Bootstrap$#53d3ff", "-B.(limited)$white",
46
"-GROUP_BRACKETS$#000",
48
"Some marked$#bb8833",
50
"Zombies etc.$#977a0e",
52
"+-No probe$black", "-Probes 1+2$yellow",
53
"+-Probe 1$red", "-Probes 1+3$magenta",
54
"+-Probe 2$green", "-Probes 2+3$cyan",
55
"+-Probe 3$blue", "-All probes$white",
61
AP_tree *AWT_graphic_tree::search(AP_tree *root, const char *name)
66
if (!strcmp(name,root->name)) {
71
AP_tree *result = this->search(root->leftson,name);
72
if (result) return result;
73
result = this->search(root->rightson,name);
74
if (result) return result;
79
void AWT_graphic_tree::jump(AP_tree *at, const char *name)
81
if (sort_is_list_style(tree_sort)) return;
85
if (tree_sort == AP_TREE_NORMAL) {
86
tree_root_display = tree_root;
94
tree_root_display = at;
98
void AWT_graphic_tree::mark_species_in_tree(AP_tree *at, int mark_mode) {
109
GB_transaction dummy(tree_static->gb_species_data);
111
if(at->gb_node) { // not a zombie
113
case 0: GB_write_flag(at->gb_node, 0); break;
114
case 1: GB_write_flag(at->gb_node, 1); break;
115
case 2: GB_write_flag(at->gb_node, !GB_read_flag(at->gb_node)); break;
116
default : awt_assert(0);
121
mark_species_in_tree(at->leftson, mark_mode);
122
mark_species_in_tree(at->rightson, mark_mode);
125
void AWT_graphic_tree::mark_species_in_tree_that(AP_tree *at, int mark_mode, int (*condition)(GBDATA*, void*), void *cd) {
133
marks are only changed for those species for that condition() != 0
138
GB_transaction dummy(tree_static->gb_species_data);
140
if(at->gb_node) { // not a zombie
141
int oldMark = GB_read_flag(at->gb_node);
142
if (oldMark != mark_mode && condition(at->gb_node, cd)) {
144
case 0: GB_write_flag(at->gb_node, 0); break;
145
case 1: GB_write_flag(at->gb_node, 1); break;
146
case 2: GB_write_flag(at->gb_node, !oldMark); break;
147
default : awt_assert(0);
153
mark_species_in_tree_that(at->leftson, mark_mode, condition, cd);
154
mark_species_in_tree_that(at->rightson, mark_mode, condition, cd);
158
// same as mark_species_in_tree but works on rest of tree
159
void AWT_graphic_tree::mark_species_in_rest_of_tree(AP_tree *at, int mark_mode) {
162
AP_tree *pa = at->father;
165
GB_transaction dummy(tree_static->gb_species_data);
167
if (at == pa->leftson) mark_species_in_tree(pa->rightson, mark_mode);
168
else mark_species_in_tree(pa->leftson, mark_mode);
170
mark_species_in_rest_of_tree(pa, mark_mode);
173
// same as mark_species_in_tree_that but works on rest of tree
174
void AWT_graphic_tree::mark_species_in_rest_of_tree_that(AP_tree *at, int mark_mode, int (*condition)(GBDATA*, void*), void *cd) {
177
AP_tree *pa = at->father;
180
GB_transaction dummy(tree_static->gb_species_data);
182
if (at == pa->leftson) mark_species_in_tree_that(pa->rightson, mark_mode, condition, cd);
183
else mark_species_in_tree_that(pa->leftson, mark_mode, condition, cd);
185
mark_species_in_rest_of_tree_that(pa, mark_mode, condition, cd);
188
bool AWT_graphic_tree::tree_has_marks(AP_tree *at) {
189
if (!at) return false;
192
if (!at->gb_node) return false; // zombie
193
int marked = GB_read_flag(at->gb_node);
197
return tree_has_marks(at->leftson) || tree_has_marks(at->rightson);
200
bool AWT_graphic_tree::rest_tree_has_marks(AP_tree *at) {
201
if (!at) return false;
203
AP_tree *pa = at->father;
204
if (!pa) return false;
206
if (at == pa->leftson) { // i am the left son
207
return tree_has_marks(pa->rightson) || rest_tree_has_marks(pa);
209
return tree_has_marks(pa->leftson) || rest_tree_has_marks(pa);
212
struct AWT_graphic_tree_group_state {
214
int closed_terminal, opened_terminal;
215
int closed_with_marked, opened_with_marked;
216
int marked_in_groups, marked_outside_groups;
223
closed_with_marked = 0;
224
opened_with_marked = 0;
225
marked_in_groups = 0;
226
marked_outside_groups = 0;
229
AWT_graphic_tree_group_state() { clear(); }
231
bool has_groups() const { return closed+opened; }
232
int marked() const { return marked_in_groups+marked_outside_groups; }
234
bool all_opened() const { return closed == 0 && opened>0; }
235
bool all_closed() const { return opened == 0 && closed>0; }
236
bool all_terminal_closed() const { return opened_terminal == 0 && closed_terminal == closed; }
237
bool all_marked_opened() const { return marked_in_groups > 0 && closed_with_marked == 0; }
239
int next_expand_mode() const {
240
if (closed_with_marked) return 1; // expand marked
241
return 4; // expand all
244
int next_collapse_mode() const {
245
if (all_terminal_closed()) return 0; // collapse all
246
return 2; // group terminal
249
int next_group_mode() const {
250
if (all_terminal_closed()) {
251
if (marked_in_groups && !all_marked_opened()) return 1; // all but marked
252
return 4; // expand all
254
if (all_marked_opened()) {
255
if (all_opened()) return 0; // collapse all
256
return 4; // expand all
258
if (all_opened()) return 0; // collapse all
259
if (!all_closed()) return 0; // collapse all
261
if (!all_terminal_closed()) return 2; // group terminal
262
if (marked_in_groups) return 1; // all but marked
263
return 4; // expand all
267
printf("closed=%i opened=%i\n", closed, opened);
268
printf("closed_terminal=%i opened_terminal=%i\n", closed_terminal, opened_terminal);
269
printf("closed_with_marked=%i opened_with_marked=%i\n", closed_with_marked, opened_with_marked);
270
printf("marked_in_groups=%i marked_outside_groups=%i\n", marked_in_groups, marked_outside_groups);
272
printf("all_opened=%i all_closed=%i all_terminal_closed=%i all_marked_opened=%i\n",
273
all_opened(), all_closed(), all_terminal_closed(), all_marked_opened());
277
// start of implementation of class AWT_graphic_tree_group_state:
279
// -end- of implementation of class AWT_graphic_tree_group_state.
281
void AWT_graphic_tree::detect_group_state(AP_tree *at, AWT_graphic_tree_group_state *state, AP_tree *skip_this_son) {
284
if (at->gb_node && GB_read_flag(at->gb_node)) state->marked_outside_groups++; // count marks
285
return; // leave are never grouped
288
if (at->gb_node) { // i am a group
289
AWT_graphic_tree_group_state sub_state;
290
if (at->leftson != skip_this_son) detect_group_state(at->leftson, &sub_state, skip_this_son);
291
if (at->rightson != skip_this_son) detect_group_state(at->rightson, &sub_state, skip_this_son);
293
if (at->gr.grouped) { // a closed group
295
if (!sub_state.has_groups()) state->closed_terminal++;
296
if (sub_state.marked()) state->closed_with_marked++;
297
state->closed += sub_state.opened;
299
else { // an open group
301
if (!sub_state.has_groups()) state->opened_terminal++;
302
if (sub_state.marked()) state->opened_with_marked++;
303
state->opened += sub_state.opened;
306
state->marked_in_groups += sub_state.marked();
308
state->closed += sub_state.closed;
309
state->opened_terminal += sub_state.opened_terminal;
310
state->closed_terminal += sub_state.closed_terminal;
311
state->opened_with_marked += sub_state.opened_with_marked;
312
state->closed_with_marked += sub_state.closed_with_marked;
314
else { // not a group
315
if (at->leftson != skip_this_son) detect_group_state(at->leftson, state, skip_this_son);
316
if (at->rightson != skip_this_son) detect_group_state(at->rightson, state, skip_this_son);
320
int AWT_graphic_tree::group_rest_tree(AP_tree *at, int mode, int color_group) {
323
AP_tree *pa = at->father;
326
if (at == pa->leftson) { // i am the left son
327
group_tree(pa->rightson, mode, color_group);
330
group_tree(pa->leftson, mode, color_group);
333
group_rest_tree(pa, mode, color_group);
334
return 1; // non-rest is always ungrouped
337
int AWT_graphic_tree::group_tree(AP_tree *at, int mode, int color_group) // run on father !!!
344
2 all but groups with subgroups
345
4 none (ungroups all)
346
8 all but color_group
352
GB_transaction dummy(this->tree_static->gb_species_data);
357
if (mode & 4) ungroup_me = 1;
358
if (at->gb_node) { // not a zombie
359
if (!ungroup_me && (mode & 1)) { // do not group marked
360
if (GB_read_flag(at->gb_node)) { // i am a marked species
364
if (!ungroup_me && (mode & 8)) { // do not group one color_group
365
int my_color_group = AW_find_color_group(at->gb_node, true);
366
if (my_color_group == color_group) { // i am of that color group
375
int flag = this->group_tree(at->leftson, mode, color_group);
376
flag += this->group_tree(at->rightson, mode, color_group);
380
if (!flag) { // no son requests to be shown
381
if (at->gb_node) { // i am a group
382
GBDATA *gn = GB_entry(at->gb_node, "group_name");
384
if (strlen(GB_read_char_pntr(gn))>0){ // and I have a name
386
if (mode & 2) flag = 1; // do not group non-terminal groups
391
if (!at->father) this->tree_root->compute_tree(this->tree_static->gb_species_data);
398
int AWT_graphic_tree::resort_tree( int mode, struct AP_tree *at ) // run on father !!!
405
3 center (to bottom; don't use this - it's used internal)
407
post-condition: leafname contains alphabetically "smallest" name of subtree
410
static const char *leafname;
413
GB_transaction dummy(this->gb_main);
414
at = this->tree_root;
416
at->arb_tree_set_leafsum_viewsum();
418
this->resort_tree(mode,at);
419
at->compute_tree(this->gb_main);
427
int leftsize = at->leftson->gr.leave_sum;
428
int rightsize = at->rightson->gr.leave_sum;
430
if ( (mode &1) == 0 ) { // to top
431
if (rightsize >leftsize ) {
435
if (rightsize < leftsize ) {
442
if ( (mode & 2) == 2){
447
resort_tree(lmode,at->leftson);
449
const char *leftleafname = leafname;
451
resort_tree(rmode,at->rightson);
453
const char *rightleafname = leafname;
455
gb_assert(leftleafname && rightleafname);
457
if (leftleafname && rightleafname) {
458
int name_cmp = strcmp(leftleafname,rightleafname);
459
if (name_cmp<0) { // leftleafname < rightleafname
460
leafname = leftleafname;
461
} else { // (name_cmp>=0) aka: rightleafname <= leftleafname
462
leafname = rightleafname;
463
if (rightsize==leftsize && name_cmp>0) { // if sizes of subtrees are equal and rightleafname<leftleafname -> swap branches
468
if (leftleafname) leafname = leftleafname;
469
else leafname = rightleafname;
476
void AWT_graphic_tree::rot_show_line(AW_device *device)
480
sx = (this->old_rot_cl.x0+this->old_rot_cl.x1)*.5;
481
sy = (this->old_rot_cl.y0+this->old_rot_cl.y1)*.5;
482
x = this->rot_cl.x0 * (1.0-this->rot_cl.length) + this->rot_cl.x1 * this->rot_cl.length;
483
y = this->rot_cl.y0 * (1.0-this->rot_cl.length) + this->rot_cl.y1 * this->rot_cl.length;
484
int gc = this->drag_gc;
485
device->line(gc, sx, sy, x, y, AWT_F_ALL, 0, 0);
488
void AWT_graphic_tree::rot_show_triangle(AW_device *device)
493
double x1, y1, x2, y2;
497
if (tree_sort == AP_TREE_IRS) scale = irs_tree_ruler_scale_factor;
501
if (!at || !at->father)
504
sx = this->old_rot_cl.x0;
505
sy = this->old_rot_cl.y0;
507
if (at == at->father->leftson) len = at->father->leftlen;
508
else len = at->father->rightlen;
512
w = this->rot_orientation; x1 = this->old_rot_cl.x0 + cos(w) * len;
513
y1 = this->old_rot_cl.y0 + sin(w) * len;
515
int gc = this->drag_gc;
517
device->line(gc, sx, sy, x1, y1, AWT_F_ALL, 0, 0);
522
len = at->gr.tree_depth;
523
w = this->rot_orientation - this->rot_spread*.5*.5 + at->gr.right_angle;
524
x1 = sx + cos(w) * len;
525
y1 = sy + sin(w) * len;
526
w = this->rot_orientation + this->rot_spread*.5*.5 + at->gr.left_angle;
527
x2 = sx + cos(w) * len;
528
y2 = sy + sin(w) * len;
530
device->line(gc, sx, sy, x1, y1, AWT_F_ALL, 0, 0);
531
device->line(gc, sx, sy, x2, y2, AWT_F_ALL, 0, 0);
532
device->line(gc, x2, y2, x1, y1, AWT_F_ALL, 0, 0);
538
void AWT_show_bootstrap_circle(AW_device *device, const char *bootstrap, double zoom_factor, double max_radius, double len, double x, double y, bool elipsoid, double elip_ysize, int filter, AW_CL cd1,AW_CL cd2){
539
double radius = .01 * atoi(bootstrap); // bootstrap values are given in % (0..100)
540
if (radius < .1) radius = .1;
542
radius = 1.0 / sqrt(radius); // -> bootstrap->radius : 100% -> 1, 0% -> inf
543
radius -= 1.0; // -> bootstrap->radius : 100% -> 0, 0% -> inf
544
radius *= 2; // diameter ?
546
if (radius < 0) return; // skip too small circles
548
// Note : radius goes against infinite, if bootstrap values go against zero
549
// For this reason we do some limitaion here:
551
// printf("bootstrap=%i -> radius=%f\n", atoi(bootstrap), radius);
554
// #define BOOTSTRAP_RADIUS_LIMIT (len*2)
555
// #define BOOTSTRAP_RADIUS_LIMIT 2.0
556
#define BOOTSTRAP_RADIUS_LIMIT max_radius
558
int gc = AWT_GC_BOOTSTRAP;
560
if (radius > BOOTSTRAP_RADIUS_LIMIT) {
561
radius = BOOTSTRAP_RADIUS_LIMIT;
562
gc = AWT_GC_BOOTSTRAP_LIMITED;
565
double radiusx = radius * len * zoom_factor; // multiply with length of branch (and zoomfactor)
568
radiusy = elip_ysize * zoom_factor;
569
if (radiusy > radiusx) radiusy = radiusx;
575
device->circle(gc, false, x, y, radiusx, radiusy, filter, cd1, (AW_CL)cd2);
578
double comp_rot_orientation(AW_clicked_line *cl)
580
return atan2(cl->y1 - cl->y0, cl->x1 - cl->x0);
583
double comp_rot_spread(AP_tree *at, AWT_graphic_tree *ntw)
592
for(bt=at; bt->father && (bt!=ntw->tree_root_display); bt=bt->father){
597
zw *= (double)at->gr.view_sum / (double)bt->gr.view_sum;
599
switch (ntw->tree_sort) {
604
zw *= 0.5*M_PI * ntw->get_irs_tree_ruler_scale_factor();
616
void reset_spread(AP_tree *at)
620
reset_spread(at->leftson);
621
reset_spread(at->rightson);
624
void reset_rotation(AP_tree *at)
627
at->gr.left_angle = 0.0;
628
at->gr.right_angle = 0.0;
629
reset_rotation(at->leftson);
630
reset_rotation(at->rightson);
633
void reset_line_width(AP_tree *at)
636
at->gr.left_linewidth = 0;
637
at->gr.right_linewidth = 0;
638
reset_line_width(at->leftson);
639
reset_line_width(at->rightson);
642
char *AWT_graphic_tree_root_changed(void *cd, AP_tree *old, AP_tree *newroot)
644
AWT_graphic_tree *agt = (AWT_graphic_tree*)cd;
645
if (agt->tree_root_display == old ||
646
agt->tree_root_display->is_son(old)) agt->tree_root_display = newroot;
647
if (agt->tree_root == old ||
648
agt->tree_root->is_son(old)) agt->tree_root = newroot;
651
char *AWT_graphic_tree_node_deleted(void *cd, AP_tree *old)
653
AWT_graphic_tree *agt = (AWT_graphic_tree*)cd;
654
if (agt->tree_root_display == old) agt->tree_root_display = agt->tree_root;
655
if (old == agt->tree_root) {
657
agt->tree_root_display = 0;
661
void AWT_graphic_tree::toggle_group(AP_tree * at)
663
GB_ERROR error = NULL;
665
if (at->gb_node) { // existing group
666
char *gname = GBT_read_string(at->gb_node, "group_name");
668
const char *msg = GBS_global_string("What to do with group '%s'?",gname);
670
switch (aw_question(msg, "Rename,Destroy,Cancel")) {
672
char *new_gname = aw_input("Rename group", "Change group name:", at->name);
674
freeset(at->name, new_gname);
675
error = GBT_write_string(at->gb_node, "group_name", new_gname);
683
error = GB_delete(at->gb_node);
695
error = create_group(at); // create new group
696
if (!error && at->name) at->gr.grouped = 1;
699
if (error) aw_message(error);
702
GB_ERROR AWT_graphic_tree::create_group(AP_tree * at) {
703
GB_ERROR error = NULL;
705
char *gname = aw_input("Enter Name of Group");
707
GBDATA *gb_mainT = GB_get_root(tree_static->gb_tree);
708
GB_transaction ta(gb_mainT);
711
at->gb_node = GB_create_container(this->tree_static->gb_tree, "node");
712
if (!at->gb_node) error = GB_await_error();
714
error = GBT_write_int(at->gb_node, "id", 0);
715
this->exports.save = !error;
720
GBDATA *gb_name = GB_search(at->gb_node, "group_name", GB_STRING);
721
if (!gb_name) error = GB_await_error();
723
error = GBT_write_group_name(gb_name, gname);
724
if (!error) at->name = gname;
727
error = ta.close(error);
730
else if (!at->gb_node) {
731
at->gb_node = GB_create_container(this->tree_static->gb_tree, "node");
733
if (!at->gb_node) error = GB_await_error();
735
error = GBT_write_int(at->gb_node, "id", 0);
736
this->exports.save = !error;
743
void AWT_graphic_tree::key_command(AWT_COMMAND_MODE /*cmd*/, AW_key_mod key_modifier, char key_char,
744
AW_pos /*x*/, AW_pos /*y*/, AW_clicked_line *cl, AW_clicked_text *ct)
746
bool update_timer = true;
747
bool calc_color = true;
751
bool compute = false;
753
if (key_modifier != AW_KEYMODE_NONE) return;
754
if (key_char == 0) return;
757
printf("key_char=%i (=%c)\n", int(key_char), key_char);
760
// ----------------------------------------
761
// commands independent of tree :
762
// ----------------------------------------
764
bool global_key = true;
766
case 9: { // Ctrl-i = invert all
767
GBT_mark_all(gb_main, 2);
770
case 13: { // Ctrl-m = mark/unmark all
771
int mark = GBT_first_marked_species(gb_main) == 0; // no species marked -> mark all
772
GBT_mark_all(gb_main, mark);
781
if (!global_key && tree_proto) {
784
const char *what = 0;
787
at = (AP_tree*)ct->client_data1;
788
what = (char*)ct->client_data2;
790
else if (cl->exists) {
791
at = (AP_tree*)cl->client_data1;
792
what = (char*)cl->client_data2;
796
printf("what='%s' at=%p\n", what, at);
799
if (what && strcmp(what, "species") == 0) {
800
GBDATA *gb_species = 0;
802
gb_species = (GBDATA *)ct->client_data1;
808
// ------------------------------------
809
// commands in species list :
810
// ------------------------------------
814
case 'm': { // i/m = mark/unmark species
815
GB_write_flag(gb_species, 1-GB_read_flag(gb_species));
818
case 'I': { // I = invert all but current;
819
int mark = GB_read_flag(gb_species);
820
GBT_mark_all(gb_main, 2);
821
GB_write_flag(gb_species, mark);
824
case 'M': { // M = mark/unmark all but current;
825
int mark = GB_read_flag(gb_species);
826
GB_write_flag(gb_species, 0); // unmark current
827
GBT_mark_all(gb_main, GBT_first_marked_species(gb_main) == 0);
828
GB_write_flag(gb_species, mark); // restore mark of current
835
// many commands work on whole tree if mouse does not point to subtree
839
// -------------------------------------
840
// command working with tree :
841
// -------------------------------------
845
case 'm': { // m = mark/unmark (sub)tree
846
mark_species_in_tree(at, !tree_has_marks(at));
849
case 'M': { // M = mark/unmark all but (sub)tree
850
mark_species_in_rest_of_tree(at, !rest_tree_has_marks(at));
854
case 'i': { // i = invert (sub)tree
855
mark_species_in_tree(at, 2);
858
case 'I': { // I = invert all but (sub)tree
859
mark_species_in_rest_of_tree(at, 2);
864
AWT_graphic_tree_group_state state;
865
detect_group_state(at, &state, 0);
867
if (!state.has_groups()) { // somewhere inside group
871
if (at->gb_node) break;
877
detect_group_state(at, &state, 0);
884
if (key_char == 'x') { // expand
885
next_group_mode = state.next_expand_mode();
888
if (state.all_closed()) goto do_parent;
889
next_group_mode = state.next_collapse_mode();
893
group_tree(at, next_group_mode, 0);
903
AP_tree *root_node = at;
904
while (root_node->father) root_node = root_node->father; // search father
906
awt_assert(root_node);
908
AWT_graphic_tree_group_state state;
909
detect_group_state(root_node, &state, at);
912
if (key_char == 'X') { // expand
913
next_group_mode = state.next_expand_mode();
916
next_group_mode = state.next_collapse_mode();
920
group_rest_tree(at, next_group_mode, 0);
935
update_timer = false;
939
if (compute && tree_root) {
940
tree_root->compute_tree(gb_main);
945
if (update_timer && tree_static) {
946
tree_static->update_timers(); // do not reload the tree
954
if (calc_color && tree_root) {
955
tree_root->calc_color();
963
inline double discrete_ruler_lenght(double analog_ruler_lenth, double min_length) {
964
double drl = int(analog_ruler_lenth*10+0.5)/10.0;
965
if (drl<min_length) {
971
void AWT_graphic_tree::command(AW_device *device, AWT_COMMAND_MODE cmd,
972
int button, AW_key_mod key_modifier, AW_key_code /*key_code*/, char key_char,
973
AW_event_type type, AW_pos x, AW_pos y,
974
AW_clicked_line *cl, AW_clicked_text *ct)
976
static int rot_drag_flag, bl_drag_flag;
978
if (type == AW_Keyboard_Press) {
979
return key_command(cmd, key_modifier, key_char, x, y, cl, ct);
983
if ( ct->exists && ct->client_data2 && !strcmp((char *) ct->client_data2, "species")){
984
// clicked on a species list :
985
GBDATA *gbd = (GBDATA *)ct->client_data1;
987
bool refresh = false;
990
case AWT_MODE_MARK: {
991
if (type == AW_Mouse_Press) {
994
GB_write_flag(gbd, 1);
999
GB_write_flag(gbd, 0);
1006
default : { // all other modes just select a species :
1012
if (select && type == AW_Mouse_Press) AD_map_viewer(gbd);
1013
if (refresh) this->exports.refresh = 1;
1018
if (!this->tree_static) return; // no tree -> no commands
1020
if ( (rot_ct.exists && (rot_ct.distance == 0) && (!rot_ct.client_data1) &&
1021
rot_ct.client_data2 && !strcmp((char *) rot_ct.client_data2, "ruler") ) ||
1022
(ct && ct->exists && (!ct->client_data1) &&
1023
ct->client_data2 && !strcmp((char *) ct->client_data2, "ruler")))
1025
const char *tree_awar;
1029
case AWT_MODE_SELECT:
1031
case AWT_MODE_SPREAD:
1033
case AWT_MODE_SETROOT:
1034
case AWT_MODE_LENGTH:
1035
case AWT_MODE_MOVE: // Move Ruler text
1037
case AW_Mouse_Press:
1039
rot_ct.textArea.moveTo(Position(x, y));
1041
case AW_Mouse_Drag: {
1042
double scale = device->get_scale();
1043
const Position &start = rot_ct.textArea.start();
1045
tree_awar = show_ruler(device, drag_gc);
1046
sprintf(awar,"ruler/%s/text_x", tree_awar);
1048
h = (x - start.xpos())/scale + *GBT_readOrCreate_float(tree_static->gb_tree, awar, 0.0);
1049
GBT_write_float(this->tree_static->gb_tree, awar, h);
1050
sprintf(awar,"ruler/%s/text_y", tree_awar);
1051
h = (y - start.ypos())/scale + *GBT_readOrCreate_float(tree_static->gb_tree, awar, 0.0);
1052
GBT_write_float(tree_static->gb_tree, awar, h);
1053
rot_ct.textArea.moveTo(Position(x, y));
1054
show_ruler(device, drag_gc);
1057
case AW_Mouse_Release:
1058
rot_ct.exists = false;
1069
if ((rot_cl.exists && (!rot_cl.client_data1) &&
1070
rot_cl.client_data2 && !strcmp((char *) rot_cl.client_data2, "ruler") ) ||
1071
(cl && cl->exists && (!cl->client_data1) &&
1072
cl->client_data2 && !strcmp((char *) cl->client_data2, "ruler")))
1074
const char *tree_awar;
1079
case AWT_MODE_SPREAD:
1081
case AWT_MODE_SETROOT:
1082
case AWT_MODE_MOVE: // Move Ruler
1084
case AW_Mouse_Press:
1090
tree_awar = show_ruler(device, this->drag_gc);
1091
sprintf(awar,"ruler/%s/ruler_x",tree_awar);
1092
h = (x - rot_cl.x0)/device->get_scale() + *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, 0.0);
1093
GBT_write_float(this->tree_static->gb_tree, awar, h);
1094
sprintf(awar,"ruler/%s/ruler_y",tree_awar);
1095
h = (y - rot_cl.y0)/device->get_scale() + *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, 0.0);
1096
GBT_write_float(this->tree_static->gb_tree, awar, h);
1100
show_ruler(device, this->drag_gc);
1102
case AW_Mouse_Release:
1103
rot_cl.exists = false;
1104
this->exports.resize = 1;
1112
case AWT_MODE_LENGTH:
1113
switch(type){ // resize Ruler
1114
case AW_Mouse_Press:
1117
if (button==AWT_M_RIGHT) { // if right mouse button is used -> adjust to 1 digit behind comma
1118
sprintf(awar,"ruler/size");
1119
tree_awar = show_ruler(device, this->drag_gc);
1120
double rulerSize = *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, 0.0);
1121
GBT_write_float(this->tree_static->gb_tree, awar, discrete_ruler_lenght(rulerSize, 0.1));
1122
tree_awar = show_ruler(device, this->drag_gc);
1125
case AW_Mouse_Drag: {
1126
sprintf(awar,"ruler/size");
1127
h = *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, 0.0);
1128
if (button == AWT_M_RIGHT) {
1129
GBT_write_float(this->tree_static->gb_tree, awar, discrete_ruler_lenght(h, 0.1));
1131
tree_awar = show_ruler(device, this->drag_gc);
1133
if (tree_sort == AP_TREE_IRS) {
1134
double scale = device->get_scale() * irs_tree_ruler_scale_factor;
1135
h += (rot_cl.x0 - x)/scale;
1138
h += (x - rot_cl.x0)/device->get_scale();
1140
if (h<0.01) h = 0.01;
1142
double h_rounded = h;
1143
if (button==AWT_M_RIGHT) { // if right mouse button is used -> adjust to 1 digit behind comma
1144
h_rounded = discrete_ruler_lenght(h, 0.1);
1145
GBT_write_float(this->tree_static->gb_tree, awar, h_rounded);
1146
show_ruler(device, this->drag_gc);
1147
GBT_write_float(this->tree_static->gb_tree, awar, h);
1150
GBT_write_float(this->tree_static->gb_tree, awar, h);
1151
show_ruler(device, this->drag_gc);
1157
case AW_Mouse_Release:
1158
rot_cl.exists = false;
1159
this->exports.refresh = 1;
1160
if (button==AWT_M_RIGHT) { // if right mouse button is used -> adjust to 1 digit behind comma
1161
sprintf(awar,"ruler/size");
1162
double rulerSize = *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, 0.0);
1163
GBT_write_float(this->tree_static->gb_tree, awar, discrete_ruler_lenght(rulerSize, 0.1));
1171
if (type == AW_Mouse_Press) {
1173
sprintf(awar,"ruler/ruler_width");
1174
i = *GBT_readOrCreate_int(this->tree_static->gb_tree, awar , 0);
1180
GBT_write_int(this->tree_static->gb_tree, awar,i);
1181
this->exports.refresh = 1;
1186
GBT_write_int(this->tree_static->gb_tree, awar,i);
1187
show_ruler(device, AWT_GC_CURSOR);
1199
case AWT_MODE_MOVE: // two point commands !!!!!
1200
if(button==AWT_M_MIDDLE){
1204
case AW_Mouse_Press:
1205
if( !(cl && cl->exists) ){
1209
/*** check security level @@@ ***/
1210
at = (AP_tree *)cl->client_data1;
1211
if(at && at->father){
1215
this->old_rot_cl = *cl;
1220
if( bl_drag_flag && this->rot_at && this->rot_at->father){
1221
this->rot_show_line(device);
1225
rot_cl = old_rot_cl;
1227
this->rot_show_line(device);
1230
case AW_Mouse_Release:
1231
if( bl_drag_flag && this->rot_at && this->rot_at->father){
1232
this->rot_show_line(device);
1234
if (cl->exists) dest = (AP_tree *)cl->client_data1;
1235
AP_tree *source = rot_at;
1236
if (!(source && dest)) {
1237
aw_message("Please Drag Line to a valid branch");
1240
if (source == dest) {
1241
aw_message("Please drag mouse from source to destination");
1248
error = source->cantMoveTo(dest);
1249
if (!error) source->moveTo(dest,cl->length);
1253
error = source->move_group_info(dest);
1256
error = "????? 45338";
1262
this->exports.refresh = 1;
1263
this->exports.save = 1;
1264
this->exports.resize = 1;
1265
this->tree_root->test_tree();
1266
this->tree_root->compute_tree(gb_main);
1276
case AWT_MODE_LENGTH:
1277
if (button == AWT_M_MIDDLE) {
1281
case AW_Mouse_Press:
1282
if( cl && cl->exists ){
1283
at = (AP_tree *)cl->client_data1;
1288
this->old_rot_cl = *cl;
1289
device->transform(cl->x0, cl->y0, rot_cl.x0, rot_cl.y0);
1290
device->transform(cl->x1, cl->y1, rot_cl.x1, rot_cl.y1);
1292
this->rot_orientation = comp_rot_orientation(&rot_cl);
1293
this->rot_spread = comp_rot_spread(at, this);
1295
printf("rot_spread=%f\n", rot_spread);
1297
rot_show_triangle(device);
1302
if( bl_drag_flag && this->rot_at && this->rot_at->father){
1303
double len, ex, ey, scale;
1305
rot_show_triangle(device);
1307
if (rot_at == rot_at->father->leftson){
1308
len = rot_at->father->leftlen;
1310
len = rot_at->father->rightlen;
1316
len = ex * cos(this->rot_orientation) +
1317
ey * sin(this->rot_orientation);
1319
if (button==AWT_M_RIGHT) { // if right mouse button is used -> adjust to 1 digit behind comma
1320
len = discrete_ruler_lenght(len, 0.0);
1326
scale = device->get_scale();
1327
if (tree_sort == AP_TREE_IRS) {
1328
scale *= irs_tree_ruler_scale_factor;
1332
if (rot_at == rot_at->father->leftson) {
1333
rot_at->father->leftlen = len;
1336
rot_at->father->rightlen = len;
1339
rot_show_triangle(device);
1343
case AW_Mouse_Release:
1344
this->exports.refresh = 1;
1345
this->exports.save = 1;
1347
this->tree_root->compute_tree(gb_main);
1355
if(button!=AWT_M_LEFT){
1359
case AW_Mouse_Press:
1360
if( cl && cl->exists ){
1361
at = (AP_tree *)cl->client_data1;
1366
this->old_rot_cl = *cl;
1367
device->transform(cl->x0, cl->y0, rot_cl.x0, rot_cl.y0);
1368
device->transform(cl->x1, cl->y1, rot_cl.x1, rot_cl.y1);
1370
this->rot_orientation = comp_rot_orientation(&rot_cl);
1371
this->rot_spread = comp_rot_spread(at, this);
1372
rot_show_triangle(device);
1377
if( rot_drag_flag && this->rot_at && this->rot_at->father){
1380
rot_show_triangle(device);
1381
new_a = atan2(y - rot_cl.y0, x - rot_cl.x0);
1382
new_a -= this->rot_orientation;
1383
this->rot_orientation += new_a;
1384
if (this->rot_at == this->rot_at->father->leftson) {
1385
this->rot_at->father->gr.left_angle += new_a;
1386
if (!this->rot_at->father->father) {
1387
this->rot_at->father->gr.right_angle += new_a;
1390
this->rot_at->father->gr.right_angle += new_a;
1391
if (!this->rot_at->father->father) {
1392
this->rot_at->father->gr.left_angle += new_a;
1395
rot_show_triangle(device);
1399
case AW_Mouse_Release:
1400
this->exports.refresh = 1;
1401
this->exports.save = 1;
1409
case AWT_MODE_LZOOM:
1410
if(type==AW_Mouse_Press){
1414
at = (AP_tree *)cl->client_data1;
1416
this->tree_root_display = at;
1417
this->exports.zoom_reset = 1;
1418
this->exports.refresh = 1;
1422
if(this->tree_root_display->father){
1423
this->tree_root_display =
1424
this->tree_root_display->father;
1425
this->exports.refresh = 1;
1426
this->exports.zoom_reset = 1;
1430
this->tree_root->compute_tree(gb_main);
1434
case AWT_MODE_RESET:
1435
if(type==AW_Mouse_Press){
1438
/** reset rotation **/
1440
at = (AP_tree *)cl->client_data1;
1443
this->exports.save = 1;
1444
this->exports.refresh = 1;
1448
/** reset spread **/
1450
at = (AP_tree *)cl->client_data1;
1453
this->exports.save = 1;
1454
this->exports.refresh = 1;
1458
/** reset linewidth **/
1460
at = (AP_tree *)cl->client_data1;
1463
reset_line_width(at);
1464
if (at->father) { // reset clicked branch
1465
if (at->father->leftson == at) at->father->gr.left_linewidth = 0;
1466
else at->father->gr.right_linewidth = 0;
1468
this->exports.save = 1;
1469
this->exports.refresh = 1;
1473
this->tree_root->compute_tree(gb_main);
1478
if(type==AW_Mouse_Press){
1482
at = (AP_tree *)cl->client_data1;
1485
if(at->father->leftson == at) {
1486
at->father->gr.left_linewidth-=1;
1487
if(at->father->gr.left_linewidth<0) at->father->gr.left_linewidth=0;
1490
at->father->gr.right_linewidth-=1;
1491
if(at->father->gr.right_linewidth<0) at->father->gr.right_linewidth=0;
1493
this->exports.save = 1;
1494
this->exports.refresh = 1;
1501
at = (AP_tree *)cl->client_data1;
1504
if(at->father->leftson == at){
1505
at->father->gr.left_linewidth+=1;
1507
at->father->gr.right_linewidth+=1;
1509
this->exports.save = 1;
1510
this->exports.refresh = 1;
1513
printf("key_modifier=%i\n", key_modifier);
1517
} /* switch button */
1521
case AWT_MODE_SPREAD:
1522
if(type==AW_Mouse_Press){
1526
at = (AP_tree *)cl->client_data1;
1528
at->gr.spread -= PH_CLICK_SPREAD;
1529
if(at->gr.spread<0) at->gr.spread = 0;
1530
this->exports.refresh = 1;
1531
this->exports.save = 1;
1536
at = (AP_tree *)cl->client_data1;
1538
at->gr.spread += PH_CLICK_SPREAD;
1539
this->exports.refresh = 1;
1540
this->exports.save = 1;
1548
case AWT_MODE_GROUP:
1549
if(type==AW_Mouse_Press){
1551
at = (AP_tree *)cl->client_data1;
1557
if ( (!at->gr.grouped) && (!at->name)) {
1558
break; // not grouped and no name
1561
if (at->is_leaf) break; // don't touch zombies
1563
if (this->tree_static->gb_tree) {
1564
GB_ERROR error = this->create_group(at);
1565
if (error) aw_message(error);
1568
at->gr.grouped ^= 1;
1569
this->exports.refresh = 1;
1570
this->exports.save = 1;
1571
this->exports.resize = 1;
1572
this->tree_root->compute_tree(gb_main);
1576
if (this->tree_static->gb_tree) {
1577
this->toggle_group(at);
1579
this->exports.refresh = 1;
1580
this->exports.save = 1;
1581
this->exports.resize = 1;
1582
this->tree_root->compute_tree(gb_main);
1591
case AWT_MODE_SETROOT:
1592
if(type==AW_Mouse_Press){
1596
at = (AP_tree *)cl->client_data1;
1599
this->exports.save = 1;
1600
this->exports.zoom_reset = 1;
1601
this->tree_root->compute_tree(gb_main);
1609
if(type==AW_Mouse_Press){
1613
at = (AP_tree *)cl->client_data1;
1617
this->exports.refresh = 1;
1618
this->exports.save = 1;
1628
if (type == AW_Mouse_Press && (cl->exists || ct->exists)) {
1629
if (cl->exists) at = (AP_tree *)cl->client_data1;
1630
else at = (AP_tree *)ct->client_data1;
1633
GB_transaction dummy(this->tree_static->gb_species_data);
1635
if (type == AW_Mouse_Press) {
1638
mark_species_in_tree(at, 1);
1641
mark_species_in_tree(at, 0);
1645
this->exports.refresh = 1;
1646
this->tree_static->update_timers(); // do not reload the tree
1647
this->tree_root->calc_color();
1653
case AWT_MODE_SELECT:
1654
if(type==AW_Mouse_Press && (cl->exists || ct->exists) && button != AWT_M_MIDDLE){
1655
GB_transaction dummy(this->tree_static->gb_species_data);
1657
at = (AP_tree *)cl->client_data1;
1659
at = (AP_tree *)ct->client_data1;
1663
this->exports.refresh = 1; // No refresh needed !! AD_map_viewer will do the refresh (needed by arb_pars)
1664
AD_map_viewer(at->gb_node, ADMVT_SELECT);
1666
if (button == AWT_M_LEFT) goto act_like_group; // now do the same like in AWT_MODE_GROUP
1671
if(type==AW_Mouse_Press && (cl->exists || ct->exists) ){
1672
GB_transaction dummy(this->tree_static->gb_species_data);
1674
at = (AP_tree *)cl->client_data1;
1676
at = (AP_tree *)ct->client_data1;
1679
AD_map_viewer(at->gb_node,ADMVT_INFO);
1683
if(type==AW_Mouse_Press && (cl->exists || ct->exists) ){
1684
GB_transaction dummy(this->tree_static->gb_species_data);
1686
at = (AP_tree *)cl->client_data1;
1688
at = (AP_tree *)ct->client_data1;
1691
AD_map_viewer(at->gb_node,ADMVT_WWW);
1699
void AWT_graphic_tree::set_tree_type(AP_tree_sort type)
1701
if (sort_is_list_style(type)) {
1702
if (tree_sort == type) { // we are already in wanted view
1703
nds_show_all = !nds_show_all; // -> toggle between 'marked' and 'all'
1706
nds_show_all = true; // default to all
1711
case AP_TREE_RADIAL:
1712
exports.dont_fit_x = 0;
1713
exports.dont_fit_y = 0;
1714
exports.dont_fit_larger = 0;
1715
exports.left_offset = 150;
1716
exports.right_offset = 150;
1717
exports.top_offset = 30;
1718
exports.bottom_offset = 30;
1719
exports.dont_scroll = 0;
1722
case AP_LIST_SIMPLE:
1724
exports.dont_fit_x = 1;
1725
exports.dont_fit_y = 1;
1726
exports.dont_fit_larger = 0;
1727
exports.left_offset = short(2*NT_SELECTED_WIDTH+0.5);
1728
exports.right_offset = 300;
1729
exports.top_offset = 30;
1730
exports.bottom_offset = 30;
1731
exports.dont_scroll = 0;
1734
case AP_TREE_IRS: // folded dendogram
1735
exports.dont_fit_x = 1;
1736
exports.dont_fit_y = 1;
1737
exports.dont_fit_larger = 0;
1738
exports.left_offset = 0;
1739
exports.right_offset = 300;
1740
exports.top_offset = 30;
1741
exports.bottom_offset = 30;
1742
exports.dont_scroll = 1;
1745
case AP_TREE_NORMAL: // normal dendogram
1746
exports.dont_fit_x = 0;
1747
exports.dont_fit_y = 1;
1748
exports.dont_fit_larger = 0;
1749
exports.left_offset = 0;
1750
exports.right_offset = 300;
1751
exports.top_offset = 30;
1752
exports.bottom_offset = 30;
1753
exports.dont_scroll = 0;
1758
AWT_graphic_tree::AWT_graphic_tree(AW_root *aw_rooti, GBDATA *gb_maini):AWT_graphic()
1760
line_filter = AW_SCREEN|AW_CLICK|AW_CLICK_DRAG|AW_SIZE|AW_PRINTER;
1761
vert_line_filter = AW_SCREEN|AW_PRINTER;
1762
text_filter = AW_SCREEN|AW_CLICK|AW_PRINTER;
1763
mark_filter = AW_SCREEN|AW_PRINTER_EXT;
1764
ruler_filter = AW_SCREEN|AW_CLICK|AW_PRINTER|AW_SIZE;
1765
root_filter = AW_SCREEN|AW_CLICK|AW_PRINTER_EXT;
1766
set_tree_type(AP_TREE_NORMAL);
1767
tree_root_display = 0;
1775
this->aw_root = aw_rooti;
1776
this->gb_main = gb_maini;
1777
rot_ct.exists = false;
1778
rot_cl.exists = false;
1779
nds_show_all = true;
1782
AWT_graphic_tree::~AWT_graphic_tree(void)
1784
delete this->tree_proto;
1785
delete this->tree_root;
1786
delete this->tree_static;
1790
void AWT_graphic_tree::init(AP_tree * tree_prot)
1792
this->tree_proto = tree_prot->dup();
1795
void AWT_graphic_tree::unload(void)
1805
tree_root_display = 0;
1809
GB_ERROR AWT_graphic_tree::load(GBDATA *, const char *name,AW_CL link_to_database, AW_CL insert_delete_cbs) {
1812
if (name[0] == 0 || strcmp(name, "tree_????") == 0) { // no tree selected
1818
AP_tree *apt = tree_proto->dup();
1819
AP_tree_root *tr = new AP_tree_root(gb_main,apt,name);
1821
error = apt->load(tr,(int)link_to_database,(GB_BOOL)insert_delete_cbs, GB_TRUE, &zombies, &duplicates); // show status
1831
tree_root_display = this->tree_root;
1833
tree_root->compute_tree(gb_main);
1835
tree_name = strdup(name);
1837
tr->root_changed_cd = (void*)this;
1838
tr->root_changed = AWT_graphic_tree_root_changed;
1839
tr->node_deleted_cd = (void*)this;
1840
tr->node_deleted = AWT_graphic_tree_node_deleted;
1847
GB_ERROR AWT_graphic_tree::save(GBDATA */*dummy*/, const char */*name*/, AW_CL /*cd1*/, AW_CL /*cd2*/) {
1848
GB_ERROR error = NULL;
1850
error = tree_root->saveTree();
1852
else if (tree_name) {
1853
if (tree_static && tree_static->gb_tree_gone) {
1854
GB_transaction ta(gb_main);
1855
error = GB_delete(tree_static->gb_tree_gone);
1856
error = ta.close(error);
1859
aw_message(GBS_global_string("Tree '%s' lost all leaves and has been deleted", tree_name));
1860
#if defined(DEVEL_RALF)
1861
#warning somehow update selected tree
1863
// solution: currently selected tree (in NTREE, maybe also in PARSIMONY)
1864
// needs to add a delete callback on treedata in DB
1866
#endif // DEVEL_RALF
1869
tree_static->gb_tree_gone = 0; // do not delete twice
1875
int AWT_graphic_tree::check_update(GBDATA *gbdummy)
1878
AP_UPDATE_FLAGS flags;
1881
if (!this->tree_static) return 0;
1882
GB_transaction dummy(gb_main);
1884
if (!this->tree_root) {
1885
flags = AP_UPDATE_ERROR;
1888
flags = this->tree_root->check_update();
1891
case AP_UPDATE_ERROR:
1893
case AP_UPDATE_RELOADED:
1894
name = strdup(this->tree_static->tree_name);
1895
error = this->load(gb_main, name, 1, 0);
1896
if (error) aw_message(error);
1898
this->exports.resize = 1;
1900
case AP_UPDATE_RELINKED:
1901
error = this->tree_root->relink();
1902
if (error) aw_message(error);
1903
else this->tree_root->compute_tree(gb_main);
1910
void AWT_graphic_tree::update(GBDATA *gbdummy){
1912
if (!this->tree_static) return;
1913
if (!this->tree_root) return;
1914
GB_transaction dummy(gb_main);
1915
this->tree_root->update();
1918
void AWT_graphic_tree::NT_scalebox(int gc, double x, double y, double width)
1920
double diam = width/disp_device->get_scale();
1921
double diam2 = diam+diam;
1922
disp_device->set_fill(gc, this->grey_level);
1923
disp_device->box(gc, true, x-diam, y-diam, diam2, diam2, mark_filter, 0, 0);
1926
void AWT_graphic_tree::NT_emptybox(int gc, double x, double y, double width)
1928
double diam = width/disp_device->get_scale();
1929
double diam2 = diam+diam;
1930
disp_device->set_line_attributes(gc, 0.0, AW_SOLID);
1931
disp_device->box(gc, false, x-diam, y-diam, diam2, diam2, mark_filter, 0, 0);
1934
void AWT_graphic_tree::NT_rotbox(int gc, double x, double y, double width) // box with one corner down
1936
double diam = width / disp_device->get_scale();
1942
disp_device->line(gc, x1, y, x, y1, mark_filter, 0, 0);
1943
disp_device->line(gc, x2, y, x, y1, mark_filter, 0, 0);
1944
disp_device->line(gc, x1, y, x, y2, mark_filter, 0, 0);
1945
disp_device->line(gc, x2, y, x, y2, mark_filter, 0, 0);
1948
bool AWT_show_remark_branch(AW_device *device, const char *remark_branch, bool is_leaf, AW_pos x, AW_pos y, AW_pos alignment, AW_bitset filteri, AW_CL cd1, AW_CL cd2) {
1949
// returns true if a bootstrap was DISPLAYED
1951
int bootstrap = int(strtol(remark_branch, &end, 10));
1952
bool is_bootstrap = end[0] == '%' && end[1] == 0;
1954
const char *text = 0;
1957
if (bootstrap == 100) {
1958
show = !is_leaf; // do not show 100% bootstraps at leafs
1959
if (show) text = "100%";
1962
if (bootstrap == 0) {
1963
text = "<1%"; // show instead of '0%'
1966
text = GBS_global_string("%i%%", bootstrap);
1971
text = remark_branch;
1975
awt_assert(text != 0);
1976
device->text(AWT_GC_BRANCH_REMARK, text, x, y, alignment, filteri, cd1, cd2);
1979
return is_bootstrap && show;
1983
double AWT_graphic_tree::show_dendrogram(AP_tree *at, double x_father, double x_son)
1985
double ny0, ny1, nx0, nx1, ry, l_min, l_max, xoffset, yoffset;
1989
if (disp_device->type() != AW_DEVICE_SIZE){ // tree below cliprect bottom can be cut
1991
AW_pos ys = y_pos - scaled_branch_distance *2.0;
1993
disp_device->transform(xs,ys,X,Y);
1994
if ( Y > disp_device->clip_rect.b){
1995
y_pos += scaled_branch_distance;
1998
ys = y_pos + scaled_branch_distance * (at->gr.view_sum+2);
1999
disp_device->transform(xs,ys,X,Y);
2001
if ( Y < disp_device->clip_rect.t){
2002
y_pos += scaled_branch_distance*at->gr.view_sum;
2009
if (at->gb_node && GB_read_flag(at->gb_node)){
2010
NT_scalebox(at->gr.gc, x_son, ny0, NT_BOX_WIDTH);
2013
at->name[0] == this->species_name[0] &&
2014
strcmp(at->name,this->species_name) == 0)
2020
if (at->name && (disp_device->filter & text_filter) ){
2022
const char *data = make_node_text_nds(this->gb_main, at->gb_node,0,at->get_gbt_tree(), tree_name);
2024
// offset = scale*0.4;
2027
const AW_font_information *fontinfo = disp_device->get_font_information(at->gr.gc,'A');
2029
#if defined(DEBUG) && 0
2030
static bool dumped = false;
2032
for (int c = 32; c <= 255; c++) {
2033
const AW_font_information *fi = disp_device->get_font_information(at->gr.gc,(char)c);
2034
printf("fontinfo: %3i '%c' ascent=%2i descent=%2i width=%2i\n",
2036
fi->this_letter.ascent,
2037
fi->this_letter.descent,
2038
fi->this_letter.width
2041
printf("fontinfo (all-maximas): ascent=%2i descent=%2i width=%2i\n",
2042
fi->max_all_letter.ascent,
2043
fi->max_all_letter.descent,
2044
fi->max_all_letter.width
2046
printf("fontinfo (ascii-maximas): ascent=%2i descent=%2i width=%2i\n",
2047
fi->max_letter.ascent,
2048
fi->max_letter.descent,
2049
fi->max_letter.width
2059
double unscale = 1.0/disp_device->get_scale();
2060
yoffset = scaled_font.ascent*.5;
2061
xoffset = ((fontinfo->max_letter.width * 0.5) + NT_BOX_WIDTH) * unscale;
2063
disp_device->text(at->gr.gc,data ,
2064
(AW_pos) x_son+xoffset,(AW_pos) ny0+yoffset,
2065
(AW_pos) 0 , text_filter,
2066
(AW_CL) at , (AW_CL) 0 );
2070
y_pos += scaled_branch_distance;
2074
if (at->gr.grouped) {
2075
l_min = at->gr.min_tree_depth;
2076
l_max = at->gr.tree_depth;
2077
ny1 = y_pos += scaled_branch_distance*(at->gr.view_sum-1);
2078
nx0 = x_son + l_max;
2079
nx1 = x_son + l_min;
2083
if (at->father->leftson == at) {
2084
linewidth = at->father->gr.left_linewidth;
2086
linewidth = at->father->gr.right_linewidth;
2090
disp_device->set_line_attributes(at->gr.gc,linewidth+baselinewidth,AW_SOLID);
2093
q[0] = x_son; q[1] = ny0;
2094
q[2] = x_son; q[3] = ny1;
2095
q[4] = nx1; q[5] = ny1;
2096
q[6] = nx0; q[7] = ny0;
2098
disp_device->set_fill(at->gr.gc, grey_level);
2099
disp_device->filled_area(at->gr.gc, 4, &q[0], line_filter, (AW_CL)at,0);
2101
// double add_y_offset = scale*0.3;
2103
const AW_font_information *fontinfo = disp_device->get_font_information(at->gr.gc,'A');
2104
double text_ascent = fontinfo->max_letter.ascent/ disp_device->get_scale() ;
2106
yoffset = (ny1-ny0+text_ascent)*.5;
2107
xoffset = text_ascent*.5;
2109
if (at->gb_node && (disp_device->filter & text_filter)){
2110
const char *data = make_node_text_nds(this->gb_main, at->gb_node,0,at->get_gbt_tree(), tree_name);
2112
disp_device->text(at->gr.gc,data ,
2113
(AW_pos) nx0+xoffset,(AW_pos) ny0+yoffset,
2114
(AW_pos) 0 , text_filter,
2115
(AW_CL) at , (AW_CL) 0 );
2117
disp_device->text(at->gr.gc,(char *)GBS_global_string(" %i",at->gr.leave_sum),
2118
x_son+xoffset, ny0+yoffset,
2119
0,text_filter,(AW_CL)at,0);
2121
y_pos += scaled_branch_distance;
2123
return (ny0+ny1)*.5;
2125
nx0 = (x_son + at->leftlen) ;
2126
nx1 = (x_son + at->rightlen) ;
2127
ny0 = show_dendrogram(at->leftson,x_son, nx0);
2128
ry = (double) y_pos - .5*scaled_branch_distance;
2129
ny1 = (double) show_dendrogram(at->rightson,x_son, nx1);
2132
NT_rotbox(at->gr.gc,x_son, ry, NT_BOX_WIDTH*2);
2135
if (at->leftson->remark_branch ) {
2136
bool bootstrap_shown = AWT_show_remark_branch(disp_device, at->leftson->remark_branch, at->leftson->is_leaf, nx0, ny0-scaled_font.ascent*0.1, 1, text_filter, (AW_CL)at, 0);
2138
if (show_circle && bootstrap_shown){
2139
AWT_show_bootstrap_circle(disp_device,at->leftson->remark_branch, circle_zoom_factor, circle_max_size, at->leftlen,nx0, ny0, use_ellipse, scaled_branch_distance, text_filter, (AW_CL) at->leftson, (AW_CL) 0);
2143
if (at->rightson->remark_branch ) {
2144
bool bootstrap_shown = AWT_show_remark_branch(disp_device, at->rightson->remark_branch, at->rightson->is_leaf, nx1, ny1-scaled_font.ascent*0.1, 1, text_filter, (AW_CL)at, 0);
2146
if (show_circle && bootstrap_shown){
2147
AWT_show_bootstrap_circle(disp_device,at->rightson->remark_branch,circle_zoom_factor, circle_max_size, at->rightlen,nx1, ny1, use_ellipse, scaled_branch_distance, text_filter, (AW_CL) at->rightson, (AW_CL) 0);
2153
disp_device->text(at->gr.gc, GBS_global_string("%p(gb_node)", at->gb_node), x_father, (ny0+ny1)/2, 0, text_filter, (AW_CL)at, 0);
2158
int lw = at->gr.left_linewidth+baselinewidth;
2159
// disp_device->set_line_attributes(at->gr.gc,lw,AW_SOLID);
2160
disp_device->set_line_attributes(at->leftson->gr.gc,lw,AW_SOLID);
2161
disp_device->line(at->leftson->gr.gc, x_son, ny0, nx0, ny0, line_filter, (AW_CL)at->leftson,0);
2162
// disp_device->set_line_attributes(at->gr.gc,lw,AW_SOLID);
2163
disp_device->line(at->leftson->gr.gc, x_son, ny0, x_son, ry, vert_line_filter, (AW_CL)at,0);
2165
int rw = at->gr.right_linewidth+baselinewidth;
2166
// disp_device->set_line_attributes(at->gr.gc,rw,AW_SOLID);
2167
disp_device->set_line_attributes(at->rightson->gr.gc,rw,AW_SOLID);
2168
disp_device->line(at->rightson->gr.gc,x_son, ny1, nx1, ny1, line_filter, (AW_CL)at->rightson,0);
2169
// disp_device->set_line_attributes(at->gr.gc,rw,AW_SOLID);
2170
disp_device->line(at->rightson->gr.gc, x_son, ry, x_son, ny1, vert_line_filter, (AW_CL)at,0);
2176
void AWT_graphic_tree::scale_text_koordinaten(AW_device *device, int gc,double& x,double& y,double orientation,int flag)
2178
const AW_font_information *fontinfo = device->get_font_information(gc,'A');
2179
double text_height = fontinfo->max_letter.height/ disp_device->get_scale() ;
2180
double dist = fontinfo->max_letter.height/ disp_device->get_scale();
2186
x += cos(orientation) * dist;
2187
y += sin(orientation) * dist + 0.3*text_height;
2193
// ********* shell and radial tree
2194
void AWT_graphic_tree::show_radial_tree(AP_tree * at, double x_center,
2195
double y_center, double tree_spread,double tree_orientation,
2196
double x_root, double y_root, int linewidth)
2198
double l,r,w,z,l_min,l_max;
2200
disp_device->set_line_attributes(at->gr.gc,linewidth+baselinewidth,AW_SOLID);
2201
disp_device->line(at->gr.gc, x_root, y_root, x_center, y_center, line_filter, (AW_CL)at,0);
2204
if (at->gb_node && GB_read_flag(at->gb_node)) {
2205
NT_scalebox(at->gr.gc, x_center, y_center, NT_BOX_WIDTH);
2209
if (at->name && (disp_device->filter & text_filter) ){
2210
if (at->name[0] == this->species_name[0] &&
2211
!strcmp(at->name,this->species_name)) {
2212
x_cursor = x_center; y_cursor = y_center;
2214
scale_text_koordinaten(disp_device,at->gr.gc, x_center,y_center,tree_orientation,0);
2215
const char *data = make_node_text_nds(this->gb_main,at->gb_node,0,at->get_gbt_tree(), tree_name);
2216
// PJ vectorfont - example for calling
2217
// disp_device->zoomtext(at->gr.gc,data,
2218
// (AW_pos)x_center,(AW_pos) y_center,
2219
// 0.005, .5-.5*cos(tree_orientation), 0,
2220
// text_filter, (AW_CL) at, (AW_CL) 0);
2222
disp_device->text(at->gr.gc,data,
2223
(AW_pos)x_center,(AW_pos) y_center,
2224
(AW_pos) .5 - .5 * cos(tree_orientation),
2225
text_filter, (AW_CL) at , (AW_CL) 0 );
2230
if( at->gr.grouped){
2231
l_min = at->gr.min_tree_depth;
2232
l_max = at->gr.tree_depth;
2238
w = tree_orientation + r*0.5*tree_spread+ at->gr.right_angle;
2239
q[2] = x_center+l_min*cos(w);
2240
q[3] = y_center+l_min*sin(w);
2241
w = tree_orientation - l*0.5*tree_spread + at->gr.right_angle;
2242
q[4] = x_center+l_max*cos(w);
2243
q[5] = y_center+l_max*sin(w);
2245
disp_device->set_fill(at->gr.gc, grey_level);
2246
disp_device->filled_area(at->gr.gc, 3, &q[0], line_filter, (AW_CL)at,0);
2248
if (at->gb_node && (disp_device->filter & text_filter) ){
2249
w = tree_orientation + at->gr.right_angle;
2250
l_max = (l_max+l_min)*.5;
2251
x_center= x_center+l_max*cos(w);
2252
y_center= y_center+l_max*sin(w);
2253
scale_text_koordinaten(disp_device,at->gr.gc,x_center,y_center,w,0);
2255
/* insert text (e.g. name of group) */
2256
const char *data = make_node_text_nds(this->gb_main, at->gb_node,0,at->get_gbt_tree(), tree_name);
2257
//PJ vectorfont - possibly groups should be rendered bigger than species
2258
// disp_device->zoomtext(at->gr.gc ,data,
2259
// (AW_pos)x_center,(AW_pos) y_center, 0.01,
2260
// (AW_pos).5 - .5 * cos(tree_orientation),0 ,
2262
// (AW_CL) at , (AW_CL) 0 );
2263
disp_device->text(at->gr.gc,data,
2264
(AW_pos)x_center,(AW_pos) y_center,
2265
(AW_pos).5 - .5 * cos(tree_orientation),
2267
(AW_CL) at , (AW_CL) 0 );
2271
l = (double) at->leftson->gr.view_sum / (double)at->gr.view_sum;
2272
r = 1.0 - (double)l;
2274
if (at->leftson->gr.gc > at->rightson->gr.gc) {
2275
// bring selected gc to front
2277
/*** left branch ***/
2278
w = r*0.5*tree_spread + tree_orientation + at->gr.left_angle;
2280
show_radial_tree(at->leftson,
2281
x_center+ z * cos(w),
2282
y_center+ z * sin(w),
2283
(at->leftson->is_leaf) ? 1.0 :
2284
tree_spread * l * at->leftson->gr.spread,
2286
x_center, y_center, at->gr.left_linewidth );
2288
/*** right branch ***/
2289
w = tree_orientation - l*0.5*tree_spread + at->gr.right_angle;
2291
show_radial_tree(at->rightson,
2292
x_center+ z * cos(w),
2293
y_center+ z * sin(w),
2294
(at->rightson->is_leaf) ? 1.0 :
2295
tree_spread * r * at->rightson->gr.spread,
2297
x_center, y_center, at->gr.right_linewidth);
2299
/*** right branch ***/
2300
w = tree_orientation - l*0.5*tree_spread + at->gr.right_angle;
2302
show_radial_tree(at->rightson,
2303
x_center+ z * cos(w),
2304
y_center+ z * sin(w),
2305
(at->rightson->is_leaf) ? 1.0 :
2306
tree_spread * r * at->rightson->gr.spread,
2308
x_center, y_center, at->gr.right_linewidth);
2310
/*** left branch ***/
2311
w = r*0.5*tree_spread + tree_orientation + at->gr.left_angle;
2313
show_radial_tree(at->leftson,
2314
x_center+ z * cos(w),
2315
y_center+ z * sin(w),
2316
(at->leftson->is_leaf) ? 1.0 :
2317
tree_spread * l * at->leftson->gr.spread,
2319
x_center, y_center, at->gr.left_linewidth );
2322
/*** left branch ***/
2323
if (at->leftson->remark_branch){
2324
w = r*0.5*tree_spread + tree_orientation + at->gr.left_angle;
2325
z = at->leftlen * .5;
2326
AWT_show_bootstrap_circle(disp_device,at->leftson->remark_branch,circle_zoom_factor, circle_max_size, at->leftlen,x_center+ z * cos(w),y_center+ z * sin(w), false, 0, text_filter, (AW_CL)at,0);
2328
if (at->rightson->remark_branch){
2329
/*** right branch ***/
2330
w = tree_orientation - l*0.5*tree_spread + at->gr.right_angle;
2331
z = at->rightlen * .5;
2332
AWT_show_bootstrap_circle(disp_device,at->rightson->remark_branch,circle_zoom_factor, circle_max_size, at->rightlen,x_center+ z * cos(w),y_center+ z * sin(w), false, 0, text_filter, (AW_CL)at,0);
2337
const char *AWT_graphic_tree::show_ruler(AW_device *device, int gc) {
2338
const char *tree_awar = 0;
2341
if (!this->tree_static->gb_tree) return 0; // no ruler !!!!
2342
GB_transaction dummy(this->tree_static->gb_tree);
2344
sprintf(awar,"ruler/size");
2345
float ruler_size = *GBT_readOrCreate_float( this->tree_static->gb_tree, awar, 0.1);
2346
float ruler_x = 0.0;
2347
float ruler_y = 0.0;
2348
float ruler_text_x = 0.0;
2349
float ruler_text_y = 0.0;
2350
float ruler_add_y = 0.0;
2351
float ruler_add_x = 0.0;
2353
switch (tree_sort) {
2354
case AP_TREE_NORMAL:
2357
case AP_TREE_RADIAL:
2358
tree_awar = "RADIAL";
2363
case AP_LIST_SIMPLE:
2365
// rulers not allowed in these display modes
2372
sprintf(awar,"ruler/%s/ruler_y",tree_awar);
2373
if (!GB_search(this->tree_static->gb_tree,awar,GB_FIND)){
2374
if (device->type() == AW_DEVICE_SIZE) {
2376
device ->get_size_information(&world);
2377
ruler_y = world.b * 1.3;
2381
double half_ruler_width = ruler_size*0.5;
2383
switch (tree_sort) {
2385
// scale is different for IRS tree -> adjust:
2386
half_ruler_width *= irs_tree_ruler_scale_factor;
2388
ruler_add_y = this->list_tree_ruler_y;
2389
ruler_add_x = -half_ruler_width;
2391
case AP_TREE_NORMAL:
2393
ruler_add_y = this->list_tree_ruler_y;
2394
ruler_add_x = half_ruler_width;
2401
ruler_y = ruler_add_y + *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, ruler_y);
2403
sprintf(awar,"ruler/%s/ruler_x",tree_awar);
2404
ruler_x = ruler_add_x + *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, ruler_x);
2406
sprintf(awar,"ruler/%s/text_x", tree_awar);
2407
// ruler_text_x = *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, ruler_text_x) * ruler_scale;
2408
ruler_text_x = *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, ruler_text_x);
2410
sprintf(awar,"ruler/%s/text_y", tree_awar);
2411
// ruler_text_y = *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, ruler_text_y) * ruler_scale;
2412
ruler_text_y = *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, ruler_text_y);
2414
sprintf(awar,"ruler/ruler_width");
2415
double ruler_width = *GBT_readOrCreate_int(this->tree_static->gb_tree, awar, 0);
2417
device->set_line_attributes(gc, ruler_width+baselinewidth, AW_SOLID);
2420
ruler_x - half_ruler_width, ruler_y,
2421
ruler_x + half_ruler_width, ruler_y,
2424
char ruler_text[20];
2425
sprintf(ruler_text,"%4.2f",ruler_size);
2427
device->text(gc, ruler_text,
2428
ruler_x + ruler_text_x,
2429
ruler_y + ruler_text_y,
2431
this->ruler_filter & ~AW_SIZE,
2437
void AWT_graphic_tree::show_nds_list(GBDATA * dummy, bool use_nds)
2440
AW_pos y_position = scaled_branch_distance;
2441
AW_pos x_position = 2*NT_SELECTED_WIDTH / disp_device->get_scale();
2442
long max_strlen = 0;
2444
disp_device->text(nds_show_all ? AWT_GC_CURSOR : AWT_GC_SELECTED,
2445
GBS_global_string("%s of %s species", use_nds ? "NDS List" : "Simple list", nds_show_all ? "all" : "marked"),
2446
(AW_pos) x_position, (AW_pos) 0,
2447
(AW_pos) 0, text_filter,
2448
(AW_CL) 0, (AW_CL) 0);
2450
for (GBDATA *gb_species = nds_show_all ? GBT_first_species(gb_main) : GBT_first_marked_species(gb_main);
2452
gb_species = nds_show_all ? GBT_next_species(gb_species) : GBT_next_marked_species(gb_species))
2454
y_position += scaled_branch_distance;
2456
const char *name = GBT_read_name(gb_species);
2458
if (strcmp(name, this->species_name) == 0) {
2460
y_cursor = y_position;
2463
bool is_marked = GB_read_flag(gb_species);
2464
if (is_marked) NT_scalebox(AWT_GC_SELECTED, 0, y_position, NT_BOX_WIDTH);
2469
disp_device->transform(xs, y_position+scaled_branch_distance, X, Y);
2470
if ( Y < disp_device->clip_rect.t) continue;
2471
disp_device->transform(xs, y_position-scaled_branch_distance, X, Y);
2472
if ( Y > disp_device->clip_rect.b) continue;
2475
if (disp_device->type() != AW_DEVICE_SIZE){ // tree below cliprect bottom can be cut
2478
data = make_node_text_nds(gb_main, gb_species, 1, 0, tree_name);
2484
long slen = strlen(data);
2485
int gc = AWT_GC_NSELECTED;
2487
if (nds_show_all && is_marked) {
2488
gc = AWT_GC_SELECTED;
2491
int color_group = AWT_species_get_dominant_color(gb_species);
2492
if (color_group) gc = AWT_GC_FIRST_COLOR_GROUP+color_group-1;
2495
disp_device->text(gc, data,
2496
(AW_pos) x_position, (AW_pos) y_position + scaled_font.ascent*.5,
2497
(AW_pos) 0, text_filter,
2498
(AW_CL) gb_species, (AW_CL) "species", slen);
2500
if (slen> max_strlen) max_strlen = slen;
2504
disp_device->invisible(AWT_GC_CURSOR, 0, 0, -1, 0, 0);
2505
disp_device->invisible(AWT_GC_CURSOR, max_strlen*scaled_font.width, y_position+scaled_branch_distance, -1, 0, 0);
2508
void AWT_graphic_tree::show(AW_device *device) {
2509
if (tree_static && tree_static->gb_tree) {
2510
check_update(gb_main);
2512
if (!tree_root_display) { // if there is no tree
2513
if (sort_is_tree_style(tree_sort)) { // but display style needs tree
2514
set_tree_type(AP_LIST_NDS); // => switch display style
2518
disp_device = device;
2520
const AW_font_information *fontinfo = disp_device->get_font_information(AWT_GC_SELECTED, 0);
2522
scaled_font.init(fontinfo->max_letter, 1/device->get_scale());
2523
scaled_branch_distance = scaled_font.height * aw_root->awar(AWAR_DTREE_VERICAL_DIST)->read_float();
2525
make_node_text_init(gb_main);
2527
grey_level = aw_root->awar(AWAR_DTREE_GREY_LEVEL)->read_int()*.01;
2528
baselinewidth = (int)aw_root->awar(AWAR_DTREE_BASELINEWIDTH)->read_int();
2529
show_circle = (int)aw_root->awar(AWAR_DTREE_SHOW_CIRCLE)->read_int();
2530
circle_zoom_factor = aw_root->awar(AWAR_DTREE_CIRCLE_ZOOM)->read_float();
2531
circle_max_size = aw_root->awar(AWAR_DTREE_CIRCLE_MAX_SIZE)->read_float();
2532
use_ellipse = aw_root->awar(AWAR_DTREE_USE_ELLIPSE)->read_int();
2534
freeset(species_name, aw_root->awar(AWAR_SPECIES_NAME)->read_string());
2536
x_cursor = y_cursor = 0.0;
2538
switch (tree_sort) {
2539
case AP_TREE_NORMAL:
2540
if (!tree_root_display) return;
2542
show_dendrogram(tree_root_display, 0, 0);
2543
list_tree_ruler_y = y_pos + 2.0 * scaled_branch_distance;
2546
case AP_TREE_RADIAL:
2547
if (!tree_root_display) return;
2548
NT_emptybox(tree_root_display->gr.gc, 0, 0, NT_ROOT_WIDTH);
2549
show_radial_tree(tree_root_display, 0,0,2*M_PI, 0.0,0, 0, tree_root_display->gr.left_linewidth);
2553
show_irs_tree(tree_root_display,disp_device,fontinfo->max_letter.height);
2554
list_tree_ruler_y = y_pos;
2557
case AP_LIST_NDS: // this is the list all/marked species mode (no tree)
2558
show_nds_list(gb_main, true);
2561
case AP_LIST_SIMPLE: // simple list of names (used at startup only)
2562
show_nds_list(gb_main, false);
2565
if (x_cursor != 0.0 || y_cursor != 0.0) {
2566
NT_emptybox(AWT_GC_CURSOR, x_cursor, y_cursor, NT_SELECTED_WIDTH);
2568
if (sort_is_tree_style(tree_sort)) { // show rulers in tree-style display modes
2569
show_ruler(device, AWT_GC_CURSOR);
2573
void AWT_graphic_tree::info(AW_device *device, AW_pos x, AW_pos y,
2574
AW_clicked_line *cl, AW_clicked_text *ct)
2576
aw_message("INFO MESSAGE");
2585
AWT_graphic_tree *NT_generate_tree(AW_root *root, GBDATA *gb_main) {
2586
AWT_graphic_tree *apdt = new AWT_graphic_tree(root,gb_main);
2587
AP_tree tree_proto(0);
2588
apdt->init(&tree_proto); // no tree_root !!! load will do this
2592
void awt_create_dtree_awars(AW_root *aw_root,AW_default def)
2594
aw_root->awar_int(AWAR_DTREE_BASELINEWIDTH,1,def)->set_minmax(1, 10);
2595
aw_root->awar_float(AWAR_DTREE_VERICAL_DIST,1.0,def)->set_minmax(0.01,30);
2596
aw_root->awar_int(AWAR_DTREE_AUTO_JUMP,1,def);
2598
aw_root->awar_int(AWAR_DTREE_SHOW_CIRCLE,0,def);
2599
aw_root->awar_int(AWAR_DTREE_USE_ELLIPSE, 1, def);
2601
aw_root->awar_float(AWAR_DTREE_CIRCLE_ZOOM,1.0,def) ->set_minmax(0.01,20);
2602
aw_root->awar_float(AWAR_DTREE_CIRCLE_MAX_SIZE,1.5,def) ->set_minmax(0.01,200);
2603
aw_root->awar_int(AWAR_DTREE_GREY_LEVEL,20,def) ->set_minmax(0,100);
2605
aw_root->awar_int(AWAR_DTREE_REFRESH,0,def);