source: tags/ms_r16q2/SECEDIT/SEC_graphic.cxx

Last change on this file was 14940, checked in by westram, 6 years ago
  • AW_manage_GC: changed trigger for color-groups (bool → definition string)
    • allows to specify the position of color_groups in GC-list managed by AW_gc_manager
    • Fixed: if a color-range was specified ⇒ fonts of color-group-GCs were undefined (bug was triggered by [14936])
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.8 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#include <ad_cb.h>
26
27#include <vector>
28
29using namespace std;
30
31AW_gc_manager *SEC_graphic::init_devices(AW_window *aww, AW_device *device, AWT_canvas *scr) {
32    AW_gc_manager *gc_manager =
33        AW_manage_GC(aww,
34                     scr->get_gc_base_name(),
35                     device,
36                     SEC_GC_LOOP,
37                     SEC_GC_MAX,
38                     AW_GCM_DATA_AREA,
39                     makeGcChangedCallback(AWT_GC_changed_cb, scr),
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 gc_manager;
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        int  curpos    = sec_root->get_cursor();
136        int  maxIndex  = sec_root->max_index();
137        bool setCurpos = false;
138        bool handled   = false;
139
140        if (key_modifier == AW_KEYMODE_NONE) {
141            bool wrapped = false;   // avoid deadlock
142
143            switch (key_code) {
144                case AW_KEY_LEFT: {
145                    while (1) {
146                        curpos--;
147                        if (curpos<0) {
148                            curpos  = maxIndex;
149                            if (wrapped) break;
150                            wrapped = true;
151                        }
152                        if (sec_root->shallDisplayPosition(curpos)) {
153                            setCurpos = true;
154                            break;
155                        }
156                    }
157                    break;
158                }
159                case AW_KEY_RIGHT: {
160                    while (1) {
161                        curpos++;
162                        if (curpos > maxIndex) {
163                            curpos  = 0;
164                            if (wrapped) break;
165                            wrapped = true;
166                        }
167                        if (sec_root->shallDisplayPosition(curpos)) {
168                            setCurpos = true;
169                            break;
170                        }
171                    }
172                    break;
173                }
174                case AW_KEY_ASCII: {
175                    const char *toggle_awar = 0;
176                    int         val_max     = 1;
177
178                    switch (key_char) {
179                        case 'b': toggle_awar = AWAR_SECEDIT_SHOW_BONDS; val_max = 2; break;
180                        case 'B': toggle_awar = AWAR_SECEDIT_HIDE_BASES; break;
181                        case 'k': toggle_awar = AWAR_SECEDIT_SHOW_STR_SKELETON; break;
182
183                        case 'c': toggle_awar = AWAR_SECEDIT_SHOW_CURPOS; val_max = 3; break;
184                        case 'h': toggle_awar = AWAR_SECEDIT_SHOW_HELIX_NRS; break;
185                        case 'e': toggle_awar = AWAR_SECEDIT_SHOW_ECOLI_POS; break;
186
187                        case 's': toggle_awar = AWAR_SECEDIT_DISPLAY_SAI; break;
188                        case 'r': toggle_awar = AWAR_SECEDIT_DISPLAY_SEARCH; break;
189
190                        case 'E': toggle_awar = AWAR_SECEDIT_DISPPOS_ECOLI; break;
191                        case 'H': toggle_awar = AWAR_SECEDIT_DISPPOS_BINDING; break;
192
193#if defined(DEBUG)
194                        case 'd': toggle_awar = AWAR_SECEDIT_SHOW_DEBUG; break;
195#endif // DEBUG
196
197                        case 't':
198                            error   = sec_root->get_db()->structure()->next();
199                            handled = true;
200                            break;
201                    }
202
203                    if (toggle_awar) {
204                        AW_awar *awar = aw_root->awar(toggle_awar);
205                        int      val  = awar->read_int()+1;
206
207                        if (val>val_max) val = 0;
208                        awar->write_int(val);
209
210                        handled = true;
211                    }
212
213                    break;
214                }
215                default:
216                    break;
217            }
218        }
219
220        if (setCurpos) {
221            aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(curpos);
222            handled = true;
223        }
224
225        if (!handled) { // pass unhandled key events to EDIT4
226            AW_event faked_event;
227
228            memset((char*)&faked_event, 0, sizeof(faked_event));
229
230            faked_event.type        = event;
231            faked_event.keymodifier = key_modifier;
232            faked_event.keycode     = key_code;
233            faked_event.character   = key_char;
234
235            sec_root->host().forward_event(&faked_event);
236        }
237    }
238
239    return error;
240}
241
242GB_ERROR SEC_graphic::handleMouse(AW_device *device, AW_event_type event, int button, AWT_COMMAND_MODE cmd, const Position& world, SEC_base * const elem, int abspos) {
243    GB_ERROR error = 0;
244
245    sec_assert(elem); // always contains the element targetted by the initial button-down
246
247    // ------------------------------------------
248    //      handle element dependent actions
249
250    static Position start;      // click position on mouse down
251
252    Position fixpoint = elem->get_fixpoint(); // of strand or loop
253
254    SEC_loop  *loop  = 0;
255    SEC_helix *helix = 0;
256
257    if (elem->getType() == SEC_HELIX) {
258        helix = static_cast<SEC_helix*>(elem);
259    }
260    else {
261        sec_assert(elem->getType() == SEC_LOOP);
262        loop = static_cast<SEC_loop*>(elem);
263    }
264
265    if (event == AW_Mouse_Press) start = world; // store start position
266
267    switch (cmd) {
268        case AWT_MODE_STRETCH: { // change constraints with mouse
269            static double start_size; // helix/loop size at start click
270
271            switch (event) {
272                case AW_Mouse_Press:
273                    if (button == AW_BUTTON_LEFT) {
274                        start_size = elem->drawnSize();
275                        sec_root->set_show_constraints(elem->getType());
276                        exports.refresh = 1;
277                    }
278                    else { // right button -> reset constraints
279                        elem->setConstraints(0, 0);
280                        elem->sizeChanged();
281                        exports.save = 1;
282                    }
283                    break;
284
285                case AW_Mouse_Drag:
286                    if (button == AW_BUTTON_LEFT) {
287                        double dfix1 = Distance(fixpoint, start);
288                        double dfix2 = Distance(fixpoint, world);
289
290                        if (dfix1>0 && dfix2>0) {
291                            double factor   = dfix2/dfix1;
292                            double new_size = start_size*factor;
293
294                            elem->setDrawnSize(new_size);
295                            elem->sizeChanged();
296
297                            exports.refresh = 1;
298                        }
299                    }
300                    break;
301
302                case AW_Mouse_Release:
303                    sec_root->set_show_constraints(SEC_ANY_TYPE);
304                    exports.save = 1;
305                    break;
306
307                default: sec_assert(0); break;
308            }
309            break;
310        }
311        case AWT_MODE_EDIT:  // edit constraints
312            if (button==AW_BUTTON_LEFT && event==AW_Mouse_Press) {
313                error = change_constraints(elem);
314                if (!error) {
315                    elem->sizeChanged();
316                    exports.save = 1;
317                }
318            }
319            break;
320
321        case AWT_MODE_ROTATE: { // rotate branches/loops
322            if (event == AW_Mouse_Release) {
323                exports.save = 1;
324            }
325            else {
326                static Angle startClick; // angle between fixpoint (of loop or helix) and first-click
327                static bool  rotateSubStructure; // whether to rotate the substructure below
328                static vector<Angle> old; // old angles
329
330                if (loop && loop->is_root_loop()) fixpoint = loop->get_center();
331
332                Angle fix2world(fixpoint, world);
333
334                if (event == AW_Mouse_Press) {
335                    startClick = fix2world;
336                    old.clear();
337                    rotateSubStructure = (button == AW_BUTTON_LEFT);
338
339                    if (loop) {
340                        old.push_back(loop->get_abs_angle());
341                        if (!rotateSubStructure) {
342                            for (SEC_strand_iterator strand(loop); strand; ++strand) {
343                                if (strand->isRootsideFixpoint()) {
344                                    old.push_back(strand->get_helix()->get_abs_angle());
345                                }
346                            }
347                        }
348                    }
349                    else {
350                        old.push_back(helix->get_abs_angle());
351                        old.push_back(helix->outsideLoop()->get_abs_angle());
352                    }
353                }
354                else {
355                    sec_assert(event == AW_Mouse_Drag);
356                    Angle diff = fix2world-startClick;
357
358                    if (loop) {
359                        loop->set_abs_angle(old[0]+diff);
360                        if (!rotateSubStructure) {
361                            int idx = 1;
362                            for (SEC_strand_iterator strand(loop); strand; ++strand) {
363                                if (strand->isRootsideFixpoint()) {
364                                    strand->get_helix()->set_abs_angle(old[idx++]);
365                                }
366                            }
367                        }
368                    }
369                    else {
370                        helix->set_abs_angle(old[0]+diff);
371                        if (!rotateSubStructure) helix->outsideLoop()->set_abs_angle(old[1]);
372                    }
373
374                    exports.refresh = 1;
375                    elem->orientationChanged();
376                }
377            }
378            break;
379        }
380
381        case AWT_MODE_SETROOT:  // set-root-mode / reset angles
382            if (event == AW_Mouse_Press) {
383                if (button == AW_BUTTON_LEFT) { // set root
384                    if (loop) {
385                        sec_root->set_root(loop);
386                        exports.save = 1;
387                    }
388                    else error = "Please click on a loop to change the root";
389                }
390                else { // reset angles
391                    sec_assert(button == AW_BUTTON_RIGHT);
392                    elem->reset_angles();
393                    elem->orientationChanged();
394                    exports.save = 1;
395                }
396            }
397            break;
398
399        case AWT_MODE_FOLD: { // fold/unfold helix
400            if (event == AW_Mouse_Press) {
401                if (button == AW_BUTTON_LEFT) { // fold helix
402                    if (loop) {
403                        const char *helix_nr = sec_root->helixNrAt(abspos);
404                        if (helix_nr) {
405                            const size_t *p = sec_root->getHelixPositions(helix_nr);
406                            error           = sec_root->split_loop(p[0], p[1]+1, p[2], p[3]+1);
407
408                            if (!error) {
409                                sec_root->nail_position(abspos);
410                                exports.save = 1;
411                            }
412                        }
413                        else {
414                            error = GBS_global_string("No helix to fold at position %i", abspos);
415                        }
416                    }
417                    else {
418                        error = "Click on a loop region to fold a helix";
419                    }
420                }
421                else { // unfold helix
422                    sec_assert(button == AW_BUTTON_RIGHT);
423                    if (helix) {
424                        error = sec_root->unsplit_loop(helix->strandToRoot());
425                        if (!error) {
426                            sec_root->nail_position(abspos);
427                            exports.save = 1;
428                        }
429                    }
430                    else {
431                        error = "Right click on a helix to remove it";
432                    }
433                }
434            }
435            break;
436        }
437
438        case AWT_MODE_CURSOR: // set cursor in ARB_EDIT4
439            drag_target_detection(true);
440            if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
441                // sequence position in AWAR_SET_CURSOR_POSITION is starting with 0!
442                aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(abspos);
443            }
444            break;
445
446        case AWT_MODE_PINFO: // display search pattern
447            if (event == AW_Mouse_Press) {
448                if (button == AW_BUTTON_LEFT) {
449                    if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
450                        sec_root->paintSearchPatternStrings(device, abspos, world.xpos()+1, world.ypos());
451                    }
452                    // don't refresh here!
453                }
454                else {
455                    sec_assert(button == AW_BUTTON_RIGHT);
456                    exports.refresh = 1; // simply refresh to remove drawn patterns
457                }
458            }
459            break;
460
461        default: sec_assert(0); break;
462    }
463
464    if (exports.save == 1) exports.refresh = 1;
465    return error;
466}
467
468void SEC_graphic::handle_command(AW_device *device, AWT_graphic_event& event) {
469    if (event.cmd() != AWT_MODE_EDIT && event.cmd() != AWT_MODE_STRETCH) sec_root->set_show_constraints(SEC_NO_TYPE);
470
471    GB_ERROR error = 0;
472    if (event.type() == AW_Keyboard_Press || event.type() == AW_Keyboard_Release) {
473        error = handleKey(event.type(), event.key_modifier(), event.key_code(), event.key_char());
474    }
475    else {
476        if (event.button() != AW_BUTTON_MIDDLE && event.cmd() != AWT_MODE_ZOOM) { // don't handle scroll + zoom
477            static SEC_base *elem   = NULL;
478            static int       abspos = -1;
479
480            bool updateClicked = false;
481
482            if (event.type() == AW_Mouse_Press) updateClicked = true; // initial button-down
483            else if (event.cmd() == AWT_MODE_CURSOR) { // special modes which act identical in click/drag/release
484                updateClicked = true;
485            }
486
487            if (updateClicked) {
488                // store information about clicked SEC_base
489                const AW_clicked_element *clicked = event.best_click();
490                if (clicked) {
491                    elem   = reinterpret_cast<SEC_base*>(clicked->cd1());
492                    abspos = clicked->cd2();
493                }
494                else {
495                    elem   = NULL;
496                }
497            }
498
499            if (elem) {
500                Position world = device->rtransform(event.position());
501                error          = handleMouse(device, event.type(), event.button(), event.cmd(), world, elem, abspos);
502            }
503
504            if (event.type() == AW_Mouse_Release) elem = NULL; // forget last clicked SEC_base
505        }
506    }
507
508    if (error) aw_message(error);
509}
510
511SEC_graphic::SEC_graphic(AW_root *aw_rooti, GBDATA *gb_maini)
512    : update_requested(SEC_UPDATE_RELOAD),
513      load_error(0),
514      disp_device(0),
515      gb_main(gb_maini),
516      aw_root(aw_rooti),
517      sec_root(new SEC_root),
518      gb_struct(0),
519      gb_struct_ref(0),
520      last_saved(0)
521{
522    exports.set_standard_default_padding();
523}
524
525SEC_graphic::~SEC_graphic() {
526    delete sec_root;
527    delete load_error;
528}
529
530static void SEC_structure_changed_cb(GBDATA *gb_seq, SEC_graphic *gfx, GB_CB_TYPE type) {
531    if (type == GB_CB_DELETE) {
532        gfx->gb_struct     = NULL;
533        gfx->gb_struct_ref = NULL;
534
535        gfx->request_update(SEC_UPDATE_RELOAD);
536    }
537    else if (GB_read_clock(gb_seq) > gfx->last_saved) { // not changed by secedit self
538        gfx->request_update(SEC_UPDATE_RELOAD);
539    }
540}
541
542GB_ERROR SEC_graphic::load(GBDATA *, const char *) {
543    //! (Re-)Load secondary structure from database
544
545    sec_assert(sec_root->get_db()->canDisplay()); // need a sequence loaded (to fix bugs in versions < 3)
546    sec_root->nail_cursor();
547
548    GB_transaction ta(gb_main);
549    // first check timestamp, do not load structure that we have saved !!!!
550    if (gb_struct) {
551        if (GB_read_clock(gb_struct) <= last_saved) return NULL;
552    }
553
554    // Reset structure:
555    if (gb_struct) {
556        GB_remove_callback(gb_struct,     GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this)); gb_struct     = NULL;
557        GB_remove_callback(gb_struct_ref, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this)); gb_struct_ref = NULL;
558    }
559
560    request_update(SEC_UPDATE_RECOUNT);
561
562    if (gb_struct) {
563        this->last_saved = GB_read_clock(gb_struct); // mark as loaded
564    }
565
566
567
568    // Setup new structure:
569    GB_ERROR  err    = 0;
570    GBDATA   *gb_ali = 0;
571    {
572        char *helix_name = GBT_get_default_helix(gb_main);
573        char *name       = GBT_readOrCreate_string(gb_main, AWAR_HELIX_NAME, helix_name);
574        sec_assert(name);
575
576        GBDATA *gb_species = GBT_find_SAI(gb_main, name);
577        if (!gb_species) {
578            err = GB_export_errorf("Cannot find helix template SAI '%s'", name);
579        }
580        else {
581            char *ali_name = GBT_get_default_alignment(gb_main);
582            long  ali_len  = GBT_get_alignment_len(gb_main, ali_name);
583
584            if (ali_len < 10) {
585                err = GB_export_errorf("alignment '%s' to short to generate helix", ali_name);
586            }
587            else {
588                gb_ali = GB_search(gb_species, ali_name, GB_FIND);
589                if (!gb_ali) {
590                    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 !!!
591                }
592            }
593            free(ali_name);
594        }
595
596        free(name);
597        free(helix_name);
598    }
599
600    // ------------------------
601    //      read structure
602
603    if (!err) {
604        gb_struct = GB_search(gb_ali, NAME_OF_STRUCT_SEQ, GB_FIND);
605
606        if (gb_struct) {
607            gb_struct_ref = GB_search(gb_ali,  NAME_OF_REF_SEQ,  GB_STRING);
608
609            char *strct = GB_read_string(gb_struct);
610            char *ref = GB_read_string(gb_struct_ref);
611            err = sec_root->read_data(strct, ref);
612            if (err) {
613                err = GBS_global_string("Defect structure in DB (read-error: '%s')", err);
614            }
615#if defined(CHECK_INTEGRITY)
616            else {
617                sec_root->check_integrity(CHECK_STRUCTURE);
618            }
619#endif // CHECK_INTEGRITY
620
621            free(strct);
622            free(ref);
623
624            // on first load init structure toggler:
625            if (!err) {
626                sec_root->get_db()->init_toggler();
627            }
628        }
629        else {
630            err = "no secondary structure was found in your database";
631        }
632
633        if (err) {
634            request_update(SEC_UPDATE_ZOOM_RESET);
635        }
636        else {
637            // in the past one additional NAME_OF_STRUCT_SEQ-entry was added everytime the default bone was created
638            // Fix: delete additional entries
639
640            GBDATA *gb_add = gb_struct;
641            do {
642                sec_assert(GB_has_key(gb_add, NAME_OF_STRUCT_SEQ));
643                gb_add = GB_nextEntry(gb_add);
644                if (gb_add) {
645                    err = GB_delete(gb_add);
646                    printf("* Deleting duplicated entry '%s' (%p)\n", NAME_OF_STRUCT_SEQ, gb_add);
647                }
648            }
649            while (gb_add && !err);
650        }
651    }
652
653    if (!err) {
654        last_saved = GB_read_clock(gb_struct); // mark as loaded
655        request_update(SEC_UPDATE_RECOUNT);
656        if (load_error) { // previous load error?
657            freenull(load_error);
658            request_update(SEC_UPDATE_ZOOM_RESET);
659        }
660    }
661    else {
662        load_error = strdup(err);
663        request_update(SEC_UPDATE_ZOOM_RESET);
664    }
665
666    // set structure-change-callbacks:
667    if(gb_struct)     GB_add_callback(gb_struct,     GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this));
668    if(gb_struct_ref) GB_add_callback(gb_struct_ref, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this));
669
670    return err;
671}
672
673GB_ERROR SEC_graphic::save(GBDATA *, const char *) {
674    //! Save secondary structure to database
675
676    if (!gb_struct) return 0;   // not loaded, so don't save
677    if (!sec_root) return 0;
678
679    char           *data  = sec_root->buildStructureString();
680    GB_transaction  ta(gb_main);
681    GB_ERROR        error = GB_write_string(gb_struct, data);
682    if (!error) {
683        const XString&  xstr     = sec_root->get_xString();
684        const char     *x_string = xstr.get_x_string();
685
686        error = GB_write_string(gb_struct_ref, x_string);
687
688        if (!error && xstr.alignment_too_short()) {
689            aw_message("Your helix needs one gap at end. Please format your alignment!");
690        }
691    }
692    this->last_saved = GB_read_clock(gb_struct);
693    if (error) {
694        error = ta.close(error);
695        aw_message(error);
696    }
697    return NULL;
698}
699
700GB_ERROR SEC_graphic::read_data_from_db(char **data, char **x_string) const {
701    GB_ERROR error = 0;
702
703    sec_assert(gb_struct && gb_struct_ref);
704    *data             = GB_read_string(gb_struct);
705    if (!*data) error = GB_await_error();
706    else {
707        *x_string             = GB_read_string(gb_struct_ref);
708        if (!*x_string) error = GB_await_error();
709    }
710    return error;
711}
712
713GB_ERROR SEC_graphic::write_data_to_db(const char *data, const char *x_string) const {
714    if (!gb_struct) return 0;
715    if (!sec_root) return 0;
716
717    GB_transaction ta(gb_main);
718    GB_ERROR       error = GB_write_string(gb_struct, data);
719    if (!error) {
720        error = GB_write_string(gb_struct_ref, x_string);
721    }
722    last_saved = 0;             // force reload of data
723    return ta.close(error);
724}
725
726int SEC_graphic::check_update(GBDATA *) {
727    GB_transaction ta(gb_main);
728
729    const SEC_db_interface *db = sec_root->get_db();
730
731    if (db && db->canDisplay()) {
732        if (update_requested & SEC_UPDATE_RELOAD) {
733            GB_ERROR error   = load(NULL, NULL); // sets change_flag
734            if (error) {
735                error = ta.close(error);
736                aw_message(error);
737            }
738
739            update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_RELOAD)|SEC_UPDATE_RECOUNT); // clear reload flag
740            exports.refresh  = 1;
741        }
742
743        if (update_requested & SEC_UPDATE_SHOWN_POSITIONS) {
744            sec_root->update_shown_positions();
745            update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_SHOWN_POSITIONS)|SEC_UPDATE_RECOUNT); // clear reload flag
746            exports.refresh  = 1;
747        }
748
749        if (update_requested & SEC_UPDATE_RECOUNT) {
750            sec_root->invalidate_base_positions();
751            sec_root->relayout();
752
753            update_requested = static_cast<SEC_update_request>(update_requested^SEC_UPDATE_RECOUNT); // clear recount flag
754            exports.refresh  = 1;
755        }
756
757        sec_root->perform_autoscroll();
758    }
759
760    int res = 0;
761    if (update_requested & SEC_UPDATE_ZOOM_RESET) {
762        res              = 1; // report zoom reset
763        update_requested = static_cast<SEC_update_request>(update_requested^SEC_UPDATE_ZOOM_RESET); // clear zoom reset flag
764    }
765    return res;
766}
767
768void SEC_graphic::update(GBDATA *) {
769}
770
771void SEC_graphic::show(AW_device *device) {
772    const char *textToDisplay = 0;
773
774    sec_assert(sec_root);
775    sec_root->clear_last_drawed_cursor_position();
776
777    if (sec_root->canDisplay()) {
778        if (sec_root->get_root_loop()) {
779            GB_ERROR paint_error = sec_root->paint(device);
780            if (paint_error) textToDisplay = GBS_global_string("Error: %s", paint_error);
781        }
782        else {
783            if (load_error)     textToDisplay = GBS_global_string("Load error: %s", load_error);
784            else                textToDisplay = "No structure loaded (yet)";
785        }
786    }
787    else {
788        const SEC_db_interface *db = sec_root->get_db();
789
790        if (!db)                textToDisplay = "Not connected to database";
791        else if (!db->helix())  textToDisplay = "No helix info";
792        else                    textToDisplay = "No species selected";
793    }
794
795    if (textToDisplay) { // no structure
796        sec_assert(strchr(textToDisplay, '\n') == 0); // linefeeds do not work here
797        device->text(SEC_GC_ECOLI, textToDisplay, 0, 0, 0, AW_SCREEN, 0);
798        sec_root->set_last_drawed_cursor_position(LineVector(Origin, ZeroVector));
799    }
800}
801
802
Note: See TracBrowser for help on using the repository browser.