source: branches/alilink/SECEDIT/SEC_main.cxx

Last change on this file was 17080, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.9 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : SEC_main.cxx                                      //
4//   Purpose   : main part of SECEDIT                              //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "SEC_root.hxx"
12#include "SEC_graphic.hxx"
13#include "SEC_helix.hxx"
14#include "SEC_drawn_pos.hxx"
15#include "SEC_toggle.hxx"
16
17#include <BufferedFileReader.h>
18
19#include <aw_awars.hxx>
20#include <aw_preset.hxx>
21#include <aw_file.hxx>
22#include <aw_msg.hxx>
23#include <aw_root.hxx>
24#include <aw_question.hxx>
25
26#include <mode_text.h>
27
28#include <arb_file.h>
29#include <awt_config_manager.hxx>
30#include <ad_cb_prot.h>
31
32#ifndef sec_assert // happens in NDEBUG mode
33#define sec_assert(cond) arb_assert(cond)
34#endif
35
36void SEC_root::invalidate_base_positions() {
37    if (root_loop) {
38        SEC_base_part *start_part = root_loop->get_fixpoint_strand();
39        SEC_base_part *part       = start_part;
40
41        do {
42            part->get_region()->invalidate_base_count();
43            part = part->next();
44        }
45        while (part != start_part);
46    }
47}
48
49// ------------------------------------------------------
50//      auto-scrolling (triggered by structure self)
51
52void SEC_root::nail_position(size_t absPos) {
53    if (drawnPositions) {
54        nailedAbsPos = absPos;
55        drawnAbsPos  = *drawnPositions->drawn_at(absPos);
56    }
57}
58
59void SEC_root::nail_cursor() { // re-position on cursor
60    if (cursorAbsPos >= 0) {
61        if (drawnPositions && !drawnPositions->empty()) {
62            size_t abs;
63            drawnAbsPos  = drawnPositions->drawn_after(cursorAbsPos-1, &abs);
64            nailedAbsPos = abs;
65        }
66    }
67}
68
69void SEC_root::add_autoscroll(const Vector& scroll) {
70    if (autoscroll) *autoscroll += scroll;
71    else autoscroll              = new Vector(scroll);
72}
73
74bool SEC_root::perform_autoscroll() {
75    bool        scrolled = false;
76    AWT_canvas *canvas   = db->canvas();
77
78    if (canvas && (nailedAbsPos != -1 || autoscroll)) {
79        AW_device *device = canvas->aww->get_device(AW_MIDDLE_AREA);
80
81        if (nailedAbsPos != -1) {
82            {
83                int     absPos = nailedAbsPos;
84                Vector *scroll = autoscroll;
85
86                // avoid endless recursion:
87                nailedAbsPos = -1;
88                autoscroll   = NULp;
89
90#if defined(WARN_TODO)
91#warning make the refresh invisible
92#endif
93                {
94                    // hack: we may be inside or outside sync_DB_model_and_view() here (be permissive about flags here)
95                    LocallyModify<int> allow_flag_modify(canvas->gfx->exports.get_modifying_flag_ref(), -1);
96                    canvas->gfx->exports.update_display_as_requested(canvas, true);
97                }
98
99                nailedAbsPos = absPos;
100                autoscroll   = scroll;
101            }
102            const Position *newPos = drawnPositions->drawn_at(nailedAbsPos);
103            if (newPos) {
104                Vector old2new(drawnAbsPos, *newPos);
105#if defined(DEBUG) && 0
106                printf("drawnAbsPos=%.2f/%.2f newPos=%.2f/%.2f old2new=%.2f/%.2f\n",
107                       drawnAbsPos.xpos(), drawnAbsPos.ypos(),
108                       newPos->xpos(), newPos->ypos(),
109                       old2new.x(), old2new.y());
110#endif // DEBUG
111                add_autoscroll(old2new);
112            }
113            nailedAbsPos = -1;
114        }
115        if (autoscroll) {
116            canvas->init_device(device); // loads correct zoom
117            Vector screen_scroll = device->transform(*autoscroll);
118
119#if defined(DEBUG) && 0
120            printf("autoscroll=%.2f/%.2f screen_scroll=%.2f/%.2f\n",
121                   autoscroll->x(), autoscroll->y(),
122                   screen_scroll.x(), screen_scroll.y());
123#endif // DEBUG
124
125            delete autoscroll;
126            autoscroll = NULp;
127
128            device->clear(-1);
129            {
130                // hack: we may be inside sync_DB_model_and_view() here, but scroll() instanciates an AWT_auto_refresh. Permit!
131                LocallyModify<int> allow_flag_modify(canvas->gfx->exports.get_modifying_flag_ref(), 0);
132                canvas->scroll(screen_scroll);
133            }
134            scrolled = true;
135        }
136    }
137    return scrolled;
138}
139// --------------------------------------------------------------------------------
140
141void SEC_root::position_cursor(bool toCenter, bool evenIfVisible) {
142    // centers the cursor in display (or scrolls it into view)
143    // if 'evenIfVisible' is true, always do it, otherwise only if not (fully) visible
144
145    const LineVector& cursorLine = get_last_drawed_cursor_position();
146    sec_assert(cursorLine.valid());
147
148    AWT_canvas *scr    = db->canvas();
149    AW_device  *device = scr->aww->get_device(AW_MIDDLE_AREA);
150
151    Rectangle cursor(device->transform(cursorLine));
152    Rectangle screen(device->get_area_size(), INCLUSIVE_OUTLINE);
153
154    if (evenIfVisible || !screen.contains(cursor)) {
155        if (!toCenter) {
156            if (perform_autoscroll()) {
157                cursor = Rectangle(device->transform(cursorLine));
158                if (!screen.contains(cursor)) {
159                    toCenter = true;
160                }
161            }
162            else { // if autoscroll didn't work
163                toCenter = true; // center cursor
164            }
165        }
166
167        if (toCenter) {
168            AWT_auto_refresh allowed_on(scr);
169            Vector           scroll(cursor.centroid(), screen.centroid());
170
171#if defined(DEBUG) && 1
172            printf("Auto-scroll: scroll = (%f, %f) [Center cursor]\n", scroll.x(), scroll.y());
173#endif
174            scr->scroll(-scroll);
175            scr->request_refresh();
176        }
177    }
178}
179
180static void SEC_toggle_cb(AW_window*, const SEC_db_interface *db) {
181    AWT_auto_refresh allowed_on(db->canvas());
182    GB_ERROR error = db->structure()->next();
183    if (error) aw_message(error);
184    db->canvas()->request_refresh();
185}
186
187static void SEC_center_cb(AW_window *, SEC_root *root) {
188    root->position_cursor(true, true);
189}
190
191static void SEC_fit_window_cb(AW_window*, const SEC_db_interface *db) {
192    AWT_auto_refresh allowed_on(db->canvas());
193    db->canvas()->request_zoom_reset();
194}
195
196static void sec_mode_event(AW_window *aws, SEC_root *sec_root, AWT_COMMAND_MODE mode) {
197    const char *text = NULp;
198    switch (mode) {
199        case AWT_MODE_ZOOM: text = MODE_TEXT_STANDARD_ZOOMMODE(); break;
200
201        case AWT_MODE_EDIT:   text = MODE_TEXT_1BUTTON("CONSTRAINT", "modify constraint");       break;
202        case AWT_MODE_CURSOR: text = MODE_TEXT_1BUTTON("SET CURSOR", "set cursor in ARB_EDIT4"); break;
203
204        case AWT_MODE_FOLD:    text = MODE_TEXT_2BUTTONS("FOLD",       "fold helix",                              "unfold helix");                  break;
205        case AWT_MODE_SETROOT: text = MODE_TEXT_2BUTTONS("SET ROOT",   "set logical center of structure",         "reset angles on sub-structure"); break;
206        case AWT_MODE_ROTATE:  text = MODE_TEXT_2BUTTONS("ROTATE",     "rotate helix/loop",                       "same w/o substructure");         break;
207        case AWT_MODE_STRETCH: text = MODE_TEXT_2BUTTONS("STRETCH",    "click and drag to stretch helices/loops", "reset");                         break;
208        case AWT_MODE_PINFO:   text = MODE_TEXT_2BUTTONS("PROBE INFO", "display PROBE information",               "undisplay");                     break;
209
210        default: text = no_mode_text_defined(); break;
211    }
212
213    sec_root->set_show_constraints((mode == AWT_MODE_STRETCH || mode == AWT_MODE_EDIT)
214                                   ? SEC_ANY_TYPE
215                                   : SEC_NO_TYPE);
216
217    sec_assert(strlen(text) < AWAR_FOOTER_MAX_LEN); // text too long!
218
219    aws->get_root()->awar(AWAR_FOOTER)->write_string(text);
220
221    AWT_canvas       *scr = sec_root->get_db()->canvas();
222    AWT_auto_refresh  allowed_on(scr);
223    scr->set_mode(mode);
224    scr->request_refresh();
225}
226
227static void SEC_undo_cb(AW_window *, const SEC_db_interface *db, GB_UNDO_TYPE undo_type) {
228    GBDATA   *gb_main = db->gbmain();
229    GB_ERROR  error   = GB_undo(gb_main, undo_type);
230    if (error) {
231        aw_message(error);
232    }
233    else {
234        GB_begin_transaction(gb_main);
235        GB_commit_transaction(gb_main);
236        AWT_auto_refresh allowed_on(db->canvas());
237        db->canvas()->request_refresh();
238    }
239}
240
241// --------------------------------------------------------------------------------
242
243#define ASS       "ARB secondary structure v1" // don't change version here!
244#define ASS_START "[" ASS "]"
245#define ASS_EOS   "[end of structure]"
246#define ASS_EOF   "[end of " ASS "]"
247
248static void export_structure_to_file(AW_window *, const SEC_db_interface *db) {
249    GB_ERROR  error    = NULp;
250    SEC_root *sec_root = db->secroot();
251
252    if (!sec_root->get_root_loop()) {
253        error = "Please select a species (to display structure once) before saving";
254    }
255    else {
256        AW_root *aw_root  = db->awroot();
257        char    *filename = aw_root->awar(AWAR_SECEDIT_SAVEDIR"/file_name")->read_string();
258        FILE    *out      = fopen(filename, "wt");
259
260        if (out) {
261
262            fputs(ASS_START, out); fputc('\n', out);
263
264            char *strct = sec_root->buildStructureString();
265            fputs(strct, out);
266            delete [] strct;
267
268            fputs(ASS_EOS, out); fputc('\n', out);
269
270            const XString& xstr     = sec_root->get_xString();
271            const char    *x_string = xstr.get_x_string();
272
273            sec_assert(xstr.get_x_string_length() == strlen(x_string));
274
275            char *foldInfo = SEC_xstring_to_foldedHelixList(x_string, xstr.get_x_string_length(), sec_root->get_helixDef(), error);
276            if (foldInfo) {
277                fprintf(out, "foldedHelices=%s\n", foldInfo);
278                free(foldInfo);
279            }
280
281            fputs(ASS_EOF, out); fputc('\n', out);
282            fclose(out);
283
284            if (error) GB_unlink_or_warn(filename, &error);
285        }
286        else {
287            error = GB_export_errorf("Can't write secondary structure to '%s'", filename);
288        }
289
290        free(filename);
291    }
292    if (error) aw_message(error);
293}
294
295inline GB_ERROR expectedError(const char *expected) {
296    return GBS_global_string("expected '%s'", expected);
297}
298inline GB_ERROR expectContent(LineReader& file, const char *expected) {
299    GB_ERROR error = NULp;
300    string   line;
301    if (!file.getLine(line) || line != expected) {
302        error = expectedError(expected);
303    }
304    return error;
305}
306
307static string scanToken(LineReader& file, string& rest, GB_ERROR& error) {
308    string line;
309    string token;
310
311    sec_assert(!error);
312
313    if (file.getLine(line)) {
314        size_t equal = line.find('=');
315
316        if (equal == string::npos) {
317            error = "Expected '='";
318        }
319        else {
320            token = line.substr(0, equal);
321            rest  = line.substr(equal+1);
322        }
323    }
324    else {
325        error = "Unexpected EOF";
326    }
327    return token;
328}
329
330static GB_ERROR expectToken(LineReader& file, const char *token, string& content) {
331    GB_ERROR error      = NULp;
332    string   foundToken = scanToken(file, content, error);
333    if (foundToken != token) error = expectedError(token);
334    return error;
335}
336
337static void import_structure_from_file(AW_window *, const SEC_db_interface *db) {
338    GB_ERROR  error = NULp;
339    SEC_root *root  = db->secroot();
340
341    if (!root->has_xString()) {
342        error = "Please select a species in EDIT4";
343    }
344    else {
345        char        *filename = db->awroot()->awar(AWAR_SECEDIT_SAVEDIR"/file_name")->read_string();
346        FILE        *in       = fopen(filename, "rt"); // closed by FileBuffer
347
348        if (!in) {
349            error = GB_export_errorf("Can't open file '%s'", filename);
350        }
351        else {
352            BufferedFileReader file(filename, in);
353            error = expectContent(file, ASS_START);
354
355            string structure;
356            while (!error) {
357                string line;
358                if (!file.getLine(line)) error = expectedError(ASS_EOS);
359                else {
360                    if (line == ASS_EOS) break;
361                    structure += line + "\n";
362                }
363            }
364
365            char *x_string = NULp;
366            if (!error) {
367                string content;
368                string token = scanToken(file, content, error);
369
370                if (!error) {
371                    // we already have an existing xstring, use it's length for new xstring
372                    size_t xlength = root->get_xString().getLength();
373
374                    if (token == "foldedHelices") { // new version
375                        x_string = SEC_foldedHelixList_to_xstring(content.c_str(), xlength, root->get_helixDef(), error); // sets error
376                    }
377                    else if (token == "no of helices") { // old version
378                        int saved_helices = atoi(content.c_str());
379
380                        error             = expectToken(file, "length of xstring", content); // ignore, using curr value
381                        if (!error) error = expectToken(file, "xstring_rel_helix", content);
382                        if (!error) {
383                            int helices_in_db;
384                            x_string = old_decode_xstring_rel_helix(content.c_str(), xlength, root->get_helixDef(), &helices_in_db);
385                            if (helices_in_db != saved_helices) {
386                                error = GBS_global_string("Number of helices does not match (file=%i, db=%i).\n"
387                                                          "Saving the structure again from another DB with correct number of helices will work around this restriction.",
388                                                          saved_helices, helices_in_db);
389                            }
390                        }
391                    }
392                    else {
393                        error = "Expected 'foldedHelices' or 'no of helices'";
394                    }
395                }
396                if (!error) error = expectContent(file, ASS_EOF);
397            }
398
399            if (error) {
400                error = GBS_static_string(file.lineError(error).c_str());
401            }
402            else {
403                AWT_auto_refresh allowed_on(db->canvas());
404                db->graphic()->write_data_to_db(structure.c_str(), x_string);
405                db->canvas()->request_refresh();
406            }
407            free(x_string);
408        }
409        free(filename);
410    }
411    if (error) aw_message(error);
412}
413
414#undef ASS
415#undef ASS_START
416#undef ASS_EOS
417#undef ASS_EOF
418
419static AW_window *SEC_importExport(AW_root *root, bool export_to_file, const SEC_db_interface *db) {
420    AW_window_simple *aws = new AW_window_simple;
421
422    if (export_to_file) aws->init(root, "export_secondary_structure", "Export secondary structure to ...");
423    else                aws->init(root, "import_secondary_structure", "Import secondary structure from ...");
424
425    aws->load_xfig("sec_imexport.fig");
426
427    aws->at("close");
428    aws->callback(AW_POPDOWN);
429    aws->create_button("CLOSE", "CLOSE", "C");
430
431    aws->at("help");
432    aws->callback(makeHelpCallback("sec_imexport.hlp"));
433    aws->create_button("HELP", "HELP", "H");
434
435    AW_create_standard_fileselection(aws, AWAR_SECEDIT_SAVEDIR);
436
437    aws->at("save");
438    if (export_to_file) {
439        aws->callback(makeWindowCallback(export_structure_to_file, db));
440        aws->create_button("EXPORT", "EXPORT", "E");
441    }
442    else {
443        aws->callback(makeWindowCallback(import_structure_from_file, db));
444        aws->create_button("IMPORT", "IMPORT", "I");
445    }
446
447    return aws;
448}
449
450static void SEC_rename_structure(AW_window*, const SEC_db_interface *db) {
451    SEC_structure_toggler *structure = db->structure();
452
453    char *new_name = aw_input("Rename structure", "New name", structure->name());
454    if (new_name) {
455        structure->setName(new_name);
456        free(new_name);
457        AWT_auto_refresh allowed_on(db->canvas());
458        db->canvas()->request_refresh();
459    }
460}
461
462static void SEC_new_structure(AW_window*, const SEC_db_interface *db) {
463    SEC_structure_toggler *structure = db->structure();
464
465    if (!structure) {
466        db->init_toggler();
467        structure = db->structure();
468        sec_assert(structure);
469    }
470
471    GB_ERROR error = NULp;
472    bool     done  = false;
473
474    switch (aw_question(NULp, "Create new structure?", "Default bone,Copy current,Abort")) {
475        case 0:                 // default bone
476            error = structure->copyTo("Default");
477            if (!error) {
478                db->secroot()->create_default_bone();
479                db->graphic()->save_to_DB(NULp, NULp);
480                done = true;
481            }
482            break;
483
484        case 1:                 // copy current
485            error = structure->copyTo(GBS_global_string("%s(copy)", structure->name()));
486            done  = !error;
487            break;
488
489        case 2:                 // abort
490            break;
491    }
492
493    if (done) {
494        {
495            AWT_auto_refresh allowed_on(db->canvas());
496            db->canvas()->request_zoom_reset();
497        }
498        SEC_rename_structure(NULp, db);
499    }
500}
501
502static void SEC_delete_structure(AW_window*, const SEC_db_interface *db) {
503    SEC_structure_toggler *structure = db->structure();
504
505    if (structure->getCount()>1) {
506        if (aw_ask_sure("delete_sec_structure", GBS_global_string("Are you sure to delete structure '%s'?", structure->name()))) {
507            AWT_auto_refresh allowed_on(db->canvas());
508            GB_ERROR error = structure->remove();
509            if (error) aw_message(error);
510            db->canvas()->request_refresh();
511        }
512    }
513    else {
514        aw_message("You cannot delete the last structure");
515    }
516}
517
518enum SyncColors {
519    COLOR_SYNC_SEARCH = 1,
520    COLOR_SYNC_RANGE  = 2,
521    COLOR_SYNC_REST   = 4,
522
523    COLOR_SYNC_ALL = (COLOR_SYNC_SEARCH|COLOR_SYNC_RANGE|COLOR_SYNC_REST),
524};
525
526static void SEC_sync_colors(AW_window *aww, SyncColors which) {
527    // overwrites color settings with those from EDIT4
528
529    if (which & COLOR_SYNC_SEARCH) {
530        AW_copy_GC_colors(aww->get_root(), "ARB_EDIT4", "ARB_SECEDIT",
531                          "User1",   "User2",   "Probe",
532                          "Primerl", "Primerr", "Primerg",
533                          "Sigl",    "Sigr",    "Sigg",
534                          "MISMATCHES",
535                          NULp);
536    }
537    if (which & COLOR_SYNC_RANGE) {
538        AW_copy_GC_colors(aww->get_root(), "ARB_EDIT4", "ARB_SECEDIT",
539                          "RANGE_0", "RANGE_1", "RANGE_2",
540                          "RANGE_3", "RANGE_4", "RANGE_5",
541                          "RANGE_6", "RANGE_7", "RANGE_8",
542                          "RANGE_9",
543                          NULp);
544    }
545    if (which & COLOR_SYNC_REST) {
546        AW_copy_GC_colors(aww->get_root(), "ARB_EDIT4", "ARB_SECEDIT",
547                          "CURSOR",
548                          NULp);
549    }
550}
551
552static AW_window *SEC_create_bonddef_window(AW_root *awr) {
553    AW_window_simple *aws = new AW_window_simple;
554
555    aws->init(awr, "SEC_BONDDEF", "Bond definitions");
556    aws->load_xfig("sec_bonddef.fig");
557
558    aws->at("close");
559    aws->callback(AW_POPDOWN);
560    aws->create_button("CLOSE", "CLOSE", "C");
561
562    aws->callback(makeHelpCallback("sec_bonddef.hlp"));
563    aws->at("help");
564    aws->create_button("HELP", "HELP", "H");
565
566    aws->at("label"); int x_label = aws->get_at_xposition();
567    aws->at("pairs"); int x_pairs = aws->get_at_xposition();
568    aws->at("chars"); int x_chars = aws->get_at_xposition();
569
570    aws->auto_space(0, 0);
571
572#define INSERT_PAIR_FIELDS(label, pairname)                             \
573    aws->at_x(x_label);                                                 \
574    aws->create_button(NULp, label);                                    \
575    aws->at_x(x_pairs);                                                 \
576    aws->create_input_field(AWAR_SECEDIT_##pairname##_PAIRS, 30);       \
577    aws->at_x(x_chars);                                                 \
578    aws->create_input_field(AWAR_SECEDIT_##pairname##_PAIR_CHAR, 1);    \
579    aws->at_newline();
580
581    INSERT_PAIR_FIELDS("Strong pairs", STRONG);
582    INSERT_PAIR_FIELDS("Normal pairs", NORMAL);
583    INSERT_PAIR_FIELDS("Weak pairs",   WEAK);
584    INSERT_PAIR_FIELDS("No pairs",     NO);
585    INSERT_PAIR_FIELDS("User pairs",   USER);
586
587#undef INSERT_PAIR_FIELDS
588
589    return aws;
590}
591
592#define INSERT_PAIR_MAPPING(pairname)                              \
593    { AWAR_SECEDIT_##pairname##_PAIRS, "pairs_" #pairname },       \
594    { AWAR_SECEDIT_##pairname##_PAIR_CHAR, "char_" #pairname }
595
596static AWT_config_mapping_def secedit_display_config_mapping[] = {
597    { AWAR_SECEDIT_HIDE_BASES,        "hidebases" },
598    { AWAR_SECEDIT_DIST_BETW_STRANDS, "stranddist" },
599    { AWAR_SECEDIT_SHOW_BONDS,        "showbonds" },
600
601    INSERT_PAIR_MAPPING(STRONG),
602    INSERT_PAIR_MAPPING(NORMAL),
603    INSERT_PAIR_MAPPING(WEAK),
604    INSERT_PAIR_MAPPING(NO),
605    INSERT_PAIR_MAPPING(USER),
606
607    { AWAR_SECEDIT_BOND_THICKNESS,     "bondthickness" },
608    { AWAR_SECEDIT_SHOW_CURPOS,        "showposition" },
609    { AWAR_SECEDIT_SHOW_HELIX_NRS,     "showhelixnrs" },
610    { AWAR_SECEDIT_SHOW_ECOLI_POS,     "showecolipos" },
611    { AWAR_SECEDIT_DISPLAY_SEARCH,     "showsearch" },
612    { AWAR_SECEDIT_DISPLAY_SAI,        "showsai" },
613    { AWAR_SECEDIT_DISPPOS_BINDING,    "disppos_helix" },
614    { AWAR_SECEDIT_DISPPOS_ECOLI,      "disppos_ecoli" },
615    { AWAR_SECEDIT_SHOW_STR_SKELETON,  "skeleton" },
616    { AWAR_SECEDIT_SKELETON_THICKNESS, "skeleton_thickness" },
617
618    { NULp, NULp }
619};
620
621#undef INSERT_PAIR_MAPPING
622
623static AW_window *SEC_create_display_window(AW_root *awr) {
624    AW_window_simple *aws = new AW_window_simple;
625
626    const int SCALED_TEXT_COLUMNS = 7;
627    const int SCALER_WIDTH        = 200;
628
629    aws->auto_space(5, 5);
630
631    aws->init(awr, "SEC_DISPLAY_OPTS", "Display options");
632    aws->load_xfig("sec_display.fig");
633
634    aws->at("close");
635    aws->callback(AW_POPDOWN);
636    aws->create_button("CLOSE", "CLOSE", "C");
637
638    aws->callback(makeHelpCallback("sec_display.hlp"));
639    aws->at("help");
640    aws->create_button("HELP", "HELP", "H");
641
642    // ----------------------------------------
643
644    aws->at("bases");
645    aws->label("Display bases              :");
646    aws->create_inverse_toggle(AWAR_SECEDIT_HIDE_BASES);
647
648    aws->at("strand_dist");
649    aws->label("Distance between strands   :");
650    aws->create_input_field_with_scaler(AWAR_SECEDIT_DIST_BETW_STRANDS, SCALED_TEXT_COLUMNS, SCALER_WIDTH, AW_SCALER_EXP_LOWER);
651
652    aws->at("bonds");
653    aws->label("Display bonds");
654    aws->create_option_menu(AWAR_SECEDIT_SHOW_BONDS, true);
655    aws->insert_option("None",       "n", SHOW_NO_BONDS);
656    aws->insert_option("Helix",      "h", SHOW_HELIX_BONDS);
657    aws->insert_option("+Non-helix", "o", SHOW_NHELIX_BONDS);
658    aws->update_option_menu();
659
660    aws->at("bonddef");
661    aws->callback(makeCreateWindowCallback(SEC_create_bonddef_window));
662    aws->create_button("sec_bonddef", "Define");
663
664    aws->at("bondThickness");
665    aws->label("Bond thickness             :");
666    aws->create_input_field_with_scaler(AWAR_SECEDIT_BOND_THICKNESS, SCALED_TEXT_COLUMNS, SCALER_WIDTH, AW_SCALER_EXP_LOWER);
667
668    // ----------------------------------------
669
670    aws->at("cursor");
671    aws->label("Annotate cursor            :");
672    aws->create_option_menu(AWAR_SECEDIT_SHOW_CURPOS, true);
673    aws->insert_option("None",     "n", SHOW_NO_CURPOS);
674    aws->insert_option("Absolute", "a", SHOW_ABS_CURPOS);
675    aws->insert_option("Ecoli",    "e", SHOW_ECOLI_CURPOS);
676    aws->insert_option("Base",     "b", SHOW_BASE_CURPOS);
677    aws->update_option_menu();
678
679    aws->at("helixNrs");
680    aws->label("Annotate helices           :");
681    aws->create_toggle(AWAR_SECEDIT_SHOW_HELIX_NRS);
682
683    aws->at("ecoli");
684    aws->label("Annotate ecoli positions   :");
685    aws->create_toggle(AWAR_SECEDIT_SHOW_ECOLI_POS);
686
687    aws->at("search");
688    aws->label("Visualize search results   :");
689    aws->create_toggle(AWAR_SECEDIT_DISPLAY_SEARCH);
690
691    aws->at("sai");
692    aws->label("Visualize SAI              :");
693    aws->create_toggle(AWAR_SECEDIT_DISPLAY_SAI);
694
695    // ----------------------------------------
696
697    aws->at("binding");
698    aws->label("Binding helix positions    :");
699    aws->create_toggle(AWAR_SECEDIT_DISPPOS_BINDING);
700
701    aws->at("ecoli2");
702    aws->label("Ecoli base positions       :");
703    aws->create_toggle(AWAR_SECEDIT_DISPPOS_ECOLI);
704
705    // ----------------------------------------
706
707    aws->at("strSkeleton");
708    aws->label("Display structure skeleton :");
709    aws->create_toggle(AWAR_SECEDIT_SHOW_STR_SKELETON);
710
711    aws->at("skelThickness");
712    aws->label("Skeleton thickness         :");
713    aws->create_input_field_with_scaler(AWAR_SECEDIT_SKELETON_THICKNESS, SCALED_TEXT_COLUMNS, SCALER_WIDTH, AW_SCALER_EXP_LOWER);
714
715#ifdef DEBUG
716    aws->at("show_debug");
717    aws->label("Show debug info:");
718    aws->create_toggle(AWAR_SECEDIT_SHOW_DEBUG);
719#endif
720
721    aws->at("config");
722    AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "secedit_display", secedit_display_config_mapping);
723
724    return aws;
725}
726
727#if defined(WARN_TODO)
728#warning use popdown callback for SEC_exit and valgrind open/close/open secedit
729#endif
730
731static void SEC_exit(GBDATA *, SEC_root *sec_root) {
732    delete sec_root;
733}
734
735static AW_window *SEC_create_gc_window(AW_root *awr, AW_gc_manager *gcman) {
736    return AW_create_gc_window_named(awr, gcman, "SECEDIT_COLOR_DEF", "SECEDIT colors and fonts");
737}
738
739AW_window *start_SECEDIT_plugin(ED4_plugin_host& host) {
740    AW_root *awr     = host.get_application_root();
741    GBDATA  *gb_main = host.get_database();
742
743    SEC_graphic *gfx  = new SEC_graphic(awr, gb_main); // never freed
744    SEC_root    *root = gfx->sec_root;
745
746    AW_window_menu_modes *awm = new AW_window_menu_modes;
747    awm->init(awr, "ARB_SECEDIT", "ARB_SECEDIT: Secondary structure editor", 200, 200);
748
749    AWT_canvas *scr = new AWT_canvas(gb_main, awm, awm->get_window_id(), gfx);
750    {
751        AWT_auto_refresh allowed_on(scr);
752        root->init(gfx, scr, host);
753        scr->request_resize();
754    }
755    scr->set_mode(AWT_MODE_ZOOM); // Default-Mode
756
757    const SEC_db_interface *db = root->get_db();
758
759    GB_atclose_callback(gb_main, makeDatabaseCallback(SEC_exit, root));
760
761    awm->create_menu("File", "F", AWM_ALL);
762
763    awm->insert_menu_topic("secedit_new",    "New structure",    "N", NULp, AWM_ALL, makeWindowCallback(SEC_new_structure,    db));
764    awm->insert_menu_topic("secedit_rename", "Rename structure", "R", NULp, AWM_ALL, makeWindowCallback(SEC_rename_structure, db));
765    awm->insert_menu_topic("secedit_delete", "Delete structure", "D", NULp, AWM_ALL, makeWindowCallback(SEC_delete_structure, db));
766    awm->sep______________();
767    awm->insert_menu_topic("secedit_import", "Load structure", "L", "secedit_imexport.hlp", AWM_ALL, makeCreateWindowCallback(SEC_importExport, false, db));
768    awm->insert_menu_topic("secedit_export", "Save structure", "S", "secedit_imexport.hlp", AWM_ALL, makeCreateWindowCallback(SEC_importExport, true, db));
769    awm->sep______________();
770    awm->insert_menu_topic("secStruct2xfig", "Export structure to XFIG", "X", "tree2file.hlp", AWM_ALL, makeWindowCallback(AWT_popup_sec_export_window, scr));
771    awm->insert_menu_topic("print_secedit",  "Print Structure",          "P", "tree2prt.hlp",  AWM_ALL, makeWindowCallback(AWT_popup_print_window,      scr));
772    awm->sep______________();
773
774    awm->insert_menu_topic("close", "Close", "C", "quit.hlp", AWM_ALL, AW_POPDOWN);
775
776    awm->create_menu("Properties", "P", AWM_ALL);
777    awm->insert_menu_topic("sec_display", "Display options", "D", "sec_display.hlp", AWM_ALL, SEC_create_display_window);
778    awm->sep______________();
779    awm->insert_menu_topic("props_secedit", "Change Colors and Fonts", "C", "color_props.hlp", AWM_ALL, makeCreateWindowCallback(SEC_create_gc_window, scr->gc_manager));
780    awm->sep______________();
781    awm->insert_menu_topic("sync_search_colors", "Sync search colors with EDIT4", "s", "sync_colors.hlp", AWM_ALL, makeWindowCallback(SEC_sync_colors, COLOR_SYNC_SEARCH));
782    awm->insert_menu_topic("sync_range_colors",  "Sync range colors with EDIT4",  "r", "sync_colors.hlp", AWM_ALL, makeWindowCallback(SEC_sync_colors, COLOR_SYNC_RANGE));
783    awm->insert_menu_topic("sync_other_colors",  "Sync other colors with EDIT4",  "o", "sync_colors.hlp", AWM_ALL, makeWindowCallback(SEC_sync_colors, COLOR_SYNC_REST));
784    awm->insert_menu_topic("sync_all_colors",    "Sync all colors with EDIT4",    "a", "sync_colors.hlp", AWM_ALL, makeWindowCallback(SEC_sync_colors, COLOR_SYNC_ALL));
785    awm->sep______________();
786    awm->insert_menu_topic("sec_save_props",    "How to save properties",   "p", "savedef.hlp", AWM_ALL, makeHelpCallback("sec_props.hlp"));
787
788    awm->create_mode("mode_zoom.xpm",    "sec_mode.hlp", AWM_ALL, makeWindowCallback(sec_mode_event, root, AWT_MODE_ZOOM));
789    awm->create_mode("mode_fold.xpm",    "sec_mode.hlp", AWM_ALL, makeWindowCallback(sec_mode_event, root, AWT_MODE_FOLD));
790    awm->create_mode("mode_setroot.xpm", "sec_mode.hlp", AWM_ALL, makeWindowCallback(sec_mode_event, root, AWT_MODE_SETROOT));
791    awm->create_mode("mode_rotate.xpm",  "sec_mode.hlp", AWM_ALL, makeWindowCallback(sec_mode_event, root, AWT_MODE_ROTATE));
792    awm->create_mode("mode_stretch.xpm", "sec_mode.hlp", AWM_ALL, makeWindowCallback(sec_mode_event, root, AWT_MODE_STRETCH));
793    awm->create_mode("mode_edit.xpm",    "sec_mode.hlp", AWM_ALL, makeWindowCallback(sec_mode_event, root, AWT_MODE_EDIT));
794    awm->create_mode("mode_cursor.xpm",  "sec_mode.hlp", AWM_ALL, makeWindowCallback(sec_mode_event, root, AWT_MODE_CURSOR));
795    awm->create_mode("mode_pinfo.xpm",   "sec_mode.hlp", AWM_ALL, makeWindowCallback(sec_mode_event, root, AWT_MODE_PINFO));
796
797    awm->set_info_area_height(250);
798    awm->at(5, 2);
799    awm->auto_space(0, -2);
800
801    awm->button_length(0);
802    awm->help_text("quit.hlp");
803    awm->callback(AW_POPDOWN);
804    awm->create_button("Close", "#quit.xpm"); // use quit button, cause users regard secedit as separate program
805
806    awm->callback(AW_help_entry_pressed);
807    awm->help_text("arb_secedit.hlp");
808    awm->create_button("HELP", "#help.xpm");
809
810    awm->callback(makeWindowCallback(SEC_undo_cb, db, GB_UNDO_UNDO));
811    awm->help_text("undo.hlp");
812    awm->create_button("Undo", "#undo.xpm");
813
814    awm->callback(makeWindowCallback(SEC_undo_cb, db, GB_UNDO_REDO));
815    awm->help_text("undo.hlp");
816    awm->create_button("Redo", "#redo.xpm");
817
818    awm->callback(makeWindowCallback(SEC_toggle_cb, db));
819    awm->help_text("sec_main.hlp");
820    awm->create_button("Toggle", "Toggle");
821
822    awm->callback(makeWindowCallback(SEC_center_cb, root));
823    awm->help_text("sec_main.hlp");
824    awm->create_button("Center", "Center");
825
826    awm->callback(makeWindowCallback(SEC_fit_window_cb, db));
827    awm->help_text("sec_main.hlp");
828    awm->create_button("fitWindow", "Fit");
829
830    awm->at_newline();
831
832    {
833        SmartPtr<AW_at_storage> maxSize(AW_at_storage::make(awm, AW_AT_MAXSIZE));
834
835        awm->button_length(AWAR_FOOTER_MAX_LEN);
836        awm->create_button(NULp, AWAR_FOOTER);
837        awm->at_newline();
838        awm->restore_at_from(*maxSize);
839    }
840
841    awm->set_info_area_height(awm->get_at_yposition());
842
843    return awm;
844}
845
Note: See TracBrowser for help on using the repository browser.