source: branches/profile/EDIT4/ED4_base.cxx

Last change on this file was 12157, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.1 KB
Line 
1#include <arbdbt.h>
2#include <ad_cb.h>
3#include <aw_preset.hxx>
4#include <aw_awar.hxx>
5#include <aw_msg.hxx>
6#include <arb_progress.h>
7#include <aw_root.hxx>
8#include <aw_question.hxx>
9
10#include <ed4_extern.hxx>
11
12#include "ed4_class.hxx"
13#include "ed4_awars.hxx"
14#include "ed4_edit_string.hxx"
15#include "ed4_list.hxx"
16
17ED4_group_manager *ED4_base::is_in_folded_group() const
18{
19    if (!parent) return 0;
20    ED4_base *group = get_parent(ED4_L_GROUP);
21    if (!group) return 0;
22    if (group->dynamic_prop & ED4_P_IS_FOLDED) return group->to_group_manager();
23    return group->is_in_folded_group();
24}
25
26void ED4_base::changed_by_database()
27{
28    e4_assert(0);
29    // this happens if you add a new species_pointer to a ED4_base-derived type
30    // without defining changed_by_database for this type
31}
32
33void ED4_manager::changed_by_database() { request_refresh(); }
34
35void ED4_terminal::changed_by_database()
36{
37    if (GB_read_clock(GLOBAL_gb_main) > curr_timestamp) { // only if timer_cb occurred after last change by EDIT4
38
39        // test if alignment length has changed:
40        {
41            GBDATA *gb_alignment = GBT_get_alignment(GLOBAL_gb_main, ED4_ROOT->alignment_name);
42            e4_assert(gb_alignment);
43            GBDATA *gb_alignment_len = GB_search(gb_alignment, "alignment_len", GB_FIND);
44            int alignment_length = GB_read_int(gb_alignment_len);
45
46            if (MAXSEQUENCECHARACTERLENGTH!=alignment_length) {
47                ED4_alignment_length_changed(gb_alignment_len, GB_CB_CHANGED);
48            }
49        }
50
51        GBDATA *gb_seq = get_species_pointer();
52        int type = GB_read_type(gb_seq);
53
54        if (type==GB_STRING) {
55            char *data = (char*)GB_read_old_value();
56            if (data) {
57                int data_len = GB_read_old_size();
58                e4_assert(data_len >= 0);
59                char *dup_data = new char[data_len+1];
60
61                memcpy(dup_data, data, data_len);
62                dup_data[data_len] = 0;
63
64#if defined(DEBUG) && 0
65                char *n = GB_read_string(gb_seq);
66                e4_assert(strcmp(n, dup_data)!=0); // not really changed
67                delete n;
68#endif
69
70                ED4_species_manager *spman = get_parent(ED4_L_SPECIES)->to_species_manager();
71                spman->do_callbacks();
72
73                if (dynamic_prop & ED4_P_CONSENSUS_RELEVANT) {
74                    ED4_multi_species_manager *multiman = get_parent(ED4_L_MULTI_SPECIES)->to_multi_species_manager();
75                    multiman->update_bases_and_rebuild_consensi(dup_data, data_len, spman, ED4_U_UP);
76                    request_refresh();
77                }
78
79                delete [] dup_data;
80            }
81            else { // sth else changed (e.g. protection)
82                GB_clear_error();
83            }
84        }
85    }
86}
87
88void ED4_base::deleted_from_database() {
89    my_species_pointer.notify_deleted();
90}
91
92void ED4_terminal::deleted_from_database() {
93    ED4_base::deleted_from_database();
94}
95
96void ED4_text_terminal::deleted_from_database() {
97    ED4_terminal::deleted_from_database();
98    parent->Delete();
99}
100
101void ED4_sequence_terminal::deleted_from_database()
102{
103#if defined(DEBUG)
104    printf("ED4_sequence_terminal::deleted_from_database (%p)\n", this);
105#endif // DEBUG
106
107    ED4_terminal::deleted_from_database();
108
109    bool was_consensus_relevant = dynamic_prop & ED4_P_CONSENSUS_RELEVANT;
110
111    clr_property(ED4_properties(ED4_P_CONSENSUS_RELEVANT|ED4_P_ALIGNMENT_DATA));
112
113    if (was_consensus_relevant) { 
114        const char *data     = (const char*)GB_read_old_value();
115        int         data_len = GB_read_old_size();
116
117        ED4_multi_species_manager *multi_species_man = get_parent(ED4_L_MULTI_SPECIES)->to_multi_species_manager();
118
119        multi_species_man->update_bases(data, data_len, 0);
120        multi_species_man->rebuild_consensi(get_parent(ED4_L_SPECIES)->to_species_manager(), ED4_U_UP);
121    }
122
123    parent->Delete();
124}
125
126void ED4_manager::deleted_from_database() {
127    if (is_species_manager()) {
128        ED4_species_manager *species_man = to_species_manager();
129        ED4_multi_species_manager *multi_man = species_man->parent->to_multi_species_manager();
130
131        multi_man->children->remove_member(species_man);
132        GB_push_transaction(GLOBAL_gb_main);
133        multi_man->update_consensus(multi_man, 0, species_man);
134        multi_man->rebuild_consensi(species_man, ED4_U_UP);
135        GB_pop_transaction(GLOBAL_gb_main);
136
137        request_resize();
138        // parent = 0;
139        // delete this; // @@@ crashes when removing callback deleted_from_database()
140    }
141    else {
142        e4_assert(0);
143    }
144}
145
146static void sequence_changed_cb(GBDATA *gb_seq, ED4_base *base, GB_CB_TYPE gbtype) {
147    if (base->get_species_pointer()!=gb_seq) {
148        e4_assert(0);
149        aw_message("Illegal callback (ED4_sequence_changed_cb())");
150    }
151
152    if (gbtype&GB_CB_DELETE) {
153        e4_assert(gbtype==GB_CB_DELETE);
154        base->deleted_from_database();
155    }
156
157    if (gbtype&GB_CB_CHANGED) {
158        base->changed_by_database();
159    }
160
161    if (gbtype&GB_CB_SON_CREATED) {
162        // @@@ New son for database-member was created ... what may we do now?
163    }
164}
165
166ED4_species_pointer::ED4_species_pointer() {
167    species_pointer = 0;
168}
169ED4_species_pointer::~ED4_species_pointer() {
170    e4_assert(species_pointer==0);      // must be destroyed before
171}
172
173void ED4_species_pointer::addCallback(ED4_base *base) {
174    GB_transaction ta(GLOBAL_gb_main);
175    GB_add_callback(species_pointer, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sequence_changed_cb, base));
176}
177void ED4_species_pointer::removeCallback(ED4_base *base) {
178    GB_transaction ta(GLOBAL_gb_main);
179    GB_remove_callback(species_pointer, GB_CB_CHANGED_OR_DELETED, makeDatabaseCallback(sequence_changed_cb, base));
180}
181
182void ED4_species_pointer::Set(GBDATA *gbd, ED4_base *base) {
183    if (species_pointer) removeCallback(base);
184    species_pointer = gbd;
185    if (species_pointer) addCallback(base);
186}
187
188// -----------------
189//      ED4_base
190
191inline bool ranges_overlap(int p1, int p2, int r1, int r2) {
192    // return true if ranges p1..p2 and r1..r2 overlap
193    e4_assert(p1 <= p2);
194    e4_assert(r1 <= r2);
195
196    return !((r2 <= p1) || (p2 <= r1)); // "exactly adjacent" means "not overlapping"
197}
198
199inline bool range_contained_in(int p1, int p2, int r1, int r2) {
200    // return true if range p1..p2 is contained in range r1..r2
201    e4_assert(p1 <= p2);
202    e4_assert(r1 <= r2);
203
204    return p1 >= r1 && p2 <= r2;
205}
206
207bool ED4_window::partly_shows(int x1, int y1, int x2, int y2) const {
208    // return true if rectangle x1/y1/x2/y2 overlaps with clipped screen
209    e4_assert(x1 <= x2);
210    e4_assert(y1 <= y2);
211
212    bool visible = (ranges_overlap(x1, x2, coords.window_left_clip_point, coords.window_right_clip_point) &&
213                    ranges_overlap(y1, y2, coords.window_upper_clip_point, coords.window_lower_clip_point));
214
215    return visible;
216}
217
218bool ED4_window::completely_shows(int x1, int y1, int x2, int y2) const {
219    // return true if rectangle x1/y1/x2/y2 is contained in clipped screen
220    e4_assert(x1 <= x2);
221    e4_assert(y1 <= y2);
222
223    bool visible = (range_contained_in(x1, x2, coords.window_left_clip_point, coords.window_right_clip_point) &&
224                    range_contained_in(y1, y2, coords.window_upper_clip_point, coords.window_lower_clip_point));
225
226    return visible;
227}
228
229char *ED4_base::resolve_pointer_to_string_copy(int *) const { return NULL; }
230const char *ED4_base::resolve_pointer_to_char_pntr(int *) const { return NULL; }
231
232ED4_returncode ED4_manager::create_group(ED4_group_manager **group_manager, GB_CSTR group_name) {
233    // creates group from user menu of AW_Window
234
235    char buffer[35];
236
237    sprintf(buffer, "Group_Manager.%ld", ED4_counter);                                                          // create new group manager
238    *group_manager = new ED4_group_manager(buffer, 0, 0, 0, 0, NULL);
239
240    sprintf(buffer, "Bracket_Terminal.%ld", ED4_counter);
241    ED4_bracket_terminal *bracket_terminal = new ED4_bracket_terminal(buffer, 0, 0, BRACKETWIDTH, 0, *group_manager);
242    (*group_manager)->children->append_member(bracket_terminal);
243
244    sprintf(buffer, "MultiSpecies_Manager.%ld", ED4_counter);                                                   // create new multi_species_manager
245    ED4_multi_species_manager *multi_species_manager = new ED4_multi_species_manager(buffer, BRACKETWIDTH, 0, 0, 0, *group_manager); // Objekt Gruppen name_terminal noch
246    (*group_manager)->children->append_member(multi_species_manager);                                           // auszeichnen
247
248    (*group_manager)->set_property(ED4_P_MOVABLE);
249    multi_species_manager->set_property(ED4_P_IS_HANDLE);
250    bracket_terminal->set_property(ED4_P_IS_HANDLE);
251    bracket_terminal->set_links(NULL, multi_species_manager);
252
253    {
254        sprintf(buffer, "Group_Spacer_Terminal_Beg.%ld", ED4_counter);                                                      // Spacer at beginning of group
255        ED4_spacer_terminal *group_spacer_terminal1 = new ED4_spacer_terminal(buffer, true, 0, 0, 10, SPACERHEIGHT, multi_species_manager); // For better Overview
256        multi_species_manager->children->append_member(group_spacer_terminal1);
257    }
258
259    {
260        sprintf(buffer, "Consensus_Manager.%ld", ED4_counter);                                                     // Create competence terminal
261        ED4_species_manager *species_manager = new ED4_species_manager(ED4_SP_CONSENSUS, buffer, 0, SPACERHEIGHT, 0, 0, multi_species_manager);
262        species_manager->set_property(ED4_P_MOVABLE);
263        multi_species_manager->children->append_member(species_manager);
264
265        {
266            ED4_species_name_terminal *species_name_terminal = new ED4_species_name_terminal(group_name, 0, 0, MAXSPECIESWIDTH - BRACKETWIDTH, TERMINALHEIGHT, species_manager);
267            species_name_terminal->set_property((ED4_properties) (ED4_P_SELECTABLE | ED4_P_DRAGABLE | ED4_P_IS_HANDLE));        // only some terminals
268            species_name_terminal->set_links(NULL, ED4_ROOT->ref_terminals.get_ref_sequence());
269            species_manager->children->append_member(species_name_terminal);                                                    // properties
270        }
271
272        sprintf(buffer, "Consensus_Seq_Manager.%ld", ED4_counter);
273        ED4_sequence_manager *sequence_manager = new ED4_sequence_manager(buffer, MAXSPECIESWIDTH, 0, 0, 0, species_manager);
274        sequence_manager->set_property(ED4_P_MOVABLE);
275        species_manager->children->append_member(sequence_manager);
276
277        {
278            ED4_sequence_info_terminal *sequence_info_terminal = new ED4_sequence_info_terminal("DATA", 0, 0, SEQUENCEINFOSIZE, TERMINALHEIGHT, sequence_manager);        // Info fuer Gruppe
279            sequence_info_terminal->set_links(ED4_ROOT->ref_terminals.get_ref_sequence_info(), ED4_ROOT->ref_terminals.get_ref_sequence_info());
280            sequence_info_terminal->set_property((ED4_properties) (ED4_P_SELECTABLE | ED4_P_DRAGABLE | ED4_P_IS_HANDLE));
281            sequence_manager->children->append_member(sequence_info_terminal);
282        }
283
284        {
285            ED4_sequence_terminal *sequence_terminal = new ED4_consensus_sequence_terminal("", SEQUENCEINFOSIZE, 0, 0, TERMINALHEIGHT, sequence_manager);
286            sequence_terminal->set_property(ED4_P_CURSOR_ALLOWED);
287            sequence_terminal->set_links(ED4_ROOT->ref_terminals.get_ref_sequence(),   ED4_ROOT->ref_terminals.get_ref_sequence());
288            sequence_manager->children->append_member(sequence_terminal);
289        }
290    }
291
292    {
293        sprintf(buffer, "Group_Spacer_Terminal_End.%ld", ED4_counter);                                                      // Spacer at beginning of group
294        ED4_spacer_terminal *group_spacer_terminal2 = new ED4_spacer_terminal(buffer, true, 0, SPACERHEIGHT + TERMINALHEIGHT, 10, SPACERHEIGHT, multi_species_manager); // For better Overview
295        multi_species_manager->children->append_member(group_spacer_terminal2);
296    }
297
298    multi_species_manager->update_requested_by_child();
299
300    ED4_counter ++;
301
302    return ED4_R_OK;
303}
304
305
306ED4_returncode ED4_base::generate_configuration_string(char **generated_string)
307{
308    ED4_multi_species_manager *multi_species_manager = NULL;
309    char sep_name[2] = { 1, 0 };
310    AW_pos old_pos = 0;
311
312    if (!(*generated_string)) {
313        *generated_string = new char[2];
314        strcpy(*generated_string, sep_name);
315    }
316    ED4_manager *consensus_manager = NULL;
317
318    if (is_species_name_terminal() &&
319        !((ED4_terminal *)this)->tflag.deleted) { // wenn multi_name_manager mehrere name_terminals hat, dann muss das echte name_terminal markiert sein
320
321        long  old_size     = strlen(*generated_string);
322        long  new_size;
323        char *old_string   = *generated_string;
324        char *species_name = NULL;
325        char *cons_id      = NULL;
326
327        ED4_species_type species_type = get_species_type();
328        if (species_type == ED4_SP_CONSENSUS) {
329            cons_id = new char[strlen(id)+1];
330            int i;
331            for (i=0; id[i] != '(' && id[i] != '\0'; i++) cons_id[i] = id[i];
332            if (id[i] == '(') cons_id[i-1] = '\0';
333            new_size   = old_size + strlen(cons_id) + 2;
334        }
335        else { // we are Species or SAI
336            int len;
337            species_name = resolve_pointer_to_string_copy(&len);
338            new_size     = old_size + len + 3; // 3 because of separator and identifier
339        }
340
341        *generated_string = new char[new_size];
342
343        int i;
344        for (i=0; i<old_size; ++i) (*generated_string)[i] = old_string[i];
345        for (;    i<new_size; ++i) (*generated_string)[i] = 0;
346
347        switch (species_type) {
348            case ED4_SP_CONSENSUS:
349                strcat (*generated_string, cons_id);
350                delete [] cons_id;
351                break;
352            case ED4_SP_SAI:
353                strcat(*generated_string, "S");
354                strcat(*generated_string, species_name);
355                break;
356            case ED4_SP_SPECIES:
357                strcat(*generated_string, "L");
358                strcat(*generated_string, species_name);
359                break;
360            case ED4_SP_NONE:
361                e4_assert(0);
362                break;
363        }
364
365        strcat(*generated_string, sep_name);
366        delete [] old_string;
367        free(species_name);
368    }
369    else if (is_group_manager()) {
370        char *old_string = *generated_string;
371        long  old_size   = strlen(*generated_string);
372        long  new_size   = old_size + 1; // 3 because of separator and identifier
373        *generated_string = new char[new_size+1];
374
375        int i;
376        for (i=0; i<old_size; ++i) (*generated_string)[i] = old_string[i];
377        for (;    i<new_size; ++i) (*generated_string)[i] = 0;
378
379        delete [] old_string;
380
381        if (dynamic_prop & ED4_P_IS_FOLDED) {
382            strcat(*generated_string, "F");
383        }
384        else {
385            strcat(*generated_string, "G");
386        }
387
388        multi_species_manager = to_group_manager()->get_multi_species_manager();
389
390        // move consensus to top of list (essential!)
391        // @@@ code below is duplicated in ED4_bracket_terminal::fold()
392        ED4_manager *spec_man = multi_species_manager->children->member(1)->to_manager();
393        if (!spec_man->is_consensus_manager()) {
394            for (i=0; i < multi_species_manager->children->members(); i++) {
395                spec_man = multi_species_manager->children->member(i)->to_manager();
396                if (spec_man->is_consensus_manager()) {
397                    consensus_manager = spec_man;
398                    break;
399                }
400            }
401
402            e4_assert(consensus_manager);
403            multi_species_manager->children->remove_member(consensus_manager);
404            old_pos                                      = consensus_manager->extension.position[Y_POS];
405            consensus_manager->extension.position[Y_POS] = SPACERHEIGHT;
406            ED4_base::touch_world_cache();
407            multi_species_manager->children->append_member(consensus_manager);
408        }
409    }
410
411    if (is_manager()) {
412        ED4_manager *this_manager = this->to_manager();
413        if (this_manager->children) {
414            for (int i=0; i<this_manager->children->members(); i++) {
415                this_manager->children->member(i)->generate_configuration_string(generated_string);
416            }
417        }
418    }
419
420    if (multi_species_manager) {
421        char *old_string = *generated_string;
422        long  old_size   = strlen(*generated_string);
423        long  new_size   = old_size + 3;                                                      // 3 because of separator and identifier
424        *generated_string = new char[new_size];
425
426        int i;
427        for (i=0; i<old_size; ++i) (*generated_string)[i] = old_string[i];
428        for (;    i<new_size; ++i) (*generated_string)[i] = 0;
429
430        delete [] old_string;
431
432        strcat(*generated_string, "E");
433        strcat(*generated_string, sep_name);
434
435        if (consensus_manager) {
436            multi_species_manager->children->remove_member(consensus_manager);                  // move Consensus back to old position
437            consensus_manager->extension.position[Y_POS] = old_pos;
438            ED4_base::touch_world_cache();
439            multi_species_manager->children->append_member(consensus_manager);
440        }
441    }
442
443    return ED4_R_OK;
444}
445
446ARB_ERROR ED4_base::route_down_hierarchy(ED4_cb cb, AW_CL cd1, AW_CL cd2) {
447    // executes 'cb' for every element in hierarchy
448    return cb(this, cd1, cd2);
449}
450
451ARB_ERROR ED4_manager::route_down_hierarchy(ED4_cb cb, AW_CL cd1, AW_CL cd2) {
452    ARB_ERROR error = cb(this, cd1, cd2);
453    if (children && !error) {
454        for (int i=0; i <children->members() && !error; i++) {
455            error = children->member(i)->route_down_hierarchy(cb, cd1, cd2);
456        }
457    }
458    return error;
459}
460
461ED4_base *ED4_manager::find_first_that(ED4_level level, bool (*condition)(ED4_base *to_test, AW_CL arg), AW_CL arg) {
462    if ((spec.level&level) && condition(this, arg)) {
463        return this;
464    }
465
466    if (children) {
467        for (int i=0; i<children->members(); i++) {
468            ED4_base *child = children->member(i);
469
470            if (child->is_manager()) {
471                ED4_base *found = child->to_manager()->find_first_that(level, condition, arg);
472                if (found) {
473                    return found;
474                }
475            }
476            else if ((child->spec.level&level) && condition(child, arg)) {
477                return child;
478            }
479        }
480    }
481
482    return 0;
483}
484
485int ED4_base::calc_group_depth() {
486    int       cntr        = 0;
487    ED4_base *temp_parent = parent;
488    while (temp_parent->parent && !(temp_parent->is_area_manager())) {
489        if (temp_parent->is_group_manager()) cntr++;
490        temp_parent = temp_parent->parent;
491    }
492    return cntr; // don't count our own group
493}
494
495ED4_returncode ED4_base::remove_callbacks() // removes callbacks
496{
497    return ED4_R_IMPOSSIBLE;
498}
499
500
501ED4_base *ED4_base::search_spec_child_rek(ED4_level level)   // recursive search for level
502{
503    return spec.level&level ? this : (ED4_base*)NULL;
504}
505
506ED4_base *ED4_manager::search_spec_child_rek(ED4_level level)
507{
508    if (spec.level & level) return this;
509
510    if (children) {
511        int i;
512
513        for (i=0; i<children->members(); i++) { // first check children
514            if (children->member(i)->spec.level & level) {
515                return children->member(i);
516            }
517        }
518
519        for (i=0; i<children->members(); i++) {
520            ED4_base *result = children->member(i)->search_spec_child_rek(level);
521            if (result) {
522                return result;
523            }
524        }
525    }
526
527    return 0;
528}
529
530ED4_terminal *ED4_base::get_next_terminal()
531{
532    ED4_terminal *terminal = 0;
533
534    if (parent) {
535        terminal = parent->get_first_terminal(index+1);
536        if (!terminal) {
537            terminal = parent->get_next_terminal();
538        }
539    }
540
541    return terminal;
542}
543
544ED4_terminal *ED4_base::get_prev_terminal()
545{
546    ED4_terminal *terminal = 0;
547
548    if (parent) {
549        if (index) {
550            terminal = parent->get_last_terminal(index-1);
551        }
552        if (!terminal) {
553            terminal = parent->get_prev_terminal();
554        }
555    }
556
557    return terminal;
558}
559
560
561bool ED4_base::has_parent(ED4_manager *Parent)
562{
563    // return true if 'parent' is a parent of this
564
565    if (is_manager()) {
566        if (this == static_cast<ED4_base*>(Parent)) {
567            return true;
568        }
569    }
570
571    if (!parent) return false;
572    return parent->has_parent(Parent);
573}
574
575
576ED4_AREA_LEVEL ED4_base::get_area_level(ED4_multi_species_manager **multi_species_manager) const {
577    ED4_base       *area_base = get_parent(ED4_L_AREA);
578    ED4_AREA_LEVEL  result    = ED4_A_ERROR;
579
580    if (area_base) {
581        ED4_area_manager *area_man = area_base->to_area_manager();
582
583        if      (area_man == ED4_ROOT->top_area_man)    result = ED4_A_TOP_AREA;
584        else if (area_man == ED4_ROOT->middle_area_man) result = ED4_A_MIDDLE_AREA;
585
586        if (result != ED4_A_ERROR && multi_species_manager) {
587            *multi_species_manager = area_man->get_multi_species_manager();
588        }
589    }
590    return result;
591}
592
593
594void ED4_multi_species_manager::update_group_id() {
595    ED4_species_name_terminal *consensus_name_terminal = get_consensus_name_terminal();
596    if (consensus_name_terminal) { // top managers dont show consensus
597        e4_assert(has_valid_counters());
598       
599        const char *cntid = consensus_name_terminal->id;
600        char       *name  = (char*)GB_calloc(strlen(cntid)+10, sizeof(*name));
601
602        int i;
603        for (i=0; cntid[i] && cntid[i] != '(';   i++) {
604            name[i] = cntid[i];
605        }
606        if (i>0 && cntid[i-1] == ' ') --i; // skip terminal space
607        sprintf(name+i, " (%d)", species);
608
609        freeset(consensus_name_terminal->id, name);
610
611        consensus_name_terminal->request_refresh();
612    }
613}
614
615PosRange ED4_abstract_sequence_terminal::pixel2index(PosRange pixel_range) {
616    int length_of_char = ED4_ROOT->font_group.get_width(ED4_G_SEQUENCES);
617
618    int left_index  = int((pixel_range.start()-CHARACTEROFFSET)/length_of_char);
619    int right_index = int((pixel_range.end()  -CHARACTEROFFSET)/length_of_char) + 1;
620
621    return PosRange(left_index, std::min(right_index, MAXSEQUENCECHARACTERLENGTH-1));
622}
623
624PosRange ED4_abstract_sequence_terminal::calc_interval_displayed_in_rectangle(AW_screen_area *rect) { // rect contains win-coords
625    AW_pos x, y;
626    calc_world_coords(&x, &y);
627    current_ed4w()->world_to_win_coords(&x, &y);
628
629    int rel_left_x  = int(rect->l-x);
630    int rel_right_x = int(rect->r-x);
631
632    return pixel2index(PosRange(rel_left_x, rel_right_x)); // changed behavior: clip at MAXSEQUENCECHARACTERLENGTH-1 (was MAXSEQUENCECHARACTERLENGTH)
633}
634
635PosRange ED4_abstract_sequence_terminal::calc_update_interval() {
636    AW_pos x, y;
637    calc_world_coords(&x, &y);
638
639    const AW_screen_area& clip_rect = current_device()->get_cliprect();
640
641    int scroll_shift = current_ed4w()->coords.window_left_clip_point-x; // Verschiebung der Sequenz (durch Scrollen) == slider Position
642    int rel_left_x   = int(clip_rect.l - x + scroll_shift);                   // Abstand vom linken Terminalrand zum Anfang des Clipping rectangles + scroll_shift
643    int rel_right_x  = int(clip_rect.r - x + scroll_shift);
644
645    return pixel2index(PosRange(rel_left_x, rel_right_x));
646}
647
648void ED4_manager::create_consensus(ED4_abstract_group_manager *upper_group_manager, arb_progress *progress) {
649    // creates consensus
650    // is called by group manager
651
652    ED4_abstract_group_manager *group_manager_for_child = upper_group_manager;
653
654    if (is_abstract_group_manager()) {
655        ED4_abstract_group_manager *group_manager = to_abstract_group_manager();
656
657        group_manager->table().init(MAXSEQUENCECHARACTERLENGTH);
658        group_manager_for_child = group_manager;
659
660        if (progress) progress->inc();
661    }
662    int i;
663    for (i=0; i<children->members(); i++) {
664        ED4_base *member = children->member(i);
665
666        if (member->is_species_manager()) {
667            ED4_species_manager *species_manager        = member->to_species_manager();
668            const ED4_terminal  *sequence_data_terminal = species_manager->get_consensus_relevant_terminal();
669
670            if (sequence_data_terminal) {
671                int   db_pointer_len;
672                char *db_pointer = sequence_data_terminal->resolve_pointer_to_string_copy(&db_pointer_len);
673                group_manager_for_child->table().add(db_pointer, db_pointer_len);
674                e4_assert(!group_manager_for_child->table().empty());
675                free(db_pointer);
676
677                if (progress) progress->inc();
678            }
679        }
680        else if (member->is_group_manager()) {
681            ED4_group_manager *sub_group = member->to_group_manager();
682
683            sub_group->create_consensus(sub_group, progress);
684            e4_assert(sub_group!=upper_group_manager);
685            upper_group_manager->table().add(sub_group->table());
686#if defined(TEST_CHAR_TABLE_INTEGRITY)
687            if (!sub_group->table().empty() && !sub_group->table().is_ignored()) {
688                e4_assert(!upper_group_manager->table().empty());
689            }
690#endif
691        }
692        else if (member->is_manager()) {
693            member->to_manager()->create_consensus(group_manager_for_child, progress);
694        }
695    }
696}
697
698const ED4_terminal *ED4_base::get_consensus_relevant_terminal() const {
699    int i;
700
701    if (is_terminal()) {
702        if (dynamic_prop & ED4_P_CONSENSUS_RELEVANT) {
703            return this->to_terminal();
704        }
705        return NULL;
706    }
707
708    const ED4_manager  *manager           = this->to_manager();
709    const ED4_terminal *relevant_terminal = 0;
710
711    int members = manager->children->members();
712
713    for (i=0; !relevant_terminal && i<members; ++i) {
714        ED4_base     *member = manager->children->member(i);
715        relevant_terminal    = member->get_consensus_relevant_terminal();
716    }
717
718#if defined(DEBUG)
719    if (relevant_terminal) {
720        for (; i<members; ++i) {
721            ED4_base *member = manager->children->member(i);
722            e4_assert(!member->get_consensus_relevant_terminal()); // there shall be only 1 consensus relevant terminal, since much code assumes that
723        }
724    }
725#endif // DEBUG
726
727    return relevant_terminal;
728}
729
730int ED4_multi_species_manager::count_visible_children() // is called by a multi_species_manager
731{
732    int counter = 0;
733
734    for (int i=0; i<children->members(); i++) {
735        ED4_base *member = children->member(i);
736        if (member->is_species_manager()) {
737            counter ++;
738        }
739        else if (member->is_group_manager()) {
740            ED4_group_manager *group_manager = member->to_group_manager();
741            if (group_manager->dynamic_prop & ED4_P_IS_FOLDED) {
742                counter ++;
743            }
744            else {
745                ED4_multi_species_manager *multi_species_manager = group_manager->get_multi_species_manager();
746                counter += multi_species_manager->count_visible_children();
747            }
748        }
749    }
750    return counter;
751}
752
753
754
755ED4_base *ED4_base::get_parent(ED4_level lev) const
756{
757    ED4_base *temp_parent = this->parent;
758
759    while (temp_parent && !(temp_parent->spec.level & lev)) {
760        temp_parent = temp_parent->parent;
761    }
762
763    return temp_parent;
764}
765
766void ED4_base::unlink_from_parent() {
767    e4_assert(parent);
768    parent->children->remove_member(this);
769}
770
771char *ED4_base::get_name_of_species() {
772    char                *name        = 0;
773    ED4_species_manager *species_man = get_parent(ED4_L_SPECIES)->to_species_manager();
774    if (species_man) {
775        ED4_species_name_terminal *species_name = species_man->search_spec_child_rek(ED4_L_SPECIES_NAME)->to_species_name_terminal();
776        if (species_name) {
777            GBDATA *gb_name   = species_name->get_species_pointer();
778            if (gb_name) {
779                GB_transaction ta(gb_name);
780                name = GB_read_as_string(gb_name);
781            }
782        }
783    }
784    return name;
785}
786
787ED4_base *ED4_manager::get_defined_level(ED4_level lev) const
788{
789    int i;
790
791    for (i=0; i<children->members(); i++) { // first make a complete search in myself
792        if (children->member(i)->spec.level & lev) {
793            return children->member(i);
794        }
795    }
796
797    for (i=0; i<children->members(); i++) { // then all groups
798        ED4_base *member = children->member(i);
799
800        if (member->is_multi_species_manager()) {
801            return member->to_multi_species_manager()->get_defined_level(lev);
802        }
803        else if (member->is_group_manager()) {
804            return member->to_group_manager()->children->member(1)->to_multi_species_manager()->get_defined_level(lev);
805        }
806    }
807    return NULL;                                                                // nothing found
808}
809
810ED4_returncode ED4_base::set_width() {
811    // sets object length of terminals to Consensus_Name_terminal if existing
812    // else to MAXSPECIESWIDTH
813
814    if (is_species_manager()) {
815        ED4_species_manager *species_manager = to_species_manager();
816
817        if (!species_manager->is_consensus_manager()) {
818            ED4_multi_name_manager    *multi_name_manager = species_manager->get_defined_level(ED4_L_MULTI_NAME)->to_multi_name_manager();  // case I'm a species
819            ED4_species_name_terminal *consensus_terminal = parent->to_multi_species_manager()->get_consensus_name_terminal();
820
821            for (int i=0; i < multi_name_manager->children->members(); i++) {
822                ED4_name_manager *name_manager = multi_name_manager->children->member(i)->to_name_manager();
823                ED4_base         *nameTerm     = name_manager->children->member(0);
824                int               width        = consensus_terminal ? consensus_terminal->extension.size[WIDTH] : MAXSPECIESWIDTH;
825
826                nameTerm->extension.size[WIDTH] = width;
827                nameTerm->request_resize();
828            }
829
830            for (int i=0; i < species_manager->children->members(); i++) { // adjust all managers as far as possible
831                ED4_base *smember = species_manager->children->member(i);
832                if (consensus_terminal) {
833                    ED4_base *kmember = consensus_terminal->parent->children->member(i);
834                    if (kmember) {
835                        smember->extension.position[X_POS] = kmember->extension.position[X_POS];
836                        ED4_base::touch_world_cache();
837                    }
838                }
839                else { // got no consensus
840                    ED4_species_manager *a_species = parent->get_defined_level(ED4_L_SPECIES)->to_species_manager();
841                    if (a_species) {
842                        smember->extension.position[X_POS] = a_species->children->member(i)->extension.position[X_POS];
843                        ED4_base::touch_world_cache();
844                    }
845                }
846                smember->request_resize();
847            }
848        }
849    }
850    else if (is_group_manager()) {
851        ED4_group_manager         *group_manager           = to_group_manager();
852        ED4_multi_species_manager *multi_species_manager   = group_manager->get_multi_species_manager();
853        ED4_species_name_terminal *mark_consensus_terminal = multi_species_manager->get_consensus_name_terminal();
854        ED4_species_name_terminal *consensus_terminal      = parent->to_multi_species_manager()->get_consensus_name_terminal();
855
856        if (consensus_terminal) { // we're a group in another group
857            mark_consensus_terminal->extension.size[WIDTH] = consensus_terminal->extension.size[WIDTH] - BRACKETWIDTH;
858        }
859        else { // we're at the top (no consensus terminal)
860            mark_consensus_terminal->extension.size[WIDTH] = MAXSPECIESWIDTH - BRACKETWIDTH;
861        }
862
863        mark_consensus_terminal->request_resize();
864
865        for (int i=0; i < multi_species_manager->children->members(); i++) {
866            multi_species_manager->children->member(i)->set_width();
867        }
868
869        for (int i=0; i < group_manager->children->members(); i++) { // for all groups below from us
870            if (group_manager->children->member(i)->is_group_manager()) {
871                group_manager->children->member(i)->set_width();
872            }
873        }
874    }
875
876    return ED4_R_OK;
877}
878
879
880short ED4_base::in_border(AW_pos x, AW_pos y, ED4_movemode mode)                                // determines if given world coords x and y
881{                                                                                               // are within borders of current object according to move mode
882    AW_pos    world_x, world_y;
883
884    calc_world_coords(&world_x, &world_y);                                              // calculate absolute extension of current object
885
886    switch (mode)                                                                               // which direction ?
887    {
888        case ED4_M_HORIZONTAL:
889            {
890                if ((x >= world_x) && (x < (world_x + extension.size[WIDTH])))
891                    return (1);                                                 // target location is within the borders of parent
892                break;
893            }
894        case ED4_M_VERTICAL:
895            {
896                if ((y >= world_y) && (y < (world_y + extension.size[HEIGHT])))
897                    return (1);                                                 // target location is within the borders of parent
898                break;
899            }
900        case ED4_M_FREE:
901            {
902                return (in_border(x, y, ED4_M_HORIZONTAL) && in_border(x, y, ED4_M_VERTICAL));
903            }
904        case ED4_M_NO_MOVE:
905            {
906                break;
907            }
908    }
909
910    return (0);
911}
912
913
914void ED4_base::calc_rel_coords(AW_pos *x, AW_pos *y) // calculates coordinates relative to current object from given world coords
915{
916    AW_pos   world_x, world_y;
917
918    calc_world_coords(&world_x, &world_y);          // calculate world coordinates of current object
919
920    *x -= world_x;                                  // calculate relative coordinates by subtracting world
921    *y -= world_y;                                  // coords of current object
922}
923
924
925ED4_returncode  ED4_base::event_sent_by_parent(AW_event * /* event */, AW_window * /* aww */)
926{
927    return (ED4_R_OK);
928}
929
930void ED4_manager::hide_children() {
931    for (int i=0; i<children->members(); i++) {
932        ED4_base *member = children->member(i);
933        if (!member->is_spacer_terminal() && !member->is_consensus_manager()) { // don't hide spacer and Consensus
934            member->flag.hidden = 1;
935        }
936    }
937    request_resize();
938}
939
940
941void ED4_manager::unhide_children() {
942    if (children) {
943        for (int i=0; i < children->members(); i++) {
944            children->member(i)->flag.hidden = 0; // make child visible
945        }
946        request_resize();
947    }
948}
949
950void ED4_bracket_terminal::unfold() {
951    if (parent) {
952        for (int i=0; i < parent->children->members(); i++) {
953            ED4_base *member = parent->children->member(i);
954
955            if (member->is_multi_species_manager()) {
956                ED4_multi_species_manager *multi_species_manager = member->to_multi_species_manager();
957                multi_species_manager->unhide_children();
958                multi_species_manager->clr_property(ED4_P_IS_FOLDED);
959
960                ED4_spacer_terminal *spacer = multi_species_manager->get_defined_level(ED4_L_SPACER)->to_spacer_terminal();
961                spacer->extension.size[HEIGHT] = SPACERHEIGHT;
962            }
963        }
964
965        clr_property(ED4_P_IS_FOLDED);
966        parent->clr_property(ED4_P_IS_FOLDED);
967    }
968}
969
970void ED4_bracket_terminal::fold() {
971    if (parent) {
972        ED4_multi_species_manager *multi_species_manager = parent->get_defined_level(ED4_L_MULTI_SPECIES)->to_multi_species_manager();
973
974        int consensus_shown = 0;
975        // @@@ code below is duplicated in ED4_base::generate_configuration_string
976        if (!(multi_species_manager->children->member(1)->is_consensus_manager())) { // if consensus is not a top = > move to top
977            ED4_members *multi_children    = multi_species_manager->children;
978            ED4_manager *consensus_manager = NULL;
979
980            int i;
981            for (i=0; i<multi_children->members(); i++) { // search for consensus
982                if (multi_children->member(i)->is_consensus_manager()) {
983                    consensus_manager = multi_children->member(i)->to_manager();
984                    break;
985                }
986            }
987
988            if (consensus_manager) {
989                multi_children->move_member(i, 1); // move Consensus to top of list
990                consensus_manager->extension.position[Y_POS] = SPACERHEIGHT;
991                ED4_base::touch_world_cache();
992                consensus_shown = 1;
993            }
994        }
995        else {
996            consensus_shown = 1;
997        }
998
999        if (consensus_shown && ED4_ROOT->aw_root->awar(ED4_AWAR_CONSENSUS_SHOW)->read_int()==0) {
1000            consensus_shown = 0;
1001        }
1002
1003        ED4_spacer_terminal *spacer = multi_species_manager->get_defined_level(ED4_L_SPACER)->to_spacer_terminal();
1004        if (spacer) {
1005            spacer->extension.size[HEIGHT] = consensus_shown ? SPACERHEIGHT : SPACERNOCONSENSUSHEIGHT;
1006        }
1007
1008        multi_species_manager->hide_children();
1009        multi_species_manager->set_property(ED4_P_IS_FOLDED);
1010
1011        set_property(ED4_P_IS_FOLDED);
1012        parent->set_property(ED4_P_IS_FOLDED);
1013    }
1014}
1015
1016void ED4_base::check_all()
1017{
1018    AW_pos x, y;
1019
1020    calc_world_coords(&x, &y);
1021
1022    printf("Typ des Aufrufers :\t\t\t%s\n", is_manager() ? "Manager" : "Terminal");
1023    printf("Name des Aufrufers von Check_All : \t%.30s\n", (id) ? id : "Keine ID");
1024    printf("Linke obere Ecke x, y : \t\t%f, %f\n", extension.position[0], extension.position[1]);
1025    printf("Breite und Hoehe x, y : \t\t%f, %f\n", extension.size[0], extension.size[1]);
1026    printf("World Coords     x, y : \t\t%f, %f\n\n", x, y);
1027    printf("***********************************************\n\n");
1028}
1029
1030int ED4_base::adjust_clipping_rectangle() {
1031    // return 0 if clipping rectangle disappeared (nothing left to draw)
1032    AW::Rectangle base_area = get_win_area(current_ed4w());
1033    return current_device()->reduceClipBorders(base_area.top(), base_area.bottom(), base_area.left(), base_area.right());
1034}
1035
1036void ED4_base::set_links(ED4_base *new_width, ED4_base *new_height) {
1037    // sets links in hierarchy :
1038    // width-link sets links between objects on same level
1039    // height-link sets links between objects on different levels
1040
1041    if (new_width) {
1042        if (width_link) width_link->linked_objects->remove_elem(this);
1043        width_link = new_width;
1044        if (!new_width->linked_objects) new_width->linked_objects = new ED4_base_list;
1045        new_width->linked_objects->append_elem(this);
1046    }
1047
1048    if (new_height) {
1049        if (height_link) height_link->linked_objects->remove_elem(this);
1050        height_link = new_height;
1051        if (!new_height->linked_objects) new_height->linked_objects = new ED4_base_list;
1052        new_height->linked_objects->append_elem(this);
1053    }
1054}
1055
1056int ED4_base::currTimestamp = 1;
1057
1058#if defined(DEBUG)
1059// #define VISIBLE_AREA_REFRESH
1060#endif
1061
1062ED4_returncode ED4_base::clear_background(int color) {
1063    if (current_device()) { // @@@ should clear be done for all windows?
1064        AW_pos x, y;
1065        calc_world_coords(&x, &y);
1066        current_ed4w()->world_to_win_coords(&x, &y);
1067
1068        current_device()->push_clip_scale();
1069        if (adjust_clipping_rectangle()) {
1070            if (!color) {
1071#if defined(VISIBLE_AREA_REFRESH)
1072                // for debugging draw each clear in different color:
1073                static int gc_area = ED4_G_FIRST_COLOR_GROUP;
1074
1075                current_device()->box(gc_area, true, x, y, extension.size[WIDTH], extension.size[HEIGHT]);
1076                gc_area = (gc_area == ED4_G_LAST_COLOR_GROUP) ? ED4_G_FIRST_COLOR_GROUP : gc_area+1;
1077#else // !defined(VISIBLE_AREA_REFRESH)
1078                current_device()->clear_part(x, y, extension.size[WIDTH], extension.size[HEIGHT], AW_ALL_DEVICES);
1079#endif
1080            }
1081            else {
1082                // fill range with color for debugging
1083                current_device()->box(color, true, x, y, extension.size[WIDTH], extension.size[HEIGHT]);
1084            }
1085        }
1086        current_device()->pop_clip_scale();
1087    }
1088    return (ED4_R_OK);
1089}
1090
1091void ED4_main_manager::clear_whole_background() {
1092    // clear AW_MIDDLE_AREA
1093    for (ED4_window *window = ED4_ROOT->first_window; window; window=window->next) {
1094        AW_device *device = window->get_device();
1095        if (device) {
1096            device->push_clip_scale();
1097            device->clear(AW_ALL_DEVICES);
1098            device->pop_clip_scale();
1099        }
1100    }
1101}
1102
1103void ED4_base::draw_bb(int color) {
1104    if (current_device()) {
1105        current_device()->push_clip_scale();
1106        if (adjust_clipping_rectangle()) {
1107            AW_pos x1, y1;
1108            calc_world_coords(&x1, &y1);
1109            current_ed4w()->world_to_win_coords(&x1, &y1);
1110            current_device()->box(color, false, x1, y1, extension.size[WIDTH]-1, extension.size[HEIGHT]-1);
1111        }
1112        current_device()->pop_clip_scale();
1113    }
1114}
1115
1116ED4_base::ED4_base(const ED4_objspec& spec_, GB_CSTR temp_id, AW_pos x, AW_pos y, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1117    : spec(spec_)
1118{
1119    index = 0;
1120    dynamic_prop = ED4_P_NO_PROP;
1121    timestamp =  0; // invalid - almost always..
1122
1123    if (!strcmp(CONSENSUS, temp_id)) {
1124        id = NULL;
1125    }
1126    else {
1127        id = (char*)malloc(strlen(temp_id)+1);
1128        strcpy(id, temp_id);
1129    }
1130
1131    linked_objects = NULL;
1132
1133    extension.position[X_POS] = x;
1134    extension.position[Y_POS] = y;
1135    ED4_base::touch_world_cache();
1136    extension.size[WIDTH] = width;
1137    extension.size[HEIGHT] = height;
1138    extension.y_folded = 0;
1139    parent = temp_parent;
1140    width_link = NULL;
1141    height_link = NULL;
1142
1143    memset((char*)&update_info, 0, sizeof(update_info));
1144    memset((char*)&flag, 0, sizeof(flag));
1145}
1146
1147
1148ED4_base::~ED4_base() {
1149    // before calling this function the first time, parent has to be set NULL
1150    e4_assert(!parent); // unlink from parent first!
1151
1152    if (linked_objects) {
1153        ED4_base_list_elem *list_elem = linked_objects->head();
1154        while (list_elem) {
1155            ED4_base *object = list_elem->elem();
1156            if (object->width_link == this) {
1157                object->width_link->linked_objects->remove_elem(this);              // delete link and
1158                object->width_link = NULL;
1159            }
1160
1161            if (object->height_link == this) {
1162                object->height_link->linked_objects->remove_elem(this);             // delete link and
1163                object->height_link = NULL;
1164            }
1165
1166            ED4_base_list_elem *old_elem = list_elem;
1167            list_elem = list_elem->next();
1168            linked_objects->remove_elem(old_elem->elem());
1169        }
1170        delete linked_objects;
1171    }
1172
1173    if (update_info.linked_to_scrolled_rectangle)
1174    {
1175        if (ED4_ROOT->main_manager)
1176        {
1177            ED4_base *sequence_terminal = ED4_ROOT->main_manager->search_spec_child_rek(ED4_L_SEQUENCE_STRING);
1178
1179            if (sequence_terminal)
1180                sequence_terminal->update_info.linked_to_scrolled_rectangle = 1;
1181
1182            update_info.linked_to_scrolled_rectangle = 0;
1183            ED4_ROOT->scroll_links.link_for_hor_slider = sequence_terminal;
1184
1185            ED4_window *ed4w = ED4_ROOT->first_window;
1186            while (ed4w != NULL) {
1187                ed4w->scrolled_rect.replace_x_width_link_to(this, sequence_terminal);
1188                ed4w = ed4w->next;
1189            }
1190        }
1191    }
1192
1193    if (width_link) {
1194        width_link->linked_objects->remove_elem(this);
1195        width_link = NULL;
1196    }
1197
1198    if (height_link) {
1199        height_link->linked_objects->remove_elem(this);
1200        height_link = NULL;
1201    }
1202
1203    set_species_pointer(0);     // clear pointer to database and remove callbacks
1204    free(id);
1205}
1206
Note: See TracBrowser for help on using the repository browser.