source: tags/ms_r16q3/GENOM/GEN_map.cxx

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