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) {
399  if (button == AW_BUTTON_LEFT) { // fold helix
400  if (loop) {
401  const char *helix_nr = sec_root->helixNrAt(abspos);
402  if (helix_nr) {
403  const size_t *p = sec_root->getHelixPositions(helix_nr);
404  error = sec_root->split_loop(p[0], p[1]+1, p[2], p[3]+1);
405 
406  if (!error) {
407  sec_root->nail_position(abspos);
408  exports.request_save();
409  }
410  }
411  else {
412  error = GBS_global_string("No helix to fold at position %i", abspos);
413  }
414  }
415  else {
416  error = "Click on a loop region to fold a helix";
417  }
418  }
419  else { // unfold helix
420  sec_assert(button == AW_BUTTON_RIGHT);
421  if (helix) {
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  }
433  break;
434  }
435 
436  case AWT_MODE_CURSOR: // set cursor in ARB_EDIT4
437  drag_target_detection(true);
438  if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
439  // sequence position in AWAR_SET_CURSOR_POSITION is starting with 0!
440  aw_root->awar_int(AWAR_SET_CURSOR_POSITION)->write_int(abspos);
441  }
442  break;
443 
444  case AWT_MODE_PINFO: // display search pattern
445  if (event == AW_Mouse_Press) {
446  if (button == AW_BUTTON_LEFT) {
447  if (abspos >= 0 && size_t(abspos) < sec_root->max_index()) {
448  sec_root->paintSearchPatternStrings(device, abspos, world.xpos()+1, world.ypos());
449  }
450  // don't refresh here!
451  }
452  else {
453  sec_assert(button == AW_BUTTON_RIGHT);
454  exports.request_refresh(); // simply refresh to remove drawn patterns
455  }
456  }
457  break;
458 
459  default: sec_assert(0); break;
460  }
461 
462  return error;
463 }
464 
465 void SEC_graphic::handle_command(AW_device *device, AWT_graphic_event& event) {
466  if (event.cmd() != AWT_MODE_EDIT && event.cmd() != AWT_MODE_STRETCH) sec_root->set_show_constraints(SEC_NO_TYPE);
467 
468  GB_ERROR error = NULp;
469  if (event.type() == AW_Keyboard_Press || event.type() == AW_Keyboard_Release) {
470  error = handleKey(event.type(), event.key_modifier(), event.key_code(), event.key_char());
471  }
472  else {
473  if (event.button() != AW_BUTTON_MIDDLE && event.cmd() != AWT_MODE_ZOOM) { // don't handle scroll + zoom
474  static SEC_base *elem = NULp;
475  static int abspos = -1;
476 
477  bool updateClicked = false;
478 
479  if (event.type() == AW_Mouse_Press) updateClicked = true; // initial button-down
480  else if (event.cmd() == AWT_MODE_CURSOR) { // special modes which act identical in click/drag/release
481  updateClicked = true;
482  }
483 
484  if (updateClicked) {
485  // store information about clicked SEC_base
486  const AW_clicked_element *clicked = event.best_click();
487  if (clicked) {
488  elem = reinterpret_cast<SEC_base*>(clicked->cd1());
489  abspos = clicked->cd2();
490  }
491  else {
492  elem = NULp;
493  }
494  }
495 
496  if (elem) {
497  Position world = device->rtransform(event.position());
498  error = handleMouse(device, event.type(), event.button(), event.cmd(), world, elem, abspos);
499  }
500 
501  if (event.type() == AW_Mouse_Release) elem = NULp; // forget last clicked SEC_base
502  }
503  }
504 
505  if (error) aw_message(error);
506 }
507 
508 SEC_graphic::SEC_graphic(AW_root *aw_rooti, GBDATA *gb_maini)
509  : update_requested(SEC_UPDATE_RELOAD),
510  load_error(NULp),
511  disp_device(NULp),
512  gb_main(gb_maini),
513  aw_root(aw_rooti),
514  sec_root(new SEC_root),
515  gb_struct(NULp),
516  gb_struct_ref(NULp),
517  last_saved(0)
518 {
519  exports.set_standard_default_padding();
520 }
521 
522 SEC_graphic::~SEC_graphic() {
523  delete sec_root;
524  delete load_error;
525 }
526 
527 static void SEC_structure_changed_cb(GBDATA *gb_seq, SEC_graphic *gfx, GB_CB_TYPE type) {
528  LocallyModify<int> allow_flag_modify(gfx->exports.get_modifying_flag_ref(), -1); // hack, allow flag modification during exit (w/o forcing a refresh)
529 
530  if (type == GB_CB_DELETE) {
531  gfx->gb_struct = NULp;
532  gfx->gb_struct_ref = NULp;
533 
534  gfx->request_update(SEC_UPDATE_RELOAD);
535  }
536  else if (GB_read_clock(gb_seq) > gfx->last_saved) { // not changed by secedit self
537  gfx->request_update(SEC_UPDATE_RELOAD);
538  }
539 }
540 
541 GB_ERROR SEC_graphic::load_from_DB(GBDATA *, const char *) {
543 
544  sec_assert(sec_root->get_db()->canDisplay()); // need a sequence loaded (to fix bugs in versions < 3)
545  sec_root->nail_cursor();
546 
548  // first check timestamp, do not load structure that we have saved !!!!
549  if (gb_struct) {
550  if (GB_read_clock(gb_struct) <= last_saved) return NULp;
551  }
552 
553  // Reset structure:
554  if (gb_struct) {
555  GB_remove_callback(gb_struct, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this)); gb_struct = NULp;
556  GB_remove_callback(gb_struct_ref, GB_CB_ALL, makeDatabaseCallback(SEC_structure_changed_cb, this)); gb_struct_ref = NULp;
557  }
558 
559  request_update(SEC_UPDATE_RECOUNT);
560 
561  if (gb_struct) {
562  this->last_saved = GB_read_clock(gb_struct); // mark as loaded
563  }
564 
565 
566 
567  // Setup new structure:
568  GB_ERROR err = NULp;
569  GBDATA *gb_ali = NULp;
570  {
571  char *helix_name = GBT_get_default_helix(gb_main);
572  char *name = GBT_readOrCreate_string(gb_main, AWAR_HELIX_NAME, helix_name);
573  sec_assert(name);
574 
575  GBDATA *gb_species = GBT_find_SAI(gb_main, name);
576  if (!gb_species) {
577  err = GB_export_errorf("Cannot find helix template SAI '%s'", name);
578  }
579  else {
580  char *ali_name = GBT_get_default_alignment(gb_main);
581  long ali_len = GBT_get_alignment_len(gb_main, ali_name);
582 
583  if (ali_len < 10) {
584  err = GB_export_errorf("alignment '%s' to short to generate helix", ali_name);
585  }
586  else {
587  gb_ali = GB_search(gb_species, ali_name, GB_FIND);
588  if (!gb_ali) {
589  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 !!!
590  }
591  }
592  free(ali_name);
593  }
594 
595  free(name);
596  free(helix_name);
597  }
598 
599  // ------------------------
600  // read structure
601 
602  if (!err) {
603  gb_struct = GB_search(gb_ali, NAME_OF_STRUCT_SEQ, GB_FIND);
604 
605  if (gb_struct) {
606  gb_struct_ref = GB_search(gb_ali, NAME_OF_REF_SEQ, GB_STRING);
607 
608  char *strct = GB_read_string(gb_struct);
609  char *ref = GB_read_string(gb_struct_ref);
610  err = sec_root->read_data(strct, ref);
611  if (err) {
612  err = GBS_global_string("Defect structure in DB (read-error: '%s')", err);
613  }
614 #if defined(CHECK_INTEGRITY)
615  else {
616  sec_root->check_integrity(CHECK_STRUCTURE);
617  }
618 #endif // CHECK_INTEGRITY
619 
620  free(strct);
621  free(ref);
622 
623  // on first load init structure toggler:
624  if (!err) {
625  sec_root->get_db()->init_toggler();
626  }
627  }
628  else {
629  err = "no secondary structure was found in your database";
630  }
631 
632  if (!err) {
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 {
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  exports.request_zoom_reset();
655  }
656  }
657  else {
658  load_error = ARB_strdup(err);
659  exports.request_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 
669 GB_ERROR SEC_graphic::save_to_DB(GBDATA *, const char *) {
671 
672  if (!gb_struct) return NULp; // not loaded, so don't save
673  if (!sec_root) return NULp;
674 
675  char *data = sec_root->buildStructureString();
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 NULp;
694 }
695 
696 GB_ERROR SEC_graphic::read_data_from_db(char **data, char **x_string) const {
697  GB_ERROR error = NULp;
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 
709 GB_ERROR SEC_graphic::write_data_to_db(const char *data, const char *x_string) const {
710  if (!gb_struct) return NULp;
711  if (!sec_root) return NULp;
712 
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 
722 void SEC_graphic::check_for_DB_update(GBDATA *) {
723 }
724 
725 void SEC_graphic::update_structure() {
727 
728  const SEC_db_interface *db = sec_root->get_db();
729 
730  if (db && db->canDisplay()) {
731  if (update_requested & SEC_UPDATE_RELOAD) {
732  GB_ERROR error = load_from_DB(NULp, NULp); // sets change_flag
733  if (error) {
734  error = ta.close(error);
735  aw_message(error);
736  }
737  // clear reload flag + set recount flag:
738  update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_RELOAD)|SEC_UPDATE_RECOUNT);
739  }
740 
741  if (update_requested & SEC_UPDATE_SHOWN_POSITIONS) {
742  sec_root->update_shown_positions();
743  // clear reload flag + set recount flag:
744  update_requested = static_cast<SEC_update_request>((update_requested^SEC_UPDATE_SHOWN_POSITIONS)|SEC_UPDATE_RECOUNT);
745  }
746 
747  if (update_requested & SEC_UPDATE_RECOUNT) {
748  sec_root->invalidate_base_positions();
749  sec_root->relayout();
750 
751  update_requested = static_cast<SEC_update_request>(update_requested^SEC_UPDATE_RECOUNT); // clear recount flag
752  exports.request_refresh();
753  }
754 
755  sec_root->perform_autoscroll();
756  }
757 }
758 
759 void SEC_graphic::notify_synchronized(GBDATA *) {
760  // nothing todo here
761 }
762 
763 void SEC_graphic::show(AW_device *device) {
764  const char *textToDisplay = NULp;
765 
766  sec_assert(sec_root);
767  sec_root->clear_last_drawed_cursor_position();
768 
769  if (sec_root->canDisplay()) {
770  if (sec_root->get_root_loop()) {
771  GB_ERROR paint_error = sec_root->paint(device);
772  if (paint_error) textToDisplay = GBS_global_string("Error: %s", paint_error);
773  }
774  else {
775  if (load_error) textToDisplay = GBS_global_string("Load error: %s", load_error);
776  else textToDisplay = "No structure loaded (yet)";
777  }
778  }
779  else {
780  const SEC_db_interface *db = sec_root->get_db();
781 
782  if (!db) textToDisplay = "Not connected to database";
783  else if (!db->helix()) textToDisplay = "No helix info";
784  else textToDisplay = "No species selected";
785  }
786 
787  if (textToDisplay) { // no structure
788  sec_assert(!strchr(textToDisplay, '\n')); // linefeeds do not work here
789  device->text(SEC_GC_ECOLI, textToDisplay, 0, 0, 0, AW_SCREEN);
790  sec_root->set_last_drawed_cursor_position(LineVector(Origin, ZeroVector));
791  }
792 }
793 
#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:1361
#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:706
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:1880
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:172
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:1681
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:879
#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:1688
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:44
BI_helix * helix() const
Definition: SEC_db.hxx:166
char * GBT_get_default_alignment(GBDATA *gb_main)
Definition: adali.cxx:675
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