source: branches/profile/EDIT4/ED4_manager.cxx

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