source: branches/stable/ARB_GDE/GDE.cxx

Last change on this file was 18159, checked in by westram, 5 years ago
  • full update from child 'fix' into 'trunk'
    • fix item name accessors (GBT_get_name + GBT_get_name_or_description)
    • add null2empty
  • adds: log:branches/fix@18140:18158
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1#include "GDE_extglob.h"
2#include "GDE_awars.h"
3
4#include <awt_sel_boxes.hxx>
5#include <awt_filter.hxx>
6
7#include <aw_msg.hxx>
8#include <aw_awar.hxx>
9#include <aw_file.hxx>
10#include <aw_root.hxx>
11#include <aw_awar_defs.hxx>
12#include <aw_select.hxx>
13
14#include <arb_str.h>
15
16#include <cmath>
17#include <awt_config_manager.hxx>
18
19// AISC_MKPT_PROMOTE:#ifndef GDE_MENU_H
20// AISC_MKPT_PROMOTE:#include "GDE_menu.h"
21// AISC_MKPT_PROMOTE:#endif
22
23adfiltercbstruct *agde_filter = NULp;
24
25Gmenu menu[GDEMAXMENU];
26int   num_menus = 0;
27
28static char GDEBLANK[] = "\0";
29
30#define SLIDERFIELDWIDTH 5      // width of numeric input fields with slider
31#define SLIDERWIDTH      200    // with of the slider itself
32
33#define AWAR_GDE_ALIGNMENT   AWAR_PREFIX_GDE_TEMP "/alignment"
34#define AWAR_GDE_FILTER_NAME AWAR_PREFIX_GDE_TEMP "/filter/name"
35
36struct gde_iteminfo {
37    GmenuItem *item;
38    int        idx;
39    gde_iteminfo(GmenuItem *item_, int idx_) : item(item_), idx(idx_) {}
40};
41
42static void GDE_showhelp_cb(UNFIXED, GmenuItem *gmenuitem) {
43    if (gmenuitem->help) {
44        AW_help_popup(NULp, gmenuitem->help);
45    }
46    else {
47        aw_message("Sorry - no help available (please report to devel@arb-home.de)");
48    }
49}
50
51static char *GDE_makeawarname_in(GmenuItem *gmenuitem, long i, const char *awar_root) {
52    char *gmenu_label     = GBS_string_2_key(gmenuitem->parent_menu->label);
53    char *gmenuitem_label = GBS_string_2_key(gmenuitem->label);
54    char *arg             = GBS_string_2_key(gmenuitem->arg[i].symbol);
55
56    char *name = GBS_global_string_copy("%s/%s/%s/%s", awar_root, gmenu_label, gmenuitem_label, arg);
57
58    free(gmenu_label);
59    free(gmenuitem_label);
60    free(arg);
61
62    return name;
63}
64
65char *GDE_makeawarname   (GmenuItem *gmenuitem, long i) { return GDE_makeawarname_in(gmenuitem, i, AWAR_PREFIX_GDE); }
66char *GDE_maketmpawarname(GmenuItem *gmenuitem, long i) { return GDE_makeawarname_in(gmenuitem, i, AWAR_PREFIX_GDE_TEMP); }
67
68static char *gde_filter_weights(GBDATA *gb_sai) {
69    char   *ali_name = GBT_get_default_alignment(GB_get_root(gb_sai));
70    GBDATA *gb_ali   = GB_entry(gb_sai, ali_name);
71    char   *result   = NULp;
72
73    if (gb_ali) {
74        GBDATA *gb_type = GB_entry(gb_ali, "_TYPE");
75        if (gb_type) {
76            const char *type = GB_read_char_pntr(gb_type);
77
78            if (GBS_string_matches(type, "PV?:*", GB_MIND_CASE)) {
79                result = GBS_global_string_copy("%s: %s", GBT_get_name_or_description(gb_sai), type);
80            }
81
82        }
83    }
84
85    free(ali_name);
86    return result;
87
88}
89
90static void refresh_weights_sellist_cb(AW_root*, AW_DB_selection *saisel) {
91    saisel->refresh();
92}
93
94static AW_window *GDE_create_filename_browser_window(AW_root *aw_root, const char *awar_prefix, const char *title) {
95    AW_window_simple *aws = new AW_window_simple;
96
97    {
98        char *wid = GBS_string_2_key(awar_prefix);
99        aws->init(aw_root, wid, title);
100        free(wid);
101    }
102    aws->load_xfig("sel_box.fig");
103
104    aws->at("close");
105    aws->callback(AW_POPDOWN);
106    aws->create_button("CLOSE", "CLOSE", "C");
107
108    AW_create_standard_fileselection(aws, awar_prefix);
109
110    return aws;
111}
112
113static void GDE_popup_filename_browser(AW_window *aw, gde_iteminfo *info, const char *title) {
114    GmenuItem *gmenuitem = info->item;
115    int        idx       = info->idx;
116    char      *base_awar = GDE_maketmpawarname(gmenuitem, idx);
117
118    static GB_HASH *popup_hash  = NULp;
119    if (!popup_hash) popup_hash = GBS_create_hash(20, GB_MIND_CASE);
120
121    AW_window *aw_browser = (AW_window*)GBS_read_hash(popup_hash, base_awar);
122    if (!aw_browser) {
123        aw_browser        = GDE_create_filename_browser_window(aw->get_root(), base_awar, title);
124        GBS_write_hash(popup_hash, base_awar, (long)aw_browser);
125    }
126    aw_browser->activate();
127    free(base_awar);
128}
129
130inline bool shall_store_in_config(const GmenuItemArg& itemarg) {
131    return itemarg.type != FILE_SELECTOR;
132}
133inline bool want_config_manager(GmenuItem *gmenuitem) {
134    for (int i=0; i<gmenuitem->numargs; i++) {
135        const GmenuItemArg& itemarg = gmenuitem->arg[i];
136        if (shall_store_in_config(itemarg)) return true;
137    }
138    return false;
139}
140static void setup_gde_config_def(AWT_config_definition& cdef, GmenuItem *gmenuitem) {
141    for (int i=0; i<gmenuitem->numargs; i++) {
142        const GmenuItemArg& itemarg = gmenuitem->arg[i];
143        if (shall_store_in_config(itemarg)) {
144            char *awar = GDE_makeawarname(gmenuitem, i);
145
146            gde_assert(awar);
147            gde_assert(itemarg.symbol);
148
149            if (awar) {
150                cdef.add(awar, itemarg.symbol);
151                free(awar);
152            }
153        }
154    }
155}
156
157static AW_window *GDE_menuitem_cb(AW_root *aw_root, GmenuItem *gmenuitem) {
158#define BUFSIZE 200
159    char bf[BUFSIZE+1];
160    IF_ASSERTION_USED(int printed =)
161        sprintf(bf, "GDE / %s / %s", gmenuitem->parent_menu->label, gmenuitem->label);
162
163    gde_assert(printed<=BUFSIZE);
164    char seqtype = gmenuitem->seqtype;
165
166    if (!gmenuitem->aws) {
167        AW_window_simple *aws = new AW_window_simple;
168        aws->init(aw_root, bf, bf);
169
170        switch (db_access.window_type) {
171            case GDE_WINDOWTYPE_DEFAULT: {
172                if (seqtype == '-') aws->load_xfig("gdeitem_simple.fig");
173                else                aws->load_xfig("gdeitem.fig");
174                break;
175            }
176            case GDE_WINDOWTYPE_EDIT4:
177                gde_assert(seqtype != '-');
178                aws->load_xfig("gde3item.fig");
179                break;
180        }
181
182        aws->button_length(10);
183        aws->at(10, 10);
184        aws->auto_space(0, 10);
185
186        aws->at("help");
187        aws->callback(makeWindowCallback(GDE_showhelp_cb, gmenuitem));
188        aws->create_button("GDE_HELP", "HELP", "H");
189
190        aws->at("start");
191        aws->callback(makeWindowCallback(GDE_startaction_cb, gmenuitem));
192        aws->create_button("GO", "GO", "O");
193
194        aws->at("cancel");
195        aws->callback(AW_POPDOWN);
196        aws->create_button("CLOSE", "CLOSE", "C");
197
198        if (want_config_manager(gmenuitem)) {
199            aws->at("config");
200            AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, aws->window_defaults_name, makeConfigSetupCallback(setup_gde_config_def, gmenuitem));
201        }
202
203        if (gmenuitem->numinputs>0) {
204            switch (db_access.window_type) {
205                case GDE_WINDOWTYPE_DEFAULT: {
206                    if (seqtype != '-') { // '-' means "skip sequence export"
207                        aws->at("which_alignment");
208                        const char *ali_filter = seqtype == 'A' ? "pro=:ami=" : (seqtype == 'N' ? "dna=:rna=" : "*=");
209                        awt_create_ALI_selection_list(db_access.gb_main, (AW_window *)aws, AWAR_GDE_ALIGNMENT, ali_filter);
210
211                        aws->at("which_species");
212                        aws->create_toggle_field(AWAR_GDE_SPECIES);
213                        aws->insert_toggle        ("all",    "a", 0);
214                        aws->insert_default_toggle("marked", "m", 1);
215                        aws->update_toggle_field();
216
217                        if (seqtype != 'N') {
218                            aws->at("stop_codon");
219                            aws->label("Cut stop-codon");
220                            aws->create_toggle(AWAR_GDE_CUTOFF_STOPCODON);
221                        }
222                    }
223                    break;
224                }
225                case GDE_WINDOWTYPE_EDIT4:
226                    aws->at("topk");      aws->create_toggle("gde/top_area_kons");
227                    aws->at("middlek");   aws->create_toggle("gde/middle_area_kons");
228                    aws->at("topr");      aws->create_toggle("gde/top_area_remark");
229                    aws->at("middler");   aws->create_toggle("gde/middle_area_remark");
230                    aws->at("top");       aws->create_toggle("gde/top_area");
231                    aws->at("topsai");    aws->create_toggle("gde/top_area_sai");
232                    aws->at("toph");      aws->create_toggle("gde/top_area_helix");
233                    aws->at("middle");    aws->create_toggle("gde/middle_area");
234                    aws->at("middlesai"); aws->create_toggle("gde/middle_area_sai");
235                    aws->at("middleh");   aws->create_toggle("gde/middle_area_helix");
236                    break;
237            }
238
239            if (seqtype != '-') {
240                aws->at("compression");
241                aws->create_option_menu(AWAR_GDE_COMPRESSION, true);
242                aws->insert_option        ("none",             "n", COMPRESS_NONE);
243                aws->insert_option        ("vertical gaps",    "v", COMPRESS_VERTICAL_GAPS);
244                aws->insert_default_option("columns w/o info", "i", COMPRESS_NONINFO_COLUMNS);
245                aws->insert_option        ("all gaps",         "g", COMPRESS_ALL);
246                aws->update_option_menu();
247
248                aws->button_length(12);
249                aws->at("filtername");
250                if (!agde_filter) { // create only one filter - used for all GDE calls
251                    agde_filter = awt_create_select_filter(aws->get_root(), db_access.gb_main, AWAR_GDE_FILTER_NAME);
252                }
253                aws->callback(makeCreateWindowCallback(awt_create_select_filter_win, agde_filter));
254                aws->create_button("SELECT_FILTER", AWAR_GDE_FILTER_NAME);
255            }
256
257            aws->at("paramsb");
258        }
259        else {
260            aws->at("paramsb");
261        }
262
263
264        int labellength = 1;
265        for (int i=0; i<gmenuitem->numargs; i++) {
266            if (!(gmenuitem->arg[i].label)) gmenuitem->arg[i].label = GDEBLANK;
267
268            const char *label    = gmenuitem->arg[i].label;
269            const char *linefeed = strchr(label, '\n');
270
271            int lablen;
272            while (linefeed) {
273                lablen = linefeed-label;
274                if (lablen>labellength) {
275                    labellength = lablen;
276                }
277                label    = linefeed+1;
278                linefeed = strchr(label, '\n');
279            }
280
281            lablen = strlen(label);
282            if (lablen>labellength) {
283                labellength = lablen;
284            }
285        }
286        aws->label_length(labellength);
287        aws->auto_space(0, 0);
288
289        for (int i=0; i<gmenuitem->numargs; i++) {
290            const GmenuItemArg& itemarg = gmenuitem->arg[i];
291
292            if (itemarg.type==SLIDER) {
293                char    *awarName = GDE_makeawarname(gmenuitem, i);
294                AW_awar *awar     = NULp;
295
296                if (int(itemarg.fvalue) == itemarg.fvalue &&
297                    int(itemarg.min) == itemarg.min &&
298                    int(itemarg.max) == itemarg.max)
299                {
300                    awar = aw_root->awar_int(awarName, (long)itemarg.fvalue, AW_ROOT_DEFAULT);
301                }
302                else {
303                    awar = aw_root->awar_float(awarName, itemarg.fvalue, AW_ROOT_DEFAULT);
304                }
305                awar->set_minmax(itemarg.min, itemarg.max);
306
307                aws->label(itemarg.label);
308                aws->sens_mask(itemarg.active_mask);
309                aws->create_input_field_with_scaler(awarName, SLIDERFIELDWIDTH, SLIDERWIDTH, AW_SCALER_LINEAR);
310                free(awarName);
311            }
312            else if (itemarg.type==CHOOSER) {
313                char    *defopt           = itemarg.choice[0].method;
314                char    *newawar          = GDE_makeawarname(gmenuitem, i);
315                AW_awar *curr_awar        = aw_root->awar_string(newawar, defopt, AW_ROOT_DEFAULT);
316                char    *curr_value       = curr_awar->read_string();
317                bool     curr_value_legal = false;
318
319                aws->label(itemarg.label);
320                aws->sens_mask(itemarg.active_mask);
321                if ((strcasecmp(itemarg.choice[0].label, "no") == 0) ||
322                    (strcasecmp(itemarg.choice[0].label, "yes") == 0))
323                {
324                    aws->create_toggle_field(newawar, 1);
325                }
326                else {
327                    aws->create_toggle_field(newawar);
328                }
329
330                for (long j=0; j<itemarg.numchoices; j++) {
331                    if (strcmp(itemarg.choice[j].method, curr_value) == 0) curr_value_legal = true;
332
333                    if (!j) {
334                        aws->insert_default_toggle(itemarg.choice[j].label, "1", itemarg.choice[j].method);
335                    }
336                    else {
337                        aws->insert_toggle(itemarg.choice[j].label, "1", itemarg.choice[j].method);
338                    }
339                }
340                if (!curr_value_legal) curr_awar->write_string(defopt); // if saved value no longer occurs in choice -> overwrite with default
341                free(curr_value);
342                aws->update_toggle_field();
343                free(newawar);
344            }
345            else if (itemarg.type==CHOICE_MENU) {
346                char    *defopt           = itemarg.choice[itemarg.ivalue].method;
347                char    *newawar          = GDE_makeawarname(gmenuitem, i);
348                AW_awar *curr_awar        = aw_root->awar_string(newawar, defopt, AW_ROOT_DEFAULT);
349                char    *curr_value       = curr_awar->read_string();
350                bool     curr_value_legal = false;
351
352                if (itemarg.label[0]) aws->label(itemarg.label);
353                aws->sens_mask(itemarg.active_mask);
354                aws->create_option_menu(newawar, true);
355
356                for (long j=0; j<itemarg.numchoices; j++) {
357                    if (strcmp(itemarg.choice[j].method, curr_value) == 0) curr_value_legal = true;
358                    aws->insert_option(itemarg.choice[j].label, "1", itemarg.choice[j].method);
359                }
360                if (!curr_value_legal) curr_awar->write_string(defopt); // if saved value no longer occurs in choice -> overwrite with default
361                free(curr_value);
362                aws->update_option_menu();
363                free(newawar);
364            }
365            else if (itemarg.type==TEXTFIELD) {
366                char *defopt  = itemarg.textvalue;
367                char *newawar = GDE_makeawarname(gmenuitem, i);
368                aw_root->awar_string(newawar, defopt, AW_ROOT_DEFAULT);
369                aws->label(itemarg.label);
370                aws->sens_mask(itemarg.active_mask);
371                aws->create_input_field(newawar, itemarg.textwidth);  // TEXTFIELDWIDTH
372                free(newawar);
373            }
374            else if (itemarg.type==FILE_SELECTOR) {
375                char *base_awar = GDE_maketmpawarname(gmenuitem, i);
376                char *name_awar = GBS_global_string_copy("%s/file_name", base_awar);
377
378                AW_create_fileselection_awars(aw_root, base_awar, "", itemarg.textvalue, "");
379
380                aws->label(itemarg.label);
381                aws->sens_mask(itemarg.active_mask);
382                aws->create_input_field(name_awar, 40);
383                aws->callback(makeWindowCallback(GDE_popup_filename_browser, new gde_iteminfo(gmenuitem, i), ARB_strdup(itemarg.label)));
384                aws->create_button("", "Browse");
385
386                free(name_awar);
387                free(base_awar);
388            }
389            else if (itemarg.type==CHOICE_TREE) {
390                char *defopt  = itemarg.textvalue;
391                char *newawar = GDE_makeawarname(gmenuitem, i);
392                aw_root->awar_string(newawar, defopt, AW_ROOT_DEFAULT);
393                aws->sens_mask(itemarg.active_mask);
394                if (itemarg.label[0]) aws->create_button(NULp, itemarg.label);
395                awt_create_TREE_selection_list(db_access.gb_main, aws, newawar, true);
396                free(newawar);
397            }
398            else if (itemarg.type==CHOICE_SAI) {
399                char *defopt  = itemarg.textvalue;
400                char *newawar = GDE_makeawarname(gmenuitem, i);
401                aw_root->awar_string(newawar, defopt, AW_ROOT_DEFAULT);
402                aws->sens_mask(itemarg.active_mask);
403                if (itemarg.label[0]) aws->create_button(NULp, itemarg.label);
404                awt_create_SAI_selection_list(db_access.gb_main, aws, newawar, true);
405                free(newawar);
406            }
407            else if (itemarg.type==CHOICE_WEIGHTS) {
408                char *defopt  = itemarg.textvalue;
409                char *newawar = GDE_makeawarname(gmenuitem, i);
410
411                aw_root->awar_string(newawar, defopt, AW_ROOT_DEFAULT);
412                aws->sens_mask(itemarg.active_mask);
413                if (itemarg.label[0]) aws->create_button(NULp, itemarg.label);
414                AW_DB_selection *saisel = awt_create_SAI_selection_list(db_access.gb_main, aws, newawar, true, makeSaiSelectionlistFilterCallback(gde_filter_weights));
415                free(newawar);
416                aw_root->awar(AWAR_GDE_ALIGNMENT)->add_callback(makeRootCallback(refresh_weights_sellist_cb, saisel));
417            }
418
419            aws->at_newline();
420        }
421        aws->at_newline();
422        aws->window_fit();
423
424        gmenuitem->aws = aws;
425    }
426    return gmenuitem->aws;
427#undef BUFSIZE
428}
429
430
431
432
433void GDE_load_menu(AW_window *awm, AW_active /*mask*/, const char *menulabel) {
434    // Load GDE menu items.
435    //
436    // If 'menulabel' == NULp -> load all menus
437    // Else                   -> load specified menu
438    //
439    // Always loads complete menu(s).
440
441    gde_assert(db_access.gb_main); // forgot to call GDE_init() ?
442
443    char hotkey[]      = "x";
444    bool topicInserted = false;
445
446    for (long nmenu = 0; nmenu<num_menus; nmenu++) {
447        {
448            const char *menuname = menu[nmenu].label;
449            if (menulabel) {
450                if (strcmp(menulabel, menuname)) {
451                    continue;
452                }
453            }
454            else {
455                hotkey[0] = menu[nmenu].meta;
456                awm->insert_sub_menu(menuname, hotkey, menu[nmenu].active_mask);
457            }
458        }
459
460        long num_items = menu[nmenu].numitems;
461        for (long nitem=0; nitem<num_items; nitem++) {
462            GmenuItem *menuitem = &menu[nmenu].item[nitem];
463            gde_assert(!menuitem->help || ARB_strBeginsWith(menuitem->help, "agde_"));
464            hotkey[0]           = menuitem->meta;
465
466            if (!menuitem->popup) {
467                menuitem->popup = new WindowCallback(AW_window::makeWindowPopper(makeCreateWindowCallback(GDE_menuitem_cb, menuitem)));
468            }
469            awm->insert_menu_topic(menuitem->label, menuitem->label, hotkey, menuitem->help, menuitem->active_mask, *menuitem->popup);
470            topicInserted = true;
471        }
472
473        if (!menulabel) {
474            awm->close_sub_menu();
475        }
476    }
477
478    if (!topicInserted && menulabel && strcmp(menulabel, "User") != 0) { // accepts empty 'User' menu; see ../GDEHELP/ARB_GDEmenus.source@User
479        fprintf(stderr, "GDE-Warning: Could not find any topics for menu '%s' \n", menulabel);
480        gde_assert(0); // nothing found -> fix
481    }
482}
483
484struct gde_database_access db_access = { NULp, NULp, GDE_WINDOWTYPE_DEFAULT, NULp};
485
486GB_ERROR GDE_init(AW_root *aw_root, AW_default aw_def, GBDATA *gb_main, GDE_get_sequences_cb get_sequences, GDE_format_alignment_cb format_ali, gde_window_type window_type) {
487    db_access.get_sequences = get_sequences;
488    db_access.format_ali    = format_ali;
489    db_access.window_type   = window_type;
490    db_access.gb_main       = gb_main;
491
492
493    switch (db_access.window_type) {
494        case GDE_WINDOWTYPE_EDIT4:
495            aw_root->awar_int("gde/top_area_kons",      1, aw_def);
496            aw_root->awar_int("gde/top_area_remark",    1, aw_def);
497            aw_root->awar_int("gde/middle_area_kons",   1, aw_def);
498            aw_root->awar_int("gde/middle_area_remark", 1, aw_def);
499            aw_root->awar_int("gde/top_area",           1, aw_def);
500            aw_root->awar_int("gde/top_area_sai",       1, aw_def);
501            aw_root->awar_int("gde/top_area_helix",     1, aw_def);
502            aw_root->awar_int("gde/middle_area",        1, aw_def);
503            aw_root->awar_int("gde/middle_area_sai",    1, aw_def);
504            aw_root->awar_int("gde/middle_area_helix",  1, aw_def);
505            aw_root->awar_int("gde/bottom_area",        1, aw_def);
506            aw_root->awar_int("gde/bottom_area_sai",    1, aw_def);
507            aw_root->awar_int("gde/bottom_area_helix",  1, aw_def);
508            break;
509        case GDE_WINDOWTYPE_DEFAULT:
510            break;
511    }
512
513    AW_awar *awar_defali = aw_root->awar_string(AWAR_DEFAULT_ALIGNMENT, "", db_access.gb_main);
514    aw_root->awar_string(AWAR_GDE_ALIGNMENT, "", aw_def)->map(awar_defali);
515
516    awt_create_filter_awars(aw_root, aw_def, AWAR_GDE_FILTER_NAME, AWAR_GDE_ALIGNMENT);
517
518    aw_root->awar_int(AWAR_GDE_CUTOFF_STOPCODON, 0, aw_def);
519    aw_root->awar_int(AWAR_GDE_SPECIES,          1, aw_def);
520
521    aw_root->awar_int(AWAR_GDE_COMPRESSION, COMPRESS_NONINFO_COLUMNS, aw_def);
522
523    return LoadMenus();
524}
525
Note: See TracBrowser for help on using the repository browser.