source: tags/svn.1.5.4/EDIT4/ED4_terminal.cxx

Last change on this file was 8359, checked in by westram, 12 years ago
  • added 'Never ask again' switch to most modal question dialogs. This is a workaround to make it possible to work with macros where modal questions are used. See also #179
    • added unique IDs to all calls to aw_question / AW_repeated_question::get_answer
    • replaced most calls to aw_popup_ok with aw_message (most of them only worked-around the non-standard way of EDIT4 to show aw_message)
  • added 'Reactivate questions' to all properties menus
  • hardcoded unused default-params from aw_ask_sure, aw_popup_ok + aw_popup_exit
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 52.9 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : ED4_terminal.cxx                                  //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include <ed4_extern.hxx>
12#include "ed4_class.hxx"
13#include "ed4_awars.hxx"
14#include "ed4_edit_string.hxx"
15#include "ed4_block.hxx"
16#include "ed4_nds.hxx"
17#include "ed4_ProteinViewer.hxx"
18
19#include <aw_preset.hxx>
20#include <aw_awar.hxx>
21#include <aw_msg.hxx>
22#include <aw_root.hxx>
23#include <aw_question.hxx>
24#include <awt_seq_colors.hxx>
25#include <st_window.hxx>
26#include <arbdb.h>
27
28// -----------------------------------
29//      static terminal properties
30
31static ED4_object_specification tree_terminal_spec =                       // variables which determine static default properties of predefined (sub-)classes
32{
33    ED4_P_IS_TERMINAL,  // static props
34    ED4_L_TREE,         // level
35    ED4_L_NO_LEVEL,     // allowed children level
36    ED4_L_NO_LEVEL,     // handled object
37    ED4_L_NO_LEVEL,     // restriction level
38    0                   // justification value --no meaning for a terminal
39};
40
41static ED4_object_specification bracket_terminal_spec =
42{
43    ED4_P_IS_TERMINAL,  // static props
44    ED4_L_BRACKET,      // level
45    ED4_L_NO_LEVEL,     // allowed children level
46    ED4_L_NO_LEVEL,     // handled object
47    ED4_L_NO_LEVEL,     // restriction level
48    0                   // justification value --no meaning for a terminal
49};
50
51static ED4_object_specification species_name_terminal_spec =
52{
53    ED4_P_IS_TERMINAL,  // static props
54    ED4_L_SPECIES_NAME, // level
55    ED4_L_NO_LEVEL,     // allowed children level
56    ED4_L_SPECIES,      // handled object
57    ED4_L_NO_LEVEL,     // restriction level
58    0                   // justification value --no meaning for a terminal
59};
60
61static ED4_object_specification sequence_info_terminal_spec =
62{
63    ED4_P_IS_TERMINAL,  // static props
64    ED4_L_SEQUENCE_INFO, // level
65    ED4_L_NO_LEVEL,     // allowed children level
66    ED4_L_SEQUENCE,     // handled object
67    ED4_L_NO_LEVEL,     // restriction level
68    0                   // justification value --no meaning for a terminal
69};
70
71static ED4_object_specification sequence_terminal_spec =
72{
73    ED4_P_IS_TERMINAL,     // static props
74    ED4_L_SEQUENCE_STRING, // level
75    ED4_L_NO_LEVEL,        // allowed children level
76    ED4_L_NO_LEVEL,        // handled object
77    ED4_L_NO_LEVEL,        // restriction level
78    0                      // justification value --no meaning for a terminal
79};
80
81static ED4_object_specification pure_text_terminal_spec =
82{
83    ED4_P_IS_TERMINAL,     // static props
84    ED4_L_PURE_TEXT,       // level
85    ED4_L_NO_LEVEL,        // allowed children level
86    ED4_L_NO_LEVEL,        // handled object
87    ED4_L_NO_LEVEL,        // restriction level
88    0                      // justification value --no meaning for a terminal
89};
90
91static ED4_object_specification spacer_terminal_spec =
92{
93    ED4_P_IS_TERMINAL,     // static props
94    ED4_L_SPACER,          // level
95    ED4_L_NO_LEVEL,        // allowed children level
96    ED4_L_NO_LEVEL,        // handled object
97    ED4_L_NO_LEVEL,        // restriction level
98    0                      // justification value --no meaning for a terminal
99};
100
101static ED4_object_specification line_terminal_spec =
102{
103    ED4_P_IS_TERMINAL,     // static props
104    ED4_L_LINE,            // level
105    ED4_L_NO_LEVEL,        // allowed children level
106    ED4_L_NO_LEVEL,        // handled object
107    ED4_L_NO_LEVEL,        // restriction level
108    0                      // justification value --no meaning for a terminal
109};
110
111static ED4_object_specification column_stat_terminal_spec =
112{
113    ED4_P_IS_TERMINAL,     // static props
114    ED4_L_COL_STAT,        // level
115    ED4_L_NO_LEVEL,        // allowed children level
116    ED4_L_NO_LEVEL,        // handled object
117    ED4_L_NO_LEVEL,        // restriction level
118    0                      // justification value --no meaning for a terminal
119};
120
121
122char *ED4_terminal::resolve_pointer_to_string_copy(int *str_len) const {
123    int         len;
124    const char *s = resolve_pointer_to_char_pntr(&len);
125    char       *t = GB_strduplen(s, len); // space for zero byte is allocated by GB_strduplen
126
127    if (str_len) *str_len = len;
128    return t;
129}
130
131const char *ED4_terminal::resolve_pointer_to_char_pntr(int *str_len) const
132{
133    GB_TYPES    gb_type;
134    const char *db_pointer = NULL;
135    GBDATA     *gbd        = get_species_pointer();
136
137    if (!gbd) {
138        if (str_len) {
139            if (id) *str_len = strlen(id);
140            else *str_len    = 0;
141        }
142        return id; // if we don't have a link to the database we have to use our id
143    }
144
145    GB_push_transaction(GLOBAL_gb_main);
146
147    const char *copy_of = 0; // if set, return a copy of this string
148
149    gb_type = GB_read_type(gbd);
150#if defined(WARN_TODO)
151#warning temporary workaround - gb_type GB_INT and GB_FLOAT in the switch directive must not be displayed but ignored
152#endif
153    switch (gb_type)
154    {
155        case GB_STRING:
156            db_pointer = GB_read_char_pntr(gbd);
157            if (str_len) {
158                *str_len = GB_read_string_count(gbd);
159                e4_assert(*str_len == (int)strlen(db_pointer));
160            }
161            break;
162        case GB_BITS:
163            db_pointer = GB_read_bits_pntr(gbd, '.', '+');
164            if (str_len) {
165                *str_len = GB_read_bits_count(gbd);
166                e4_assert(*str_len == (int)strlen(db_pointer));
167            }
168            break;
169        case GB_BYTES:
170            db_pointer = GB_read_bytes_pntr(gbd);
171            if (str_len) {
172                *str_len = GB_read_bytes_count(gbd);
173                e4_assert(*str_len == (int)strlen(db_pointer));
174            }
175            break;
176        case GB_DB:
177            copy_of = "GB_DB";
178            break;
179        case GB_INT: // FIXME: temporary Workaround
180            copy_of = "GB_INT";
181            break;
182        case GB_INTS:
183            copy_of = "GB_INTS";
184            break;
185        case GB_FLOAT: // FIXME: temporary Workaround
186            copy_of = "GB_FLOAT";
187            break;
188        case GB_FLOATS:
189            copy_of = "GB_FLOATS";
190            break;
191        default:
192            printf("Unknown data type - Please contact administrator\n");
193            e4_assert(0);
194            break;
195    }
196
197    if (copy_of) {
198        e4_assert(db_pointer == 0);
199
200        int len    = strlen(copy_of);
201        db_pointer = GB_strduplen(copy_of, len);
202
203        if (str_len) *str_len = len;
204    }
205
206    GB_pop_transaction(GLOBAL_gb_main);
207
208    return db_pointer;
209}
210
211GB_ERROR ED4_terminal::write_sequence(const char *seq, int seq_len)
212{
213    GB_ERROR err = 0;
214    GBDATA *gbd = get_species_pointer();
215    e4_assert(gbd); // we must have a link to the database!
216
217    GB_push_transaction(GLOBAL_gb_main);
218
219    int   old_seq_len;
220    char *old_seq = resolve_pointer_to_string_copy(&old_seq_len);
221
222    bool allow_write_data = true;
223    if (ED4_ROOT->aw_root->awar(ED4_AWAR_ANNOUNCE_CHECKSUM_CHANGES)->read_int()) {
224        long old_checksum = GBS_checksum(old_seq, 1, "-.");
225        long new_checksum = GBS_checksum(seq, 1, "-.");
226
227        if (old_checksum != new_checksum) {
228            if (aw_question(NULL, "Checksum changed!", "Allow, Reject") == 1) {
229                allow_write_data = false;
230            }
231
232        }
233    }
234
235    if (allow_write_data) {
236        GB_TYPES gb_type = GB_read_type(gbd);
237        switch (gb_type) {
238            case GB_STRING: {
239                err = GB_write_string(gbd, seq);
240                break;
241            }
242            case GB_BITS: {
243                err = GB_write_bits(gbd, seq, seq_len, ".-");
244                break;
245            }
246            default: {
247                e4_assert(0);
248                break;
249            }
250        }
251    }
252
253    GB_pop_transaction(GLOBAL_gb_main);
254
255    if (!err && dynamic_prop&ED4_P_CONSENSUS_RELEVANT) {
256        if (old_seq) {
257            actual_timestamp = GB_read_clock(GLOBAL_gb_main);
258
259            get_parent(ED4_L_MULTI_SPECIES)->to_multi_species_manager()
260                ->check_bases_and_rebuild_consensi(old_seq, old_seq_len, get_parent(ED4_L_SPECIES)->to_species_manager(), ED4_U_UP); // bases_check
261        }
262        else {
263            aw_message("Couldn't read old sequence data");
264        }
265
266        set_refresh();
267        parent->refresh_requested_by_child();
268    }
269
270    if (old_seq) free(old_seq);
271
272    return err;
273}
274
275
276ED4_returncode ED4_terminal::remove_callbacks()                     // removes callbacks and gb_alignment
277{
278    if (get_species_pointer()) {
279        set_species_pointer(0);
280        flag.deleted = 1;
281        dynamic_prop = (ED4_properties) (dynamic_prop & ~ED4_P_CURSOR_ALLOWED);
282
283        set_refresh();
284        parent->refresh_requested_by_child();
285    }
286    return ED4_R_OK;
287}
288
289static ARB_ERROR ed4_remove_species_manager_callbacks(ED4_base *base) {
290    if (base->is_species_manager()) {
291        base->to_species_manager()->remove_all_callbacks();
292    }
293    return NULL;
294}
295
296ED4_returncode ED4_terminal::kill_object()
297{
298    ED4_species_manager *species_manager = get_parent(ED4_L_SPECIES)->to_species_manager();
299    ED4_manager         *parent_manager  = species_manager->parent;
300    ED4_group_manager   *group_manager   = 0;
301
302    if (species_manager->flag.is_consensus)                         // whole group has to be killed
303    {
304        if (parent_manager->is_multi_species_manager() && ED4_new_species_multi_species_manager()==parent_manager) {
305            aw_message("This group has to exist - deleting it isn't allowed");
306            return ED4_R_IMPOSSIBLE;
307        }
308
309        parent_manager = species_manager;
310        while (!parent_manager->is_group_manager()) {
311            parent_manager = parent_manager->parent;
312        }
313        group_manager = parent_manager->to_group_manager();
314
315        parent_manager = group_manager->parent;
316        parent_manager->children->delete_member(group_manager);
317
318        GB_push_transaction (GLOBAL_gb_main);
319        parent_manager->update_consensus(parent_manager, NULL,   group_manager);
320        parent_manager->rebuild_consensi(parent_manager,   ED4_U_UP);
321        GB_pop_transaction (GLOBAL_gb_main);
322        species_manager = NULL;
323    }
324    else
325    {
326        parent_manager->children->delete_member(species_manager);
327        GB_push_transaction (GLOBAL_gb_main);
328        parent_manager->update_consensus(parent_manager,   NULL, species_manager);
329        parent_manager->rebuild_consensi(species_manager, ED4_U_UP);
330        GB_pop_transaction (GLOBAL_gb_main);
331    }
332
333    ED4_device_manager *device_manager = ED4_ROOT->main_manager
334        ->get_defined_level(ED4_L_GROUP)->to_group_manager()
335        ->get_defined_level(ED4_L_DEVICE)->to_device_manager();
336
337    for (int i=0; i<device_manager->children->members(); i++) { // when killing species numbers have to be recalculated
338        ED4_base *member = device_manager->children->member(i);
339
340        if (member->is_area_manager()) {
341            member->to_area_manager()->get_defined_level(ED4_L_MULTI_SPECIES)->to_multi_species_manager()->generate_id_for_groups();
342        }
343    }
344
345    if (species_manager) {
346        species_manager->parent = NULL;
347        species_manager->remove_all_callbacks();
348        delete species_manager;
349    }
350
351    if (group_manager) {
352        group_manager->parent = NULL;
353        group_manager->route_down_hierarchy(ed4_remove_species_manager_callbacks).expect_no_error();
354        delete group_manager;
355    }
356
357    return ED4_R_OK;
358}
359
360ED4_base *ED4_terminal::get_competent_clicked_child(AW_pos /* x */, AW_pos /* y */, ED4_properties /* relevant_prop */)
361{
362    e4_assert(0);
363    return NULL;
364}
365
366ED4_returncode   ED4_terminal::handle_move(ED4_move_info * /* moveinfo */)
367{
368    e4_assert(0);
369    return ED4_R_IMPOSSIBLE;
370}
371
372ED4_returncode  ED4_terminal::move_requested_by_child(ED4_move_info * /* moveinfo */)
373{
374    e4_assert(0);
375    return ED4_R_IMPOSSIBLE;
376}
377
378
379ED4_base *ED4_terminal::get_competent_child(AW_pos /* x */, AW_pos /* y */, ED4_properties /* relevant_prop */)
380{
381    e4_assert(0);
382    return NULL;
383}
384
385ED4_returncode ED4_terminal::resize_requested_by_child()
386{
387    e4_assert(0);
388    return ED4_R_IMPOSSIBLE;
389}
390
391ED4_returncode ED4_terminal::draw_drag_box(AW_pos x, AW_pos y, GB_CSTR text, int cursor_y)      // draws drag box of object at location abs_x, abs_y
392{
393    ED4_index      i;
394    AW_pos         drag_x, drag_y;
395    AW_pos         drag_line_x0[3], drag_line_y0[3];
396    AW_pos         drag_line_x1[3], drag_line_y1[3];
397    ED4_base      *drag_target = NULL;
398    AW_pos         target_x, target_y;
399    ED4_extension  location;
400
401    if (cursor_y!=-1) {
402        ED4_device_manager *device_manager = ED4_ROOT->main_manager->search_spec_child_rek(ED4_L_DEVICE)->to_device_manager();
403        drag_x = 0;
404        drag_y = (AW_pos)cursor_y; // cursor_y is already in world coordinates!
405        location.position[X_POS] = drag_x;
406        location.position[Y_POS] = drag_y;
407        device_manager->children->search_target_species(&location, ED4_P_HORIZONTAL, &drag_target, ED4_L_NO_LEVEL);
408
409        if (drag_target && !is_sequence_info_terminal()) {
410            drag_target->calc_world_coords (&target_x, &target_y);
411            ED4_ROOT->world_to_win_coords(ED4_ROOT->get_aww(), &target_x, &target_y);
412#define ARROW_LENGTH 3
413            drag_line_x0[0] = target_x + 5;                                     // horizontal
414            drag_line_y0[0] = target_y + drag_target->extension.size[HEIGHT];
415            drag_line_x1[0] = drag_line_x0[0] + 50;
416            drag_line_y1[0] = target_y + drag_target->extension.size[HEIGHT];
417
418            drag_line_x0[1] = drag_line_x0[0] -ARROW_LENGTH;                                // arrow
419            drag_line_y0[1] = drag_line_y0[0] -ARROW_LENGTH;
420            drag_line_x1[1] = drag_line_x0[0];
421            drag_line_y1[1] = drag_line_y0[0];
422
423            drag_line_x0[2] = drag_line_x0[0] -ARROW_LENGTH;                                // arrow
424            drag_line_y0[2] = drag_line_y0[0] + ARROW_LENGTH;
425            drag_line_x1[2] = drag_line_x0[0];
426            drag_line_y1[2] = drag_line_y0[0];
427#undef ARROW_LENGTH
428            for (i = 0; i <= 2; i++) {
429                ED4_ROOT->get_device()->line(ED4_G_DRAG, drag_line_x0[i], drag_line_y0[i], drag_line_x1[i], drag_line_y1[i], AW_SCREEN);
430            }
431        }
432    }
433
434    if (text != NULL) {
435        ED4_ROOT->get_device()->text(ED4_G_DRAG, text, (x + 20), (y + INFO_TERM_TEXT_YOFFSET), 0, AW_SCREEN);
436    }
437
438    return (ED4_R_OK);
439}
440
441ED4_returncode  ED4_terminal::move_requested_by_parent(ED4_move_info *) { // handles a move request coming from parent
442    e4_assert(0);
443    return (ED4_R_IMPOSSIBLE);
444}
445
446#if defined(DEBUG) && 1
447static inline void dumpEvent(const char *where, AW_event *event) {
448    printf("%s: x=%i y=%i\n", where, event->x, event->y);
449}
450#else
451#define dumpEvent(w, e)
452#endif
453
454ED4_returncode  ED4_terminal::event_sent_by_parent(AW_event *event, AW_window *aww)             // handles an input event coming from parent
455{
456    static ED4_species_name_terminal    *dragged_name_terminal = 0;
457    static int              dragged_was_selected;
458    static bool                 pressed_left_button = 0;
459    static int              other_x, other_y; // coordinates of last event
460    static bool                 right_button_started_on_sequence_term = 0;
461
462    switch (event->type) {
463        case AW_Mouse_Press: {
464            switch (event->button) {
465                case ED4_B_LEFT_BUTTON: {
466                    pressed_left_button = 0;
467                    if (is_species_name_terminal()) {
468                        switch (ED4_ROOT->species_mode) {
469                            case ED4_SM_KILL: {
470                                if (flag.selected) {
471                                    ED4_ROOT->remove_from_selected(this);
472                                }
473                                kill_object();
474                                ED4_ROOT->refresh_all_windows(0);
475                                return ED4_R_BREAK;
476                            }
477                            case ED4_SM_MOVE: {
478                                dragged_name_terminal = to_species_name_terminal();
479                                pressed_left_button = 1;
480                                other_x = event->x;
481                                other_y = event->y;
482
483                                if (!flag.selected) {
484                                    ED4_ROOT->add_to_selected(dragged_name_terminal);
485                                    dragged_was_selected = 0;
486                                    ED4_ROOT->main_manager->Show();
487                                }
488                                else {
489                                    dragged_was_selected = 1;
490                                }
491                                break;
492                            }
493                            case ED4_SM_MARK: {
494                                ED4_species_manager *species_man = get_parent(ED4_L_SPECIES)->to_species_manager();
495                                GBDATA *gbd = species_man->get_species_pointer();
496
497                                if (gbd) {
498                                    GB_write_flag(gbd, !GB_read_flag(gbd));
499                                    set_refresh();
500                                    parent->refresh_requested_by_child();
501                                    // ProtView: Refreshing AA_sequence terminals
502                                    if (ED4_ROOT->alignment_type ==  GB_AT_DNA) {
503                                        PV_RefreshWindow(aww->get_root());
504                                    }
505                                }
506                                break;
507                            }
508                            default: {
509                                e4_assert(0);
510                                break;
511                            }
512                        }
513                    }
514                    else if (is_bracket_terminal()) { // fold/unfold group
515                        if (dynamic_prop & ED4_P_IS_FOLDED) {
516                            ED4_ROOT->main_manager->unfold_group(id);
517                        }
518                        else {
519                            ED4_ROOT->main_manager->fold_group(id);
520                        }
521                        ED4_ROOT->refresh_all_windows(1);
522                    }
523                    else {
524                        if (dynamic_prop & ED4_P_CURSOR_ALLOWED) {
525                            ED4_no_dangerous_modes();
526                            ED4_ROOT->get_ed4w()->cursor.show_clicked_cursor(event->x, this);
527                        }
528                    }
529                    break;
530                }
531                case ED4_B_RIGHT_BUTTON: {
532                    right_button_started_on_sequence_term = 0;
533                    if (is_bracket_terminal()) { // right click on bracket terminal
534                        ED4_base *group = get_parent(ED4_L_GROUP);
535                        if (group) {
536                            ED4_multi_species_manager *multi_man = group->to_group_manager()->get_defined_level(ED4_L_MULTI_SPECIES)->to_multi_species_manager();
537                            multi_man->deselect_all_species();
538                            ED4_correctBlocktypeAfterSelection();
539                            ED4_ROOT->refresh_all_windows(0);
540                        }
541                    }
542                    else if (is_species_name_terminal()) {
543                        ED4_species_manager *species_man = get_parent(ED4_L_SPECIES)->to_species_manager();
544
545                        if (parent->flag.is_consensus) { // click on consensus-name
546                            ED4_multi_species_manager *multi_man = parent->get_parent(ED4_L_MULTI_SPECIES)->to_multi_species_manager();
547                            int species = multi_man->get_no_of_species();
548                            int selected = multi_man->get_no_of_selected_species();
549
550                            if (selected==species) { // all species selected => deselect all
551                                multi_man->deselect_all_species();
552                            }
553                            else { // otherwise => select all
554                                multi_man->select_all_species();
555                            }
556
557                            ED4_correctBlocktypeAfterSelection();
558                            ED4_ROOT->refresh_all_windows(0);
559                            return (ED4_R_BREAK);
560                        }
561                        else if (species_man->flag.is_SAI) {
562                            ; // don't mark SAIs
563                        }
564                        else { // click on species name
565                            if (!flag.selected) { // select if not selected
566                                if (ED4_ROOT->add_to_selected(this) == ED4_R_OK) {
567                                    ED4_correctBlocktypeAfterSelection();
568                                    ED4_ROOT->refresh_all_windows(0);
569                                }
570                            }
571                            else { // deselect if already selected
572                                ED4_ROOT->remove_from_selected(this);
573                                ED4_correctBlocktypeAfterSelection();
574                                ED4_ROOT->refresh_all_windows(0);
575                                return (ED4_R_BREAK);   // in case we were called by event_to selected()
576                            }
577                        }
578                    }
579                    else if (is_sequence_terminal()) {
580                        dumpEvent("Press", event);
581
582                        ED4_no_dangerous_modes();
583                        ED4_setColumnblockCorner(event, to_sequence_terminal()); // mark columnblock
584                        right_button_started_on_sequence_term = 1;
585                        ED4_ROOT->refresh_all_windows(0);
586                    }
587                    break;
588                }
589                case ED4_B_MIDDLE_BUTTON: {
590                    break;
591                }
592            }
593            break;
594        }
595        case AW_Mouse_Drag: {
596            switch (event->button) {
597                case ED4_B_LEFT_BUTTON: {
598                    if (dragged_name_terminal) {
599                        ED4_selection_entry *sel_info = dragged_name_terminal->selection_info;
600
601                        if (pressed_left_button) {
602                            AW_pos world_x, world_y;
603
604                            dragged_name_terminal->calc_world_coords(&world_x, &world_y);
605                            ED4_ROOT->world_to_win_coords(aww, &world_x, &world_y);
606
607                            sel_info->drag_old_x = world_x;
608                            sel_info->drag_old_y = world_y;
609                            sel_info->drag_off_x = world_x-other_x;
610                            sel_info->drag_off_y = world_y-other_y;
611                            sel_info->old_event_y = -1;
612
613                            pressed_left_button = 0;
614                        }
615
616                        GB_CSTR text = dragged_name_terminal->get_displayed_text();
617
618                        if (dragged_name_terminal->flag.dragged) {
619                            dragged_name_terminal->draw_drag_box(sel_info->drag_old_x, sel_info->drag_old_y, text, sel_info->old_event_y);
620                        }
621
622                        AW_pos new_x = sel_info->drag_off_x + event->x;
623                        AW_pos new_y = sel_info->drag_off_y + event->y;
624
625                        dragged_name_terminal->draw_drag_box(new_x, new_y, text, event->y); // @@@ event->y ist falsch, falls vertikal gescrollt ist!
626
627                        sel_info->drag_old_x = new_x;
628                        sel_info->drag_old_y = new_y;
629                        sel_info->old_event_y = event->y;
630
631                        dragged_name_terminal->flag.dragged = 1;
632                    }
633
634                    break;
635                }
636                case ED4_B_RIGHT_BUTTON: {
637                    if (is_sequence_terminal() && right_button_started_on_sequence_term) {
638                        ED4_no_dangerous_modes();
639                        ED4_setColumnblockCorner(event, to_sequence_terminal()); // mark columnblock
640                        ED4_ROOT->refresh_all_windows(0);
641                    }
642                    break;
643                }
644            }
645            break;
646        }
647        case AW_Mouse_Release: {
648            switch (event->button) {
649                case ED4_B_LEFT_BUTTON: {
650                    if (dragged_name_terminal) {
651                        if (dragged_name_terminal->flag.dragged) {
652                            {
653                                char                *db_pointer = dragged_name_terminal->resolve_pointer_to_string_copy();
654                                ED4_selection_entry *sel_info   = dragged_name_terminal->selection_info;
655
656                                dragged_name_terminal->draw_drag_box(sel_info->drag_old_x, sel_info->drag_old_y, db_pointer, sel_info->old_event_y);
657                                dragged_name_terminal->flag.dragged = 0;
658
659                                free(db_pointer);
660                            }
661                            {
662                                ED4_move_info mi;
663
664                                mi.object = dragged_name_terminal;
665                                mi.end_x = event->x;
666                                mi.end_y = event->y;
667                                mi.mode = ED4_M_FREE;
668                                mi.preferred_parent = ED4_L_NO_LEVEL;
669
670                                dragged_name_terminal->parent->move_requested_by_child(&mi);
671                            }
672                            {
673                                ED4_device_manager *device_manager = ED4_ROOT->main_manager
674                                    ->get_defined_level(ED4_L_GROUP)->to_group_manager()
675                                    ->get_defined_level(ED4_L_DEVICE)->to_device_manager();
676
677                                int i;
678                                for (i=0; i<device_manager->children->members(); i++) { // when moving species numbers have to be recalculated
679                                    ED4_base *member = device_manager->children->member(i);
680
681                                    if (member->is_area_manager()) {
682                                        member->to_area_manager()->get_defined_level(ED4_L_MULTI_SPECIES)->to_multi_species_manager()->generate_id_for_groups();
683                                    }
684                                }
685                            }
686                        }
687                        if (!dragged_was_selected) {
688                            ED4_ROOT->remove_from_selected(dragged_name_terminal);
689                        }
690
691                        ED4_expose_cb(ED4_ROOT->get_aww(), 0, 0);
692
693                        pressed_left_button = 0;
694                        dragged_name_terminal = 0;
695                    }
696                    break;
697                }
698
699                case ED4_B_RIGHT_BUTTON: {
700                    if (is_sequence_terminal() && right_button_started_on_sequence_term) {
701                        dumpEvent("Relea", event);
702                        ED4_no_dangerous_modes();
703                        ED4_setColumnblockCorner(event, to_sequence_terminal()); // mark columnblock
704                        ED4_ROOT->refresh_all_windows(0);
705                    }
706                    break;
707                }
708            }
709            break;
710        }
711        default:
712            e4_assert(0);
713            break;
714    }
715    return (ED4_R_OK);
716}
717
718
719ED4_returncode  ED4_terminal::calc_size_requested_by_parent()
720{
721    return ED4_R_OK;
722}
723
724short ED4_terminal::calc_bounding_box()
725{
726    short            bb_changed = 0;
727    ED4_list_elem   *current_list_elem;
728    ED4_base        *object;
729
730    if (width_link) {
731        if (extension.size[WIDTH] != width_link->extension.size[WIDTH]) {   // all bounding Boxes have the same size !!!
732            extension.size[WIDTH] = width_link->extension.size[WIDTH];
733            bb_changed = 1;
734        }
735    }
736
737    if (height_link) {
738        if (extension.size[HEIGHT] != height_link->extension.size[HEIGHT]) {
739            extension.size[HEIGHT] = height_link->extension.size[HEIGHT];
740            bb_changed = 1;
741        }
742    }
743
744
745    if (bb_changed) {
746        current_list_elem = linked_objects.first();
747        while (current_list_elem) {
748            object = (ED4_base *) current_list_elem->elem();
749
750            if (object != NULL) {
751                object->link_changed(this);
752            }
753
754            current_list_elem = current_list_elem->next();
755        }
756
757        clear_background();
758
759        set_refresh();
760        parent->refresh_requested_by_child();
761    }
762
763    return (bb_changed);
764}
765
766ED4_returncode ED4_terminal::Show(int /* refresh_all */, int /* is_cleared */)
767{
768    e4_assert(0);
769    return ED4_R_IMPOSSIBLE;
770}
771
772
773ED4_returncode ED4_terminal::draw(int /* only_text */)
774{
775    e4_assert(0);
776    return ED4_R_IMPOSSIBLE;
777}
778
779
780ED4_returncode ED4_terminal::resize_requested_by_parent()
781{
782    if (update_info.resize) { // likes to resize?
783        if (calc_bounding_box()) { // size changed?
784            parent->resize_requested_by_child(); // tell parent!
785        }
786    }
787
788    return ED4_R_OK;
789}
790
791
792ED4_returncode ED4_terminal::set_refresh(int clear)                 // sets refresh flag of current object
793{
794    update_info.set_refresh(1);
795    update_info.set_clear_at_refresh(clear);
796    return (ED4_R_OK);
797}
798
799
800ED4_base* ED4_terminal::search_ID(const char *temp_id)
801{
802    if (id && strcmp(temp_id, id) == 0) return (this);
803    return (NULL);
804}
805
806
807int ED4_terminal::adjust_clipping_rectangle() {
808    // set scrolling area in AW_MIDDLE_AREA
809    AW_pos x, y;
810    calc_world_coords(&x, &y);
811    ED4_ROOT->world_to_win_coords(ED4_ROOT->get_aww(), &x, &y);
812
813    return ED4_ROOT->get_device()->reduceClipBorders(int(y), int(y+extension.size[HEIGHT]-1), int(x), int(x+extension.size[WIDTH]-1));
814}
815
816
817
818ED4_terminal::ED4_terminal(GB_CSTR temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
819    ED4_base(temp_id, x, y, width, height, temp_parent)
820{
821    memset((char*)&flag, 0, sizeof(flag));
822    selection_info   = 0;
823    actual_timestamp = 0;
824}
825
826
827ED4_terminal::~ED4_terminal()
828{
829    if (selection_info) {
830        delete selection_info;
831    }
832    ED4_cursor& cursor = ED4_ROOT->get_ed4w()->cursor;
833    if (this == cursor.owner_of_cursor) {
834        cursor.init();
835    }
836}
837
838ED4_tree_terminal::ED4_tree_terminal(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
839    : ED4_terminal(temp_id, x, y, width, height, temp_parent)
840{
841    spec = &(tree_terminal_spec);
842}
843
844ED4_returncode ED4_tree_terminal::Show(int IF_ASSERTION_USED(refresh_all), int is_cleared)
845{
846    e4_assert(update_info.refresh || refresh_all);
847    ED4_ROOT->get_device()->push_clip_scale();
848    if (adjust_clipping_rectangle()) {
849        if (update_info.clear_at_refresh && !is_cleared) {
850            clear_background();
851        }
852        draw();
853    }
854    ED4_ROOT->get_device()->pop_clip_scale();
855
856    return (ED4_R_OK);
857}
858
859
860
861ED4_returncode ED4_tree_terminal::draw(int /* only_text */)                  // draws bounding box of object
862{
863    AW_pos  x, y;
864    AW_pos  text_x, text_y;
865    char   *db_pointer;
866
867    calc_world_coords(&x, &y);
868    ED4_ROOT->world_to_win_coords(ED4_ROOT->get_aww(), &x, &y);
869
870    text_x = x + CHARACTEROFFSET;                           // don't change
871    text_y = y + SEQ_TERM_TEXT_YOFFSET;
872
873    db_pointer = resolve_pointer_to_string_copy();
874    ED4_ROOT->get_device()->text(ED4_G_STANDARD, db_pointer, text_x, text_y, 0, AW_SCREEN);
875    free(db_pointer);
876
877    return (ED4_R_OK);
878}
879
880ED4_tree_terminal::~ED4_tree_terminal()
881{
882}
883
884ED4_bracket_terminal::ED4_bracket_terminal(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
885    : ED4_terminal(temp_id, x, y, width, height, temp_parent)
886{
887    spec = &(bracket_terminal_spec);
888}
889
890ED4_returncode ED4_bracket_terminal::Show(int IF_ASSERTION_USED(refresh_all), int is_cleared)
891{
892    e4_assert(update_info.refresh || refresh_all);
893    ED4_ROOT->get_device()->push_clip_scale();
894    if (adjust_clipping_rectangle()) {
895        if (update_info.clear_at_refresh && !is_cleared) {
896            clear_background();
897        }
898        draw();
899    }
900    ED4_ROOT->get_device()->pop_clip_scale();
901
902    return ED4_R_OK;
903}
904
905
906ED4_returncode ED4_bracket_terminal::draw(int /* only_text */)                   // draws bounding box of object
907{
908    ED4_index   i;
909    AW_pos      x, y,
910        width  = extension.size[WIDTH] - 1,
911        height = extension.size[HEIGHT] - 1,
912        margin = 0;
913    AW_pos      line_x0[3], line_y0[3];
914    AW_pos      line_x1[3], line_y1[3];
915    AW_pos      arrow_x0[6], arrow_y0[6];
916    AW_pos      arrow_x1[6], arrow_y1[6];
917
918
919    calc_world_coords(&x, &y);
920    ED4_ROOT->world_to_win_coords(ED4_ROOT->get_aww(), &x, &y);
921
922    line_x0[0] = x + margin + 2;
923    line_y0[0] = y + margin + 2;
924    line_x1[0] = x + width - margin + 2;
925    line_y1[0] = y + margin + 2;
926
927    line_x0[1] = x + width - margin + 2;
928    line_y0[1] = y + height - margin - 2;
929    line_x1[1] = x + margin + 2;
930    line_y1[1] = y + height - margin - 2;
931
932    line_x0[2] = x + margin + 2;
933    line_y0[2] = y + height - margin - 2;
934    line_x1[2] = x + margin + 2;
935    line_y1[2] = y + margin + 2;
936
937    ED4_group_manager *group_man = get_parent(ED4_L_GROUP)->to_group_manager();
938    ED4_multi_species_manager *multi_man = group_man->get_defined_level(ED4_L_MULTI_SPECIES)->to_multi_species_manager();
939    if (multi_man->get_no_of_selected_species()) {  // if multi_species_manager contains selected species
940        ED4_ROOT->get_device()->box(ED4_G_SELECTED, true, x, y, extension.size[WIDTH], extension.size[HEIGHT]);
941    }
942
943    if (dynamic_prop & ED4_P_IS_FOLDED) { // paint triangle for folded group
944        arrow_x0[0] = x + margin + 4;
945        arrow_y0[0] = y + margin + 4 + 0;
946        arrow_x1[0] = x + margin + 4;
947        arrow_y1[0] = y + margin + 4 + 10;
948
949        arrow_x0[1] = x + margin + 5;
950        arrow_y0[1] = y + margin + 4 + 1;
951        arrow_x1[1] = x + margin + 5;
952        arrow_y1[1] = y + margin + 4 + 9;
953
954        arrow_x0[2] = x + margin + 6;
955        arrow_y0[2] = y + margin + 4 + 2;
956        arrow_x1[2] = x + margin + 6;
957        arrow_y1[2] = y + margin + 4 + 8;
958
959        arrow_x0[3] = x + margin + 7;
960        arrow_y0[3] = y + margin + 4 + 3;
961        arrow_x1[3] = x + margin + 7;
962        arrow_y1[3] = y + margin + 4 + 7;
963
964        arrow_x0[4] = x + margin + 8;
965        arrow_y0[4] = y + margin + 4 + 4;
966        arrow_x1[4] = x + margin + 8;
967        arrow_y1[4] = y + margin + 4 + 6;
968
969        arrow_x0[5] = x + margin + 9;
970        arrow_y0[5] = y + margin + 4 + 5;
971        arrow_x1[5] = x + margin + 9;
972        arrow_y1[5] = y + margin + 4 + 5;
973
974        for (i = 0; i < 6; i++) {
975            ED4_ROOT->get_device()->line(ED4_G_STANDARD, arrow_x0[i], arrow_y0[i], arrow_x1[i], arrow_y1[i], AW_SCREEN);
976        }
977    }
978    else {
979        arrow_x0[0] = x + margin + 4 + 0;
980        arrow_y0[0] = y + margin + 4;
981        arrow_x1[0] = x + margin + 4 + 4;
982        arrow_y1[0] = y + margin + 4;
983
984        arrow_x0[1] = x + margin + 4 + 0;
985        arrow_y0[1] = y + margin + 5;
986        arrow_x1[1] = x + margin + 4 + 4;
987        arrow_y1[1] = y + margin + 5;
988
989        arrow_x0[2] = x + margin + 4 + 1;
990        arrow_y0[2] = y + margin + 6;
991        arrow_x1[2] = x + margin + 4 + 3;
992        arrow_y1[2] = y + margin + 6;
993
994        arrow_x0[3] = x + margin + 4 + 1;
995        arrow_y0[3] = y + margin + 7;
996        arrow_x1[3] = x + margin + 4 + 3;
997        arrow_y1[3] = y + margin + 7;
998
999        arrow_x0[4] = x + margin + 4 + 2;
1000        arrow_y0[4] = y + margin + 8;
1001        arrow_x1[4] = x + margin + 4 + 2;
1002        arrow_y1[4] = y + margin + 8;
1003
1004        arrow_x0[5] = x + margin + 4 + 2;
1005        arrow_y0[5] = y + margin + 9;
1006        arrow_x1[5] = x + margin + 4 + 2;
1007        arrow_y1[5] = y + margin + 9;
1008
1009        for (i = 0; i < 6; i++) {
1010            ED4_ROOT->get_device()->line(ED4_G_STANDARD, arrow_x0[i], arrow_y0[i], arrow_x1[i], arrow_y1[i], AW_SCREEN);
1011        }
1012    }
1013
1014    for (i = 0; i <= 2; i++) {
1015        ED4_ROOT->get_device()->line(ED4_G_STANDARD, line_x0[i], line_y0[i], line_x1[i], line_y1[i], AW_SCREEN);
1016    }
1017
1018    return (ED4_R_OK);
1019}
1020
1021ED4_bracket_terminal::~ED4_bracket_terminal()
1022{
1023}
1024
1025ED4_species_name_terminal::ED4_species_name_terminal(GB_CSTR temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1026    ED4_text_terminal(temp_id, x, y, width, height, temp_parent)
1027{
1028    spec = &(species_name_terminal_spec);
1029}
1030
1031
1032ED4_species_name_terminal::~ED4_species_name_terminal()
1033{
1034}
1035
1036#define MAXNAMELEN MAXSPECIESWIDTH
1037#define BUFFERSIZE (MAXNAMELEN<<1)
1038GB_CSTR ED4_species_name_terminal::get_displayed_text() const
1039{
1040    static char *real_name;
1041    static int allocatedSize;
1042
1043    if (!real_name || allocatedSize<(BUFFERSIZE+1)) {
1044        free(real_name);
1045        allocatedSize = BUFFERSIZE+1;
1046        real_name = (char*)malloc(allocatedSize);
1047    }
1048    memset(real_name, 0, allocatedSize);
1049
1050    if (parent->flag.is_consensus) {
1051        char *db_pointer = resolve_pointer_to_string_copy();
1052        char *bracket = strchr(db_pointer, '(');
1053
1054        if (bracket) {
1055            int bracket_len = strlen(bracket);
1056            int name_len = bracket-db_pointer;
1057
1058            if (bracket[-1]==' ') {
1059                name_len--;
1060            }
1061
1062            if ((name_len+1+bracket_len)<=MAXNAMELEN) {
1063                strcpy(real_name, db_pointer);
1064            }
1065            else {
1066                int short_name_len = MAXNAMELEN-bracket_len-1;
1067
1068                memcpy(real_name, db_pointer, short_name_len);
1069                real_name[short_name_len] = ' ';
1070                strcpy(real_name+short_name_len+1, bracket);
1071            }
1072        }
1073        else {
1074            strncpy(real_name, db_pointer, BUFFERSIZE);
1075        }
1076
1077        free(db_pointer);
1078    }
1079    else if (parent->parent->parent->flag.is_SAI) { // whether species_manager has is_SAI flag
1080        char *db_pointer = resolve_pointer_to_string_copy();
1081
1082        strcpy(real_name, "SAI: ");
1083        if (strcmp(db_pointer, "ECOLI")==0) {
1084            const char *name_for_ecoli = ED4_ROOT->aw_root->awar(ED4_AWAR_NDS_ECOLI_NAME)->read_char_pntr();
1085            if (name_for_ecoli[0]==0) name_for_ecoli = db_pointer;
1086            strncpy(real_name+5, name_for_ecoli, BUFFERSIZE-5);
1087        }
1088        else {
1089            strncpy(real_name+5, db_pointer, BUFFERSIZE-5);
1090        }
1091        free(db_pointer);
1092    }
1093    else { // normal species
1094        ED4_species_manager *species_man = get_parent(ED4_L_SPECIES)->to_species_manager();
1095        char *result = ED4_get_NDS_text(species_man);
1096
1097        strncpy(real_name, result, BUFFERSIZE);
1098        free(result);
1099    }
1100
1101    return real_name;
1102}
1103#undef MAXNAMELEN
1104#undef BUFFERSIZE
1105
1106
1107ED4_sequence_info_terminal::ED4_sequence_info_terminal(const char *temp_id, /* GBDATA *gbd, */ AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1108    : ED4_text_terminal(temp_id, x, y, width, height, temp_parent)
1109{
1110    spec = &(sequence_info_terminal_spec);
1111}
1112
1113
1114ED4_sequence_info_terminal::~ED4_sequence_info_terminal()
1115{
1116}
1117
1118ED4_consensus_sequence_terminal::ED4_consensus_sequence_terminal(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1119    : ED4_sequence_terminal(temp_id, x, y, width, height, temp_parent)
1120{
1121    spec = &(sequence_terminal_spec);
1122    species_name = NULL;
1123}
1124
1125ED4_consensus_sequence_terminal::~ED4_consensus_sequence_terminal()
1126{
1127}
1128
1129ED4_sequence_terminal_basic::ED4_sequence_terminal_basic(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1130    : ED4_text_terminal(temp_id, x, y, width, height, temp_parent)
1131{
1132    spec = &(sequence_terminal_spec);
1133    species_name = NULL;
1134}
1135
1136ED4_sequence_terminal_basic::~ED4_sequence_terminal_basic() {
1137    free(species_name);
1138}
1139
1140ED4_AA_sequence_terminal::ED4_AA_sequence_terminal(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1141    : ED4_sequence_terminal_basic(temp_id, x, y, width, height, temp_parent)
1142{
1143    spec = &(sequence_terminal_spec);
1144    aaSequence   = 0;
1145    aaColor   = 0;
1146    aaStartPos   = 0;
1147    aaStrandType = 0;
1148}
1149
1150GB_alignment_type ED4_AA_sequence_terminal::GetAliType()
1151{
1152    return (GB_alignment_type) GB_AT_AA;
1153}
1154
1155ED4_AA_sequence_terminal::~ED4_AA_sequence_terminal()
1156{
1157    free(aaSequence);
1158    free(aaColor);
1159}
1160
1161ED4_sequence_terminal::ED4_sequence_terminal(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1162    : ED4_sequence_terminal_basic(temp_id, x, y, width, height, temp_parent)
1163{
1164    spec = &(sequence_terminal_spec);
1165    st_ml_node = NULL;
1166}
1167
1168GB_alignment_type ED4_sequence_terminal::GetAliType()
1169{
1170    return ED4_ROOT->alignment_type;
1171}
1172
1173ED4_sequence_terminal::~ED4_sequence_terminal()
1174{
1175}
1176
1177ED4_pure_text_terminal::ED4_pure_text_terminal(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1178    : ED4_text_terminal(temp_id, x, y, width, height, temp_parent)
1179{
1180    spec = &pure_text_terminal_spec;
1181}
1182
1183ED4_pure_text_terminal::~ED4_pure_text_terminal()
1184{
1185}
1186
1187
1188ED4_returncode ED4_spacer_terminal::Show(int /* refresh_all */, int is_cleared) // a spacer terminal doesn't show anything - it's just a dummy terminal
1189{
1190    if (update_info.clear_at_refresh && !is_cleared) {
1191        clear_background();
1192    }
1193    draw();
1194    return ED4_R_OK;
1195}
1196
1197
1198ED4_returncode ED4_spacer_terminal::draw(int /* only_text */)                    // draws bounding box of object
1199{
1200#if defined(DEBUG) && 0
1201    clear_background(ED4_G_FIRST_COLOR_GROUP); // draw colored spacers to make them visible
1202#else
1203    clear_background(0);
1204#endif // DEBUG
1205    return (ED4_R_OK);
1206}
1207
1208ED4_spacer_terminal::ED4_spacer_terminal(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1209    : ED4_terminal(temp_id, x, y, width, height, temp_parent)
1210{
1211    spec = &(spacer_terminal_spec);
1212}
1213
1214
1215ED4_spacer_terminal::~ED4_spacer_terminal()
1216{
1217}
1218
1219ED4_returncode ED4_line_terminal::draw(int /* only_text */)      // draws bounding box of object
1220{
1221    AW_pos x1, y1;
1222    calc_world_coords(&x1, &y1);
1223    ED4_ROOT->world_to_win_coords(ED4_ROOT->get_aww(), &x1, &y1);
1224
1225    AW_pos x2 = x1+extension.size[WIDTH]-1;
1226    AW_pos y2 = y1+extension.size[HEIGHT]-1;
1227
1228    AW_device *device = ED4_ROOT->get_device();
1229
1230    device->line(ED4_G_STANDARD, x1, y1, x2, y1);
1231#if defined(DEBUG)
1232    device->box(ED4_G_MARKED, true, x1, y1+1, x2-x1+1, y2-y1-1);
1233#else
1234    device->clear_part(x1, y1+1, x2-x1+1, y2-y1-1, AW_ALL_DEVICES);
1235#endif // DEBUG
1236    device->line(ED4_G_STANDARD, x1, y2, x2, y2);
1237
1238    return ED4_R_OK;
1239}
1240
1241ED4_returncode ED4_line_terminal::Show(int /* refresh_all */, int is_cleared)
1242{
1243    if (update_info.clear_at_refresh && !is_cleared) {
1244        clear_background();
1245    }
1246    draw();
1247    return ED4_R_OK;
1248}
1249
1250
1251ED4_line_terminal::ED4_line_terminal(const char *temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1252    : ED4_terminal(temp_id, x, y, width, height, temp_parent)
1253{
1254    spec = &(line_terminal_spec);
1255}
1256
1257ED4_line_terminal::~ED4_line_terminal()
1258{
1259}
1260
1261// --------------------------------------------------------------------------------
1262//  ED4_columnStat_terminal
1263// --------------------------------------------------------------------------------
1264
1265ED4_returncode ED4_columnStat_terminal::Show(int IF_ASSERTION_USED(refresh_all), int is_cleared)
1266{
1267    e4_assert(update_info.refresh || refresh_all);
1268    ED4_ROOT->get_device()->push_clip_scale();
1269    if (adjust_clipping_rectangle()) {
1270        if (update_info.clear_at_refresh && !is_cleared) {
1271            clear_background();
1272        }
1273        draw();
1274    }
1275    ED4_ROOT->get_device()->pop_clip_scale();
1276
1277    return ED4_R_OK;
1278}
1279
1280inline char stat2display(int val, bool is_upper_digit) {
1281    if (val<0) {
1282        e4_assert(val==-1); // -1 indicates that no statistic is existing for that column
1283        return '?';
1284    }
1285    if (val==20) return ' '; // value if ACGT and - are distributed equally
1286    if (val==100) return '^'; // we have only 2 characters to display likelihood (100 cannot be displayed)
1287
1288    e4_assert(val>=0 && val<100);
1289
1290    return '0' + (is_upper_digit ? (val/10) : (val%10));
1291}
1292
1293inline int find_significant_positions(int sig, int like_A, int like_C, int like_G, int like_TU, int *sumPtr) {
1294    // result == 0      -> no base-char has a significant likelihood (>=sig)
1295    // result == 1, 2, 4, 8     -> A, C, G, T/U has a significant likelihood
1296    // else             -> the sum two of the likelihoods >= sig (bit-or-ed as in line above)
1297
1298    int like[4];
1299    like[0] = like_A;
1300    like[1] = like_C;
1301    like[2] = like_G;
1302    like[3] = like_TU;
1303
1304    int bestSum = 0;
1305    int bestResult = 0;
1306
1307    int b, c;
1308    for (b=0; b<4; b++) {
1309        int sum = like[b];
1310        if (sum>=sig && sum>=bestSum) {
1311            bestSum = sum;
1312            bestResult = 1<<b;
1313        }
1314    }
1315
1316    if (!bestResult) {
1317        for (b=0; b<4; b++) {
1318            for (c=b+1; c<4; c++) {
1319                int sum = like[b]+like[c];
1320                if (sum>=sig && sum>=bestSum) {
1321                    bestSum = sum;
1322                    bestResult = (1<<b)|(1<<c);
1323                }
1324            }
1325        }
1326    }
1327
1328    if (bestResult) {
1329        if (sumPtr) *sumPtr = bestSum;
1330        return bestResult;
1331    }
1332
1333    return 0;
1334}
1335
1336#define PROBE_MATCH_TARGET_STRING_LENGTH 32
1337
1338GB_CSTR ED4_columnStat_terminal::build_probe_match_string(int start_pos, int end_pos) const {
1339    static char            result[PROBE_MATCH_TARGET_STRING_LENGTH+1]; // see create_probe_match_window() for length
1340    int                    max_insert   = PROBE_MATCH_TARGET_STRING_LENGTH;
1341    char                  *r            = result;
1342    int                    significance = int(get_threshold());
1343    ED4_sequence_terminal *seq_term     = corresponding_sequence_terminal()->to_sequence_terminal();
1344    char                  *seq          = seq_term->resolve_pointer_to_string_copy();
1345
1346    for (int pos=start_pos; pos<=end_pos; pos++) {
1347        int found = find_significant_positions(significance, likelihood[0][pos], likelihood[1][pos], likelihood[2][pos], likelihood[3][pos], 0);
1348
1349        if (found || strchr("-=.", seq[pos])==0) {
1350            // '?' is inserted at every base position without significant bases (not at gaps!)
1351
1352            *r++ = "NACMGRSVUWYHKDBN"[found]; // this creates a string containing the full IUPAC code
1353
1354            if (max_insert--==0) {
1355                r--;
1356                break;
1357            }
1358        }
1359    }
1360    r[0] = 0;
1361    free(seq);
1362
1363    if (max_insert<0) {
1364        aw_message(GBS_global_string("Max. %i bases allowed in Probe Match", PROBE_MATCH_TARGET_STRING_LENGTH));
1365        result[0] = 0;
1366    }
1367    return result;
1368}
1369#undef PROBE_MATCH_TARGET_STRING_LENGTH
1370
1371ED4_returncode ED4_columnStat_terminal::draw(int /* only_text */)
1372{
1373#if defined(WARN_TODO)
1374#warning test drawing of ED4_columnStat_terminal
1375#endif
1376    if (!update_likelihood()) {
1377        aw_message("Can't calculate likelihood.");
1378        return ED4_R_IMPOSSIBLE;
1379    }
1380
1381    AW_pos x, y;
1382    calc_world_coords(&x, &y);
1383    ED4_ROOT->world_to_win_coords(ED4_ROOT->get_aww(), &x, &y);
1384
1385    AW_pos term_height = extension.size[HEIGHT];
1386    AW_pos font_height = ED4_ROOT->font_group.get_height(ED4_G_SEQUENCES);
1387    AW_pos font_width  = ED4_ROOT->font_group.get_width(ED4_G_SEQUENCES);
1388
1389    AW_pos text_x = x + CHARACTEROFFSET;
1390    AW_pos text_y = y + term_height - font_height;
1391
1392    AW_device *device = ED4_ROOT->get_device();
1393    ED4_sequence_terminal *seq_term = corresponding_sequence_terminal();
1394    const ED4_remap *rm = ED4_ROOT->root_group_man->remap();
1395    long left, right;
1396    seq_term->calc_update_intervall(&left, &right);
1397    rm->clip_screen_range(&left, &right);
1398
1399    {
1400        int max_seq_len = seq_term->get_length();
1401        int max_seq_pos = rm->sequence_to_screen_clipped(max_seq_len);
1402
1403        if (right>max_seq_len) right = max_seq_pos;
1404        if (left>right) return ED4_R_OK;
1405    }
1406
1407    char *sbuffer = new char[right+1];  // used to build displayed terminal content  (values = '0'-'9')
1408    memset(sbuffer, ' ', right);
1409    sbuffer[right] = 0; // eos
1410
1411    AW_pos y2;
1412    int r;
1413
1414    // Set background:
1415    {
1416        int significance = int(get_threshold());
1417        // normal columns are colored in ED4_G_STANDARD
1418        // all columns with one (or sum of two) probability above 'significance' are back-colored in ED4_G_CBACK_0
1419        // the responsible probabilities (one or two) are back-colored in ED4_G_CBACK_1..ED4_G_CBACK_9
1420
1421        int color = ED4_G_STANDARD;
1422        int old_color = ED4_G_STANDARD;
1423        AW_pos x2 = text_x + font_width*left + 1;
1424        AW_pos old_x2 = x2;
1425        int i;
1426        int selection_col1, selection_col2;
1427        int is_selected = ED4_get_selected_range(seq_term, &selection_col1, &selection_col2);
1428
1429        for (i=left; i<=right; i++, x2+=font_width) { // colorize significant columns in ALL rows
1430            int p = rm->screen_to_sequence(i);
1431            int found = find_significant_positions(significance, likelihood[0][p], likelihood[1][p], likelihood[2][p], likelihood[3][p], 0);
1432
1433            if (found)  color = ED4_G_CBACK_0;
1434            else    color = ED4_G_STANDARD;
1435
1436            if (is_selected && p>=selection_col1 && p<=selection_col2) {
1437                color = ED4_G_SELECTED;
1438            }
1439
1440            if (color!=old_color) {
1441                if (x2>old_x2 && old_color!=ED4_G_STANDARD) {
1442                    device->box(old_color, true, old_x2, y, x2-old_x2, term_height);
1443                }
1444                old_color = color;
1445                old_x2 = x2;
1446            }
1447        }
1448        if (x2>old_x2 && old_color!=ED4_G_STANDARD) {
1449            device->box(old_color, true, old_x2, y, x2-old_x2, term_height);
1450        }
1451
1452        color = ED4_G_STANDARD;
1453        x2 = text_x + font_width*left + 1;
1454
1455        for (i=left; i<=right; i++, x2+=font_width) { // colorize significant columns in SINGLE rows
1456            int p = rm->screen_to_sequence(i);
1457            int sum;
1458            int found = find_significant_positions(significance, likelihood[0][p], likelihood[1][p], likelihood[2][p], likelihood[3][p], &sum);
1459
1460            if (found) {
1461                e4_assert(sum>=significance && sum<=100);
1462                color = ED4_G_CBACK_1+((sum-significance)*(ED4_G_CBACK_9-ED4_G_CBACK_1))/(100-significance);
1463                e4_assert(color>=ED4_G_CBACK_1 && color<=ED4_G_CBACK_9);
1464            }
1465            else {
1466                color = ED4_G_STANDARD;
1467            }
1468
1469            if (color!=ED4_G_STANDARD) {
1470                int bit;
1471
1472                for (r=3, y2=text_y+1, bit=1<<3;
1473                     r>=0;
1474                     r--, y2-=COLUMN_STAT_ROW_HEIGHT(font_height), bit>>=1)
1475                {
1476                    if (found&bit) {
1477                        device->box(color, true, x2, y2-2*font_height+1, font_width, 2*font_height);
1478                    }
1479                }
1480            }
1481        }
1482    }
1483
1484    // Draw text:
1485    for (r=3, y2=text_y;
1486         r>=0;
1487         r--, y2-=COLUMN_STAT_ROW_HEIGHT(font_height)) { // 4 rows (one for T/U, G, C and A)
1488
1489        int gc = ED4_ROOT->sequence_colors->char_2_gc[(unsigned char)"ACGU"[r]];
1490        int i;
1491        for (i=left; i<=right; i++) {
1492            int p = rm->screen_to_sequence(i);
1493            int val = likelihood[r][p];
1494            sbuffer[i] = stat2display(val, 0); // calc lower digit
1495        }
1496        device->text(gc, sbuffer, text_x+font_width*0.2, y2, 0, AW_SCREEN, right); // draw lower-significant digit (shifted a bit to the right)
1497
1498        for (i=left; i<=right; i++) {
1499            int p = rm->screen_to_sequence(i);
1500            int val = likelihood[r][p];
1501            sbuffer[i] = stat2display(val, 1); // calc upper digit
1502        }
1503        device->text(gc, sbuffer, text_x, y2-font_height, 0, AW_SCREEN, right); // draw higher-significant digit
1504    }
1505
1506    free(sbuffer);
1507    return ED4_R_OK;
1508}
1509
1510int ED4_columnStat_terminal::update_likelihood() {
1511    ED4_sequence_terminal *seq_term = corresponding_sequence_terminal();
1512
1513    return STAT_update_ml_likelihood(ED4_ROOT->st_ml, likelihood, latest_update, 0, seq_term->st_ml_node);
1514}
1515
1516ED4_columnStat_terminal::ED4_columnStat_terminal(GB_CSTR temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1517    ED4_text_terminal(temp_id, x, y, width, height, temp_parent)
1518{
1519    spec = &(column_stat_terminal_spec);
1520    for (int i=0; i<4; i++) likelihood[i] = 0;
1521    latest_update = 0;
1522}
1523
1524ED4_columnStat_terminal::~ED4_columnStat_terminal()
1525{
1526    for (int i=0; i<4; i++) free(likelihood[i]);
1527}
1528
1529// --------------------------------------------------------------------------------
1530//  ED4_reference_terminals
1531// --------------------------------------------------------------------------------
1532
1533void ED4_reference_terminals::clear()
1534{
1535    delete ref_sequence_info;
1536    delete ref_sequence;
1537    delete ref_column_stat;
1538    delete ref_column_stat_info;
1539    null();
1540}
1541
1542void ED4_reference_terminals::init(ED4_sequence_info_terminal *ref_sequence_info_,
1543                                   ED4_sequence_terminal *ref_sequence_,
1544                                   ED4_sequence_info_terminal *ref_column_stat_info_,
1545                                   ED4_columnStat_terminal *ref_column_stat_)
1546{
1547    clear();
1548    ref_sequence_info    = ref_sequence_info_;
1549    ref_sequence     = ref_sequence_;
1550    ref_column_stat_info = ref_column_stat_info_;
1551    ref_column_stat      = ref_column_stat_;
1552}
Note: See TracBrowser for help on using the repository browser.