~ubuntu-branches/debian/jessie/arb/jessie

« back to all changes in this revision

Viewing changes to AWT/AWT_dtree.cxx

  • Committer: Package Import Robot
  • Author(s): Elmar Pruesse, Andreas Tille, Elmar Pruesse
  • Date: 2014-09-02 15:15:06 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20140902151506-jihq58b3iz342wif
Tags: 6.0.2-1
[ Andreas Tille ]
* New upstream version
  Closes: #741890
* debian/upstream -> debian/upstream/metadata
* debian/control:
   - Build-Depends: added libglib2.0-dev
   - Depends: added mafft, mrbayes
* debian/rules
   - Add explicite --remove-section=.comment option to manual strip call
* cme fix dpkg-control
* arb-common.dirs: Do not create unneeded lintian dir
* Add turkish debconf translation (thanks for the patch to Mert Dirik
  <mertdirik@gmail.com>)
  Closes: #757497

[ Elmar Pruesse ]
* patches removed:
   - 10_config.makefiles.patch,
     80_no_GL.patch
       removed in favor of creating file from config.makefile.template via 
       sed in debian/control
   - 20_Makefile_main.patch
       merged upstream
   - 21_Makefiles.patch
       no longer needed
   - 30_tmpfile_CVE-2008-5378.patch: 
       merged upstream
   - 50_fix_gcc-4.8.patch:
       merged upstream
   - 40_add_libGLU.patch:
       libGLU not needed for arb_ntree)
   - 60_use_debian_packaged_raxml.patch:
       merged upstream
   - 70_hardening.patch
       merged upstream
   - 72_add_math_lib_to_linker.patch
       does not appear to be needed
* patches added:
   - 10_upstream_r12793__show_db_load_progress:
       backported patch showing progress while ARB is loading a database
       (needed as indicator/splash screen while ARB is launching)
   - 20_upstream_r12794__socket_permissions:
       backported security fix
   - 30_upstream_r12814__desktop_keywords:
       backported add keywords to desktop (fixes lintian warning)
   - 40_upstream_r12815__lintian_spelling:
       backported fix for lintian reported spelling errors
   - 50_private_nameservers
       change configuration to put nameservers into users home dirs
       (avoids need for shared writeable directory)
   - 60_use_debian_phyml
       use phyml from debian package for both interfaces in ARB
* debian/rules:
   - create config.makefile from override_dh_configure target
   - use "make tarfile" in override_dh_install
   - remove extra cleaning not needed for ARB 6
   - use "dh_install --list-missing" to avoid missing files
   - added override_dh_fixperms target
* debian/control:
   - added libarb-dev package
   - Depends: added phyml, xdg-utils
   - Suggests: removed phyml
   - fix lintian duplicate-short-description (new descriptions)
* debian/*.install:
   - "unrolled" confusing globbing to select files
   - pick files from debian/tmp
   - moved all config files to /etc/arb
* debian/arb-common.templates: updated
* scripts:
   - removed arb-add-pt-server
   - launch-wrapper: 
     - only add demo.arb to newly created $ARBUSERDATA
     - pass commandline arguments through bin/arb wrapper
   - preinst: removing old PT server index files on upgrade from 5.5*
   - postinst: set setgid on shared PT dir
* rewrote arb.1 manfile
* added file icon for ARB databases
* using upstream arb_tcp.dat

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <cstdio>
2
 
#include <cstdlib>
3
 
#include <cmath>
4
 
#include <cstring>
5
 
 
6
 
#include <iostream>
7
 
 
8
 
#include <arbdb.h>
9
 
#include <arbdbt.h>
10
 
#include <aw_root.hxx>
11
 
#include <aw_device.hxx>
12
 
#include <aw_keysym.hxx>
13
 
#include <aw_window.hxx>
14
 
#include <awt.hxx>
15
 
#include <awt_canvas.hxx>
16
 
#include <awt_nds.hxx>
17
 
#include <aw_preset.hxx>
18
 
#include <aw_awars.hxx>
19
 
 
20
 
#include "awt_tree.hxx"
21
 
#include "awt_dtree.hxx"
22
 
#include "awt_attributes.hxx"
23
 
 
24
 
/***************************
25
 
      class AP_tree
26
 
****************************/
27
 
 
28
 
using namespace AW;
29
 
 
30
 
AW_gc_manager AWT_graphic_tree::init_devices(AW_window *aww, AW_device *device, AWT_canvas* ntw, AW_CL cd2)
31
 
{
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
36
 
                     "#3be",
37
 
 
38
 
                     // Important note :
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)
42
 
 
43
 
                     "Cursor$white",
44
 
                     "Branch remarks$#b6ffb6",
45
 
                     "+-Bootstrap$#53d3ff",    "-B.(limited)$white",
46
 
                     "-GROUP_BRACKETS$#000",
47
 
                     "Marked$#ffe560",
48
 
                     "Some marked$#bb8833",
49
 
                     "Not marked$#622300",
50
 
                     "Zombies etc.$#977a0e",
51
 
 
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",
56
 
                     NULL );
57
 
 
58
 
    return preset_window;
59
 
}
60
 
 
61
 
AP_tree *AWT_graphic_tree::search(AP_tree *root, const char *name)
62
 
{
63
 
    if(!root) return 0;
64
 
    if (root->is_leaf) {
65
 
        if(root->name){
66
 
            if (!strcmp(name,root->name)) {
67
 
                return root;
68
 
            }
69
 
        }
70
 
    }else{
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;
75
 
    }
76
 
    return 0;
77
 
}
78
 
 
79
 
void AWT_graphic_tree::jump(AP_tree *at, const char *name)
80
 
{
81
 
    if (sort_is_list_style(tree_sort)) return;
82
 
 
83
 
    at = search(at,name);
84
 
    if(!at) return;
85
 
    if (tree_sort == AP_TREE_NORMAL) {
86
 
        tree_root_display = tree_root;
87
 
    }else{
88
 
        while (at->father &&
89
 
               at->gr.view_sum<15 &&
90
 
               0 == at->gr.grouped)
91
 
        {
92
 
            at = at->father;
93
 
        }
94
 
        tree_root_display = at;
95
 
    }
96
 
}
97
 
 
98
 
void AWT_graphic_tree::mark_species_in_tree(AP_tree *at, int mark_mode) {
99
 
    /*
100
 
      mode      does
101
 
 
102
 
      0         unmark all
103
 
      1         mark all
104
 
      2         invert all marks
105
 
    */
106
 
 
107
 
    if (!at) return;
108
 
 
109
 
    GB_transaction dummy(tree_static->gb_species_data);
110
 
    if (at->is_leaf) {
111
 
        if(at->gb_node) {       // not a zombie
112
 
            switch (mark_mode) {
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);
117
 
            }
118
 
        }
119
 
    }
120
 
 
121
 
    mark_species_in_tree(at->leftson, mark_mode);
122
 
    mark_species_in_tree(at->rightson, mark_mode);
123
 
}
124
 
 
125
 
void AWT_graphic_tree::mark_species_in_tree_that(AP_tree *at, int mark_mode, int (*condition)(GBDATA*, void*), void *cd) {
126
 
    /*
127
 
      mark_mode does
128
 
 
129
 
      0         unmark all
130
 
      1         mark all
131
 
      2         invert all marks
132
 
 
133
 
      marks are only changed for those species for that condition() != 0
134
 
    */
135
 
 
136
 
    if (!at) return;
137
 
 
138
 
    GB_transaction dummy(tree_static->gb_species_data);
139
 
    if (at->is_leaf) {
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)) {
143
 
                switch (mark_mode) {
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);
148
 
                }
149
 
            }
150
 
        }
151
 
    }
152
 
 
153
 
    mark_species_in_tree_that(at->leftson, mark_mode, condition, cd);
154
 
    mark_species_in_tree_that(at->rightson, mark_mode, condition, cd);
155
 
}
156
 
 
157
 
 
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) {
160
 
    if (!at) return;
161
 
 
162
 
    AP_tree *pa = at->father;
163
 
    if (!pa) return;
164
 
 
165
 
    GB_transaction dummy(tree_static->gb_species_data);
166
 
 
167
 
    if (at == pa->leftson)  mark_species_in_tree(pa->rightson, mark_mode);
168
 
    else mark_species_in_tree(pa->leftson, mark_mode);
169
 
 
170
 
    mark_species_in_rest_of_tree(pa, mark_mode);
171
 
}
172
 
 
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) {
175
 
    if (!at) return;
176
 
 
177
 
    AP_tree *pa = at->father;
178
 
    if (!pa) return;
179
 
 
180
 
    GB_transaction dummy(tree_static->gb_species_data);
181
 
 
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);
184
 
 
185
 
    mark_species_in_rest_of_tree_that(pa, mark_mode, condition, cd);
186
 
}
187
 
 
188
 
bool AWT_graphic_tree::tree_has_marks(AP_tree *at) {
189
 
    if (!at) return false;
190
 
 
191
 
    if (at->is_leaf) {
192
 
        if (!at->gb_node) return false; // zombie
193
 
        int marked = GB_read_flag(at->gb_node);
194
 
        return marked;
195
 
    }
196
 
 
197
 
    return tree_has_marks(at->leftson) || tree_has_marks(at->rightson);
198
 
}
199
 
 
200
 
bool AWT_graphic_tree::rest_tree_has_marks(AP_tree *at) {
201
 
    if (!at) return false;
202
 
 
203
 
    AP_tree *pa = at->father;
204
 
    if (!pa) return false;
205
 
 
206
 
    if (at == pa->leftson) {    // i am the left son
207
 
        return tree_has_marks(pa->rightson) || rest_tree_has_marks(pa);
208
 
    }
209
 
    return tree_has_marks(pa->leftson) || rest_tree_has_marks(pa);
210
 
}
211
 
 
212
 
struct AWT_graphic_tree_group_state {
213
 
    int closed, opened;
214
 
    int closed_terminal, opened_terminal;
215
 
    int closed_with_marked, opened_with_marked;
216
 
    int marked_in_groups, marked_outside_groups;
217
 
 
218
 
    void clear() {
219
 
        closed                = 0;
220
 
        opened                = 0;
221
 
        closed_terminal       = 0;
222
 
        opened_terminal       = 0;
223
 
        closed_with_marked    = 0;
224
 
        opened_with_marked    = 0;
225
 
        marked_in_groups      = 0;
226
 
        marked_outside_groups = 0;
227
 
    }
228
 
 
229
 
    AWT_graphic_tree_group_state() { clear(); }
230
 
 
231
 
    bool has_groups() const { return closed+opened; }
232
 
    int marked() const { return marked_in_groups+marked_outside_groups; }
233
 
 
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; }
238
 
 
239
 
    int next_expand_mode() const {
240
 
        if (closed_with_marked) return 1; // expand marked
241
 
        return 4; // expand all
242
 
    }
243
 
 
244
 
    int next_collapse_mode() const {
245
 
        if (all_terminal_closed()) return 0; // collapse all
246
 
        return 2; // group terminal
247
 
    }
248
 
 
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
253
 
        }
254
 
        if (all_marked_opened()) {
255
 
            if (all_opened()) return 0; // collapse all
256
 
            return 4;           // expand all
257
 
        }
258
 
        if (all_opened()) return 0; // collapse all
259
 
        if (!all_closed()) return 0; // collapse all
260
 
 
261
 
        if (!all_terminal_closed()) return 2; // group terminal
262
 
        if (marked_in_groups) return 1; // all but marked
263
 
        return 4; // expand all
264
 
    }
265
 
 
266
 
    void dump(void) {
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);
271
 
 
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());
274
 
    }
275
 
};
276
 
 
277
 
// start of implementation of class AWT_graphic_tree_group_state:
278
 
 
279
 
// -end- of implementation of class AWT_graphic_tree_group_state.
280
 
 
281
 
void AWT_graphic_tree::detect_group_state(AP_tree *at, AWT_graphic_tree_group_state *state, AP_tree *skip_this_son) {
282
 
    if (!at) return;
283
 
    if (at->is_leaf) {
284
 
        if (at->gb_node && GB_read_flag(at->gb_node)) state->marked_outside_groups++; // count marks
285
 
        return;                 // leave are never grouped
286
 
    }
287
 
 
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);
292
 
 
293
 
        if (at->gr.grouped) {   // a closed group
294
 
            state->closed++;
295
 
            if (!sub_state.has_groups()) state->closed_terminal++;
296
 
            if (sub_state.marked()) state->closed_with_marked++;
297
 
            state->closed += sub_state.opened;
298
 
        }
299
 
        else { // an open group
300
 
            state->opened++;
301
 
            if (!sub_state.has_groups()) state->opened_terminal++;
302
 
            if (sub_state.marked()) state->opened_with_marked++;
303
 
            state->opened += sub_state.opened;
304
 
        }
305
 
 
306
 
        state->marked_in_groups += sub_state.marked();
307
 
 
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;
313
 
    }
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);
317
 
    }
318
 
}
319
 
 
320
 
int AWT_graphic_tree::group_rest_tree(AP_tree *at, int mode, int color_group) {
321
 
    if (!at) return 1;
322
 
 
323
 
    AP_tree *pa = at->father;
324
 
    if (!pa) return 1;
325
 
 
326
 
    if (at == pa->leftson) { // i am the left son
327
 
        group_tree(pa->rightson, mode, color_group);
328
 
    }
329
 
    else {
330
 
        group_tree(pa->leftson, mode, color_group);
331
 
    }
332
 
 
333
 
    group_rest_tree(pa, mode, color_group);
334
 
    return 1; // non-rest is always ungrouped
335
 
}
336
 
 
337
 
int AWT_graphic_tree::group_tree(AP_tree *at, int mode, int color_group)    // run on father !!!
338
 
{
339
 
    /*
340
 
      mode      does group
341
 
 
342
 
      0         all
343
 
      1         all but marked
344
 
      2         all but groups with subgroups
345
 
      4         none (ungroups all)
346
 
      8         all but color_group
347
 
 
348
 
    */
349
 
 
350
 
    if (!at) return 1;
351
 
 
352
 
    GB_transaction dummy(this->tree_static->gb_species_data);
353
 
 
354
 
    if (at->is_leaf) {
355
 
        int ungroup_me = 0;
356
 
 
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
361
 
                    ungroup_me = 1;
362
 
                }
363
 
            }
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
367
 
                    ungroup_me = 1;
368
 
                }
369
 
            }
370
 
        }
371
 
 
372
 
        return ungroup_me;
373
 
    }
374
 
 
375
 
    int flag  = this->group_tree(at->leftson, mode, color_group);
376
 
    flag     += this->group_tree(at->rightson, mode, color_group);
377
 
 
378
 
    at->gr.grouped = 0;
379
 
 
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");
383
 
            if (gn) {
384
 
                if (strlen(GB_read_char_pntr(gn))>0){ // and I have a name
385
 
                    at->gr.grouped     = 1;
386
 
                    if (mode & 2) flag = 1; // do not group non-terminal groups
387
 
                }
388
 
            }
389
 
        }
390
 
    }
391
 
    if (!at->father) this->tree_root->compute_tree(this->tree_static->gb_species_data);
392
 
 
393
 
    return flag;
394
 
}
395
 
 
396
 
 
397
 
 
398
 
int AWT_graphic_tree::resort_tree( int mode, struct AP_tree *at ) // run on father !!!
399
 
{
400
 
    /* mode
401
 
 
402
 
       0    to top
403
 
       1    to bottom
404
 
       2    center (to top)
405
 
       3    center (to bottom; don't use this - it's used internal)
406
 
 
407
 
       post-condition: leafname contains alphabetically "smallest" name of subtree
408
 
 
409
 
    */
410
 
    static const char *leafname;
411
 
 
412
 
    if (!at) {
413
 
        GB_transaction dummy(this->gb_main);
414
 
        at = this->tree_root;
415
 
        if(!at) return 0;
416
 
        at->arb_tree_set_leafsum_viewsum();
417
 
 
418
 
        this->resort_tree(mode,at);
419
 
        at->compute_tree(this->gb_main);
420
 
        return 0;
421
 
    }
422
 
 
423
 
    if (at->is_leaf) {
424
 
        leafname = at->name;
425
 
        return 1;
426
 
    }
427
 
    int leftsize = at->leftson->gr.leave_sum;
428
 
    int rightsize = at->rightson->gr.leave_sum;
429
 
 
430
 
    if ( (mode &1) == 0 ) { // to top
431
 
        if (rightsize >leftsize ) {
432
 
            at->swap_sons();
433
 
        }
434
 
    }else{
435
 
        if (rightsize < leftsize ) {
436
 
            at->swap_sons();
437
 
        }
438
 
    }
439
 
 
440
 
    int lmode = mode;
441
 
    int rmode = mode;
442
 
    if ( (mode & 2) == 2){
443
 
        lmode = 2;
444
 
        rmode = 3;
445
 
    }
446
 
 
447
 
    resort_tree(lmode,at->leftson);
448
 
    gb_assert(leafname);
449
 
    const char *leftleafname = leafname;
450
 
 
451
 
    resort_tree(rmode,at->rightson);
452
 
    gb_assert(leafname);
453
 
    const char *rightleafname = leafname;
454
 
 
455
 
    gb_assert(leftleafname && rightleafname);
456
 
 
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
464
 
                at->swap_sons();
465
 
            }
466
 
        }
467
 
    }else{
468
 
        if (leftleafname) leafname = leftleafname;
469
 
        else leafname = rightleafname;
470
 
    }
471
 
 
472
 
    return 0;
473
 
}
474
 
 
475
 
 
476
 
void AWT_graphic_tree::rot_show_line(AW_device *device)
477
 
{
478
 
    double             sx, sy;
479
 
    double             x, y;
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);
486
 
}
487
 
 
488
 
void AWT_graphic_tree::rot_show_triangle(AW_device *device)
489
 
{
490
 
    double   w;
491
 
    double   len;
492
 
    double   sx, sy;
493
 
    double   x1, y1, x2, y2;
494
 
    AP_tree *at;
495
 
    double   scale = 1.0;
496
 
 
497
 
    if (tree_sort == AP_TREE_IRS) scale = irs_tree_ruler_scale_factor;
498
 
 
499
 
    at = this->rot_at;
500
 
 
501
 
    if (!at || !at->father)
502
 
        return;
503
 
 
504
 
    sx = this->old_rot_cl.x0;
505
 
    sy = this->old_rot_cl.y0;
506
 
 
507
 
    if (at == at->father->leftson) len = at->father->leftlen;
508
 
    else len = at->father->rightlen;
509
 
 
510
 
    len *= scale;
511
 
 
512
 
    w = this->rot_orientation;  x1 = this->old_rot_cl.x0 + cos(w) * len;
513
 
    y1 = this->old_rot_cl.y0 + sin(w) * len;
514
 
 
515
 
    int gc = this->drag_gc;
516
 
 
517
 
    device->line(gc, sx, sy, x1, y1, AWT_F_ALL, 0, 0);
518
 
 
519
 
 
520
 
    if (!at->is_leaf) {
521
 
        sx = x1; sy = y1;
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;
529
 
 
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);
533
 
 
534
 
    }
535
 
 
536
 
 
537
 
}
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;
541
 
 
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 ?
545
 
 
546
 
    if (radius < 0) return;     // skip too small circles
547
 
 
548
 
    // Note : radius goes against infinite, if bootstrap values go against zero
549
 
    //        For this reason we do some limitaion here:
550
 
 
551
 
    // printf("bootstrap=%i -> radius=%f\n", atoi(bootstrap), radius);
552
 
 
553
 
    // was 0.06
554
 
// #define BOOTSTRAP_RADIUS_LIMIT (len*2)
555
 
// #define BOOTSTRAP_RADIUS_LIMIT 2.0
556
 
#define BOOTSTRAP_RADIUS_LIMIT max_radius
557
 
 
558
 
    int gc = AWT_GC_BOOTSTRAP;
559
 
 
560
 
    if (radius > BOOTSTRAP_RADIUS_LIMIT) {
561
 
        radius = BOOTSTRAP_RADIUS_LIMIT;
562
 
        gc     = AWT_GC_BOOTSTRAP_LIMITED;
563
 
    }
564
 
 
565
 
    double     radiusx = radius * len * zoom_factor; // multiply with length of branch (and zoomfactor)
566
 
    double     radiusy;
567
 
    if (elipsoid) {
568
 
        radiusy = elip_ysize * zoom_factor;
569
 
        if (radiusy > radiusx) radiusy = radiusx;
570
 
    }
571
 
    else {
572
 
        radiusy = radiusx;
573
 
    }
574
 
 
575
 
    device->circle(gc, false, x, y, radiusx, radiusy, filter, cd1, (AW_CL)cd2);
576
 
}
577
 
 
578
 
double comp_rot_orientation(AW_clicked_line *cl)
579
 
{
580
 
    return atan2(cl->y1 - cl->y0, cl->x1 - cl->x0);
581
 
}
582
 
 
583
 
double comp_rot_spread(AP_tree *at, AWT_graphic_tree *ntw)
584
 
{
585
 
    double zw = 0;
586
 
    AP_tree *bt;
587
 
 
588
 
    if(!at) return 0;
589
 
 
590
 
    zw = 1.0;
591
 
 
592
 
    for(bt=at; bt->father && (bt!=ntw->tree_root_display); bt=bt->father){
593
 
        zw *= bt->gr.spread;
594
 
    }
595
 
 
596
 
    zw *= bt->gr.spread;
597
 
    zw *= (double)at->gr.view_sum / (double)bt->gr.view_sum;
598
 
 
599
 
    switch (ntw->tree_sort) {
600
 
        case AP_TREE_NORMAL:
601
 
            zw *= 0.5*M_PI;
602
 
            break;
603
 
        case AP_TREE_IRS:
604
 
            zw *= 0.5*M_PI * ntw->get_irs_tree_ruler_scale_factor();
605
 
            break;
606
 
        case AP_TREE_RADIAL:
607
 
            zw *= 2*M_PI;
608
 
            break;
609
 
        default:
610
 
            awt_assert(0);
611
 
    }
612
 
 
613
 
    return zw;
614
 
}
615
 
 
616
 
void reset_spread(AP_tree *at)
617
 
{
618
 
    if(!at) return;
619
 
    at->gr.spread =  1.0;
620
 
    reset_spread(at->leftson);
621
 
    reset_spread(at->rightson);
622
 
}
623
 
 
624
 
void reset_rotation(AP_tree *at)
625
 
{
626
 
    if(!at) return;
627
 
    at->gr.left_angle = 0.0;
628
 
    at->gr.right_angle = 0.0;
629
 
    reset_rotation(at->leftson);
630
 
    reset_rotation(at->rightson);
631
 
}
632
 
 
633
 
void reset_line_width(AP_tree *at)
634
 
{
635
 
    if(!at) return;
636
 
    at->gr.left_linewidth =  0;
637
 
    at->gr.right_linewidth =  0;
638
 
    reset_line_width(at->leftson);
639
 
    reset_line_width(at->rightson);
640
 
}
641
 
 
642
 
char *AWT_graphic_tree_root_changed(void *cd, AP_tree *old, AP_tree *newroot)
643
 
{
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;
649
 
    return 0;
650
 
}
651
 
char *AWT_graphic_tree_node_deleted(void *cd, AP_tree *old)
652
 
{
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) {
656
 
        agt->tree_root = 0;
657
 
        agt->tree_root_display = 0;
658
 
    }
659
 
    return 0;
660
 
}
661
 
void AWT_graphic_tree::toggle_group(AP_tree * at)
662
 
{
663
 
    GB_ERROR error = NULL;
664
 
    
665
 
    if (at->gb_node) {                                            // existing group
666
 
        char *gname = GBT_read_string(at->gb_node, "group_name");
667
 
        if (gname) {
668
 
            const char *msg = GBS_global_string("What to do with group '%s'?",gname);
669
 
 
670
 
            switch (aw_question(msg, "Rename,Destroy,Cancel")) {
671
 
                case 0: {                                                    // rename
672
 
                    char *new_gname = aw_input("Rename group", "Change group name:", at->name);
673
 
                    if (new_gname) {
674
 
                        freeset(at->name, new_gname);
675
 
                        error = GBT_write_string(at->gb_node, "group_name", new_gname);
676
 
                    }
677
 
                    break;
678
 
                }
679
 
 
680
 
                case 1:                                      // destroy
681
 
                    at->gr.grouped = 0;
682
 
                    at->name       = 0;
683
 
                    error          = GB_delete(at->gb_node);
684
 
                    at->gb_node    = 0;
685
 
                    break;
686
 
 
687
 
                case 2:         // cancel
688
 
                    break;
689
 
            }
690
 
 
691
 
            free(gname);
692
 
        }
693
 
    }
694
 
    else {
695
 
        error = create_group(at); // create new group
696
 
        if (!error && at->name) at->gr.grouped = 1;
697
 
    }
698
 
 
699
 
    if (error) aw_message(error);
700
 
}
701
 
 
702
 
GB_ERROR AWT_graphic_tree::create_group(AP_tree * at) {
703
 
    GB_ERROR error = NULL;
704
 
    if (!at->name) {
705
 
        char *gname = aw_input("Enter Name of Group");
706
 
        if (gname) {
707
 
            GBDATA         *gb_mainT = GB_get_root(tree_static->gb_tree);
708
 
            GB_transaction  ta(gb_mainT);
709
 
 
710
 
            if (!at->gb_node) {
711
 
                at->gb_node   = GB_create_container(this->tree_static->gb_tree, "node");
712
 
                if (!at->gb_node) error = GB_await_error();
713
 
                else {
714
 
                    error = GBT_write_int(at->gb_node, "id", 0);
715
 
                    this->exports.save = !error;
716
 
                }
717
 
            }
718
 
 
719
 
            if (!error) {
720
 
                GBDATA *gb_name     = GB_search(at->gb_node, "group_name", GB_STRING);
721
 
                if (!gb_name) error = GB_await_error();
722
 
                else {
723
 
                    error = GBT_write_group_name(gb_name, gname);
724
 
                    if (!error) at->name = gname;
725
 
                }
726
 
            }
727
 
            error = ta.close(error);
728
 
        }
729
 
    }
730
 
    else if (!at->gb_node) {
731
 
        at->gb_node = GB_create_container(this->tree_static->gb_tree, "node");
732
 
 
733
 
        if (!at->gb_node) error = GB_await_error();
734
 
        else {
735
 
            error = GBT_write_int(at->gb_node, "id", 0);
736
 
            this->exports.save = !error;
737
 
        }
738
 
    }
739
 
 
740
 
    return error;
741
 
}
742
 
 
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)
745
 
{
746
 
    bool update_timer = true;
747
 
    bool calc_color   = true;
748
 
    bool refresh      = true;
749
 
    bool Save         = false;
750
 
    bool resize       = false;
751
 
    bool compute      = false;
752
 
 
753
 
    if (key_modifier != AW_KEYMODE_NONE) return;
754
 
    if (key_char == 0) return;
755
 
 
756
 
#if defined(DEBUG)
757
 
    printf("key_char=%i (=%c)\n", int(key_char), key_char);
758
 
#endif // DEBUG
759
 
 
760
 
    // ----------------------------------------
761
 
    //      commands independent of tree :
762
 
    // ----------------------------------------
763
 
 
764
 
    bool global_key = true;
765
 
    switch (key_char) {
766
 
        case 9:  {    // Ctrl-i = invert all
767
 
            GBT_mark_all(gb_main, 2);
768
 
            break;
769
 
        }
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);
773
 
            break;
774
 
        }
775
 
        default: {
776
 
            global_key = false;
777
 
            break;
778
 
        }
779
 
    }
780
 
 
781
 
    if (!global_key && tree_proto) {
782
 
 
783
 
        AP_tree    *at   = 0;
784
 
        const char *what = 0;
785
 
 
786
 
        if (ct->exists) {
787
 
            at   = (AP_tree*)ct->client_data1;
788
 
            what = (char*)ct->client_data2;
789
 
        }
790
 
        else if (cl->exists) {
791
 
            at   = (AP_tree*)cl->client_data1;
792
 
            what = (char*)cl->client_data2;
793
 
        }
794
 
 
795
 
#if defined(DEBUG)
796
 
        printf("what='%s' at=%p\n", what, at);
797
 
#endif // DEBUG
798
 
 
799
 
        if (what && strcmp(what, "species") == 0) {
800
 
            GBDATA *gb_species = 0;
801
 
            if (ct->exists) {
802
 
                gb_species = (GBDATA *)ct->client_data1;
803
 
            }
804
 
            else {
805
 
                awt_assert(0);
806
 
            }
807
 
 
808
 
            // ------------------------------------
809
 
            //      commands in species list :
810
 
            // ------------------------------------
811
 
 
812
 
            switch (key_char) {
813
 
                case 'i':
814
 
                case 'm':  {    // i/m = mark/unmark species
815
 
                    GB_write_flag(gb_species, 1-GB_read_flag(gb_species));
816
 
                    break;
817
 
                }
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);
822
 
                    break;
823
 
                }
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
829
 
                    break;
830
 
                }
831
 
            }
832
 
        }
833
 
        else {
834
 
            if (!at) {
835
 
                // many commands work on whole tree if mouse does not point to subtree
836
 
                at = tree_root;
837
 
            }
838
 
 
839
 
            // -------------------------------------
840
 
            //      command working with tree :
841
 
            // -------------------------------------
842
 
 
843
 
            if (at) {
844
 
                switch (key_char) {
845
 
                    case 'm':  {    // m = mark/unmark (sub)tree
846
 
                        mark_species_in_tree(at, !tree_has_marks(at));
847
 
                        break;
848
 
                    }
849
 
                    case 'M':  {    // M = mark/unmark all but (sub)tree
850
 
                        mark_species_in_rest_of_tree(at, !rest_tree_has_marks(at));
851
 
                        break;
852
 
                    }
853
 
 
854
 
                    case 'i':  {    // i = invert (sub)tree
855
 
                        mark_species_in_tree(at, 2);
856
 
                        break;
857
 
                    }
858
 
                    case 'I':  {    // I = invert all but (sub)tree
859
 
                        mark_species_in_rest_of_tree(at, 2);
860
 
                        break;
861
 
                    }
862
 
                    case 'c':
863
 
                    case 'x':  {
864
 
                        AWT_graphic_tree_group_state state;
865
 
                        detect_group_state(at, &state, 0);
866
 
 
867
 
                        if (!state.has_groups()) { // somewhere inside group
868
 
                        do_parent:
869
 
                            at = at->father;
870
 
                            while (at) {
871
 
                                if (at->gb_node) break;
872
 
                                at = at->father;
873
 
                            }
874
 
 
875
 
                            if (at) {
876
 
                                state.clear();
877
 
                                detect_group_state(at, &state, 0);
878
 
                            }
879
 
                        }
880
 
 
881
 
                        if (at) {
882
 
                            int next_group_mode;
883
 
 
884
 
                            if (key_char == 'x')  { // expand
885
 
                                next_group_mode = state.next_expand_mode();
886
 
                            }
887
 
                            else { // collapse
888
 
                                if (state.all_closed()) goto do_parent;
889
 
                                next_group_mode = state.next_collapse_mode();
890
 
                            }
891
 
 
892
 
                            /*int result = */
893
 
                            group_tree(at, next_group_mode, 0);
894
 
 
895
 
                            Save    = true;
896
 
                            resize  = true;
897
 
                            compute = true;
898
 
                        }
899
 
                        break;
900
 
                    }
901
 
                    case 'C':
902
 
                    case 'X':  {
903
 
                        AP_tree *root_node                  = at;
904
 
                        while (root_node->father) root_node = root_node->father; // search father
905
 
 
906
 
                        awt_assert(root_node);
907
 
 
908
 
                        AWT_graphic_tree_group_state state;
909
 
                        detect_group_state(root_node, &state, at);
910
 
 
911
 
                        int next_group_mode;
912
 
                        if (key_char == 'X')  { // expand
913
 
                            next_group_mode = state.next_expand_mode();
914
 
                        }
915
 
                        else { // collapse
916
 
                            next_group_mode = state.next_collapse_mode();
917
 
                        }
918
 
 
919
 
                        /*int result = */
920
 
                        group_rest_tree(at, next_group_mode, 0);
921
 
 
922
 
                        Save    = true;
923
 
                        resize  = true;
924
 
                        compute = true;
925
 
 
926
 
 
927
 
                        break;
928
 
                    }
929
 
                }
930
 
            }
931
 
        }
932
 
    }
933
 
 
934
 
    if (Save) {
935
 
        update_timer = false;
936
 
        exports.save = 1;
937
 
    }
938
 
 
939
 
    if (compute && tree_root) {
940
 
        tree_root->compute_tree(gb_main);
941
 
        resize     = true;
942
 
        calc_color = false;
943
 
    }
944
 
 
945
 
    if (update_timer && tree_static) {
946
 
        tree_static->update_timers(); // do not reload the tree
947
 
    }
948
 
 
949
 
    if (resize) {
950
 
        exports.resize = 1;
951
 
        refresh        = true;
952
 
    }
953
 
 
954
 
    if (calc_color && tree_root) {
955
 
        tree_root->calc_color();
956
 
        refresh = true;
957
 
    }
958
 
    if (refresh) {
959
 
        exports.refresh = 1;
960
 
    }
961
 
}
962
 
 
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) {
966
 
        drl = min_length;
967
 
    }
968
 
    return drl;
969
 
}
970
 
 
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)
975
 
{
976
 
    static int rot_drag_flag, bl_drag_flag;
977
 
 
978
 
    if (type == AW_Keyboard_Press) {
979
 
        return key_command(cmd, key_modifier, key_char, x, y, cl, ct);
980
 
    }
981
 
 
982
 
    AP_tree *at;
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;
986
 
        bool    select  = false;
987
 
        bool    refresh = false;
988
 
 
989
 
        switch (cmd) {
990
 
            case AWT_MODE_MARK:  {
991
 
                if (type == AW_Mouse_Press) {
992
 
                    switch (button) {
993
 
                        case AWT_M_LEFT:
994
 
                            GB_write_flag(gbd, 1);
995
 
                            refresh = true;
996
 
                            select  = true;
997
 
                            break;
998
 
                        case AWT_M_RIGHT:
999
 
                            GB_write_flag(gbd, 0);
1000
 
                            refresh = true;
1001
 
                            break;
1002
 
                    }
1003
 
                }
1004
 
                break;
1005
 
            }
1006
 
            default :  { // all other modes just select a species :
1007
 
                select = true;
1008
 
                break;
1009
 
            }
1010
 
        }
1011
 
 
1012
 
        if (select && type == AW_Mouse_Press) AD_map_viewer(gbd);
1013
 
        if (refresh) this->exports.refresh = 1;
1014
 
 
1015
 
        return;
1016
 
    }
1017
 
 
1018
 
    if (!this->tree_static) return;     // no tree -> no commands
1019
 
 
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")))
1024
 
    {
1025
 
        const char *tree_awar;
1026
 
        char awar[256];
1027
 
        float h;
1028
 
        switch(cmd){
1029
 
            case AWT_MODE_SELECT:
1030
 
            case AWT_MODE_ROT:
1031
 
            case AWT_MODE_SPREAD:
1032
 
            case AWT_MODE_SWAP:
1033
 
            case AWT_MODE_SETROOT:
1034
 
            case AWT_MODE_LENGTH:
1035
 
            case AWT_MODE_MOVE: // Move Ruler text
1036
 
                switch(type){
1037
 
                    case AW_Mouse_Press:
1038
 
                        rot_ct          = *ct;
1039
 
                        rot_ct.textArea.moveTo(Position(x, y));
1040
 
                        break;
1041
 
                    case AW_Mouse_Drag: {
1042
 
                        double          scale = device->get_scale();
1043
 
                        const Position &start = rot_ct.textArea.start();
1044
 
 
1045
 
                        tree_awar    = show_ruler(device, drag_gc);
1046
 
                        sprintf(awar,"ruler/%s/text_x", tree_awar);
1047
 
 
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);
1055
 
                        break;
1056
 
                    }
1057
 
                    case AW_Mouse_Release:
1058
 
                        rot_ct.exists = false;
1059
 
                        exports.resize = 1;
1060
 
                        break;
1061
 
                    default: break;
1062
 
                }
1063
 
                return;
1064
 
            default:    break;
1065
 
        }
1066
 
    }
1067
 
 
1068
 
 
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")))
1073
 
    {
1074
 
        const char *tree_awar;
1075
 
        char awar[256];
1076
 
        float h;
1077
 
        switch(cmd){
1078
 
            case AWT_MODE_ROT:
1079
 
            case AWT_MODE_SPREAD:
1080
 
            case AWT_MODE_SWAP:
1081
 
            case AWT_MODE_SETROOT:
1082
 
            case AWT_MODE_MOVE: // Move Ruler
1083
 
                switch(type){
1084
 
                    case AW_Mouse_Press:
1085
 
                        rot_cl = *cl;
1086
 
                        rot_cl.x0 = x;
1087
 
                        rot_cl.y0 = y;
1088
 
                        break;
1089
 
                    case AW_Mouse_Drag:
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);
1097
 
 
1098
 
                        rot_cl.x0 = x;
1099
 
                        rot_cl.y0 = y;
1100
 
                        show_ruler(device, this->drag_gc);
1101
 
                        break;
1102
 
                    case AW_Mouse_Release:
1103
 
                        rot_cl.exists = false;
1104
 
                        this->exports.resize = 1;
1105
 
                        break;
1106
 
                    default:
1107
 
                        break;
1108
 
                }
1109
 
                break;
1110
 
 
1111
 
 
1112
 
            case AWT_MODE_LENGTH:
1113
 
                switch(type){   // resize Ruler
1114
 
                    case AW_Mouse_Press:
1115
 
                        rot_cl = *cl;
1116
 
                        rot_cl.x0 = x;
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);
1123
 
                        }
1124
 
                        break;
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));
1130
 
                        }
1131
 
                        tree_awar = show_ruler(device, this->drag_gc);
1132
 
 
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;
1136
 
                        }
1137
 
                        else {
1138
 
                            h += (x - rot_cl.x0)/device->get_scale();
1139
 
                        }
1140
 
                        if (h<0.01) h = 0.01;
1141
 
 
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);
1148
 
                        }
1149
 
                        else {
1150
 
                            GBT_write_float(this->tree_static->gb_tree, awar, h);
1151
 
                            show_ruler(device, this->drag_gc);
1152
 
                        }
1153
 
 
1154
 
                        rot_cl.x0 = x;
1155
 
                        break;
1156
 
                    }
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));
1164
 
                        }
1165
 
                        break;
1166
 
                    default:
1167
 
                        break;
1168
 
                }
1169
 
                break;
1170
 
            case AWT_MODE_LINE:
1171
 
                if (type == AW_Mouse_Press) {
1172
 
                    long i;
1173
 
                    sprintf(awar,"ruler/ruler_width");
1174
 
                    i = *GBT_readOrCreate_int(this->tree_static->gb_tree, awar , 0);
1175
 
                    switch(button){
1176
 
                        case AWT_M_LEFT:
1177
 
                            i --;
1178
 
                            if (i<0) i= 0;
1179
 
                            else{
1180
 
                                GBT_write_int(this->tree_static->gb_tree, awar,i);
1181
 
                                this->exports.refresh = 1;
1182
 
                            }
1183
 
                            break;
1184
 
                        case AWT_M_RIGHT:
1185
 
                            i++;
1186
 
                            GBT_write_int(this->tree_static->gb_tree, awar,i);
1187
 
                            show_ruler(device, AWT_GC_CURSOR);
1188
 
                            break;
1189
 
                        default: break;
1190
 
                    }
1191
 
                }
1192
 
                break;
1193
 
            default:    break;
1194
 
        }
1195
 
        return;
1196
 
    }
1197
 
 
1198
 
    switch(cmd) {
1199
 
        case AWT_MODE_MOVE:             // two point commands !!!!!
1200
 
            if(button==AWT_M_MIDDLE){
1201
 
                break;
1202
 
            }
1203
 
            switch(type){
1204
 
                case AW_Mouse_Press:
1205
 
                    if( !(cl && cl->exists) ){
1206
 
                        break;
1207
 
                    }
1208
 
 
1209
 
                    /*** check security level @@@ ***/
1210
 
                    at = (AP_tree *)cl->client_data1;
1211
 
                    if(at && at->father){
1212
 
                        bl_drag_flag = 1;
1213
 
                        this->rot_at = at;
1214
 
                        this->rot_cl = *cl;
1215
 
                        this->old_rot_cl = *cl;
1216
 
                    }
1217
 
                    break;
1218
 
 
1219
 
                case AW_Mouse_Drag:
1220
 
                    if( bl_drag_flag && this->rot_at && this->rot_at->father){
1221
 
                        this->rot_show_line(device);
1222
 
                        if (cl->exists) {
1223
 
                            this->rot_cl = *cl;
1224
 
                        }else{
1225
 
                            rot_cl = old_rot_cl;
1226
 
                        }
1227
 
                        this->rot_show_line(device);
1228
 
                    }
1229
 
                    break;
1230
 
                case AW_Mouse_Release:
1231
 
                    if( bl_drag_flag && this->rot_at && this->rot_at->father){
1232
 
                        this->rot_show_line(device);
1233
 
                        AP_tree *dest= 0;
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");
1238
 
                            break;
1239
 
                        }
1240
 
                        if (source == dest) {
1241
 
                            aw_message("Please drag mouse from source to destination");
1242
 
                            break;
1243
 
                        }
1244
 
 
1245
 
                        GB_ERROR error;
1246
 
                        switch(button){
1247
 
                            case AWT_M_LEFT:
1248
 
                                error = source->cantMoveTo(dest);
1249
 
                                if (!error) source->moveTo(dest,cl->length);
1250
 
                                break;
1251
 
                                
1252
 
                            case AWT_M_RIGHT:
1253
 
                                error = source->move_group_info(dest);
1254
 
                                break;
1255
 
                            default:
1256
 
                                error = "????? 45338";
1257
 
                        }
1258
 
 
1259
 
                        if (error){
1260
 
                            aw_message(error);
1261
 
                        }else{
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);
1267
 
                        }
1268
 
                    }
1269
 
                    break;
1270
 
                default:
1271
 
                    break;
1272
 
            }
1273
 
            break;
1274
 
 
1275
 
 
1276
 
        case AWT_MODE_LENGTH:
1277
 
            if (button == AWT_M_MIDDLE) {
1278
 
                break;
1279
 
            }
1280
 
            switch(type){
1281
 
                case AW_Mouse_Press:
1282
 
                    if( cl && cl->exists ){
1283
 
                        at = (AP_tree *)cl->client_data1;
1284
 
                        if (!at) break;
1285
 
                        bl_drag_flag = 1;
1286
 
                        this->rot_at = at;
1287
 
                        this->rot_cl = *cl;
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);
1291
 
 
1292
 
                        this->rot_orientation = comp_rot_orientation(&rot_cl);
1293
 
                        this->rot_spread      = comp_rot_spread(at, this);
1294
 
#if defined(DEBUG)
1295
 
                        printf("rot_spread=%f\n", rot_spread);
1296
 
#endif // DEBUG
1297
 
                        rot_show_triangle(device);
1298
 
                    }
1299
 
                    break;
1300
 
 
1301
 
                case AW_Mouse_Drag:
1302
 
                    if( bl_drag_flag && this->rot_at && this->rot_at->father){
1303
 
                        double len, ex, ey, scale;
1304
 
 
1305
 
                        rot_show_triangle(device);
1306
 
 
1307
 
                        if (rot_at == rot_at->father->leftson){
1308
 
                            len = rot_at->father->leftlen;
1309
 
                        }else{
1310
 
                            len = rot_at->father->rightlen;
1311
 
                        }
1312
 
 
1313
 
                        ex = x-rot_cl.x0;
1314
 
                        ey = y-rot_cl.y0;
1315
 
 
1316
 
                        len = ex * cos(this->rot_orientation) +
1317
 
                            ey * sin(this->rot_orientation);
1318
 
 
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);
1321
 
                        }
1322
 
                        else if (len<0.0) {
1323
 
                            len = 0.0;
1324
 
                        }
1325
 
 
1326
 
                        scale = device->get_scale();
1327
 
                        if (tree_sort == AP_TREE_IRS) {
1328
 
                            scale *= irs_tree_ruler_scale_factor;
1329
 
                        }
1330
 
                        len = len/scale;
1331
 
 
1332
 
                        if (rot_at == rot_at->father->leftson) {
1333
 
                            rot_at->father->leftlen = len;
1334
 
                        }
1335
 
                        else {
1336
 
                            rot_at->father->rightlen = len;
1337
 
                        }
1338
 
 
1339
 
                        rot_show_triangle(device);
1340
 
                    }
1341
 
                    break;
1342
 
 
1343
 
                case AW_Mouse_Release:
1344
 
                    this->exports.refresh = 1;
1345
 
                    this->exports.save = 1;
1346
 
                    rot_drag_flag = 0;
1347
 
                    this->tree_root->compute_tree(gb_main);
1348
 
                    break;
1349
 
                default:
1350
 
                    break;
1351
 
            }
1352
 
            break;
1353
 
 
1354
 
        case AWT_MODE_ROT:
1355
 
            if(button!=AWT_M_LEFT){
1356
 
                break;
1357
 
            }
1358
 
            switch(type){
1359
 
                case AW_Mouse_Press:
1360
 
                    if( cl && cl->exists ){
1361
 
                        at = (AP_tree *)cl->client_data1;
1362
 
                        if (!at) break;
1363
 
                        rot_drag_flag = 1;
1364
 
                        this->rot_at = at;
1365
 
                        this->rot_cl = *cl;
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);
1369
 
 
1370
 
                        this->rot_orientation = comp_rot_orientation(&rot_cl);
1371
 
                        this->rot_spread = comp_rot_spread(at, this);
1372
 
                        rot_show_triangle(device);
1373
 
                    }
1374
 
                    break;
1375
 
 
1376
 
                case AW_Mouse_Drag:
1377
 
                    if( rot_drag_flag && this->rot_at && this->rot_at->father){
1378
 
                        double new_a;
1379
 
 
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;
1388
 
                            }
1389
 
                        }else{
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;
1393
 
                            }
1394
 
                        }
1395
 
                        rot_show_triangle(device);
1396
 
                    }
1397
 
                    break;
1398
 
 
1399
 
                case AW_Mouse_Release:
1400
 
                    this->exports.refresh = 1;
1401
 
                    this->exports.save = 1;
1402
 
                    rot_drag_flag = 0;
1403
 
                    break;
1404
 
                default:    break;
1405
 
            }
1406
 
 
1407
 
            break;
1408
 
 
1409
 
        case AWT_MODE_LZOOM:
1410
 
            if(type==AW_Mouse_Press){
1411
 
                switch(button){
1412
 
                    case AWT_M_LEFT:
1413
 
                        if(cl->exists){
1414
 
                            at = (AP_tree *)cl->client_data1;
1415
 
                            if (!at) break;
1416
 
                            this->tree_root_display = at;
1417
 
                            this->exports.zoom_reset = 1;
1418
 
                            this->exports.refresh = 1;
1419
 
                        }
1420
 
                        break;
1421
 
                    case AWT_M_RIGHT:
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;
1427
 
                        }
1428
 
                        break;
1429
 
                }
1430
 
                this->tree_root->compute_tree(gb_main);
1431
 
            } /* if type */
1432
 
            break;
1433
 
 
1434
 
        case AWT_MODE_RESET:
1435
 
            if(type==AW_Mouse_Press){
1436
 
                switch(button){
1437
 
                    case AWT_M_LEFT:
1438
 
                        /** reset rotation **/
1439
 
                        if(cl->exists){
1440
 
                            at = (AP_tree *)cl->client_data1;
1441
 
                            if (!at) break;
1442
 
                            reset_rotation(at);
1443
 
                            this->exports.save = 1;
1444
 
                            this->exports.refresh = 1;
1445
 
                        }
1446
 
                        break;
1447
 
                    case AWT_M_MIDDLE:
1448
 
                        /** reset spread **/
1449
 
                        if(cl->exists){
1450
 
                            at = (AP_tree *)cl->client_data1;
1451
 
                            if (!at) break;
1452
 
                            reset_spread(at);
1453
 
                            this->exports.save = 1;
1454
 
                            this->exports.refresh = 1;
1455
 
                        }
1456
 
                        break;
1457
 
                    case AWT_M_RIGHT:
1458
 
                        /** reset linewidth **/
1459
 
                        if(cl->exists){
1460
 
                            at = (AP_tree *)cl->client_data1;
1461
 
                            if (!at) break;
1462
 
 
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;
1467
 
                            }
1468
 
                            this->exports.save = 1;
1469
 
                            this->exports.refresh = 1;
1470
 
                        }
1471
 
                        break;
1472
 
                }
1473
 
                this->tree_root->compute_tree(gb_main);
1474
 
            } /* if press */
1475
 
            break;
1476
 
 
1477
 
        case AWT_MODE_LINE:
1478
 
            if(type==AW_Mouse_Press){
1479
 
                switch(button){
1480
 
                    case AWT_M_LEFT:
1481
 
                        if(cl->exists){
1482
 
                            at = (AP_tree *)cl->client_data1;
1483
 
                            if (!at) break;
1484
 
                            if(at->father){
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;
1488
 
                                }
1489
 
                                else {
1490
 
                                    at->father->gr.right_linewidth-=1;
1491
 
                                    if(at->father->gr.right_linewidth<0) at->father->gr.right_linewidth=0;
1492
 
                                }
1493
 
                                this->exports.save = 1;
1494
 
                                this->exports.refresh = 1;
1495
 
                            }
1496
 
 
1497
 
                        }
1498
 
                        break;
1499
 
                    case AWT_M_RIGHT:
1500
 
                        if(cl->exists){
1501
 
                            at = (AP_tree *)cl->client_data1;
1502
 
                            if (!at) break;
1503
 
                            if(at->father){
1504
 
                                if(at->father->leftson == at){
1505
 
                                    at->father->gr.left_linewidth+=1;
1506
 
                                }else{
1507
 
                                    at->father->gr.right_linewidth+=1;
1508
 
                                }
1509
 
                                this->exports.save = 1;
1510
 
                                this->exports.refresh = 1;
1511
 
                            }
1512
 
#if defined(DEBUG)
1513
 
                            printf("key_modifier=%i\n", key_modifier);
1514
 
#endif // DEBUG
1515
 
                        }
1516
 
                        break;
1517
 
                } /* switch button */
1518
 
            } /* if type */
1519
 
            break;
1520
 
 
1521
 
        case AWT_MODE_SPREAD:
1522
 
            if(type==AW_Mouse_Press){
1523
 
                switch(button){
1524
 
                    case AWT_M_LEFT:
1525
 
                        if(cl->exists){
1526
 
                            at = (AP_tree *)cl->client_data1;
1527
 
                            if (!at) break;
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;
1532
 
                        }
1533
 
                        break;
1534
 
                    case AWT_M_RIGHT:
1535
 
                        if(cl->exists){
1536
 
                            at = (AP_tree *)cl->client_data1;
1537
 
                            if (!at) break;
1538
 
                            at->gr.spread += PH_CLICK_SPREAD;
1539
 
                            this->exports.refresh = 1;
1540
 
                            this->exports.save = 1;
1541
 
                        }
1542
 
                        break;
1543
 
                }
1544
 
            } /* if type */
1545
 
            break;
1546
 
 
1547
 
    act_like_group:
1548
 
        case AWT_MODE_GROUP:
1549
 
            if(type==AW_Mouse_Press){
1550
 
                if(cl->exists){
1551
 
                    at = (AP_tree *)cl->client_data1;
1552
 
                    if (!at) break;
1553
 
                }else break;
1554
 
 
1555
 
                switch(button){
1556
 
                    case AWT_M_LEFT:
1557
 
                        if ( (!at->gr.grouped) && (!at->name)) {
1558
 
                            break; // not grouped and no name
1559
 
                        }
1560
 
 
1561
 
                        if (at->is_leaf) break; // don't touch zombies
1562
 
 
1563
 
                        if (this->tree_static->gb_tree) {
1564
 
                            GB_ERROR error = this->create_group(at);
1565
 
                            if (error) aw_message(error);
1566
 
                        }
1567
 
                        if (at->name) {
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);
1573
 
                        }
1574
 
                        break;
1575
 
                    case AWT_M_RIGHT:
1576
 
                        if (this->tree_static->gb_tree) {
1577
 
                            this->toggle_group(at);
1578
 
                        }
1579
 
                        this->exports.refresh = 1;
1580
 
                        this->exports.save = 1;
1581
 
                        this->exports.resize = 1;
1582
 
                        this->tree_root->compute_tree(gb_main);
1583
 
 
1584
 
                        break;
1585
 
                    default:
1586
 
                        break;
1587
 
                }
1588
 
            } /* if type */
1589
 
            break;
1590
 
 
1591
 
        case AWT_MODE_SETROOT:
1592
 
            if(type==AW_Mouse_Press){
1593
 
                switch(button){
1594
 
                    case AWT_M_LEFT:
1595
 
                        if(cl->exists){
1596
 
                            at = (AP_tree *)cl->client_data1;
1597
 
                            if (!at) break;
1598
 
                            at->set_root();
1599
 
                            this->exports.save = 1;
1600
 
                            this->exports.zoom_reset = 1;
1601
 
                            this->tree_root->compute_tree(gb_main);
1602
 
                        }
1603
 
                        break;
1604
 
                }
1605
 
            } /* if type */
1606
 
            break;
1607
 
 
1608
 
        case AWT_MODE_SWAP:
1609
 
            if(type==AW_Mouse_Press){
1610
 
                switch(button){
1611
 
                    case AWT_M_LEFT:
1612
 
                        if(cl->exists){
1613
 
                            at = (AP_tree *)cl->client_data1;
1614
 
                            if (!at) break;
1615
 
                            at->swap_sons();
1616
 
 
1617
 
                            this->exports.refresh = 1;
1618
 
                            this->exports.save = 1;
1619
 
                        }
1620
 
                        break;
1621
 
                    case AWT_M_RIGHT:
1622
 
                        break;
1623
 
                }
1624
 
            } /* if type */
1625
 
            break;
1626
 
 
1627
 
        case AWT_MODE_MARK:
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;
1631
 
 
1632
 
                if (at) {
1633
 
                    GB_transaction dummy(this->tree_static->gb_species_data);
1634
 
 
1635
 
                    if (type == AW_Mouse_Press) {
1636
 
                        switch (button) {
1637
 
                            case AWT_M_LEFT:
1638
 
                                mark_species_in_tree(at, 1);
1639
 
                                break;
1640
 
                            case AWT_M_RIGHT:
1641
 
                                mark_species_in_tree(at, 0);
1642
 
                                break;
1643
 
                        }
1644
 
                    }
1645
 
                    this->exports.refresh = 1;
1646
 
                    this->tree_static->update_timers(); // do not reload the tree
1647
 
                    this->tree_root->calc_color();
1648
 
                }
1649
 
            }
1650
 
            break;
1651
 
 
1652
 
        case AWT_MODE_NONE:
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);
1656
 
                if (cl->exists) {
1657
 
                    at = (AP_tree *)cl->client_data1;
1658
 
                }else{
1659
 
                    at = (AP_tree *)ct->client_data1;
1660
 
                }
1661
 
                if (!at) break;
1662
 
 
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);
1665
 
 
1666
 
                if (button == AWT_M_LEFT) goto act_like_group; // now do the same like in AWT_MODE_GROUP
1667
 
            }
1668
 
            break;
1669
 
 
1670
 
        case AWT_MODE_MOD:
1671
 
            if(type==AW_Mouse_Press && (cl->exists || ct->exists) ){
1672
 
                GB_transaction dummy(this->tree_static->gb_species_data);
1673
 
                if (cl->exists) {
1674
 
                    at = (AP_tree *)cl->client_data1;
1675
 
                }else{
1676
 
                    at = (AP_tree *)ct->client_data1;
1677
 
                }
1678
 
                if (!at) break;
1679
 
                AD_map_viewer(at->gb_node,ADMVT_INFO);
1680
 
            }
1681
 
            break;
1682
 
        case AWT_MODE_WWW:
1683
 
            if(type==AW_Mouse_Press && (cl->exists || ct->exists) ){
1684
 
                GB_transaction dummy(this->tree_static->gb_species_data);
1685
 
                if (cl->exists) {
1686
 
                    at = (AP_tree *)cl->client_data1;
1687
 
                }else{
1688
 
                    at = (AP_tree *)ct->client_data1;
1689
 
                }
1690
 
                if (!at) break;
1691
 
                AD_map_viewer(at->gb_node,ADMVT_WWW);
1692
 
            }
1693
 
            break;
1694
 
        default:
1695
 
            break;
1696
 
    }
1697
 
}
1698
 
 
1699
 
void AWT_graphic_tree::set_tree_type(AP_tree_sort type)
1700
 
{
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'
1704
 
        }
1705
 
        else {
1706
 
            nds_show_all = true; // default to all
1707
 
        }
1708
 
    }
1709
 
    tree_sort = type;
1710
 
    switch(type) {
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;
1720
 
            break;
1721
 
 
1722
 
        case AP_LIST_SIMPLE:
1723
 
        case AP_LIST_NDS:
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;
1732
 
            break;
1733
 
 
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;
1743
 
            break;
1744
 
 
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;
1754
 
            break;
1755
 
    }
1756
 
}
1757
 
 
1758
 
AWT_graphic_tree::AWT_graphic_tree(AW_root *aw_rooti, GBDATA *gb_maini):AWT_graphic()
1759
 
{
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;
1768
 
    tree_root         = 0;
1769
 
    y_pos             = 0;
1770
 
    tree_proto        = 0;
1771
 
    tree_static       = 0;
1772
 
    tree_name         = 0;
1773
 
    baselinewidth     = 0;
1774
 
    species_name      = 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;
1780
 
}
1781
 
 
1782
 
AWT_graphic_tree::~AWT_graphic_tree(void)
1783
 
{
1784
 
    delete this->tree_proto;
1785
 
    delete this->tree_root;
1786
 
    delete this->tree_static;
1787
 
    free(tree_name);
1788
 
}
1789
 
 
1790
 
void AWT_graphic_tree::init(AP_tree * tree_prot)
1791
 
{
1792
 
    this->tree_proto = tree_prot->dup();
1793
 
}
1794
 
 
1795
 
void AWT_graphic_tree::unload(void)
1796
 
{
1797
 
    rot_at = 0;
1798
 
 
1799
 
    delete tree_root;
1800
 
    delete tree_static;
1801
 
    free(tree_name);
1802
 
 
1803
 
    tree_root         = 0;
1804
 
    tree_static       = 0;
1805
 
    tree_root_display = 0;
1806
 
    tree_name         = 0;
1807
 
}
1808
 
 
1809
 
GB_ERROR AWT_graphic_tree::load(GBDATA *, const char *name,AW_CL link_to_database, AW_CL insert_delete_cbs) {
1810
 
    GB_ERROR error = 0;
1811
 
 
1812
 
    if (name[0] == 0 || strcmp(name, "tree_????") == 0) { // no tree selected
1813
 
        unload();
1814
 
        zombies    = 0;
1815
 
        duplicates = 0;
1816
 
    }
1817
 
    else {
1818
 
        AP_tree      *apt = tree_proto->dup();
1819
 
        AP_tree_root *tr  = new AP_tree_root(gb_main,apt,name);
1820
 
 
1821
 
        error = apt->load(tr,(int)link_to_database,(GB_BOOL)insert_delete_cbs, GB_TRUE, &zombies, &duplicates); // show status
1822
 
        unload();
1823
 
 
1824
 
        if (error) {
1825
 
            delete tr;
1826
 
            delete apt;
1827
 
        }
1828
 
        else {
1829
 
            tree_root         = apt;
1830
 
            tree_static       = tr;
1831
 
            tree_root_display = this->tree_root;
1832
 
 
1833
 
            tree_root->compute_tree(gb_main);
1834
 
            
1835
 
            tree_name = strdup(name);
1836
 
 
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;
1841
 
        }
1842
 
    }
1843
 
 
1844
 
    return error;
1845
 
}
1846
 
 
1847
 
GB_ERROR AWT_graphic_tree::save(GBDATA */*dummy*/, const char */*name*/, AW_CL /*cd1*/, AW_CL /*cd2*/) {
1848
 
    GB_ERROR error = NULL;
1849
 
    if (tree_root) {
1850
 
        error = tree_root->saveTree();
1851
 
    }
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);
1857
 
 
1858
 
            if (!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
1862
 
 
1863
 
                // solution: currently selected tree (in NTREE, maybe also in PARSIMONY)
1864
 
                // needs to add a delete callback on treedata in DB
1865
 
 
1866
 
#endif // DEVEL_RALF
1867
 
            }
1868
 
 
1869
 
            tree_static->gb_tree_gone = 0; // do not delete twice
1870
 
        }
1871
 
    }
1872
 
    return error;
1873
 
}
1874
 
 
1875
 
int AWT_graphic_tree::check_update(GBDATA *gbdummy)
1876
 
{
1877
 
    AWUSE(gbdummy);
1878
 
    AP_UPDATE_FLAGS flags;
1879
 
    char *name;
1880
 
    GB_ERROR error;
1881
 
    if (!this->tree_static) return 0;
1882
 
    GB_transaction dummy(gb_main);
1883
 
 
1884
 
    if (!this->tree_root) {
1885
 
        flags = AP_UPDATE_ERROR;
1886
 
    }
1887
 
    else {
1888
 
        flags = this->tree_root->check_update();
1889
 
        switch (flags){
1890
 
            case AP_UPDATE_OK:
1891
 
            case AP_UPDATE_ERROR:
1892
 
                return flags;
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);
1897
 
                free(name);
1898
 
                this->exports.resize = 1;
1899
 
                break;
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);
1904
 
                break;
1905
 
        }
1906
 
    }
1907
 
    return (int)flags;
1908
 
}
1909
 
 
1910
 
void AWT_graphic_tree::update(GBDATA *gbdummy){
1911
 
    AWUSE(gbdummy);
1912
 
    if (!this->tree_static) return;
1913
 
    if (!this->tree_root) return;
1914
 
    GB_transaction dummy(gb_main);
1915
 
    this->tree_root->update();
1916
 
}
1917
 
 
1918
 
void AWT_graphic_tree::NT_scalebox(int gc, double x, double y, double width)
1919
 
{
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);
1924
 
}
1925
 
 
1926
 
void AWT_graphic_tree::NT_emptybox(int gc, double x, double y, double width)
1927
 
{
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);
1932
 
}
1933
 
 
1934
 
void AWT_graphic_tree::NT_rotbox(int gc, double x, double y, double width) // box with one corner down
1935
 
{
1936
 
    double diam = width / disp_device->get_scale();
1937
 
    double x1   = x-diam;
1938
 
    double x2   = x+diam;
1939
 
    double y1   = y-diam;
1940
 
    double y2   = y+diam;
1941
 
 
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);
1946
 
}
1947
 
 
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
1950
 
    char       *end          = 0;
1951
 
    int         bootstrap    = int(strtol(remark_branch, &end, 10));
1952
 
    bool        is_bootstrap = end[0] == '%' && end[1] == 0;
1953
 
    bool        show         = true;
1954
 
    const char *text         = 0;
1955
 
 
1956
 
    if (is_bootstrap) {
1957
 
        if (bootstrap == 100) {
1958
 
            show           = !is_leaf; // do not show 100% bootstraps at leafs
1959
 
            if (show) text = "100%";
1960
 
        }
1961
 
        else {
1962
 
            if (bootstrap == 0) {
1963
 
                text = "<1%"; // show instead of '0%'
1964
 
            }
1965
 
            else {
1966
 
                text = GBS_global_string("%i%%", bootstrap);
1967
 
            }
1968
 
        }
1969
 
    }
1970
 
    else {
1971
 
        text = remark_branch;
1972
 
    }
1973
 
 
1974
 
    if (show) {
1975
 
        awt_assert(text != 0);
1976
 
        device->text(AWT_GC_BRANCH_REMARK, text, x, y, alignment, filteri, cd1, cd2);
1977
 
    }
1978
 
 
1979
 
    return is_bootstrap && show;
1980
 
}
1981
 
 
1982
 
 
1983
 
double AWT_graphic_tree::show_dendrogram(AP_tree *at, double x_father, double x_son)
1984
 
{
1985
 
    double ny0, ny1, nx0, nx1, ry, l_min, l_max, xoffset, yoffset;
1986
 
    AWUSE(x_father);
1987
 
    ny0 = y_pos;
1988
 
 
1989
 
    if (disp_device->type() != AW_DEVICE_SIZE){ // tree below cliprect bottom can be cut
1990
 
        AW_pos xs = 0;
1991
 
        AW_pos ys = y_pos - scaled_branch_distance *2.0;
1992
 
        AW_pos X,Y;
1993
 
        disp_device->transform(xs,ys,X,Y);
1994
 
        if ( Y > disp_device->clip_rect.b){
1995
 
            y_pos += scaled_branch_distance;
1996
 
            return ny0;
1997
 
        }
1998
 
        ys = y_pos + scaled_branch_distance * (at->gr.view_sum+2);
1999
 
        disp_device->transform(xs,ys,X,Y);
2000
 
 
2001
 
        if ( Y  < disp_device->clip_rect.t){
2002
 
            y_pos += scaled_branch_distance*at->gr.view_sum;
2003
 
            return ny0;
2004
 
        }
2005
 
    }
2006
 
 
2007
 
    if (at->is_leaf) {
2008
 
        /* draw mark box */
2009
 
        if (at->gb_node && GB_read_flag(at->gb_node)){
2010
 
            NT_scalebox(at->gr.gc, x_son, ny0, NT_BOX_WIDTH);
2011
 
        }
2012
 
        if (at->name &&
2013
 
            at->name[0] == this->species_name[0] &&
2014
 
            strcmp(at->name,this->species_name) == 0)
2015
 
        {
2016
 
            x_cursor = x_son;
2017
 
            y_cursor = ny0;
2018
 
        }
2019
 
 
2020
 
        if (at->name && (disp_device->filter & text_filter) ){
2021
 
            // text darstellen
2022
 
            const char *data = make_node_text_nds(this->gb_main, at->gb_node,0,at->get_gbt_tree(), tree_name);
2023
 
 
2024
 
            //             offset = scale*0.4;
2025
 
 
2026
 
 
2027
 
            const AW_font_information *fontinfo = disp_device->get_font_information(at->gr.gc,'A');
2028
 
 
2029
 
#if defined(DEBUG) && 0
2030
 
            static bool dumped = false;
2031
 
            if (!dumped) {
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",
2035
 
                           c, (char)c,
2036
 
                           fi->this_letter.ascent,
2037
 
                           fi->this_letter.descent,
2038
 
                           fi->this_letter.width
2039
 
                           );
2040
 
                    if (c == 255) {
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
2045
 
                               );
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
2050
 
                               );
2051
 
                    }
2052
 
                }
2053
 
 
2054
 
                dumped = true;
2055
 
            }
2056
 
#endif // DEBUG
2057
 
 
2058
 
 
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;
2062
 
 
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 );
2067
 
        }
2068
 
 
2069
 
 
2070
 
        y_pos += scaled_branch_distance;
2071
 
        return ny0;
2072
 
    }
2073
 
 
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;
2080
 
 
2081
 
        int linewidth = 0;
2082
 
        if (at->father) {
2083
 
            if (at->father->leftson == at) {
2084
 
                linewidth = at->father->gr.left_linewidth;
2085
 
            }else{
2086
 
                linewidth = at->father->gr.right_linewidth;
2087
 
            }
2088
 
        }
2089
 
 
2090
 
        disp_device->set_line_attributes(at->gr.gc,linewidth+baselinewidth,AW_SOLID);
2091
 
 
2092
 
        AW_pos q[8];
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;
2097
 
 
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);
2100
 
 
2101
 
        // double add_y_offset = scale*0.3;
2102
 
 
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() ;
2105
 
 
2106
 
        yoffset = (ny1-ny0+text_ascent)*.5;
2107
 
        xoffset = text_ascent*.5;
2108
 
 
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);
2111
 
 
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 );
2116
 
        }
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);
2120
 
 
2121
 
        y_pos += scaled_branch_distance;
2122
 
 
2123
 
        return (ny0+ny1)*.5;
2124
 
    }
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);
2130
 
 
2131
 
    if (at->name) {
2132
 
        NT_rotbox(at->gr.gc,x_son, ry, NT_BOX_WIDTH*2);
2133
 
    }
2134
 
 
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);
2137
 
 
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);
2140
 
        }
2141
 
    }
2142
 
 
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);
2145
 
 
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);
2148
 
        }
2149
 
    }
2150
 
 
2151
 
#if defined(DEBUG)
2152
 
    if (at->gb_node) {
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);
2154
 
    }
2155
 
#endif // DEBUG
2156
 
 
2157
 
 
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);
2164
 
 
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);
2171
 
 
2172
 
    return ry;
2173
 
}
2174
 
 
2175
 
 
2176
 
void AWT_graphic_tree::scale_text_koordinaten(AW_device *device, int gc,double& x,double& y,double orientation,int flag)
2177
 
{
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();
2181
 
    
2182
 
    if (flag==1) {
2183
 
        dist += 1;
2184
 
    }
2185
 
    else {
2186
 
        x += cos(orientation) * dist;
2187
 
        y += sin(orientation) * dist + 0.3*text_height;
2188
 
    }
2189
 
    return;
2190
 
}
2191
 
 
2192
 
 
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)
2197
 
{
2198
 
    double l,r,w,z,l_min,l_max;
2199
 
 
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);
2202
 
 
2203
 
    // draw mark box
2204
 
    if (at->gb_node && GB_read_flag(at->gb_node)) {
2205
 
        NT_scalebox(at->gr.gc, x_center, y_center, NT_BOX_WIDTH);
2206
 
    }
2207
 
 
2208
 
    if( at->is_leaf){
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;
2213
 
            }
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);
2221
 
 
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 );
2226
 
        }
2227
 
        return;
2228
 
    }
2229
 
 
2230
 
    if( at->gr.grouped){
2231
 
        l_min = at->gr.min_tree_depth;
2232
 
        l_max = at->gr.tree_depth;
2233
 
 
2234
 
        r    = l = 0.5;
2235
 
        AW_pos q[6];
2236
 
        q[0] = x_center;
2237
 
        q[1] = y_center;
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);
2244
 
 
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);
2247
 
 
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);
2254
 
 
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 ,
2261
 
            //                                text_filter,
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),
2266
 
                              text_filter,
2267
 
                              (AW_CL) at , (AW_CL) 0 );
2268
 
        }
2269
 
        return;
2270
 
    }
2271
 
    l = (double) at->leftson->gr.view_sum / (double)at->gr.view_sum;
2272
 
    r = 1.0 - (double)l;
2273
 
 
2274
 
    if (at->leftson->gr.gc > at->rightson->gr.gc) {
2275
 
        // bring selected gc to front
2276
 
 
2277
 
        /*** left branch ***/
2278
 
        w = r*0.5*tree_spread + tree_orientation + at->gr.left_angle;
2279
 
        z = at->leftlen;
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,
2285
 
                         w,
2286
 
                         x_center, y_center, at->gr.left_linewidth );
2287
 
 
2288
 
        /*** right branch ***/
2289
 
        w = tree_orientation - l*0.5*tree_spread + at->gr.right_angle;
2290
 
        z = at->rightlen;
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,
2296
 
                         w,
2297
 
                         x_center, y_center, at->gr.right_linewidth);
2298
 
    }else{
2299
 
        /*** right branch ***/
2300
 
        w = tree_orientation - l*0.5*tree_spread + at->gr.right_angle;
2301
 
        z = at->rightlen;
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,
2307
 
                         w,
2308
 
                         x_center, y_center, at->gr.right_linewidth);
2309
 
 
2310
 
        /*** left branch ***/
2311
 
        w = r*0.5*tree_spread + tree_orientation + at->gr.left_angle;
2312
 
        z = at->leftlen;
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,
2318
 
                         w,
2319
 
                         x_center, y_center, at->gr.left_linewidth );
2320
 
    }
2321
 
    if (show_circle){
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);
2327
 
        }
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);
2333
 
        }
2334
 
    }
2335
 
}
2336
 
 
2337
 
const char *AWT_graphic_tree::show_ruler(AW_device *device, int gc) {
2338
 
    const char *tree_awar = 0;
2339
 
 
2340
 
    char awar[256];
2341
 
    if (!this->tree_static->gb_tree)    return 0;   // no ruler !!!!
2342
 
    GB_transaction dummy(this->tree_static->gb_tree);
2343
 
 
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;
2352
 
 
2353
 
    switch (tree_sort) {
2354
 
        case AP_TREE_NORMAL:
2355
 
            tree_awar = "LIST";
2356
 
            break;
2357
 
        case AP_TREE_RADIAL:
2358
 
            tree_awar = "RADIAL";
2359
 
            break;
2360
 
        case AP_TREE_IRS:
2361
 
            tree_awar = "IRS";
2362
 
            break;
2363
 
        case AP_LIST_SIMPLE:
2364
 
        case AP_LIST_NDS:
2365
 
            // rulers not allowed in these display modes
2366
 
            awt_assert(0);
2367
 
            tree_awar = 0;
2368
 
            break;
2369
 
    }
2370
 
 
2371
 
    if (tree_awar) {
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) {
2375
 
                AW_world world;
2376
 
                device ->get_size_information(&world);
2377
 
                ruler_y = world.b * 1.3;
2378
 
            }
2379
 
        }
2380
 
 
2381
 
        double half_ruler_width = ruler_size*0.5;
2382
 
 
2383
 
        switch (tree_sort) {
2384
 
            case AP_TREE_IRS:
2385
 
                // scale is different for IRS tree -> adjust:
2386
 
                half_ruler_width *= irs_tree_ruler_scale_factor;
2387
 
                ruler_y     = 0;
2388
 
                ruler_add_y = this->list_tree_ruler_y;
2389
 
                ruler_add_x = -half_ruler_width;
2390
 
                break;
2391
 
            case AP_TREE_NORMAL:
2392
 
                ruler_y     = 0;
2393
 
                ruler_add_y = this->list_tree_ruler_y;
2394
 
                ruler_add_x = half_ruler_width;
2395
 
                break;
2396
 
            default:
2397
 
                break;
2398
 
        }
2399
 
 
2400
 
 
2401
 
        ruler_y = ruler_add_y + *GBT_readOrCreate_float(this->tree_static->gb_tree, awar, ruler_y);
2402
 
 
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);
2405
 
 
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);
2409
 
 
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);
2413
 
 
2414
 
        sprintf(awar,"ruler/ruler_width");
2415
 
        double ruler_width = *GBT_readOrCreate_int(this->tree_static->gb_tree, awar, 0);
2416
 
 
2417
 
        device->set_line_attributes(gc, ruler_width+baselinewidth, AW_SOLID);
2418
 
 
2419
 
        device->line(gc,
2420
 
                     ruler_x - half_ruler_width, ruler_y,
2421
 
                     ruler_x + half_ruler_width, ruler_y,
2422
 
                     this->ruler_filter,
2423
 
                     0, (AW_CL)"ruler");
2424
 
        char ruler_text[20];
2425
 
        sprintf(ruler_text,"%4.2f",ruler_size);
2426
 
 
2427
 
        device->text(gc, ruler_text,
2428
 
                     ruler_x + ruler_text_x,
2429
 
                     ruler_y + ruler_text_y,
2430
 
                     0.5,
2431
 
                     this->ruler_filter & ~AW_SIZE,
2432
 
                     0, (AW_CL)"ruler");
2433
 
    }
2434
 
    return tree_awar;
2435
 
}
2436
 
 
2437
 
void AWT_graphic_tree::show_nds_list(GBDATA * dummy, bool use_nds)
2438
 
{
2439
 
    AWUSE(dummy);
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;
2443
 
 
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);
2449
 
 
2450
 
    for (GBDATA *gb_species = nds_show_all ? GBT_first_species(gb_main) : GBT_first_marked_species(gb_main);
2451
 
         gb_species;
2452
 
         gb_species = nds_show_all ? GBT_next_species(gb_species) : GBT_next_marked_species(gb_species))
2453
 
    {
2454
 
        y_position += scaled_branch_distance;
2455
 
 
2456
 
        const char *name = GBT_read_name(gb_species);
2457
 
 
2458
 
        if (strcmp(name, this->species_name) == 0) {
2459
 
            x_cursor = 0;
2460
 
            y_cursor = y_position;
2461
 
        }
2462
 
 
2463
 
        bool is_marked = GB_read_flag(gb_species);
2464
 
        if (is_marked) NT_scalebox(AWT_GC_SELECTED, 0, y_position, NT_BOX_WIDTH);
2465
 
 
2466
 
        {
2467
 
            AW_pos xs = 0;
2468
 
            AW_pos X,Y;
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;
2473
 
        }
2474
 
 
2475
 
        if (disp_device->type() != AW_DEVICE_SIZE){ // tree below cliprect bottom can be cut
2476
 
            const char *data;
2477
 
            if (use_nds) {
2478
 
                data = make_node_text_nds(gb_main, gb_species, 1, 0, tree_name);
2479
 
            }
2480
 
            else {
2481
 
                data = name;
2482
 
            }
2483
 
 
2484
 
            long slen = strlen(data);
2485
 
            int  gc   = AWT_GC_NSELECTED;
2486
 
 
2487
 
            if (nds_show_all && is_marked) {
2488
 
                gc = AWT_GC_SELECTED;
2489
 
            }
2490
 
            else {
2491
 
                int color_group     = AWT_species_get_dominant_color(gb_species);
2492
 
                if (color_group) gc = AWT_GC_FIRST_COLOR_GROUP+color_group-1;
2493
 
            }
2494
 
 
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);
2499
 
 
2500
 
            if (slen> max_strlen) max_strlen = slen;
2501
 
        }
2502
 
    }
2503
 
 
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);
2506
 
}
2507
 
 
2508
 
void AWT_graphic_tree::show(AW_device *device)  {
2509
 
    if (tree_static && tree_static->gb_tree) {
2510
 
        check_update(gb_main);
2511
 
    }
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
2515
 
        }
2516
 
    }
2517
 
 
2518
 
    disp_device = device;
2519
 
 
2520
 
    const AW_font_information *fontinfo = disp_device->get_font_information(AWT_GC_SELECTED, 0);
2521
 
 
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();
2524
 
 
2525
 
    make_node_text_init(gb_main);
2526
 
 
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();
2533
 
 
2534
 
    freeset(species_name, aw_root->awar(AWAR_SPECIES_NAME)->read_string());
2535
 
 
2536
 
    x_cursor = y_cursor = 0.0;
2537
 
 
2538
 
    switch (tree_sort) {
2539
 
        case AP_TREE_NORMAL:
2540
 
            if (!tree_root_display) return;
2541
 
            y_pos = 0.05;
2542
 
            show_dendrogram(tree_root_display, 0, 0);
2543
 
            list_tree_ruler_y = y_pos + 2.0 * scaled_branch_distance;
2544
 
            break;
2545
 
 
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);
2550
 
            break;
2551
 
 
2552
 
        case AP_TREE_IRS:
2553
 
            show_irs_tree(tree_root_display,disp_device,fontinfo->max_letter.height);
2554
 
            list_tree_ruler_y = y_pos;
2555
 
            break;
2556
 
 
2557
 
        case AP_LIST_NDS:       // this is the list all/marked species mode (no tree)
2558
 
            show_nds_list(gb_main, true);
2559
 
            break;
2560
 
 
2561
 
        case AP_LIST_SIMPLE:    // simple list of names (used at startup only)
2562
 
            show_nds_list(gb_main, false);
2563
 
            break;            
2564
 
    }
2565
 
    if (x_cursor != 0.0 || y_cursor != 0.0) {
2566
 
        NT_emptybox(AWT_GC_CURSOR, x_cursor, y_cursor, NT_SELECTED_WIDTH);
2567
 
    }
2568
 
    if (sort_is_tree_style(tree_sort)) { // show rulers in tree-style display modes
2569
 
        show_ruler(device, AWT_GC_CURSOR);
2570
 
    }
2571
 
}
2572
 
 
2573
 
void AWT_graphic_tree::info(AW_device *device, AW_pos x, AW_pos y,
2574
 
                            AW_clicked_line *cl, AW_clicked_text *ct)
2575
 
{
2576
 
    aw_message("INFO MESSAGE");
2577
 
    AWUSE(device);
2578
 
    AWUSE(x);
2579
 
    AWUSE(y);
2580
 
    AWUSE(cl);
2581
 
    AWUSE(ct);
2582
 
 
2583
 
}
2584
 
 
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
2589
 
    return apdt;
2590
 
}
2591
 
 
2592
 
void awt_create_dtree_awars(AW_root *aw_root,AW_default def)
2593
 
{
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);
2597
 
 
2598
 
    aw_root->awar_int(AWAR_DTREE_SHOW_CIRCLE,0,def);
2599
 
    aw_root->awar_int(AWAR_DTREE_USE_ELLIPSE, 1, def);
2600
 
 
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);
2604
 
 
2605
 
    aw_root->awar_int(AWAR_DTREE_REFRESH,0,def);
2606
 
}
2607
 
 
2608