source: branches/profile/GENOM/GEN_interface.cxx

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