source: branches/species/GENOM/GEN_map.cxx

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