source: tags/ms_r18q1/EDIT4/ED4_manager.cxx

Last change on this file was 16766, 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: 65.7 KB
Line 
1#include <arbdbt.h>
2
3#include <aw_preset.hxx>
4#include <aw_awar.hxx>
5#include <aw_msg.hxx>
6#include <aw_root.hxx>
7
8#include "ed4_class.hxx"
9#include "ed4_awars.hxx"
10#include "ed4_edit_string.hxx"
11#include "ed4_tools.hxx"
12#include "ed4_list.hxx"
13#include "ed4_ProteinViewer.hxx"
14#include "ed4_protein_2nd_structure.hxx"
15#include "ed4_seq_colors.hxx"
16
17#if defined(DEBUG)
18#define TEST_REFRESH_FLAG
19#endif
20
21// -----------------------------------------------------------------
22//      Manager static properties (used by manager-constructors)
23
24static ED4_objspec main_manager_spec(
25    (ED4_properties)(PROP_IS_MANAGER | PROP_HORIZONTAL), // static props
26    LEV_ROOT,                                              // level
27    LEV_ROOTGROUP,                                         // allowed children level
28    LEV_NONE,                                              // handled object
29    LEV_NONE                                               // restriction level
30    );
31
32static ED4_objspec device_manager_spec(
33    (ED4_properties)(PROP_IS_MANAGER | PROP_HORIZONTAL), // static props
34    LEV_DEVICE,                                            // level
35    (ED4_level)(LEV_AREA | LEV_SPACER | LEV_LINE),         // allowed children level
36    LEV_NONE,                                              // handled object
37    LEV_NONE                                               // restriction level
38    );
39
40static ED4_objspec area_manager_spec(
41    (ED4_properties)(PROP_IS_MANAGER | PROP_VERTICAL),    // static props
42    LEV_AREA,                                               // level
43    (ED4_level)(LEV_MULTI_SPECIES | LEV_TREE | LEV_SPACER), // allowed children level
44    LEV_NONE,                                               // handled object
45    LEV_NONE                                                // restriction level
46    );
47
48static ED4_objspec multi_species_manager_spec(
49    (ED4_properties)(PROP_IS_MANAGER | PROP_HORIZONTAL), // static props
50    LEV_MULTI_SPECIES,                                     // level
51    (ED4_level)(LEV_SPECIES | LEV_GROUP | LEV_SPACER),     // allowed children level
52    LEV_NONE,                                              // handled object
53    LEV_NONE                                               // restriction level
54    );
55
56static ED4_objspec species_manager_spec(
57    (ED4_properties)(PROP_IS_MANAGER | PROP_VERTICAL),  // static props
58    LEV_SPECIES,                                        // level
59    (ED4_level)(LEV_MULTI_SEQUENCE | LEV_MULTI_NAME |   // (used by normal species)
60                LEV_SPECIES_NAME | LEV_SEQUENCE |       // allowed children level (used by consensus)
61                LEV_FLAG_HEADER),
62    LEV_NONE,                                           // handled object
63    LEV_NONE                                            // restriction level
64    );
65
66static ED4_objspec multi_sequence_manager_spec(
67    (ED4_properties)(PROP_IS_MANAGER | PROP_HORIZONTAL), // static props
68    LEV_MULTI_SEQUENCE,                                    // level
69    LEV_SEQUENCE,                                          // allowed children level
70    LEV_NONE,                                              // handled object
71    LEV_NONE                                               // restriction level
72    );
73
74static ED4_objspec sequence_manager_spec(
75    (ED4_properties)(PROP_IS_MANAGER | PROP_VERTICAL),      // static props
76    LEV_SEQUENCE,                                             // level
77    (ED4_level)(LEV_SEQUENCE_INFO | LEV_SEQUENCE_STRING | LEV_ORF | LEV_PURE_TEXT | LEV_COL_STAT), // allowed children level
78    LEV_NONE,                                                 // handled object
79    LEV_SPECIES                                               // restriction level
80    );
81
82static ED4_objspec multi_name_manager_spec(
83    (ED4_properties)(PROP_IS_MANAGER | PROP_HORIZONTAL), // static props
84    LEV_MULTI_NAME,                                        // level
85    LEV_NAME_MANAGER,                                      // allowed children level
86    LEV_NONE,                                              // handled object
87    LEV_NONE                                               // restriction level
88    );
89
90static ED4_objspec name_manager_spec(
91    (ED4_properties)(PROP_IS_MANAGER | PROP_VERTICAL),   // static props
92    LEV_NAME_MANAGER,                                    // level
93    (ED4_level)(LEV_SPECIES_NAME | LEV_FLAG),            // allowed children level
94    LEV_NONE,                                            // handled object
95    LEV_SPECIES                                          // restriction level
96    );
97
98static ED4_objspec group_manager_spec(
99    (ED4_properties)(PROP_IS_MANAGER | PROP_VERTICAL), // static props
100    LEV_GROUP,                                           // level
101    (ED4_level)(LEV_MULTI_SPECIES | LEV_BRACKET),        // allowed children level
102    LEV_NONE,                                            // handled object
103    LEV_NONE                                             // restriction level
104    );
105
106static ED4_objspec root_group_manager_spec(
107    (ED4_properties)(PROP_IS_MANAGER | PROP_VERTICAL), // static props
108    LEV_ROOTGROUP,                                       // level
109    (ED4_level)(LEV_DEVICE),                             // allowed children level
110    LEV_NONE,                                            // handled object
111    LEV_NONE                                             // restriction level
112    );
113
114// ----------------------------
115//      ED4_manager methods
116
117ED4_returncode ED4_manager::rebuild_consensi(ED4_base *start_species, ED4_update_flag update_flag) {
118    int                        i;
119    ED4_base                  *temp_parent;
120    ED4_multi_species_manager *multi_species_manager = NULp;
121    ED4_group_manager         *first_group_manager   = NULp;
122
123    temp_parent = start_species;
124
125    switch (update_flag) {
126        case ED4_U_UP:          // rebuild consensus from a certain starting point upwards
127            while (temp_parent) {
128                if (temp_parent->is_group_manager()) {
129                    multi_species_manager = temp_parent->to_group_manager()->get_multi_species_manager();
130                    for (i=0; i<multi_species_manager->members(); i++) {
131                        if (multi_species_manager->member(i)->is_consensus_manager()) {
132                            rebuild_consensus(multi_species_manager->member(i)).expect_no_error();
133                        }
134                    }
135                }
136                temp_parent = temp_parent->parent;
137            }
138            break;
139        case ED4_U_UP_DOWN:     // only search first groupmanager and update consensi recursively downwards
140            while (temp_parent) {
141                if (temp_parent->is_group_manager()) {
142                    first_group_manager = temp_parent->to_group_manager();
143                }
144                temp_parent = temp_parent->parent;
145            }
146            if (first_group_manager)
147                first_group_manager->route_down_hierarchy(makeED4_route_cb(rebuild_consensus)).expect_no_error();
148            break;
149    }
150    return ED4_R_OK;
151}
152
153ED4_returncode ED4_manager::check_in_bases(ED4_base *added_base) {
154    if (added_base->is_species_manager()) { // add a sequence
155        ED4_species_manager *species_manager = added_base->to_species_manager();
156        const ED4_terminal *sequence_terminal = species_manager->get_consensus_relevant_terminal();
157
158        if (sequence_terminal) {
159            int   seq_len;
160            char *seq          = sequence_terminal->resolve_pointer_to_string_copy(&seq_len);
161            ED4_returncode res = update_bases(NULp, 0, seq, seq_len);
162            free(seq);
163            return res;
164        }
165    }
166
167    e4_assert(!added_base->is_root_group_manager());
168    if (added_base->is_group_manager()) { // add a group
169        return update_bases(NULp, &added_base->to_group_manager()->table());
170    }
171
172    e4_assert(0); // wrong type
173   
174    return ED4_R_OK;
175}
176
177ED4_returncode ED4_manager::check_out_bases(ED4_base *subbed_base) {
178    if (subbed_base->is_species_manager()) { // sub a sequence
179        ED4_species_manager *species_manager = subbed_base->to_species_manager();
180        const ED4_terminal *sequence_terminal = species_manager->get_consensus_relevant_terminal();
181
182        if (sequence_terminal) {
183            int   seq_len;
184            char *seq          = sequence_terminal->resolve_pointer_to_string_copy(&seq_len);
185            ED4_returncode res = update_bases(seq, seq_len, NULp, 0);
186            free(seq);
187            return res;
188        }
189    }
190    else {
191        e4_assert(!subbed_base->is_root_group_manager());
192        if (subbed_base->is_group_manager()) { // sub a group
193            return update_bases(&subbed_base->to_group_manager()->table(), NULp);
194        }
195        e4_assert(0); // wrong type
196    }
197    return ED4_R_OK;
198}
199
200ED4_returncode ED4_manager::update_bases(const char *old_sequence, int old_len, const ED4_base *new_base, PosRange range) {
201    if (!new_base) {
202        return update_bases(old_sequence, old_len, NULp, 0, range);
203    }
204
205    e4_assert(new_base->is_species_manager());
206
207    const ED4_species_manager *new_species_manager   = new_base->to_species_manager();
208    const ED4_terminal        *new_sequence_terminal = new_species_manager->get_consensus_relevant_terminal();
209
210    int   new_len;
211    char *new_sequence = new_sequence_terminal->resolve_pointer_to_string_copy(&new_len);
212
213    if (range.is_whole()) {
214        const PosRange *restricted = BaseFrequencies::changed_range(old_sequence, new_sequence, std::min(old_len, new_len));
215       
216        e4_assert(restricted);
217        range = *restricted;
218    }
219
220    ED4_returncode res = update_bases(old_sequence, old_len, new_sequence, new_len, range);
221    free(new_sequence);
222    return res;
223}
224
225ED4_returncode ED4_manager::update_bases_and_rebuild_consensi(const char *old_sequence, int old_len, ED4_base *new_base, ED4_update_flag update_flag, PosRange range) {
226    e4_assert(new_base);
227    e4_assert(new_base->is_species_manager());
228
229    ED4_species_manager *new_species_manager   = new_base->to_species_manager();
230    const ED4_terminal  *new_sequence_terminal = new_species_manager->get_consensus_relevant_terminal();
231
232    int         new_len;
233    const char *new_sequence = new_sequence_terminal->resolve_pointer_to_char_pntr(&new_len);
234
235#if defined(DEBUG) && 0
236    printf("old: %s\n", old_sequence);
237    printf("new: %s\n", new_sequence);
238#endif // DEBUG
239
240    const PosRange *changedRange = NULp;
241    if (range.is_whole()) {
242        changedRange = BaseFrequencies::changed_range(old_sequence, new_sequence, std::min(old_len, new_len));
243    }
244    else {
245        changedRange = &range; // @@@ use method similar to changed_range here, which just reduces the existing range
246    }
247
248    ED4_returncode result = ED4_R_OK;
249    if (changedRange) {
250        ED4_returncode result1 = update_bases(old_sequence, old_len, new_sequence, new_len, *changedRange);
251        ED4_returncode result2 = rebuild_consensi(new_base, update_flag);
252
253        result = (result1 != ED4_R_OK) ? result1 : result2;
254
255        // Refresh aminoacid sequence terminals in Protein Viewer or protstruct // @@@ this is definitely wrong here (omg)
256        if (ED4_ROOT->alignment_type == GB_AT_DNA) {
257            PV_SequenceUpdate_CB(GB_CB_CHANGED);
258        }
259        else if (ED4_ROOT->alignment_type == GB_AT_AA) { 
260            GB_ERROR err = ED4_pfold_set_SAI(&ED4_ROOT->protstruct, GLOBAL_gb_main, ED4_ROOT->alignment_name, &ED4_ROOT->protstruct_len);
261            if (err) { aw_message(err); result = ED4_R_WARNING; }
262        }
263    }
264    return result;
265}
266
267ED4_returncode ED4_manager::update_bases(const ED4_base *old_base, const ED4_base *new_base, PosRange range) {
268    e4_assert(old_base);
269    e4_assert(new_base);
270
271    if (old_base->is_species_manager()) {
272        e4_assert(new_base->is_species_manager());
273        const ED4_species_manager *old_species_manager   = old_base->to_species_manager();
274        const ED4_species_manager *new_species_manager   = new_base->to_species_manager();
275        const ED4_terminal        *old_sequence_terminal = old_species_manager->get_consensus_relevant_terminal();
276        const ED4_terminal        *new_sequence_terminal = new_species_manager->get_consensus_relevant_terminal();
277
278        int   old_len;
279        int   new_len;
280        char *old_seq = old_sequence_terminal->resolve_pointer_to_string_copy(&old_len);
281        char *new_seq = new_sequence_terminal->resolve_pointer_to_string_copy(&new_len);
282
283        ED4_returncode res = update_bases(old_seq, old_len, new_seq, new_len, range);
284        free(new_seq);
285        free(old_seq);
286        return res;
287    }
288
289    e4_assert(!old_base->is_root_group_manager());
290    e4_assert(!new_base->is_root_group_manager());
291    if (old_base->is_group_manager()) {
292        e4_assert(new_base->is_group_manager());
293
294        return update_bases(&old_base->to_group_manager()->table(),
295                           &new_base->to_group_manager()->table(),
296                           range);
297    }
298
299    return ED4_R_OK;
300}
301
302// WITH_ALL_ABOVE_GROUP_MANAGER_TABLES performs a command with all groupmanager-tables
303// starting at walk_up (normally the current) until top (or until one table has an ignore flag)
304
305#define WITH_ALL_ABOVE_GROUP_MANAGER_TABLES(walk_up, COMMAND)                                   \
306    do {                                                                                        \
307        while (walk_up) {                                                                       \
308            if (walk_up->is_abstract_group_manager()) {                                         \
309                BaseFrequencies& char_table = walk_up->to_abstract_group_manager()->table();     \
310                char_table.COMMAND;                                                             \
311                if (char_table.is_ignored()) break; /* @@@ problematic */                       \
312            }                                                                                   \
313            walk_up = walk_up->parent;                                                          \
314        }                                                                                       \
315    } while (0)
316
317ED4_returncode ED4_manager::update_bases(const char *old_sequence, int old_len, const char *new_sequence, int new_len, PosRange range) {
318    ED4_manager *walk_up = this;
319
320    if (old_sequence) {
321        if (new_sequence) {
322            if (range.is_whole()) {
323                const PosRange *restricted = BaseFrequencies::changed_range(old_sequence, new_sequence, std::min(old_len, new_len));
324                if (!restricted) return ED4_R_OK;
325               
326                range = *restricted;
327            }
328
329#if defined(DEBUG) && 0
330            printf("update_bases(..., %i, %i)\n", start_pos, end_pos);
331#endif
332
333            WITH_ALL_ABOVE_GROUP_MANAGER_TABLES(walk_up, sub_and_add(old_sequence, new_sequence, range));
334        }
335        else {
336            e4_assert(range.is_whole());
337            WITH_ALL_ABOVE_GROUP_MANAGER_TABLES(walk_up, sub(old_sequence, old_len));
338        }
339    }
340    else {
341        if (new_sequence) {
342            e4_assert(range.is_whole());
343            WITH_ALL_ABOVE_GROUP_MANAGER_TABLES(walk_up, add(new_sequence, new_len));
344        }
345        else {
346            return ED4_R_OK;
347        }
348    }
349
350    ED4_ROOT->root_group_man->remap()->mark_compile_needed();
351    return ED4_R_OK;
352}
353
354ED4_returncode ED4_manager::update_bases(const BaseFrequencies *old_table, const BaseFrequencies *new_table, PosRange range) {
355    ED4_manager *walk_up = this;
356
357    if (old_table) {
358        if (new_table) {
359            if (range.is_whole()) {
360                const PosRange *restricted = old_table->changed_range(*new_table);
361                if (!restricted) return ED4_R_OK;
362
363                range = *restricted;
364            }
365            WITH_ALL_ABOVE_GROUP_MANAGER_TABLES(walk_up, sub_and_add(*old_table, *new_table, range));
366        }
367        else {
368            e4_assert(range.is_whole());
369            WITH_ALL_ABOVE_GROUP_MANAGER_TABLES(walk_up, sub(*old_table));
370        }
371    }
372    else {
373        if (new_table) {
374            e4_assert(range.is_whole());
375            WITH_ALL_ABOVE_GROUP_MANAGER_TABLES(walk_up, add(*new_table));
376        }
377        else {
378            return ED4_R_OK;
379        }
380    }
381
382    ED4_ROOT->root_group_man->remap()->mark_compile_needed();
383    return ED4_R_OK;
384}
385
386#undef WITH_ALL_ABOVE_GROUP_MANAGER_TABLES
387
388void ED4_manager::remove_callbacks() {
389    // removes callbacks
390    for (int i=0; i < members(); i++) {
391        member(i)->remove_callbacks();
392    }
393}
394
395void ED4_manager::update_consensus(ED4_manager *old_parent, ED4_manager *new_parent, ED4_base *sequence) {
396    if (old_parent) old_parent->check_out_bases(sequence);
397    if (new_parent) new_parent->check_in_bases(sequence);
398}
399
400ED4_terminal* ED4_manager::get_first_terminal(int start_index) const {
401    ED4_terminal *terminal = NULp;
402
403    for (int i=start_index; !terminal && i>=0 && i<members(); i++) {
404        ED4_base *base = member(i);
405        if (base->is_terminal()) {
406            terminal = base->to_terminal();
407        }
408        else {
409            terminal = base->to_manager()->get_first_terminal();
410        }
411    }
412
413    return terminal;
414}
415
416ED4_terminal* ED4_manager::get_last_terminal(int start_index) const {
417    ED4_terminal *terminal = NULp;
418
419    if (start_index<0) start_index = members()-1;
420    for (int i=start_index; !terminal && i>=0 && i<members(); i--) {
421        ED4_base *base = member(i);
422        if (base->is_terminal()) {
423            terminal = base->to_terminal();
424        }
425        else {
426            terminal = base->to_manager()->get_last_terminal();
427        }
428    }
429
430    return terminal;
431}
432
433ED4_base* ED4_manager::get_competent_child(AW_pos x, AW_pos y, ED4_properties relevant_prop) {
434    ED4_extension  ext;
435    ED4_index      temp_index;
436    ED4_base      *child;
437
438    ext.position[X_POS] = x;
439    ext.position[Y_POS] = y;
440    ED4_base::touch_world_cache();
441
442    temp_index = search_member(&ext, spec.static_prop);
443
444    if ((temp_index < 0) || (temp_index >= members())) {     // no child at given location
445        return NULp;
446    }
447
448    child = member(temp_index);
449
450    return (child->spec.static_prop & relevant_prop) ? child : (ED4_base*)NULp;
451}
452
453ED4_base* ED4_manager::get_competent_clicked_child(AW_pos x, AW_pos y, ED4_properties relevant_prop) {
454    ED4_extension  ext;
455    ED4_base      *child;
456    ED4_base      *temp_parent = NULp;
457
458    ext.position[X_POS] = x;
459    ext.position[Y_POS] = y;
460    ED4_base::touch_world_cache();
461
462    search_target_species(&ext, spec.static_prop, &temp_parent, LEV_MULTI_SPECIES);
463
464    if (!temp_parent) {
465        temp_parent = this;
466    }
467
468    child = temp_parent;
469    if (child->spec.static_prop & relevant_prop) {
470        return child;
471    }
472    else {
473        return NULp;
474    }
475}
476
477ED4_returncode ED4_manager::handle_move(ED4_move_info *mi) {
478    // handles a move request with target world
479    // coordinates within current object's borders
480
481    if ((!mi) || (mi->object->spec.level <= spec.level)) {
482        return ED4_R_IMPOSSIBLE;
483    }
484
485    AW_pos rel_x = mi->end_x; // calculate target position relative to current object
486    AW_pos rel_y = mi->end_y;
487    calc_rel_coords(&rel_x, &rel_y);
488
489    if ((mi->preferred_parent & spec.level) ||             // desired parent or levels match = > can handle moving
490        (mi->object->spec.level & spec.allowed_children)) // object(s) myself, take info from list of selected objects
491    {
492        ED4_base *object;
493        bool      i_am_consensus = false;
494
495        if (mi->object->has_property(PROP_IS_HANDLE)) { // object is a handle for an object up in the hierarchy = > search it
496            ED4_level mlevel = mi->object->spec.handled_level;
497
498            object = mi->object;
499
500            while (object && !(object->spec.level & mlevel)) object = object->parent;
501            if (!object) return ED4_R_IMPOSSIBLE; // no target level found
502        }
503        else {
504            object = mi->object; // selected object is no handle => take it directly
505
506            if (object->is_consensus_manager()) {
507                if (this->is_child_of(object->parent)) return ED4_R_IMPOSSIBLE; // has to pass multi_species_manager
508                i_am_consensus = true;
509                if (object->parent != this) {
510                    object = object->parent->parent;
511                    mi->object = object;
512                }
513            }
514        }
515
516
517        ED4_manager *old_parent = object->parent;
518
519        AW_pos x_off = 0;
520
521        // now do move action => determine insertion offsets and insert object
522
523        if (ED4_ROOT->selected_objects->size()>1) {
524            ED4_selected_elem *list_elem = ED4_ROOT->selected_objects->head();
525            while (list_elem) {
526                ED4_selection_entry *sel_info   = list_elem->elem();
527                ED4_terminal        *sel_object = sel_info->object;
528
529                if (sel_object==mi->object) break;
530                if (spec.static_prop & PROP_VERTICAL) x_off += sel_info->actual_width;
531
532                list_elem = list_elem->next();
533            }
534        }
535
536        {
537            ED4_extension loc;
538            loc.position[Y_POS] = mi->end_y;
539            loc.position[X_POS] = mi->end_x;
540            ED4_base::touch_world_cache();
541
542            ED4_base *found_member = NULp;
543            {
544                ED4_manager *dummy_mark = ED4_ROOT->main_manager->search_spec_child_rek(LEV_DEVICE)->to_manager();
545                dummy_mark->search_target_species(&loc, PROP_HORIZONTAL, &found_member, LEV_NONE);
546            }
547
548            if (found_member==object) { // if we are dropped on ourself => don't move
549                return ED4_R_BREAK;
550            }
551        }
552
553        {
554            ED4_base *parent_man = object->get_parent(LEV_MULTI_SPECIES);
555            object->parent->remove_member(object);
556            parent_man->to_multi_species_manager()->invalidate_species_counters();
557        }
558
559        object->extension.position[X_POS] = rel_x + x_off;
560        object->extension.position[Y_POS] = rel_y;
561        ED4_base::touch_world_cache();
562
563        object->parent = this;
564
565        if (old_parent != this) { // check whether consensus has to be calculated new or not
566            GB_push_transaction(GLOBAL_gb_main);
567            update_consensus(old_parent, this, object);
568            rebuild_consensi(old_parent, ED4_U_UP);
569            rebuild_consensi(this, ED4_U_UP);
570            GB_pop_transaction(GLOBAL_gb_main);
571        }
572
573        if ((i_am_consensus && object->parent != old_parent) || !i_am_consensus) {
574            object->set_width();
575
576            if (parent->has_property(PROP_IS_FOLDED)) { // add spacer and consensusheight
577                e4_assert(parent->is_group_manager());
578                object->extension.position[Y_POS] = member(0)->extension.size[HEIGHT] + member(1)->extension.size[HEIGHT];
579                object->flag.hidden = 1;
580                ED4_base::touch_world_cache();
581            }
582        }
583
584        insert_member(object);
585        if (is_multi_species_manager()) {
586            to_multi_species_manager()->invalidate_species_counters();
587        }
588        else {
589            get_parent(LEV_MULTI_SPECIES)->to_multi_species_manager()->invalidate_species_counters();
590        }
591
592        ED4_request_relayout();
593
594        return ED4_R_OK;
595    }
596    else {
597        // levels do not match = > ask competent manager child to handle move request
598        ED4_manager *manager = (ED4_manager *) get_competent_child(rel_x, rel_y, PROP_IS_MANAGER);
599        if (!manager) return ED4_R_IMPOSSIBLE; // no manager child covering target location = > move not possible
600        return manager->move_requested_by_parent(mi); // there is a manager child covering target location = > pass on move request
601    }
602}
603
604
605ED4_returncode ED4_manager::move_requested_by_parent(ED4_move_info *mi) {
606    // handles a move request with target world coordinates coming from parent
607    if ((!mi) || !(in_border(mi->end_x, mi->end_y, mi->mode)))
608        return ED4_R_IMPOSSIBLE;
609
610    return handle_move(mi);
611}
612
613
614ED4_returncode  ED4_manager::move_requested_by_child(ED4_move_info *mi) {
615    // handles a move request coming from a child,
616    // target location can be out of borders
617    if (!mi)
618        return ED4_R_IMPOSSIBLE;
619
620    if (spec.level < mi->object->spec.restriction_level) return ED4_R_IMPOSSIBLE; // check if there is a level restriction to the move request
621
622    if (mi->object->has_property(PROP_IS_HANDLE)) { // determine first if we could be the moving object
623        if (has_property(PROP_MOVABLE) && (spec.level & mi->object->spec.handled_level)) { // yes, we are meant to be the moving object
624            mi->object = this;
625        }
626
627        if (!parent) return ED4_R_WARNING;
628
629        return parent->move_requested_by_child(mi);
630    }
631
632    if (!(in_border(mi->end_x, mi->end_y, mi->mode))) {
633        // determine if target location is within
634        // the borders of current object, do boundary
635        // adjustment of target coordinates if necessary
636        // target location is not within borders =>
637        // ask parent, i.e. move recursively up
638        if (!parent) return ED4_R_WARNING;
639        return parent->move_requested_by_child(mi);
640    }
641    else { // target location within current borders = > handle move myself
642        ED4_base *temp_parent = get_competent_clicked_child(mi->end_x, mi->end_y, PROP_IS_MANAGER);
643
644        if (!temp_parent) {
645            return handle_move(mi);
646        }
647        else {
648            if ((temp_parent->is_group_manager()) || (temp_parent->is_area_manager())) {
649                temp_parent = temp_parent->to_group_manager()->get_defined_level(LEV_MULTI_SPECIES);
650            }
651            else if (!(temp_parent->is_multi_species_manager())) {
652                temp_parent = temp_parent->get_parent(LEV_MULTI_SPECIES);
653            }
654            if (!temp_parent) {
655                return ED4_R_IMPOSSIBLE;
656            }
657            return temp_parent->to_manager()->handle_move(mi);
658        }
659    }
660}
661
662ED4_returncode ED4_manager::event_sent_by_parent(AW_event *event, AW_window *aww) {
663    // handles an input event coming from parent
664    if (flag.hidden) {
665        return ED4_R_BREAK;
666    }
667
668    ED4_extension ext;
669    ext.position[X_POS] = event->x;
670    ext.position[Y_POS] = event->y;
671
672    calc_rel_coords(&ext.position[X_POS], &ext.position[Y_POS]);
673
674    ED4_index temp_index = search_member(&ext, spec.static_prop); // search child who is competent for the location of given event
675    if (!existing_index(temp_index)) {
676        return ED4_R_IMPOSSIBLE; // no suitable member found
677    }
678
679    return member(temp_index)->event_sent_by_parent(event, aww);
680}
681
682ED4_returncode  ED4_manager::refresh_requested_by_child() {
683    // handles a refresh-request from a child
684    if (!update_info.refresh) { // determine if there were more refresh requests already => no need to tell parent about it
685        update_info.set_refresh(1); // this is the first refresh request
686        if (parent) parent->refresh_requested_by_child(); // if we have a parent, tell him about the refresh request
687    }
688
689#ifdef TEST_REFRESH_FLAG
690    e4_assert(refresh_flag_ok());
691#endif
692    return ED4_R_OK;
693}
694
695int ED4_manager::refresh_flag_ok() {
696    ED4_index i;
697
698    for (i=0; i<members(); i++) {
699        ED4_base *child = member(i);
700
701        if (child->is_manager()) {
702            if (!child->to_manager()->refresh_flag_ok()) {
703                return 0;
704            }
705        }
706
707        if (child->update_info.refresh==1 && update_info.refresh==0) {
708            printf("Forgotten refresh-flag in '%s' (son of '%s')\n", child->id, id);
709            fflush(stdout);
710            return 0;
711        }
712    }
713
714    return 1;
715}
716
717inline void ED4_base::resize_requested_by_link(ED4_base *IF_ASSERTION_USED(link)) {
718    e4_assert((width_link == link) || (height_link == link)); // wrong link
719    if (calc_bounding_box()) request_resize();
720}
721
722void ED4_base::request_resize_of_linked() {
723    if (linked_objects) {
724        ED4_base_list_elem *current_list_elem = linked_objects->head();
725        while (current_list_elem) {
726            ED4_base *object = current_list_elem->elem();
727            object->resize_requested_by_link(this);
728            current_list_elem = current_list_elem->next();
729        }
730    }
731}
732
733bool ED4_manager::calc_bounding_box() {
734    // calculates the smallest rectangle containing the object.
735    // returns true if bounding box has changed.
736    AW_pos     sum_width  = 0;
737    AW_pos     sum_height = 0;
738    AW_pos     max_x      = 0;
739    AW_pos     max_y      = 0;
740    AW_pos     dummy      = 0;
741
742    for (ED4_index i = 0; existing_index(i); ++i) { // check all children
743        ED4_base *child = member(i);
744        if (!child->flag.hidden) {
745            sum_width  += child->extension.size[WIDTH];
746            sum_height += child->extension.size[HEIGHT];
747
748            dummy = child->extension.position[X_POS] + child->extension.size[WIDTH];
749            if (dummy > max_x) {
750                max_x = dummy;
751            }
752
753            dummy = child->extension.position[Y_POS] + child->extension.size[HEIGHT];
754            if (dummy > max_y) {
755                max_y = dummy;
756            }
757            ED4_base::touch_world_cache();
758        }
759    }
760
761    bool bb_changed = false;
762    if (spec.static_prop & PROP_HORIZONTAL) {
763        bb_changed = extension.set_size_does_change(WIDTH, max_x) || bb_changed;
764        bb_changed = extension.set_size_does_change(HEIGHT, sum_height) || bb_changed;
765    }
766
767    if (spec.static_prop & PROP_VERTICAL) {
768        bb_changed = extension.set_size_does_change(WIDTH, sum_width) || bb_changed;
769        bb_changed = extension.set_size_does_change(HEIGHT, max_y) || bb_changed;
770    }
771
772    if (bb_changed) {
773        request_resize_of_linked();
774    }
775    return bb_changed;
776}
777
778ED4_returncode ED4_manager::distribute_children() {
779    // distributes all children of current object according to current object's properties and
780    // justification value; a recalculation of current object's extension will take place if necessary
781
782    ED4_index rel_pos        = 0;
783    ED4_index rel_size       = 0;
784    ED4_index other_pos      = 0;
785    ED4_index other_size     = 0;
786    AW_pos    max_rel_size   = 0;
787    AW_pos    max_other_size = 0;
788
789    // set extension-indexes rel_pos and rel_size according to properties
790    if (spec.static_prop & PROP_HORIZONTAL) {
791        rel_pos    = X_POS;
792        other_pos  = Y_POS;
793        rel_size   = WIDTH;
794        other_size = HEIGHT;
795    }
796    if (spec.static_prop & PROP_VERTICAL) {
797        rel_pos    = Y_POS;
798        other_pos  = X_POS;
799        rel_size   = HEIGHT;
800        other_size = WIDTH;
801    }
802
803    // get maximal relevant and other size of children, set children's other position increasingly
804    for (ED4_index i = 0; existing_index(i); ++i) {
805        ED4_base *child = member(i);
806
807        max_rel_size = std::max(int(max_rel_size), int(child->extension.size[rel_size]));
808        if (child->extension.position[other_pos] != max_other_size) {
809            child->extension.position[other_pos] = max_other_size;
810            ED4_base::touch_world_cache();
811        }
812        max_other_size += child->extension.size[other_size];
813    }
814
815    // set children's relevant position according to justification value
816    // (0.0 means top- or left-justified, 1.0 means bottom- or right-justified)
817    for (ED4_index i = 0; existing_index(i); ++i) {
818        member(i)->extension.position[rel_pos] = 0.0;
819        ED4_base::touch_world_cache();
820    }
821
822    refresh_requested_by_child();
823    return ED4_R_OK;
824}
825
826void ED4_manager::resize_requested_children() {
827    if (update_info.resize) { // object wants to resize
828        update_info.set_resize(0); // first clear the resize flag (remember it could be set again from somewhere below the hierarchy)
829
830        for (ED4_index i = 0; existing_index(i); ++i) {
831            ED4_base *child = member(i);
832
833            child->update_info.set_resize(1);
834            child->resize_requested_children();
835        }
836
837        distribute_children();
838        if (calc_bounding_box()) request_resize();
839    }
840}
841void ED4_root_group_manager::resize_requested_children() {
842    if (update_info.resize) {
843        if (update_remap()) ED4_ROOT->request_refresh_for_specific_terminals(LEV_SEQUENCE_STRING);
844        ED4_manager::resize_requested_children();
845    }
846    else {
847        e4_assert(!update_remap());
848    }
849}
850
851static void update_scrolled_rectangles(ED4_window *win) { win->update_scrolled_rectangle(); }
852void ED4_main_manager::resize_requested_children() {
853    if (update_info.resize) {
854        ED4_manager::resize_requested_children();
855        ED4_with_all_edit_windows(update_scrolled_rectangles);
856    }
857}
858
859void ED4_main_manager::Show(bool refresh_all, bool is_cleared) {
860#ifdef TEST_REFRESH_FLAG
861    e4_assert(refresh_flag_ok());
862#endif
863
864    AW_device *device = current_device();
865
866    if (!flag.hidden && (refresh_all || update_info.refresh)) {
867#if defined(TRACE_REFRESH)
868        fprintf(stderr, "- really paint in ED4_main_manager::Show(refresh_all=%i, is_cleared=%i)\n", int(refresh_all), int(is_cleared)); fflush(stderr);
869#endif
870        const AW_screen_area& area_rect = device->get_area_size();
871
872        // if update all -> clear_background
873
874        if (update_info.clear_at_refresh && !is_cleared) {
875            device->push_clip_scale();
876            if (device->reduceClipBorders(area_rect.t, area_rect.b, area_rect.l, area_rect.r)) {
877                clear_background();
878            }
879            is_cleared = 1;
880            device->pop_clip_scale();
881        }
882
883        // loop through all rectangles between folding lines:
884
885        int x1, y1, x2, y2;
886        ED4_window& win = *current_ed4w();
887        x1 = area_rect.l;
888        for (const ED4_folding_line *flv = win.get_vertical_folding(); ; flv = flv->get_next()) {
889            if (flv) {
890                x2 = int(flv->get_pos()); // @@@ use AW_INT ?
891            }
892            else {
893                x2 = area_rect.r;
894                if (x1==x2) break; // do not draw last range, if it's only 1 pixel width
895            }
896
897            y1 = area_rect.t;
898            for (const ED4_folding_line *flh = win.get_horizontal_folding(); ; flh = flh->get_next()) {
899                if (flh) {
900                    y2 = int(flh->get_pos()); // @@@ use AW_INT ?
901                }
902                else {
903                    y2 = area_rect.b;
904                    if (y1==y2) break; // do not draw last range, if it's only 1 pixel high
905                }
906
907                device->push_clip_scale();
908                if (device->reduceClipBorders(y1, y2-1, x1, x2-1)) {
909                    ED4_manager::Show(refresh_all, is_cleared);
910                }
911                device->pop_clip_scale();
912
913                if (!flh) break; // break out after drawing lowest range
914                y1 = y2;
915            }
916            if (!flv) break; // break out after drawing rightmost range
917
918            x1 = x2;
919        }
920
921        // to avoid text clipping problems between top and middle area we redraw the top-middle-spacer :
922        {
923            device->push_clip_scale();
924            const AW_screen_area& clip_rect = device->get_cliprect();
925            device->set_top_clip_border(clip_rect.t-TERMINAL_HEIGHT);
926
927            int char_width = ED4_ROOT->font_group.get_max_width();
928            device->set_left_clip_border(clip_rect.l-char_width);
929            device->set_right_clip_border(clip_rect.r+char_width);
930
931            get_top_middle_spacer_terminal()->Show(true, false);
932            get_top_middle_line_terminal()->Show(true, false);
933            device->pop_clip_scale();
934        }
935
936        // always draw cursor
937        ED4_cursor& cursor = current_cursor();
938        if (cursor.owner_of_cursor && cursor.allowed_to_draw) {
939            if (cursor.is_partly_visible()) {
940                cursor.ShowCursor(0, ED4_C_NONE, 0);
941            }
942        }
943    }
944#ifdef TEST_REFRESH_FLAG
945    e4_assert(refresh_flag_ok());
946#endif
947}
948
949
950void ED4_root_group_manager::Show(bool refresh_all, bool is_cleared) {
951    if (update_remap()) { // @@@ dont call here ?
952#if defined(TRACE_REFRESH)
953        printf("map updated in ED4_root_group_manager::Show (bad?)\n");
954#endif
955    }
956    ED4_manager::Show(refresh_all, is_cleared);
957}
958
959void ED4_manager::Show(bool refresh_all, bool is_cleared) {
960#ifdef TEST_REFRESH_FLAG
961    e4_assert(refresh_flag_ok());
962#endif
963
964    if (!flag.hidden && (refresh_all || update_info.refresh)) {
965        if (update_info.clear_at_refresh && !is_cleared) {
966            clear_background();
967            is_cleared = 1;
968        }
969
970        AW_screen_area rect; // clipped rectangle in world coordinates
971
972        {
973            const AW_screen_area &clip_rect = current_device()->get_cliprect();      // clipped rectangle in win coordinates
974           
975            double x, y;
976            x = clip_rect.l;
977            y = clip_rect.t;
978
979            current_ed4w()->win_to_world_coords(&x, &y);
980
981            rect.l = int(x);
982            rect.t = int(y);
983
984            e4_assert(AW::nearlyEqual(current_device()->get_scale(), 1.0)); // assumed by calculation below
985            rect.r = rect.l+(clip_rect.r-clip_rect.l);
986            rect.b = rect.t+(clip_rect.b-clip_rect.t);
987        }
988
989        // binary search to find first visible child
990
991        int first_visible_child = 0; //@@@FIXME: this variable is never again set
992
993        {
994            int l = 0;
995            int h = members()-1;
996
997            while (l<h) {
998
999                while (member(l)->flag.hidden && l<h) l++;
1000                while (member(h)->flag.hidden && l<h) h--;
1001
1002                int m = (l+h)/2;
1003                int min_m = m;
1004                int max_m = m+1;
1005
1006                while (member(m)->flag.hidden) {
1007                    if (m==h) {
1008                        m = (l+h)/2-1;
1009                        while (member(m)->flag.hidden) {
1010                            if (m==l) {
1011                                // all children between l..h are flag.hidden
1012                                goto no_visible_child_found;
1013                            }
1014                            m--;
1015                        }
1016                        min_m = m;
1017                        break;
1018                    }
1019                    m++;
1020                    max_m = m;
1021                }
1022
1023                ED4_base *child = member(m);
1024                e4_assert(!child->flag.hidden);
1025
1026                AW_pos x, y;
1027                child->calc_world_coords(&x, &y);
1028
1029                if (spec.static_prop & PROP_HORIZONTAL) { // horizontal manager
1030                    e4_assert((spec.static_prop&PROP_VERTICAL)==0);   // otherwise this binary search will not work correctly
1031                    if ((x+child->extension.size[WIDTH])<=rect.l) { // left of clipping range
1032                        l = max_m;
1033                    }
1034                    else {
1035                        h = min_m;
1036                    }
1037                }
1038                else if (spec.static_prop & PROP_VERTICAL) { // vertical manager
1039                    if ((y+child->extension.size[HEIGHT])<=rect.t) { // above clipping range
1040                        l = max_m;
1041                    }
1042                    else {
1043                        h = min_m;
1044                    }
1045                }
1046                else {
1047                    e4_assert(0);
1048                }
1049            }
1050        }
1051
1052      no_visible_child_found :
1053
1054        for (ED4_index i = 0; existing_index(i); ++i) {
1055            ED4_base *child = member(i);
1056            e4_assert(child);
1057
1058            if (!child->flag.hidden && (refresh_all || child->update_info.refresh) && i>=first_visible_child) {
1059                AW_pos x, y;
1060                child->calc_world_coords(&x, &y);
1061
1062                AW_device *device = current_device();
1063
1064                if (!(((y-rect.b)>0.5) ||
1065                      ((rect.t-(y+child->extension.size[HEIGHT]-1))>0.5) ||
1066                      ((x-rect.r)>0.5) ||
1067                      ((rect.l-(x+child->extension.size[WIDTH]-1))>0.5)
1068                     ))
1069                {
1070                    // they overlap -> show it
1071                    device->push_clip_scale();
1072                    if (child->adjust_clipping_rectangle()) {
1073                        child->Show(refresh_all, is_cleared);
1074                    }
1075                    device->pop_clip_scale();
1076                }
1077            }
1078        }
1079    }
1080
1081#ifdef TEST_REFRESH_FLAG
1082    e4_assert(refresh_flag_ok());
1083#endif
1084}
1085
1086ED4_returncode ED4_manager::clear_refresh() {
1087    e4_assert(update_info.refresh);
1088
1089    for (int i=0; i<members(); i++) {
1090        ED4_base *child = member(i);
1091
1092        if (child->update_info.refresh) {
1093            if (child->is_manager()) {
1094                child->to_manager()->clear_refresh();
1095            }
1096            else {
1097                child->update_info.set_refresh(0);
1098                child->update_info.set_clear_at_refresh(0);
1099            }
1100        }
1101    }
1102
1103    update_info.set_refresh(0);
1104    update_info.set_clear_at_refresh(0);
1105
1106    return ED4_R_OK;
1107}
1108
1109void ED4_manager::update_requested_by_child() { // @@@ same as set_update -> DRY
1110    if (!update_info.update_requested) {
1111        if (parent) parent->update_requested_by_child();
1112        update_info.update_requested = 1;
1113    }
1114}
1115void ED4_manager::delete_requested_by_child() {
1116    if (!update_info.delete_requested) {
1117        if (parent) parent->delete_requested_by_child();
1118        update_info.delete_requested = 1;
1119    }
1120}
1121void ED4_terminal::delete_requested_children() {
1122    e4_assert(update_info.delete_requested);
1123    e4_assert(tflag.deleted);
1124
1125    ED4_ROOT->announce_deletion(this);
1126
1127    unlink_from_parent();
1128    delete this;
1129}
1130
1131void ED4_manager::update_requested_children() {
1132    e4_assert(update_info.update_requested);
1133
1134    for (int i=0; i<members(); i++) {
1135        ED4_base *child = member(i);
1136        if (child->update_info.update_requested) {
1137            child->update_requested_children();
1138        }
1139    }
1140
1141    update_info.update_requested = 0;
1142}
1143
1144void ED4_multi_species_manager::update_requested_children() {
1145    e4_assert(update_info.update_requested);
1146    ED4_manager::update_requested_children();
1147    update_species_counters();
1148    update_group_id();
1149
1150    ED4_base *group_base = get_parent(LEV_GROUP);
1151    if (group_base) {
1152        e4_assert(group_base->is_group_manager());
1153        e4_assert(!group_base->is_root_group_manager());
1154
1155        ED4_group_manager *group_man    = parent->to_group_manager();
1156        ED4_base          *bracket_base = group_man->get_defined_level(LEV_BRACKET);
1157
1158        if (bracket_base) bracket_base->request_refresh();
1159    }
1160}
1161
1162void ED4_manager::delete_requested_children() {
1163    e4_assert(update_info.delete_requested);
1164
1165    for (int i = members()-1; i >= 0; --i) {
1166        ED4_base *child = member(i);
1167        if (child->update_info.delete_requested) {
1168            child->delete_requested_children();
1169        }
1170    }
1171
1172    update_info.delete_requested = 0;
1173
1174    if (!members()) {
1175        ED4_ROOT->announce_deletion(this);
1176       
1177        unlink_from_parent();
1178        delete this;
1179    }
1180}
1181
1182void ED4_multi_species_manager::delete_requested_children() {
1183    e4_assert(update_info.delete_requested);
1184    invalidate_species_counters();
1185    ED4_manager::delete_requested_children();
1186}
1187
1188void ED4_terminal::Delete() {
1189    if (!tflag.deleted) {
1190        tflag.deleted                = 1;
1191        update_info.delete_requested = 1;
1192        parent->delete_requested_by_child();
1193    }
1194}
1195
1196void ED4_manager::Delete() {
1197    delete_cbs.call(this);
1198    delete_cbs.clear();
1199
1200    for (int i=0; i<members(); i++) {
1201        member(i)->Delete();
1202    }
1203}
1204
1205void ED4_manager::request_refresh(int clear_at_refresh) {
1206    // sets refresh flag of current object and its children
1207    update_info.set_refresh(1);
1208    update_info.set_clear_at_refresh(clear_at_refresh);
1209
1210    if (parent) parent->refresh_requested_by_child();
1211
1212    for (ED4_index i = 0; existing_index(i); ++i) {
1213        member(i)->request_refresh(0); // clear_at_refresh not needed for childs!
1214    }
1215}
1216
1217
1218ED4_base* ED4_manager::search_ID(const char *temp_id) {
1219    if (strcmp(temp_id, id) == 0) return this; // this object is the sought one
1220
1221    // search whole memberlist recursively for object with the given id
1222    for (ED4_index i = 0; existing_index(i); ++i) {
1223        ED4_base *object = member(i)->search_ID(temp_id);
1224        if (object) return object;
1225    }
1226
1227    return NULp; // no object found
1228}
1229
1230
1231ED4_manager::ED4_manager(const ED4_objspec& spec_, const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1232    ED4_base(spec_, temp_id, width, height, temp_parent)
1233{}
1234
1235ED4_manager::~ED4_manager() {
1236    ED4_container::clear();
1237}
1238
1239// --------------------------
1240//      ED4_main_manager
1241
1242ED4_main_manager::ED4_main_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1243    ED4_manager(main_manager_spec, temp_id, width, height, temp_parent),
1244    top_middle_line(NULp),
1245    top_middle_spacer(NULp)
1246{
1247}
1248
1249// ----------------------------
1250//      ED4_device_manager
1251
1252ED4_device_manager::ED4_device_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1253    ED4_manager(device_manager_spec, temp_id, width, height, temp_parent)
1254{
1255}
1256
1257// --------------------------
1258//      ED4_area_manager
1259
1260ED4_area_manager::ED4_area_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1261    ED4_manager(area_manager_spec, temp_id, width, height, temp_parent)
1262{
1263}
1264
1265// -----------------------------------
1266//      ED4_multi_species_manager
1267
1268ED4_multi_species_manager::ED4_multi_species_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1269    ED4_manager(multi_species_manager_spec, temp_id, width, height, temp_parent),
1270    species(-1),
1271    selected_species(-1)
1272{
1273}
1274
1275int ED4_multi_species_manager::get_no_of_species() {
1276    if (!has_valid_counters()) {
1277        update_species_counters();
1278        e4_assert(has_valid_counters());
1279    }
1280    return species;
1281}
1282
1283int ED4_multi_species_manager::get_no_of_selected_species() {
1284    if (!has_valid_counters()) {
1285        update_species_counters();
1286        e4_assert(has_valid_counters());
1287    }
1288    return selected_species;
1289}
1290
1291void ED4_multi_species_manager::invalidate_species_counters() {
1292    if (has_valid_counters()) {
1293        species          = -1;
1294        selected_species = -1;
1295
1296        ED4_base *pms = get_parent(LEV_MULTI_SPECIES);
1297        if (pms) pms->to_multi_species_manager()->invalidate_species_counters();
1298       
1299        update_requested_by_child();
1300    }
1301}
1302
1303void ED4_multi_species_manager::set_species_counters(int no_of_species, int no_of_selected) {
1304
1305#if defined(DEBUG)
1306    int sp, sel;
1307
1308    count_species(&sp, &sel);
1309    e4_assert(no_of_species==sp);
1310    e4_assert(no_of_selected==sel);
1311#endif
1312
1313    e4_assert(no_of_species>=no_of_selected);
1314
1315    if (species!=no_of_species || selected_species!=no_of_selected) {
1316        int species_diff  = no_of_species-species;
1317        int selected_diff = no_of_selected-selected_species;
1318
1319        int quickSet = 1;
1320        if (species==-1 || selected_species==-1) {
1321            quickSet = 0;
1322        }
1323
1324        species          = no_of_species;
1325        selected_species = no_of_selected;
1326
1327        ED4_manager *gm = get_parent(LEV_GROUP);
1328        if (gm) gm->search_spec_child_rek(LEV_BRACKET)->request_refresh();
1329
1330        ED4_manager *ms = get_parent(LEV_MULTI_SPECIES);
1331        if (ms) {
1332            ED4_multi_species_manager *parent_multi_species_man = ms->to_multi_species_manager();
1333
1334            if (!quickSet) parent_multi_species_man->invalidate_species_counters();
1335
1336            if (parent_multi_species_man->has_valid_counters()) {
1337                parent_multi_species_man->set_species_counters(parent_multi_species_man->species+species_diff,
1338                                                               parent_multi_species_man->selected_species+selected_diff);
1339            }
1340        }
1341    }
1342}
1343
1344#ifdef DEBUG
1345void ED4_multi_species_manager::count_species(int *speciesPtr, int *selectedPtr) const {
1346    int m;
1347    int sp  = 0;
1348    int sel = 0;
1349
1350    for (m=0; m<members(); m++) {
1351        ED4_base *child = member(m);
1352
1353        if (child->is_group_manager()) {
1354            ED4_multi_species_manager *multi_species_man = child->to_group_manager()->get_multi_species_manager();
1355
1356            if (!multi_species_man->has_valid_counters()) {
1357                int sp1, sel1;
1358
1359                multi_species_man->count_species(&sp1, &sel1);
1360                sel += sel1;
1361                sp += sp1;
1362            }
1363            else {
1364                sel += multi_species_man->get_no_of_selected_species();
1365                sp += multi_species_man->get_no_of_species();
1366            }
1367        }
1368        else if (child->is_species_manager()) {
1369            ED4_species_manager *species_man = child->to_species_manager();
1370            if (!species_man->is_consensus_manager()) {
1371                sp++;
1372                if (species_man->is_selected()) sel++;
1373            }
1374        }
1375    }
1376
1377    *speciesPtr = sp;
1378    *selectedPtr = sel;
1379}
1380#endif
1381
1382void ED4_multi_species_manager::update_species_counters() {
1383    int m;
1384    int sp  = 0;
1385    int sel = 0;
1386
1387    for (m=0; m<members(); m++) {
1388        ED4_base *child = member(m);
1389
1390        if (child->is_group_manager()) {
1391            ED4_multi_species_manager *multi_species_man = child->to_group_manager()->get_multi_species_manager();
1392
1393            if (!multi_species_man->has_valid_counters()) {
1394                multi_species_man->update_species_counters();
1395            }
1396            sel += multi_species_man->get_no_of_selected_species();
1397            sp += multi_species_man->get_no_of_species();
1398        }
1399        else if (child->is_species_manager()) {
1400            ED4_species_manager *species_man = child->to_species_manager();
1401
1402            if (!species_man->is_consensus_manager()) {
1403                sp++;
1404                if (species_man->is_selected()) sel++;
1405            }
1406        }
1407    }
1408    set_species_counters(sp, sel);
1409}
1410
1411void ED4_multi_species_manager::select_all(bool only_species) {
1412    int m;
1413    int sp  = 0;
1414    int sel = 0;
1415
1416    for (m=0; m<members(); m++) {
1417        ED4_base *child = member(m);
1418
1419        if (child->is_group_manager()) {
1420            ED4_multi_species_manager *multi_species_man = child->to_group_manager()->get_multi_species_manager();
1421            multi_species_man->select_all(only_species);
1422            sp += multi_species_man->get_no_of_species();
1423            sel += multi_species_man->get_no_of_selected_species();
1424        }
1425        else if (child->is_species_manager()) {
1426            ED4_species_manager *species_man = child->to_species_manager();
1427
1428            if (!species_man->is_consensus_manager()) {
1429                sp++;
1430                if (!species_man->is_selected()) {
1431                    if (!only_species || !species_man->is_SAI_manager()) {
1432                        ED4_species_name_terminal *species_name = species_man->search_spec_child_rek(LEV_SPECIES_NAME)->to_species_name_terminal();
1433                        ED4_ROOT->add_to_selected(species_name);
1434                    }
1435                }
1436                if (species_man->is_selected()) sel++;
1437            }
1438        }
1439    }
1440    set_species_counters(sp, sel);
1441}
1442void ED4_multi_species_manager::deselect_all_species_and_SAI() {
1443    int m;
1444    int sp = 0;
1445
1446    for (m=0; m<members(); m++) {
1447        ED4_base *child = member(m);
1448
1449        if (child->is_group_manager()) {
1450            ED4_multi_species_manager *multi_species_man = child->to_group_manager()->get_multi_species_manager();
1451            multi_species_man->deselect_all_species_and_SAI();
1452            sp += multi_species_man->get_no_of_species();
1453        }
1454        else if (child->is_species_manager()) {
1455            ED4_species_manager *species_man = child->to_species_manager();
1456
1457            if (!species_man->is_consensus_manager()) {
1458                sp++;
1459                if (species_man->is_selected()) {
1460                    ED4_species_name_terminal *species_name = species_man->search_spec_child_rek(LEV_SPECIES_NAME)->to_species_name_terminal();
1461                    ED4_ROOT->remove_from_selected(species_name);
1462                }
1463            }
1464        }
1465        else {
1466            e4_assert(!child->is_manager());
1467        }
1468    }
1469    set_species_counters(sp, 0);
1470}
1471void ED4_multi_species_manager::invert_selection_of_all_species() {
1472    int m;
1473    int sp  = 0;
1474    int sel = 0;
1475
1476    for (m=0; m<members(); m++) {
1477        ED4_base *child = member(m);
1478
1479        if (child->is_group_manager()) {
1480            ED4_multi_species_manager *multi_species_man = child->to_group_manager()->get_multi_species_manager();
1481            multi_species_man->invert_selection_of_all_species();
1482            sp += multi_species_man->get_no_of_species();
1483            sel += multi_species_man->get_no_of_selected_species();
1484        }
1485        else if (child->is_species_manager()) {
1486            ED4_species_manager *species_man = child->to_species_manager();
1487
1488            if (!species_man->is_consensus_manager()) {
1489                sp++;
1490
1491                if (!species_man->is_SAI_manager()) {
1492                    ED4_species_name_terminal *species_name = species_man->search_spec_child_rek(LEV_SPECIES_NAME)->to_species_name_terminal();
1493
1494                    if (species_man->is_selected()) ED4_ROOT->remove_from_selected(species_name);
1495                    else                            ED4_ROOT->add_to_selected(species_name);
1496                }
1497                if (species_man->is_selected()) sel++;
1498            }
1499        }
1500        else {
1501            e4_assert(!child->is_manager());
1502        }
1503    }
1504
1505    e4_assert(get_no_of_selected_species()==sel);
1506    e4_assert(get_no_of_species()==sp);
1507}
1508void ED4_multi_species_manager::marked_species_select(bool select) {
1509    int m;
1510    int sp  = 0;
1511    int sel = 0;
1512
1513    for (m=0; m<members(); m++) {
1514        ED4_base *child = member(m);
1515
1516        if (child->is_group_manager()) {
1517            ED4_multi_species_manager *multi_species_man = child->to_group_manager()->get_multi_species_manager();
1518            multi_species_man->marked_species_select(select);
1519            sp += multi_species_man->get_no_of_species();
1520            sel += multi_species_man->get_no_of_selected_species();
1521        }
1522        else if (child->is_species_manager()) {
1523            ED4_species_manager *species_man = child->to_species_manager();
1524
1525            if (!species_man->is_consensus_manager()) {
1526                sp++;
1527
1528                if (species_man->is_species_seq_manager()) {
1529                    GBDATA *gbd = species_man->get_species_pointer();
1530                    e4_assert(gbd);
1531                    int is_marked = GB_read_flag(gbd);
1532
1533                    if (is_marked) {
1534                        if (select) { // select marked
1535                            if (!species_man->is_selected()) {
1536                                ED4_species_name_terminal *species_name = species_man->search_spec_child_rek(LEV_SPECIES_NAME)->to_species_name_terminal();
1537                                ED4_ROOT->add_to_selected(species_name);
1538                            }
1539                        }
1540                        else { // de-select marked
1541                            if (species_man->is_selected()) {
1542                                ED4_species_name_terminal *species_name = species_man->search_spec_child_rek(LEV_SPECIES_NAME)->to_species_name_terminal();
1543                                ED4_ROOT->remove_from_selected(species_name);
1544                            }
1545                        }
1546                    }
1547                }
1548                if (species_man->is_selected()) sel++;
1549            }
1550        }
1551        else {
1552            e4_assert(!child->is_manager());
1553        }
1554    }
1555    set_species_counters(sp, sel);
1556}
1557void ED4_multi_species_manager::selected_species_mark(bool mark) {
1558    int m;
1559    int sp  = 0;
1560    int sel = 0;
1561
1562    for (m=0; m<members(); m++) {
1563        ED4_base *child = member(m);
1564
1565        if (child->is_group_manager()) {
1566            ED4_multi_species_manager *multi_species_man = child->to_group_manager()->get_multi_species_manager();
1567            multi_species_man->selected_species_mark(mark);
1568            sp += multi_species_man->get_no_of_species();
1569            sel += multi_species_man->get_no_of_selected_species();
1570        }
1571        else if (child->is_species_manager()) {
1572            ED4_species_manager *species_man = child->to_species_manager();
1573
1574            if (!species_man->is_consensus_manager()) {
1575                sp++;
1576                if (species_man->is_selected()) {
1577                    if (species_man->is_species_seq_manager()) {
1578                        GBDATA *gbd = species_man->get_species_pointer();
1579                        e4_assert(gbd);
1580
1581                        GB_write_flag(gbd, mark ? 1 : 0);
1582                    }
1583                    sel++;
1584                }
1585            }
1586        }
1587        else {
1588            e4_assert(!child->is_manager());
1589        }
1590    }
1591    set_species_counters(sp, sel);
1592}
1593
1594ED4_species_manager *ED4_multi_species_manager::get_consensus_manager() const {
1595    ED4_species_manager *consensus_manager = NULp;
1596
1597    for (int i=0; i<members(); i++) {
1598        ED4_base *child = member(i);
1599        if (child->is_consensus_manager()) {
1600            consensus_manager = child->to_species_manager();
1601            break;
1602        }
1603    }
1604
1605    return consensus_manager;
1606}
1607
1608// -----------------------------
1609//      ED4_species_manager
1610
1611ED4_species_manager::ED4_species_manager(ED4_species_type type_, const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1612    ED4_manager(species_manager_spec, temp_id, width, height, temp_parent),
1613    type(type_),
1614    selected(false)
1615{
1616    e4_assert(type != ED4_SP_NONE);
1617    if (type == ED4_SP_SAI) ED4_ROOT->loadable_SAIs_may_have_changed();
1618}
1619
1620ED4_species_manager::~ED4_species_manager() {
1621    if (type == ED4_SP_SAI) ED4_ROOT->loadable_SAIs_may_have_changed();
1622}
1623
1624void ED4_root::remove_all_callbacks() {
1625    for (ED4_window *ew = first_window; ew; ew = ew->next) {
1626        ew->cursor.prepare_shutdown(); // removes any callbacks
1627    }
1628    ED4_viewDifferences_disable();
1629}
1630
1631// ------------------------
1632//      group managers
1633
1634ED4_abstract_group_manager::ED4_abstract_group_manager(const ED4_objspec& spec_, const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1635    ED4_manager(spec_, temp_id, width, height, temp_parent),
1636    my_table(0)
1637{
1638}
1639
1640ED4_group_manager::ED4_group_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent) :
1641    ED4_abstract_group_manager(group_manager_spec, temp_id, width, height, temp_parent)
1642{
1643}
1644
1645// -------------------
1646//      ED4_remap
1647
1648ED4_remap::ED4_remap() {
1649    mode               = ED4_RM_NONE;
1650    show_above_percent = 0;
1651
1652    sequence_table_len = 1;
1653    screen_table_len   = 1;
1654
1655    screen_to_sequence_tab = new int[1];        screen_to_sequence_tab[0] = 0;
1656    sequence_to_screen_tab = new int[1];        sequence_to_screen_tab[0] = 0;
1657
1658    sequence_len               = 0;
1659    MAXSEQUENCECHARACTERLENGTH = screen_len = 0;
1660
1661    changed       = 0;
1662    update_needed = 1;
1663
1664}
1665ED4_remap::~ED4_remap() {
1666    delete [] screen_to_sequence_tab;
1667    delete [] sequence_to_screen_tab;
1668}
1669int ED4_remap::screen_to_sequence(int screen_pos) const {
1670    if (size_t(screen_pos) == screen_len) {
1671        return screen_to_sequence_tab[screen_len-1];
1672    }
1673    e4_assert(screen_pos>=0 && size_t(screen_pos)<screen_len);
1674    return screen_to_sequence_tab[screen_pos];
1675}
1676int ED4_remap::clipped_sequence_to_screen_PLAIN(int sequence_pos) const {
1677    if (sequence_pos<0) {
1678        sequence_pos = 0;
1679    }
1680    else if (size_t(sequence_pos)>sequence_len) {
1681        sequence_pos = sequence_len;
1682    }
1683    return sequence_to_screen_PLAIN(sequence_pos);
1684}
1685int ED4_remap::sequence_to_screen(int sequence_pos) const {
1686    int scr_pos = sequence_to_screen_PLAIN(sequence_pos);
1687    if (scr_pos<0) scr_pos = -scr_pos;
1688    return scr_pos;
1689}
1690
1691void ED4_remap::adjacent_screen_positions(int seq_pos, int& screen_pos_left, int& screen_pos_right) {
1692    e4_assert(!is_shown(seq_pos)); // otherwise use sequence_to_screen()
1693
1694    screen_pos_left = -1;
1695    for (int p = seq_pos-1; screen_pos_left<0 && p>=0; --p) {
1696        screen_pos_left = sequence_to_screen_PLAIN(p);
1697    }
1698    screen_pos_right = -1;
1699    for (int p = seq_pos+1; screen_pos_right<0 && size_t(p)<=sequence_len; ++p) {
1700        screen_pos_right = sequence_to_screen_PLAIN(p);
1701    }
1702}
1703
1704inline void ED4_remap::set_sequence_to_screen(int pos, int newVal) {
1705    e4_assert(pos>=0 && size_t(pos)<sequence_table_len);
1706    if (sequence_to_screen_tab[pos]!=newVal) {
1707        sequence_to_screen_tab[pos] = newVal;
1708        changed = 1;
1709    }
1710}
1711void ED4_remap::mark_compile_needed_force() {
1712    if (!update_needed) {
1713        update_needed = 1;
1714        if (ED4_ROOT && ED4_ROOT->root_group_man) {                     // test if root_group_man already exists
1715            ED4_ROOT->root_group_man->resize_requested_by_child();      // remapping is recompiled while re-displaying the root_group_manager
1716        }
1717    }
1718}
1719void ED4_remap::mark_compile_needed() {
1720    if (mode!=ED4_RM_NONE) mark_compile_needed_force();
1721}
1722
1723GB_ERROR ED4_remap::compile(ED4_root_group_manager *gm) {
1724    e4_assert(update_needed);
1725
1726    const BaseFrequencies& table = gm->table();
1727    size_t i, j;
1728
1729    changed = 0; // is changed by set_sequence_to_screen
1730    update_needed = 0;
1731
1732    sequence_len = table.size(); // take size of any table
1733    if ((sequence_len+1) > sequence_table_len) {
1734        delete [] sequence_to_screen_tab;
1735        sequence_to_screen_tab = new int[sequence_table_len = sequence_len+1];
1736        memset(sequence_to_screen_tab, 0, sequence_table_len*sizeof(int));
1737        changed = 1;
1738    }
1739
1740    int above_percent;
1741    switch (gm->remap()->get_mode()) {
1742        default: e4_assert(0); FALLTHROUGH; // in NDEBUG
1743        case ED4_RM_NONE: {
1744        dont_map :
1745            for (i=0; i<sequence_table_len; i++) {
1746                set_sequence_to_screen(i, i);
1747            }
1748            screen_len = sequence_len;
1749            break;
1750        }
1751        case ED4_RM_SHOW_ABOVE: {
1752            above_percent = show_above_percent;
1753            goto calc_percent;
1754        }
1755        case ED4_RM_MAX_ALIGN:
1756        case ED4_RM_MAX_EDIT: {
1757            above_percent = 0;
1758        calc_percent :
1759            for (i=0, j=0; i<(sequence_table_len-1); i++) {
1760                int bases;
1761                int gaps;
1762
1763                table.bases_and_gaps_at(i, &bases, &gaps);
1764
1765                if (bases==0 && gaps==0) {  // special case (should occur only after inserting columns)
1766                    set_sequence_to_screen(i, -j); // hide
1767                }
1768                else {
1769                    int percent = (int)((bases*100L)/table.added_sequences());
1770
1771                    e4_assert(percent==((bases*100)/(bases+gaps)));
1772
1773                    if (bases && percent>=above_percent) {
1774                        set_sequence_to_screen(i, j++);
1775                    }
1776                    else {
1777                        set_sequence_to_screen(i, -j);
1778                    }
1779                }
1780            }
1781            for (; i<sequence_table_len; i++) { // fill rest of table
1782                set_sequence_to_screen(i, j++);
1783            }
1784            screen_len = j;
1785            break;
1786        }
1787        case ED4_RM_DYNAMIC_GAPS: {
1788            for (i=0, j=0; i<(sequence_table_len-1); i++) {
1789                int bases;
1790
1791                table.bases_and_gaps_at(i, &bases, NULp);
1792                if (bases) {
1793                    set_sequence_to_screen(i, j++);
1794                }
1795                else {
1796                    size_t k = i+1;
1797
1798                    while (k<(sequence_table_len-1)) {
1799                        int bases2;
1800
1801                        table.bases_and_gaps_at(k, &bases2, NULp);
1802                        if (bases2) {
1803                            break;
1804                        }
1805                        k++;
1806                    }
1807
1808                    int gaps = k-i;
1809                    int shown_gapsize;
1810
1811                    if (gaps<100) {
1812                        shown_gapsize = gaps/10 + 1;
1813                    }
1814                    else if (gaps<1000) {
1815                        shown_gapsize = gaps/100 + 10;
1816                    }
1817                    else {
1818                        shown_gapsize = gaps/1000 + 19;
1819                    }
1820
1821                    for (; i<k && shown_gapsize; i++, shown_gapsize--) {
1822                        set_sequence_to_screen(i, j++);
1823                    }
1824                    for (; i<k; i++) {
1825                        set_sequence_to_screen(i, -j);
1826                    }
1827                    i--;
1828                }
1829            }
1830            for (; i<sequence_table_len; i++) {
1831                set_sequence_to_screen(i, j++); // fill rest of table
1832            }
1833            screen_len = j;
1834            break;
1835        }
1836    }
1837
1838    if (sequence_table_len) {
1839        if (!screen_len && sequence_len) {
1840            goto dont_map;
1841        }
1842        if ((screen_len+1) > screen_table_len) {
1843            delete [] screen_to_sequence_tab;
1844            screen_to_sequence_tab = new int[screen_table_len = screen_len+1];
1845        }
1846        memset(screen_to_sequence_tab, 0, sizeof(int)*screen_table_len);
1847        for (i=0; i<sequence_table_len; i++) {
1848            int screen_pos = sequence_to_screen_tab[i];
1849            if (screen_pos>=0) {
1850                screen_to_sequence_tab[screen_pos] = i;
1851            }
1852        }
1853    }
1854
1855    if (sequence_len>1) {
1856        MAXSEQUENCECHARACTERLENGTH = sequence_len;
1857    }
1858
1859    return NULp;
1860}
1861
1862// --------------------------------
1863//      ED4_root_group_manager
1864
1865ED4_root_group_manager::ED4_root_group_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1866    : ED4_abstract_group_manager(root_group_manager_spec, temp_id, width, height, temp_parent),
1867      my_remap()
1868{
1869    AW_root *awr = ED4_ROOT->aw_root;
1870    my_remap.set_mode((ED4_remap_mode)awr->awar(ED4_AWAR_COMPRESS_SEQUENCE_TYPE)->read_int(),
1871                      awr->awar(ED4_AWAR_COMPRESS_SEQUENCE_PERCENT)->read_int());
1872    my_remap.mark_compile_needed_force();
1873}
1874
1875bool ED4_root_group_manager::update_remap() {
1876    bool remapped = false;
1877
1878    if (my_remap.compile_needed()) {
1879        my_remap.compile(this);
1880        if (my_remap.was_changed()) remapped = true;
1881    }
1882
1883    return remapped;
1884}
1885
1886// -----------------------------------
1887//      ED4_multi_species_manager
1888
1889ED4_multi_sequence_manager::ED4_multi_sequence_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1890    : ED4_manager(multi_sequence_manager_spec, temp_id, width, height, temp_parent)
1891{}
1892
1893ED4_sequence_manager::ED4_sequence_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1894    : ED4_manager(sequence_manager_spec, temp_id, width, height, temp_parent)
1895{}
1896
1897ED4_multi_name_manager::ED4_multi_name_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1898    : ED4_manager(multi_name_manager_spec, temp_id, width, height, temp_parent)
1899{}
1900
1901ED4_name_manager::ED4_name_manager(const char *temp_id, AW_pos width, AW_pos height, ED4_manager *temp_parent)
1902    : ED4_manager(name_manager_spec, temp_id, width, height, temp_parent)
1903{}
1904
1905
Note: See TracBrowser for help on using the repository browser.