source: tags/arb_5.2/EDIT4/ED4_manager.cxx

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