source: tags/svn.1.5.4/GENOM/GEN_interface.cxx

Last change on this file was 8360, checked in by westram, 13 years ago
  • renamed menu separator functions
  • removed macro AWMIMT
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.3 KB
Line 
1// =============================================================  //
2//                                                                //
3//   File      : GEN_interface.cxx                                //
4//   Purpose   :                                                  //
5//                                                                //
6//   Coded by Ralf Westram (coder@reallysoft.de) in February 2001 //
7//   Institute of Microbiology (Technical University Munich)      //
8//   http://www.arb-home.de/                                      //
9//                                                                //
10// ============================================================== //
11
12#include "GEN_local.hxx"
13
14#include <db_scanner.hxx>
15#include <db_query.h>
16#include <dbui.h>
17#include <item_sel_list.h>
18#include <awt_sel_boxes.hxx>
19#include <aw_awar_defs.hxx>
20#include <aw_detach.hxx>
21#include <aw_msg.hxx>
22#include <aw_question.hxx>
23#include <arbdbt.h>
24#include <adGene.h>
25#include <Location.h>
26#include <arb_strarray.h>
27#include <arb_strbuf.h>
28
29using namespace std;
30
31// --------------------------------------------------------------------------------
32
33#define AWAR_GENE_DEST "tmp/gene/dest"
34
35// --------------------------------------------------------------------------------
36
37#if defined(WARN_TODO)
38#warning replace all occurrences of AD_F_ALL by AWM_ALL
39#endif
40
41#define AD_F_ALL AWM_ALL
42
43// --------------------------------------------------------------------------------
44
45static void GEN_select_gene(GBDATA* /* gb_main */, AW_root *aw_root, const char *item_name) {
46    char *organism  = strdup(item_name);
47    char *gene = strchr(organism, '/');
48
49    if (gene) {
50        *gene++ = 0;
51        aw_root->awar(AWAR_ORGANISM_NAME)->write_string(organism);
52        aw_root->awar(AWAR_GENE_NAME)->write_string(gene);
53    }
54    else if (!item_name[0]) { // accept empty input -> deselect gene/organism
55        aw_root->awar(AWAR_GENE_NAME)->write_string("");
56        aw_root->awar(AWAR_ORGANISM_NAME)->write_string("");
57    }
58    else {
59        aw_message(GBS_global_string("Illegal item_name '%s' in GEN_select_gene()", item_name));
60    }
61    free(organism);
62}
63
64static char *gen_get_gene_id(GBDATA * /* gb_main */, GBDATA *gb_gene) {
65    GBDATA *gb_species = GB_get_grandfather(gb_gene);
66    return GBS_global_string_copy("%s/%s", GBT_read_name(gb_species), GBT_read_name(gb_gene));
67}
68
69static GBDATA *gen_find_gene_by_id(GBDATA *gb_main, const char *id) {
70    char   *organism = strdup(id);
71    char   *gene     = strchr(organism, '/');
72    GBDATA *result   = 0;
73
74    if (gene) {
75        *gene++ = 0;
76        GBDATA *gb_organism = GEN_find_organism(gb_main, organism);
77        if (gb_organism) {
78            result = GEN_find_gene(gb_organism, gene);
79        }
80    }
81
82    free(organism);
83    return result;
84}
85
86
87GB_ERROR GEN_mark_organism_or_corresponding_organism(GBDATA *gb_species, int */*client_data*/) {
88    GB_ERROR error = 0;
89
90    if (GEN_is_pseudo_gene_species(gb_species)) {
91        GBDATA *gb_organism = GEN_find_origin_organism(gb_species, 0);
92        if (gb_organism) {
93            GB_write_flag(gb_organism, 1);
94        }
95        else {
96            error = GEN_organism_not_found(gb_species);
97        }
98    }
99    else if (GEN_is_organism(gb_species)) {
100        GB_write_flag(gb_species, 1);
101    }
102
103    return error;
104}
105
106static char *old_species_marks = 0; // configuration storing marked species
107
108inline void gen_restore_old_species_marks(GBDATA *gb_main) {
109    if (old_species_marks) {
110        GBT_restore_marked_species(gb_main, old_species_marks);
111        freenull(old_species_marks);
112    }
113}
114
115static GBDATA *GEN_get_first_gene_data(GBDATA *gb_main, AW_root *aw_root, QUERY_RANGE range) {
116    GBDATA   *gb_organism = 0;
117    GB_ERROR  error      = 0;
118
119    gen_restore_old_species_marks(gb_main);
120
121    switch (range) {
122        case QUERY_CURRENT_ITEM: {
123            char *species_name = aw_root->awar(AWAR_ORGANISM_NAME)->read_string();
124            gb_organism         = GEN_find_organism(gb_main, species_name);
125            free(species_name);
126            break;
127        }
128        case QUERY_MARKED_ITEMS: {
129            gb_organism = GEN_first_marked_organism(gb_main);
130            GBDATA *gb_pseudo   = GEN_first_marked_pseudo_species(gb_main);
131
132            if (gb_pseudo) {    // there are marked pseudo-species..
133                old_species_marks = GBT_store_marked_species(gb_main, 1); // store and unmark marked species
134
135                error                   = GBT_with_stored_species(gb_main, old_species_marks, GEN_mark_organism_or_corresponding_organism, 0); // mark organisms related with stored
136                if (!error) gb_organism = GEN_first_marked_organism(gb_main);
137            }
138
139            break;
140        }
141        case QUERY_ALL_ITEMS: {
142            gb_organism = GEN_first_organism(gb_main);
143            break;
144        }
145        default: {
146            gen_assert(0);
147            break;
148        }
149    }
150
151    if (error) GB_export_error(error);
152    return gb_organism ? GEN_expect_gene_data(gb_organism) : 0;
153}
154
155static GBDATA *GEN_get_next_gene_data(GBDATA *gb_gene_data, QUERY_RANGE range) {
156    GBDATA *gb_organism = 0;
157    switch (range) {
158        case QUERY_CURRENT_ITEM: {
159            break;
160        }
161        case QUERY_MARKED_ITEMS: {
162            GBDATA *gb_last_organism = GB_get_father(gb_gene_data);
163            gb_organism              = GEN_next_marked_organism(gb_last_organism);
164
165            if (!gb_organism) gen_restore_old_species_marks(GB_get_root(gb_last_organism)); // got all -> clean up
166
167            break;
168        }
169        case QUERY_ALL_ITEMS: {
170            GBDATA *gb_last_organism = GB_get_father(gb_gene_data);
171            gb_organism              = GEN_next_organism(gb_last_organism);
172            break;
173        }
174        default: {
175            gen_assert(0);
176            break;
177        }
178    }
179
180    return gb_organism ? GEN_expect_gene_data(gb_organism) : 0;
181}
182
183static GBDATA *GEN_get_current_gene(GBDATA *gb_main, AW_root *aw_root) {
184    GBDATA *gb_species = GEN_get_current_organism(gb_main, aw_root);
185    GBDATA *gb_gene    = 0;
186
187    if (gb_species) {
188        char *gene_name = aw_root->awar(AWAR_GENE_NAME)->read_string();
189        gb_gene         = GEN_find_gene(gb_species, gene_name);
190        free(gene_name);
191    }
192
193    return gb_gene;
194}
195
196static GBDATA *first_gene_in_range(GBDATA *gb_gene_data, QUERY_RANGE range) {
197    GBDATA *gb_first = NULL;
198    switch (range) {
199        case QUERY_ALL_ITEMS:    gb_first = GEN_first_gene_rel_gene_data(gb_gene_data); break;
200        case QUERY_MARKED_ITEMS: gb_first = GB_first_marked(gb_gene_data, "gene"); break;
201        case QUERY_CURRENT_ITEM: gb_first = GEN_get_current_gene(GB_get_root(gb_gene_data), AW_root::SINGLETON); break;
202    }
203    return gb_first;
204}
205static GBDATA *next_gene_in_range(GBDATA *gb_prev, QUERY_RANGE range) {
206    GBDATA *gb_next = NULL;
207    switch (range) {
208        case QUERY_ALL_ITEMS:    gb_next = GEN_next_gene(gb_prev); break;
209        case QUERY_MARKED_ITEMS: gb_next = GEN_next_marked_gene(gb_prev); break;
210        case QUERY_CURRENT_ITEM: gb_next = NULL; break;
211    }
212    return gb_next;
213}
214
215#if defined(WARN_TODO)
216#warning move GEN_item_selector to SL/ITEMS
217#endif
218
219static struct MutableItemSelector GEN_item_selector = {
220    QUERY_ITEM_GENES,
221    GEN_select_gene,
222    gen_get_gene_id,
223    gen_find_gene_by_id,
224    (AW_CB)gene_field_selection_list_update_cb,
225    -1, // unknown
226    CHANGE_KEY_PATH_GENES,
227    "gene",
228    "genes",
229    "name",
230    GEN_get_first_gene_data,
231    GEN_get_next_gene_data,
232    first_gene_in_range,
233    next_gene_in_range,
234    GEN_get_current_gene,
235    &ORGANISM_get_selector(), GB_get_grandfather,
236};
237
238ItemSelector& GEN_get_selector() { return GEN_item_selector; }
239
240static void GEN_species_name_changed_cb(AW_root *awr, AW_CL cl_gb_main) {
241    char           *species_name = awr->awar(AWAR_SPECIES_NAME)->read_string();
242    GBDATA         *gb_main      = (GBDATA*)cl_gb_main;
243    GB_transaction  ta(gb_main);
244    GBDATA         *gb_species   = GBT_find_species(gb_main, species_name);
245
246    if (gb_species) {
247        if (GEN_is_pseudo_gene_species(gb_species)) {
248            awr->awar(AWAR_ORGANISM_NAME)->write_string(GEN_origin_organism(gb_species));
249            awr->awar(AWAR_GENE_NAME)->write_string(GEN_origin_gene(gb_species));
250        }
251        else {
252            awr->awar(AWAR_ORGANISM_NAME)->write_string(species_name);
253        }
254    }
255    free(species_name);
256}
257
258static void auto_select_pseudo_species(AW_root *awr, GBDATA *gb_main, const char *organism, const char *gene) {
259    GB_transaction  ta(gb_main);
260    GBDATA         *gb_pseudo = GEN_find_pseudo_species(gb_main, organism, gene, 0); // search for pseudo species..
261
262    awr->awar(AWAR_SPECIES_NAME)->write_string(gb_pseudo
263                                               ? GBT_read_name(gb_pseudo) // .. if found select
264                                               : organism);               // otherwise select organism
265}
266
267static void GEN_update_GENE_CONTENT(GBDATA *gb_main, AW_root *awr) {
268    GB_transaction  dummy(gb_main);
269    GBDATA         *gb_gene      = GEN_get_current_gene(gb_main, awr);
270    bool            clear        = true;
271    AW_awar        *awar_content = awr->awar(AWAR_GENE_CONTENT);
272
273    if (gb_gene) {
274        // ignore complement here (to highlight gene in ARB_EDIT4);
275        // separate multiple parts by \n
276        char *gene_content = GBT_read_gene_sequence(gb_gene, false, '\n');
277        if (gene_content) {
278            awar_content->write_string(gene_content);
279            clear = false;
280            free(gene_content);
281        }
282        else {
283            awar_content->write_string(GB_await_error());
284        }
285    }
286    else {
287        char      *gene_name  = awr->awar(AWAR_GENE_NAME)->read_string();
288        const int  prefix_len = 10;
289
290        if (strncmp(gene_name, "intergene_", prefix_len) == 0) { // special case (non-gene result from gene pt server)
291            char *start_pos_ptr = gene_name+prefix_len;
292            char *end_pos_ptr   = strchr(start_pos_ptr, '_');
293
294            gen_assert(end_pos_ptr);
295            if (end_pos_ptr) {
296                *end_pos_ptr++ = 0;
297                long start_pos = atol(start_pos_ptr);
298                long end_pos   = atol(end_pos_ptr);
299
300                gen_assert(end_pos >= start_pos);
301
302                GBDATA *gb_organism = GEN_get_current_organism(gb_main, awr);
303                if (gb_organism) {
304                    GBDATA     *gb_seq   = GBT_read_sequence(gb_organism, GENOM_ALIGNMENT);
305                    const char *seq_data = GB_read_char_pntr(gb_seq);
306
307                    long  len    = end_pos-start_pos+1;
308                    char *buffer = (char*)malloc(len+1);
309                    memcpy(buffer, seq_data+start_pos, len);
310                    buffer[len]  = 0;
311
312                    awar_content->write_string(buffer);
313                    clear = false;
314
315                    free(buffer);
316                }
317            }
318        }
319        free(gene_name);
320    }
321
322    if (clear) {
323        awar_content->write_string(""); // if we did not detect any gene sequence -> clear
324    }
325}
326
327static void GEN_update_combined_cb(AW_root *awr, AW_CL cl_gb_main) {
328    char       *organism     = awr->awar(AWAR_ORGANISM_NAME)->read_string();
329    char       *gene         = awr->awar(AWAR_GENE_NAME)->read_string();
330    char       *old_combined = awr->awar(AWAR_COMBINED_GENE_NAME)->read_string();
331    const char *combined     = GBS_global_string("%s/%s", organism, gene);
332
333    if (strcmp(combined, old_combined) != 0) {
334        GBDATA *gb_main = (GBDATA*)cl_gb_main;
335        awr->awar(AWAR_COMBINED_GENE_NAME)->write_string(combined);
336        auto_select_pseudo_species(awr, gb_main, organism, gene);
337        GEN_update_GENE_CONTENT(gb_main, awr);
338    }
339
340    free(old_combined);
341    free(gene);
342    free(organism);
343}
344
345void GEN_create_awars(AW_root *aw_root, AW_default aw_def, GBDATA *gb_main) {
346    aw_root->awar_string(AWAR_COMBINED_GENE_NAME, "", gb_main);
347    aw_root->awar_string(AWAR_GENE_CONTENT, "", gb_main);
348
349    aw_root->awar_string(AWAR_GENE_NAME,     "", gb_main)->add_callback(GEN_update_combined_cb,      (AW_CL)gb_main);
350    aw_root->awar_string(AWAR_ORGANISM_NAME, "", gb_main)->add_callback(GEN_update_combined_cb,      (AW_CL)gb_main);
351    aw_root->awar_string(AWAR_SPECIES_NAME,  "", gb_main)->add_callback(GEN_species_name_changed_cb, (AW_CL)gb_main);
352
353    aw_root->awar_string(AWAR_GENE_DEST, "", aw_def);
354   
355    aw_root->awar_string(AWAR_GENE_EXTRACT_ALI, "ali_gene_",    aw_def);
356}
357
358GBDATA *GEN_get_current_organism(GBDATA *gb_main, AW_root *aw_root) {
359    char   *species_name = aw_root->awar(AWAR_ORGANISM_NAME)->read_string();
360    GBDATA *gb_species   = GBT_find_species(gb_main, species_name);
361    free(species_name);
362    return gb_species;
363}
364
365GBDATA* GEN_get_current_gene_data(GBDATA *gb_main, AW_root *aw_root) {
366    GBDATA *gb_species      = GEN_get_current_organism(gb_main, aw_root);
367    GBDATA *gb_gene_data    = 0;
368
369    if (gb_species) gb_gene_data = GEN_expect_gene_data(gb_species);
370
371    return gb_gene_data;
372}
373
374static QUERY::DbQuery *GLOBAL_gene_query      = 0;
375
376static void gene_rename_cb(AW_window *aww, AW_CL cl_gb_main) {
377    AW_root *aw_root = aww->get_root();
378    char    *source  = aw_root->awar(AWAR_GENE_NAME)->read_string();
379    char    *dest    = aw_root->awar(AWAR_GENE_DEST)->read_string();
380
381    if (strcmp(source, dest) != 0) {
382        GBDATA   *gb_main = (GBDATA*)cl_gb_main;
383        GB_ERROR  error   = GB_begin_transaction(gb_main);
384
385        if (!error) {
386            GBDATA *gb_gene_data = GEN_get_current_gene_data(gb_main, aww->get_root());
387
388            if (!gb_gene_data) error = "Please select a species";
389            else {
390                GBDATA *gb_source = GEN_find_gene_rel_gene_data(gb_gene_data, source);
391                GBDATA *gb_dest   = GEN_find_gene_rel_gene_data(gb_gene_data, dest);
392
393                if (!gb_source) error   = "Please select a gene first";
394                else if (gb_dest) error = GB_export_errorf("Gene '%s' already exists", dest);
395                else {
396                    GBDATA *gb_name = GB_search(gb_source, "name", GB_STRING);
397
398                    if (!gb_name) error = GB_await_error();
399                    else {
400                        error = GB_write_string(gb_name, dest);
401                        if (!error) aww->get_root()->awar(AWAR_GENE_NAME)->write_string(dest);
402                    }
403                }
404            }
405        }
406
407        error = GB_end_transaction(gb_main, error);
408        aww->hide_or_notify(error);
409    }
410
411    free(source);
412    free(dest);
413}
414
415static AW_window *create_gene_rename_window(AW_root *root, AW_CL cl_gb_main) {
416    AW_window_simple *aws = new AW_window_simple;
417    aws->init(root, "RENAME_GENE", "GENE RENAME");
418    aws->load_xfig("ad_al_si.fig");
419
420    aws->callback((AW_CB0)AW_POPDOWN);
421    aws->at("close");
422    aws->create_button("CLOSE", "CLOSE", "C");
423
424    aws->at("label");
425    aws->create_autosize_button(0, "Please enter the new name\nof the gene");
426
427    aws->at("input");
428    aws->create_input_field(AWAR_GENE_DEST, 15);
429    aws->at("ok");
430    aws->callback(gene_rename_cb, cl_gb_main);
431    aws->create_button("GO", "GO", "G");
432
433    return (AW_window *)aws;
434}
435
436static void gene_copy_cb(AW_window *aww, AW_CL cl_gb_main) {
437    char     *source  = aww->get_root()->awar(AWAR_GENE_NAME)->read_string();
438    char     *dest    = aww->get_root()->awar(AWAR_GENE_DEST)->read_string();
439    GBDATA   *gb_main = (GBDATA*)cl_gb_main;
440    GB_ERROR  error   = GB_begin_transaction(gb_main);
441
442    if (!error) {
443        GBDATA *gb_gene_data = GEN_get_current_gene_data(gb_main, aww->get_root());
444
445        if (!gb_gene_data) {
446            error = "Please select a species first.";
447        }
448        else {
449            GBDATA *gb_source = GEN_find_gene_rel_gene_data(gb_gene_data, source);
450            GBDATA *gb_dest   = GEN_find_gene_rel_gene_data(gb_gene_data, dest);
451
452            if (!gb_source) error   = "Please select a gene";
453            else if (gb_dest) error = GB_export_errorf("Gene '%s' already exists", dest);
454            else {
455                gb_dest             = GB_create_container(gb_gene_data, "gene");
456                if (!gb_dest) error = GB_await_error();
457                else error          = GB_copy(gb_dest, gb_source);
458
459                if (!error) error = GBT_write_string(gb_dest, "name", dest);
460                if (!error) aww->get_root()->awar(AWAR_GENE_NAME)->write_string(dest);
461            }
462        }
463    }
464
465    error = GB_end_transaction(gb_main, error);
466    aww->hide_or_notify(error);
467
468    free(source);
469    free(dest);
470}
471
472static AW_window *create_gene_copy_window(AW_root *root, AW_CL cl_gb_main) {
473    AW_window_simple *aws = new AW_window_simple;
474    aws->init(root, "COPY_GENE", "GENE COPY");
475    aws->load_xfig("ad_al_si.fig");
476
477    aws->callback((AW_CB0)AW_POPDOWN);
478    aws->at("close");
479    aws->create_button("CLOSE", "CLOSE", "C");
480
481    aws->at("label");
482    aws->create_autosize_button(0, "Please enter the name\nof the new gene");
483
484    aws->at("input");
485    aws->create_input_field(AWAR_GENE_DEST, 15);
486
487    aws->at("ok");
488    aws->callback(gene_copy_cb, cl_gb_main);
489    aws->create_button("GO", "GO", "G");
490
491    return aws;
492}
493
494
495// -----------------------
496//      LocationEditor
497
498const int NAME_WIDTH = 33;
499const int POS_WIDTH  = NAME_WIDTH;
500const int CER_WIDTH  = POS_WIDTH/2;
501const int LOC_WIDTH  = 53;
502
503#define GLE_POS1       "pos1"
504#define GLE_POS2       "pos2"
505#define GLE_CERT1      "cert1"
506#define GLE_CERT2      "cert2"
507#define GLE_COMPLEMENT "complement"
508#define GLE_JOINABLE   "joinable"
509#define GLE_READABLE   "location"
510#define GLE_STATUS     "status"
511
512class LocationEditor : virtual Noncopyable { // GLE
513    typedef void (*PosChanged_cb)(AW_root *aw_root, LocationEditor *loced);
514
515    char          *tag;
516    AW_root       *aw_root;
517    GBDATA        *gb_main;
518    char          *status;
519    GEN_position  *pos;
520    PosChanged_cb  pos_changed_cb;
521
522    void createAwars();
523
524    void createInputField(AW_window *aws, const char *at, const char *aname, int width) const {
525        aws->at(at);
526        aws->create_input_field(loc_awar_name(aname), width);
527    }
528
529public:
530    LocationEditor(AW_root *aw_root_, GBDATA *gb_main_, const char *tag_)
531        : tag(strdup(tag_)),
532          aw_root(aw_root_),
533          gb_main(gb_main_), 
534          status(NULL),
535          pos(NULL),
536          pos_changed_cb(NULL)
537    {
538        createAwars();
539        set_status(NULL);
540    }
541    ~LocationEditor() {
542        free(tag);
543        free(status);
544        GEN_free_position(pos);
545    }
546
547    GBDATA *get_gb_main() const { return gb_main; }
548
549    void add_pos_changed_cb(PosChanged_cb cb) { pos_changed_cb = cb; }
550
551    const GEN_position *get_pos() const { return pos; }
552    void set_pos(GEN_position*& pos_) {
553        GEN_free_position(pos);
554        pos  = pos_;
555        pos_ = NULL; // take ownership
556        set_status(status);
557
558        if (pos && pos_changed_cb) {
559            pos_changed_cb(aw_root, this);
560        }
561    }
562    void set_status(const char *status_) {
563        if (status != status) freedup(status, status_);
564        loc_awar(GLE_STATUS)->write_string(status ? status : (pos ? "Ok" : "No data"));
565    }
566
567    const char *loc_awar_name(const char *aname) const {
568        const int   BUFSIZE = 100;
569        static char buf[BUFSIZE];
570
571        IF_DEBUG(int printed =) sprintf(buf, "tmp/loc/%s/%s", tag, aname);
572        gen_assert(printed<BUFSIZE);
573
574        return buf;
575    }
576    AW_awar *loc_awar(const char *aname) const { return aw_root->awar(loc_awar_name(aname)); }
577    const char *awar_charp_value(const char *aname) const { return loc_awar(aname)->read_char_pntr(); }
578
579    void createEditFields(AW_window *aws);
580   
581    GEN_position *create_GEN_position_from_fields(GB_ERROR& error);
582    void revcomp() {
583        loc_awar(GLE_READABLE)->write_string(GBS_global_string("complement(%s)", awar_charp_value(GLE_READABLE)));
584    }
585};
586
587inline const char *elemOr(ConstStrArray& a, size_t i, const char *Default) {
588    return i<a.size() ? a[i] : Default;
589}
590inline char elemOr(const char *a, size_t len, size_t i, char Default) {
591    return i<len ? a[i] : Default;
592}
593
594GEN_position *LocationEditor::create_GEN_position_from_fields(GB_ERROR& error) {
595    const char *ipos1  = awar_charp_value(GLE_POS1);
596    const char *ipos2  = awar_charp_value(GLE_POS2);
597    const char *icert1 = awar_charp_value(GLE_CERT1);
598    const char *icert2 = awar_charp_value(GLE_CERT2);
599    const char *icomp  = awar_charp_value(GLE_COMPLEMENT);
600
601    const char *sep = ",; ";
602
603    ConstStrArray pos1, pos2;
604    GBT_split_string(pos1, ipos1, sep, true);
605    GBT_split_string(pos2, ipos2, sep, true);
606
607    size_t clen1 = strlen(icert1);
608    size_t clen2 = strlen(icert2);
609    size_t clen  = strlen(icomp);
610
611    size_t max_size = pos1.size();
612    bool   joinable = loc_awar(GLE_JOINABLE)->read_int();
613
614    GEN_position *gp = NULL;
615    if (max_size>0) {
616        gp = GEN_new_position(max_size, joinable);
617        GEN_use_uncertainties(gp);
618
619        for (size_t i = 0; i<max_size; ++i) {
620            const char *p1c = elemOr(pos1, i, "1");
621            size_t      p1  = atoi(p1c);
622            size_t      p2  = atoi(elemOr(pos2, i, p1c));
623
624            char c  = elemOr(icomp,  clen,  i, '0');
625            char c1 = elemOr(icert1, clen1, i, '=');
626            char c2 = elemOr(icert2, clen2, i, '=');
627
628            gen_assert(c1 && c2);
629
630            gp->start_pos[i]       = p1;
631            gp->stop_pos[i]        = p2;
632            gp->complement[i]      = !!(c-'0');
633            gp->start_uncertain[i] = c1;
634            gp->stop_uncertain[i]  = c2;
635        }
636    }
637    else {
638        error = "No data";
639    }
640
641    return gp;
642}
643
644static int loc_update_running = 0;
645
646inline GB_ERROR update_location_from_GEN_position(LocationEditor *loced, const GEN_position *gp) {
647    GB_ERROR error = NULL;
648    if (gp) {
649        try {
650            LocationPtr loc = to_Location(gp);
651            loced->loc_awar(GLE_READABLE)->write_string(loc->as_string().c_str());
652        }
653        catch (const char *& err) { error = GBS_global_string("%s", err); }
654        catch (string& err) { error = GBS_global_string("%s", err.c_str()); }
655        catch (...) { gen_assert(0); }
656    }
657    return error;
658}
659
660
661static void GLE_update_from_detailFields(AW_root *, AW_CL cl_loced) {
662    // update location according to other fields
663    if (!loc_update_running) {
664        loc_update_running++;
665
666        GB_ERROR        error = NULL;
667        LocationEditor *loced = (LocationEditor*)cl_loced;
668        GEN_position   *gp    = loced->create_GEN_position_from_fields(error);
669       
670        if (!error) {
671            error = update_location_from_GEN_position(loced, gp);
672        }
673
674        loced->set_pos(gp);
675        loced->set_status(error);
676
677        loc_update_running--;
678    }
679}
680
681
682static SmartCharPtr sizetarray2string(const size_t *array, int size) {
683    GBS_strstruct out(size*5);
684    for (int i = 0; i<size; ++i) {
685        out.putlong(array[i]);
686        out.put(' ');
687    }
688    out.cut_tail(1);
689    return out.release();
690}
691inline SmartCharPtr dupSizedPart(const unsigned char *in, int size) {
692    const char *in2 = reinterpret_cast<const char*>(in);
693    return GB_strpartdup(in2, in2+size-1);
694}
695inline SmartCharPtr dupComplement(const unsigned char *in, int size) {
696    char *dup = (char*)malloc(size+1);
697    for (int i = 0; i<size; ++i) {
698        dup[i] = in[i] ? '1' : '0';
699    }
700    dup[size] = 0;
701    return dup;
702}
703
704static void GLE_update_from_location(AW_root *, AW_CL cl_loced) {
705    // update other fields according to location
706    if (!loc_update_running) {
707        loc_update_running++;
708
709        GB_ERROR        error  = NULL;
710        LocationEditor *loced  = (LocationEditor*)cl_loced;
711        const char     *locstr = loced->awar_charp_value(GLE_READABLE);
712        GEN_position   *gp     = NULL;
713
714        try {
715            LocationPtr loc = parseLocation(locstr);
716            gp              = loc->create_GEN_position();
717        }
718        catch (const char *& err) { error = GBS_global_string("%s", err); }
719        catch (string& err) { error = GBS_global_string("%s", err.c_str()); }
720        catch (...) { gen_assert(0); }
721
722        if (!error) {
723            loced->loc_awar(GLE_POS1)->write_string(&*sizetarray2string(gp->start_pos, gp->parts));
724            loced->loc_awar(GLE_POS2)->write_string(&*sizetarray2string(gp->stop_pos, gp->parts));
725
726            loced->loc_awar(GLE_CERT1)->write_string(&*dupSizedPart(gp->start_uncertain, gp->parts));
727            loced->loc_awar(GLE_CERT2)->write_string(&*dupSizedPart(gp->stop_uncertain, gp->parts));
728            loced->loc_awar(GLE_COMPLEMENT)->write_string(&*dupComplement(gp->complement, gp->parts));
729
730            loced->loc_awar(GLE_JOINABLE)->write_int(gp->parts>1 ? gp->joinable : 1);
731        }
732
733        loced->set_pos(gp);
734        loced->set_status(error);
735
736        loc_update_running--;
737    }
738}
739
740static void GLE_revcomp_cb(AW_window*, AW_CL cl_loced) {
741    LocationEditor *loced  = (LocationEditor*)cl_loced;
742    loced->revcomp();
743}
744
745void LocationEditor::createAwars() {
746    aw_root->awar_string(loc_awar_name(GLE_POS1),       "", gb_main)->add_callback(GLE_update_from_detailFields,      (AW_CL)this);
747    aw_root->awar_string(loc_awar_name(GLE_POS2),       "", gb_main)->add_callback(GLE_update_from_detailFields,      (AW_CL)this);
748    aw_root->awar_string(loc_awar_name(GLE_CERT1),      "", gb_main)->add_callback(GLE_update_from_detailFields,      (AW_CL)this);
749    aw_root->awar_string(loc_awar_name(GLE_CERT2),      "", gb_main)->add_callback(GLE_update_from_detailFields,      (AW_CL)this);
750    aw_root->awar_string(loc_awar_name(GLE_COMPLEMENT), "", gb_main)->add_callback(GLE_update_from_detailFields,      (AW_CL)this);
751    aw_root->awar_int   (loc_awar_name(GLE_JOINABLE),    1, gb_main)->add_callback(GLE_update_from_detailFields,      (AW_CL)this);
752    aw_root->awar_string(loc_awar_name(GLE_READABLE),   "", gb_main)->add_callback(GLE_update_from_location, (AW_CL)this);
753    aw_root->awar_string(loc_awar_name(GLE_STATUS),     "", gb_main);
754}
755
756void LocationEditor::createEditFields(AW_window *aws) {
757    createInputField(aws, "pos1",   GLE_POS1,       POS_WIDTH);
758    createInputField(aws, "cert1",  GLE_CERT1,      CER_WIDTH);
759    createInputField(aws, "pos2",   GLE_POS2,       POS_WIDTH);
760    createInputField(aws, "cert2",  GLE_CERT2,      CER_WIDTH);
761    createInputField(aws, "comp",   GLE_COMPLEMENT, CER_WIDTH);
762    createInputField(aws, "loc",    GLE_READABLE,   LOC_WIDTH);
763    createInputField(aws, "status", GLE_STATUS,     LOC_WIDTH);
764
765    aws->at("rev");
766    aws->callback(GLE_revcomp_cb, (AW_CL)this);
767    aws->button_length(8);
768    aws->create_button("REV", "RevComp");
769   
770    aws->at("join");
771    aws->create_toggle(loc_awar_name(GLE_JOINABLE));
772}
773
774static void gene_changed_cb(AW_root *aw_root, AW_CL cl_loced) {
775    LocationEditor *loced   = (LocationEditor*)cl_loced;
776    GBDATA         *gb_gene = GEN_get_current_gene(loced->get_gb_main(), aw_root);
777    GEN_position   *pos     = gb_gene ? GEN_read_position(gb_gene) : NULL;
778
779    GB_ERROR error = NULL;
780    if (pos) {
781        GEN_use_uncertainties(pos);
782        error = update_location_from_GEN_position(loced, pos);
783    }
784    loced->set_pos(pos);
785    loced->set_status(error);
786}
787
788static void boundloc_changed_cb(AW_root *aw_root, LocationEditor *loced) {
789    GBDATA*             gb_main = loced->get_gb_main();
790    const GEN_position *pos     = loced->get_pos();
791    gen_assert(pos);
792
793    GB_push_transaction(gb_main);
794    GBDATA   *gb_gene = GEN_get_current_gene(gb_main, aw_root);
795    GB_ERROR  error;
796    if (gb_gene) {
797        error = GEN_write_position(gb_gene, pos);
798    }
799    else {
800        error = "That had no effect (no gene is selected)";
801    }
802    GB_end_transaction_show_error(gb_main, error, aw_message);
803
804    if (error) {
805        gene_changed_cb(aw_root, (AW_CL)loced);
806    }
807}
808
809static void gene_create_cb(AW_window *aww, AW_CL cl_gb_main, AW_CL cl_loced) {
810    GBDATA   *gb_main = (GBDATA*)cl_gb_main;
811    GB_ERROR  error   = GB_begin_transaction(gb_main);
812
813    if (!error) {
814        AW_root *aw_root      = aww->get_root();
815        GBDATA  *gb_gene_data = GEN_get_current_gene_data(gb_main, aw_root);
816
817        if (!gb_gene_data) error = "Please select an organism";
818        else {
819            char    *dest    = aw_root->awar(AWAR_GENE_DEST)->read_string();
820            GBDATA  *gb_dest = GEN_find_gene_rel_gene_data(gb_gene_data, dest);
821
822            if (gb_dest) error = GBS_global_string("Gene '%s' already exists", dest);
823            else {
824                LocationEditor     *loced = (LocationEditor*)cl_loced;
825                const GEN_position *pos   = loced->get_pos();
826
827                if (!pos) error = "Won't create a gene with invalid position";
828                else  {
829                    gb_dest             = GEN_find_or_create_gene_rel_gene_data(gb_gene_data, dest);
830                    if (!gb_dest) error = GB_await_error();
831                    else error          = GEN_write_position(gb_dest, pos);
832
833                    if (!error) {
834                        aw_root->awar(AWAR_GENE_NAME)->write_string(dest);
835                        aww->hide();
836                    }
837                }
838            }
839
840            free(dest);
841        }
842    }
843    GB_end_transaction_show_error(gb_main, error, aw_message);
844
845    gen_assert(!GB_have_error());
846}
847
848static AW_window *get_gene_create_or_locationEdit_window(AW_root *root, bool createGene, GBDATA *gb_main) {
849    static AW_window_simple *awa[2] = { NULL, NULL};
850    static LocationEditor   *le[2] = { NULL, NULL};
851
852    AW_window_simple*& aws   = awa[createGene];
853    LocationEditor*&   loced = le[createGene];
854
855    if (!aws) {
856        gen_assert(gb_main);
857
858        aws   = new AW_window_simple;
859        loced = new LocationEditor(root, gb_main, createGene ? "create" : "edit");
860
861        if (createGene) aws->init(root, "CREATE_GENE",   "GENE CREATE");
862        else            aws->init(root, "EDIT_LOCATION", "EDIT LOCATION");
863
864        aws->load_xfig("ad_gen_create.fig");
865
866        aws->callback((AW_CB0)AW_POPDOWN);
867        aws->at("close");
868        aws->create_button("CLOSE", "Close", "C");
869
870        aws->at("help");
871        aws->callback(AW_POPUP_HELP, (AW_CL)"gen_create.hlp");
872        aws->create_button("HELP", "Help", "H");
873
874        aws->button_length(NAME_WIDTH);
875       
876        aws->at("organism");
877        aws->create_button(NULL, AWAR_ORGANISM_NAME);
878
879        aws->at("gene");
880        if (createGene) {
881            aws->create_input_field(AWAR_GENE_DEST, NAME_WIDTH);
882        }
883        else {
884            aws->create_button(NULL, AWAR_GENE_NAME);
885            AW_awar *awar_cgene = aws->get_root()->awar(AWAR_COMBINED_GENE_NAME);
886            awar_cgene->add_callback(gene_changed_cb, (AW_CL)loced);
887            awar_cgene->touch();
888
889            loced->add_pos_changed_cb(boundloc_changed_cb);
890        }
891        aws->button_length(0);
892
893        loced->createEditFields(aws);
894
895        if (createGene) {
896            aws->at_shift(0, 30);
897            aws->callback(gene_create_cb, (AW_CL)gb_main, (AW_CL)loced);
898            aws->create_autosize_button("CREATE", "Create gene", "G");
899        }
900    }
901    return aws;
902}
903static void popup_gene_location_editor(AW_window *aww, AW_CL cl_gb_main, AW_CL) {
904    AW_window *aws = get_gene_create_or_locationEdit_window(aww->get_root(), false, (GBDATA*)cl_gb_main);
905    aws->activate();
906}
907static AW_window *create_gene_create_window(AW_root *root, AW_CL cl_gb_main) {
908    return get_gene_create_or_locationEdit_window(root, true, (GBDATA*)cl_gb_main);
909}
910
911static void gene_delete_cb(AW_window *aww, AW_CL cl_gb_main) {
912    if (aw_ask_sure("gene_delete", "Are you sure to delete the gene?")) {
913        GBDATA         *gb_main = (GBDATA*)cl_gb_main;
914        GB_transaction  ta(gb_main);
915        GB_ERROR        error   = 0;
916        GBDATA         *gb_gene = GEN_get_current_gene(gb_main, aww->get_root());
917
918        error = gb_gene ? GB_delete(gb_gene) : "Please select a gene first";
919        if (error) {
920            error = ta.close(error);
921            aw_message(error);
922        }
923    }
924}
925
926static void GEN_map_gene(AW_root *aw_root, AW_CL cl_scanner, AW_CL cl_gb_main) {
927    GBDATA         *gb_main = (GBDATA*)cl_gb_main;
928    GB_transaction  dummy(gb_main);
929    GBDATA         *gb_gene = GEN_get_current_gene(gb_main, aw_root);
930
931    if (gb_gene) map_db_scanner((DbScanner*)cl_scanner, gb_gene, CHANGE_KEY_PATH_GENES);
932}
933
934static void GEN_create_field_items(AW_window *aws, GBDATA *gb_main) {
935    static BoundItemSel *bis = new BoundItemSel(gb_main, GEN_get_selector());
936    gen_assert(bis->gb_main == gb_main);
937
938    aws->insert_menu_topic("gen_reorder_fields", "Reorder fields ...",    "R", "spaf_reorder.hlp", AD_F_ALL, AW_POPUP, (AW_CL)DBUI::create_fields_reorder_window, (AW_CL)bis);
939    aws->insert_menu_topic("gen_delete_field",   "Delete/Hide field ...", "D", "spaf_delete.hlp",  AD_F_ALL, AW_POPUP, (AW_CL)DBUI::create_field_delete_window, (AW_CL)bis);
940    aws->insert_menu_topic("gen_create_field",   "Create fields ...",     "C", "spaf_create.hlp",  AD_F_ALL, AW_POPUP, (AW_CL)DBUI::create_field_create_window, (AW_CL)bis);
941    aws->sep______________();
942    aws->insert_menu_topic("gen_unhide_fields", "Show all hidden fields", "S", "scandb.hlp", AD_F_ALL, (AW_CB)gene_field_selection_list_unhide_all_cb, (AW_CL)gb_main, FIELD_FILTER_NDS);
943    aws->sep______________();
944    aws->insert_menu_topic("gen_scan_unknown_fields", "Scan unknown fields",   "u", "scandb.hlp", AD_F_ALL, (AW_CB)gene_field_selection_list_scan_unknown_cb,  (AW_CL)gb_main, FIELD_FILTER_NDS);
945    aws->insert_menu_topic("gen_del_unused_fields",   "Remove unused fields",  "e", "scandb.hlp", AD_F_ALL, (AW_CB)gene_field_selection_list_delete_unused_cb, (AW_CL)gb_main, FIELD_FILTER_NDS);
946    aws->insert_menu_topic("gen_refresh_fields",      "Refresh fields (both)", "f", "scandb.hlp", AD_F_ALL, (AW_CB)gene_field_selection_list_update_cb,        (AW_CL)gb_main, FIELD_FILTER_NDS);
947    aws->sep______________();
948    aws->insert_menu_topic("gen_edit_loc", "Edit gene location", "l", "gen_create.hlp", AD_F_ALL, popup_gene_location_editor, (AW_CL)gb_main, 0);
949}
950
951#if defined(WARN_TODO)
952#warning move GEN_create_gene_window to SL/DB_UI
953#endif
954
955AW_window *GEN_create_gene_window(AW_root *aw_root, AW_CL cl_gb_main) {
956    static AW_window_simple_menu *aws = 0;
957    if (!aws) {
958        GBDATA *gb_main = (GBDATA*)cl_gb_main;
959
960        aws = new AW_window_simple_menu;
961        aws->init(aw_root, "GENE_INFORMATION", "GENE INFORMATION");
962        aws->load_xfig("ad_spec.fig");
963
964        aws->button_length(8);
965
966        aws->at("close");
967        aws->callback((AW_CB0)AW_POPDOWN);
968        aws->create_button("CLOSE", "CLOSE", "C");
969
970        aws->at("search");
971        aws->callback(AW_POPUP, (AW_CL)GEN_create_gene_query_window, (AW_CL)gb_main);
972        aws->create_button("SEARCH", "SEARCH", "S");
973
974        aws->at("help");
975        aws->callback(AW_POPUP_HELP, (AW_CL)"gene_info.hlp");
976        aws->create_button("HELP", "HELP", "H");
977
978        DbScanner *scanner = create_db_scanner(gb_main, aws, "box", 0, "field", "enable", DB_VIEWER, 0, "mark", FIELD_FILTER_NDS, GEN_get_selector());
979
980        aws->create_menu("GENE", "G", AD_F_ALL);
981        aws->insert_menu_topic("gene_delete", "Delete",     "D", "spa_delete.hlp", AD_F_ALL, (AW_CB)gene_delete_cb, (AW_CL)gb_main, 0);
982        aws->insert_menu_topic("gene_rename", "Rename ...", "R", "spa_rename.hlp", AD_F_ALL, AW_POPUP, (AW_CL)create_gene_rename_window, (AW_CL)gb_main);
983        aws->insert_menu_topic("gene_copy",   "Copy ...",   "y", "spa_copy.hlp",   AD_F_ALL, AW_POPUP, (AW_CL)create_gene_copy_window,   (AW_CL)gb_main);
984        aws->insert_menu_topic("gene_create", "Create ...", "C", "gen_create.hlp", AD_F_ALL, AW_POPUP, (AW_CL)create_gene_create_window, (AW_CL)gb_main);
985        aws->sep______________();
986
987        aws->create_menu("FIELDS", "F", AD_F_ALL);
988        GEN_create_field_items(aws, gb_main);
989
990        {
991            Awar_Callback_Info    *cb_info     = new Awar_Callback_Info(aws->get_root(), AWAR_GENE_NAME, GEN_map_gene, (AW_CL)scanner, (AW_CL)gb_main); // do not delete!
992            AW_detach_information *detach_info = new AW_detach_information(cb_info); // do not delete!
993
994            cb_info->add_callback();
995
996            aws->at("detach");
997            aws->callback(DBUI::detach_info_window, (AW_CL)&aws, (AW_CL)detach_info);
998            aws->create_button("DETACH", "DETACH", "D");
999
1000            detach_info->set_detach_button(aws->get_last_widget());
1001        }
1002
1003        aws->show();
1004        GEN_map_gene(aws->get_root(), (AW_CL)scanner, (AW_CL)gb_main);
1005    }
1006    else {
1007        aws->show();
1008    }
1009
1010    return aws;
1011}
1012
1013#if defined(WARN_TODO)
1014#warning move GEN_create_gene_query_window to SL/DB_UI
1015#endif
1016
1017AW_window *GEN_create_gene_query_window(AW_root *aw_root, AW_CL cl_gb_main) {
1018    static AW_window_simple_menu *aws = 0;
1019
1020    if (!aws) {
1021        aws = new AW_window_simple_menu;
1022        aws->init(aw_root, "GEN_QUERY", "Gene SEARCH and QUERY");
1023        aws->create_menu("More functions", "f");
1024        aws->load_xfig("ad_query.fig");
1025
1026        QUERY::query_spec awtqs(GEN_get_selector());
1027
1028        awtqs.gb_main             = (GBDATA*)cl_gb_main;
1029        awtqs.species_name        = AWAR_SPECIES_NAME;
1030        awtqs.tree_name           = AWAR_TREE;
1031        awtqs.select_bit          = 1;
1032        awtqs.use_menu            = 1;
1033        awtqs.ere_pos_fig         = "ere3";
1034        awtqs.where_pos_fig       = "where3";
1035        awtqs.by_pos_fig          = "by3";
1036        awtqs.qbox_pos_fig        = "qbox";
1037        awtqs.rescan_pos_fig      = 0;
1038        awtqs.key_pos_fig         = 0;
1039        awtqs.query_pos_fig       = "content";
1040        awtqs.result_pos_fig      = "result";
1041        awtqs.count_pos_fig       = "count";
1042        awtqs.do_query_pos_fig    = "doquery";
1043        awtqs.config_pos_fig      = "doconfig";
1044        awtqs.do_mark_pos_fig     = "domark";
1045        awtqs.do_unmark_pos_fig   = "dounmark";
1046        awtqs.do_delete_pos_fig   = "dodelete";
1047        awtqs.do_set_pos_fig      = "doset";
1048        awtqs.do_refresh_pos_fig  = "dorefresh";
1049        awtqs.open_parser_pos_fig = "openparser";
1050        awtqs.create_view_window  = GEN_create_gene_window;
1051
1052        QUERY::DbQuery *query = create_query_box(aws, &awtqs, "gen");
1053        GLOBAL_gene_query     = query;
1054
1055        aws->create_menu("More search",     "s");
1056        aws->insert_menu_topic("gen_search_equal_fields_within_db", "Search For Equal Fields and Mark Duplicates",               "E", "search_duplicates.hlp", AWM_ALL, (AW_CB)QUERY::search_duplicated_field_content, (AW_CL)query, 0);
1057        aws->insert_menu_topic("gen_search_equal_words_within_db",  "Search For Equal Words Between Fields and Mark Duplicates", "W", "search_duplicates.hlp", AWM_ALL, (AW_CB)QUERY::search_duplicated_field_content, (AW_CL)query, 1);
1058
1059        aws->button_length(7);
1060
1061        aws->at("close");
1062        aws->callback((AW_CB0)AW_POPDOWN);
1063        aws->create_button("CLOSE", "CLOSE", "C");
1064        aws->at("help");
1065        aws->callback(AW_POPUP_HELP, (AW_CL)"gene_search.hlp");
1066        aws->create_button("HELP", "HELP", "H");
1067    }
1068
1069    return aws;
1070}
Note: See TracBrowser for help on using the repository browser.