source: tags/arb-6.0/GENOM/GEN_map.cxx

Last change on this file was 12303, checked in by westram, 10 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 70.0 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : GEN_map.cxx                                       //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in 2001           //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "GEN_local.hxx"
13#include "GEN_gene.hxx"
14#include "GEN_graphic.hxx"
15#include "GEN_nds.hxx"
16#include "EXP_local.hxx"
17
18#include <dbui.h>
19#include <aw_preset.hxx>
20#include <aw_awars.hxx>
21#include <aw_question.hxx>
22#include <AW_rename.hxx>
23#include <awt.hxx>
24#include <awt_input_mask.hxx>
25#include <aw_msg.hxx>
26#include <arb_progress.h>
27#include <aw_root.hxx>
28#include <adGene.h>
29#include <db_query.h>
30#include <rootAsWin.h>
31#include <mode_text.h>
32#include <ad_cb.h>
33
34#include <map>
35
36using namespace std;
37
38extern GBDATA *GLOBAL_gb_main;
39
40// -----------------------
41//      GEN_map_window
42
43class GEN_map_window : public AW_window_menu_modes {
44    int          window_nr;
45    GEN_graphic *gen_graphic;
46    AWT_canvas  *gen_canvas;
47
48    GEN_map_window(const GEN_map_window& other); // copying not allowed
49    GEN_map_window& operator = (const GEN_map_window& other); // assignment not allowed
50public:
51    GEN_map_window(int window_nr_)
52        : AW_window_menu_modes()
53        , window_nr(window_nr_)
54        , gen_graphic(0)
55        , gen_canvas(0)
56    {}
57
58    void init(AW_root *root, GBDATA *gb_main);
59
60    GEN_graphic *get_graphic() const { gen_assert(gen_graphic); return gen_graphic; }
61    AWT_canvas *get_canvas() const { gen_assert(gen_canvas); return gen_canvas; }
62    int get_nr() const { return window_nr; }
63
64    GBDATA *get_gb_main() const { return get_canvas()->gb_main; }
65};
66
67// ------------------------
68//      GEN_map_manager
69
70class GEN_map_manager {
71    static AW_root         *aw_root;
72    static GBDATA          *gb_main;
73    static GEN_map_manager *the_manager;            // there can be only one!
74
75    int              window_counter;
76    GEN_map_window **windows;   // array of managed windows
77    int              windows_size; // size of 'windows' array
78
79    GEN_map_manager(const GEN_map_manager& other); // copying not allowed
80    GEN_map_manager& operator = (const GEN_map_manager& other); // assignment not allowed
81
82public:
83
84    GEN_map_manager();
85
86    static bool initialized() { return aw_root != 0; }
87    static void initialize(AW_root *aw_root_, GBDATA *gb_main_) { aw_root = aw_root_; gb_main = gb_main_; }
88
89    static GEN_map_manager *get_map_manager();
90
91    GEN_map_window *get_map_window(int nr);
92
93    int no_of_managed_windows() { return window_counter; }
94
95    typedef void (*GMW_CB2)(GEN_map_window*, AW_CL, AW_CL);
96    typedef void (*GMW_CB1)(GEN_map_window*, AW_CL);
97    typedef void (*GMW_CB0)(GEN_map_window*);
98
99    static void with_all_mapped_windows(GMW_CB2 callback, AW_CL cd1, AW_CL cd2);
100    static void with_all_mapped_windows(GMW_CB1 callback, AW_CL cd) { with_all_mapped_windows((GMW_CB2)callback, cd, 0); }
101    static void with_all_mapped_windows(GMW_CB0 callback) { with_all_mapped_windows((GMW_CB2)callback, 0, 0); }
102};
103
104// ____________________________________________________________
105// start of implementation of class GEN_map_manager:
106
107AW_root         *GEN_map_manager::aw_root     = 0;
108GBDATA          *GEN_map_manager::gb_main     = 0;
109GEN_map_manager *GEN_map_manager::the_manager = 0;
110
111GEN_map_manager::GEN_map_manager()
112    : window_counter(0)
113    , windows(new GEN_map_window *[5])
114    , windows_size(5)
115{
116    gen_assert(!the_manager);   // only one instance allowed
117    the_manager = this;
118}
119
120GEN_map_manager *GEN_map_manager::get_map_manager() {
121    if (!the_manager) {
122        gen_assert(aw_root);    // call initialize() before!
123        new GEN_map_manager;  // sets the manager
124        gen_assert(the_manager);
125    }
126    return the_manager;
127}
128
129void GEN_map_manager::with_all_mapped_windows(GMW_CB2 callback, AW_CL cd1, AW_CL cd2) {
130    GEN_map_manager *mm       = get_map_manager();
131    int              winCount = mm->no_of_managed_windows();
132    for (int nr = 0; nr<winCount; ++nr) {
133        callback(mm->get_map_window(nr), cd1, cd2);
134    }
135}
136
137GEN_map_window *GEN_map_manager::get_map_window(int nr)
138{
139    gen_assert(aw_root);
140    gen_assert(nr >= 0);
141    if (nr<window_counter) {
142        return windows[nr]; // window has already been created before
143    }
144
145    gen_assert(nr == window_counter); // increase nr sequentially!
146
147    window_counter++;
148    if (window_counter>windows_size) {
149        int             new_windows_size = windows_size+5;
150        GEN_map_window **new_windows      = new GEN_map_window*[new_windows_size];
151
152        for (int i = 0; i<windows_size; ++i) new_windows[i] = windows[i];
153
154        delete [] windows;
155        windows      = new_windows;
156        windows_size = new_windows_size;
157    }
158
159    gen_assert(nr<windows_size);
160
161    windows[nr] = new GEN_map_window(nr);
162    windows[nr]->init(aw_root, gb_main);
163
164    return windows[nr];
165}
166
167// -end- of implementation of class GEN_map_manager.
168
169
170
171const char *GEN_window_local_awar_name(const char *awar_name, int window_nr) {
172    return GBS_global_string("%s_%i", awar_name, window_nr);
173}
174
175static void reinit_NDS_4_window(GEN_map_window *win) {
176    win->get_graphic()->get_gen_root()->reinit_NDS();
177}
178
179static void GEN_NDS_changed(GBDATA *gb_viewkey) {
180    GBDATA *gb_main = GB_get_root(gb_viewkey);
181    GEN_make_node_text_init(gb_main);
182    GEN_map_manager::with_all_mapped_windows(reinit_NDS_4_window);
183}
184
185struct gene_container_changed_cb_data {
186    AWT_canvas  *canvas;
187    GEN_graphic *graphic;
188    GBDATA      *gb_gene_data; // callback was installed for this gene_data
189
190    gene_container_changed_cb_data() : canvas(0), graphic(0), gb_gene_data(0) {}
191    gene_container_changed_cb_data(AWT_canvas *canvas_, GEN_graphic *graphic_, GBDATA *gb_gene_data_)
192        : canvas(canvas_)
193        , graphic(graphic_)
194        , gb_gene_data(gb_gene_data_)
195    {}
196};
197
198static void GEN_gene_container_changed_cb(GBDATA*, gene_container_changed_cb_data *cb_data) {
199    cb_data->graphic->reinit_gen_root(cb_data->canvas, true);
200    cb_data->canvas->refresh();
201}
202
203static void GEN_gene_container_cb_installer(bool install, AWT_canvas *gmw, GEN_graphic *gg) {
204    typedef map<GEN_graphic*, gene_container_changed_cb_data> callback_dict;
205    static callback_dict                                      installed_callbacks;
206
207    callback_dict::iterator found = installed_callbacks.find(gg);
208    if (found == installed_callbacks.end()) {
209        gen_assert(install); // if !install then entry has to exist!
210        installed_callbacks[gg] = gene_container_changed_cb_data(gmw, gg, 0);
211        found                   = installed_callbacks.find(gg);
212        gen_assert(found != installed_callbacks.end());
213    }
214
215    gene_container_changed_cb_data *curr_cb_data = &(found->second);
216
217    if (install) {
218        gen_assert(curr_cb_data->gb_gene_data == 0); // 0 means : no callback installed
219        GBDATA         *gb_main    = gg->get_gb_main();
220        GB_transaction  ta(gb_main);
221        curr_cb_data->gb_gene_data = GEN_get_current_gene_data(gb_main, gg->get_aw_root());
222        // @@@ FIXME: get data of local genome!
223
224        if (curr_cb_data->gb_gene_data) {
225            GB_add_callback(curr_cb_data->gb_gene_data, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(GEN_gene_container_changed_cb, curr_cb_data));
226        }
227    }
228    else {
229        if (curr_cb_data->gb_gene_data) { // if callback is installed
230            GB_remove_callback(curr_cb_data->gb_gene_data, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(GEN_gene_container_changed_cb, curr_cb_data));
231            curr_cb_data->gb_gene_data = 0;
232        }
233    }
234}
235
236static void GEN_jump_cb(AW_window *aww, AW_CL cl_force_center_if_fits) {
237    GEN_map_window *win                  = dynamic_cast<GEN_map_window*>(aww);
238    bool            force_center_if_fits = (bool)cl_force_center_if_fits; // center gene if gene fits into display
239    gen_assert(win);
240
241    AW_device             *device = win->get_graphic()->get_device();
242    const AW_screen_area&  screen = device->get_area_size();
243#if defined(DEBUG)
244    printf("Window %i: screen is: %i/%i -> %i/%i\n", win->get_nr(), screen.l, screen.t, screen.r, screen.b);
245#endif // DEBUG
246
247    const GEN_root *gen_root = win->get_graphic()->get_gen_root();
248    if (gen_root) {
249        const AW::Rectangle& wrange = gen_root->get_selected_range();
250
251        if (wrange.valid()) {
252#if defined(DEBUG)
253            printf("Window %i: Draw world range of selected gene is: %f/%f -> %f/%f\n",
254                   win->get_nr(), wrange.left(), wrange.top(), wrange.right(), wrange.bottom());
255#endif // DEBUG
256
257            AW::Rectangle srange = device->transform(wrange);
258#if defined(DEBUG)
259            printf("Window %i: Draw screen range of selected gene is: %f/%f -> %f/%f\n",
260                   win->get_nr(), srange.left(), srange.top(), srange.right(), srange.bottom());
261#endif // DEBUG
262
263            AWT_canvas *canvas  = win->get_canvas();
264            int         scrollx = 0;
265            int         scrolly = 0;
266
267            if (srange.top() < 0) {
268                scrolly = AW_INT(srange.top())-2;
269            }
270            else if (srange.bottom() > screen.b) {
271                scrolly = AW_INT(srange.bottom())-screen.b+2;
272            }
273            if (srange.left() < 0) {
274                scrollx = AW_INT(srange.left())-2;
275            }
276            else if (srange.right() > screen.r) {
277                scrollx = AW_INT(srange.right())-screen.r+2;
278            }
279
280            if (force_center_if_fits) {
281                if (!scrollx) { // no scrolling needed, i.e. gene fits onto display horizontally
282                    int gene_center_x   = AW_INT((srange.left()+srange.right())/2);
283                    int screen_center_x = (screen.l+screen.r)/2;
284                    scrollx             = gene_center_x-screen_center_x;
285#if defined(DEBUG)
286                    printf("center x\n");
287#endif // DEBUG
288                }
289                if (!scrolly) { // no scrolling needed, i.e. gene fits onto display vertically
290                    int gene_center_y   = AW_INT((srange.top()+srange.bottom())/2);
291                    int screen_center_y = (screen.t+screen.b)/2;
292                    scrolly             = gene_center_y-screen_center_y;
293#if defined(DEBUG)
294                    printf("center y\n");
295#endif // DEBUG
296                }
297            }
298
299#if defined(DEBUG)
300            printf("scroll %i/%i\n", scrollx, scrolly);
301#endif // DEBUG
302
303            canvas->scroll(scrollx, scrolly);
304        }
305    }
306    win->get_canvas()->refresh();
307}
308
309static void GEN_jump_cb_auto(AW_root *root, GEN_map_window *win, bool force_refresh) {
310    int jump = root->awar(AWAR_GENMAP_AUTO_JUMP)->read_int();
311    if (jump) {
312        win->get_canvas()->refresh(); // needed to recalculate position
313        GEN_jump_cb(win, (AW_CL)false);
314    }
315    else if (force_refresh) win->get_canvas()->refresh();
316}
317
318static void GEN_local_organism_or_gene_name_changed_cb(AW_root *awr, AW_CL cl_win) {
319    GEN_map_window *win = (GEN_map_window*)cl_win;
320    win->get_graphic()->reinit_gen_root(win->get_canvas(), false);
321    GEN_jump_cb_auto(awr, win, true);
322}
323
324static void GEN_map_window_zoom_reset_and_refresh(GEN_map_window *gmw) {
325    gmw->get_canvas()->zoom_reset_and_refresh();
326}
327
328#define DISPLAY_TYPE_BIT(disp_type) (1<<(disp_type))
329#define ALL_DISPLAY_TYPES           (DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLES)-1)
330
331static void GEN_map_window_refresh_if_display_type(GEN_map_window *win, AW_CL cl_display_type_mask) {
332    int display_type_mask = int(cl_display_type_mask);
333    int my_display_type   = win->get_graphic()->get_display_style();
334
335    if (display_type_mask & DISPLAY_TYPE_BIT(my_display_type)) {
336        AWT_canvas *canvas = win->get_canvas();
337        canvas->refresh();
338    }
339}
340
341static void GEN_update_unlocked_organism_and_gene_awars(GEN_map_window *win, AW_CL cl_organism, AW_CL cl_gene) {
342    AW_root *aw_root   = win->get_graphic()->get_aw_root();
343    int      window_nr = win->get_nr();
344    if (!aw_root->awar(AWAR_LOCAL_ORGANISM_LOCK(window_nr))->read_int()) {
345        aw_root->awar(AWAR_LOCAL_ORGANISM_NAME(window_nr))->write_string((const char*)cl_organism);
346    }
347    if (!aw_root->awar(AWAR_LOCAL_GENE_LOCK(window_nr))->read_int()) {
348        aw_root->awar(AWAR_LOCAL_GENE_NAME(window_nr))->write_string((const char*)cl_gene);
349    }
350}
351
352static void GEN_organism_or_gene_changed_cb(AW_root *awr) {
353    char *organism = awr->awar(AWAR_ORGANISM_NAME)->read_string();
354    char *gene     = awr->awar(AWAR_GENE_NAME)->read_string();
355
356    GEN_map_manager::with_all_mapped_windows(GEN_update_unlocked_organism_and_gene_awars, (AW_CL)organism, (AW_CL)gene);
357
358    free(gene);
359    free(organism);
360}
361
362
363static void GEN_local_lock_changed_cb(AW_root *awr, AW_CL cl_win, AW_CL cl_what_lock) {
364    int             what_lock = (int)cl_what_lock;
365    GEN_map_window *win       = (GEN_map_window*)cl_win;
366    int             window_nr = win->get_nr();
367
368    const char *local_awar_name      = 0;
369    const char *local_lock_awar_name = 0;
370    const char *global_awar_name     = 0;
371
372    if (what_lock == 0) { // organism
373        local_awar_name      = AWAR_LOCAL_ORGANISM_NAME(window_nr);
374        local_lock_awar_name = AWAR_LOCAL_ORGANISM_LOCK(window_nr);
375        global_awar_name     = AWAR_ORGANISM_NAME;
376    }
377    else { // gene
378        local_awar_name      = AWAR_LOCAL_GENE_NAME(window_nr);
379        local_lock_awar_name = AWAR_LOCAL_GENE_LOCK(window_nr);
380        global_awar_name     = AWAR_GENE_NAME;
381    }
382
383    AW_awar *local_awar  = awr->awar(local_awar_name);
384    AW_awar *global_awar = awr->awar(global_awar_name);
385
386    int lock_value = awr->awar(local_lock_awar_name)->read_int();
387    if (lock_value == 0) { // lock has been removed -> map to global awar
388        local_awar->map(global_awar);
389    }
390    else { // lock has been installed -> unmap from global awar
391        local_awar->unmap();
392        char *content = global_awar->read_string();
393        local_awar->write_string(content);
394        free(content);
395    }
396}
397
398// -------------------------------------
399//      display parameter change cb
400
401static void GEN_display_param_changed_cb(AW_root * /* awr */, AW_CL cl_display_type_mask) {
402    GEN_map_manager::with_all_mapped_windows(GEN_map_window_refresh_if_display_type, cl_display_type_mask);
403}
404inline void set_display_update_callback(AW_root *awr, const char *awar_name, int display_type_mask) {
405    awr->awar(awar_name)->add_callback(GEN_display_param_changed_cb, AW_CL(display_type_mask));
406}
407
408// --------------------------
409//      View-local AWARS
410
411static void GEN_create_genemap_local_awars(AW_root *aw_root, AW_default /* def */, int window_nr) {
412    // awars local to each view
413
414    aw_root->awar_int(AWAR_GENMAP_DISPLAY_TYPE(window_nr), GEN_DISPLAY_STYLE_RADIAL); // @@@ FIXME: make local
415
416    aw_root->awar_string(AWAR_LOCAL_ORGANISM_NAME(window_nr), "");
417    aw_root->awar_string(AWAR_LOCAL_GENE_NAME(window_nr), "");
418
419    aw_root->awar_int(AWAR_LOCAL_ORGANISM_LOCK(window_nr), 0);
420    aw_root->awar_int(AWAR_LOCAL_GENE_LOCK(window_nr), 0);
421}
422
423static void GEN_add_local_awar_callbacks(AW_root *awr, AW_default /* def */, GEN_map_window *win) {
424    int window_nr = win->get_nr();
425
426    awr->awar(AWAR_LOCAL_ORGANISM_NAME(window_nr))->add_callback(GEN_local_organism_or_gene_name_changed_cb, (AW_CL)win);
427    awr->awar(AWAR_LOCAL_GENE_NAME(window_nr))->add_callback(GEN_local_organism_or_gene_name_changed_cb, (AW_CL)win);
428
429    AW_awar *awar_lock_organism = awr->awar(AWAR_LOCAL_ORGANISM_LOCK(window_nr));
430    AW_awar *awar_lock_gene     = awr->awar(AWAR_LOCAL_GENE_LOCK(window_nr));
431
432    awar_lock_organism->add_callback(GEN_local_lock_changed_cb, (AW_CL)win, (AW_CL)0);
433    awar_lock_gene->add_callback(GEN_local_lock_changed_cb, (AW_CL)win, (AW_CL)1);
434
435    awar_lock_organism->touch();
436    awar_lock_gene->touch();
437}
438
439// ----------------------
440//      global AWARS
441
442static void GEN_create_genemap_global_awars(AW_root *aw_root, AW_default def, GBDATA *gb_main) {
443    // layout options:
444
445    aw_root->awar_int(AWAR_GENMAP_ARROW_SIZE, 150);
446    aw_root->awar_int(AWAR_GENMAP_SHOW_HIDDEN, 0);
447    aw_root->awar_int(AWAR_GENMAP_SHOW_ALL_NDS, 0);
448
449    aw_root->awar_int(AWAR_GENMAP_BOOK_BASES_PER_LINE, 15000);
450    aw_root->awar_float(AWAR_GENMAP_BOOK_WIDTH_FACTOR, 0.1);
451    aw_root->awar_int(AWAR_GENMAP_BOOK_LINE_HEIGHT, 20);
452    aw_root->awar_int(AWAR_GENMAP_BOOK_LINE_SPACE, 5);
453
454    aw_root->awar_float(AWAR_GENMAP_VERTICAL_FACTOR_X, 1.0);
455    aw_root->awar_float(AWAR_GENMAP_VERTICAL_FACTOR_Y, 0.3);
456
457    aw_root->awar_float(AWAR_GENMAP_RADIAL_INSIDE, 50);
458    aw_root->awar_float(AWAR_GENMAP_RADIAL_OUTSIDE, 4);
459
460    // other options:
461
462    aw_root->awar_int(AWAR_GENMAP_AUTO_JUMP, 1);
463
464    GEN_create_nds_vars(aw_root, def, gb_main, makeDatabaseCallback(GEN_NDS_changed));
465}
466
467static void GEN_add_global_awar_callbacks(AW_root *awr) {
468    set_display_update_callback(awr, AWAR_GENMAP_ARROW_SIZE,          ALL_DISPLAY_TYPES^DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_BOOK));
469    set_display_update_callback(awr, AWAR_GENMAP_SHOW_HIDDEN,         ALL_DISPLAY_TYPES);
470    set_display_update_callback(awr, AWAR_GENMAP_SHOW_ALL_NDS,        ALL_DISPLAY_TYPES);
471
472    set_display_update_callback(awr, AWAR_GENMAP_BOOK_BASES_PER_LINE, DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_BOOK));
473    set_display_update_callback(awr, AWAR_GENMAP_BOOK_WIDTH_FACTOR,   DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_BOOK));
474    set_display_update_callback(awr, AWAR_GENMAP_BOOK_LINE_HEIGHT,    DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_BOOK));
475    set_display_update_callback(awr, AWAR_GENMAP_BOOK_LINE_SPACE,     DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_BOOK));
476
477    set_display_update_callback(awr, AWAR_GENMAP_VERTICAL_FACTOR_X,   DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_VERTICAL));
478    set_display_update_callback(awr, AWAR_GENMAP_VERTICAL_FACTOR_Y,   DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_VERTICAL));
479
480    set_display_update_callback(awr, AWAR_GENMAP_RADIAL_INSIDE,       DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_RADIAL));
481    set_display_update_callback(awr, AWAR_GENMAP_RADIAL_OUTSIDE,      DISPLAY_TYPE_BIT(GEN_DISPLAY_STYLE_RADIAL));
482
483    awr->awar(AWAR_ORGANISM_NAME)->add_callback(GEN_organism_or_gene_changed_cb);
484    awr->awar(AWAR_GENE_NAME)->add_callback(GEN_organism_or_gene_changed_cb);
485}
486
487
488// --------------------------------------------------------------------------------
489
490static void GEN_mode_event(AW_window *aws, GEN_map_window *win, AWT_COMMAND_MODE mode) {
491    const char *text = 0;
492    switch (mode) {
493        case AWT_MODE_SELECT: text = MODE_TEXT_1BUTTON("SELECT", "click to select a gene"); break;
494        case AWT_MODE_INFO:   text = MODE_TEXT_1BUTTON("INFO",   "click for info");         break;
495
496        case AWT_MODE_ZOOM: text = MODE_TEXT_STANDARD_ZOOMMODE(); break;
497
498        default: text = no_mode_text_defined(); break;
499    }
500
501    gen_assert(strlen(text) < AWAR_FOOTER_MAX_LEN); // text too long!
502
503    aws->get_root()->awar(AWAR_FOOTER)->write_string(text);
504    AWT_canvas *canvas = win->get_canvas();
505    canvas->set_mode(mode);
506    canvas->refresh();
507}
508
509static void GEN_undo_cb(AW_window *, AW_CL undo_type, AW_CL cl_gb_main) {
510    GBDATA   *gb_main = (GBDATA*)cl_gb_main;
511    GB_ERROR  error   = GB_undo(gb_main, (GB_UNDO_TYPE)undo_type);
512    if (error) {
513        aw_message(error);
514    }
515    else {
516        GB_begin_transaction(gb_main);
517        GB_commit_transaction(gb_main);
518    }
519}
520
521static AW_window *GEN_create_options_window(AW_root *awr) {
522    static AW_window_simple *aws = 0;
523    if (!aws) {
524
525        aws = new AW_window_simple;
526        aws->init(awr, "GEN_OPTIONS", "GENE MAP OPTIONS");
527        aws->load_xfig("gene_options.fig");
528
529        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
530        aws->create_button("CLOSE", "CLOSE", "C");
531
532        aws->at("help"); aws->callback(makeHelpCallback("gene_options.hlp"));
533        aws->create_button("HELP", "HELP", "H");
534
535        aws->at("button");
536        aws->auto_space(10, 10);
537        aws->label_length(30);
538
539        aws->label("Auto jump to selected gene");
540        aws->create_toggle(AWAR_GENMAP_AUTO_JUMP);
541        aws->at_newline();
542    }
543    return aws;
544}
545
546static AW_window *GEN_create_layout_window(AW_root *awr) {
547    static AW_window_simple *aws = 0;
548
549    if (!aws) {
550        aws = new AW_window_simple;
551
552        aws->init(awr, "GENE_LAYOUT", "Gene Map Layout");
553        aws->load_xfig("gene_layout.fig");
554
555        aws->callback((AW_CB0)AW_POPDOWN);
556        aws->at("close");
557        aws->create_button("CLOSE", "CLOSE", "C");
558
559        aws->callback(makeHelpCallback("gen_layout.hlp"));
560        aws->at("help");
561        aws->create_button("HELP", "HELP", "H");
562
563        aws->at("base_pos");        aws->create_input_field(AWAR_GENMAP_BOOK_BASES_PER_LINE, 15);
564        aws->at("width_factor");    aws->create_input_field(AWAR_GENMAP_BOOK_WIDTH_FACTOR, 7);
565        aws->at("line_height");     aws->create_input_field(AWAR_GENMAP_BOOK_LINE_HEIGHT, 5);
566        aws->at("line_space");      aws->create_input_field(AWAR_GENMAP_BOOK_LINE_SPACE, 5);
567
568        aws->at("factor_x");        aws->create_input_field(AWAR_GENMAP_VERTICAL_FACTOR_X, 5);
569        aws->at("factor_y");        aws->create_input_field(AWAR_GENMAP_VERTICAL_FACTOR_Y, 5);
570
571        aws->at("inside");          aws->create_input_field(AWAR_GENMAP_RADIAL_INSIDE, 5);
572        aws->at("outside");         aws->create_input_field(AWAR_GENMAP_RADIAL_OUTSIDE, 5);
573
574        aws->at("arrow_size");      aws->create_input_field(AWAR_GENMAP_ARROW_SIZE, 5);
575
576        aws->at("show_hidden");
577        aws->label("Show hidden genes");
578        aws->create_toggle(AWAR_GENMAP_SHOW_HIDDEN);
579
580        aws->at("show_all");
581        aws->label("Show NDS for all genes");
582        aws->create_toggle(AWAR_GENMAP_SHOW_ALL_NDS);
583    }
584    return aws;
585}
586
587enum GEN_PERFORM_MODE {
588    GEN_PERFORM_ALL_ORGANISMS,
589    GEN_PERFORM_CURRENT_ORGANISM,
590    GEN_PERFORM_ALL_BUT_CURRENT_ORGANISM,
591    GEN_PERFORM_MARKED_ORGANISMS,
592
593    GEN_PERFORM_MODES, // counter
594};
595
596static const char *GEN_PERFORM_MODE_id[GEN_PERFORM_MODES] = {
597    "org_all",
598    "org_current",
599    "org_butcur",
600    "org_marked",
601};
602
603inline string performmode_relative_id(const char *id, GEN_PERFORM_MODE pmode) {
604    return GBS_global_string("%s_%s", GEN_PERFORM_MODE_id[pmode], id);
605}
606
607enum GEN_MARK_MODE {
608    GEN_MARK,
609    GEN_UNMARK,
610    GEN_INVERT_MARKED,
611    GEN_COUNT_MARKED,
612
613    //     GEN_MARK_COLORED,              done by awt_colorize_marked now
614    //     GEN_UNMARK_COLORED,
615    //     GEN_INVERT_COLORED,
616    //     GEN_COLORIZE_MARKED,
617
618    GEN_EXTRACT_MARKED,
619
620    GEN_MARK_HIDDEN,
621    GEN_MARK_VISIBLE,
622    GEN_UNMARK_HIDDEN,
623    GEN_UNMARK_VISIBLE
624};
625
626enum GEN_HIDE_MODE {
627    GEN_HIDE_ALL,
628    GEN_UNHIDE_ALL,
629    GEN_INVERT_HIDE_ALL,
630
631    GEN_HIDE_MARKED,
632    GEN_UNHIDE_MARKED,
633    GEN_INVERT_HIDE_MARKED
634};
635
636// --------------------------------------------------------------------------------
637
638inline bool nameIsUnique(const char *short_name, GBDATA *gb_species_data) {
639    return GBT_find_species_rel_species_data(gb_species_data, short_name)==0;
640}
641
642static GB_ERROR GEN_species_add_entry(GBDATA *gb_pseudo, const char *key, const char *value) {
643    GB_ERROR  error = 0;
644    GB_clear_error();
645    GBDATA   *gbd   = GB_entry(gb_pseudo, key);
646
647    if (!gbd) { // key does not exist yet -> create
648        gbd             = GB_create(gb_pseudo, key, GB_STRING);
649        if (!gbd) error = GB_await_error();
650    }
651    else { // key exists
652        if (GB_read_type(gbd) != GB_STRING) { // test correct key type
653            error = GB_export_errorf("field '%s' exists and has wrong type", key);
654        }
655    }
656
657    if (!error) error = GB_write_string(gbd, value);
658
659    return error;
660}
661
662static AW_repeated_question *ask_about_existing_gene_species = 0;
663static AW_repeated_question *ask_to_overwrite_alignment      = 0;
664
665struct EG2PS_data : virtual Noncopyable {
666    arb_progress        progress;
667    GBDATA             *gb_species_data;
668    char               *ali;
669    UniqueNameDetector  existing;
670    GB_HASH            *pseudo_hash;
671    int                 duplicateSpecies; // counts created gene-species with identical ACC
672    bool                nameProblem; // nameserver and DB disagree about names
673
674    EG2PS_data(const char *ali_, GBDATA *gb_species_data_, int marked_genes_)
675        : progress(marked_genes_), 
676          gb_species_data(gb_species_data_), 
677          ali(strdup(ali_)), 
678          existing(gb_species_data, marked_genes_), 
679          duplicateSpecies(0), 
680          nameProblem(false)
681    {
682        pseudo_hash = GEN_create_pseudo_species_hash(GB_get_root(gb_species_data), marked_genes_);
683    }
684
685    ~EG2PS_data() {
686        if (duplicateSpecies>0) {
687            aw_message(GBS_global_string("There are %i duplicated gene-species (with identical sequence and accession number)\n"
688                                         "Duplicated gene-species got names with numerical postfixes ('.1', '.2', ...)"
689                                         , duplicateSpecies));
690        }
691        if (nameProblem) {
692            aw_message("Naming problems occurred.\nYou have to call 'Species/Synchronize IDs'!");
693        }
694        GBS_free_hash(pseudo_hash);
695        free(ali);
696    }
697};
698
699static const char* readACC(GBDATA *gb_species_data, const char *name) {
700    const char *other_acc    = 0;
701    GBDATA *gb_other_species = GBT_find_species_rel_species_data(gb_species_data, name);
702    if (gb_other_species) {
703        GBDATA *gb_other_acc = GB_entry(gb_other_species, "acc");
704        if (gb_other_acc) other_acc = GB_read_char_pntr(gb_other_acc);
705    }
706    return other_acc;
707}
708
709static void gen_extract_gene_2_pseudoSpecies(GBDATA *gb_species, GBDATA *gb_gene, EG2PS_data *eg2ps) {
710    const char *gene_name         = GBT_read_name(gb_gene);
711    const char *species_name      = GBT_read_name(gb_species);
712    const char *full_species_name = GBT_read_char_pntr(gb_species, "full_name");
713
714    if (!full_species_name) full_species_name = species_name;
715
716    char     *full_name = GBS_global_string_copy("%s [%s]", full_species_name, gene_name);
717    char     *sequence  = GBT_read_gene_sequence(gb_gene, true, 0);
718    GB_ERROR  error     = 0;
719
720    if (!sequence) error = GB_await_error();
721    else {
722        const char *ali = eg2ps->ali;
723        long        id  = GBS_checksum(sequence, 1, ".-");
724        char        acc[100];
725
726        sprintf(acc, "ARB_GENE_%lX", id);
727
728        // test if this gene has been already extracted to a gene-species
729
730        GBDATA *gb_main                 = GB_get_root(gb_species);
731        GBDATA *gb_exist_geneSpec       = GEN_find_pseudo_species(gb_main, species_name, gene_name, eg2ps->pseudo_hash);
732        bool    create_new_gene_species = true;
733        char   *short_name              = 0;
734
735        if (gb_exist_geneSpec) {
736            const char *existing_name = GBT_read_name(gb_exist_geneSpec);
737
738            gen_assert(ask_about_existing_gene_species);
739            gen_assert(ask_to_overwrite_alignment);
740
741            char *question = GBS_global_string_copy("Already have a gene-species for %s/%s ('%s')", species_name, gene_name, existing_name);
742            int   answer   = ask_about_existing_gene_species->get_answer("existing_pseudo_species", question, "Overwrite species,Insert new alignment,Skip,Create new", "all", true);
743
744            create_new_gene_species = false;
745
746            switch (answer) {
747                case 0: {   // Overwrite species
748                    // @@@ FIXME:  delete species needed here
749                    create_new_gene_species = true;
750                    short_name              = strdup(existing_name);
751                    break;
752                }
753                case 1: {     // Insert new alignment or overwrite alignment
754                    GBDATA     *gb_ali = GB_entry(gb_exist_geneSpec, ali);
755                    if (gb_ali) { // the alignment already exists
756                        char *question2        = GBS_global_string_copy("Gene-species '%s' already has data in '%s'", existing_name, ali);
757                        int   overwrite_answer = ask_to_overwrite_alignment->get_answer("overwrite_gene_data", question2, "Overwrite data,Skip", "all", true);
758
759                        if (overwrite_answer == 1) error      = GBS_global_string("Skipped gene-species '%s' (already had data in alignment)", existing_name); // Skip
760                        else if (overwrite_answer == 2) error = "Aborted."; // Abort
761                        // @@@ FIXME: overwrite data is missing
762
763                        free(question2);
764                    }
765                    break;
766                }
767                case 2: {       // Skip existing ones
768                    error = GBS_global_string("Skipped gene-species '%s'", existing_name);
769                    break;
770                }
771                case 3: {   // Create with new name
772                    create_new_gene_species = true;
773                    break;
774                }
775                case 4: {   // Abort
776                    error = "Aborted.";
777                    break;
778                }
779                default: gen_assert(0);
780            }
781            free(question);
782        }
783
784        if (!error) {
785            if (create_new_gene_species) {
786                if (!short_name) { // create a new name
787                    error = AWTC_generate_one_name(gb_main, full_name, acc, 0, short_name);
788                    if (!error) { // name has been created
789                        if (eg2ps->existing.name_known(short_name)) { // nameserver-generated name is already in use
790                            const char *other_acc    = readACC(eg2ps->gb_species_data, short_name);
791                            if (other_acc) {
792                                if (strcmp(acc, other_acc) == 0) { // duplicate (gene-)species -> generate postfixed name
793                                    char *newName = 0;
794                                    for (int postfix = 1; ; ++postfix) {
795                                        newName = GBS_global_string_copy("%s.%i", short_name, postfix);
796                                        if (!eg2ps->existing.name_known(newName)) {
797                                            eg2ps->duplicateSpecies++;
798                                            break;
799                                        }
800
801                                        other_acc = readACC(eg2ps->gb_species_data, newName);
802                                        if (!other_acc || strcmp(acc, other_acc) != 0) {
803                                            eg2ps->nameProblem = true;
804                                            error              = GBS_global_string("Unexpected acc-mismatch for '%s'", newName);
805                                            break;
806                                        }
807                                    }
808
809                                    if (!error) freeset(short_name, newName);
810                                    else free(newName);
811                                }
812                                else { // different acc, but uses name generated by nameserver
813                                    eg2ps->nameProblem = true;
814                                    error              = GBS_global_string("acc of '%s' differs from acc stored in nameserver", short_name);
815                                }
816                            }
817                            else { // can't detect acc of existing species
818                                eg2ps->nameProblem = true;
819                                error       = GBS_global_string("can't detect acc of species '%s'", short_name);
820                            }
821                        }
822                    }
823                    if (error) {            // try to make a random name
824                        const char *msg = GBS_global_string("%s\nGenerating a random name instead.", error);
825                        aw_message(msg);
826                        error      = 0;
827
828                        short_name = AWTC_generate_random_name(eg2ps->existing);
829                        if (!short_name) error = GBS_global_string("Failed to create a new name for pseudo gene-species '%s'", full_name);
830                    }
831                }
832
833                if (!error) { // create the species
834                    gen_assert(short_name);
835                    gb_exist_geneSpec = GBT_find_or_create_species(gb_main, short_name);
836                    if (!gb_exist_geneSpec) error = GB_export_errorf("Failed to create pseudo-species '%s'", short_name);
837                    else eg2ps->existing.add_name(short_name);
838                }
839            }
840            else {
841                gen_assert(gb_exist_geneSpec); // do not generate new or skip -> should only occur when gene-species already existed
842            }
843
844            if (!error) { // write sequence data
845                GBDATA *gb_data     = GBT_add_data(gb_exist_geneSpec, ali, "data", GB_STRING);
846                if (!gb_data) error = GB_await_error();
847                else {
848                    size_t sequence_length = strlen(sequence);
849                    error                  = GBT_write_sequence(gb_data, ali, sequence_length, sequence);
850                }
851            }
852
853            // write other entries:
854            if (!error) error = GEN_species_add_entry(gb_exist_geneSpec, "full_name", full_name);
855            if (!error) error = GEN_species_add_entry(gb_exist_geneSpec, "ARB_origin_species", species_name);
856            if (!error) error = GEN_species_add_entry(gb_exist_geneSpec, "ARB_origin_gene", gene_name);
857            if (!error) GEN_add_pseudo_species_to_hash(gb_exist_geneSpec, eg2ps->pseudo_hash);
858            if (!error) error = GEN_species_add_entry(gb_exist_geneSpec, "acc", acc);
859
860            // copy codon_start and transl_table :
861            const char *codon_start  = 0;
862            const char *transl_table = 0;
863
864            {
865                GBDATA *gb_codon_start  = GB_entry(gb_gene, "codon_start");
866                GBDATA *gb_transl_table = GB_entry(gb_gene, "transl_table");
867
868                if (gb_codon_start)  codon_start  = GB_read_char_pntr(gb_codon_start);
869                if (gb_transl_table) transl_table = GB_read_char_pntr(gb_transl_table);
870            }
871
872            if (!error && codon_start)  error = GEN_species_add_entry(gb_exist_geneSpec, "codon_start", codon_start);
873            if (!error && transl_table) error = GEN_species_add_entry(gb_exist_geneSpec, "transl_table", transl_table);
874        }
875
876        free(short_name);
877        free(sequence);
878    }
879    if (error) aw_message(error);
880
881    free(full_name);
882}
883
884static long gen_count_marked_genes = 0; // used to count marked genes
885
886static void do_mark_command_for_one_species(int imode, GBDATA *gb_species, AW_CL cl_user) {
887    GEN_MARK_MODE mode = (GEN_MARK_MODE)imode;
888
889    for (GBDATA *gb_gene = GEN_first_gene(gb_species);
890         gb_gene;
891         gb_gene = GEN_next_gene(gb_gene))
892    {
893        bool mark_flag     = GB_read_flag(gb_gene) != 0;
894        bool org_mark_flag = mark_flag;
895
896        switch (mode) {
897            case GEN_MARK:              mark_flag = 1; break;
898            case GEN_UNMARK:            mark_flag = 0; break;
899            case GEN_INVERT_MARKED:     mark_flag = !mark_flag; break;
900
901            case GEN_COUNT_MARKED: {
902                if (mark_flag) ++gen_count_marked_genes;
903                break;
904            }
905            case GEN_EXTRACT_MARKED: {
906                if (mark_flag) {
907                    EG2PS_data *eg2ps = (EG2PS_data*)cl_user;
908                    gen_extract_gene_2_pseudoSpecies(gb_species, gb_gene, eg2ps);
909                    eg2ps->progress.inc();
910                }
911                break;
912            }
913            default: {
914                GBDATA *gb_hidden = GB_entry(gb_gene, ARB_HIDDEN);
915                bool    hidden    = gb_hidden ? GB_read_byte(gb_hidden) != 0 : false;
916
917                switch (mode) {
918                    case GEN_MARK_HIDDEN:       if (hidden) mark_flag = 1; break;
919                    case GEN_UNMARK_HIDDEN:     if (hidden) mark_flag = 0; break;
920                    case GEN_MARK_VISIBLE:      if (!hidden) mark_flag = 1; break;
921                    case GEN_UNMARK_VISIBLE:    if (!hidden) mark_flag = 0; break;
922                    default: gen_assert(0); break;
923                }
924            }
925        }
926
927        if (mark_flag != org_mark_flag) GB_write_flag(gb_gene, mark_flag ? 1 : 0);
928    }
929}
930
931static void do_hide_command_for_one_species(int imode, GBDATA *gb_species, AW_CL /* cl_user */) {
932    GEN_HIDE_MODE mode = (GEN_HIDE_MODE)imode;
933
934    for (GBDATA *gb_gene = GEN_first_gene(gb_species);
935         gb_gene;
936         gb_gene = GEN_next_gene(gb_gene))
937    {
938        bool marked = GB_read_flag(gb_gene) != 0;
939
940        GBDATA *gb_hidden  = GB_entry(gb_gene, ARB_HIDDEN);
941        bool    hidden     = gb_hidden ? (GB_read_byte(gb_hidden) != 0) : false;
942        bool    org_hidden = hidden;
943
944        switch (mode) {
945            case GEN_HIDE_ALL:              hidden = true; break;
946            case GEN_UNHIDE_ALL:            hidden = false; break;
947            case GEN_INVERT_HIDE_ALL:       hidden = !hidden; break;
948            case GEN_HIDE_MARKED:           if (marked) hidden = true; break;
949            case GEN_UNHIDE_MARKED:         if (marked) hidden = false; break;
950            case GEN_INVERT_HIDE_MARKED:    if (marked) hidden = !hidden; break;
951            default: gen_assert(0); break;
952        }
953
954        if (hidden != org_hidden) {
955            if (!gb_hidden) gb_hidden = GB_create(gb_gene, ARB_HIDDEN, GB_BYTE);
956            GB_write_byte(gb_hidden, hidden ? 1 : 0); // change gene visibility
957        }
958    }
959}
960
961static void GEN_perform_command(AW_window *aww, GBDATA *gb_main, GEN_PERFORM_MODE pmode,
962                                void (*do_command)(int cmode, GBDATA *gb_species, AW_CL cl_user), int mode, AW_CL cl_user) {
963    GB_ERROR error = 0;
964
965    GB_begin_transaction(gb_main);
966
967    switch (pmode) {
968        case GEN_PERFORM_ALL_ORGANISMS: {
969            for (GBDATA *gb_organism = GEN_first_organism(gb_main);
970                 gb_organism;
971                 gb_organism = GEN_next_organism(gb_organism))
972            {
973                do_command(mode, gb_organism, cl_user);
974            }
975            break;
976        }
977        case GEN_PERFORM_MARKED_ORGANISMS: {
978            for (GBDATA *gb_organism = GEN_first_marked_organism(gb_main);
979                 gb_organism;
980                 gb_organism = GEN_next_marked_organism(gb_organism))
981            {
982                do_command(mode, gb_organism, cl_user);
983            }
984            break;
985        }
986        case GEN_PERFORM_ALL_BUT_CURRENT_ORGANISM: {
987            AW_root *aw_root          = aww->get_root();
988            GBDATA  *gb_curr_organism = GEN_get_current_organism(gb_main, aw_root);
989
990            for (GBDATA *gb_organism = GEN_first_organism(gb_main);
991                 gb_organism;
992                 gb_organism = GEN_next_organism(gb_organism))
993            {
994                if (gb_organism != gb_curr_organism) do_command(mode, gb_organism, cl_user);
995            }
996            break;
997        }
998        case GEN_PERFORM_CURRENT_ORGANISM: {
999            AW_root *aw_root     = aww->get_root();
1000            GBDATA  *gb_organism = GEN_get_current_organism(gb_main, aw_root);
1001
1002            if (!gb_organism) {
1003                error = "First you have to select a species.";
1004            }
1005            else {
1006                do_command(mode, gb_organism, cl_user);
1007            }
1008            break;
1009        }
1010        default: {
1011            gen_assert(0);
1012            break;
1013        }
1014    }
1015
1016    GB_end_transaction_show_error(gb_main, error, aw_message);
1017}
1018
1019class GEN_unique_param {
1020    GEN_unique_param(GBDATA *gb_main_, AW_CL unique_)
1021        : unique(unique_)
1022        , gb_main(gb_main_)
1023    {}
1024
1025    typedef map<AW_CL, GEN_unique_param> ExistingParams;
1026    static ExistingParams existing_params; // to ensure exactly one instance per 'command_mode'
1027
1028    AW_CL   unique;
1029public:
1030    GBDATA *gb_main;
1031
1032    AW_CL get_unique() { return unique; }
1033
1034    static GEN_unique_param *get(GBDATA *gb_main_, AW_CL unique_) { // get unique instance for each 'unique_'
1035        pair<ExistingParams::iterator, bool> created = existing_params.insert(ExistingParams::value_type(unique_, GEN_unique_param(gb_main_, unique_)));
1036        ExistingParams::iterator             wanted  = created.first;
1037        GEN_unique_param&                    param   = wanted->second;
1038        return &param;
1039    }
1040};
1041GEN_unique_param::ExistingParams GEN_unique_param::existing_params;
1042
1043
1044struct GEN_command_mode_param : public GEN_unique_param {
1045    static GEN_command_mode_param *get(GBDATA *gb_main_, AW_CL command_mode_) { return (GEN_command_mode_param*)GEN_unique_param::get(gb_main_, command_mode_); }
1046    AW_CL get_command_mode() { return get_unique(); }
1047};
1048
1049
1050static void GEN_hide_command(AW_window *aww, AW_CL cl_pmode, AW_CL cl_mode_param) {
1051    GEN_command_mode_param *param = (GEN_command_mode_param*)cl_mode_param;
1052    GEN_perform_command(aww, param->gb_main, (GEN_PERFORM_MODE)cl_pmode, do_hide_command_for_one_species, param->get_command_mode(), 0);
1053}
1054
1055static void GEN_mark_command(AW_window *aww, AW_CL cl_pmode, AW_CL cl_mode_param) {
1056    GEN_command_mode_param *param = (GEN_command_mode_param*)cl_mode_param;
1057
1058    gen_count_marked_genes = 0;
1059    GEN_perform_command(aww, param->gb_main, (GEN_PERFORM_MODE)cl_pmode, do_mark_command_for_one_species, param->get_command_mode(), 0);
1060
1061    if ((GEN_MARK_MODE)param->get_command_mode() == GEN_COUNT_MARKED) {
1062        const char *where = 0;
1063
1064        switch ((GEN_PERFORM_MODE)cl_pmode) {
1065            case GEN_PERFORM_CURRENT_ORGANISM:         where = "the current species"; break;
1066            case GEN_PERFORM_MARKED_ORGANISMS:         where = "all marked species"; break;
1067            case GEN_PERFORM_ALL_ORGANISMS:            where = "all species"; break;
1068            case GEN_PERFORM_ALL_BUT_CURRENT_ORGANISM: where = "all but the current species"; break;
1069            default: gen_assert(0); break;
1070        }
1071        aw_message(GBS_global_string("There are %li marked genes in %s", gen_count_marked_genes, where));
1072    }
1073}
1074
1075struct GEN_extract_mode_param : public GEN_unique_param {
1076    static GEN_extract_mode_param *get(GBDATA *gb_main_, GEN_PERFORM_MODE perform_mode) { return (GEN_extract_mode_param*)GEN_unique_param::get(gb_main_, perform_mode); }
1077    GEN_PERFORM_MODE get_perform_mode() { return (GEN_PERFORM_MODE)get_unique(); }
1078};
1079
1080static void gene_extract_cb(AW_window *aww, AW_CL cl_GEN_extract_mode_param) {
1081    GEN_extract_mode_param *param   = (GEN_extract_mode_param*)cl_GEN_extract_mode_param;
1082    GBDATA                 *gb_main = param->gb_main;
1083    char                   *ali     = aww->get_root()->awar(AWAR_GENE_EXTRACT_ALI)->read_string();
1084    GB_ERROR                error   = GBT_check_alignment_name(ali);
1085
1086    if (!error) {
1087        GB_transaction  ta(gb_main);
1088        GBDATA         *gb_ali = GBT_get_alignment(gb_main, ali);
1089
1090        if (!gb_ali && !GBT_create_alignment(gb_main, ali, 0, 0, 0, "dna")) {
1091            error = GB_await_error();
1092        }
1093    }
1094
1095    if (error) {
1096        aw_message(error);
1097    }
1098    else {
1099        ask_about_existing_gene_species = new AW_repeated_question;
1100        ask_to_overwrite_alignment      = new AW_repeated_question;
1101
1102        arb_progress progress("Extracting pseudo-species");
1103        {
1104            EG2PS_data *eg2ps = 0;
1105            {
1106                gen_count_marked_genes = 0;
1107                GEN_perform_command(aww, gb_main, param->get_perform_mode(), do_mark_command_for_one_species, GEN_COUNT_MARKED, 0);
1108
1109                GB_transaction  ta(gb_main);
1110                GBDATA         *gb_species_data = GBT_get_species_data(gb_main);
1111                eg2ps                           = new EG2PS_data(ali, gb_species_data, gen_count_marked_genes);
1112            }
1113
1114            PersistentNameServerConnection stayAlive;
1115
1116            GEN_perform_command(aww, gb_main, param->get_perform_mode(), do_mark_command_for_one_species, GEN_EXTRACT_MARKED, (AW_CL)eg2ps);
1117            delete eg2ps;
1118        }
1119
1120        delete ask_to_overwrite_alignment;
1121        delete ask_about_existing_gene_species;
1122        ask_to_overwrite_alignment      = 0;
1123        ask_about_existing_gene_species = 0;
1124    }
1125    free(ali);
1126}
1127
1128static void mark_organisms(AW_window * /* aww */, AW_CL cl_mark, AW_CL cl_gb_main) {
1129    // cl_mark == 0 -> unmark
1130    // cl_mark == 1 -> mark
1131    // cl_mark == 2 -> invert mark
1132    // cl_mark == 3 -> mark organisms, unmark rest
1133
1134    GBDATA         *gb_main = (GBDATA*)cl_gb_main;
1135    GB_transaction  ta(gb_main);
1136    int             mark    = (int)cl_mark;
1137
1138    if (mark == 3) {
1139        GBT_mark_all(gb_main, 0); // unmark all species
1140        mark = 1;
1141    }
1142
1143    for (GBDATA *gb_org = GEN_first_organism(gb_main);
1144         gb_org;
1145         gb_org = GEN_next_organism(gb_org))
1146    {
1147        if (mark == 2) {
1148            GB_write_flag(gb_org, !GB_read_flag(gb_org)); // invert mark of organism
1149        }
1150        else {
1151            GB_write_flag(gb_org, mark); // mark/unmark organism
1152        }
1153    }
1154}
1155
1156
1157static void mark_gene_species(AW_window * /* aww */, AW_CL cl_mark, AW_CL cl_gb_main) {
1158    //  cl_mark == 0 -> unmark
1159    //  cl_mark == 1 -> mark
1160    //  cl_mark == 2 -> invert mark
1161    //  cl_mark == 3 -> mark gene-species, unmark rest
1162   
1163    GBDATA         *gb_main = (GBDATA*)cl_gb_main;
1164    GB_transaction  ta(gb_main);
1165    int             mark    = (int)cl_mark;
1166
1167    if (mark == 3) {
1168        GBT_mark_all(gb_main, 0); // unmark all species
1169        mark = 1;
1170    }
1171
1172    for (GBDATA *gb_pseudo = GEN_first_pseudo_species(gb_main);
1173         gb_pseudo;
1174         gb_pseudo = GEN_next_pseudo_species(gb_pseudo))
1175    {
1176        if (mark == 2) {
1177            GB_write_flag(gb_pseudo, !GB_read_flag(gb_pseudo)); // invert mark of pseudo-species
1178        }
1179        else {
1180            GB_write_flag(gb_pseudo, mark); // mark/unmark gene-species
1181        }
1182    }
1183}
1184
1185static void mark_gene_species_of_marked_genes(AW_window * /* aww */, AW_CL cl_gb_main, AW_CL) {
1186    GBDATA         *gb_main       = (GBDATA*)cl_gb_main;
1187    GB_transaction  ta(gb_main);
1188    GB_HASH        *organism_hash = GBT_create_organism_hash(gb_main);
1189
1190    for (GBDATA *gb_pseudo = GEN_first_pseudo_species(gb_main);
1191         gb_pseudo;
1192         gb_pseudo = GEN_next_pseudo_species(gb_pseudo))
1193    {
1194        GBDATA *gb_gene = GEN_find_origin_gene(gb_pseudo, organism_hash);
1195        if (GB_read_flag(gb_gene)) {
1196            GB_write_flag(gb_pseudo, 1); // mark pseudo
1197        }
1198    }
1199
1200    GBS_free_hash(organism_hash);
1201}
1202
1203
1204
1205static void mark_organisms_with_marked_genes(AW_window * /* aww */, AW_CL cl_gb_main, AW_CL) {
1206    GBDATA         *gb_main = (GBDATA*)cl_gb_main;
1207    GB_transaction  ta(gb_main);
1208
1209    for (GBDATA *gb_species = GEN_first_organism(gb_main);
1210         gb_species;
1211         gb_species = GEN_next_organism(gb_species))
1212    {
1213        for (GBDATA *gb_gene = GEN_first_gene(gb_species);
1214             gb_gene;
1215             gb_gene = GEN_next_gene(gb_gene))
1216        {
1217            if (GB_read_flag(gb_gene)) {
1218                GB_write_flag(gb_species, 1);
1219                break; // continue with next organism
1220            }
1221        }
1222    }
1223}
1224static void mark_gene_species_using_current_alignment(AW_window * /* aww */, AW_CL cl_gb_main, AW_CL) {
1225    GBDATA         *gb_main = (GBDATA*)cl_gb_main;
1226    GB_transaction  ta(gb_main);
1227    char           *ali = GBT_get_default_alignment(gb_main);
1228
1229    for (GBDATA *gb_pseudo = GEN_first_pseudo_species(gb_main);
1230         gb_pseudo;
1231         gb_pseudo = GEN_next_pseudo_species(gb_pseudo))
1232    {
1233        GBDATA *gb_ali = GB_entry(gb_pseudo, ali);
1234        if (gb_ali) {
1235            GBDATA *gb_data = GB_entry(gb_ali, "data");
1236            if (gb_data) {
1237                GB_write_flag(gb_pseudo, 1);
1238            }
1239        }
1240    }
1241}
1242static void mark_genes_of_marked_gene_species(AW_window * /* aww */, AW_CL cl_gb_main, AW_CL) {
1243    GBDATA         *gb_main = (GBDATA*)cl_gb_main;
1244    GB_transaction  ta(gb_main);
1245    GB_HASH        *organism_hash = GBT_create_organism_hash(gb_main);
1246
1247    for (GBDATA *gb_pseudo = GEN_first_pseudo_species(gb_main);
1248         gb_pseudo;
1249         gb_pseudo = GEN_next_pseudo_species(gb_pseudo))
1250    {
1251        if (GB_read_flag(gb_pseudo)) {
1252            GBDATA *gb_gene = GEN_find_origin_gene(gb_pseudo, organism_hash);
1253            GB_write_flag(gb_gene, 1); // mark gene
1254        }
1255    }
1256
1257    GBS_free_hash(organism_hash);
1258}
1259
1260static AW_window *create_gene_extract_window(AW_root *root, AW_CL cl_mode_param) {
1261    GEN_extract_mode_param *param     = (GEN_extract_mode_param*)cl_mode_param;
1262    AW_window_simple       *aws       = new AW_window_simple;
1263    string                  window_id = performmode_relative_id("EXTRACT_GENE", param->get_perform_mode());
1264
1265    aws->init(root, window_id.c_str(), "Extract genes to alignment");
1266    aws->load_xfig("ad_al_si.fig");
1267
1268    aws->callback((AW_CB0)AW_POPDOWN);
1269    aws->at("close");
1270    aws->create_button("CLOSE", "CLOSE", "C");
1271
1272    aws->at("label");
1273    aws->create_autosize_button(0, "Please enter the name\nof the alignment to extract to");
1274
1275    aws->at("input");
1276    aws->create_input_field(AWAR_GENE_EXTRACT_ALI, 15);
1277
1278    aws->at("ok");
1279    aws->callback(gene_extract_cb, (AW_CL)param);
1280
1281    aws->create_button("GO", "GO", "G");
1282
1283    return aws;
1284}
1285
1286static void GEN_insert_extract_submenu(AW_window_menu_modes *awm, GBDATA *gb_main, const char *macro_prefix, const char *submenu_name, const char *hot_key, const char *help_file) {
1287    awm->insert_sub_menu(submenu_name, hot_key);
1288
1289    char macro_name_buffer[50];
1290
1291    sprintf(macro_name_buffer, "%s_of_current", macro_prefix);
1292    awm->insert_menu_topic(macro_name_buffer, "of current species...", "c", help_file, AWM_ALL, AW_POPUP, (AW_CL)create_gene_extract_window, (AW_CL)GEN_extract_mode_param::get(gb_main, GEN_PERFORM_CURRENT_ORGANISM));
1293
1294    sprintf(macro_name_buffer, "%s_of_marked", macro_prefix);
1295    awm->insert_menu_topic(macro_name_buffer, "of marked species...", "m", help_file, AWM_ALL, AW_POPUP, (AW_CL)create_gene_extract_window, (AW_CL)GEN_extract_mode_param::get(gb_main, GEN_PERFORM_MARKED_ORGANISMS));
1296
1297    sprintf(macro_name_buffer, "%s_of_all", macro_prefix);
1298    awm->insert_menu_topic(macro_name_buffer, "of all species...", "a", help_file, AWM_ALL, AW_POPUP, (AW_CL)create_gene_extract_window, (AW_CL)GEN_extract_mode_param::get(gb_main, GEN_PERFORM_ALL_ORGANISMS));
1299
1300    awm->close_sub_menu();
1301}
1302
1303static void GEN_insert_multi_submenu(AW_window_menu_modes *awm, const char *macro_prefix, const char *submenu_name, const char *hot_key,
1304                              const char *help_file, void (*command)(AW_window*, AW_CL, AW_CL), AW_CL command_mode)
1305{
1306    awm->insert_sub_menu(submenu_name, hot_key);
1307
1308    char macro_name_buffer[50];
1309
1310    sprintf(macro_name_buffer, "%s_of_current", macro_prefix);
1311    awm->insert_menu_topic(macro_name_buffer, "of current species", "c", help_file, AWM_ALL, command, GEN_PERFORM_CURRENT_ORGANISM, command_mode);
1312
1313    sprintf(macro_name_buffer, "%s_of_all_but_current", macro_prefix);
1314    awm->insert_menu_topic(macro_name_buffer, "of all but current species", "b", help_file, AWM_ALL, command, GEN_PERFORM_ALL_BUT_CURRENT_ORGANISM, command_mode);
1315
1316    sprintf(macro_name_buffer, "%s_of_marked", macro_prefix);
1317    awm->insert_menu_topic(macro_name_buffer, "of marked species", "m", help_file, AWM_ALL, command, GEN_PERFORM_MARKED_ORGANISMS, command_mode);
1318
1319    sprintf(macro_name_buffer, "%s_of_all", macro_prefix);
1320    awm->insert_menu_topic(macro_name_buffer, "of all species", "a", help_file, AWM_ALL, command, GEN_PERFORM_ALL_ORGANISMS, command_mode);
1321
1322    awm->close_sub_menu();
1323}
1324
1325static void GEN_insert_mark_submenu(AW_window_menu_modes *awm, GBDATA *gb_main, const char *macro_prefix, const char *submenu_name, const char *hot_key, const char *help_file, GEN_MARK_MODE mark_mode) {
1326    GEN_insert_multi_submenu(awm, macro_prefix, submenu_name, hot_key, help_file, GEN_mark_command, (AW_CL)GEN_command_mode_param::get(gb_main, (AW_CL)mark_mode));
1327}
1328static void GEN_insert_hide_submenu(AW_window_menu_modes *awm, GBDATA *gb_main, const char *macro_prefix, const char *submenu_name, const char *hot_key, const char *help_file, GEN_HIDE_MODE hide_mode) {
1329    GEN_insert_multi_submenu(awm, macro_prefix, submenu_name, hot_key, help_file, GEN_hide_command, (AW_CL)GEN_command_mode_param::get(gb_main, (AW_CL)hide_mode));
1330}
1331
1332#if defined(DEBUG)
1333static AW_window *GEN_create_awar_debug_window(AW_root *aw_root) {
1334    static AW_window_simple *aws = 0;
1335    if (!aws) {
1336        aws = new AW_window_simple;
1337
1338        aws->init(aw_root, "DEBUG_AWARS", "DEBUG AWARS");
1339        aws->at(10, 10);
1340        aws->auto_space(10, 10);
1341
1342        const int width = 50;
1343
1344        ;                  aws->label("AWAR_SPECIES_NAME            "); aws->create_input_field(AWAR_SPECIES_NAME, width);
1345        aws->at_newline(); aws->label("AWAR_ORGANISM_NAME           "); aws->create_input_field(AWAR_ORGANISM_NAME, width);
1346        aws->at_newline(); aws->label("AWAR_GENE_NAME               "); aws->create_input_field(AWAR_GENE_NAME, width);
1347        aws->at_newline(); aws->label("AWAR_COMBINED_GENE_NAME      "); aws->create_input_field(AWAR_COMBINED_GENE_NAME, width);
1348        aws->at_newline(); aws->label("AWAR_EXPERIMENT_NAME         "); aws->create_input_field(AWAR_EXPERIMENT_NAME, width);
1349        aws->at_newline(); aws->label("AWAR_COMBINED_EXPERIMENT_NAME"); aws->create_input_field(AWAR_COMBINED_EXPERIMENT_NAME, width);
1350        aws->at_newline(); aws->label("AWAR_PROTEOM_NAME            "); aws->create_input_field(AWAR_PROTEOM_NAME, width);
1351        aws->at_newline(); aws->label("AWAR_PROTEIN_NAME            "); aws->create_input_field(AWAR_PROTEIN_NAME, width);
1352
1353        aws->window_fit();
1354    }
1355    return aws;
1356}
1357#endif // DEBUG
1358
1359// ---------------------------
1360//      user mask section
1361
1362struct GEN_item_type_species_selector : public awt_item_type_selector {
1363    GEN_item_type_species_selector() : awt_item_type_selector(AWT_IT_GENE) {}
1364    virtual ~GEN_item_type_species_selector() OVERRIDE {}
1365
1366    virtual const char *get_self_awar() const OVERRIDE {
1367        return AWAR_COMBINED_GENE_NAME;
1368    }
1369    virtual size_t get_self_awar_content_length() const OVERRIDE {
1370        return 12 + 1 + 40; // species-name+'/'+gene_name
1371    }
1372    virtual GBDATA *current(AW_root *root, GBDATA *gb_main) const OVERRIDE { // give the current item
1373        char   *species_name = root->awar(AWAR_ORGANISM_NAME)->read_string();
1374        char   *gene_name   = root->awar(AWAR_GENE_NAME)->read_string();
1375        GBDATA *gb_gene      = 0;
1376
1377        if (species_name[0] && gene_name[0]) {
1378            GB_transaction ta(gb_main);
1379            GBDATA *gb_species = GBT_find_species(gb_main, species_name);
1380            if (gb_species) {
1381                gb_gene = GEN_find_gene(gb_species, gene_name);
1382            }
1383        }
1384
1385        free(gene_name);
1386        free(species_name);
1387
1388        return gb_gene;
1389    }
1390    virtual const char *getKeyPath() const OVERRIDE { // give the keypath for items
1391        return CHANGE_KEY_PATH_GENES;
1392    }
1393};
1394
1395static GEN_item_type_species_selector item_type_gene;
1396
1397static void GEN_open_mask_window(AW_window *aww, int id, GBDATA *gb_main) {
1398    const awt_input_mask_descriptor *descriptor = AWT_look_input_mask(id);
1399    gen_assert(descriptor);
1400    if (descriptor) {
1401        AWT_initialize_input_mask(aww->get_root(), gb_main, &item_type_gene, descriptor->get_internal_maskname(), descriptor->is_local_mask());
1402    }
1403}
1404
1405static void GEN_create_mask_submenu(AW_window_menu_modes *awm, GBDATA *gb_main) {
1406    AWT_create_mask_submenu(awm, AWT_IT_GENE, GEN_open_mask_window, gb_main);
1407}
1408
1409static AW_window *create_colorize_genes_window(AW_root *aw_root, AW_CL cl_gb_main) {
1410    return QUERY::create_colorize_items_window(aw_root, (GBDATA*)cl_gb_main, GEN_get_selector());
1411}
1412
1413static AW_window *create_colorize_organisms_window(AW_root *aw_root, AW_CL cl_gb_main) {
1414    return QUERY::create_colorize_items_window(aw_root, (GBDATA*)cl_gb_main, ORGANISM_get_selector());
1415}
1416
1417static void GEN_create_organism_submenu(AW_window_menu_modes *awm, GBDATA *gb_main, bool submenu) {
1418    const char *title  = "Organisms";
1419    const char *hotkey = "O";
1420
1421    if (submenu) awm->insert_sub_menu(title, hotkey);
1422    else awm->create_menu(title, hotkey, AWM_ALL);
1423
1424    {
1425        awm->insert_menu_topic("organism_info", "Organism information", "i", "organism_info.hlp", AWM_ALL, RootAsWindowCallback::simple(DBUI::popup_organism_info_window, gb_main));
1426
1427        awm->sep______________();
1428
1429        awm->insert_menu_topic("mark_organisms",             "Mark All organisms",              "A", "organism_mark.hlp", AWM_ALL, mark_organisms, 1, (AW_CL)gb_main);
1430        awm->insert_menu_topic("mark_organisms_unmark_rest", "Mark all organisms, unmark Rest", "R", "organism_mark.hlp", AWM_ALL, mark_organisms, 3, (AW_CL)gb_main);
1431        awm->insert_menu_topic("unmark_organisms",           "Unmark all organisms",            "U", "organism_mark.hlp", AWM_ALL, mark_organisms, 0, (AW_CL)gb_main);
1432        awm->insert_menu_topic("invmark_organisms",          "Invert marks of all organisms",   "v", "organism_mark.hlp", AWM_ALL, mark_organisms, 2, (AW_CL)gb_main);
1433        awm->sep______________();
1434        awm->insert_menu_topic("mark_organisms_with_marked_genes", "Mark organisms with marked Genes", "G", "organism_mark.hlp", AWM_ALL, mark_organisms_with_marked_genes, (AW_CL)gb_main, 0);
1435        awm->sep______________();
1436        awm->insert_menu_topic("organism_colors",   "Colors ...",           "C",    "colorize.hlp", AWM_ALL, AW_POPUP,  (AW_CL)create_colorize_organisms_window, (AW_CL)gb_main);
1437    }
1438    if (submenu) awm->close_sub_menu();
1439}
1440
1441static void GEN_create_gene_species_submenu(AW_window_menu_modes *awm, GBDATA *gb_main, bool submenu) {
1442    const char *title  = "Gene-Species";
1443    const char *hotkey = "S";
1444
1445    if (submenu) awm->insert_sub_menu(title, hotkey);
1446    else awm->create_menu(title, hotkey, AWM_ALL);
1447
1448    {
1449        awm->insert_menu_topic("mark_gene_species",             "Mark All gene-species",              "A", "gene_species_mark.hlp", AWM_ALL, mark_gene_species, 1, (AW_CL)gb_main);
1450        awm->insert_menu_topic("mark_gene_species_unmark_rest", "Mark all gene-species, unmark Rest", "R", "gene_species_mark.hlp", AWM_ALL, mark_gene_species, 3, (AW_CL)gb_main);
1451        awm->insert_menu_topic("unmark_gene_species",           "Unmark all gene-species",            "U", "gene_species_mark.hlp", AWM_ALL, mark_gene_species, 0, (AW_CL)gb_main);
1452        awm->insert_menu_topic("invmark_gene_species",          "Invert marks of all gene-species",   "I", "gene_species_mark.hlp", AWM_ALL, mark_gene_species, 2, (AW_CL)gb_main);
1453        awm->sep______________();
1454        awm->insert_menu_topic("mark_gene_species_of_marked_genes", "Mark gene-species of marked genes",             "M", "gene_species_mark.hlp", AWM_ALL, mark_gene_species_of_marked_genes,         (AW_CL)gb_main, 0);
1455        awm->insert_menu_topic("mark_gene_species_curr_ali",        "Mark all gene-species using Current alignment", "C", "gene_species_mark.hlp", AWM_ALL, mark_gene_species_using_current_alignment, (AW_CL)gb_main, 0);
1456    }
1457
1458    if (submenu) awm->close_sub_menu();
1459}
1460
1461struct GEN_update_info {
1462    AWT_canvas *canvas1;        // just canvasses of different windows (needed for updates)
1463    AWT_canvas *canvas2;
1464};
1465
1466void GEN_create_genes_submenu(AW_window_menu_modes *awm, GBDATA *gb_main, bool for_ARB_NTREE) {
1467    awm->create_menu("Genome", "G", AWM_ALL);
1468    {
1469#if defined(DEBUG)
1470        awm->insert_menu_topic("debug_awars", "[DEBUG] Show main AWARs", "A", "no.hlp", AWM_ALL, AW_POPUP, (AW_CL)GEN_create_awar_debug_window, 0);
1471        awm->sep______________();
1472#endif // DEBUG
1473
1474        if (for_ARB_NTREE) {
1475            awm->insert_menu_topic("gene_map", "Gene Map", "p", "gene_map.hlp", AWM_ALL, makeCreateWindowCallback(GEN_create_first_map, gb_main)); // initial gene map
1476            awm->sep______________();
1477
1478            GEN_create_gene_species_submenu(awm, gb_main, true); // Gene-species
1479            GEN_create_organism_submenu    (awm, gb_main, true); // Organisms
1480            EXP_create_experiments_submenu (awm, gb_main, true); // Experiments
1481            awm->sep______________();
1482        }
1483
1484        awm->insert_menu_topic("gene_info",   "Gene information", "i", "gene_info.hlp",   AWM_ALL, RootAsWindowCallback::simple(GEN_popup_gene_infowindow, gb_main));
1485        awm->insert_menu_topic("gene_search", "Search and Query", "Q", "gene_search.hlp", AWM_ALL, AW_POPUP, (AW_CL)GEN_create_gene_query_window, (AW_CL)gb_main);
1486
1487        GEN_create_mask_submenu(awm, gb_main);
1488
1489        awm->sep______________();
1490
1491        GEN_insert_mark_submenu(awm, gb_main, "gene_mark_all",      "Mark all genes",      "M", "gene_mark.hlp", GEN_MARK);
1492        GEN_insert_mark_submenu(awm, gb_main, "gene_unmark_all",    "Unmark all genes",    "U", "gene_mark.hlp", GEN_UNMARK);
1493        GEN_insert_mark_submenu(awm, gb_main, "gene_invert_marked", "Invert marked genes", "v", "gene_mark.hlp", GEN_INVERT_MARKED);
1494        GEN_insert_mark_submenu(awm, gb_main, "gene_count_marked",  "Count marked genes",  "C", "gene_mark.hlp", GEN_COUNT_MARKED);
1495
1496        awm->insert_menu_topic("gene_colors", "Colors ...", "l", "colorize.hlp", AWM_ALL, AW_POPUP, (AW_CL)create_colorize_genes_window, (AW_CL)gb_main);
1497
1498        awm->sep______________();
1499
1500        awm->insert_menu_topic("mark_genes_of_marked_gene_species", "Mark genes of marked gene-species", "g", "gene_mark.hlp", AWM_ALL, mark_genes_of_marked_gene_species, (AW_CL)gb_main, 0);
1501
1502        awm->sep______________();
1503
1504        GEN_insert_extract_submenu(awm, gb_main, "gene_extract_marked", "Extract marked genes", "E", "gene_extract.hlp");
1505
1506        if (!for_ARB_NTREE) {   // only in ARB_GENE_MAP:
1507            awm->sep______________();
1508            GEN_insert_mark_submenu(awm, gb_main, "gene_mark_hidden",  "Mark hidden genes",  "h", "gene_hide.hlp", GEN_MARK_HIDDEN);
1509            GEN_insert_mark_submenu(awm, gb_main, "gene_mark_visible", "Mark visible genes", "s", "gene_hide.hlp", GEN_MARK_VISIBLE);
1510
1511            awm->sep______________();
1512            GEN_insert_mark_submenu(awm, gb_main, "gene_unmark_hidden",  "Unmark hidden genes",  "d", "gene_hide.hlp", GEN_UNMARK_HIDDEN);
1513            GEN_insert_mark_submenu(awm, gb_main, "gene_unmark_visible", "Unmark visible genes", "r", "gene_hide.hlp", GEN_UNMARK_VISIBLE);
1514        }
1515    }
1516}
1517
1518static void GEN_create_hide_submenu(AW_window_menu_modes *awm, GBDATA *gb_main) {
1519    awm->create_menu("Hide", "H", AWM_ALL);
1520    {
1521        GEN_insert_hide_submenu(awm, gb_main, "gene_hide_marked",    "Hide marked genes",        "H", "gene_hide.hlp", GEN_HIDE_MARKED);
1522        GEN_insert_hide_submenu(awm, gb_main, "gene_unhide_marked",  "Unhide marked genes",      "U", "gene_hide.hlp", GEN_UNHIDE_MARKED);
1523        GEN_insert_hide_submenu(awm, gb_main, "gene_invhide_marked", "Invert-hide marked genes", "v", "gene_hide.hlp", GEN_INVERT_HIDE_MARKED);
1524
1525        awm->sep______________();
1526        GEN_insert_hide_submenu(awm, gb_main, "gene_hide_all",    "Hide all genes",        "a", "gene_hide.hlp", GEN_HIDE_ALL);
1527        GEN_insert_hide_submenu(awm, gb_main, "gene_unhide_all",  "Unhide all genes",      "l", "gene_hide.hlp", GEN_UNHIDE_ALL);
1528        GEN_insert_hide_submenu(awm, gb_main, "gene_invhide_all", "Invert-hide all genes", "I", "gene_hide.hlp", GEN_INVERT_HIDE_ALL);
1529    }
1530}
1531
1532static void GEN_set_display_style(AW_window *aww, AW_CL cl_style) {
1533    GEN_DisplayStyle  style = (GEN_DisplayStyle)cl_style;
1534    GEN_map_window   *win   = dynamic_cast<GEN_map_window*>(aww);
1535    gen_assert(win);
1536
1537    win->get_root()->awar(AWAR_GENMAP_DISPLAY_TYPE(win->get_nr()))->write_int(style);
1538    win->get_graphic()->set_display_style(style);
1539    GEN_map_window_zoom_reset_and_refresh(win);
1540}
1541
1542static AW_window *GEN_create_map(AW_root *aw_root, GEN_create_map_param *param) {
1543    // param->window_nr shall be 0 for first window (called from ARB_NTREE)
1544    // additional views are always created by the previous window created with GEN_map
1545    GEN_map_manager *manager = 0;
1546
1547    if (!GEN_map_manager::initialized()) {          // first call
1548        gen_assert(param->window_nr == 0); // has to be 0 for first call
1549
1550        GEN_map_manager::initialize(aw_root, param->gb_main);
1551        manager = GEN_map_manager::get_map_manager(); // creates the manager
1552
1553        // global initialization (AWARS etc.) done here :
1554
1555        GEN_create_genemap_global_awars(aw_root, AW_ROOT_DEFAULT, param->gb_main);
1556        GEN_add_global_awar_callbacks(aw_root);
1557        {
1558            GB_transaction ta(param->gb_main);
1559            GEN_make_node_text_init(param->gb_main);
1560        }
1561    }
1562    else {
1563        manager = GEN_map_manager::get_map_manager();
1564    }
1565
1566    GEN_map_window *gmw = manager->get_map_window(param->window_nr);
1567    return gmw;
1568}
1569
1570AW_window *GEN_create_first_map(AW_root *aw_root, GBDATA *gb_main) {
1571    return GEN_create_map(aw_root, new GEN_create_map_param(gb_main, 0));
1572}
1573
1574// ____________________________________________________________
1575// start of implementation of class GEN_map_window::
1576
1577void GEN_map_window::init(AW_root *awr, GBDATA *gb_main) {
1578    {
1579        char *windowName = (window_nr == 0) ? strdup("ARB Gene Map") : GBS_global_string_copy("ARB Gene Map %i", window_nr);
1580        AW_window_menu_modes::init(awr, "ARB_GENE_MAP", windowName, 200, 200);
1581        free(windowName);
1582    }
1583
1584    GEN_create_genemap_local_awars(awr, AW_ROOT_DEFAULT, window_nr);
1585
1586    gen_graphic = new GEN_graphic(awr, gb_main, GEN_gene_container_cb_installer, window_nr);
1587    gen_canvas  = new AWT_canvas(gb_main, this, get_window_id(), gen_graphic, AWAR_SPECIES_NAME);
1588
1589    GEN_add_local_awar_callbacks(awr, AW_ROOT_DEFAULT, this);
1590
1591    {
1592        GB_transaction ta(gb_main);
1593        gen_graphic->reinit_gen_root(gen_canvas, false);
1594    }
1595
1596    gen_canvas->recalc_size_and_refresh();
1597    gen_canvas->set_mode(AWT_MODE_SELECT); // Default-Mode
1598
1599    // ---------------
1600    //      menus
1601
1602    // File Menu
1603    create_menu("File", "F", AWM_ALL);
1604    insert_menu_topic("close", "Close", "C", "quit.hlp", AWM_ALL, (AW_CB)AW_POPDOWN, 0, 0);
1605    insert_menu_topic("new_view", "New view", "v", "new_view.hlp", AWM_ALL, makeCreateWindowCallback(GEN_create_map, new GEN_create_map_param(gb_main, window_nr+1)));
1606
1607    GEN_create_genes_submenu       (this, gb_main, false); // Genes
1608    GEN_create_gene_species_submenu(this, gb_main, false); // Gene-species
1609    GEN_create_organism_submenu    (this, gb_main, false); // Organisms
1610    EXP_create_experiments_submenu (this, gb_main, false); // Experiments
1611    GEN_create_hide_submenu(this, gb_main);         // Hide Menu
1612
1613    // Properties Menu
1614    create_menu("Properties", "r", AWM_ALL);
1615    insert_menu_topic("gene_props_menu", "Menu: Colors and Fonts ...",          "M", "props_frame.hlp",     AWM_ALL, AW_preset_window);
1616    insert_menu_topic("gene_props",      "GENEMAP: Colors and Fonts ...",       "C", "gene_props_data.hlp", AWM_ALL, makeCreateWindowCallback(AW_create_gc_window, gen_canvas->gc_manager)); // @@@ FIXME: replace AW_create_gc_window by local function returning same window for all mapped views
1617    insert_menu_topic("gene_layout",     "Layout",                              "L", "gene_layout.hlp",     AWM_ALL, GEN_create_layout_window);
1618    insert_menu_topic("gene_options",    "Options",                             "O", "gene_options.hlp",    AWM_ALL, GEN_create_options_window);
1619    insert_menu_topic("gene_nds",        "NDS ( Select Gene Information ) ...", "N", "props_nds.hlp",       AWM_ALL, AW_POPUP, (AW_CL)GEN_open_nds_window, (AW_CL)gb_main);
1620    sep______________();
1621    AW_insert_common_property_menu_entries(this);
1622    sep______________();
1623    insert_menu_topic("gene_save_props",   "Save Defaults (ntree.arb)", "D", "savedef.hlp", AWM_ALL, AW_save_properties);
1624
1625    // ----------------------
1626    //      mode buttons
1627
1628    create_mode("mode_select.xpm", "gen_mode.hlp", AWM_ALL, makeWindowCallback(GEN_mode_event, this, AWT_MODE_SELECT));
1629    create_mode("mode_zoom.xpm",   "gen_mode.hlp", AWM_ALL, makeWindowCallback(GEN_mode_event, this, AWT_MODE_ZOOM));
1630    create_mode("mode_info.xpm",   "gen_mode.hlp", AWM_ALL, makeWindowCallback(GEN_mode_event, this, AWT_MODE_INFO));
1631
1632    // -------------------
1633    //      info area
1634
1635    set_info_area_height(250);
1636    at(11, 2);
1637    auto_space(2, -2);
1638    shadow_width(1);
1639
1640    // close + undo button, info area, define line y-positions:
1641
1642    int cur_x, cur_y, start_x, first_line_y, second_line_y, third_line_y;
1643    get_at_position(&start_x, &first_line_y);
1644    button_length(6);
1645
1646    at(start_x, first_line_y);
1647    help_text("quit.hlp");
1648    callback((AW_CB0)AW_POPDOWN);
1649    create_button("Close", "Close");
1650
1651    get_at_position(&cur_x, &cur_y);
1652
1653    int gene_x = cur_x;
1654    at_newline();
1655    get_at_position(&cur_x, &second_line_y);
1656
1657    at(start_x, second_line_y);
1658    help_text("undo.hlp");
1659    callback(GEN_undo_cb, (AW_CL)GB_UNDO_UNDO, (AW_CL)gb_main);
1660    create_button("Undo", "Undo");
1661
1662    at_newline();
1663    get_at_position(&cur_x, &third_line_y);
1664
1665    button_length(AWAR_FOOTER_MAX_LEN);
1666    create_button(0, AWAR_FOOTER);
1667
1668    at_newline();
1669    get_at_position(&cur_x, &cur_y);
1670    set_info_area_height(cur_y+6);
1671
1672    // gene+species buttons:
1673    button_length(20);
1674
1675    at(gene_x, first_line_y);
1676    help_text("organism_search.hlp");
1677    callback(makeCreateWindowCallback(DBUI::create_species_query_window, gb_main)); // @@@ should use an organism search (using ITEM_organism)
1678    create_button("SEARCH_ORGANISM", AWAR_LOCAL_ORGANISM_NAME(window_nr));
1679
1680    at(gene_x, second_line_y);
1681    help_text("gene_search.hlp");
1682    callback(AW_POPUP, (AW_CL)GEN_create_gene_query_window, (AW_CL)gb_main);
1683    create_button("SEARCH_GENE", AWAR_LOCAL_GENE_NAME(window_nr));
1684
1685    get_at_position(&cur_x, &cur_y);
1686    int lock_x = cur_x;
1687
1688    at(lock_x, first_line_y);
1689    create_toggle(AWAR_LOCAL_ORGANISM_LOCK(window_nr));
1690
1691    at(lock_x, second_line_y);
1692    create_toggle(AWAR_LOCAL_GENE_LOCK(window_nr));
1693
1694    get_at_position(&cur_x, &cur_y);
1695    int dtype_x1 = cur_x;
1696
1697    // display type buttons:
1698
1699    button_length(4);
1700
1701    at(dtype_x1, first_line_y);
1702    help_text("gen_disp_radial.hlp");
1703    callback(GEN_set_display_style, (AW_CL)GEN_DISPLAY_STYLE_RADIAL);
1704    create_button("RADIAL_DISPLAY_TYPE", "#gen_radial.xpm", 0);
1705
1706    help_text("gen_disp_book.hlp");
1707    callback(GEN_set_display_style, (AW_CL)GEN_DISPLAY_STYLE_BOOK);
1708    create_button("BOOK_DISPLAY_TYPE", "#gen_book.xpm", 0);
1709
1710    get_at_position(&cur_x, &cur_y);
1711    int jump_x = cur_x;
1712
1713    at(dtype_x1, second_line_y);
1714    help_text("gen_disp_vertical.hlp");
1715    callback(GEN_set_display_style, (AW_CL)GEN_DISPLAY_STYLE_VERTICAL);
1716    create_button("VERTICAL_DISPLAY_TYPE", "#gen_vertical.xpm", 0);
1717
1718    // jump button:
1719
1720    button_length(0);
1721
1722    at(jump_x, first_line_y);
1723    help_text("gen_jump.hlp");
1724    callback(GEN_jump_cb, (AW_CL)true);
1725    create_button("Jump", "Jump");
1726
1727    // help buttons:
1728
1729    get_at_position(&cur_x, &cur_y);
1730    int help_x = cur_x;
1731
1732    at(help_x, first_line_y);
1733    help_text("help.hlp");
1734    callback(makeHelpCallback("gene_map.hlp"));
1735    create_button("HELP", "HELP", "H");
1736
1737    at(help_x, second_line_y);
1738    callback(AW_help_entry_pressed);
1739    create_button(0, "?");
1740
1741}
1742
1743// -end- of implementation of class GEN_map_window:.
1744
1745
Note: See TracBrowser for help on using the repository browser.