source: tags/ms_r18q1/GENOM/GEN_interface.cxx

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