source: branches/profile/SECEDIT/SEC_graphic.cxx

Last change on this file was 11143, checked in by westram, 6 years ago
  • unified names of mode-pixmaps and -helpfiles
  • renamed modes (using separate enum values for distinct modes)
  • sorted modes according to their usage in arb applications
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.4 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{
33    AW_gc_manager gc_manager =
34        AW_manage_GC(aww,
35                     scr->get_gc_base_name(),
36                     device,
37                     SEC_GC_LOOP,
38                     SEC_GC_MAX,
39                     AW_GCM_DATA_AREA,
40                     makeWindowCallback(AWT_expose_cb, scr),
41                     false,
42                     "#A1A1A1",
43                     "LOOP$#247900",
44                     "HELIX$#085DAB",
45                     "NONPAIRING HELIX$#D52B69",
46                     "DEFAULT$#000000",
47                     "BONDS$#000000",
48                     "ECOLI POSITION$#FFE223",
49                     "HELIX NUMBERS$#D4D4D4",
50
51                     // Color Ranges to paint SAIs
52                     "+-RANGE 0$#FFFFFF",    "+-RANGE 1$#E0E0E0",    "-RANGE 2$#C0C0C0",
53                     "+-RANGE 3$#A0A0A0",    "+-RANGE 4$#909090",    "-RANGE 5$#808080",
54                     "+-RANGE 6$#808080",    "+-RANGE 7$#505050",    "-RANGE 8$#404040",
55                     "+-RANGE 9$#303030",    "+-CURSOR$#BF1515",     "-MISMATCHES$#FF9AFF",
56
57                     // colors used to Paint search patterns
58                     // (do not change the names of these gcs)
59                     "+-User1$#B8E2F8",          "+-User2$#B8E2F8",         "-Probe$#B8E2F8",
60                     "+-Primer(l)$#A9FE54",      "+-Primer(r)$#A9FE54",     "-Primer(g)$#A9FE54",
61                     "+-Sig(l)$#DBB0FF",         "+-Sig(r)$#DBB0FF",        "-Sig(g)$#DBB0FF",
62
63                     // colors used to paint the skeleton of the structure
64                     "+-SKELETON HELIX${HELIX}", "+-SKELETON LOOP${LOOP}", "-SKELETON NONHELIX${NONPAIRING HELIX}",
65                     NULL);
66
67    return gc_manager;
68}
69
70static GB_ERROR change_constraints(SEC_base *elem) {
71    GB_ERROR  error    = 0;
72
73    GB_CSTR constraint_type = 0;
74    GB_CSTR element_type    = 0;
75
76    switch (elem->getType()) {
77        case SEC_HELIX:
78            constraint_type = "length";
79            element_type    = "helix";
80            break;
81        case SEC_LOOP:
82            constraint_type = "radius";
83            element_type    = "loop";
84            break;
85        default:
86            sec_assert(0);
87            error           = "Illegal element type";
88            break;
89    }
90
91    if (!error) {
92        char *question = GBS_global_string_copy("%s-constraints for %s", constraint_type, element_type);
93        char *answer   = aw_input(question, GBS_global_string("%.2f-%.2f", elem->minSize(), elem->maxSize()));
94
95        while (answer) {
96            char *end;
97            double low = strtod(answer, &end);
98
99            if (end[0]!='-') {
100                error = "Wrong format! Wanted format is 'lower-upper'";
101            }
102            else {
103                double high = strtod(end+1, 0);
104
105                if (low<0 || high<0 || (low && high && low>high)) {
106                    error = "Illegal values";
107                }
108                else {
109#if defined(DEBUG)
110                    sec_assert(!low || !high || low<=high);
111#endif // DEBUG
112                    elem->setConstraints(low, high);
113                    break;
114                }
115            }
116
117            sec_assert(error);
118            aw_message(error);
119
120            char *retry = aw_input(question, answer);
121            free(answer);
122
123            answer = retry;
124        }
125
126        free(answer);
127        free(question);
128    }
129    return error;
130}
131
132
133GB_ERROR SEC_graphic::handleKey(AW_event_type event, AW_key_mod key_modifier, AW_key_code key_code, char key_char) {
134    GB_ERROR error = 0;
135
136    if (event == AW_Keyboard_Press) {
137        int  curpos    = sec_root->get_cursor();
138        int  maxIndex  = sec_root->max_index();
139        bool setCurpos = false;
140        bool handled   = false;
141
142        if (key_modifier == AW_KEYMODE_NONE) {
143            bool wrapped = false;   // avoid deadlock
144
145            switch (key_code) {
146                case AW_KEY_LEFT: {
147                    while (1) {
148                        curpos--;
149                        if (curpos<0) {
150                            curpos  = maxIndex;
151                            if (wrapped) break;
152                            wrapped = true;
153                        }
154                        if (sec_root->shallDisplayPosition(curpos)) {
155                            setCurpos = true;
156                            break;
157                        }
158                    }
159                    break;
160                }
161                case AW_KEY_RIGHT: {
162                    while (1) {
163                        curpos++;
164                        if (curpos > maxIndex) {
165                            curpos  = 0;
166                            if (wrapped) break;
167                            wrapped = true;
168                        }
169                        if (sec_root->shallDisplayPosition(curpos)) {
170                            setCurpos = true;
171                            break;
172                        }
173                    }
174                    break;
175                }
176                case AW_KEY_ASCII: {
177                    const char *toggle_awar = 0;
178                    int         val_max     = 1;
179
180                    switch (key_char) {
181                        case 'b': toggle_awar = AWAR_SECEDIT_SHOW_BONDS; val_max = 2; break;
182                        case 'B': toggle_awar = AWAR_SECEDIT_HIDE_BASES; break;
183                        case 'k': toggle_awar = AWAR_SECEDIT_SHOW_STR_SKELETON; break;
184
185                        case 'c': toggle_awar = AWAR_SECEDIT_SHOW_CURPOS; val_max = 3; break;
186                        case 'h': toggle_awar = AWAR_SECEDIT_SHOW_HELIX_NRS; break;
187                        case 'e': toggle_awar = AWAR_SECEDIT_SHOW_ECOLI_POS; break;
188
189                        case 's': toggle_awar = AWAR_SECEDIT_DISPLAY_SAI; break;
190                        case 'r': toggle_awar = AWAR_SECEDIT_DISPLAY_SEARCH; break;
191
192                        case 'E': toggle_awar = AWAR_SECEDIT_DISPPOS_ECOLI; break;
193                        case 'H': toggle_awar = AWAR_SECEDIT_DISPPOS_BINDING; break;
194
195#if defined(DEBUG)
196                        case 'd': toggle_awar = AWAR_SECEDIT_SHOW_DEBUG; break;
197#endif // DEBUG
198
199                        case 't':
200                            error   = sec_root->get_db()->structure()->next();
201                            handled = true;
202                            break;
203                    }
204
205                    if (toggle_awar) {
206                        AW_awar *awar = aw_root->awar(toggle_awar);
207                        int      val  = awar->read_int()+1;
208
209                        if (val>val_max) val = 0;
210                        awar->write_int(val);
211
212                        handled = true;
213                    }
214
215                    break;
216                }
217                default:
218                    break;
219            }
220        }
221
222        if (setCurpos) {
223            aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(curpos);
224            handled = true;
225        }
226
227        if (!handled) { // pass unhandled key events to EDIT4
228            AW_event faked_event;
229
230            memset((char*)&faked_event, 0, sizeof(faked_event));
231
232            faked_event.type        = event;
233            faked_event.keymodifier = key_modifier;
234            faked_event.keycode     = key_code;
235            faked_event.character   = key_char;
236
237            sec_root->host().forward_event(&faked_event);
238        }
239    }
240
241    return error;
242}
243
244GB_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) {
245    GB_ERROR error = 0;
246
247    // ------------------------------------------
248    //      handle element dependent actions
249
250    if (elem) {
251        static Position start;      // click position on mouse down
252
253        Position fixpoint = elem->get_fixpoint(); // of strand or loop
254
255        SEC_loop  *loop  = 0;
256        SEC_helix *helix = 0;
257
258        if (elem->getType() == SEC_HELIX) helix = static_cast<SEC_helix*>(elem);
259        else {
260            sec_assert(elem->getType() == SEC_LOOP);
261            loop = static_cast<SEC_loop*>(elem);
262        }
263
264        if (event == AW_Mouse_Press) start = world; // store start position
265
266        switch (cmd) {
267            case AWT_MODE_STRETCH: { // change constraints with mouse
268                static double start_size; // helix/loop size at start click
269
270                switch (event) {
271                    case AW_Mouse_Press:
272                        if (button == AW_BUTTON_LEFT) {
273                            start_size = elem->drawnSize();
274                            sec_root->set_show_constraints(elem->getType());
275                            exports.refresh = 1;
276                        }
277                        else { // right button -> reset constraints
278                            elem->setConstraints(0, 0);
279                            elem->sizeChanged();
280                            exports.refresh = 1;
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            case AWT_MODE_CURSOR:
438            case AWT_MODE_PINFO:
439                elem = 0; // handle element-independent
440                break;
441            default: sec_assert(0); break;
442        }
443    }
444
445    // ---------------------------------------
446    //      action independent of element
447
448    if (!elem) {
449        switch (cmd) {
450            case AWT_MODE_CURSOR: // set cursor in ARB_EDIT4
451                if (event == AW_Mouse_Press) {
452                    if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
453                        // sequence position in AWAR_SET_CURSOR_POSITION is starting with 0!
454                        aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(abspos);
455                    }
456                }
457                break;
458
459            case AWT_MODE_PINFO: // display search pattern
460                if (event == AW_Mouse_Press) {
461                    if (button == AW_BUTTON_LEFT) {
462                        if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
463                            sec_root->paintSearchPatternStrings(device, abspos, world.xpos()+1, world.ypos());
464                        }
465                        // don't refresh here!
466                    }
467                    else {
468                        sec_assert(button == AW_BUTTON_RIGHT);
469                        exports.refresh = 1; // simply refresh to remove drawn patterns
470                    }
471                }
472                break;
473
474            default:
475                break;
476        }
477        return 0; // no error
478    }
479
480    if (exports.save == 1) exports.refresh = 1;
481    return error;
482}
483
484void SEC_graphic::handle_command(AW_device *device, AWT_graphic_event& event) {
485    if (event.cmd() != AWT_MODE_EDIT && event.cmd() != AWT_MODE_STRETCH) sec_root->set_show_constraints(SEC_NO_TYPE);
486
487    GB_ERROR error = 0;
488    if (event.type() == AW_Keyboard_Press || event.type() == AW_Keyboard_Release) {
489        error = handleKey(event.type(), event.key_modifier(), event.key_code(), event.key_char());
490    }
491    else {
492        if (event.button() != AW_BUTTON_MIDDLE && event.cmd() != AWT_MODE_ZOOM) { // don't handle scroll + zoom
493            const AW_clicked_element *clicked = event.best_click();
494            if (clicked) {
495                SEC_base *elem   = reinterpret_cast<SEC_base*>(clicked->cd1());
496                int       abspos = clicked->cd2();
497
498                Position world = device->rtransform(event.position());
499                error = handleMouse(device, event.type(), event.button(), event.cmd(), world, elem, abspos);
500            }
501        }
502    }
503
504    if (error) aw_message(error);
505}
506
507SEC_graphic::SEC_graphic(AW_root *aw_rooti, GBDATA *gb_maini)
508    : update_requested(SEC_UPDATE_RELOAD),
509      load_error(0),
510      disp_device(0),
511      gb_main(gb_maini),
512      aw_root(aw_rooti),
513      sec_root(new SEC_root),
514      gb_struct(0),
515      gb_struct_ref(0),
516      last_saved(0)
517{
518    exports.set_standard_default_padding();
519}
520
521SEC_graphic::~SEC_graphic() {
522    delete sec_root;
523    delete load_error;
524}
525
526static void SEC_structure_changed_cb(GBDATA *gb_seq, SEC_graphic *gfx, GB_CB_TYPE type) {
527    if (type == GB_CB_DELETE) {
528        gfx->gb_struct     = NULL;
529        gfx->gb_struct_ref = NULL;
530
531        gfx->request_update(SEC_UPDATE_RELOAD);
532    }
533    else if (GB_read_clock(gb_seq) > gfx->last_saved) { // not changed by secedit self
534        gfx->request_update(SEC_UPDATE_RELOAD);
535    }
536}
537
538GB_ERROR SEC_graphic::load(GBDATA *, const char *, AW_CL, AW_CL) {
539    //! (Re-)Load secondary structure from database
540
541    sec_assert(sec_root->get_db()->canDisplay()); // need a sequence loaded (to fix bugs in versions < 3)
542    sec_root->nail_cursor();
543
544    GB_transaction ta(gb_main);
545    // first check timestamp, do not load structure that we have saved !!!!
546    if (gb_struct) {
547        if (GB_read_clock(gb_struct) <= last_saved) return NULL;
548    }
549
550    // Reset structure:
551    if (gb_struct) {
552        GB_remove_callback(gb_struct,     GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this)); gb_struct     = NULL;
553        GB_remove_callback(gb_struct_ref, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this)); gb_struct_ref = NULL;
554    }
555
556    request_update(SEC_UPDATE_RECOUNT);
557
558    if (gb_struct) {
559        this->last_saved = GB_read_clock(gb_struct); // mark as loaded
560    }
561
562
563
564    // Setup new structure:
565    GB_ERROR  err    = 0;
566    GBDATA   *gb_ali = 0;
567    {
568        char *helix_name = GBT_get_default_helix(gb_main);
569        char *name       = GBT_readOrCreate_string(gb_main, AWAR_HELIX_NAME, helix_name);
570        sec_assert(name);
571
572        GBDATA *gb_species = GBT_find_SAI(gb_main, name);
573        if (!gb_species) {
574            err = GB_export_errorf("Cannot find helix template SAI '%s'", name);
575        }
576        else {
577            char *ali_name = GBT_get_default_alignment(gb_main);
578            long  ali_len  = GBT_get_alignment_len(gb_main, ali_name);
579
580            if (ali_len < 10) {
581                err = GB_export_errorf("alignment '%s' to short to generate helix", ali_name);
582            }
583            else {
584                gb_ali = GB_search(gb_species, ali_name, GB_FIND);
585                if (!gb_ali) {
586                    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 !!!
587                }
588            }
589            free(ali_name);
590        }
591
592        free(name);
593        free(helix_name);
594    }
595
596    // ------------------------
597    //      read structure
598
599    if (!err) {
600        gb_struct = GB_search(gb_ali, NAME_OF_STRUCT_SEQ, GB_FIND);
601
602        if (gb_struct) {
603            gb_struct_ref = GB_search(gb_ali,  NAME_OF_REF_SEQ,  GB_STRING);
604
605            char *strct = GB_read_string(gb_struct);
606            char *ref = GB_read_string(gb_struct_ref);
607            err = sec_root->read_data(strct, ref);
608            if (err) {
609                err = GBS_global_string("Defect structure in DB (read-error: '%s')", err);
610            }
611#if defined(CHECK_INTEGRITY)
612            else {
613                sec_root->check_integrity(CHECK_STRUCTURE);
614            }
615#endif // CHECK_INTEGRITY
616
617            free(strct);
618            free(ref);
619
620            // on first load init structure toggler:
621            if (!err) {
622                sec_root->get_db()->init_toggler();
623            }
624        }
625        else {
626            err = "no secondary structure was found in your database";
627        }
628
629        if (err) {
630            request_update(SEC_UPDATE_ZOOM_RESET);
631        }
632        else {
633            // in the past one additional NAME_OF_STRUCT_SEQ-entry was added everytime the default bone was created
634            // Fix: delete additional entries
635
636            GBDATA *gb_add = gb_struct;
637            do {
638                sec_assert(GB_has_key(gb_add, NAME_OF_STRUCT_SEQ));
639                gb_add = GB_nextEntry(gb_add);
640                if (gb_add) {
641                    err = GB_delete(gb_add);
642                    printf("* Deleting duplicated entry '%s' (%p)\n", NAME_OF_STRUCT_SEQ, gb_add);
643                }
644            }
645            while (gb_add && !err);
646        }
647    }
648
649    if (!err) {
650        last_saved = GB_read_clock(gb_struct); // mark as loaded
651        request_update(SEC_UPDATE_RECOUNT);
652        if (load_error) { // previous load error?
653            freenull(load_error);
654            request_update(SEC_UPDATE_ZOOM_RESET);
655        }
656    }
657    else {
658        load_error = strdup(err);
659        request_update(SEC_UPDATE_ZOOM_RESET);
660    }
661
662    // set structure-change-callbacks:
663    if(gb_struct)     GB_add_callback(gb_struct,     GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this));
664    if(gb_struct_ref) GB_add_callback(gb_struct_ref, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this));
665
666    return err;
667}
668
669GB_ERROR SEC_graphic::save(GBDATA *, const char *, AW_CL, AW_CL) {
670    //! Save secondary structure to database
671
672    if (!gb_struct) return 0;   // not loaded, so don't save
673    if (!sec_root) return 0;
674
675    char           *data  = sec_root->buildStructureString();
676    GB_transaction  ta(gb_main);
677    GB_ERROR        error = GB_write_string(gb_struct, data);
678    if (!error) {
679        const XString&  xstr     = sec_root->get_xString();
680        const char     *x_string = xstr.get_x_string();
681
682        error = GB_write_string(gb_struct_ref, x_string);
683
684        if (!error && xstr.alignment_too_short()) {
685            aw_message("Your helix needs one gap at end. Please format your alignment!");
686        }
687    }
688    this->last_saved = GB_read_clock(gb_struct);
689    if (error) {
690        error = ta.close(error);
691        aw_message(error);
692    }
693    return NULL;
694}
695
696GB_ERROR SEC_graphic::read_data_from_db(char **data, char **x_string) const {
697    GB_ERROR error = 0;
698
699    sec_assert(gb_struct && gb_struct_ref);
700    *data             = GB_read_string(gb_struct);
701    if (!*data) error = GB_await_error();
702    else {
703        *x_string             = GB_read_string(gb_struct_ref);
704        if (!*x_string) error = GB_await_error();
705    }
706    return error;
707}
708
709GB_ERROR SEC_graphic::write_data_to_db(const char *data, const char *x_string) const {
710    if (!gb_struct) return 0;
711    if (!sec_root) return 0;
712
713    GB_transaction ta(gb_main);
714    GB_ERROR       error = GB_write_string(gb_struct, data);
715    if (!error) {
716        error = GB_write_string(gb_struct_ref, x_string);
717    }
718    last_saved = 0;             // force reload of data
719    return ta.close(error);
720}
721
722int SEC_graphic::check_update(GBDATA *) {
723    GB_transaction ta(gb_main);
724
725    const SEC_db_interface *db = sec_root->get_db();
726
727    if (db && db->canDisplay()) {
728        if (update_requested & SEC_UPDATE_RELOAD) {
729            GB_ERROR error   = load(0, 0, 0, 0); // sets change_flag
730            if (error) {
731                error = ta.close(error);
732                aw_message(error);
733            }
734
735            update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_RELOAD)|SEC_UPDATE_RECOUNT); // clear reload flag
736            exports.refresh  = 1;
737        }
738
739        if (update_requested & SEC_UPDATE_SHOWN_POSITIONS) {
740            sec_root->update_shown_positions();
741            update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_SHOWN_POSITIONS)|SEC_UPDATE_RECOUNT); // clear reload flag
742            exports.refresh  = 1;
743        }
744
745        if (update_requested & SEC_UPDATE_RECOUNT) {
746            sec_root->invalidate_base_positions();
747            sec_root->relayout();
748
749            update_requested = static_cast<SEC_update_request>(update_requested^SEC_UPDATE_RECOUNT); // clear recount flag
750            exports.refresh  = 1;
751        }
752
753        sec_root->perform_autoscroll();
754    }
755
756    int res = 0;
757    if (update_requested & SEC_UPDATE_ZOOM_RESET) {
758        res              = 1; // report zoom reset
759        update_requested = static_cast<SEC_update_request>(update_requested^SEC_UPDATE_ZOOM_RESET); // clear zoom reset flag
760    }
761    return res;
762}
763
764void SEC_graphic::update(GBDATA *) {
765}
766
767void SEC_graphic::show(AW_device *device) {
768    const char *textToDisplay = 0;
769
770    sec_assert(sec_root);
771    sec_root->clear_last_drawed_cursor_position();
772
773    if (sec_root->canDisplay()) {
774        if (sec_root->get_root_loop()) {
775            GB_ERROR paint_error = sec_root->paint(device);
776            if (paint_error) textToDisplay = GBS_global_string("Error: %s", paint_error);
777        }
778        else {
779            if (load_error)     textToDisplay = GBS_global_string("Load error: %s", load_error);
780            else                textToDisplay = "No structure loaded (yet)";
781        }
782    }
783    else {
784        const SEC_db_interface *db = sec_root->get_db();
785
786        if (!db)                textToDisplay = "Not connected to database";
787        else if (!db->helix())  textToDisplay = "No helix info";
788        else                    textToDisplay = "No species selected";
789    }
790
791    if (textToDisplay) { // no structure
792        sec_assert(strchr(textToDisplay, '\n') == 0); // linefeeds do not work here
793        device->text(SEC_GC_ECOLI, textToDisplay, 0, 0, 0, AW_SCREEN, 0);
794        sec_root->set_last_drawed_cursor_position(LineVector(Origin, ZeroVector));
795    }
796}
797
798void SEC_graphic::info(AW_device */*device*/, AW_pos /*x*/, AW_pos /*y*/, AW_clicked_line */*cl*/, AW_clicked_text */*ct*/) {
799    aw_message("INFO MESSAGE");
800}
801
802
Note: See TracBrowser for help on using the repository browser.