source: tags/svn.1.5.4/SECEDIT/SEC_graphic.cxx

Last change on this file was 8359, checked in by westram, 13 years ago
  • added 'Never ask again' switch to most modal question dialogs. This is a workaround to make it possible to work with macros where modal questions are used. See also #179
    • added unique IDs to all calls to aw_question / AW_repeated_question::get_answer
    • replaced most calls to aw_popup_ok with aw_message (most of them only worked-around the non-standard way of EDIT4 to show aw_message)
  • added 'Reactivate questions' to all properties menus
  • hardcoded unused default-params from aw_ask_sure, aw_popup_ok + aw_popup_exit
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.9 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : SEC_graphic.cxx                                   //
4//   Purpose   : GUI for structure window                          //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "SEC_graphic.hxx"
12#include "SEC_root.hxx"
13#include "SEC_iter.hxx"
14#include "SEC_toggle.hxx"
15
16#include <ed4_extern.hxx>
17
18#include <aw_awars.hxx>
19#include <aw_global.hxx>
20#include <aw_preset.hxx>
21#include <aw_msg.hxx>
22#include <aw_root.hxx>
23#include <aw_question.hxx>
24#include <arbdbt.h>
25
26#include <vector>
27
28using namespace std;
29
30AW_gc_manager SEC_graphic::init_devices(AW_window *aww, AW_device *device, AWT_canvas* ntw, AW_CL)
31{
32    AW_gc_manager preset_window =
33        AW_manage_GC(aww,
34                     device,
35                     SEC_GC_LOOP,
36                     SEC_GC_MAX,
37                     AW_GCM_DATA_AREA,
38                     (AW_CB)AWT_expose_cb, (AW_CL)ntw, 0,
39                     false,
40                     "#A1A1A1",
41                     "LOOP$#247900",
42                     "HELIX$#085DAB",
43                     "NONPAIRING HELIX$#D52B69",
44                     "DEFAULT$#000000",
45                     "BONDS$#000000",
46                     "ECOLI POSITION$#FFE223",
47                     "HELIX NUMBERS$#D4D4D4",
48
49                     // Color Ranges to paint SAIs
50                     "+-RANGE 0$#FFFFFF",    "+-RANGE 1$#E0E0E0",    "-RANGE 2$#C0C0C0",
51                     "+-RANGE 3$#A0A0A0",    "+-RANGE 4$#909090",    "-RANGE 5$#808080",
52                     "+-RANGE 6$#808080",    "+-RANGE 7$#505050",    "-RANGE 8$#404040",
53                     "+-RANGE 9$#303030",    "+-CURSOR$#BF1515",     "-MISMATCHES$#FF9AFF",
54
55                     // colors used to Paint search patterns
56                     // (do not change the names of these gcs)
57                     "+-User1$#B8E2F8",          "+-User2$#B8E2F8",         "-Probe$#B8E2F8",
58                     "+-Primer(l)$#A9FE54",      "+-Primer(r)$#A9FE54",     "-Primer(g)$#A9FE54",
59                     "+-Sig(l)$#DBB0FF",         "+-Sig(r)$#DBB0FF",        "-Sig(g)$#DBB0FF",
60
61                     // colors used to paint the skeleton of the structure
62                     "+-SKELETON HELIX${HELIX}", "+-SKELETON LOOP${LOOP}", "-SKELETON NONHELIX${NONPAIRING HELIX}",
63                     NULL);
64
65    return preset_window;
66}
67
68static GB_ERROR change_constraints(SEC_base *elem) {
69    GB_ERROR  error    = 0;
70
71    GB_CSTR constraint_type = 0;
72    GB_CSTR element_type    = 0;
73
74    switch (elem->getType()) {
75        case SEC_HELIX:
76            constraint_type = "length";
77            element_type    = "helix";
78            break;
79        case SEC_LOOP:
80            constraint_type = "radius";
81            element_type    = "loop";
82            break;
83        default:
84            sec_assert(0);
85            error           = "Illegal element type";
86            break;
87    }
88
89    if (!error) {
90        char *question = GBS_global_string_copy("%s-constraints for %s", constraint_type, element_type);
91        char *answer   = aw_input(question, GBS_global_string("%.2f-%.2f", elem->minSize(), elem->maxSize()));
92
93        while (answer) {
94            char *end;
95            double low = strtod(answer, &end);
96
97            if (end[0]!='-') {
98                error = "Wrong format! Wanted format is 'lower-upper'";
99            }
100            else {
101                double high = strtod(end+1, 0);
102
103                if (low<0 || high<0 || (low && high && low>high)) {
104                    error = "Illegal values";
105                }
106                else {
107#if defined(DEBUG)
108                    sec_assert(!low || !high || low<=high);
109#endif // DEBUG
110                    elem->setConstraints(low, high);
111                    break;
112                }
113            }
114
115            sec_assert(error);
116            aw_message(error);
117
118            char *retry = aw_input(question, answer);
119            free(answer);
120
121            answer = retry;
122        }
123
124        free(answer);
125        free(question);
126    }
127    return error;
128}
129
130
131GB_ERROR SEC_graphic::handleKey(AW_event_type event, AW_key_mod key_modifier, AW_key_code key_code, char key_char) {
132    GB_ERROR error = 0;
133
134    if (event == AW_Keyboard_Press) {
135        bool wrapped   = false; // avoid deadlock
136        int  curpos    = sec_root->get_cursor();
137        int  maxIndex  = sec_root->max_index();
138        bool setCurpos = false;
139        bool handled   = false;
140
141        if (key_modifier == AW_KEYMODE_NONE) {
142            switch (key_code) {
143                case AW_KEY_LEFT: {
144                    while (1) {
145                        curpos--;
146                        if (curpos<0) {
147                            curpos  = maxIndex;
148                            if (wrapped) break;
149                            wrapped = true;
150                        }
151                        if (sec_root->shallDisplayPosition(curpos)) {
152                            setCurpos = true;
153                            break;
154                        }
155                    }
156                    break;
157                }
158                case AW_KEY_RIGHT: {
159                    while (1) {
160                        curpos++;
161                        if (curpos > maxIndex) {
162                            curpos  = 0;
163                            if (wrapped) break;
164                            wrapped = true;
165                        }
166                        if (sec_root->shallDisplayPosition(curpos)) {
167                            setCurpos = true;
168                            break;
169                        }
170                    }
171                    break;
172                }
173                case AW_KEY_ASCII: {
174                    const char *toggle_awar = 0;
175                    int         val_max     = 1;
176
177                    switch (key_char) {
178                        case 'b': toggle_awar = AWAR_SECEDIT_SHOW_BONDS; val_max = 2; break;
179                        case 'B': toggle_awar = AWAR_SECEDIT_HIDE_BASES; break;
180                        case 'k': toggle_awar = AWAR_SECEDIT_SHOW_STR_SKELETON; break;
181
182                        case 'c': toggle_awar = AWAR_SECEDIT_SHOW_CURPOS; val_max = 3; break;
183                        case 'h': toggle_awar = AWAR_SECEDIT_SHOW_HELIX_NRS; break;
184                        case 'e': toggle_awar = AWAR_SECEDIT_SHOW_ECOLI_POS; break;
185
186                        case 's': toggle_awar = AWAR_SECEDIT_DISPLAY_SAI; break;
187                        case 'r': toggle_awar = AWAR_SECEDIT_DISPLAY_SEARCH; break;
188
189                        case 'E': toggle_awar = AWAR_SECEDIT_DISPPOS_ECOLI; break;
190                        case 'H': toggle_awar = AWAR_SECEDIT_DISPPOS_BINDING; break;
191
192#if defined(DEBUG)
193                        case 'd': toggle_awar = AWAR_SECEDIT_SHOW_DEBUG; break;
194#endif // DEBUG
195
196                        case 't':
197                            error   = sec_root->get_db()->structure()->next();
198                            handled = true;
199                            break;
200                    }
201
202                    if (toggle_awar) {
203                        AW_awar *awar = aw_root->awar(toggle_awar);
204                        int      val  = awar->read_int()+1;
205
206                        if (val>val_max) val = 0;
207                        awar->write_int(val);
208
209                        handled = true;
210                    }
211
212                    break;
213                }
214                default:
215                    break;
216            }
217        }
218
219        if (setCurpos) {
220            aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(curpos);
221            handled = true;
222        }
223
224        if (!handled) { // pass unhandled key events to EDIT4
225            AW_event faked_event;
226
227            memset((char*)&faked_event, 0, sizeof(faked_event));
228
229            faked_event.type        = event;
230            faked_event.keymodifier = key_modifier;
231            faked_event.keycode     = key_code;
232            faked_event.character   = key_char;
233
234            sec_root->host().forward_event(&faked_event);
235        }
236    }
237
238    return error;
239}
240
241GB_ERROR SEC_graphic::handleMouse(AW_device *device, AW_event_type event, int button, AWT_COMMAND_MODE cmd, const Position& world, SEC_base *elem, int abspos) {
242    GB_ERROR error = 0;
243
244    // -----------------------------------------
245    //      handle element dependent actions
246    // -----------------------------------------
247
248    if (elem) {
249        static Position start;      // click position on mouse down
250
251        Position fixpoint = elem->get_fixpoint(); // of strand or loop
252
253        SEC_loop  *loop  = 0;
254        SEC_helix *helix = 0;
255
256        if (elem->getType() == SEC_HELIX) helix = static_cast<SEC_helix*>(elem);
257        else {
258            sec_assert(elem->getType() == SEC_LOOP);
259            loop = static_cast<SEC_loop*>(elem);
260        }
261
262        if (event == AW_Mouse_Press) start = world; // store start position
263
264        switch (cmd) {
265            case AWT_MODE_STRETCH: { // change constraints with mouse
266                static double start_size; // helix/loop size at start click
267
268                switch (event) {
269                    case AW_Mouse_Press:
270                        if (button == AWT_M_LEFT) {
271                            start_size = elem->drawnSize();
272                            sec_root->set_show_constraints(elem->getType());
273                            exports.refresh = 1;
274                        }
275                        else { // right button -> reset constraints
276                            elem->setConstraints(0, 0);
277                            elem->sizeChanged();
278                            exports.refresh = 1;
279                            exports.save    = 1;
280                        }
281                        break;
282
283                    case AW_Mouse_Drag:
284                        if (button == AWT_M_LEFT) {
285                            double dfix1 = Distance(fixpoint, start);
286                            double dfix2 = Distance(fixpoint, world);
287
288                            if (dfix1>0 && dfix2>0) {
289                                double factor   = dfix2/dfix1;
290                                double new_size = start_size*factor;
291
292                                elem->setDrawnSize(new_size);
293                                elem->sizeChanged();
294
295                                exports.refresh            = 1;
296                            }
297                        }
298                        break;
299
300                    case AW_Mouse_Release:
301                        sec_root->set_show_constraints(SEC_ANY_TYPE);
302                        exports.save = 1;
303                        break;
304
305                    default: sec_assert(0); break;
306                }
307                break;
308            }
309            case AWT_MODE_EDIT:  // edit constraints
310                if (button==AWT_M_LEFT && event==AW_Mouse_Press) {
311                    error = change_constraints(elem);
312                    if (!error) {
313                        elem->sizeChanged();
314                        exports.save = 1;
315                    }
316                }
317                break;
318
319            case AWT_MODE_ROT: { // rotate branches/loops
320                if (event == AW_Mouse_Release) {
321                    exports.save = 1;
322                }
323                else {
324                    static Angle startClick; // angle between fixpoint (of loop or helix) and first-click
325                    static bool  rotateSubStructure; // whether to rotate the substructure below
326                    static vector<Angle> old; // old angles
327
328                    if (loop && loop->is_root_loop()) fixpoint = loop->get_center();
329
330                    Angle fix2world(fixpoint, world);
331
332                    if (event == AW_Mouse_Press) {
333                        startClick = fix2world;
334                        old.clear();
335                        rotateSubStructure = (button == AWT_M_LEFT);
336
337                        if (loop) {
338                            old.push_back(loop->get_abs_angle());
339                            if (!rotateSubStructure) {
340                                for (SEC_strand_iterator strand(loop); strand; ++strand) {
341                                    if (strand->isRootsideFixpoint()) {
342                                        old.push_back(strand->get_helix()->get_abs_angle());
343                                    }
344                                }
345                            }
346                        }
347                        else {
348                            old.push_back(helix->get_abs_angle());
349                            old.push_back(helix->outsideLoop()->get_abs_angle());
350                        }
351                    }
352                    else {
353                        sec_assert(event == AW_Mouse_Drag);
354                        Angle diff = fix2world-startClick;
355
356                        if (loop) {
357                            loop->set_abs_angle(old[0]+diff);
358                            if (!rotateSubStructure) {
359                                int idx = 1;
360                                for (SEC_strand_iterator strand(loop); strand; ++strand) {
361                                    if (strand->isRootsideFixpoint()) {
362                                        strand->get_helix()->set_abs_angle(old[idx++]);
363                                    }
364                                }
365                            }
366                        }
367                        else {
368                            helix->set_abs_angle(old[0]+diff);
369                            if (!rotateSubStructure) helix->outsideLoop()->set_abs_angle(old[1]);
370                        }
371
372                        exports.refresh = 1;
373                        elem->orientationChanged();
374                    }
375                }
376                break;
377            }
378
379            case AWT_MODE_SETROOT:  // set-root-mode / reset angles
380                if (event == AW_Mouse_Press) {
381                    if (button == AWT_M_LEFT) { // set root
382                        if (loop) {
383                            sec_root->set_root(loop);
384                            exports.save = 1;
385                        }
386                        else error = "Please click on a loop to change the root";
387                    }
388                    else { // reset angles
389                        sec_assert(button == AWT_M_RIGHT);
390                        elem->reset_angles();
391                        elem->orientationChanged();
392                        exports.save = 1;
393                    }
394                }
395                break;
396
397            case AWT_MODE_MOVE: { // fold/unfold helix
398                if (event == AW_Mouse_Press) {
399                    if (button == AWT_M_LEFT) { // fold helix
400                        if (loop) {
401                            const char *helix_nr = sec_root->helixNrAt(abspos);
402                            if (helix_nr) {
403                                const size_t *p = sec_root->getHelixPositions(helix_nr);
404                                error           = sec_root->split_loop(p[0], p[1]+1, p[2], p[3]+1);
405
406                                if (!error) {
407                                    sec_root->nail_position(abspos);
408                                    exports.save = 1;
409                                }
410                            }
411                            else {
412                                error = GBS_global_string("No helix to fold at position %i", abspos);
413                            }
414                        }
415                        else {
416                            error = "Click on a loop region to fold a helix";
417                        }
418                    }
419                    else { // unfold helix
420                        sec_assert(button == AWT_M_RIGHT);
421                        if (helix) {
422                            error = sec_root->unsplit_loop(helix->strandToRoot());
423                            if (!error) {
424                                sec_root->nail_position(abspos);
425                                exports.save = 1;
426                            }
427                        }
428                        else {
429                            error = "Right click on a helix to remove it";
430                        }
431                    }
432                }
433                break;
434            }
435            case AWT_MODE_LINE:
436            case AWT_MODE_PROINFO:
437                elem = 0; // handle element-independent
438                break;
439            default: sec_assert(0); break;
440        }
441    }
442
443    // --------------------------------------
444    //      action independent of element
445    // --------------------------------------
446
447    if (!elem) {
448        switch (cmd) {
449            case AWT_MODE_LINE: // set cursor in ARB_EDIT4
450                if (event == AW_Mouse_Press) {
451                    if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
452                        // sequence position in AWAR_SET_CURSOR_POSITION is starting with 0!
453                        aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(abspos);
454                    }
455                }
456                break;
457
458            case AWT_MODE_PROINFO: // display search pattern
459                if (event == AW_Mouse_Press) {
460                    if (button == AWT_M_LEFT) {
461                        if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
462                            sec_root->paintSearchPatternStrings(device, abspos, world.xpos()+1, world.ypos());
463                        }
464                        // don't refresh here!
465                    }
466                    else {
467                        sec_assert(button == AWT_M_RIGHT);
468                        exports.refresh = 1; // simply refresh to remove drawn patterns
469                    }
470                }
471                break;
472
473            default:
474                break;
475        }
476        return 0; // no error
477    }
478
479    if (exports.save == 1) exports.refresh = 1;
480    return error;
481}
482
483void SEC_graphic::command(AW_device *device, AWT_COMMAND_MODE cmd,
484                          int button, AW_key_mod key_modifier, AW_key_code key_code, char key_char,
485                          AW_event_type event, AW_pos screen_x, AW_pos screen_y,
486                          AW_clicked_line *cl, AW_clicked_text *ct)
487{
488    if (cmd != AWT_MODE_EDIT && cmd != AWT_MODE_STRETCH) sec_root->set_show_constraints(SEC_NO_TYPE);
489
490    GB_ERROR error = 0;
491    if (event == AW_Keyboard_Press || event == AW_Keyboard_Release) {
492        error = handleKey(event, key_modifier, key_code, key_char);
493    }
494    else {
495        if (button != AWT_M_MIDDLE && cmd != AWT_MODE_ZOOM) { // don't handle scroll + zoom
496            AW_CL    cd1, cd2;
497
498            if (AW_getBestClick(cl, ct, &cd1, &cd2)) {
499                SEC_base *elem   = reinterpret_cast<SEC_base*>(cd1);
500                int       abspos = cd2;
501
502#if defined(DEBUG) && 0
503                if (cl->exists) device->line(SEC_GC_CURSOR, cl->x0, cl->y0, cl->x1, cl->y1, -1, 0, -1);
504                if (ct->exists) device->box(SEC_GC_CURSOR, false, ct->textArea, -1, 0, -1);
505#endif // DEBUG
506
507                Position world = device->rtransform(Position(screen_x, screen_y)); // current click position
508                error = handleMouse(device, event, button, cmd, world, elem, abspos);
509            }
510        }
511    }
512
513    if (error) aw_message(error);
514}
515
516
517SEC_graphic::SEC_graphic(AW_root *aw_rooti, GBDATA *gb_maini)
518    : update_requested(SEC_UPDATE_RELOAD)
519    , load_error(0)
520    , disp_device(0)
521    , gb_main(gb_maini)
522    , aw_root(aw_rooti)
523    , sec_root(new SEC_root)
524    , gb_struct(0)
525    , gb_struct_ref(0)
526    , last_saved(0)
527{
528    exports.dont_fit_x  = 0;
529    exports.dont_fit_y  = 0;
530    exports.dont_scroll = 0;
531    exports.set_standard_default_padding();
532
533    rot_ct.exists = false;
534    rot_cl.exists = false;
535}
536
537SEC_graphic::~SEC_graphic() {
538    delete sec_root;
539    delete load_error;
540}
541
542static void SEC_structure_changed_cb(GBDATA *gb_seq, SEC_graphic *gfx, GB_CB_TYPE type) {
543    if (type == GB_CB_DELETE) {
544        gfx->gb_struct     = NULL;
545        gfx->gb_struct_ref = NULL;
546
547        gfx->request_update(SEC_UPDATE_RELOAD);
548    }
549    else if (GB_read_clock(gb_seq) > gfx->last_saved) { // not changed by secedit self
550        gfx->request_update(SEC_UPDATE_RELOAD);
551    }
552}
553
554GB_ERROR SEC_graphic::load(GBDATA *, const char *, AW_CL, AW_CL) {
555    //! (Re-)Load secondary structure from database
556
557    sec_assert(sec_root->get_db()->canDisplay()); // need a sequence loaded (to fix bugs in versions < 3)
558    sec_root->nail_cursor();
559
560    GB_transaction ta(gb_main);
561    // first check timestamp, do not load structure that we have saved !!!!
562    if (gb_struct) {
563        if (GB_read_clock(gb_struct) <= last_saved) return NULL;
564    }
565
566    // Reset structure:
567    if (gb_struct) {
568        GB_remove_callback(gb_struct,   GB_CB_ALL, (GB_CB)SEC_structure_changed_cb, (int *)this);
569        gb_struct = NULL;
570        GB_remove_callback(gb_struct_ref,   GB_CB_ALL, (GB_CB)SEC_structure_changed_cb, (int *)this);
571        gb_struct_ref = NULL;
572    }
573
574    request_update(SEC_UPDATE_RECOUNT);
575
576    if (gb_struct) {
577        this->last_saved = GB_read_clock(gb_struct); // mark as loaded
578    }
579
580
581    GB_ERROR err = 0;
582
583    // Setup new structure:
584    long    ali_len = -1;
585    GBDATA *gb_ali  = 0;
586    {
587        char *helix_name = GBT_get_default_helix(gb_main);
588        char *name       = GBT_readOrCreate_string(gb_main, AWAR_HELIX_NAME, helix_name);
589        sec_assert(name);
590
591        GBDATA *gb_species = GBT_find_SAI(gb_main, name);
592        if (!gb_species) {
593            err = GB_export_errorf("Cannot find helix template SAI '%s'", name);
594        }
595        else {
596            char *ali_name = GBT_get_default_alignment(gb_main);
597
598            ali_len = GBT_get_alignment_len(gb_main, ali_name);
599            if (ali_len < 10) {
600                err = GB_export_errorf("alignment '%s' to short to generate helix", ali_name);
601            }
602            else {
603                gb_ali = GB_search(gb_species, ali_name, GB_FIND);
604                if (!gb_ali) {
605                    err = GB_export_errorf("Your helix structure template '%s' has no valid sequence for alignment '%s'", name, ali_name); // no sequence for name in the database !!!
606                }
607            }
608            free(ali_name);
609        }
610
611        free(name);
612        free(helix_name);
613    }
614
615    // -----------------------
616    //      read structure
617    // -----------------------
618
619    if (!err) {
620        gb_struct = GB_search(gb_ali, NAME_OF_STRUCT_SEQ, GB_FIND);
621
622        if (gb_struct) {
623            gb_struct_ref = GB_search(gb_ali,  NAME_OF_REF_SEQ,  GB_STRING);
624
625            char *strct = GB_read_string(gb_struct);
626            char *ref = GB_read_string(gb_struct_ref);
627            err = sec_root->read_data(strct, ref);
628            if (err) {
629                err = GBS_global_string("Defect structure in DB (read-error: '%s')", err);
630            }
631#if defined(CHECK_INTEGRITY)
632            else {
633                sec_root->check_integrity(CHECK_STRUCTURE);
634            }
635#endif // CHECK_INTEGRITY
636
637            free(strct);
638            free(ref);
639
640            // on first load init structure toggler:
641            if (!err) {
642                sec_root->get_db()->init_toggler();
643            }
644        }
645        else {
646            err = "no secondary structure was found in your database";
647        }
648
649        if (err) {
650            request_update(SEC_UPDATE_ZOOM_RESET);
651        }
652        else {
653            // in the past one additional NAME_OF_STRUCT_SEQ-entry was added everytime the default bone was created
654            // Fix: delete additional entries
655
656            GBDATA *gb_add = gb_struct;
657            do {
658                sec_assert(GB_has_key(gb_add, NAME_OF_STRUCT_SEQ));
659                gb_add = GB_nextEntry(gb_add);
660                if (gb_add) {
661                    err = GB_delete(gb_add);
662                    printf("* Deleting duplicated entry '%s' (%p)\n", NAME_OF_STRUCT_SEQ, gb_add);
663                }
664            }
665            while (gb_add && !err);
666        }
667    }
668
669    if (!err) {
670        last_saved = GB_read_clock(gb_struct); // mark as loaded
671        request_update(SEC_UPDATE_RECOUNT);
672        if (load_error) { // previous load error?
673            freenull(load_error);
674            request_update(SEC_UPDATE_ZOOM_RESET);
675        }
676    }
677    else {
678        load_error = strdup(err);
679        request_update(SEC_UPDATE_ZOOM_RESET);
680    }
681
682    // set structure-change-callbacks:
683    if (gb_struct)     GB_add_callback(gb_struct, GB_CB_ALL, (GB_CB)SEC_structure_changed_cb, (int *)this);
684    if (gb_struct_ref) GB_add_callback(gb_struct_ref, GB_CB_ALL, (GB_CB)SEC_structure_changed_cb, (int *)this);
685
686    return err;
687}
688
689GB_ERROR SEC_graphic::save(GBDATA *, const char *, AW_CL, AW_CL) {
690    //! Save secondary structure to database
691
692    if (!gb_struct) return 0;   // not loaded, so don't save
693    if (!sec_root) return 0;
694
695    char           *data  = sec_root->buildStructureString();
696    GB_transaction  ta(gb_main);
697    GB_ERROR        error = GB_write_string(gb_struct, data);
698    if (!error) {
699        const XString&  xstr     = sec_root->get_xString();
700        const char     *x_string = xstr.get_x_string();
701
702        error = GB_write_string(gb_struct_ref, x_string);
703
704        if (!error && xstr.alignment_too_short()) {
705            aw_message("Your helix needs one gap at end. Please format your alignment!");
706        }
707    }
708    this->last_saved = GB_read_clock(gb_struct);
709    if (error) {
710        error = ta.close(error);
711        aw_message(error);
712    }
713    return NULL;
714}
715
716GB_ERROR SEC_graphic::read_data_from_db(char **data, char **x_string) const {
717    GB_ERROR error = 0;
718
719    sec_assert(gb_struct && gb_struct_ref);
720    *data             = GB_read_string(gb_struct);
721    if (!*data) error = GB_await_error();
722    else {
723        *x_string             = GB_read_string(gb_struct_ref);
724        if (!*x_string) error = GB_await_error();
725    }
726    return error;
727}
728
729GB_ERROR SEC_graphic::write_data_to_db(const char *data, const char *x_string) const {
730    if (!gb_struct) return 0;
731    if (!sec_root) return 0;
732
733    GB_transaction ta(gb_main);
734    GB_ERROR       error = GB_write_string(gb_struct, data);
735    if (!error) {
736        error = GB_write_string(gb_struct_ref, x_string);
737    }
738    last_saved = 0;             // force reload of data
739    return ta.close(error);
740}
741
742int SEC_graphic::check_update(GBDATA *) {
743    GB_transaction ta(gb_main);
744
745    const SEC_db_interface *db = sec_root->get_db();
746
747    if (db && db->canDisplay()) {
748        if (update_requested & SEC_UPDATE_RELOAD) {
749            GB_ERROR error   = load(0, 0, 0, 0); // sets change_flag
750            if (error) {
751                error = ta.close(error);
752                aw_message(error);
753            }
754
755            update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_RELOAD)|SEC_UPDATE_RECOUNT); // clear reload flag
756            exports.refresh  = 1;
757        }
758
759        if (update_requested & SEC_UPDATE_SHOWN_POSITIONS) {
760            sec_root->update_shown_positions();
761            update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_SHOWN_POSITIONS)|SEC_UPDATE_RECOUNT); // clear reload flag
762            exports.refresh  = 1;
763        }
764
765        if (update_requested & SEC_UPDATE_RECOUNT) {
766            sec_root->invalidate_base_positions();
767            sec_root->relayout();
768
769            update_requested = static_cast<SEC_update_request>(update_requested^SEC_UPDATE_RECOUNT); // clear recount flag
770            exports.refresh  = 1;
771        }
772
773        sec_root->perform_autoscroll();
774    }
775
776    int res = 0;
777    if (update_requested & SEC_UPDATE_ZOOM_RESET) {
778        res              = 1; // report zoom reset
779        update_requested = static_cast<SEC_update_request>(update_requested^SEC_UPDATE_ZOOM_RESET); // clear zoom reset flag
780    }
781    return res;
782}
783
784void SEC_graphic::update(GBDATA *) {
785}
786
787void SEC_graphic::show(AW_device *device) {
788    const char *textToDisplay = 0;
789
790    sec_assert(sec_root);
791    sec_root->clear_last_drawed_cursor_position();
792
793    if (sec_root->canDisplay()) {
794        if (sec_root->get_root_loop()) {
795            GB_ERROR paint_error = sec_root->paint(device);
796            if (paint_error) textToDisplay = GBS_global_string("Error: %s", paint_error);
797        }
798        else {
799            if (load_error)     textToDisplay = GBS_global_string("Load error: %s", load_error);
800            else                textToDisplay = "No structure loaded (yet)";
801        }
802    }
803    else {
804        const SEC_db_interface *db = sec_root->get_db();
805
806        if (!db)                textToDisplay = "Not connected to database";
807        else if (!db->helix())  textToDisplay = "No helix info";
808        else                    textToDisplay = "No species selected";
809    }
810
811    if (textToDisplay) { // no structure
812        sec_assert(strchr(textToDisplay, '\n') == 0); // linefeeds do not work here
813        device->text(SEC_GC_ECOLI, textToDisplay, 0, 0, 0, AW_SCREEN, 0);
814        sec_root->set_last_drawed_cursor_position(LineVector(Origin, ZeroVector));
815    }
816}
817
818void SEC_graphic::info(AW_device */*device*/, AW_pos /*x*/, AW_pos /*y*/, AW_clicked_line */*cl*/, AW_clicked_text */*ct*/) {
819    aw_message("INFO MESSAGE");
820}
821
Note: See TracBrowser for help on using the repository browser.