| 1 | #include <stdio.h> |
|---|
| 2 | #include <stdlib.h> |
|---|
| 3 | #include <string.h> |
|---|
| 4 | #include <ctype.h> |
|---|
| 5 | |
|---|
| 6 | #include <arbdb.h> |
|---|
| 7 | #include <arbdbt.h> |
|---|
| 8 | |
|---|
| 9 | #include <aw_root.hxx> |
|---|
| 10 | #include <aw_device.hxx> |
|---|
| 11 | #include <aw_window.hxx> |
|---|
| 12 | #include <aw_awars.hxx> |
|---|
| 13 | #include <awt_canvas.hxx> |
|---|
| 14 | #include <awt_tree.hxx> |
|---|
| 15 | #include <awt_dtree.hxx> |
|---|
| 16 | #include <awt_tree_cb.hxx> |
|---|
| 17 | #include <awt_advice.hxx> |
|---|
| 18 | #include <awt.hxx> |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | void |
|---|
| 22 | nt_mode_event( AW_window *aws, AWT_canvas *ntw, AWT_COMMAND_MODE mode) |
|---|
| 23 | { |
|---|
| 24 | AWUSE(aws); |
|---|
| 25 | const char *text; |
|---|
| 26 | |
|---|
| 27 | switch(mode){ |
|---|
| 28 | case AWT_MODE_SELECT: |
|---|
| 29 | text = "SELECT MODE LEFT: select species and open/close group"; |
|---|
| 30 | break; |
|---|
| 31 | case AWT_MODE_MARK: |
|---|
| 32 | text = "MARK MODE LEFT: mark subtree RIGHT: unmark subtree"; |
|---|
| 33 | break; |
|---|
| 34 | case AWT_MODE_GROUP: |
|---|
| 35 | text = "GROUP MODE LEFT: fold/unfold group RIGHT: create/rename/destroy group"; |
|---|
| 36 | break; |
|---|
| 37 | case AWT_MODE_ZOOM: |
|---|
| 38 | text = "ZOOM MODE LEFT: press and drag to zoom RIGHT: zoom out one step"; |
|---|
| 39 | break; |
|---|
| 40 | case AWT_MODE_LZOOM: |
|---|
| 41 | text = "LOGICAL ZOOM MODE LEFT: show subtree RIGHT: go up one step"; |
|---|
| 42 | break; |
|---|
| 43 | case AWT_MODE_MOD: |
|---|
| 44 | text = "MODIFY MODE LEFT: select node M: assign info to internal node"; |
|---|
| 45 | break; |
|---|
| 46 | case AWT_MODE_WWW: |
|---|
| 47 | text = "CLICK NODE TO SEARCH WEB (See <PROPS/WWW...> also"; |
|---|
| 48 | break; |
|---|
| 49 | case AWT_MODE_LINE: |
|---|
| 50 | text = "LINE MODE LEFT: reduce linewidth RIGHT: increase linewidth"; |
|---|
| 51 | break; |
|---|
| 52 | case AWT_MODE_ROT: |
|---|
| 53 | text = "ROTATE MODE LEFT: Select branch and drag to rotate"; |
|---|
| 54 | break; |
|---|
| 55 | case AWT_MODE_SPREAD: |
|---|
| 56 | text = "SPREAD MODE LEFT: decrease angles RIGHT: increase angles"; |
|---|
| 57 | break; |
|---|
| 58 | case AWT_MODE_SWAP: |
|---|
| 59 | text = "SWAP MODE LEFT: swap branches"; |
|---|
| 60 | break; |
|---|
| 61 | case AWT_MODE_LENGTH: |
|---|
| 62 | text = "BRANCH LENGTH MODE LEFT: Drag branch/ruler to change length RIGHT: use discrete lengths"; |
|---|
| 63 | break; |
|---|
| 64 | case AWT_MODE_MOVE: |
|---|
| 65 | text = "MOVE MODE LEFT: move subtree/ruler to new destination RIGHT: move group info only"; |
|---|
| 66 | break; |
|---|
| 67 | case AWT_MODE_NNI: |
|---|
| 68 | text = "NEAREST NEIGHBOUR INTERCHANGE OPTIMIZER L: select subtree R: whole tree"; |
|---|
| 69 | break; |
|---|
| 70 | case AWT_MODE_KERNINGHAN: |
|---|
| 71 | text = "KERNIGHAN LIN OPTIMIZER L: select subtree R: whole tree"; |
|---|
| 72 | break; |
|---|
| 73 | case AWT_MODE_OPTIMIZE: |
|---|
| 74 | text = "NNI & KL OPTIMIZER L: select subtree R: whole tree"; |
|---|
| 75 | break; |
|---|
| 76 | case AWT_MODE_SETROOT: |
|---|
| 77 | text = "SET ROOT MODE LEFT: set root"; |
|---|
| 78 | break; |
|---|
| 79 | case AWT_MODE_RESET: |
|---|
| 80 | text = "RESET MODE LEFT: reset rotation MIDDLE: reset angles RIGHT: reset linewidth"; |
|---|
| 81 | break; |
|---|
| 82 | |
|---|
| 83 | default: |
|---|
| 84 | text="No help for this mode available"; |
|---|
| 85 | break; |
|---|
| 86 | } |
|---|
| 87 | |
|---|
| 88 | awt_assert(strlen(text) < AWAR_FOOTER_MAX_LEN); // text too long! |
|---|
| 89 | |
|---|
| 90 | ntw->awr->awar(AWAR_FOOTER)->write_string( text); |
|---|
| 91 | ntw->set_mode(mode); |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | // --------------------------------------- |
|---|
| 95 | // Basic mark/unmark callbacks : |
|---|
| 96 | // --------------------------------------- |
|---|
| 97 | |
|---|
| 98 | void NT_count_mark_all_cb(void *dummy, AW_CL cl_ntw) |
|---|
| 99 | { |
|---|
| 100 | AWUSE(dummy); |
|---|
| 101 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 102 | GB_push_transaction(ntw->gb_main); |
|---|
| 103 | |
|---|
| 104 | GBDATA *gb_species_data = GB_search(ntw->gb_main,"species_data",GB_CREATE_CONTAINER); |
|---|
| 105 | long count = GB_number_of_marked_subentries(gb_species_data); |
|---|
| 106 | |
|---|
| 107 | GB_pop_transaction(ntw->gb_main); |
|---|
| 108 | |
|---|
| 109 | char buf[256]; |
|---|
| 110 | switch (count) { |
|---|
| 111 | case 0: strcpy(buf, "There are NO marked species"); break; |
|---|
| 112 | case 1: strcpy(buf, "There is 1 marked species"); break; |
|---|
| 113 | default: sprintf(buf, "There are %li marked species", count); break; |
|---|
| 114 | } |
|---|
| 115 | strcat(buf, ". (The number of species is displayed in the top area as well)"); |
|---|
| 116 | aw_message(buf); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | static int nt_species_has_alignment(GBDATA *gb_species, void *cd_use) { |
|---|
| 120 | return GBT_read_sequence(gb_species, (const char*)cd_use) != 0; |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | static int nt_sequence_is_partial(GBDATA *gb_species, void *cd_partial) { |
|---|
| 124 | long wanted = (long)cd_partial; |
|---|
| 125 | awt_assert(wanted == 0 || wanted == 1); |
|---|
| 126 | int partial = GBT_is_partial(gb_species, 1-wanted, 0); |
|---|
| 127 | |
|---|
| 128 | return partial == wanted; |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | #define MARK_MODE_LOWER_BITS (1|2) |
|---|
| 132 | #define MARK_MODE_UPPER_BITS (4|8|16) |
|---|
| 133 | |
|---|
| 134 | void NT_mark_all_cb(AW_window *, AW_CL cl_ntw, AW_CL cl_mark_mode) |
|---|
| 135 | // Bits 0 and 1 of mark_mode: |
|---|
| 136 | // |
|---|
| 137 | // mark_mode&3 == 0 -> unmark |
|---|
| 138 | // mark_mode&3 == 1 -> mark |
|---|
| 139 | // mark_mode&3 == 2 -> toggle mark |
|---|
| 140 | // |
|---|
| 141 | // Bits 2 .. 4 of mark_mode: |
|---|
| 142 | // |
|---|
| 143 | // mark_mode&12 == 4 -> affect only full sequences |
|---|
| 144 | // mark_mode&12 == 8 -> affect only partial sequences |
|---|
| 145 | // mark_mode&12 == 16 -> affect only species with data in current alignment |
|---|
| 146 | // else -> affect all sequences |
|---|
| 147 | { |
|---|
| 148 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 149 | int mark_mode = (int)cl_mark_mode; |
|---|
| 150 | |
|---|
| 151 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 152 | |
|---|
| 153 | switch (mark_mode&MARK_MODE_UPPER_BITS) { |
|---|
| 154 | case 0: // all sequences |
|---|
| 155 | GBT_mark_all(ntw->gb_main,mark_mode&MARK_MODE_LOWER_BITS); |
|---|
| 156 | break; |
|---|
| 157 | case 4: // full sequences only |
|---|
| 158 | GBT_mark_all_that(ntw->gb_main,mark_mode&MARK_MODE_LOWER_BITS, nt_sequence_is_partial, (void*)0); |
|---|
| 159 | break; |
|---|
| 160 | case 8: // partial sequences only |
|---|
| 161 | GBT_mark_all_that(ntw->gb_main,mark_mode&MARK_MODE_LOWER_BITS, nt_sequence_is_partial, (void*)1); |
|---|
| 162 | break; |
|---|
| 163 | case 16: { // species with data in alignment only |
|---|
| 164 | char *ali = GBT_get_default_alignment(ntw->gb_main); |
|---|
| 165 | if (ali) GBT_mark_all_that(ntw->gb_main, mark_mode&MARK_MODE_LOWER_BITS, nt_species_has_alignment, (void*)ali); |
|---|
| 166 | free(ali); |
|---|
| 167 | break; |
|---|
| 168 | } |
|---|
| 169 | default : |
|---|
| 170 | awt_assert(0); // illegal mode |
|---|
| 171 | break; |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | ntw->refresh(); |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | void NT_mark_tree_cb(AW_window *, AW_CL cl_ntw, AW_CL cl_mark_mode) |
|---|
| 178 | { |
|---|
| 179 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 180 | int mark_mode = (int)cl_mark_mode; |
|---|
| 181 | AWT_graphic_tree *gtree = AWT_TREE(ntw); |
|---|
| 182 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 183 | |
|---|
| 184 | gtree->check_update(ntw->gb_main); |
|---|
| 185 | switch (mark_mode&MARK_MODE_UPPER_BITS) { |
|---|
| 186 | case 0: // all sequences |
|---|
| 187 | gtree->mark_species_in_tree(gtree->tree_root, mark_mode&MARK_MODE_LOWER_BITS); |
|---|
| 188 | break; |
|---|
| 189 | case 4: // full sequences only |
|---|
| 190 | gtree->mark_species_in_tree_that(gtree->tree_root, mark_mode&MARK_MODE_LOWER_BITS, nt_sequence_is_partial, (void*)0); |
|---|
| 191 | break; |
|---|
| 192 | case 8: // partial sequences only |
|---|
| 193 | gtree->mark_species_in_tree_that(gtree->tree_root, mark_mode&MARK_MODE_LOWER_BITS, nt_sequence_is_partial, (void*)1); |
|---|
| 194 | break; |
|---|
| 195 | case 16: { // species with data in alignment only |
|---|
| 196 | char *ali = GBT_get_default_alignment(ntw->gb_main); |
|---|
| 197 | if (ali) gtree->mark_species_in_tree_that(gtree->tree_root, mark_mode&MARK_MODE_LOWER_BITS, nt_species_has_alignment, (void*)ali); |
|---|
| 198 | free(ali); |
|---|
| 199 | break; |
|---|
| 200 | } |
|---|
| 201 | default : |
|---|
| 202 | awt_assert(0); // illegal mode |
|---|
| 203 | break; |
|---|
| 204 | } |
|---|
| 205 | ntw->refresh(); |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | struct mark_nontree_cb_data { |
|---|
| 209 | int mark_mode_upper_bits; |
|---|
| 210 | char *ali; // current alignment (only if mark_mode_upper_bits == 16) |
|---|
| 211 | GB_HASH *hash; |
|---|
| 212 | }; |
|---|
| 213 | |
|---|
| 214 | static int mark_nontree_cb(GBDATA *gb_species, void *cb_data) { |
|---|
| 215 | struct mark_nontree_cb_data *data = (mark_nontree_cb_data*)cb_data; |
|---|
| 216 | const char *name = GBT_read_name(gb_species); |
|---|
| 217 | bool mark_me = false; |
|---|
| 218 | |
|---|
| 219 | if (GBS_read_hash(data->hash, name) == (long)gb_species) { // species is not in tree! |
|---|
| 220 | switch (data->mark_mode_upper_bits) { |
|---|
| 221 | case 0: // all sequences |
|---|
| 222 | mark_me = true; |
|---|
| 223 | break; |
|---|
| 224 | case 4: // full sequences only |
|---|
| 225 | mark_me = nt_sequence_is_partial(gb_species, (void*)0); |
|---|
| 226 | break; |
|---|
| 227 | case 8: // partial sequences only |
|---|
| 228 | mark_me = nt_sequence_is_partial(gb_species, (void*)1); |
|---|
| 229 | break; |
|---|
| 230 | case 16: // species with data in alignment only |
|---|
| 231 | mark_me = nt_species_has_alignment(gb_species, data->ali); |
|---|
| 232 | break; |
|---|
| 233 | default : |
|---|
| 234 | awt_assert(0); // illegal mode |
|---|
| 235 | break; |
|---|
| 236 | } |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | return mark_me; |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | void NT_mark_nontree_cb(AW_window *, AW_CL cl_ntw, AW_CL cl_mark_mode) |
|---|
| 243 | { |
|---|
| 244 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 245 | int mark_mode = (int)cl_mark_mode; |
|---|
| 246 | AWT_graphic_tree *gtree = AWT_TREE(ntw); |
|---|
| 247 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 248 | struct mark_nontree_cb_data cd; |
|---|
| 249 | |
|---|
| 250 | if ((mark_mode&MARK_MODE_LOWER_BITS) == 0) { // unmark is much faster |
|---|
| 251 | cd.hash = GBT_create_marked_species_hash(ntw->gb_main); // because it only hashes marked species |
|---|
| 252 | } |
|---|
| 253 | else { |
|---|
| 254 | cd.hash = GBT_create_species_hash(ntw->gb_main/*, 1*/); // otherwise we have to hash ALL species |
|---|
| 255 | // Note: changed to ignore case (ralf 2007-07-06) |
|---|
| 256 | } |
|---|
| 257 | |
|---|
| 258 | NT_remove_species_in_tree_from_hash(gtree->tree_root, cd.hash); |
|---|
| 259 | |
|---|
| 260 | cd.mark_mode_upper_bits = mark_mode&MARK_MODE_UPPER_BITS; |
|---|
| 261 | cd.ali = cd.mark_mode_upper_bits == 16 ? GBT_get_default_alignment(ntw->gb_main) : 0; |
|---|
| 262 | |
|---|
| 263 | GBT_mark_all_that(ntw->gb_main, mark_mode&MARK_MODE_LOWER_BITS, mark_nontree_cb, (void*)&cd); |
|---|
| 264 | |
|---|
| 265 | free(cd.ali); |
|---|
| 266 | |
|---|
| 267 | ntw->refresh(); |
|---|
| 268 | } |
|---|
| 269 | |
|---|
| 270 | void NT_mark_color_cb(AW_window *, AW_CL cl_ntw, AW_CL cl_mark_mode) |
|---|
| 271 | { |
|---|
| 272 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 273 | int mark_mode = (int)cl_mark_mode; |
|---|
| 274 | |
|---|
| 275 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 276 | |
|---|
| 277 | int color_group = mark_mode>>4; |
|---|
| 278 | awt_assert(mark_mode&(4|8)); // either 4 or 8 has to be set |
|---|
| 279 | bool mark_matching = (mark_mode&4) == 4; |
|---|
| 280 | mark_mode = mark_mode&3; |
|---|
| 281 | |
|---|
| 282 | for (GBDATA *gb_species = GBT_first_species(ntw->gb_main); gb_species; gb_species = GBT_next_species(gb_species)) { |
|---|
| 283 | int my_color_group = AW_find_color_group(gb_species, true); |
|---|
| 284 | |
|---|
| 285 | if (mark_matching == (color_group == my_color_group)) { |
|---|
| 286 | switch (mark_mode) { |
|---|
| 287 | case 0: GB_write_flag(gb_species, 0); break; |
|---|
| 288 | case 1: GB_write_flag(gb_species, 1); break; |
|---|
| 289 | case 2: GB_write_flag(gb_species, !GB_read_flag(gb_species)); break; |
|---|
| 290 | default : awt_assert(0); break; |
|---|
| 291 | } |
|---|
| 292 | } |
|---|
| 293 | } |
|---|
| 294 | |
|---|
| 295 | ntw->refresh(); |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | |
|---|
| 299 | void NT_insert_color_mark_submenu(AW_window_menu_modes *awm, AWT_canvas *ntree_canvas, const char *menuname, int mark_basemode) { |
|---|
| 300 | #define MAXLABEL 40 |
|---|
| 301 | #define MAXENTRY 20 |
|---|
| 302 | awm->insert_sub_menu(menuname, ""); |
|---|
| 303 | |
|---|
| 304 | char label_buf[MAXLABEL+1]; |
|---|
| 305 | char entry_buf[MAXENTRY+1]; |
|---|
| 306 | char hotkey[] = "x"; |
|---|
| 307 | const char *hotkeys = "N1234567890 "; |
|---|
| 308 | |
|---|
| 309 | const char *label_base = 0; |
|---|
| 310 | switch (mark_basemode) { |
|---|
| 311 | case 0: label_base = "all_unmark_color"; break; |
|---|
| 312 | case 1: label_base = "all_mark_color"; break; |
|---|
| 313 | case 2: label_base = "all_invert_mark_color"; break; |
|---|
| 314 | default : awt_assert(0); break; |
|---|
| 315 | } |
|---|
| 316 | |
|---|
| 317 | for (int all_but = 0; all_but <= 1; ++all_but) { |
|---|
| 318 | const char *entry_prefix; |
|---|
| 319 | if (all_but) entry_prefix = "all but"; |
|---|
| 320 | else entry_prefix = "all of"; |
|---|
| 321 | |
|---|
| 322 | for (int i = 0; i <= AW_COLOR_GROUPS; ++i) { |
|---|
| 323 | sprintf(label_buf, "%s_%i", label_base, i); |
|---|
| 324 | |
|---|
| 325 | if (i) { |
|---|
| 326 | char *color_group_name = AW_get_color_group_name(awm->get_root(), i); |
|---|
| 327 | sprintf(entry_buf, "%s '%s'", entry_prefix, color_group_name); |
|---|
| 328 | free(color_group_name); |
|---|
| 329 | } |
|---|
| 330 | else { |
|---|
| 331 | sprintf(entry_buf, "%s no color group", entry_prefix); |
|---|
| 332 | } |
|---|
| 333 | |
|---|
| 334 | hotkey[0] = hotkeys[i]; |
|---|
| 335 | if (hotkey[0] == ' ' || all_but) hotkey[0] = 0; |
|---|
| 336 | |
|---|
| 337 | awm->insert_menu_topic(label_buf, entry_buf, hotkey, "markcolor.hlp", AWM_ALL, |
|---|
| 338 | NT_mark_color_cb, |
|---|
| 339 | (AW_CL)ntree_canvas, |
|---|
| 340 | (AW_CL)mark_basemode|((all_but == 0) ? 4 : 8)|(i*16)); |
|---|
| 341 | } |
|---|
| 342 | if (!all_but) awm->insert_separator(); |
|---|
| 343 | } |
|---|
| 344 | |
|---|
| 345 | awm->close_sub_menu(); |
|---|
| 346 | #undef MAXLABEL |
|---|
| 347 | #undef MAXENTRY |
|---|
| 348 | } |
|---|
| 349 | |
|---|
| 350 | static char *create_mark_menu_entry(const char *attrib, const char *entry_template) { |
|---|
| 351 | char *entry = 0; |
|---|
| 352 | if (attrib) { |
|---|
| 353 | bool append = attrib[0] == '-'; // if attrib starts with '-' then append (otherwise prepend) |
|---|
| 354 | if (append) ++attrib; // skip '-' |
|---|
| 355 | |
|---|
| 356 | if (append) { |
|---|
| 357 | char *spaced_attrib = GBS_global_string_copy(" %s", attrib); |
|---|
| 358 | entry = GBS_global_string_copy(entry_template, "", spaced_attrib); |
|---|
| 359 | free(spaced_attrib); |
|---|
| 360 | } |
|---|
| 361 | else { |
|---|
| 362 | char *spaced_attrib = GBS_global_string_copy("%s ", attrib); |
|---|
| 363 | entry = GBS_global_string_copy(entry_template, spaced_attrib, ""); |
|---|
| 364 | |
|---|
| 365 | if (islower(entry[0])) entry[0] = toupper(entry[0]); // Caps prepended lowercase 'attrib' |
|---|
| 366 | |
|---|
| 367 | free(spaced_attrib); |
|---|
| 368 | } |
|---|
| 369 | } |
|---|
| 370 | else { |
|---|
| 371 | entry = GBS_global_string_copy(entry_template, "", ""); |
|---|
| 372 | } |
|---|
| 373 | return entry; |
|---|
| 374 | } |
|---|
| 375 | static char *create_mark_menu_id(const char *attrib, const char *id_suffix) { |
|---|
| 376 | char *id = 0; |
|---|
| 377 | if (attrib) { |
|---|
| 378 | id = GBS_global_string_copy("%s_%s", attrib[0] == '-' ? attrib+1 : attrib, id_suffix); |
|---|
| 379 | } |
|---|
| 380 | else { |
|---|
| 381 | id = strdup(id_suffix); |
|---|
| 382 | } |
|---|
| 383 | return id; |
|---|
| 384 | } |
|---|
| 385 | |
|---|
| 386 | static void nt_insert_mark_topic(AW_window_menu_modes *awm, AW_active mask, const char *attrib, const char *id_suffix, const char *entry_template, |
|---|
| 387 | const char *hotkey, const char *helpfile, |
|---|
| 388 | AW_CB cb, AW_CL cl1, AW_CL cl2) |
|---|
| 389 | { |
|---|
| 390 | char *entry = create_mark_menu_entry(attrib, entry_template); |
|---|
| 391 | char *id = create_mark_menu_id(attrib, id_suffix); |
|---|
| 392 | |
|---|
| 393 | awm->insert_menu_topic(id, entry, hotkey, helpfile, mask, cb, cl1, cl2); |
|---|
| 394 | |
|---|
| 395 | free(id); |
|---|
| 396 | free(entry); |
|---|
| 397 | } |
|---|
| 398 | |
|---|
| 399 | static void nt_insert_mark_topics(AW_window_menu_modes *awm, AW_active mask, AWT_canvas *ntw, int affect, const char *attrib) |
|---|
| 400 | { |
|---|
| 401 | awt_assert(affect == (affect&MARK_MODE_UPPER_BITS)); // only bits 2 .. 4 are allowed |
|---|
| 402 | |
|---|
| 403 | nt_insert_mark_topic(awm, mask, attrib, "mark_all", "Mark all %sSpecies%s", "M", "sp_mrk_all.hlp", (AW_CB)NT_mark_all_cb, (AW_CL)ntw, (AW_CL)(1+affect)); |
|---|
| 404 | nt_insert_mark_topic(awm, mask, attrib, "unmark_all", "Unmark all %sSpecies%s", "U", "sp_umrk_all.hlp", (AW_CB)NT_mark_all_cb, (AW_CL)ntw, (AW_CL)(0+affect)); |
|---|
| 405 | nt_insert_mark_topic(awm, mask, attrib, "swap_marked", "Invert marks of all %sSpecies%s", "I", "sp_invert_mrk.hlp", (AW_CB)NT_mark_all_cb, (AW_CL)ntw, (AW_CL)(2+affect)); |
|---|
| 406 | awm->insert_separator(); |
|---|
| 407 | |
|---|
| 408 | char *label = create_mark_menu_entry(attrib, "%sSpecies%s in Tree"); |
|---|
| 409 | |
|---|
| 410 | awm->insert_sub_menu(label, "T"); |
|---|
| 411 | nt_insert_mark_topic(awm, mask, attrib, "mark_tree", "Mark %sSpecies%s in Tree", "M", "sp_mrk_tree.hlp", (AW_CB)NT_mark_tree_cb, (AW_CL)ntw, (AW_CL)(1+affect)); |
|---|
| 412 | nt_insert_mark_topic(awm, mask, attrib, "unmark_tree", "Unmark %sSpecies%s in Tree", "U", "sp_umrk_tree.hlp", (AW_CB)NT_mark_tree_cb, (AW_CL)ntw, (AW_CL)(0+affect)); |
|---|
| 413 | nt_insert_mark_topic(awm, mask, attrib, "swap_marked_tree", "Invert marks of %sSpecies%s in Tree", "I", "sp_invert_mrk.hlp", (AW_CB)NT_mark_tree_cb, (AW_CL)ntw, (AW_CL)(2+affect)); |
|---|
| 414 | awm->close_sub_menu(); |
|---|
| 415 | |
|---|
| 416 | freeset(label, create_mark_menu_entry(attrib, "%sSpecies%s NOT in Tree")); |
|---|
| 417 | |
|---|
| 418 | awm->insert_sub_menu(label, "N"); |
|---|
| 419 | nt_insert_mark_topic(awm, mask, attrib, "mark_nontree", "Mark %sSpecies%s NOT in Tree", "M", "sp_mrk_tree.hlp", (AW_CB)NT_mark_nontree_cb, (AW_CL)ntw, (AW_CL)(1+affect)); |
|---|
| 420 | nt_insert_mark_topic(awm, mask, attrib, "unmark_nontree", "Unmark %sSpecies%s NOT in Tree", "U", "sp_umrk_tree.hlp", (AW_CB)NT_mark_nontree_cb, (AW_CL)ntw, (AW_CL)(0+affect)); |
|---|
| 421 | nt_insert_mark_topic(awm, mask, attrib, "swap_marked_nontree", "Invert marks of %sSpecies%s NOT in Tree", "I", "sp_invert_mrk.hlp", (AW_CB)NT_mark_nontree_cb, (AW_CL)ntw, (AW_CL)(2+affect)); |
|---|
| 422 | awm->close_sub_menu(); |
|---|
| 423 | |
|---|
| 424 | free(label); |
|---|
| 425 | } |
|---|
| 426 | |
|---|
| 427 | void NT_insert_mark_submenus(AW_window_menu_modes *awm, AWT_canvas *ntw, int insert_as_submenu) { |
|---|
| 428 | if (insert_as_submenu) { |
|---|
| 429 | awm->insert_sub_menu("Mark species", "M"); |
|---|
| 430 | } |
|---|
| 431 | |
|---|
| 432 | { |
|---|
| 433 | awm->insert_menu_topic("count_marked", "Count Marked Species", "C","sp_count_mrk.hlp", AWM_ALL, (AW_CB)NT_count_mark_all_cb, (AW_CL)ntw, 0 ); |
|---|
| 434 | awm->insert_separator(); |
|---|
| 435 | nt_insert_mark_topics(awm, AWM_ALL, ntw, 0, 0); |
|---|
| 436 | awm->insert_separator(); |
|---|
| 437 | |
|---|
| 438 | awm->insert_sub_menu("Complete sequences", "o"); |
|---|
| 439 | nt_insert_mark_topics(awm, AWM_EXP, ntw, 4, "complete"); |
|---|
| 440 | awm->close_sub_menu(); |
|---|
| 441 | |
|---|
| 442 | awm->insert_sub_menu("Partial sequences", "P"); |
|---|
| 443 | nt_insert_mark_topics(awm, AWM_EXP, ntw, 8, "partial"); |
|---|
| 444 | awm->close_sub_menu(); |
|---|
| 445 | |
|---|
| 446 | awm->insert_sub_menu("Current Alignment", "A"); |
|---|
| 447 | nt_insert_mark_topics(awm, AWM_EXP, ntw, 16, "-with data"); |
|---|
| 448 | awm->close_sub_menu(); |
|---|
| 449 | } |
|---|
| 450 | |
|---|
| 451 | if (insert_as_submenu) { |
|---|
| 452 | awm->close_sub_menu(); |
|---|
| 453 | } |
|---|
| 454 | } |
|---|
| 455 | |
|---|
| 456 | static void nt_save_changed_tree(AWT_canvas *ntw) { |
|---|
| 457 | GB_ERROR error = AWT_TREE(ntw)->save(ntw->gb_main,0,0,0); |
|---|
| 458 | if (error) aw_message(error); |
|---|
| 459 | ntw->zoom_reset(); |
|---|
| 460 | ntw->refresh(); |
|---|
| 461 | } |
|---|
| 462 | |
|---|
| 463 | // --------------------------------------- |
|---|
| 464 | // Automated collapse/expand tree |
|---|
| 465 | // --------------------------------------- |
|---|
| 466 | |
|---|
| 467 | static void nt_group_tree(AWT_canvas *ntw, int mode, int color_group) { |
|---|
| 468 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 469 | |
|---|
| 470 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 471 | AWT_TREE(ntw)->group_tree(AWT_TREE(ntw)->tree_root, mode, color_group); |
|---|
| 472 | nt_save_changed_tree(ntw); |
|---|
| 473 | } |
|---|
| 474 | |
|---|
| 475 | void NT_group_tree_cb (void *, AWT_canvas *ntw){ nt_group_tree(ntw, 0, 0); } |
|---|
| 476 | void NT_group_not_marked_cb(void *, AWT_canvas *ntw){ nt_group_tree(ntw, 1, 0); } |
|---|
| 477 | void NT_group_terminal_cb (void *, AWT_canvas *ntw){ nt_group_tree(ntw, 2, 0); } |
|---|
| 478 | void NT_ungroup_all_cb (void *, AWT_canvas *ntw){ nt_group_tree(ntw, 4, 0); } |
|---|
| 479 | |
|---|
| 480 | void NT_group_not_color_cb(AW_window *, AW_CL cl_ntw, AW_CL cl_colornum) { |
|---|
| 481 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 482 | int colornum = (int)cl_colornum; |
|---|
| 483 | |
|---|
| 484 | nt_group_tree(ntw, 8, colornum); |
|---|
| 485 | } |
|---|
| 486 | |
|---|
| 487 | // ---------------------------------------------------------------------------------------------------- |
|---|
| 488 | // void NT_insert_color_collapse_submenu(AW_window_menu_modes *awm, AWT_canvas *ntree_canvas) |
|---|
| 489 | // ---------------------------------------------------------------------------------------------------- |
|---|
| 490 | void NT_insert_color_collapse_submenu(AW_window_menu_modes *awm, AWT_canvas *ntree_canvas) { |
|---|
| 491 | #define MAXLABEL 30 |
|---|
| 492 | #define MAXENTRY (AW_COLOR_GROUP_NAME_LEN+10) |
|---|
| 493 | |
|---|
| 494 | awt_assert(ntree_canvas != 0); |
|---|
| 495 | |
|---|
| 496 | awm->insert_sub_menu("Group all except Color ...", "C"); |
|---|
| 497 | |
|---|
| 498 | char label_buf[MAXLABEL+1]; |
|---|
| 499 | char entry_buf[MAXENTRY+1]; |
|---|
| 500 | char hotkey[] = "x"; |
|---|
| 501 | const char *hotkeys = "N1234567890 "; |
|---|
| 502 | |
|---|
| 503 | for (int i = 0; i <= AW_COLOR_GROUPS; ++i) { |
|---|
| 504 | sprintf(label_buf, "tree_group_not_color_%i", i); |
|---|
| 505 | |
|---|
| 506 | hotkey[0] = hotkeys[i]; |
|---|
| 507 | if (hotkey[0] == ' ') hotkey[0] = 0; |
|---|
| 508 | |
|---|
| 509 | if (i) { |
|---|
| 510 | char *color_group_name = AW_get_color_group_name(awm->get_root(), i); |
|---|
| 511 | sprintf(entry_buf, "%s group '%s'", hotkey, color_group_name); |
|---|
| 512 | free(color_group_name); |
|---|
| 513 | } |
|---|
| 514 | else { |
|---|
| 515 | strcpy(entry_buf, "No color group"); |
|---|
| 516 | } |
|---|
| 517 | |
|---|
| 518 | awm->insert_menu_topic(awm->local_id(label_buf), entry_buf, hotkey, "tgroupcolor.hlp", AWM_ALL, NT_group_not_color_cb, (AW_CL)ntree_canvas, (AW_CL)i); |
|---|
| 519 | } |
|---|
| 520 | |
|---|
| 521 | awm->close_sub_menu(); |
|---|
| 522 | |
|---|
| 523 | #undef MAXLABEL |
|---|
| 524 | #undef MAXENTRY |
|---|
| 525 | } |
|---|
| 526 | |
|---|
| 527 | // ------------------------ |
|---|
| 528 | // tree sorting : |
|---|
| 529 | // ------------------------ |
|---|
| 530 | |
|---|
| 531 | void NT_resort_tree_cb(void *dummy, AWT_canvas *ntw,int type) |
|---|
| 532 | { |
|---|
| 533 | AWUSE(dummy); |
|---|
| 534 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 535 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 536 | int stype; |
|---|
| 537 | switch(type){ |
|---|
| 538 | case 0: stype = 0; break; |
|---|
| 539 | case 1: stype = 2; break; |
|---|
| 540 | default:stype = 1; break; |
|---|
| 541 | } |
|---|
| 542 | AWT_TREE(ntw)->resort_tree(stype); |
|---|
| 543 | nt_save_changed_tree(ntw); |
|---|
| 544 | } |
|---|
| 545 | |
|---|
| 546 | void NT_reset_lzoom_cb(void *dummy, AWT_canvas *ntw) |
|---|
| 547 | { |
|---|
| 548 | AWUSE(dummy); |
|---|
| 549 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 550 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 551 | AWT_TREE(ntw)->tree_root_display = AWT_TREE(ntw)->tree_root; |
|---|
| 552 | ntw->zoom_reset(); |
|---|
| 553 | ntw->refresh(); |
|---|
| 554 | } |
|---|
| 555 | |
|---|
| 556 | void NT_reset_pzoom_cb(void *dummy, AWT_canvas *ntw) |
|---|
| 557 | { |
|---|
| 558 | AWUSE(dummy); |
|---|
| 559 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 560 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 561 | ntw->zoom_reset(); |
|---|
| 562 | ntw->refresh(); |
|---|
| 563 | } |
|---|
| 564 | |
|---|
| 565 | void NT_set_tree_style(void *dummy, AWT_canvas *ntw, AP_tree_sort type) |
|---|
| 566 | { |
|---|
| 567 | AWUSE(dummy); |
|---|
| 568 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 569 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 570 | AWT_TREE(ntw)->set_tree_type(type); |
|---|
| 571 | ntw->zoom_reset(); |
|---|
| 572 | ntw->refresh(); |
|---|
| 573 | } |
|---|
| 574 | |
|---|
| 575 | void NT_remove_leafs(void *, AWT_canvas *ntw, long mode) { |
|---|
| 576 | GB_transaction ta(ntw->gb_main); |
|---|
| 577 | |
|---|
| 578 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 579 | if (AWT_TREE(ntw)->tree_root) { |
|---|
| 580 | AWT_TREE(ntw)->tree_root->remove_leafs(ntw->gb_main, (int)mode); |
|---|
| 581 | if (AWT_TREE(ntw)->tree_root) AWT_TREE(ntw)->tree_root->compute_tree(ntw->gb_main); |
|---|
| 582 | nt_save_changed_tree(ntw); |
|---|
| 583 | } |
|---|
| 584 | else { |
|---|
| 585 | aw_message("Got no tree"); |
|---|
| 586 | } |
|---|
| 587 | } |
|---|
| 588 | |
|---|
| 589 | void NT_remove_bootstrap(AW_window*, AW_CL cl_ntw, AW_CL) // delete all bootstrap values |
|---|
| 590 | { |
|---|
| 591 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 592 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 593 | |
|---|
| 594 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 595 | |
|---|
| 596 | AP_tree *tree_root = AWT_TREE(ntw)->tree_root; |
|---|
| 597 | if (tree_root) { |
|---|
| 598 | tree_root->remove_bootstrap(ntw->gb_main); |
|---|
| 599 | tree_root->compute_tree(ntw->gb_main); |
|---|
| 600 | nt_save_changed_tree(ntw); |
|---|
| 601 | } |
|---|
| 602 | } |
|---|
| 603 | |
|---|
| 604 | void NT_reset_branchlengths(AW_window*, AW_CL cl_ntw, AW_CL) // set all branchlengths to 0.1 |
|---|
| 605 | { |
|---|
| 606 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 607 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 608 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 609 | |
|---|
| 610 | AP_tree *tree_root = AWT_TREE(ntw)->tree_root; |
|---|
| 611 | if (tree_root){ |
|---|
| 612 | tree_root->reset_branchlengths(ntw->gb_main); |
|---|
| 613 | tree_root->compute_tree(ntw->gb_main); |
|---|
| 614 | nt_save_changed_tree(ntw); |
|---|
| 615 | } |
|---|
| 616 | } |
|---|
| 617 | |
|---|
| 618 | void NT_move_boot_branch(AW_window*, AW_CL cl_ntw, AW_CL cl_direction) // copy branchlengths to bootstraps (or vice versa) |
|---|
| 619 | { |
|---|
| 620 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 621 | int direction = (int)cl_direction; |
|---|
| 622 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 623 | |
|---|
| 624 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 625 | |
|---|
| 626 | AP_tree *tree_root = AWT_TREE(ntw)->tree_root; |
|---|
| 627 | if (tree_root) { |
|---|
| 628 | if (direction == 0) tree_root->bootstrap2branchlen(ntw->gb_main); |
|---|
| 629 | else tree_root->branchlen2bootstrap(ntw->gb_main); |
|---|
| 630 | |
|---|
| 631 | tree_root->compute_tree(ntw->gb_main); |
|---|
| 632 | nt_save_changed_tree(ntw); |
|---|
| 633 | |
|---|
| 634 | char *adviceText = GBS_global_string_copy("Please note, that you just overwrote your existing %s.", |
|---|
| 635 | direction ? "bootstrap values" : "branchlengths"); |
|---|
| 636 | AWT_advice(adviceText, AWT_ADVICE_TOGGLE|AWT_ADVICE_HELP, 0, "tbl_boot2len.hlp"); |
|---|
| 637 | free(adviceText); |
|---|
| 638 | } |
|---|
| 639 | } |
|---|
| 640 | |
|---|
| 641 | void NT_scale_tree(AW_window*, AW_CL cl_ntw, AW_CL) // scale branchlengths |
|---|
| 642 | { |
|---|
| 643 | char *answer = aw_input("Enter scale factor", "Scale branchlengths by factor:", "100"); |
|---|
| 644 | if (answer) { |
|---|
| 645 | AWT_canvas *ntw = (AWT_canvas*)cl_ntw; |
|---|
| 646 | double factor = atof(answer); |
|---|
| 647 | GB_transaction ta(ntw->gb_main); |
|---|
| 648 | |
|---|
| 649 | AP_tree *tree_root = AWT_TREE(ntw)->tree_root; |
|---|
| 650 | if (tree_root){ |
|---|
| 651 | tree_root->scale_branchlengths(ntw->gb_main, factor); |
|---|
| 652 | tree_root->compute_tree(ntw->gb_main); |
|---|
| 653 | nt_save_changed_tree(ntw); |
|---|
| 654 | } |
|---|
| 655 | free(answer); |
|---|
| 656 | } |
|---|
| 657 | } |
|---|
| 658 | |
|---|
| 659 | void NT_jump_cb(AW_window *dummy, AWT_canvas *ntw, AW_CL auto_expand_groups) |
|---|
| 660 | { |
|---|
| 661 | AWUSE(dummy); |
|---|
| 662 | AW_window *aww = ntw->aww; |
|---|
| 663 | if (!AWT_TREE(ntw)) return; |
|---|
| 664 | GB_transaction gb_dummy(ntw->gb_main); |
|---|
| 665 | AWT_TREE(ntw)->check_update(ntw->gb_main); |
|---|
| 666 | char *name = aww->get_root()->awar(AWAR_SPECIES_NAME)->read_string(); |
|---|
| 667 | if (name[0]){ |
|---|
| 668 | AP_tree * found = AWT_TREE(ntw)->search(AWT_TREE(ntw)->tree_root_display,name); |
|---|
| 669 | if (!found && AWT_TREE(ntw)->tree_root_display != AWT_TREE(ntw)->tree_root){ |
|---|
| 670 | found = AWT_TREE(ntw)->search(AWT_TREE(ntw)->tree_root,name); |
|---|
| 671 | if (found) { |
|---|
| 672 | // now i found a species outside logical zoomed tree |
|---|
| 673 | aw_message("Species found outside displayed subtree: zoom reset done"); |
|---|
| 674 | AWT_TREE(ntw)->tree_root_display = AWT_TREE(ntw)->tree_root; |
|---|
| 675 | ntw->zoom_reset(); |
|---|
| 676 | } |
|---|
| 677 | } |
|---|
| 678 | switch (AWT_TREE(ntw)->tree_sort) { |
|---|
| 679 | case AP_TREE_IRS: |
|---|
| 680 | case AP_TREE_NORMAL:{ |
|---|
| 681 | if (auto_expand_groups) { |
|---|
| 682 | bool changed = false; |
|---|
| 683 | while (found) { |
|---|
| 684 | if (found->gr.grouped) { |
|---|
| 685 | found->gr.grouped = 0; |
|---|
| 686 | changed = true; |
|---|
| 687 | } |
|---|
| 688 | found = found->father; |
|---|
| 689 | } |
|---|
| 690 | if (changed) { |
|---|
| 691 | AWT_TREE(ntw)->tree_root->compute_tree(ntw->gb_main); |
|---|
| 692 | GB_ERROR error = AWT_TREE(ntw)->save(ntw->gb_main, 0, 0, 0); |
|---|
| 693 | if (error) aw_message(error); |
|---|
| 694 | ntw->zoom_reset(); |
|---|
| 695 | } |
|---|
| 696 | } |
|---|
| 697 | AW_device *device = aww->get_size_device(AW_MIDDLE_AREA); |
|---|
| 698 | device->set_filter(AW_SIZE); |
|---|
| 699 | device->reset(); |
|---|
| 700 | ntw->init_device(device); |
|---|
| 701 | ntw->tree_disp->show(device); |
|---|
| 702 | AW_rectangle screen; |
|---|
| 703 | device->get_area_size(&screen); |
|---|
| 704 | AW_pos ys = AWT_TREE(ntw)->y_cursor; |
|---|
| 705 | AW_pos xs = 0; |
|---|
| 706 | if (AWT_TREE(ntw)->x_cursor != 0.0 || ys != 0.0) { |
|---|
| 707 | AW_pos x, y; |
|---|
| 708 | device->transform(xs, ys, x, y); |
|---|
| 709 | if (y < 0.0) { |
|---|
| 710 | ntw->scroll(aww, 0, (int) (y - screen.b * .5)); |
|---|
| 711 | } else if (y > screen.b) { |
|---|
| 712 | ntw->scroll(aww, 0, (int) (y - screen.b * .5)); |
|---|
| 713 | } |
|---|
| 714 | }else{ |
|---|
| 715 | if (auto_expand_groups){ |
|---|
| 716 | aw_message(GBS_global_string("Sorry, I didn't find the species '%s' in this tree", name)); |
|---|
| 717 | } |
|---|
| 718 | } |
|---|
| 719 | ntw->refresh(); |
|---|
| 720 | break; |
|---|
| 721 | } |
|---|
| 722 | case AP_LIST_NDS: |
|---|
| 723 | { |
|---|
| 724 | AW_device *device = aww->get_size_device(AW_MIDDLE_AREA); |
|---|
| 725 | device->set_filter(AW_SIZE); |
|---|
| 726 | device->reset(); |
|---|
| 727 | ntw->init_device(device); |
|---|
| 728 | ntw->tree_disp->show(device); |
|---|
| 729 | AW_rectangle screen; |
|---|
| 730 | device->get_area_size(&screen); |
|---|
| 731 | AW_pos ys = AWT_TREE(ntw)->y_cursor; |
|---|
| 732 | AW_pos xs = 0; |
|---|
| 733 | if (AWT_TREE(ntw)->x_cursor != 0.0 || ys != 0.0) { |
|---|
| 734 | AW_pos x, y; |
|---|
| 735 | device->transform(xs, ys, x, y); |
|---|
| 736 | if (y < 0.0) { |
|---|
| 737 | ntw->scroll(aww, 0, (int) (y - screen.b * .5)); |
|---|
| 738 | } else if (y > screen.b) { |
|---|
| 739 | ntw->scroll(aww, 0, (int) (y - screen.b * .5)); |
|---|
| 740 | } |
|---|
| 741 | }else{ |
|---|
| 742 | if (auto_expand_groups){ |
|---|
| 743 | aw_message(GBS_global_string("Sorry, your species '%s' is not marked and therefore not in this list", name)); |
|---|
| 744 | } |
|---|
| 745 | } |
|---|
| 746 | ntw->refresh(); |
|---|
| 747 | break; |
|---|
| 748 | } |
|---|
| 749 | case AP_TREE_RADIAL:{ |
|---|
| 750 | AWT_TREE(ntw)->tree_root_display = 0; |
|---|
| 751 | AWT_TREE(ntw)->jump(AWT_TREE(ntw)->tree_root, name); |
|---|
| 752 | if (!AWT_TREE(ntw)->tree_root_display) { |
|---|
| 753 | aw_message(GBS_global_string("Sorry, I didn't find the species '%s' in this tree", name)); |
|---|
| 754 | AWT_TREE(ntw)->tree_root_display = AWT_TREE(ntw)->tree_root; |
|---|
| 755 | } |
|---|
| 756 | ntw->zoom_reset(); |
|---|
| 757 | ntw->refresh(); |
|---|
| 758 | break; |
|---|
| 759 | } |
|---|
| 760 | default : awt_assert(0); break; |
|---|
| 761 | } |
|---|
| 762 | } |
|---|
| 763 | free(name); |
|---|
| 764 | } |
|---|
| 765 | |
|---|
| 766 | void NT_jump_cb_auto(AW_window *dummy, AWT_canvas *ntw){ // jump only if auto jump is set |
|---|
| 767 | if (AWT_TREE(ntw)->tree_sort == AP_TREE_NORMAL || AWT_TREE(ntw)->tree_sort == AP_LIST_NDS) { |
|---|
| 768 | if (ntw->aww->get_root()->awar(AWAR_DTREE_AUTO_JUMP)->read_int()) { |
|---|
| 769 | NT_jump_cb(dummy,ntw,0); |
|---|
| 770 | return; |
|---|
| 771 | } |
|---|
| 772 | } |
|---|
| 773 | ntw->refresh(); |
|---|
| 774 | } |
|---|
| 775 | |
|---|
| 776 | inline const char *plural(int val) { |
|---|
| 777 | return "s"+(val == 1); |
|---|
| 778 | } |
|---|
| 779 | |
|---|
| 780 | void NT_reload_tree_event(AW_root *awr, AWT_canvas *ntw, GB_BOOL set_delete_cbs) |
|---|
| 781 | { |
|---|
| 782 | GB_push_transaction(ntw->gb_main); |
|---|
| 783 | char *tree_name = awr->awar(ntw->user_awar)->read_string(); |
|---|
| 784 | |
|---|
| 785 | GB_ERROR error = ntw->tree_disp->load(ntw->gb_main, tree_name,1,set_delete_cbs); // linked |
|---|
| 786 | if (error) { |
|---|
| 787 | aw_message(error); |
|---|
| 788 | } |
|---|
| 789 | else { |
|---|
| 790 | int zombies, duplicates; |
|---|
| 791 | ((AWT_graphic_tree*)ntw->tree_disp)->get_zombies_and_duplicates(zombies, duplicates); |
|---|
| 792 | |
|---|
| 793 | if (zombies || duplicates) { |
|---|
| 794 | const char *msg = 0; |
|---|
| 795 | if (duplicates) { |
|---|
| 796 | if (zombies) msg = GBS_global_string("%i zombie%s and %i duplicate%s", zombies, plural(zombies), duplicates, plural(duplicates)); |
|---|
| 797 | else msg = GBS_global_string("%i duplicate%s", duplicates, plural(duplicates)); |
|---|
| 798 | } |
|---|
| 799 | else { |
|---|
| 800 | awt_assert(zombies); |
|---|
| 801 | msg = GBS_global_string("%i zombie%s", zombies, plural(zombies)); |
|---|
| 802 | } |
|---|
| 803 | aw_message(GBS_global_string("%s in '%s'", msg, tree_name)); |
|---|
| 804 | } |
|---|
| 805 | } |
|---|
| 806 | free(tree_name); |
|---|
| 807 | ntw->zoom_reset(); |
|---|
| 808 | AWT_expose_cb(0,ntw,0); |
|---|
| 809 | GB_pop_transaction(ntw->gb_main); |
|---|
| 810 | } |
|---|
| 811 | |
|---|
| 812 | void NT_recompute_cb(AW_window *,AWT_canvas *ntw, AW_CL cl2) { |
|---|
| 813 | AWT_graphic_tree *gt = dynamic_cast<AWT_graphic_tree*>(ntw->tree_disp); |
|---|
| 814 | awt_assert(gt); |
|---|
| 815 | |
|---|
| 816 | gt->tree_root->compute_tree(ntw->gb_main); |
|---|
| 817 | AWT_expose_cb (ntw->aww, ntw, cl2 ); |
|---|
| 818 | } |
|---|
| 819 | |
|---|
| 820 | void NT_remove_species_in_tree_from_hash(AP_tree *tree,GB_HASH *hash) { |
|---|
| 821 | if (!tree) return; |
|---|
| 822 | if (tree->is_leaf && tree->name) { |
|---|
| 823 | GBS_write_hash(hash,tree->name,0); // delete species in hash table |
|---|
| 824 | }else{ |
|---|
| 825 | NT_remove_species_in_tree_from_hash(tree->leftson,hash); |
|---|
| 826 | NT_remove_species_in_tree_from_hash(tree->rightson,hash); |
|---|
| 827 | } |
|---|
| 828 | } |
|---|
| 829 | |
|---|