root/trunk/EDIT4/ED4_base.cxx

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