ARB
SEC_graphic.cxx
Go to the documentation of this file.
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 
29 using namespace std;
30 
31 AW_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_MAX,
38  makeGcChangedCallback(AWT_GC_changed_cb, scr),
39  "#A1A1A1",
40  "LOOP$#247900",
41  "HELIX$#085DAB",
42  "NONPAIRING HELIX$#D52B69",
43  "DEFAULT$#000000",
44  "BONDS$#000000",
45  "ECOLI POSITION$#FFE223",
46  "HELIX NUMBERS$#D4D4D4",
47 
48  // Color Ranges to paint SAIs
49  "+-RANGE 0$#FFFFFF", "+-RANGE 1$#E0E0E0", "-RANGE 2$#C0C0C0",
50  "+-RANGE 3$#A0A0A0", "+-RANGE 4$#909090", "-RANGE 5$#808080",
51  "+-RANGE 6$#808080", "+-RANGE 7$#505050", "-RANGE 8$#404040",
52  "+-RANGE 9$#303030", "+-CURSOR$#BF1515", "-MISMATCHES$#FF9AFF",
53 
54  // colors used to Paint search patterns
55  // (do not change the names of these gcs)
56  "+-User1$#B8E2F8", "+-User2$#B8E2F8", "-Probe$#B8E2F8",
57  "+-Primer(l)$#A9FE54", "+-Primer(r)$#A9FE54", "-Primer(g)$#A9FE54",
58  "+-Sig(l)$#DBB0FF", "+-Sig(r)$#DBB0FF", "-Sig(g)$#DBB0FF",
59 
60  // colors used to paint the skeleton of the structure
61  "+-SKELETON HELIX${HELIX}", "+-SKELETON LOOP${LOOP}", "-SKELETON NONHELIX${NONPAIRING HELIX}",
62  NULp);
63 
64  return gc_manager;
65 }
66 
69  GB_CSTR constraint_type = NULp;
70  GB_CSTR element_type = NULp;
71 
72  switch (elem->getType()) {
73  case SEC_HELIX:
74  constraint_type = "length";
75  element_type = "helix";
76  break;
77  case SEC_LOOP:
78  constraint_type = "radius";
79  element_type = "loop";
80  break;
81  default:
82  sec_assert(0);
83  error = "Illegal element type";
84  break;
85  }
86 
87  if (!error) {
88  char *question = GBS_global_string_copy("%s-constraints for %s", constraint_type, element_type);
89  char *answer = aw_input(question, GBS_global_string("%.2f-%.2f", elem->minSize(), elem->maxSize()));
90 
91  while (answer) {
92  char *end;
93  double low = strtod(answer, &end);
94 
95  if (end[0]!='-') {
96  error = "Wrong format! Wanted format is 'lower-upper'";
97  }
98  else {
99  double high = strtod(end+1, NULp);
100 
101  if (low<0 || high<0 || (low && high && low>high)) {
102  error = "Illegal values";
103  }
104  else {
105 #if defined(DEBUG)
106  sec_assert(!low || !high || low<=high);
107 #endif // DEBUG
108  elem->setConstraints(low, high);
109  break;
110  }
111  }
112 
113  sec_assert(error);
114  aw_message(error);
115 
116  char *retry = aw_input(question, answer);
117  free(answer);
118 
119  answer = retry;
120  }
121 
122  free(answer);
123  free(question);
124  }
125  return error;
126 }
127 
128 
129 GB_ERROR SEC_graphic::handleKey(AW_event_type event, AW_key_mod key_modifier, AW_key_code key_code, char key_char) {
130  GB_ERROR error = NULp;
131 
132  if (event == AW_Keyboard_Press) {
133  int curpos = sec_root->get_cursor();
134  int maxIndex = sec_root->max_index();
135  bool setCurpos = false;
136  bool handled = false;
137 
138  if (key_modifier == AW_KEYMODE_NONE) {
139  bool wrapped = false; // avoid deadlock
140 
141  switch (key_code) {
142  case AW_KEY_LEFT: {
143  while (1) {
144  curpos--;
145  if (curpos<0) {
146  curpos = maxIndex;
147  if (wrapped) break;
148  wrapped = true;
149  }
150  if (sec_root->shallDisplayPosition(curpos)) {
151  setCurpos = true;
152  break;
153  }
154  }
155  break;
156  }
157  case AW_KEY_RIGHT: {
158  while (1) {
159  curpos++;
160  if (curpos > maxIndex) {
161  curpos = 0;
162  if (wrapped) break;
163  wrapped = true;
164  }
165  if (sec_root->shallDisplayPosition(curpos)) {
166  setCurpos = true;
167  break;
168  }
169  }
170  break;
171  }
172  case AW_KEY_ASCII: {
173  const char *toggle_awar = NULp;
174  int val_max = 1;
175 
176  switch (key_char) {
177  case 'b': toggle_awar = AWAR_SECEDIT_SHOW_BONDS; val_max = 2; break;
178  case 'B': toggle_awar = AWAR_SECEDIT_HIDE_BASES; break;
179  case 'k': toggle_awar = AWAR_SECEDIT_SHOW_STR_SKELETON; break;
180 
181  case 'c': toggle_awar = AWAR_SECEDIT_SHOW_CURPOS; val_max = 3; break;
182  case 'h': toggle_awar = AWAR_SECEDIT_SHOW_HELIX_NRS; break;
183  case 'e': toggle_awar = AWAR_SECEDIT_SHOW_ECOLI_POS; break;
184 
185  case 's': toggle_awar = AWAR_SECEDIT_DISPLAY_SAI; break;
186  case 'r': toggle_awar = AWAR_SECEDIT_DISPLAY_SEARCH; break;
187 
188  case 'E': toggle_awar = AWAR_SECEDIT_DISPPOS_ECOLI; break;
189  case 'H': toggle_awar = AWAR_SECEDIT_DISPPOS_BINDING; break;
190 
191 #if defined(DEBUG)
192  case 'd': toggle_awar = AWAR_SECEDIT_SHOW_DEBUG; break;
193 #endif // DEBUG
194 
195  case 't':
196  error = sec_root->get_db()->structure()->next();
197  handled = true;
198  break;
199  }
200 
201  if (toggle_awar) {
202  AW_awar *awar = aw_root->awar(toggle_awar);
203  int val = awar->read_int()+1;
204 
205  if (val>val_max) val = 0;
206  awar->write_int(val);
207 
208  handled = true;
209  }
210 
211  break;
212  }
213  default:
214  break;
215  }
216  }
217 
218  if (setCurpos) {
219  aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(curpos);
220  handled = true;
221  }
222 
223  if (!handled) { // pass unhandled key events to EDIT4
224  AW_event faked_event;
225 
226  memset((char*)&faked_event, 0, sizeof(faked_event));
227 
228  faked_event.type = event;
229  faked_event.keymodifier = key_modifier;
230  faked_event.keycode = key_code;
231  faked_event.character = key_char;
232 
233  sec_root->host().forward_event(&faked_event);
234  }
235  }
236 
237  return error;
238 }
239 
240 GB_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) {
241  GB_ERROR error = NULp;
242 
243  sec_assert(elem); // always contains the element targetted by the initial button-down
244 
245  // ------------------------------------------
246  // handle element dependent actions
247 
248  static Position start; // click position on mouse down
249 
250  Position fixpoint = elem->get_fixpoint(); // of strand or loop
251 
252  SEC_loop *loop = NULp;
253  SEC_helix *helix = NULp;
254 
255  if (elem->getType() == SEC_HELIX) {
256  helix = static_cast<SEC_helix*>(elem);
257  }
258  else {
259  sec_assert(elem->getType() == SEC_LOOP);
260  loop = static_cast<SEC_loop*>(elem);
261  }
262 
263  if (event == AW_Mouse_Press) start = world; // store start position
264 
265  switch (cmd) {
266  case AWT_MODE_STRETCH: { // change constraints with mouse
267  static double start_size; // helix/loop size at start click
268 
269  switch (event) {
270  case AW_Mouse_Press:
271  if (button == AW_BUTTON_LEFT) {
272  start_size = elem->drawnSize();
273  sec_root->set_show_constraints(elem->getType());
274  exports.request_refresh();
275  }
276  else { // right button -> reset constraints
277  elem->setConstraints(0, 0);
278  elem->sizeChanged();
279  exports.request_save();
280  }
281  break;
282 
283  case AW_Mouse_Drag:
284  if (button == AW_BUTTON_LEFT) {
285  double dfix1 = Distance(fixpoint, start);
286  double dfix2 = Distance(fixpoint, world);
287 
288  if (dfix1>0 && dfix2>0) {
289  double factor = dfix2/dfix1;
290  double new_size = start_size*factor;
291 
292  elem->setDrawnSize(new_size);
293  elem->sizeChanged();
294 
295  exports.request_refresh();
296  }
297  }
298  break;
299 
300  case AW_Mouse_Release:
301  sec_root->set_show_constraints(SEC_ANY_TYPE);
302  exports.request_save();
303  break;
304 
305  default: sec_assert(0); break;
306  }
307  break;
308  }
309  case AWT_MODE_EDIT: // edit constraints
310  if (button==AW_BUTTON_LEFT && event==AW_Mouse_Press) {
311  error = change_constraints(elem);
312  if (!error) {
313  elem->sizeChanged();
314  exports.request_save();
315  }
316  }
317  break;
318 
319  case AWT_MODE_ROTATE: { // rotate branches/loops
320  if (event == AW_Mouse_Release) {
321  exports.request_save();
322  }
323  else {
324  static Angle startClick; // angle between fixpoint (of loop or helix) and first-click
325  static bool rotateSubStructure; // whether to rotate the substructure below
326  static vector<Angle> old; // old angles
327 
328  if (loop && loop->is_root_loop()) fixpoint = loop->get_center();
329 
330  Angle fix2world(fixpoint, world);
331 
332  if (event == AW_Mouse_Press) {
333  startClick = fix2world;
334  old.clear();
335  rotateSubStructure = (button == AW_BUTTON_LEFT);
336 
337  if (loop) {
338  old.push_back(loop->get_abs_angle());
339  if (!rotateSubStructure) {
340  for (SEC_strand_iterator strand(loop); strand; ++strand) {
341  if (strand->isRootsideFixpoint()) {
342  old.push_back(strand->get_helix()->get_abs_angle());
343  }
344  }
345  }
346  }
347  else {
348  old.push_back(helix->get_abs_angle());
349  old.push_back(helix->outsideLoop()->get_abs_angle());
350  }
351  }
352  else {
353  sec_assert(event == AW_Mouse_Drag);
354  Angle diff = fix2world-startClick;
355 
356  if (loop) {
357  loop->set_abs_angle(old[0]+diff);
358  if (!rotateSubStructure) {
359  int idx = 1;
360  for (SEC_strand_iterator strand(loop); strand; ++strand) {
361  if (strand->isRootsideFixpoint()) {
362  strand->get_helix()->set_abs_angle(old[idx++]);
363  }
364  }
365  }
366  }
367  else {
368  helix->set_abs_angle(old[0]+diff);
369  if (!rotateSubStructure) helix->outsideLoop()->set_abs_angle(old[1]);
370  }
371 
372  exports.request_refresh();
373  elem->orientationChanged();
374  }
375  }
376  break;
377  }
378 
379  case AWT_MODE_SETROOT: // set-root-mode / reset angles
380  if (event == AW_Mouse_Press) {
381  if (button == AW_BUTTON_LEFT) { // set root
382  if (loop) {
383  sec_root->set_root(loop);
384  exports.request_save();
385  }
386  else error = "Please click on a loop to change the root";
387  }
388  else { // reset angles
389  sec_assert(button == AW_BUTTON_RIGHT);
390  elem->reset_angles();
391  elem->orientationChanged();
392  exports.request_save();
393  }
394  }
395  break;
396 
397  case AWT_MODE_FOLD: { // fold/unfold helix
398  if (event == AW_Mouse_Press && button == AW_BUTTON_LEFT) { // fold helix
399  if (loop) {
400  const char *helix_nr = sec_root->helixNrAt(abspos);
401  if (helix_nr) {
402  const size_t *p = sec_root->getHelixPositions(helix_nr);
403  error = sec_root->split_loop(p[0], p[1]+1, p[2], p[3]+1);
404 
405  if (!error) {
406  sec_root->nail_position(abspos);
407  exports.request_save();
408  }
409  }
410  else {
411  error = GBS_global_string("No helix to fold at position %i", abspos);
412  }
413  }
414  else {
415  error = "Click on a loop region to fold a helix";
416  }
417  }
418  if (event == AW_Mouse_Release && button == AW_BUTTON_RIGHT) { // unfold helix
419  if (helix) {
420  // this section may only executed during mouse-release-callback, otherwise secedit crashes (see #828)
421  sec_assert(event == AW_Mouse_Release);
422  error = sec_root->unsplit_loop(helix->strandToRoot());
423  if (!error) {
424  sec_root->nail_position(abspos);
425  exports.request_save();
426  }
427  }
428  else {
429  error = "Right click on a helix to remove it";
430  }
431  }
432  break;
433  }
434 
435  case AWT_MODE_CURSOR: // set cursor in ARB_EDIT4
436  drag_target_detection(true);
437  if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
438  // sequence position in AWAR_SET_CURSOR_POSITION is starting with 0!
439  aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(abspos);
440  }
441  break;
442 
443  case AWT_MODE_PINFO: // display search pattern
444  if (event == AW_Mouse_Press) {
445  if (button == AW_BUTTON_LEFT) {
446  if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
447  sec_root->paintSearchPatternStrings(device, abspos, world.xpos()+1, world.ypos());
448  }
449  // don't refresh here!
450  }
451  else {
452  sec_assert(button == AW_BUTTON_RIGHT);
453  exports.request_refresh(); // simply refresh to remove drawn patterns
454  }
455  }
456  break;
457 
458  default: sec_assert(0); break;
459  }
460 
461  return error;
462 }
463 
464 void SEC_graphic::handle_command(AW_device *device, AWT_graphic_event& event) {
465  if (event.cmd() != AWT_MODE_EDIT && event.cmd() != AWT_MODE_STRETCH) sec_root->set_show_constraints(SEC_NO_TYPE);
466 
467  GB_ERROR error = NULp;
468  if (event.type() == AW_Keyboard_Press || event.type() == AW_Keyboard_Release) {
469  error = handleKey(event.type(), event.key_modifier(), event.key_code(), event.key_char());
470  }
471  else {
472  if (event.button() != AW_BUTTON_MIDDLE && event.cmd() != AWT_MODE_ZOOM) { // don't handle scroll + zoom
473  static SEC_base *elem = NULp; // Warning: if handleMouse() destroys 'elem' during mouse press callback, this pointer will become stale!
474  static int abspos = -1;
475 
476  bool updateClicked = false;
477 
478  if (event.type() == AW_Mouse_Press) updateClicked = true; // initial button-down
479  else if (event.cmd() == AWT_MODE_CURSOR) { // special modes which act identical in click/drag/release
480  updateClicked = true;
481  }
482 
483  if (updateClicked) {
484  // store information about clicked SEC_base
485  const AW_clicked_element *clicked = event.best_click();
486  if (clicked) {
487  elem = reinterpret_cast<SEC_base*>(clicked->cd1());
488  abspos = clicked->cd2();
489  }
490  else {
491  elem = NULp;
492  }
493  }
494 
495  if (elem) {
496  Position world = device->rtransform(event.position());
497  error = handleMouse(device, event.type(), event.button(), event.cmd(), world, elem, abspos);
498  }
499 
500  if (event.type() == AW_Mouse_Release) elem = NULp; // forget last clicked SEC_base
501  }
502  }
503 
504  if (error) aw_message(error);
505 }
506 
507 SEC_graphic::SEC_graphic(AW_root *aw_rooti, GBDATA *gb_maini)
508  : update_requested(SEC_UPDATE_RELOAD),
509  load_error(NULp),
510  disp_device(NULp),
511  gb_main(gb_maini),
512  aw_root(aw_rooti),
513  sec_root(new SEC_root),
514  gb_struct(NULp),
515  gb_struct_ref(NULp),
516  last_saved(0)
517 {
518  exports.set_standard_default_padding();
519 }
520 
521 SEC_graphic::~SEC_graphic() {
522  delete sec_root;
523  delete load_error;
524 }
525 
526 static void SEC_structure_changed_cb(GBDATA *gb_seq, SEC_graphic *gfx, GB_CB_TYPE type) {
527  LocallyModify<int> allow_flag_modify(gfx->exports.get_modifying_flag_ref(), -1); // hack, allow flag modification during exit (w/o forcing a refresh)
528 
529  if (type == GB_CB_DELETE) {
530  gfx->gb_struct = NULp;
531  gfx->gb_struct_ref = NULp;
532 
533  gfx->request_update(SEC_UPDATE_RELOAD);
534  }
535  else if (GB_read_clock(gb_seq) > gfx->last_saved) { // not changed by secedit self
536  gfx->request_update(SEC_UPDATE_RELOAD);
537  }
538 }
539 
540 GB_ERROR SEC_graphic::load_from_DB(GBDATA *, const char *) {
542 
543  sec_assert(sec_root->get_db()->canDisplay()); // need a sequence loaded (to fix bugs in versions < 3)
544  sec_root->nail_cursor();
545 
547  // first check timestamp, do not load structure that we have saved !!!!
548  if (gb_struct) {
549  if (GB_read_clock(gb_struct) <= last_saved) return NULp;
550  }
551 
552  // Reset structure:
553  if (gb_struct) {
554  GB_remove_callback(gb_struct, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this)); gb_struct = NULp;
555  GB_remove_callback(gb_struct_ref, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this)); gb_struct_ref = NULp;
556  }
557 
558  request_update(SEC_UPDATE_RECOUNT);
559 
560  if (gb_struct) {
561  this->last_saved = GB_read_clock(gb_struct); // mark as loaded
562  }
563 
564 
565 
566  // Setup new structure:
567  GB_ERROR err = NULp;
568  GBDATA *gb_ali = NULp;
569  {
570  char *helix_name = GBT_get_default_helix(gb_main);
571  char *name = GBT_readOrCreate_string(gb_main, AWAR_HELIX_NAME, helix_name);
572  sec_assert(name);
573 
574  GBDATA *gb_species = GBT_find_SAI(gb_main, name);
575  if (!gb_species) {
576  err = GB_export_errorf("Cannot find helix template SAI '%s'", name);
577  }
578  else {
579  char *ali_name = GBT_get_default_alignment(gb_main);
580  long ali_len = GBT_get_alignment_len(gb_main, ali_name);
581 
582  if (ali_len < 10) {
583  err = GB_export_errorf("alignment '%s' to short to generate helix", ali_name);
584  }
585  else {
586  gb_ali = GB_search(gb_species, ali_name, GB_FIND);
587  if (!gb_ali) {
588  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 !!!
589  }
590  }
591  free(ali_name);
592  }
593 
594  free(name);
595  free(helix_name);
596  }
597 
598  // ------------------------
599  // read structure
600 
601  if (!err) {
602  gb_struct = GB_search(gb_ali, NAME_OF_STRUCT_SEQ, GB_FIND);
603 
604  if (gb_struct) {
605  gb_struct_ref = GB_search(gb_ali, NAME_OF_REF_SEQ, GB_STRING);
606 
607  char *strct = GB_read_string(gb_struct);
608  char *ref = GB_read_string(gb_struct_ref);
609  err = sec_root->read_data(strct, ref);
610  if (err) {
611  err = GBS_global_string("Defect structure in DB (read-error: '%s')", err);
612  }
613 #if defined(CHECK_INTEGRITY)
614  else {
615  sec_root->check_integrity(CHECK_STRUCTURE);
616  }
617 #endif // CHECK_INTEGRITY
618 
619  free(strct);
620  free(ref);
621 
622  // on first load init structure toggler:
623  if (!err) {
624  sec_root->get_db()->init_toggler();
625  }
626  }
627  else {
628  err = "no secondary structure was found in your database";
629  }
630 
631  if (!err) {
632  // in the past one additional NAME_OF_STRUCT_SEQ-entry was added everytime the default bone was created
633  // Fix: delete additional entries
634 
635  GBDATA *gb_add = gb_struct;
636  do {
638  gb_add = GB_nextEntry(gb_add);
639  if (gb_add) {
640  err = GB_delete(gb_add);
641  printf("* Deleting duplicated entry '%s' (%p)\n", NAME_OF_STRUCT_SEQ, gb_add);
642  }
643  }
644  while (gb_add && !err);
645  }
646  }
647 
648  if (!err) {
649  last_saved = GB_read_clock(gb_struct); // mark as loaded
650  request_update(SEC_UPDATE_RECOUNT);
651  if (load_error) { // previous load error?
652  freenull(load_error);
653  exports.request_zoom_reset();
654  }
655  }
656  else {
657  load_error = ARB_strdup(err);
658  exports.request_zoom_reset();
659  }
660 
661  // set structure-change-callbacks:
662  if(gb_struct) GB_add_callback(gb_struct, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this));
663  if(gb_struct_ref) GB_add_callback(gb_struct_ref, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this));
664 
665  return err;
666 }
667 
668 GB_ERROR SEC_graphic::save_to_DB(GBDATA *, const char *) {
670 
671  if (!gb_struct) return NULp; // not loaded, so don't save
672  if (!sec_root) return NULp;
673 
674  char *data = sec_root->buildStructureString();
676  GB_ERROR error = GB_write_string(gb_struct, data);
677  if (!error) {
678  const XString& xstr = sec_root->get_xString();
679  const char *x_string = xstr.get_x_string();
680 
681  error = GB_write_string(gb_struct_ref, x_string);
682 
683  if (!error && xstr.alignment_too_short()) {
684  aw_message("Your helix needs one gap at end. Please format your alignment!");
685  }
686  }
687  this->last_saved = GB_read_clock(gb_struct);
688  if (error) {
689  error = ta.close(error);
690  aw_message(error);
691  }
692  return NULp;
693 }
694 
695 GB_ERROR SEC_graphic::read_data_from_db(char **data, char **x_string) const {
696  GB_ERROR error = NULp;
697 
698  sec_assert(gb_struct && gb_struct_ref);
699  *data = GB_read_string(gb_struct);
700  if (!*data) error = GB_await_error();
701  else {
702  *x_string = GB_read_string(gb_struct_ref);
703  if (!*x_string) error = GB_await_error();
704  }
705  return error;
706 }
707 
708 GB_ERROR SEC_graphic::write_data_to_db(const char *data, const char *x_string) const {
709  if (!gb_struct) return NULp;
710  if (!sec_root) return NULp;
711 
713  GB_ERROR error = GB_write_string(gb_struct, data);
714  if (!error) {
715  error = GB_write_string(gb_struct_ref, x_string);
716  }
717  last_saved = 0; // force reload of data
718  return ta.close(error);
719 }
720 
721 void SEC_graphic::check_for_DB_update(GBDATA *) {
722 }
723 
724 void SEC_graphic::update_structure() {
726 
727  const SEC_db_interface *db = sec_root->get_db();
728 
729  if (db && db->canDisplay()) {
730  if (update_requested & SEC_UPDATE_RELOAD) {
731  GB_ERROR error = load_from_DB(NULp, NULp); // sets change_flag
732  if (error) {
733  error = ta.close(error);
734  aw_message(error);
735  }
736  // clear reload flag + set recount flag:
737  update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_RELOAD)|SEC_UPDATE_RECOUNT);
738  }
739 
740  if (update_requested & SEC_UPDATE_SHOWN_POSITIONS) {
741  sec_root->update_shown_positions();
742  // clear reload flag + set recount flag:
743  update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_SHOWN_POSITIONS)|SEC_UPDATE_RECOUNT);
744  }
745 
746  if (update_requested & SEC_UPDATE_RECOUNT) {
747  sec_root->invalidate_base_positions();
748  sec_root->relayout();
749 
750  update_requested = static_cast<SEC_update_request>(update_requested^SEC_UPDATE_RECOUNT); // clear recount flag
751  exports.request_refresh();
752  }
753 
754  sec_root->perform_autoscroll();
755  }
756 }
757 
758 void SEC_graphic::notify_synchronized(GBDATA *) {
759  // nothing todo here
760 }
761 
762 void SEC_graphic::show(AW_device *device) {
763  const char *textToDisplay = NULp;
764 
765  sec_assert(sec_root);
766  sec_root->clear_last_drawed_cursor_position();
767 
768  if (sec_root->canDisplay()) {
769  if (sec_root->get_root_loop()) {
770  GB_ERROR paint_error = sec_root->paint(device);
771  if (paint_error) textToDisplay = GBS_global_string("Error: %s", paint_error);
772  }
773  else {
774  if (load_error) textToDisplay = GBS_global_string("Load error: %s", load_error);
775  else textToDisplay = "No structure loaded (yet)";
776  }
777  }
778  else {
779  const SEC_db_interface *db = sec_root->get_db();
780 
781  if (!db) textToDisplay = "Not connected to database";
782  else if (!db->helix()) textToDisplay = "No helix info";
783  else textToDisplay = "No species selected";
784  }
785 
786  if (textToDisplay) { // no structure
787  sec_assert(!strchr(textToDisplay, '\n')); // linefeeds do not work here
788  device->text(SEC_GC_ECOLI, textToDisplay, 0, 0, 0, AW_SCREEN);
789  sec_root->set_last_drawed_cursor_position(LineVector(Origin, ZeroVector));
790  }
791 }
792 
#define AWAR_SECEDIT_SHOW_CURPOS
Definition: SEC_db.hxx:41
const char * GB_ERROR
Definition: arb_core.h:25
GB_TYPES type
AW_event_type
Definition: aw_window.hxx:62
SEC_update_request
Definition: SEC_graphic.hxx:30
const AW_bitset AW_SCREEN
Definition: aw_device.hxx:34
AWT_COMMAND_MODE
Definition: awt_canvas.hxx:25
double drawnSize() const
Definition: SEC_root.hxx:165
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
Definition: arbdb.cxx:1385
#define AWAR_HELIX_NAME
GB_ERROR GB_add_callback(GBDATA *gbd, GB_CB_TYPE type, const DatabaseCallback &dbcb)
Definition: ad_cb.cxx:356
double minSize() const
Definition: SEC_root.hxx:168
#define AWAR_SECEDIT_DISPLAY_SEARCH
Definition: SEC_db.hxx:43
GBDATA * GB_nextEntry(GBDATA *entry)
Definition: adquery.cxx:339
virtual void reset_angles()=0
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
long read_int() const
Definition: AW_awar.cxx:187
double maxSize() const
Definition: SEC_root.hxx:169
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
long GBT_get_alignment_len(GBDATA *gb_main, const char *aliname)
Definition: adali.cxx:718
STL namespace.
virtual SEC_BASE_TYPE getType() const =0
AW_MouseButton button() const
Definition: awt_canvas.hxx:223
AW_gc_manager * AW_manage_GC(AW_window *aww, const char *gc_base_name, AW_device *device, int base_drag, AW_GCM_AREA area, const GcChangedCallback &changecb, const char *default_background_color,...)
Definition: AW_preset.cxx:969
static void SEC_structure_changed_cb(GBDATA *gb_seq, SEC_graphic *gfx, GB_CB_TYPE type)
char character
Definition: aw_window.hxx:91
GB_ERROR GB_delete(GBDATA *&source)
Definition: arbdb.cxx:1904
static HelixNrInfo * start
const Vector ZeroVector
const AW::Position & position() const
Definition: awt_canvas.hxx:231
GBDATA * GBT_find_SAI(GBDATA *gb_main, const char *name)
Definition: aditem.cxx:177
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:353
static int diff(int v1, int v2, int v3, int v4, int st, int en)
Definition: ClustalV.cxx:534
const double & ypos() const
const char * get_gc_base_name() const
Definition: awt_canvas.hxx:391
ValueCounter< double > Distance
Definition: AP_Tree.cxx:1315
const char * get_x_string() const
Definition: SEC_abspos.cxx:122
AW_CL cd1() const
#define AWAR_SECEDIT_SHOW_STR_SKELETON
Definition: SEC_db.hxx:38
AW::Vector rtransform(const AW::Vector &vec) const
Definition: aw_device.hxx:145
static void error(const char *msg)
Definition: mkptypes.cxx:96
#define AWAR_SECEDIT_HIDE_BASES
Definition: SEC_db.hxx:39
char * GBT_readOrCreate_string(GBDATA *gb_container, const char *fieldpath, const char *default_value)
Definition: adtools.cxx:371
#define AWAR_SECEDIT_SHOW_DEBUG
Definition: SEC_db.hxx:35
#define AWAR_SECEDIT_SHOW_ECOLI_POS
Definition: SEC_db.hxx:37
#define AWAR_SET_CURSOR_POSITION
#define AWAR_SECEDIT_SHOW_BONDS
Definition: SEC_db.hxx:40
#define AWAR_SECEDIT_SHOW_HELIX_NRS
Definition: SEC_db.hxx:36
bool GB_has_key(GBDATA *gbd, const char *key)
Definition: arbdb.cxx:1705
AW_key_code keycode
Definition: aw_window.hxx:90
AW_key_mod keymodifier
Definition: aw_window.hxx:83
Definition: arbdb.h:86
static GB_ERROR change_constraints(SEC_base *elem)
Definition: SEC_graphic.cxx:67
bool alignment_too_short() const
Definition: SEC_abspos.hxx:71
virtual void orientationChanged()=0
GB_ERROR GB_export_errorf(const char *templat,...)
Definition: arb_msg.cxx:264
AW_event_type type
Definition: aw_window.hxx:81
AW_CL cd2() const
GB_ERROR close(GB_ERROR error)
Definition: arbdbpp.cxx:32
virtual const Position & get_fixpoint() const =0
AW_key_code
Definition: aw_keysym.hxx:14
AWT_COMMAND_MODE cmd() const
Definition: awt_canvas.hxx:222
bool canDisplay() const
Definition: SEC_db.hxx:149
void setConstraints(double low, double high)
Definition: SEC_root.hxx:193
char * GB_read_string(GBDATA *gbd)
Definition: arbdb.cxx:903
#define AWAR_SECEDIT_DISPLAY_SAI
Definition: SEC_db.hxx:42
void GB_remove_callback(GBDATA *gbd, GB_CB_TYPE type, const DatabaseCallback &dbcb)
Definition: ad_cb.cxx:360
#define AWAR_SECEDIT_DISPPOS_ECOLI
Definition: SEC_db.hxx:45
#define NAME_OF_STRUCT_SEQ
Definition: SEC_graphic.hxx:25
void aw_message(const char *msg)
Definition: AW_status.cxx:932
AW_event_type type() const
Definition: awt_canvas.hxx:229
long GB_read_clock(GBDATA *gbd)
Definition: arbdb.cxx:1712
const double & xpos() const
char * GBT_get_default_helix(GBDATA *)
Definition: adtools.cxx:64
#define NULp
Definition: cxxforward.h:97
AW_key_mod
Definition: aw_keysym.hxx:46
BI_helix * helix() const
Definition: SEC_db.hxx:166
char * GBT_get_default_alignment(GBDATA *gb_main)
Definition: adali.cxx:687
GB_transaction ta(gb_var)
virtual void sizeChanged()=0
GBDATA * gb_main
Definition: adname.cxx:33
GBDATA * GB_search(GBDATA *gbd, const char *fieldpath, GB_TYPES create)
Definition: adquery.cxx:531
void setDrawnSize(double size)
Definition: SEC_root.hxx:171
char * aw_input(const char *title, const char *prompt, const char *default_input)
Definition: AW_modal.cxx:251
GB_CB_TYPE
Definition: arbdb_base.h:46
#define NAME_OF_REF_SEQ
Definition: SEC_graphic.hxx:26
const Position Origin
#define sec_assert(cond)
Definition: SEC_defs.hxx:19
static void wrapped()
GB_ERROR write_int(long aw_int)
bool text(int gc, const SizedCstr &cstr, const AW::Position &pos, AW_pos alignment=0.0, AW_bitset filteri=AW_ALL_DEVICES_UNSCALED)
Definition: aw_device.hxx:440
char * GBS_global_string_copy(const char *templat,...)
Definition: arb_msg.cxx:195
#define AWAR_SECEDIT_DISPPOS_BINDING
Definition: SEC_db.hxx:44
void AWT_GC_changed_cb(GcChange whatChanged, AWT_canvas *scr)
Definition: AWT_canvas.cxx:394