source: branches/species/NTREE/NT_extern.cxx

Last change on this file was 19700, checked in by westram, 2 days ago
  • rename public methods:
    • NT_generate_treeTREE_generate_display.
    • nt_create_configurationcreate_species_selection
    • create_configuration_admin_windowcreate_species_selection_window
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 79.2 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : NT_extern.cxx                                     //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "map_viewer.h"
12#include "NT_local.h"
13#include "ad_trees.h"
14#include "NT_group_search.h"
15
16#include <seq_quality.h>
17#include <multi_probe.hxx>
18#include <st_window.hxx>
19#include <GEN.hxx>
20#include <EXP.hxx>
21
22#include <TreeCallbacks.hxx>
23#include <AW_rename.hxx>
24#include <probe_gui.hxx>
25#include <primer_design.hxx>
26#include <gde.hxx>
27#include <awtc_submission.hxx>
28
29#include <macros.hxx>
30#include <MacroExitor.hxx>
31#include <xcmd.hxx>
32#include <nds.h>
33#include <db_query.h>
34#include <dbui.h>
35#include <refentries.h>
36#include <insdel.h>
37
38#include <awti_export.hxx>
39#include <awti_import.hxx>
40
41#include <app.hxx>
42#include <input_mask.hxx>
43#include <sel_boxes.hxx>
44#include <www.hxx>
45#include <TreeAwars.hxx>
46#include <arb_spec.hxx>
47
48#include <aw_color_groups.hxx>
49#include <aw_advice.hxx>
50#include <aw_preset.hxx>
51#include <aw_awars.hxx>
52#include <aw_global_awars.hxx>
53#include <aw_file.hxx>
54#include <arb_progress.h>
55#include <aw_select.hxx>
56#include <aw_system.hxx>
57#include <rootAsWin.h>
58
59#include <ad_cb.h>
60
61#include <arb_strbuf.h>
62#include <arb_file.h>
63#include <arb_version.h>
64
65#include <saicalc.h>
66
67#include <string>
68
69#if defined(DEVEL_RALF)
70# define TRACE_GROUP_SELECTION
71#endif
72
73#define AWAR_EXPORT_NDS              "tmp/export_nds"
74#define AWAR_EXPORT_NDS_SEPARATOR    AWAR_EXPORT_NDS "/delimiter"
75#define AWAR_MARKED_SPECIES_COUNTER  "tmp/disp_marked_species"
76#define AWAR_NTREE_TITLE_MODE        "tmp/title_mode"
77
78void create_probe_design_variables(AW_root *aw_root, AW_default def, AW_default global);
79
80void       create_insertDeleteColumn_variables(AW_root *root, AW_default db1);
81AW_window *create_insertDeleteColumn_window(AW_root *root);
82AW_window *create_insertDeleteBySAI_window(AW_root *root, GBDATA *gb_main);
83
84AW_window *create_tree_window(AW_root *aw_root, AWT_graphic *awd);
85
86enum Export_Type {
87    EXPORT_SPACE_PADDED_RIGHT_ALIGNED = 1, // format info (using spaces). slow - uses one extra pass for column width detection.
88    EXPORT_SPACE_PADDED_LEFT_ALIGNED  = 4, // dito, but left aligned
89    EXPORT_TAB_SEPARATED              = 2, // format info (using 1 tab per column - for easy import into star-calc, excel, etc. )
90    EXPORT_COMMA_SEPARATED            = 3, // like EXPORT_TAB_SEPARATED, but using commas
91};
92
93static void nt_changesecurity(AW_root *aw_root) {
94    int level = aw_root->awar(AWAR_SECURITY_LEVEL)->read_int();
95    GB_push_transaction(GLOBAL.gb_main);
96    GB_change_my_security(GLOBAL.gb_main, level); // changes user security
97    GB_pop_transaction(GLOBAL.gb_main);
98}
99
100static void export_nds_cb(AW_window *aww, bool do_print) {
101    AW_root *aw_root = aww->get_root();
102    char    *name    = aw_root->awar(AWAR_EXPORT_NDS"/file_name")->read_string();
103    FILE    *out     = fopen(name, "w");
104
105    if (!out) {
106        aw_message("Error: Cannot open and write to file");
107    }
108    else {
109        GB_transaction ta(GLOBAL.gb_main);
110
111        char              *tree_name    = aw_root->awar(AWAR_TREE)->read_string();
112        const Export_Type  export_type  = (Export_Type)aw_root->awar(AWAR_EXPORT_NDS_SEPARATOR)->read_int();
113        const NDS_Type     nds_type     = export_type == EXPORT_COMMA_SEPARATED ? NDS_OUTPUT_COMMA_SEPARATED : NDS_OUTPUT_TAB_SEPARATED;
114        const bool         spacePadded  = export_type == EXPORT_SPACE_PADDED_LEFT_ALIGNED || export_type == EXPORT_SPACE_PADDED_RIGHT_ALIGNED;
115        const int          passesNeeded = spacePadded ? 2 : 1;
116        NDS_Labeler        labeler(nds_type);
117
118        arb_progress progress("Exporting data using NDS", passesNeeded*GBT_count_marked_species(GLOBAL.gb_main));
119
120        const size_t max_col = std::max(labeler.max_columns(GLOBAL.gb_main), 1L);
121        size_t       col_max_len[max_col];
122
123        const char *col_format = NULp;
124
125        if (spacePadded) {
126            for (size_t i = 0; i<max_col; ++i) {
127                col_max_len[i] = 0;
128            }
129            if (export_type == EXPORT_SPACE_PADDED_RIGHT_ALIGNED) {
130                col_format = "%*s";
131            }
132            else {
133                col_format = "%-*s";
134            }
135        }
136
137        for (int pass = 1; pass<=passesNeeded; ++pass) {
138            for (GBDATA *gb_species = GBT_first_marked_species(GLOBAL.gb_main);
139                 gb_species;
140                 gb_species = GBT_next_marked_species(gb_species))
141            {
142                const char *label = labeler.speciesLabel(GLOBAL.gb_main, gb_species, NULp, tree_name);
143
144                if (spacePadded) {
145                    ConstStrArray parts;
146                    GBT_split_string(parts, label, "\t", SPLIT_KEEPEMPTY);
147
148                    size_t col_count = parts.size();
149                    nt_assert(col_count<=max_col);
150
151                    if (pass == 1) { // track maximum used width for all columns
152                        for (size_t i = 0; i<col_count; ++i) {
153                            col_max_len[i] = std::max(col_max_len[i], strlen(parts[i]));
154                        }
155                    }
156                    else { // format according to tracked widths
157                        for (size_t i = 0; i<col_count; ++i) {
158                            if (i) fputc(' ', out);
159
160                            arb_assert(col_max_len[i]>0);        // otherwise empty, unused column (might be ok, but might need different handling)
161                            arb_assert(col_max_len[i]<=INT_MAX); // (protect cast below)
162
163                            if (export_type == EXPORT_SPACE_PADDED_LEFT_ALIGNED && i == (col_count-1)) { // left aligned and last column
164                                fputs(parts[i], out);
165                            }
166                            else {
167                                fprintf(out, col_format, int(col_max_len[i]), parts[i]);
168                            }
169                        }
170                        fputc('\n', out);
171                    }
172                }
173                else {
174                    fprintf(out, "%s\n", label);
175                }
176                ++progress;
177            }
178        }
179
180        AW_refresh_fileselection(aw_root, AWAR_EXPORT_NDS);
181        fclose(out);
182        if (do_print) {
183            GB_ERROR error = GB_textprint(name);
184            if (error) aw_message(error);
185        }
186        free(tree_name);
187    }
188    free(name);
189}
190
191static AW_window *create_nds_export_window(AW_root *root) {
192    AW_window_simple *aws = new AW_window_simple;
193    aws->init(root, "EXPORT_NDS_OF_MARKED", "EXPORT NDS OF MARKED SPECIES");
194    aws->load_xfig("sel_box_nds.fig");
195
196    aws->callback(AW_POPDOWN);
197    aws->at("close");
198    aws->create_button("CLOSE", "CLOSE", "C");
199
200    aws->callback(makeHelpCallback("arb_export_nds.hlp"));
201    aws->at("help");
202    aws->create_button("HELP", "HELP", "H");
203
204    aws->at("save");
205    aws->callback(makeWindowCallback(export_nds_cb, false));
206    aws->create_button("SAVE", "SAVE", "S");
207
208    aws->at("print");
209    aws->callback(makeWindowCallback(export_nds_cb, true));
210    aws->create_button("PRINT", "PRINT", "P");
211
212    aws->at("toggle1");
213    aws->label("Column output");
214    aws->create_option_menu(AWAR_EXPORT_NDS_SEPARATOR);
215    aws->insert_option        ("Space padded (left aligned)",  "S", EXPORT_SPACE_PADDED_LEFT_ALIGNED);
216    aws->insert_option        ("Space padded (right aligned)", "r", EXPORT_SPACE_PADDED_RIGHT_ALIGNED);
217    aws->insert_default_option("TAB separated",                "T", EXPORT_TAB_SEPARATED);
218    aws->insert_option        ("Comma separated",              "C", EXPORT_COMMA_SEPARATED);
219    aws->update_option_menu();
220
221    AW_create_standard_fileselection(aws, AWAR_EXPORT_NDS);
222
223    return aws;
224}
225
226static void create_export_nds_awars(AW_root *awr, AW_default def) {
227    AW_create_fileselection_awars(awr, AWAR_EXPORT_NDS, "", ".nds", "export.nds");
228    awr->awar_int(AWAR_EXPORT_NDS_SEPARATOR, EXPORT_TAB_SEPARATED, def);
229}
230
231static void selectedSpeciesChanged_cb(AW_root *awr) {
232    const char *value = awr->awar(AWAR_SPECIES_NAME)->read_char_pntr();
233    awr->awar(AWAR_INFO_BUTTON_TEXT)->write_string(value[0] ? value : "Species Info");
234    if (value[0]) {
235        awr->awar(AWAR_GROUP)->write_pointer(NULp); // deselect group when species gets selected
236#if defined(TRACE_GROUP_SELECTION)
237        fputs("clear AWAR_GROUP (because species selected)\n", stderr);
238#endif
239    }
240}
241
242static void expert_mode_changed_cb(AW_root *aw_root) {
243    aw_root->awar(AWAR_AWM_MASK)->write_int(aw_root->awar(AWAR_EXPERT)->read_int() ? AWM_ALL : AWM_BASIC); // publish expert-mode globally
244}
245
246static void NT_toggle_expert_mode(AW_window *aww) { aww->get_root()->awar(AWAR_EXPERT)->toggle_toggle(); }
247static void NT_toggle_focus_policy(AW_window *aww) { aww->get_root()->awar(AWAR_AW_FOCUS_FOLLOWS_MOUSE)->toggle_toggle(); }
248
249static void nt_create_all_awars(AW_root *awr) {
250    // creates awars for all modules reachable from ARB_NT main window
251
252    awr->awar_string(AWAR_FOOTER, "", AW_ROOT_DEFAULT);
253    if (GB_read_clients(GLOBAL.gb_main)>=0) {
254        awr->awar_string(AWAR_TREE, "", GLOBAL.gb_main);
255    }
256    else {
257        awr->awar_string(AWAR_TREE, "", AW_ROOT_DEFAULT);
258    }
259
260    awr->awar_string(AWAR_TOPAREA_SAIS, "ECOLI;HELIX;HELIX_NR", AW_ROOT_DEFAULT);
261
262    awr->awar_string(AWAR_SPECIES_NAME, "",     GLOBAL.gb_main);
263    awr->awar_string(AWAR_SAI_NAME, "",     GLOBAL.gb_main);
264    awr->awar_string(AWAR_SAI_GLOBAL, "",     GLOBAL.gb_main);
265    awr->awar_string(AWAR_MARKED_SPECIES_COUNTER, "unknown",    GLOBAL.gb_main);
266    awr->awar_string(AWAR_INFO_BUTTON_TEXT, "Species Info",    GLOBAL.gb_main);
267    awr->awar(AWAR_SPECIES_NAME)->add_callback(selectedSpeciesChanged_cb);
268    awr->awar_int(AWAR_NTREE_TITLE_MODE, 1);
269
270    awr->awar_string(AWAR_SAI_COLOR_STR, "", GLOBAL.gb_main); // sai visualization in probe match
271
272    GEN_create_awars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
273    EXP_create_awars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
274#if defined(DEBUG)
275    AWT_create_db_browser_awars(awr, AW_ROOT_DEFAULT);
276#endif // DEBUG
277
278    AW_create_namesadmin_awars(awr, GLOBAL.gb_main);
279
280    awr->awar_int(AWAR_SECURITY_LEVEL, 0, AW_ROOT_DEFAULT);
281    awr->awar(AWAR_SECURITY_LEVEL)->add_callback(nt_changesecurity);
282#if defined(DEBUG) && 0
283    awr->awar(AWAR_SECURITY_LEVEL)->write_int(6); // no security for debugging..
284#endif // DEBUG
285
286    create_insertDeleteColumn_variables(awr, AW_ROOT_DEFAULT);
287    create_probe_design_variables(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
288    create_primer_design_variables(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
289    create_trees_var(awr, AW_ROOT_DEFAULT);
290    DBUI::create_dbui_awars(awr);
291    AP_create_consensus_var(awr, AW_ROOT_DEFAULT);
292    {
293        GB_ERROR gde_err = GDE_init(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main, NULp, ARB_format_alignment, GDE_WINDOWTYPE_DEFAULT);
294        if (gde_err) GBK_terminatef("Fatal: %s", gde_err);
295    }
296    NT_create_transpro_variables(awr, AW_ROOT_DEFAULT);
297    NT_create_resort_awars(awr, AW_ROOT_DEFAULT);
298    NT_create_compare_taxonomy_awars(awr, AW_ROOT_DEFAULT);
299    NT_create_trackAliChanges_Awars(awr, AW_ROOT_DEFAULT);
300
301    NT_create_alignment_vars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
302    NT_create_extendeds_vars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
303    NDS_create_vars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
304    create_export_nds_awars(awr, AW_ROOT_DEFAULT);
305    create_group_search_awars(awr, AW_ROOT_DEFAULT);
306    TREE_create_awars(awr, GLOBAL.gb_main);
307
308    awr->awar_string(AWAR_ERROR_MESSAGES, "", GLOBAL.gb_main);
309    awr->awar_string(AWAR_DB_COMMENT, "<no description>", GLOBAL.gb_main);
310
311    AWTC_create_submission_variables(awr, GLOBAL.gb_main);
312    NT_createConcatenationAwars(awr, AW_ROOT_DEFAULT, GLOBAL.gb_main);
313    NT_createValidNamesAwars(awr, AW_ROOT_DEFAULT); // lothar
314    SQ_create_awars(awr, AW_ROOT_DEFAULT);
315    RefEntries::create_refentries_awars(awr, AW_ROOT_DEFAULT);
316
317    NT_create_multifurcate_tree_awars(awr, AW_ROOT_DEFAULT);
318
319    GB_ERROR error = ARB_bind_global_awars(GLOBAL.gb_main);
320    if (!error) {
321        AW_awar *awar_expert = awr->awar(AWAR_EXPERT);
322        awar_expert->add_callback(expert_mode_changed_cb);
323        awar_expert->touch();
324
325        awt_create_aww_vars(awr, AW_ROOT_DEFAULT);
326    }
327
328    if (error) aw_message(error);
329}
330
331// --------------------------------------------------------------------------------
332
333static void nt_run(const char *command) {
334    GB_ERROR error = GBK_system(command);
335    if (error) {
336        fprintf(stderr, "nt_run: Failed to run '%s' (Reason: %s)\n", command, error);
337#if defined(DEBUG)
338        GBK_dump_backtrace(stderr, "nt_run-error");
339#endif
340    }
341}
342
343void NT_start_if(const char *arb_ntree_args) {
344    if (arb_ntree_args && arb_ntree_args[0]) {
345        char *command = GBS_global_string_copy("arb_launcher --async arb %s", arb_ntree_args);
346        nt_run(command);
347        free(command);
348    }
349}
350
351void NT_exit_now_restart_if(AW_root *aw_root, int exitcode, const char *restart_ntree_args) { // goes to header: __ATTR__NORETURN
352    // Exit arb_ntree + optionally restart arb.
353    //
354    // 'exitcode':           exit with this code.
355    // 'restart_ntree_args': if null or empty  -> just exit;
356    //                       otherwise         -> restarts arb_ntree (with new ARB_PID).
357
358    AWTI_cleanup_importer(aw_root);
359
360    bool is_server_and_has_clients = GLOBAL.gb_main && GB_read_clients(GLOBAL.gb_main)>0;
361    ARB_disconnect_from_db(aw_root, GLOBAL.gb_main);
362    NT_start_if(restart_ntree_args);
363    if (is_server_and_has_clients) {
364        nt_run("(arb_clean session; echo ARB done) &"); // kills all clients
365    }
366    exit(exitcode);
367}
368
369class NT_MacroExitor: public MacroExitor {
370    int         exitcode;
371    std::string restart_ntree_args; // [if non-empty] restart arb with these arguments
372
373    __ATTR__NORETURN void perform_exit() OVERRIDE {
374        NT_exit_now_restart_if(get_root(), exitcode, restart_ntree_args.c_str());
375    }
376
377    GBDATA* get_gbmain_checked_for_save() OVERRIDE {
378        return GLOBAL.gb_main;
379    }
380
381public:
382    NT_MacroExitor(AW_root *aw_root_, int exitcode_, const char *restart_ntree_args_)
383        : MacroExitor(aw_root_, "ARB"),
384          exitcode(exitcode_),
385          restart_ntree_args(null2empty(restart_ntree_args_)) // restart arb if not empty/null
386    {}
387};
388
389void NT_confirm_exit_restart_if(AW_root *aw_root, int exitcode, const char *restart_ntree_args) {
390    // finally (may) exit ARB using NT_exit_now_restart_if(). see there for arguments.
391    //
392    // Beforehand this will happen:
393    // - if no macro running -> asks user to confirm quit (and maybe aborts exit/restart).
394    // - otherwise waits for macro to finish, then quits w/o question.
395
396    static SmartPtr<NT_MacroExitor> exitor;
397    if (exitor.isNull()) exitor = new NT_MacroExitor(aw_root, exitcode, restart_ntree_args);
398    exitor->maybe_exit_delayed();
399    if (!exitor->is_performing_delayed_exit()) exitor.setNull();
400}
401
402void NT_confirm_exit(AW_window *aws, int exitcode) {
403    NT_confirm_exit_restart_if(aws->get_root(), exitcode, NULp);
404}
405
406static void nt_start_2nd_arb(AW_window *aww, bool quit) {
407    // start 2nd arb with intro window
408    AW_root *aw_root = aww->get_root();
409    char    *dir4intro;
410    GB_split_full_path(aw_root->awar(AWAR_SAVED_DB_PATH)->read_char_pntr(), &dir4intro, NULp, NULp, NULp);
411    if (!dir4intro) {
412        dir4intro = ARB_strdup(".");
413    }
414
415    if (quit) {
416        NT_confirm_exit_restart_if(aww->get_root(), EXIT_SUCCESS, dir4intro);
417    }
418    else {
419        NT_start_if(dir4intro);
420    }
421    free(dir4intro);
422}
423
424// --------------------------------------------------------------------------------
425
426static void NT_save_quick_cb(AW_window *aww) {
427    AW_root *awr      = aww->get_root();
428    char    *filename = awr->awar(AWAR_DB_PATH)->read_string();
429
430    awr->dont_save_awars_with_default_value(GLOBAL.gb_main);
431
432    GB_ERROR error = GB_save_quick(GLOBAL.gb_main, filename);
433    if (error) aw_message(error);
434    else {
435        awr->awar(AWAR_SAVED_DB_PATH)->write_string(filename);
436        AW_refresh_fileselection(awr, AWAR_DBBASE);
437    }
438
439    free(filename);
440}
441
442
443static void NT_save_quick_as_cb(AW_window *aww) {
444    AW_root *awr      = aww->get_root();
445    char    *filename = awr->awar(AWAR_DB_PATH)->read_string();
446
447    // @@@ also use dont_save_awars_with_default_value here?
448
449    GB_ERROR error = GB_save_quick_as(GLOBAL.gb_main, filename);
450    if (!error) {
451        awr->awar(AWAR_SAVED_DB_PATH)->write_string(filename);
452        AW_refresh_fileselection(awr, AWAR_DBBASE);
453    }
454    aww->hide_or_notify(error);
455
456    free(filename);
457}
458
459#define AWAR_DB_TYPE          AWAR_DBBASE "/type"      // created by AWT_insert_DBsaveType_selector
460#define AWAR_DB_COMPRESSION   AWAR_DBBASE "/compression" // created by AWT_insert_DBcompression_selector
461#define AWAR_DB_OPTI_TREENAME AWAR_DBBASE "/optimize_tree_name"
462
463static void NT_save_as_cb(AW_window *aww) {
464    AW_root    *awr      = aww->get_root();
465    char       *filename = awr->awar(AWAR_DB_PATH)->read_string();
466    const char *atype    = awr->awar(AWAR_DB_TYPE)->read_char_pntr();
467    const char *ctype    = awr->awar(AWAR_DB_COMPRESSION)->read_char_pntr();
468    char       *savetype = GBS_global_string_copy("%s%s", atype, ctype);
469
470    awr->dont_save_awars_with_default_value(GLOBAL.gb_main);
471
472    GB_ERROR error = GB_save(GLOBAL.gb_main, filename, savetype);
473    if (!error) {
474        awr->awar(AWAR_SAVED_DB_PATH)->write_string(filename);
475        AW_refresh_fileselection(awr, AWAR_DBBASE);
476    }
477    aww->hide_or_notify(error);
478
479    free(savetype);
480    free(filename);
481}
482
483static AW_window *NT_create_save_quick_as_window(AW_root *aw_root, const char *base_name) {
484    static AW_window_simple *aws = NULp;
485    if (!aws) {
486        aws = new AW_window_simple;
487        aws->init(aw_root, "SAVE_CHANGES_TO", "Quicksave changes as");
488        aws->load_xfig("save_as.fig");
489
490        aws->at("close");
491        aws->callback(AW_POPDOWN);
492        aws->create_button("CLOSE", "CLOSE", "C");
493
494        aws->callback(makeHelpCallback("save.hlp"));
495        aws->at("help");
496        aws->create_button("HELP", "HELP", "H");
497
498        AW_create_standard_fileselection(aws, base_name);
499
500        aws->at("comment");
501        aws->create_text_field(AWAR_DB_COMMENT);
502
503        aws->at("save");
504        aws->callback(NT_save_quick_as_cb);
505        aws->create_button("SAVE", "SAVE", "S");
506    }
507    return aws;
508}
509
510static void NT_database_optimization(AW_window *aww) {
511    arb_progress progress(WEIGHTED, "Optimizing database compression", 0.38);
512    // 38% for seq-compression is just a rough guess made with silvaNR99138
513    // (a real guess would have to depend on ali-count, ali-length + field-count)
514
515    GB_topSecurityLevel unsecured(GLOBAL.gb_main);
516
517    GB_ERROR error = GB_begin_transaction(GLOBAL.gb_main);
518    if (!error) {
519        ConstStrArray ali_names;
520        GBT_get_alignment_names(ali_names, GLOBAL.gb_main);
521
522        arb_progress ali_progress("Optimizing sequence data", ali_names.size());
523        ali_progress.allow_title_reuse();
524
525        error = GBT_check_data(GLOBAL.gb_main, NULp);
526        error = GB_end_transaction(GLOBAL.gb_main, error);
527
528        if (!error) {
529            char *tree_name = aww->get_root()->awar(AWAR_DB_OPTI_TREENAME)->read_string();
530            for (int i = 0; ali_names[i]; ++i) {
531                error = GBT_compress_sequence_tree2(GLOBAL.gb_main, tree_name, ali_names[i]);
532                ali_progress.inc_and_check_user_abort(error);
533            }
534            free(tree_name);
535        }
536    }
537    progress.inc_and_check_user_abort(error);
538
539    if (!error) {
540        error = GB_optimize(GLOBAL.gb_main);
541        progress.inc_and_check_user_abort(error);
542    }
543    aww->hide_or_notify(error);
544}
545
546static AW_window *NT_create_database_optimization_window(AW_root *aw_root) {
547    static AW_window_simple *aws = NULp;
548    if (aws) return aws;
549    GB_transaction ta(GLOBAL.gb_main);
550
551    const char *largest_tree = GBT_name_of_largest_tree(GLOBAL.gb_main);
552    aw_root->awar_string(AWAR_DB_OPTI_TREENAME, largest_tree);
553
554    aws = new AW_window_simple;
555    aws->init(aw_root, "OPTIMIZE_DATABASE", "Optimize database compression");
556    aws->load_xfig("optimize.fig");
557
558    aws->at("trees");
559    awt_create_TREE_selection_list(GLOBAL.gb_main, aws, AWAR_DB_OPTI_TREENAME);
560
561    aws->at("close");
562    aws->callback(AW_POPDOWN);
563    aws->create_button("CLOSE", "CLOSE", "C");
564
565    aws->callback(makeHelpCallback("optimize.hlp"));
566    aws->at("help");
567    aws->create_button("HELP", "HELP", "H");
568
569    aws->at("go");
570    aws->callback(NT_database_optimization);
571    aws->create_button("GO", "GO");
572    return aws;
573}
574
575static AW_window *NT_create_save_as(AW_root *aw_root, const char *base_name) {
576    static AW_window_simple *aws = NULp;
577    if (aws) return aws;
578
579    aws = new AW_window_simple;
580    aws->init(aw_root, "SAVE_DB", "SAVE ARB DB");
581    aws->load_xfig("save_as.fig");
582
583    aws->at("close");
584    aws->callback(AW_POPDOWN);
585    aws->create_button("CLOSE", "CLOSE", "C");
586
587    aws->at("help");
588    aws->callback(makeHelpCallback("save.hlp"));
589    aws->create_button("HELP", "HELP", "H");
590
591    AW_create_standard_fileselection(aws, base_name);
592
593    aws->at("type");
594    AWT_insert_DBsaveType_selector(aws, AWAR_DB_TYPE);
595
596    aws->at("compression");
597    AWT_insert_DBcompression_selector(aws, AWAR_DB_COMPRESSION);
598
599    aws->at("optimize");
600    aws->callback(NT_create_database_optimization_window);
601    aws->help_text("optimize.hlp");
602    aws->create_autosize_button("OPTIMIZE", "Optimize database compression");
603
604    aws->at("save");
605    aws->callback(NT_save_as_cb);
606    aws->create_button("SAVE", "SAVE", "S");
607
608    aws->at("comment");
609    aws->create_text_field(AWAR_DB_COMMENT);
610
611    return aws;
612}
613
614static void NT_undo_cb(AW_window*, GB_UNDO_TYPE undo_type, TREE_canvas *ntw) {
615    GB_ERROR error = GB_undo(GLOBAL.gb_main, undo_type);
616    if (error) aw_message(error);
617    else {
618        GB_transaction ta(GLOBAL.gb_main);
619        AWT_auto_refresh allowed_on(ntw);
620        ntw->request_refresh();
621    }
622}
623
624static void NT_infomode_cb(UNFIXED, TREE_canvas *canvas, AWT_COMMAND_MODE mode) {
625    DBUI::popup_species_info_window(canvas->awr, canvas->gb_main);
626    nt_mode_event(NULp, canvas, mode);
627}
628
629static void NT_mark_duplicates(UNFIXED, TREE_canvas *ntw) {
630    AP_tree *tree_root = AWT_TREE(ntw)->get_root_node();
631    if (tree_root) {
632        AWT_auto_refresh allowed_on(ntw);
633        GB_transaction   ta(ntw->gb_main);
634
635        NT_mark_all_cb(NULp, ntw, 0); // unmark all
636        tree_root->mark_duplicates();
637        ntw->request_structure_update();
638    }
639}
640
641static void NT_justify_branch_lenghs(UNFIXED, TREE_canvas *ntw) {
642    GB_transaction  ta(ntw->gb_main);
643    AP_tree        *tree_root = AWT_TREE(ntw)->get_root_node();
644
645    if (tree_root) {
646        AWT_auto_refresh allowed_on(ntw);
647        tree_root->justify_branch_lenghs(ntw->gb_main);
648        ntw->request_save_and_zoom_reset();
649    }
650}
651
652#if defined(DEBUG)
653static void NT_fix_database(AW_window *) {
654    GB_ERROR err = NULp;
655    err = GB_fix_database(GLOBAL.gb_main);
656    if (err) aw_message(err);
657}
658#endif
659
660static void relink_pseudo_species_to_organisms(GBDATA *&ref_gb_node, char *&ref_name, GB_HASH *organism_hash) {
661    if (ref_gb_node) {
662        if (GEN_is_pseudo_gene_species(ref_gb_node)) {
663            GBDATA *gb_organism = GEN_find_origin_organism(ref_gb_node, organism_hash);
664
665            if (gb_organism) {
666                char *name = GBT_read_string(gb_organism, "name");
667
668                if (name) {
669                    freeset(ref_name, name);
670                    ref_gb_node = gb_organism;
671                }
672            }
673        }
674    }
675}
676
677static void NT_pseudo_species_to_organism(AW_window *, TREE_canvas *ntw) {
678    GB_transaction  ta(ntw->gb_main);
679    AP_tree        *tree_root = AWT_TREE(ntw)->get_root_node();
680
681    if (tree_root) {
682        AWT_auto_refresh allowed_on(ntw);
683
684        GB_HASH *organism_hash = GBT_create_organism_hash(ntw->gb_main);
685        tree_root->relink_tree(ntw->gb_main, relink_pseudo_species_to_organisms, organism_hash);
686        GBS_free_hash(organism_hash);
687        ntw->request_save();
688    }
689}
690
691
692// #########################################
693// #########################################
694// ###                                   ###
695// ##          user mask section          ##
696// ###                                   ###
697// #########################################
698// #########################################
699
700struct nt_item_type_species_selector FINAL_TYPE : public awt_item_type_selector {
701    nt_item_type_species_selector() : awt_item_type_selector(AWT_IT_SPECIES) {}
702    ~nt_item_type_species_selector() OVERRIDE {}
703
704    const char *get_self_awar() const OVERRIDE {
705        return AWAR_SPECIES_NAME;
706    }
707    size_t get_self_awar_content_length() const OVERRIDE {
708        return 12; // should be enough for "nnaammee.999"
709    }
710    GBDATA *current(AW_root *root, GBDATA *gb_main) const OVERRIDE { // give the current item
711        char           *species_name = root->awar(get_self_awar())->read_string();
712        GBDATA         *gb_species   = NULp;
713
714        if (species_name[0]) {
715            GB_transaction ta(gb_main);
716            gb_species = GBT_find_species(gb_main, species_name);
717        }
718
719        free(species_name);
720        return gb_species;
721    }
722    const char *getKeyPath() const OVERRIDE { // give the keypath for items
723        return CHANGE_KEY_PATH;
724    }
725};
726
727static nt_item_type_species_selector item_type_species;
728
729static void NT_open_mask_window(AW_window *aww, int id, GBDATA *gb_main) {
730    const awt_input_mask_descriptor *descriptor = AWT_look_input_mask(id);
731    nt_assert(descriptor);
732    if (descriptor) AWT_initialize_input_mask(aww->get_root(), gb_main, &item_type_species, descriptor->get_internal_maskname(), descriptor->is_local_mask());
733}
734
735static void NT_create_mask_submenu(AW_window_menu_modes *awm) {
736    AWT_create_mask_submenu(awm, AWT_IT_SPECIES, NT_open_mask_window, GLOBAL.gb_main);
737}
738static AW_window *create_colorize_species_window(AW_root *aw_root) {
739    return QUERY::create_colorize_items_window(aw_root, GLOBAL.gb_main, SPECIES_get_selector());
740}
741
742static void NT_update_marked_counter(GBDATA*, AW_window* aww) {
743    /*! Updates marked counter and issues redraw on tree if number of marked species changes.
744     * Called on any change of species_information container.
745     */
746    long        count   = GBT_count_marked_species(GLOBAL.gb_main);
747    const char *buffer  = count ? GBS_global_string("%li marked", count) : "";
748    AW_awar    *counter = aww->get_root()->awar(AWAR_MARKED_SPECIES_COUNTER);
749    char       *oldval  = counter->read_string();
750    if (strcmp(oldval, buffer)) {
751        counter->write_string(buffer);
752        aww->get_root()->awar(AWAR_TREE_REFRESH)->touch();
753    }
754    free(oldval);
755}
756
757// --------------------------------------------------------------------------------------------------
758
759static void NT_alltree_remove_leafs(AW_window *, GBT_TreeRemoveType mode, GBDATA *gb_main) {
760    GB_ERROR       error = NULp;
761    GB_transaction ta(gb_main);
762
763    ConstStrArray tree_names;
764    GBT_get_tree_names(tree_names, gb_main, false);
765
766    if (!tree_names.empty()) {
767        long treeCount = tree_names.size();
768
769        const char *whats_removed = NULp;
770        switch (mode) {
771            case GBT_REMOVE_ZOMBIES: whats_removed = "zombies"; break;
772            case GBT_REMOVE_MARKED:  whats_removed = "marked";  break;
773            default: nt_assert(0); break;
774        }
775
776        const char *task = GBS_global_string("Deleting %s from %li trees", whats_removed, treeCount);
777
778        arb_progress  progress(task, treeCount);
779        GB_HASH      *species_hash = GBT_create_species_hash(gb_main);
780
781        int modified = 0;
782
783        for (int t = 0; t<treeCount && !error; t++) {
784            progress.subtitle(tree_names[t]);
785            TreeNode *tree = GBT_read_tree(gb_main, tree_names[t], new SimpleRoot);
786            if (!tree) {
787                aw_message(GBS_global_string("Can't load tree '%s' - skipped", tree_names[t]));
788            }
789            else {
790                int removed        = 0;
791                int groups_removed = 0;
792
793                tree = GBT_remove_leafs(tree, mode, species_hash, &removed, &groups_removed);
794
795                nt_assert(removed >= groups_removed);
796
797                if (!tree) {
798                    aw_message(GBS_global_string("'%s' would disappear. Please delete tree manually.", tree_names[t]));
799                }
800                else {
801                    if (removed>0) {
802                        error = GBT_write_tree(gb_main, tree_names[t], tree);
803                        if (error) {
804                            aw_message(GBS_global_string("Failed to write '%s' (Reason: %s)", tree_names[t], error));
805                        }
806                        else {
807                            if (groups_removed>0) {
808                                aw_message(GBS_global_string("Removed %i species and %i groups from '%s'", removed, groups_removed, tree_names[t]));
809                            }
810                            else {
811                                aw_message(GBS_global_string("Removed %i species from '%s'", removed, tree_names[t]));
812                            }
813                            modified++;
814                        }
815                    }
816                    UNCOVERED();
817                    destroy(tree);
818                }
819            }
820            progress.inc_and_check_user_abort(error);
821        }
822
823        if (modified) {
824            aw_message(GBS_global_string("Changed %i of %li trees.", modified, treeCount));
825        }
826        else {
827            aw_message("No tree modified");
828        }
829
830        GBS_free_hash(species_hash);
831    }
832
833    aw_message_if(ta.close(error));
834}
835
836// --------------------------------------------------------------------------------------------------
837
838static ARB_ERROR mark_referred_species(GBDATA *gb_main, const DBItemSet& referred) {
839    GB_transaction ta(gb_main);
840    GBT_mark_all(gb_main, 0);
841
842    DBItemSetIter end = referred.end();
843    for (DBItemSetIter s = referred.begin(); s != end; ++s) {
844        GB_write_flag(*s, 1);
845    }
846    return ARB_ERROR();
847}
848
849static AW_window *create_mark_by_refentries_window(AW_root *awr, GBDATA *gbmain) {
850    static AW_window *aws = NULp;
851    if (!aws) {
852        static RefEntries::ReferringEntriesHandler reh(gbmain, SPECIES_get_selector());
853        aws = RefEntries::create_refentries_window(awr, &reh, "markbyref", "Mark by reference", "markbyref.hlp", NULp, "Mark referenced", mark_referred_species);
854    }
855    return aws;
856}
857
858// --------------------------------------------------------------------------------------------------
859
860static void merge_from_to(AW_root *awr, const char *db_awar_name, bool merge_to) {
861    const char *db_name  = awr->awar(db_awar_name)->read_char_pntr();
862    char       *quotedDB = GBK_singlequote(db_name);
863
864    AW_system(
865        GBS_global_string(
866            merge_to
867            ? "arb_ntree : %s &"
868            : "arb_ntree %s : &",
869            quotedDB)
870        );
871
872    free(quotedDB);
873}
874
875static void merge_from_cb(AW_window *aww, AW_CL cl_awarNamePtr) { merge_from_to(aww->get_root(), *(const char**)cl_awarNamePtr, false); }
876static void merge_into_cb(AW_window *aww, AW_CL cl_awarNamePtr) { merge_from_to(aww->get_root(), *(const char**)cl_awarNamePtr, true); }
877
878static AW_window *NT_create_merge_from_window(AW_root *awr) {
879    static char *awar_name = NULp; // do not free, bound to callback
880    AW_window *aw_from     =
881        awt_create_load_box(awr, "Merge data from", "other ARB database",
882                            ".", ".arb", &awar_name,
883                            makeWindowCallback(merge_from_cb, AW_CL(&awar_name)));
884    return aw_from;
885}
886static AW_window *NT_create_merge_to_window(AW_root *awr) {
887    static char *awar_name = NULp; // do not free, bound to callback
888    AW_window *aw_to       =
889        awt_create_load_box(awr, "Merge data to", "other or new ARB database",
890                            ".", ".arb", &awar_name,
891                            makeWindowCallback(merge_into_cb, AW_CL(&awar_name)),
892                            makeWindowCallback(AW_POPDOWN), NULp);
893    return aw_to;
894}
895
896// --------------------------------------------------------------------------------------------------
897
898static void update_main_window_title(AW_root* awr, AW_window_menu_modes* aww, int clone) {
899    const char* filename = awr->awar(AWAR_DB_NAME)->read_char_pntr();
900    if (clone) {
901        aww->set_window_title(GBS_global_string("%s - ARB (%i)",  filename, clone));
902    }
903    else {
904        aww->set_window_title(GBS_global_string("%s - ARB", filename));
905    }
906}
907
908static void canvas_tree_awar_changed_cb(AW_awar *, bool, TREE_canvas *ntw) {
909    NT_reload_tree_event(AW_root::SINGLETON, ntw, true);
910    AW_root::SINGLETON->awar(AWAR_NTREE_MAIN_WINDOW_COUNT)->touch(); // refresh canvas selection lists
911    TREE_auto_jump_cb(NULp, ntw, AP_JUMP_REASON_TREE);
912}
913
914class TREE_canvas_registry {
915    int          count;
916    TREE_canvas *canvas[MAX_NT_WINDOWS];
917
918    static TREE_canvas_registry *SINGLETON;
919
920    TREE_canvas_registry() : count(0) {
921        AW_root::SINGLETON->awar_int(AWAR_NTREE_MAIN_WINDOW_COUNT, 0, AW_ROOT_DEFAULT);
922    }
923
924public:
925    static TREE_canvas_registry& instance() {
926        if (!SINGLETON) SINGLETON = new TREE_canvas_registry;
927        return *SINGLETON;
928    }
929
930    void register_canvas(TREE_canvas *ntw) {
931        nt_assert(count<MAX_NT_WINDOWS);
932        nt_assert(count == ntw->get_index()); // you have to register TREE_canvas'es in order of creation!
933        canvas[count++] = ntw;
934        ntw->awr->awar(AWAR_NTREE_MAIN_WINDOW_COUNT)->write_int(count); // trigger callbacks
935    }
936
937    int get_count() const  { return count; }
938
939    TREE_canvas *get_canvas(int idx) const {
940        if (idx<0 || idx>=count) return NULp;
941        return canvas[idx];
942    }
943};
944
945TREE_canvas_registry *TREE_canvas_registry::SINGLETON = NULp;
946
947TREE_canvas *NT_get_canvas_by_index(int idx) {
948    /*! return canvas with index 'idx' [0...MAX_NT_WINDOWS-1] */
949    nt_assert(idx>=0 && idx<MAX_NT_WINDOWS);
950    return TREE_canvas_registry::instance().get_canvas(idx);
951}
952
953#if defined(TRACE_GROUP_SELECTION)
954static TREE_canvas *find_canvas_showing(AWT_graphic_tree *agt) {
955    // look for (registered) canvas showing given AWT_graphic_tree
956    // returns NULp if none found
957    const TREE_canvas_registry& reg = TREE_canvas_registry::instance();
958
959    int maxIdx = reg.get_count();
960    for (int32_t i = 0; i<maxIdx; ++i) {
961        TREE_canvas *ntw = reg.get_canvas(i);
962        if (ntw->gfx == agt) return ntw;
963    }
964    return NULp;
965}
966#endif
967
968void NT_fill_canvas_selection_list(class AW_selection_list *sellst, TREE_canvas *to_skip) {
969    /*! insert canvases into selection list (using canvas-indices as values)
970     */
971    const TREE_canvas_registry& reg = TREE_canvas_registry::instance();
972
973    int maxIdx = reg.get_count();
974    for (int32_t i = 0; i<maxIdx; ++i) {
975        TREE_canvas *ntw = reg.get_canvas(i);
976        if (ntw && ntw != to_skip) {
977            nt_assert(ntw->get_awar_tree());
978            const char *treename    = ntw->get_awar_tree()->read_char_pntr();
979            const char *description = i
980                ? GBS_global_string("ARB (%i):  %s", i, treename)
981                : GBS_global_string("ARB main: %s", treename);
982            sellst->insert(description, i);
983        }
984    }
985}
986
987// ----------------------------------
988//      group-selection handlers
989
990void NT_deselect_group(AW_root *awr) {
991    awr->awar(AWAR_GROUP)->write_pointer(NULp);
992}
993
994static bool track_group_selection_by_canvas = true;
995
996static void group_selected_by_canvas_cb(AWT_graphic_tree *gfx) {
997    const Group& group = gfx->get_selected_group();
998
999#if defined(TRACE_GROUP_SELECTION)
1000    fprintf(stderr, "[%s] ", track_group_selection_by_canvas ? "track" : "dont track");
1001    TREE_canvas *ntw = find_canvas_showing(gfx);
1002    if (group.is_valid()) {
1003        fprintf(stderr, "canvas %i selects group '%s'\n", ntw->get_index(), group.get_name());
1004    }
1005    else {
1006        fprintf(stderr, "canvas %i de-selects group\n", ntw->get_index());
1007    }
1008#endif
1009
1010    if (track_group_selection_by_canvas) {
1011        // set group-awar:
1012        gfx->get_root()->awar(AWAR_GROUP)->write_pointer(group.get_group_data()); // writes NULp if !group.is_valid()
1013    }
1014}
1015
1016static void group_awar_changed_cb(AW_root *awr) {
1017    AW_awar *awar_group      = awr->awar(AWAR_GROUP);
1018    GBDATA  *gb_wanted_group = awar_group->read_pointer();
1019
1020    GBDATA *gb_wanted_tree = NULp;
1021    {
1022        if (gb_wanted_group) {
1023            GB_transaction ta(gb_wanted_group);
1024            gb_wanted_tree = GB_get_father(gb_wanted_group);
1025            awr->awar(AWAR_SPECIES_NAME)->write_string(""); // deselect species when group gets selected
1026#if defined(TRACE_GROUP_SELECTION)
1027            fputs("clear AWAR_SPECIES_NAME (because group selected)\n", stderr);
1028#endif
1029        }
1030#if defined(TRACE_GROUP_SELECTION)
1031        const char *group_name = NULp;
1032        if (gb_wanted_group) {
1033            GB_transaction  ta(gb_wanted_group);
1034            GBDATA         *gb_name = GB_entry(gb_wanted_group, "group_name");
1035            if (gb_name) group_name = GB_read_char_pntr(gb_name);
1036        }
1037        fprintf(stderr, "group awar changed to %p", gb_wanted_group);
1038        if (group_name) fprintf(stderr, " (='%s')", group_name);
1039        fputc('\n', stderr);
1040#endif
1041    }
1042
1043    LocallyModify<bool> ignore_group_selection_by_canvas(track_group_selection_by_canvas, false);
1044
1045    {
1046        const TREE_canvas_registry& reg = TREE_canvas_registry::instance();
1047
1048        int maxIdx = reg.get_count();
1049        for (int32_t i = 0; i<maxIdx; ++i) {
1050            TREE_canvas      *ntw        = reg.get_canvas(i);
1051            AWT_graphic_tree *agt        = AWT_TREE(ntw);
1052            const Group&      curr_group = agt->get_selected_group();
1053
1054            GBDATA *gb_curr_tree = agt->get_tree_root()->get_gb_tree();
1055            if (gb_curr_tree == gb_wanted_tree) {
1056                AWT_auto_refresh allowed_on(ntw);
1057                if (!curr_group.is_valid() ||                       // no group selected
1058                    curr_group.get_group_data() != gb_wanted_group) // wrong group selected
1059                {
1060                    agt->select_group(gb_wanted_group);
1061                    ntw->request_refresh();
1062                }
1063                // perform auto-jump (also if group was already selected, otherwise group-traversal keys will not follow the selected group)
1064                TREE_auto_jump_cb(NULp, ntw, AP_JUMP_REASON_GROUP);
1065            }
1066            else {
1067                if (curr_group.is_valid()) {
1068                    AWT_auto_refresh allowed_on(ntw);
1069                    agt->deselect_group();
1070                    ntw->request_refresh();
1071                }
1072            }
1073        }
1074    }
1075}
1076
1077// ----------------------------
1078//      create main window
1079
1080static AW_window *popup_new_main_window(AW_root *awr, int clone, TREE_canvas **result_ntw) {
1081    /*! create ARB_NTREE main window
1082     * @param awr application root
1083     * @param clone == 0 -> first window (full functionality); >0 -> additional tree views (restricted functionality)
1084     * @param result_ntw is set to the created TREE_canvas (passed pointer may be NULp if result is not needed)
1085     */
1086    GB_push_transaction(GLOBAL.gb_main);
1087
1088    char        window_title[256];
1089    const char *awar_tree = NULp;
1090
1091    if (clone) {
1092        awar_tree = ARB_keep_string(GBS_global_string_copy(AWAR_TREE "_%i", clone));
1093        sprintf(window_title, "ARB_NT_%i", clone);
1094    }
1095    else {
1096        awar_tree = AWAR_TREE;
1097        sprintf(window_title, "ARB_NT");
1098    }
1099    AW_window_menu_modes *awm = new AW_window_menu_modes;
1100    awm->init(awr, window_title, window_title, 0, 0);
1101
1102    awr->awar(AWAR_DB_NAME)
1103       ->add_callback(makeRootCallback(update_main_window_title, awm, clone))
1104       ->update();
1105
1106    awm->button_length(5);
1107
1108    if (!clone) AW_init_color_group_defaults("arb_ntree");
1109
1110    AWT_graphic_tree *tree = TREE_generate_display(awr, GLOBAL.gb_main, launch_MapViewer_cb);
1111
1112    if (!clone) { // while creating initial window
1113        AWT_graphic_tree::install_group_changed_callback(makeGraphicTreeCallback(group_selected_by_canvas_cb));
1114        awr->awar(AWAR_GROUP)->add_callback(group_awar_changed_cb);
1115    }
1116
1117    TREE_canvas *ntw;
1118    {
1119        AW_awar *tree_awar = awr->awar_string(awar_tree);
1120        {
1121            AP_tree_display_style prev_style = tree->get_tree_style();
1122            tree->set_tree_style(AP_LIST_SIMPLE, NULp); // avoid NDS warnings during startup
1123
1124            ntw = new TREE_canvas(GLOBAL.gb_main, awm, "ARB_NT", tree, tree_awar);
1125            tree->set_tree_style(prev_style, ntw);
1126            ntw->set_mode(AWT_MODE_SELECT);
1127        }
1128
1129        if (result_ntw) *result_ntw = ntw;
1130
1131        {
1132            const char *tree_name          = tree_awar->read_char_pntr();
1133            const char *existing_tree_name = GBT_existing_tree(GLOBAL.gb_main, tree_name);
1134
1135            if (existing_tree_name) {
1136                tree_awar->write_string(existing_tree_name);
1137                NT_reload_tree_event(awr, ntw, true); // load first tree
1138            }
1139            else {
1140                AW_advice("Your database contains no tree.", AW_ADVICE_TOGGLE_AND_HELP, NULp, "no_tree.hlp");
1141                tree->set_tree_style(AP_LIST_NDS, ntw); // no tree -> show NDS list
1142            }
1143
1144            TREE_canvas_registry::instance().register_canvas(ntw);
1145            AWT_registerTreeAwarCallback(tree_awar, makeTreeAwarCallback(canvas_tree_awar_changed_cb, ntw), false);
1146        }
1147    }
1148
1149    TREE_install_update_callbacks(ntw);
1150
1151    bool is_genome_db = GEN_is_genome_db(GLOBAL.gb_main, 0); //  is this a genome database ? (default = 0 = not a genom db)
1152
1153    WindowCallback popupinfo_wcb = RootAsWindowCallback::simple(DBUI::popup_species_info_window, GLOBAL.gb_main);
1154
1155    // --------------
1156    //      File
1157
1158#if defined(DEBUG)
1159    AWT_create_debug_menu(awm);
1160#endif // DEBUG
1161
1162    bool allow_new_window = (ntw->get_index()+1) < MAX_NT_WINDOWS;
1163
1164    if (clone) {
1165        awm->create_menu("File", "F", AWM_ALL);
1166        if (allow_new_window) {
1167            awm->insert_menu_topic(awm->local_id("new_window"), "New window (same database)", "N", "newwindow.hlp", AWM_ALL, makeCreateWindowCallback(popup_new_main_window, clone+1, (TREE_canvas**)NULp));
1168        }
1169        awm->insert_menu_topic("close", "Close", "C", NULp, AWM_ALL, AW_POPDOWN);
1170    }
1171    else {
1172#if defined(DEBUG)
1173        // add more to debug-menu
1174        awm->sep______________();
1175        awm->insert_menu_topic("fix_db",      "Fix database",            "F", NULp, AWM_ALL, NT_fix_database);
1176        awm->insert_menu_topic("debug_arbdb", "Print debug information", "d", NULp, AWM_ALL, makeWindowCallback(GB_print_debug_information, GLOBAL.gb_main));
1177        awm->insert_menu_topic("test_compr",  "Test compression",        "T", NULp, AWM_ALL, makeWindowCallback(GBT_compression_test,       GLOBAL.gb_main));
1178#endif // DEBUG
1179
1180        awm->create_menu("File", "F", AWM_ALL);
1181        {
1182            // keep the following entries in sync with ../EDIT4/ED4_root.cxx@common_save_menu_entries
1183            awm->insert_menu_topic("save_changes", "Quicksave changes",          "s", "save.hlp",      AWM_ALL, NT_save_quick_cb);
1184            awm->insert_menu_topic("save_all_as",  "Save whole database as ...", "w", "save.hlp",      AWM_ALL, makeCreateWindowCallback(NT_create_save_as, AWAR_DBBASE));
1185            if (allow_new_window) {
1186                awm->sep______________();
1187                awm->insert_menu_topic("new_window", "New window (same database)", "N", "newwindow.hlp", AWM_ALL, makeCreateWindowCallback(popup_new_main_window, clone+1, (TREE_canvas**)NULp));
1188            }
1189            awm->sep______________();
1190            awm->insert_menu_topic("optimize_db",  "Optimize database compression", "O", "optimize.hlp",  AWM_ALL, NT_create_database_optimization_window);
1191            awm->sep______________();
1192
1193            awm->insert_sub_menu("Import",      "I");
1194            {
1195                awm->insert_menu_topic("merge_from", "Merge from other ARB database", "d", "arb_merge_into.hlp", AWM_ALL, NT_create_merge_from_window);
1196                awm->insert_menu_topic("import_seq", "Import from external format",   "I", "arb_import.hlp",     AWM_ALL, makeWindowCallback(NT_import_sequences, ntw));
1197                GDE_load_menu(awm, AWM_EXP, "Import");
1198            }
1199            awm->close_sub_menu();
1200
1201            awm->insert_sub_menu("Export",      "E");
1202            {
1203                awm->insert_menu_topic("export_to_ARB", "Merge to other or new ARB database", "A", "arb_merge_outof.hlp", AWM_ALL, NT_create_merge_to_window);
1204                awm->insert_menu_topic("export_seqs",   "Export to external format",          "f", "arb_export.hlp",      AWM_ALL, makeCreateWindowCallback(create_AWTC_export_window, GLOBAL.gb_main));
1205                GDE_load_menu(awm, AWM_ALL, "Export");
1206                awm->insert_menu_topic("export_nds",    "Export fields (to calc-sheet using NDS)", "N", "arb_export_nds.hlp",  AWM_ALL, create_nds_export_window);
1207            }
1208            awm->close_sub_menu();
1209            awm->sep______________();
1210
1211            insert_macro_menu_entry(awm, false);
1212
1213            awm->insert_sub_menu("VersionInfo/Bugreport/MailingList", "V");
1214            {
1215                awm->insert_menu_topic("version_info", "Version info (" ARB_VERSION_DETAILED ")", "V", "version.hlp", AWM_ALL, makeHelpCallback  ("version.hlp"));
1216                awm->insert_menu_topic("bug_report",   "Report bug",                              "b", NULp,          AWM_ALL, makeWindowCallback(AWT_openURL, "http://bugs.arb-home.de/wiki/BugReport"));
1217                awm->insert_menu_topic("mailing_list", "Mailing list",                            "M", NULp,          AWM_ALL, makeWindowCallback(AWT_openURL, "http://bugs.arb-home.de/wiki/ArbMailingList"));
1218            }
1219            awm->close_sub_menu();
1220            awm->sep______________();
1221
1222            awm->insert_menu_topic("new_arb",     "Start second database",      "d", "quit.hlp", AWM_ALL, makeWindowCallback(nt_start_2nd_arb, false));
1223            awm->insert_menu_topic("restart_arb", "Quit + load other database", "l", "quit.hlp", AWM_ALL, makeWindowCallback(nt_start_2nd_arb, true));
1224            awm->insert_menu_topic("quit",        "Quit",                       "Q", "quit.hlp", AWM_ALL, makeWindowCallback(NT_confirm_exit, EXIT_SUCCESS));
1225        }
1226
1227        // -----------------
1228        //      Species
1229
1230        awm->create_menu("Species", "c", AWM_ALL);
1231        {
1232            awm->insert_menu_topic("species_search", "Search and query",    "q", "sp_search.hlp", AWM_ALL, makeCreateWindowCallback(DBUI::create_species_query_window, GLOBAL.gb_main));
1233            awm->insert_menu_topic("species_info",   "Species information", "i", "sp_info.hlp",   AWM_ALL, popupinfo_wcb);
1234
1235            awm->sep______________();
1236
1237            NT_insert_mark_submenus(awm, ntw, 1);
1238            awm->insert_menu_topic("mark_by_ref",     "Mark by reference..", "r", "markbyref.hlp",       AWM_EXP, makeCreateWindowCallback(create_mark_by_refentries_window, GLOBAL.gb_main));
1239            awm->insert_menu_topic("species_colors",  "Colors ...",          "l", "colorize.hlp",        AWM_ALL, create_colorize_species_window);
1240            awm->insert_menu_topic("selection_admin", "Selections ...",      "o", "species_configs.hlp", AWM_ALL, makeWindowCallback(NT_popup_configuration_admin, ntw));
1241
1242            awm->sep______________();
1243
1244            awm->insert_sub_menu("Database fields admin", "f");
1245            DBUI::insert_field_admin_menuitems(awm, GLOBAL.gb_main);
1246            awm->close_sub_menu();
1247            NT_create_mask_submenu(awm);
1248
1249            awm->sep______________();
1250
1251            awm->insert_menu_topic("del_marked",    "Delete Marked Species",    "D", "sp_del_mrkd.hlp", AWM_ALL, makeWindowCallback(NT_delete_mark_all_cb, ntw));
1252
1253            awm->insert_sub_menu("Sort Species",         "s");
1254            {
1255                awm->insert_menu_topic("$sort_by_field", "According to Database Entries", "D", "sp_sort_fld.hlp",  AWM_ALL, NT_create_resort_window);
1256                awm->insert_menu_topic("$sort_by_tree",  "According to Phylogeny",        "P", "sp_sort_phyl.hlp", AWM_ALL, makeWindowCallback(NT_resort_data_by_phylogeny, ntw));
1257            }
1258            awm->close_sub_menu();
1259
1260            awm->insert_sub_menu("Merge Species", "g", AWM_EXP);
1261            {
1262                awm->insert_menu_topic("merge_species", "Create merged species from similar species", "m", "merge_species.hlp", AWM_EXP, NT_createMergeSimilarSpeciesWindow);
1263                awm->insert_menu_topic("join_marked",   "Join Marked Species",                        "J", "species_join.hlp",  AWM_EXP, NT_create_species_join_window);
1264            }
1265            awm->close_sub_menu();
1266
1267            awm->sep______________();
1268
1269            awm->insert_menu_topic("species_submission", "Submit Species", "b", "submission.hlp", AWM_EXP, makeCreateWindowCallback(AWTC_create_submission_window, GLOBAL.gb_main));
1270
1271            awm->sep______________();
1272
1273            awm->insert_menu_topic("new_names", "Synchronize IDs", "e", "rename.hlp", AWM_ALL, makeCreateWindowCallback(AWTC_create_rename_window, GLOBAL.gb_main));
1274
1275            awm->insert_sub_menu("Valid Names ...", "V", AWM_EXP);
1276            {
1277                awm->insert_menu_topic("imp_names",    "Import names from file", "I", "vn_import.hlp",  AWM_EXP, NT_importValidNames);
1278                awm->insert_menu_topic("del_names",    "Delete names from DB",   "D", "vn_delete.hlp",  AWM_EXP, NT_deleteValidNames);
1279                awm->insert_menu_topic("sug_names",    "Suggest valid names",    "v", "vn_suggest.hlp", AWM_EXP, NT_suggestValidNames);
1280                awm->insert_menu_topic("search_names", "Search manually",        "m", "vn_search.hlp",  AWM_EXP, NT_create_searchManuallyNames_window);
1281            }
1282            awm->close_sub_menu();
1283        }
1284
1285        // ----------------------------
1286        //      Genes + Experiment
1287
1288        if (is_genome_db) GEN_create_genes_submenu(awm, GLOBAL.gb_main, true);
1289
1290        // ------------------
1291        //      Sequence
1292
1293        awm->create_menu("Sequence", "S", AWM_ALL);
1294        {
1295            awm->insert_menu_topic("seq_admin",   "Sequence/Alignment Admin", "A", "ad_align.hlp",   AWM_ALL, makeCreateWindowCallback(NT_create_alignment_admin_window, (AW_window*)NULp));
1296            awm->insert_sub_menu("Insert/delete", "I");
1297            {
1298                awm->insert_menu_topic("ins_del_col", ".. column",     "c", "insdel.hlp",     AWM_ALL, create_insertDeleteColumn_window);
1299                awm->insert_menu_topic("ins_del_sai", ".. using SAI",  "S", "insdel_sai.hlp", AWM_ALL, makeCreateWindowCallback(create_insertDeleteBySAI_window,  GLOBAL.gb_main));
1300            }
1301            awm->close_sub_menu();
1302            awm->sep______________();
1303
1304            awm->insert_sub_menu("Edit Sequences", "E");
1305            {
1306                awm->insert_menu_topic("new_arb_edit4",  "Using marked species and tree", "m", "arb_edit4.hlp", AWM_ALL, makeWindowCallback(NT_start_editor_on_tree,  0, ntw));
1307                awm->insert_menu_topic("new2_arb_edit4", "... plus relatives",            "r", "arb_edit4.hlp", AWM_ALL, makeWindowCallback(NT_start_editor_on_tree, -1, ntw));
1308                awm->insert_menu_topic("old_arb_edit4",  "Using earlier configuration",   "c", "arb_edit4.hlp", AWM_ALL, NT_create_startEditorOnOldConfiguration_window);
1309            }
1310            awm->close_sub_menu();
1311
1312            awm->sep______________();
1313
1314            awm->insert_sub_menu("Align sequences",  "l");
1315            {
1316                awm->insert_menu_topic("realign_dna", "Realign DNA according to aligned protein", "R", "realign_dna.hlp", AWM_ALL, NT_create_realign_dna_window);
1317                GDE_load_menu(awm, AWM_ALL, "Align");
1318            }
1319            awm->close_sub_menu();
1320            awm->insert_menu_topic("seq_concat",    "Concatenate sequences",   "C", "concatenate.hlp",       AWM_ALL, NT_createConcatenationWindow);
1321            awm->insert_menu_topic("seq_split",     "Split sequences",         "S", "split.hlp",             AWM_ALL, NT_create_splitAlignment_window);
1322            awm->insert_menu_topic("track_changes", "Track alignment changes", "k", "track_ali_changes.hlp", AWM_EXP, NT_create_trackAliChanges_window);
1323            awm->sep______________();
1324
1325            awm->insert_menu_topic("dna_2_pro", "Perform translation",      "t", "translate_dna_2_pro.hlp", AWM_ALL, NT_create_dna_2_pro_window);
1326            awm->insert_menu_topic("arb_dist",  "Distance Matrix + ARB NJ", "D", "dist.hlp",                AWM_ALL, makeWindowCallback(AW_system_async_cb, "arb_dist"));
1327            awm->sep______________();
1328
1329            awm->insert_menu_topic("seq_quality",   "Check Sequence Quality", "Q", "seq_quality.hlp",   AWM_EXP, makeCreateWindowCallback(SQ_create_seq_quality_window, GLOBAL.gb_main));
1330            awm->insert_menu_topic("chimera_check", "Chimera Check",          "m", "chimera_check.hlp", AWM_EXP, makeCreateWindowCallback(STAT_create_chimera_check_window, GLOBAL.gb_main));
1331
1332            awm->sep______________();
1333
1334            GDE_load_menu(awm, AWM_ALL, "Print");
1335        }
1336
1337        // -------------
1338        //      SAI
1339
1340        awm->create_menu("SAI", "A", AWM_ALL);
1341        {
1342            awm->insert_menu_topic("sai_admin", "Manage SAIs",  "S", "ad_extended.hlp", AWM_ALL, NT_create_extendeds_window);
1343            awm->insert_menu_topic("sai_calc",  "Combine SAIs", "b", "saicalc.hlp",     AWM_ALL, makeWindowCallback(SAI_popup_calculator_window, GLOBAL.gb_main));
1344            awm->insert_sub_menu("Create SAI using ...", "C");
1345            {
1346                awm->insert_menu_topic("sai_max_freq",  "Max. Frequency",                                               "M", "max_freq.hlp",     AWM_EXP, AP_create_max_freq_window);
1347                awm->insert_menu_topic("sai_consensus", "Consensus",                                                    "C", "consensus.hlp",    AWM_ALL, AP_create_con_expert_window);
1348                awm->insert_menu_topic("pos_var_pars",  "Positional variability + Column statistic (parsimony method)", "a", "pos_var_pars.hlp", AWM_ALL, AP_create_pos_var_pars_window);
1349                awm->insert_menu_topic("arb_phyl",      "Filter by base frequency",                                     "F", "phylo.hlp",        AWM_ALL, makeWindowCallback(AW_system_async_cb, "arb_phylo"));
1350                awm->insert_menu_topic("sai_pfold",     "Protein secondary structure (field \"sec_struct\")",           "P", "pfold.hlp",        AWM_EXP, NT_create_sai_from_pfold);
1351
1352                GDE_load_menu(awm, AWM_EXP, "SAI");
1353            }
1354            awm->close_sub_menu();
1355
1356            awm->insert_sub_menu("Other functions", "O");
1357            {
1358                awm->insert_menu_topic("count_different_chars", "Count different chars/column",             "C", "count_chars.hlp",    AWM_EXP, makeWindowCallback(NT_count_different_chars, GLOBAL.gb_main));
1359                awm->insert_menu_topic("corr_mutat_analysis",   "Compute clusters of correlated positions", "m", "",                   AWM_ALL, makeWindowCallback(ARB_system_in_console_cb, "arb_rnacma", new XCmdType(XCMD_SERVSYNC_WAIT_ON_ERROR, GLOBAL.gb_main)));
1360                awm->insert_menu_topic("export_pos_var",        "Export Column Statistic (GNUPLOT format)", "E", "csp_2_gnuplot.hlp",  AWM_ALL, NT_create_colstat_2_gnuplot_window);
1361            }
1362            awm->close_sub_menu();
1363        }
1364
1365        // ----------------
1366        //      Probes
1367
1368        awm->create_menu("Probes", "P", AWM_ALL);
1369        {
1370            awm->insert_menu_topic("probe_design", "Design Probes",          "D", "probedesign.hlp", AWM_ALL, makeCreateWindowCallback(create_probe_design_window, GLOBAL.gb_main));
1371            awm->insert_menu_topic("probe_multi",  "Calculate Multi-Probes", "u", "multiprobe.hlp",  AWM_ALL, makeCreateWindowCallback(create_multiprobe_window, ntw));
1372            awm->insert_menu_topic("probe_match",  "Match Probes",           "M", "probematch.hlp",  AWM_ALL, makeCreateWindowCallback(create_probe_match_window, GLOBAL.gb_main));
1373            awm->sep______________();
1374            awm->insert_menu_topic("probe_match_sp",   "Match Probes with Specificity", "f", "probespec.hlp", AWM_ALL, makeCreateWindowCallback(create_probe_match_with_specificity_window,    ntw));
1375            awm->sep______________();
1376            awm->insert_menu_topic("primer_design_new", "Design Primers",            "P", "primer_new.hlp", AWM_EXP, makeCreateWindowCallback(create_primer_design_window, GLOBAL.gb_main));
1377            awm->insert_menu_topic("primer_design",     "Design Sequencing Primers", "S", "primer.hlp",     AWM_EXP, makeWindowCallback(ARB_system_in_console_cb, "arb_primer", new XCmdType(XCMD_SERVSYNC_WAIT_ON_ERROR, GLOBAL.gb_main)));
1378            awm->sep______________();
1379            awm->insert_menu_topic("pt_server_admin",   "PT_SERVER Admin",           "A", "probeadmin.hlp",  AWM_ALL, makeCreateWindowCallback(create_probe_admin_window, GLOBAL.gb_main));
1380        }
1381
1382    }
1383
1384    // --------------
1385    //      Tree
1386
1387    awm->create_menu("Tree", "T", AWM_ALL);
1388    {
1389        if (!clone) {
1390            awm->insert_menu_topic("tree_admin", "Tree admin",               "i", "treeadm.hlp",   AWM_ALL, popup_tree_admin_window);
1391            awm->insert_menu_topic("nds",        "NDS (Node display setup)", "N", "props_nds.hlp", AWM_ALL, makeCreateWindowCallback(NDS_create_window, GLOBAL.gb_main));
1392            awm->sep______________();
1393            awm->insert_sub_menu("Add Species to Existing Tree", "A");
1394            {
1395                awm->insert_menu_topic("arb_pars_quick", "ARB Parsimony (Quick add marked)", "Q", "pars.hlp", AWM_ALL, makeWindowCallback(AW_system_async_cb, "arb_pars -add_marked -quit"));
1396                awm->insert_menu_topic("arb_pars",       "ARB Parsimony interactive",        "i", "pars.hlp", AWM_ALL, makeWindowCallback(AW_system_async_cb, "arb_pars"));
1397                GDE_load_menu(awm, AWM_EXP, "Incremental phylogeny");
1398            }
1399            awm->close_sub_menu();
1400        }
1401
1402        awm->insert_sub_menu("Remove Species from Tree",     "R");
1403        {
1404            awm->insert_menu_topic(awm->local_id("tree_remove_deleted"), "Remove zombies", "z", "trm_del.hlp",    AWM_ALL, makeWindowCallback(NT_remove_leafs, ntw, AWT_REMOVE_ZOMBIES));
1405            awm->insert_menu_topic(awm->local_id("tree_remove_marked"),  "Remove marked",  "m", "trm_mrkd.hlp",   AWM_ALL, makeWindowCallback(NT_remove_leafs, ntw, AWT_REMOVE_MARKED));
1406            awm->insert_menu_topic(awm->local_id("tree_keep_marked"),    "Keep marked",    "K", "tkeep_mrkd.hlp", AWM_ALL, makeWindowCallback(NT_remove_leafs, ntw, AWT_KEEP_MARKED));
1407            awm->sep______________();
1408            awm->insert_menu_topic("all_tree_remove_deleted", "Remove zombies from ALL trees", "A", "trm_del.hlp",  AWM_ALL, makeWindowCallback(NT_alltree_remove_leafs, GBT_REMOVE_ZOMBIES, GLOBAL.gb_main));
1409            awm->insert_menu_topic("all_tree_remove_marked",  "Remove marked from ALL trees",  "L", "trm_mrkd.hlp", AWM_ALL, makeWindowCallback(NT_alltree_remove_leafs, GBT_REMOVE_MARKED,  GLOBAL.gb_main));
1410        }
1411        awm->close_sub_menu();
1412
1413        if (!clone) {
1414            awm->insert_sub_menu("Build tree from sequence data",    "B");
1415            {
1416                awm->insert_sub_menu("Distance matrix methods", "D");
1417                awm->insert_menu_topic("arb_dist", "Distance Matrix + ARB NJ", "J", "dist.hlp", AWM_ALL, makeWindowCallback(AW_system_async_cb, "arb_dist"));
1418                GDE_load_menu(awm, AWM_ALL, "Phylogeny Distance Matrix");
1419                awm->close_sub_menu();
1420
1421                awm->insert_sub_menu("Maximum Parsimony methods", "P");
1422                GDE_load_menu(awm, AWM_ALL, "Phylogeny max. parsimony");
1423                awm->close_sub_menu();
1424
1425                awm->insert_sub_menu("Maximum Likelihood methods", "L");
1426                GDE_load_menu(awm, AWM_EXP, "Phylogeny max. Likelihood EXP");
1427                GDE_load_menu(awm, AWM_ALL, "Phylogeny max. Likelihood");
1428                awm->close_sub_menu();
1429
1430                awm->insert_sub_menu("Other methods", "O", AWM_EXP);
1431                GDE_load_menu(awm, AWM_EXP, "Phylogeny (Other)");
1432                awm->close_sub_menu();
1433            }
1434            awm->close_sub_menu();
1435        }
1436
1437        awm->insert_menu_topic(awm->local_id("consense_tree"), "Build consensus tree", "c", "consense_tree.hlp", AWM_ALL, NT_create_consense_window);
1438
1439        awm->sep______________();
1440
1441        awm->insert_sub_menu("Reset zoom",         "z");
1442        {
1443            awm->insert_menu_topic(awm->local_id("reset_logical_zoom"),  "Logical zoom",  "L", "rst_log_zoom.hlp",  AWM_ALL, makeWindowCallback(NT_reset_lzoom_cb, ntw));
1444            awm->insert_menu_topic(awm->local_id("reset_physical_zoom"), "Physical zoom", "P", "rst_phys_zoom.hlp", AWM_ALL, makeWindowCallback(NT_reset_pzoom_cb, ntw));
1445        }
1446        awm->close_sub_menu();
1447
1448        awm->sep______________();
1449
1450        // taxonomic groups
1451        NT_insert_collapse_submenu(awm, ntw);
1452        if (!clone) {
1453            awm->insert_menu_topic("group_search",     "Search groups...",    "g", "group_search.hlp",     AWM_ALL, makeWindowCallback      (popup_group_search_window,         GLOBAL.gb_main));
1454            awm->insert_menu_topic("compare_taxonomy", "Compare taxonomy...", "x", "compare_taxonomy.hlp", AWM_ALL, makeCreateWindowCallback(NT_create_compare_taxonomy_window, ntw));
1455            awm->insert_menu_topic("move_groups",      "Move groups...",      "v", "move_groups.hlp",      AWM_ALL, makeCreateWindowCallback(NT_create_moveGroupInfo_window));
1456        }
1457
1458        awm->sep______________();
1459
1460        if (!clone) {
1461            awm->insert_menu_topic("compare_topology", "Compare topology...", "o", "compare_topo.hlp",     AWM_ALL, makeCreateWindowCallback(NT_create_compareTopologies_window));
1462        }
1463
1464        awm->insert_sub_menu("Modify branches", "M");
1465        {
1466            awm->insert_menu_topic(awm->local_id("tree_remove_remark"), "Remove bootstraps", "b", "trm_boot.hlp", AWM_ALL, makeWindowCallback(NT_remove_bootstrap, ntw));
1467            awm->insert_menu_topic(awm->local_id("tree_edit_remark"),   "Edit bootstraps",   "E", "ted_boot.hlp", AWM_ALL, makeWindowCallback(NT_edit_bootstrap, ntw));
1468            awm->sep______________();
1469            awm->insert_menu_topic(awm->local_id("tree_reset_lengths"),     "Reset branchlengths",   "R", "tbl_reset.hlp",   AWM_ALL, makeWindowCallback(NT_reset_branchlengths,   ntw));
1470            awm->insert_menu_topic(awm->local_id("justify_branch_lengths"), "Justify branchlengths", "J", "tbl_justify.hlp", AWM_ALL, makeWindowCallback(NT_justify_branch_lenghs, ntw));
1471            awm->insert_menu_topic(awm->local_id("tree_scale_lengths"),     "Scale Branchlengths",   "S", "tbl_scale.hlp",   AWM_ALL, makeWindowCallback(NT_scale_tree,            ntw));
1472            awm->sep______________();
1473            awm->insert_menu_topic(awm->local_id("tree_multifurcate"), "Multifurcate...", "M", "multifurcate.hlp", AWM_ALL, makeCreateWindowCallback(NT_create_multifurcate_tree_window, ntw));
1474            awm->sep______________();
1475            awm->insert_menu_topic(awm->local_id("tree_boot2len"), "Bootstraps -> Branchlengths", "l", "tbl_boot2len.hlp", AWM_ALL, makeWindowCallback(NT_move_boot_branch, ntw, 0));
1476            awm->insert_menu_topic(awm->local_id("tree_len2boot"), "Bootstraps <- Branchlengths", "o", "tbl_boot2len.hlp", AWM_ALL, makeWindowCallback(NT_move_boot_branch, ntw, 1));
1477
1478        }
1479        awm->close_sub_menu();
1480        awm->insert_sub_menu("Beautify tree", "u");
1481        {
1482            awm->insert_menu_topic(awm->local_id("beautifyt_tree"),  "#beautifyt.xpm",  "",  "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_TO_TOP));
1483            awm->insert_menu_topic(awm->local_id("beautifyc_tree"),  "#beautifyc.xpm",  "",  "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_TO_EDGE));
1484            awm->insert_menu_topic(awm->local_id("beautifyb_tree"),  "#beautifyb.xpm",  "",  "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_TO_BOTTOM));
1485            awm->insert_menu_topic(awm->local_id("beautifyr_tree"),  "Radial tree (1)", "1", "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_TO_CENTER));
1486            awm->insert_menu_topic(awm->local_id("beautifyr2_tree"), "Radial tree (2)", "2", "resorttree.hlp", AWM_ALL, makeWindowCallback(NT_resort_tree_cb, ntw, BIG_BRANCHES_ALTERNATING));
1487            awm->sep______________();
1488            awm->insert_menu_topic(awm->local_id("sort_by_other"),   "By other tree",   "o", "resortbyother.hlp", AWM_ALL, makeCreateWindowCallback(NT_create_sort_tree_by_other_tree_window, ntw));
1489        }
1490        awm->close_sub_menu();
1491
1492        awm->insert_menu_topic(awm->local_id("branch_analysis"), "Branch analysis", "h", "branch_analysis.hlp", AWM_ALL, makeCreateWindowCallback(NT_create_branch_analysis_window, ntw));
1493        awm->insert_menu_topic(awm->local_id("syncroots"),       "Adjust roots...", "j", "syncroots.hlp",       AWM_ALL, makeCreateWindowCallback(NT_create_syncroot_window,        GLOBAL.gb_main));
1494        awm->insert_menu_topic(awm->local_id("mark_duplicates"), "Mark duplicates", "k", "mark_duplicates.hlp", AWM_ALL, makeWindowCallback      (NT_mark_duplicates,               ntw));
1495
1496        awm->sep______________();
1497        awm->insert_menu_topic(awm->local_id("shade"),            "Tree shading...",       "s", "tree_shading.hlp",     AWM_ALL, makeWindowCallback      (NT_configure_treeShader));
1498        awm->insert_menu_topic(awm->local_id("syncscroll"),       "Sync tree scrolling..", "e", "syncscroll.hlp",       AWM_ALL, makeCreateWindowCallback(NT_create_syncScroll_window, ntw));
1499
1500        awm->sep______________();
1501        awm->insert_menu_topic(awm->local_id("tree_select_latest"), "Select Last Tree", "L", NULp, AWM_ALL, makeWindowCallback(NT_select_bottom_tree, awar_tree));
1502
1503        awm->sep______________();
1504        awm->insert_menu_topic("transversion",       "Transversion analysis",   "y", "trans_anal.hlp", AWM_EXP, makeHelpCallback("trans_anal.hlp"));
1505
1506        if (is_genome_db) {
1507            awm->sep______________();
1508            awm->insert_menu_topic(awm->local_id("tree_pseudo_species_to_organism"), "Relink tree to organisms", "i", "tree_pseudo.hlp", AWM_EXP, makeWindowCallback(NT_pseudo_species_to_organism, ntw));
1509        }
1510
1511        if (!clone) {
1512            awm->sep______________();
1513            awm->insert_menu_topic("print_tree",  "Print tree",          "P", "tree2prt.hlp",  AWM_ALL, makeWindowCallback(AWT_popup_print_window, static_cast<AWT_canvas*>(ntw)));
1514            awm->insert_menu_topic("tree_2_xfig", "Export tree to XFIG", "F", "tree2file.hlp", AWM_ALL, makeWindowCallback(AWT_popup_tree_export_window, static_cast<AWT_canvas*>(ntw)));
1515        }
1516
1517    }
1518
1519    if (!clone) {
1520        // ---------------
1521        //      Tools
1522
1523        awm->create_menu("Tools", "o", AWM_ALL);
1524        {
1525            awm->insert_menu_topic("names_admin", "Nameserver admin (IDs)", "s", "namesadmin.hlp", AWM_ALL, makeWindowCallback(AW_popup_namesadmin_window, GLOBAL.gb_main));
1526            awm->insert_sub_menu("DB admin", "D", AWM_EXP);
1527            {
1528                awm->insert_menu_topic("db_admin", "Re-repair DB", "R", "rerepair.hlp", AWM_EXP, makeWindowCallback(NT_rerepair_DB, GLOBAL.gb_main));
1529            }
1530            awm->close_sub_menu();
1531            awm->sep______________();
1532
1533            awm->insert_sub_menu("GDE specials", "G", AWM_EXP);
1534            {
1535                GDE_load_menu(awm, AWM_EXP, NULp);
1536            }
1537            awm->close_sub_menu();
1538
1539            awm->sep______________();
1540            awm->insert_menu_topic("xterm",    "Start XTERM",     "X", "xterm.hlp",   AWM_ALL, AW_console_cb);
1541            XCmdType *showlog_cmdtype = new XCmdType(XCMD_ASYNC_WAIT_ON_ERROR, GLOBAL.gb_main); // do not free (used in callback)
1542            awm->insert_menu_topic("viewlog",  "View ARB log",    "l", "console.hlp", AWM_ALL, makeWindowCallback(ARB_system_in_console_cb, "arb_show_log.pl run",    showlog_cmdtype)); // ../SH/arb_show_log.pl
1543            awm->insert_menu_topic("viewserv", "View server log", "V", "console.hlp", AWM_ALL, makeWindowCallback(ARB_system_in_console_cb, "arb_show_log.pl server", showlog_cmdtype));
1544            awm->insert_menu_topic("viewsys",  "View sysinfo",    "i", "console.hlp", AWM_ALL, makeWindowCallback(ARB_system_in_console_cb, "arb_show_log.pl sysinf", showlog_cmdtype));
1545            awm->sep______________();
1546            GDE_load_menu(awm, AWM_EXP, "User");
1547        }
1548        // --------------------
1549        //      Properties
1550
1551        awm->create_menu("Properties", "r", AWM_ALL);
1552        {
1553            awm->insert_menu_topic("props_menu",                 "Frame settings ...",          "F", "props_frame.hlp",      AWM_ALL, AW_preset_window);
1554            awm->insert_menu_topic(awm->local_id("props_tree2"), "Tree options",                "o", "nt_tree_settings.hlp", AWM_ALL, TREE_create_settings_window);
1555            awm->insert_menu_topic("props_tree",                 "Tree colors & fonts",         "c", "color_props.hlp",      AWM_ALL, makeCreateWindowCallback(AW_create_gc_window, ntw->gc_manager));
1556            awm->insert_menu_topic("props_www",                  "Search world wide web (WWW)", "b", "props_www.hlp",        AWM_ALL, makeCreateWindowCallback(AWT_create_www_window, GLOBAL.gb_main));
1557            awm->sep______________();
1558            awm->insert_menu_topic("!toggle_expert", "Toggle expert mode",         "x", NULp, AWM_ALL, NT_toggle_expert_mode);
1559            awm->insert_menu_topic("!toggle_focus",  "Toggle focus follows mouse", "m", NULp, AWM_ALL, NT_toggle_focus_policy);
1560            awm->sep______________();
1561            AW_insert_common_property_menu_entries(awm);
1562            awm->sep______________();
1563            awm->insert_menu_topic("save_props", "Save properties (ntree.arb)", "S", "savedef.hlp", AWM_ALL, AW_save_properties);
1564        }
1565    }
1566
1567    awm->insert_help_topic("ARB_NT help",     "N", "arb_ntree.hlp", AWM_ALL, makeHelpCallback("arb_ntree.hlp"));
1568
1569    // ----------------------
1570    //      mode buttons
1571    //
1572    // keep them synchronized as far as possible with those in ARB_PARSIMONY
1573    // see ../PARSIMONY/PARS_main.cxx@keepModesSynchronized
1574
1575    awm->create_mode("mode_select.xpm", "mode_select.hlp", AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_SELECT));
1576    awm->create_mode("mode_mark.xpm",   "mode_mark.hlp",   AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_MARK));
1577    awm->create_mode("mode_group.xpm",  "mode_group.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_GROUP));
1578    awm->create_mode("mode_zoom.xpm",   "mode_pzoom.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_ZOOM));
1579    awm->create_mode("mode_lzoom.xpm",  "mode_lzoom.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_LZOOM));
1580
1581    awm->create_mode("mode_info.xpm", "mode_info.hlp", AWM_ALL, makeWindowCallback(NT_infomode_cb, ntw, AWT_MODE_INFO));
1582    awm->create_mode("mode_www.xpm",  "mode_www.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event,  ntw, AWT_MODE_WWW));
1583
1584    // topology-modification-modes
1585    awm->create_mode("mode_setroot.xpm",   "mode_setroot.hlp", AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_SETROOT));
1586    awm->create_mode("mode_swap.xpm",      "mode_swap.hlp",    AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_SWAP));
1587    awm->create_mode("mode_move.xpm",      "mode_move.hlp",    AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_MOVE));
1588    awm->create_mode("mode_length.xpm",    "mode_length.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_LENGTH));
1589    awm->create_mode("mode_multifurc.xpm", "mode_length.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_MULTIFURC));
1590
1591    // layout-modes
1592    awm->create_mode("mode_line.xpm",   "mode_width.hlp",  AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_LINE));
1593    awm->create_mode("mode_rotate.xpm", "mode_rotate.hlp", AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_ROTATE));
1594    awm->create_mode("mode_spread.xpm", "mode_spread.hlp", AWM_ALL, makeWindowCallback(nt_mode_event, ntw, AWT_MODE_SPREAD));
1595
1596    awm->set_info_area_height(250);
1597    awm->at(5, 2);
1598    awm->auto_space(-2, -2);
1599    awm->shadow_width(1);
1600
1601    // -------------------------
1602    //      create top area
1603
1604    int first_liney;
1605    int leftx;
1606    awm->get_at_position(&leftx, &first_liney);
1607
1608    // ---------------------
1609    //      quit + help
1610
1611    awm->button_length(0);
1612
1613    if (clone) {
1614        awm->callback(AW_POPDOWN);
1615        awm->create_button("CLOSE", "#close.xpm");
1616    }
1617    else {
1618        awm->callback(makeWindowCallback(NT_confirm_exit, EXIT_SUCCESS));
1619        awm->help_text("quit.hlp");
1620        awm->create_button("QUIT", "#quit.xpm");
1621    }
1622
1623    int db_pathx = awm->get_at_xposition();
1624
1625    // now fetch the yposition for the 2nd button line
1626    awm->at_newline();
1627    int second_liney = awm->get_at_yposition();
1628
1629    awm->callback(AW_help_entry_pressed);
1630    awm->help_text("arb_ntree.hlp");
1631    awm->create_button("?", "#help.xpm");
1632
1633    // --------------------------
1634    //      save + undo/redo
1635
1636    awm->callback(NT_save_quick_cb);
1637    awm->help_text("save.hlp");
1638    awm->create_button("SAVE", "#save.xpm");
1639
1640    awm->callback(makeCreateWindowCallback(NT_create_save_as, AWAR_DBBASE));
1641    awm->help_text("save.hlp");
1642    awm->create_button("SAVE_AS", "#saveAs.xpm");
1643
1644    // undo/redo:
1645    awm->callback(makeWindowCallback(NT_undo_cb, GB_UNDO_UNDO, ntw));
1646    awm->help_text("undo.hlp");
1647    awm->create_button("UNDO", "#undo.xpm");
1648
1649    awm->callback(makeWindowCallback(NT_undo_cb, GB_UNDO_REDO, ntw));
1650    awm->help_text("undo.hlp");
1651    awm->create_button("REDO", "#redo.xpm");
1652
1653    int db_pathx2 = awm->get_at_xposition();
1654
1655    // fetch position for mode help-line:
1656    awm->at_newline();
1657    int third_liney = awm->get_at_yposition();
1658
1659    awm->at(db_pathx, first_liney);
1660    // size of DB-name button is determined by buttons below:
1661    awm->at_attach_to(false, false, db_pathx2-db_pathx-1, second_liney-first_liney+1);
1662    awm->callback(makeCreateWindowCallback(NT_create_save_quick_as_window, AWAR_DBBASE));
1663    awm->help_text("save.hlp");
1664    awm->create_button("QUICK_SAVE_AS", AWAR_DB_NAME);
1665
1666    // -----------------------------
1667    //      tree + tree display
1668
1669#define TREE_BUTTON_OVERSIZE 6
1670
1671    int db_treex      = awm->get_at_xposition();
1672    int second_uppery = second_liney-TREE_BUTTON_OVERSIZE;
1673
1674    awm->at(db_treex, second_uppery);
1675    awm->button_length(0);
1676
1677    awm->callback(makeWindowCallback(NT_set_tree_style, ntw, AP_TREE_RADIAL));
1678    awm->help_text("tr_type_radial.hlp");
1679    awm->create_button("RADIAL_TREE_TYPE", "#radial.xpm");
1680
1681    awm->callback(makeWindowCallback(NT_set_tree_style, ntw, AP_TREE_NORMAL));
1682    awm->help_text("tr_type_dendro.hlp");
1683    awm->create_button("LIST_TREE_TYPE", "#dendro.xpm");
1684
1685    awm->callback(makeWindowCallback(NT_set_tree_style, ntw, AP_TREE_IRS));
1686    awm->help_text("tr_type_irs.hlp");
1687    awm->create_button("FOLDED_LIST_TREE_TYPE", "#dendroIrs.xpm");
1688
1689    awm->callback(makeWindowCallback(NT_set_tree_style, ntw, AP_LIST_NDS));
1690    awm->help_text("tr_type_nds.hlp");
1691    awm->create_button("NO_TREE_TYPE", "#listdisp.xpm");
1692
1693    int db_treex2 = awm->get_at_xposition();
1694
1695    awm->at(db_treex, first_liney);
1696    // size of tree-name button is determined by buttons below:
1697    awm->at_attach_to(false, false, db_treex2-db_treex-1, second_uppery-first_liney+1);
1698    awm->callback(makeCreateWindowCallback(NT_create_select_tree_window, awar_tree));
1699    awm->help_text("nt_tree_select.hlp");
1700    awm->create_button("SELECT_A_TREE", awar_tree);
1701
1702    // ---------------------------------------------------------------
1703    //      protection, alignment + editor (and maybe Genome Map)
1704
1705    int db_alignx = awm->get_at_xposition();
1706
1707    // editor and genemap buttons have to be 44x24 sized
1708#define EDIT_XSIZE 50
1709#define EDIT_YSIZE 30 // same as 'save as' buttons
1710
1711    // first draw protection:
1712    int protectx = db_alignx + 2*EDIT_XSIZE;
1713
1714    awm->at(protectx+2, first_liney+1);
1715    awm->button_length(0);
1716    awm->create_button(NULp, "#protect.xpm");
1717
1718    awm->at(protectx, second_liney+2);
1719    awm->create_option_menu(AWAR_SECURITY_LEVEL);
1720    awm->insert_option        ("0", NULp, 0);
1721    awm->insert_option        ("1", NULp, 1);
1722    awm->insert_option        ("2", NULp, 2);
1723    awm->insert_option        ("3", NULp, 3);
1724    awm->insert_option        ("4", NULp, 4);
1725    awm->insert_option        ("5", NULp, 5);
1726    awm->insert_default_option("6", NULp, 6);
1727    awm->update_option_menu();
1728
1729    int db_searchx = awm->get_at_xposition() - 7;
1730
1731    // draw ali/editor buttons AFTER protect menu (to get rid of it's label)
1732    awm->at(db_alignx, second_liney);
1733
1734    awm->at_attach_to(false, false, ((2-is_genome_db)*EDIT_XSIZE), EDIT_YSIZE);
1735    awm->callback(makeWindowCallback(NT_start_editor_on_tree, 0, ntw));
1736    awm->help_text("arb_edit4.hlp");
1737    if (is_genome_db) awm->create_button("EDIT_SEQUENCES", "#editor_small.xpm");
1738    else              awm->create_button("EDIT_SEQUENCES", "#editor.xpm");
1739
1740    if (is_genome_db) {
1741        awm->at_attach_to(false, false, EDIT_XSIZE, EDIT_YSIZE);
1742        awm->callback(makeCreateWindowCallback(GEN_create_first_map, GLOBAL.gb_main)); // initial gene map
1743        awm->help_text("gene_map.hlp");
1744        awm->create_button("OPEN_GENE_MAP", "#gen_map.xpm");
1745    }
1746
1747    int db_alignx2 = awm->get_at_xposition();
1748
1749    awm->at(db_alignx, first_liney);
1750    awm->at_attach_to(false, false, db_alignx2-db_alignx-1, second_liney-first_liney+1);
1751    awm->callback(NT_create_select_alignment_window);
1752    awm->help_text("nt_align_select.hlp");
1753    awm->create_button("SELECT_AN_ALIGNMENT", AWAR_DEFAULT_ALIGNMENT);
1754
1755    // -------------------------------
1756    //      create mode-help line
1757
1758    awm->at(leftx, third_liney);
1759    awm->button_length(AWAR_FOOTER_MAX_LEN);
1760    awm->create_button(NULp, AWAR_FOOTER);
1761
1762    awm->at_newline();
1763    int bottomy = awm->get_at_yposition();
1764
1765    // ---------------------------------------
1766    //      Info / marked / Search / Jump
1767
1768    awm->button_length(7);
1769
1770    awm->at(db_searchx, first_liney);
1771    awm->callback(makeCreateWindowCallback(DBUI::create_species_query_window, GLOBAL.gb_main));
1772    awm->help_text("sp_search.hlp");
1773    awm->create_button("SEARCH",  "Search");
1774
1775    awm->at(db_searchx, second_uppery);
1776    awm->callback(makeWindowCallback(NT_jump_cb, ntw, AP_JUMP_BY_BUTTON));
1777    awm->help_text("tr_jump.hlp");
1778    awm->create_button("JUMP", "Jump");
1779
1780    int db_infox = awm->get_at_xposition();
1781
1782    awm->at(db_infox, first_liney);
1783    awm->button_length(13);
1784    awm->callback(popupinfo_wcb);
1785    awm->help_text("sp_info.hlp");
1786    awm->create_button("INFO",  AWAR_INFO_BUTTON_TEXT);
1787
1788    awm->at(db_infox, second_uppery);
1789    awm->button_length(13);
1790    awm->help_text("species_configs.hlp");
1791    awm->callback(makeWindowCallback(NT_popup_configuration_admin, ntw));
1792    awm->create_button("selection_admin2", AWAR_MARKED_SPECIES_COUNTER);
1793    {
1794        GBDATA *gb_species_data = GBT_get_species_data(GLOBAL.gb_main);
1795        GB_add_callback(gb_species_data, GB_CB_CHANGED, makeDatabaseCallback(NT_update_marked_counter, static_cast<AW_window*>(awm)));
1796        NT_update_marked_counter(NULp, awm);
1797    }
1798
1799    // set height of top area:
1800    awm->set_info_area_height(bottomy+2);
1801    awm->set_bottom_area_height(0);
1802
1803    NT_activate_configMarkers_display(ntw);
1804
1805    // ------------------------------------
1806    //      Autostarts for development
1807
1808#if defined(DEVEL_RALF)
1809    // if (is_genome_db) GEN_map_first(awr)->show();
1810#endif // DEVEL_RALF
1811
1812    GB_pop_transaction(GLOBAL.gb_main);
1813
1814#if defined(DEBUG)
1815    AWT_check_action_ids(awr, is_genome_db ? "_genome" : "");
1816#endif
1817
1818    return awm;
1819}
1820
1821TREE_canvas *NT_create_main_window(AW_root *aw_root) {
1822    GB_ERROR error = GB_request_undo_type(GLOBAL.gb_main, GB_UNDO_NONE);
1823    if (error) aw_message(error);
1824
1825    nt_create_all_awars(aw_root);
1826
1827    TREE_canvas *ntw = NULp;
1828    AW_window   *aww = popup_new_main_window(aw_root, 0, &ntw);
1829    NT_install_treeShader(ntw, GLOBAL.gb_main);
1830    aww->show();
1831
1832    error = GB_request_undo_type(GLOBAL.gb_main, GB_UNDO_UNDO);
1833    if (error) aw_message(error);
1834
1835    return ntw;
1836}
Note: See TracBrowser for help on using the repository browser.