source: branches/stable/GENOM/GEN_map.cxx

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