source: branches/lib/NTREE/NT_extern.cxx

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