root/trunk/EDIT4/ED4_members.cxx

Revision 8630, 16.7 KB (checked in by westram, 5 weeks ago)

merge from e4fix [8430] [8431] [8432] [8433] [8434] [8435] [8436] [8437] [8438] [8440] [8441] [8442]

  • fixed display concerns
    • wrong mark boxes for unmarked species when (slowly) scrolling vertically
    • tiny gaps when moving cursor leftwards (best visible if species is selected)
    • do not draw all spacer terminals
    • rewrote ED4_bracket_terminal::draw (increased bracket-width by 1 pixel)
  • marked_species_select and selected_species_mark produced wrong counters since [8625]. fixed
  • signature of AW_device::clear_part now same as box_impl
  • Rectangle::distinct_from() no longer counts adjacent rectangles as distinct
  • AW_screen_area_conversion_mode
    • removed FAULTY_OLD_CONVERSION
    • added UPPER_LEFT_OUTLINE
  • added functions using namespace-AW-Positions
    • coordinate transformation
    • ED4_base::get_screen_area
  • no need for virtual adjust_clipping_rectangle()
    • both methods (ED4_base and ED4_terminal) were identical
  • get_screen_area -> get_win_area
    • decrement size by 1
    • use in ED4_bracket_terminal::draw and ED4_base::adjust_clipping_rectangle (eliminating confusing -1 offsets at both places)
  • added get_multi_species_manager() to ED4_area_manager and ED4_group_manager
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : ED4_members.cxx                                   //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "ed4_class.hxx"
12#include <aw_msg.hxx>
13#include <aw_question.hxx>
14#include <arbdb.h>
15
16ED4_returncode ED4_members::search_target_species(ED4_extension *location,   ED4_properties prop,  ED4_base **found_member, ED4_level return_level)
17{
18    // who's extension falls within the given
19    // location thereby considering orientation given by
20    // prop (only pos[] is relevant) list has to be
21    // ordered in either x- or y- direction, ( binary
22    // search algorithm later ) returns index of found member,
23    // -1 if list is empty or no_of_members if search reached end of list
24    ED4_index   current_index = 0,
25        old_index,
26        rel_pos,                                                                // relative position, i.e. on screen, to check
27        rel_size;
28    AW_pos              abs_pos_x = 0,
29        abs_pos_y = 0,
30        abs_pos;                                                                // relative size of object, to check
31    ED4_base    *current_member;
32
33
34    current_member = member(0); // search list
35    if (! current_member) { // there's no list
36        return (ED4_R_IMPOSSIBLE);
37    }
38
39    // case for the device_manager:
40    if (current_member->is_area_manager()) {
41        current_member->to_area_manager()
42            ->get_multi_species_manager()
43            ->children->search_target_species(location, prop, found_member, return_level); // there are always the three areas !!!
44
45        if (*found_member) {
46            return ED4_R_OK;
47        }
48    }
49
50    current_member->parent->calc_world_coords(& abs_pos_x, & abs_pos_y);
51
52    if (prop & ED4_P_HORIZONTAL)                                                                // set extension-indexes rel_pos and rel_size according to properties
53    {
54        rel_pos = Y_POS;
55        rel_size = HEIGHT;
56        abs_pos = abs_pos_y;
57    }
58    else                                                                                        // i.e. prop & ED4_P_VERTICAL
59    {
60        rel_pos = X_POS;
61        rel_size = WIDTH;
62        abs_pos = abs_pos_x;
63    }
64
65
66    while (current_member &&
67             (location->position[rel_pos] >= (current_member->extension.position[rel_pos] + abs_pos)) &&        // just as long as possibility exists, to find the object
68             (location->position[rel_pos] >= abs_pos && location->position[rel_pos] <= current_member->parent->extension.size[rel_size] + abs_pos))
69    {
70        e4_assert(!current_member->is_root_group_manager());
71        if (current_member->is_group_manager() &&
72            !current_member->flag.hidden &&
73            !current_member->is_consensus_manager()) { // search_clicked_member for multi_species_manager in groups
74            current_member->to_group_manager()->children->search_target_species(location, prop, found_member, return_level);
75        }
76        else if (!(current_member->flag.hidden)   &&
77                  (location->position[rel_pos] <= (current_member->extension.position[rel_pos] +
78                                                   abs_pos + current_member->extension.size[rel_size])))                        // found a suitable member
79        {
80            if (return_level & ED4_L_MULTI_SPECIES) { // search for drag target
81                if (current_member->is_multi_species_manager()) {
82                    *found_member = current_member;                                     // we have to give back the multi_species_manager for
83                    // insertion
84                    current_member->to_multi_species_manager()->children->search_target_species(location, prop, found_member, return_level);
85                }
86                else if ((current_member->is_spacer_terminal()) && (current_index + 1 == no_of_members)) { // if we have found the last spacer
87                    *found_member = current_member->get_parent(ED4_L_MULTI_SPECIES);                            // in a group we can move the
88                    if ((*found_member) && !((*found_member)->parent->is_area_manager())) {
89                        *found_member = (*found_member)->parent->get_parent(ED4_L_MULTI_SPECIES);
90                    }
91                }
92                else if (!(current_member->is_terminal()) || (current_member->is_spacer_terminal())) { // object behind the group
93                    *found_member = current_member->get_parent(ED4_L_MULTI_SPECIES);
94                }
95
96            }
97            else                                                                        // search for drag target line
98            {
99                if (current_member->is_multi_species_manager()) {
100                    current_member->to_multi_species_manager()->children->search_target_species(location, prop, found_member, return_level);
101                }
102                else if ((current_member->is_spacer_terminal()) && (current_index + 1 == no_of_members)) { // if we have found the last spacer
103                    *found_member = current_member->get_parent(ED4_L_MULTI_SPECIES);   // in a group we can move the
104                    if ((*found_member) && !((*found_member)->parent->is_area_manager())) {
105                        *found_member = (*found_member)->parent;
106                    }
107                }
108                else if ((current_member->is_species_manager()) ||
109                         ((current_member->is_spacer_terminal()) && current_member->parent->is_multi_species_manager())) { // we are a species manager
110                    *found_member = current_member;
111                }
112            }
113
114        }
115
116        current_index++;                                                                // no hit => search on
117        current_member = member(current_index);
118
119        if (current_member) { // handle folding groups
120            old_index = current_index;
121            while (current_member && current_member->flag.hidden && current_index!=no_of_members) {
122                current_index ++;
123                current_member = member(current_index);
124            }
125
126            if (current_index != old_index) {
127                if (current_member &&
128                         !((location->position[rel_pos] >= (current_member->extension.position[rel_pos] + abs_pos)) &&
129                           (location->position[rel_pos] >= abs_pos && location->position[rel_pos] <= current_member->parent->extension.size[rel_size] + abs_pos)) &&
130                         (current_member->is_spacer_terminal()) && (current_index + 1 == no_of_members))
131                {
132                    if (return_level & ED4_L_MULTI_SPECIES)
133                        *found_member = current_member->get_parent(ED4_L_MULTI_SPECIES)->parent->get_parent(ED4_L_MULTI_SPECIES);
134                    else
135                        *found_member = current_member->get_parent(ED4_L_MULTI_SPECIES)->parent;
136                }
137            }
138        }
139
140        if (current_member) {
141            if (current_member->is_area_manager()) {
142                current_member->to_area_manager()
143                    ->get_multi_species_manager()
144                    ->children->search_target_species(location, prop, found_member, return_level);      // there are always the three areas !!!
145
146                if (*found_member) {
147                    return ED4_R_OK;
148                }
149            }
150        }
151    }
152
153    return ED4_R_OK;
154}
155
156ED4_returncode ED4_members::insert_member(ED4_base *new_member) {
157    // inserts a new member into current owners's member array and
158    // asks to adjust owner's bounding box
159
160    ED4_properties prop = owner()->spec.static_prop; // properties of parent object
161
162    ED4_index index;
163    if ((index = search_member(&(new_member->extension), prop)) < 0) {          // search list for a suitable position
164        index = 0;                                                              // list was empty
165    }
166    else if (index != no_of_members) {                                          // we want to insert new member just behind found position
167        index++;                                                                // if index == no_of_members we reached the end of the list
168    }                                                                           // and index already has the right value
169
170    if (index > 0) { // ensure to insert before group_end_spacer
171        if (member(index-1)) {
172            if (member(index-1)->is_spacer_terminal() && !owner()->is_device_manager()) { // only in group_manager
173                if (index > 1) {
174                    index --;
175                }
176            }
177        }
178    }
179
180    if (shift_list(index, 1) != ED4_R_OK) {    // insert new_member at index after shifting to the right
181        return (ED4_R_WARNING);
182    }
183
184    memberList[index] = new_member; // insert new member in list in just allocated memory
185    no_of_members ++;
186    new_member->index = index;
187
188    owner()->request_resize(); // tell owner about resize
189
190    return (ED4_R_OK);
191}
192
193ED4_returncode ED4_members::append_member(ED4_base *new_member) {
194    ED4_index index = no_of_members;
195
196    e4_assert(owner()->spec.allowed_to_contain(new_member->spec.level));
197 
198    if (index>=size_of_list) { // ensure free element
199        ED4_index new_size_of_list = (size_of_list*3)/2;        // resize to 1.5*size_of_list
200        ED4_base **new_member_list = (ED4_base**)GB_calloc(new_size_of_list, sizeof(*new_member_list));
201        if (!new_member_list) {
202            GB_memerr();
203            return ED4_R_IMPOSSIBLE;
204        }
205        memcpy(new_member_list, memberList, size_of_list*sizeof(*new_member_list));
206
207        freeset(memberList, new_member_list);
208        size_of_list = new_size_of_list;
209    }
210
211    if (index>0) { // ensure to insert before group_end_spacer
212        if (member(index-1)) {
213            if (member(index-1)->is_spacer_terminal() && !owner()->is_device_manager()) {
214                if (index>1) {
215                    index--;
216                }
217            }
218        }
219    }
220
221    if (shift_list(index, 1)!=ED4_R_OK) { // shift member if necessary
222        return ED4_R_WARNING;
223    }
224
225    memberList[index] = new_member;
226    no_of_members++;
227    new_member->index = index;
228
229    owner()->spec.announce_added(new_member->spec.level);
230    owner()->request_resize();
231
232    return ED4_R_OK;
233}
234
235ED4_returncode ED4_members::remove_member(ED4_base *member_to_del)
236{
237    if (!member_to_del || (no_of_members <= 0)) {
238        return (ED4_R_IMPOSSIBLE);
239    }
240
241    ED4_index index = member_to_del->index;
242
243    if (shift_list((index + 1), -1) != ED4_R_OK) {     // shift member list to left, starting at index+1
244        return (ED4_R_WARNING);
245    }
246
247    member_to_del->parent = 0; // avoid referencing wrong parent
248
249    no_of_members--;
250    e4_assert(members_ok());
251
252    owner()->request_resize();
253
254    return (ED4_R_OK);
255}
256
257ED4_returncode  ED4_members::shift_list(ED4_index start_index, int length)              // shifts member_list of current object by |length| positions starting with start_index,
258{                                                                                       // if length is positive shift is to the right, allocating new memory if necessary
259    // if length is negative shift is to the left (up to position 0) without freeing memory
260    ED4_index   i = 0;
261    ED4_base    **tmp_ptr;
262    unsigned int        new_alloc_size = 0;
263
264    if (length>0) { // shift list to the right
265        if ((no_of_members + length) >= size_of_list) {   // member_list is full => allocate more memory
266            new_alloc_size = (unsigned int) ((size_of_list + length) * 1.3); // calculate new size of member_list for realloc()
267
268            tmp_ptr = memberList;
269            tmp_ptr = (ED4_base **) realloc((char *) memberList, (new_alloc_size * sizeof(ED4_base *))); // try to realloc memory
270
271            if (! tmp_ptr) { // realloc() failed => try malloc() and copy member_list
272                aw_message("ED4_members::shift_list: realloc problem!");
273                tmp_ptr = (ED4_base **) malloc((new_alloc_size * sizeof(ED4_base *)));
274
275                if (! tmp_ptr)                                                                  // malloc has failed, too
276                    return (ED4_R_DESASTER);
277                else
278                    tmp_ptr = (ED4_base **) memcpy((char *) tmp_ptr,                    // malloc was successfull, now copy memory
279                                                    (char *) memberList,
280                                                    (new_alloc_size * sizeof(ED4_base *)));
281            }
282            memberList = tmp_ptr;
283            size_of_list = new_alloc_size;
284            for (i = no_of_members; i < size_of_list; i++)                              // clear free entries at the end of the list
285                memberList[i] = NULL;
286        }
287
288        for (i = (no_of_members + length); i > start_index; i--)                                // start shifting to the right
289        {
290            memberList[i] = memberList[i - length];
291            if (memberList[i] != NULL)
292                (memberList[i])->index = i;
293        }
294    }
295    else if (length<0)                                                                                  // shift list to the left, thereby not freeing any memory !
296    {
297        if ((start_index + length) < 0)
298        {
299            aw_message("ED4_members::shift_list: shift is too far to the left!");
300            return (ED4_R_WARNING);
301        }
302
303        for (i = (start_index + length); i <= (no_of_members + length); i++)                    // start shifting left
304        {
305            memberList[i] = memberList[i - length];                                     // length is negative
306            if (memberList[i] != NULL)
307                (memberList[i])->index = i;
308        }
309    }
310
311    return (ED4_R_OK);
312}
313
314
315ED4_returncode ED4_members::move_member(ED4_index old_pos, ED4_index new_pos) {
316    if (old_pos>=0 && old_pos<no_of_members && new_pos>=0 && new_pos<no_of_members) {
317        if (new_pos!=old_pos) {
318            ED4_base *moved_member = memberList[old_pos];
319
320            shift_list(old_pos+1, -1);
321            shift_list(new_pos, 1);
322
323            memberList[new_pos] = moved_member;
324            moved_member->index = new_pos;
325
326            e4_assert(members_ok());
327        }
328        return ED4_R_OK;
329    }
330
331    return ED4_R_IMPOSSIBLE;
332}
333
334ED4_index ED4_members::search_member(ED4_extension *location, ED4_properties prop)
335// searches member_list of current object for a member who's extension falls within the given location
336// thereby considering orientation given by prop (only pos[] is relevant)
337// list has to be ordered in either x- or y- direction, ( binary search algorithm later )
338// returns index of found member, -1 if list is empty or no_of_members if search reached end of list
339{
340    ED4_index   current_index = 0,
341        rel_pos,
342        rel_size;
343
344    ED4_base *current_member;
345
346    if (prop & ED4_P_HORIZONTAL) {   // set extension-indexes rel_pos and rel_size according to properties
347        rel_pos = Y_POS; rel_size = HEIGHT;
348    }
349    else { // i.e. prop & ED4_P_VERTICAL
350        rel_pos = X_POS; rel_size = WIDTH;
351    }
352
353    current_member = memberList[0]; // search list
354    if (! current_member) { // there's no list
355        return (-1);
356    }
357
358    current_index = 0;
359    while (current_member) { // just as long as possibility exists, to find the object
360        if (location->position[rel_pos] <= (current_member->extension.position[rel_pos] + current_member->extension.size[rel_size])) {  // found a suitable member
361            return (current_index);
362        }
363        current_index++; // no hit => search on
364        current_member = memberList[current_index];
365    }
366
367    return (no_of_members);                                                           // reached this position => no hit, return no_of_members
368}
369
370#ifdef ASSERTION_USED
371int ED4_members::members_ok() const {
372    int m;
373    int error = 0;
374
375    for (m=0; m<no_of_members; m++) {
376        ED4_base *base = memberList[m];
377
378        if (base->index!=m) {
379            printf("Member %i has illegal index %li\n", m, base->index);
380            error = 1;
381        }
382    }
383
384    return !error;
385}
386#endif // ASSERTION_USED
387
388ED4_members::ED4_members(ED4_manager *the_owner)
389{
390    my_owner = the_owner;
391    memberList = (ED4_base **) calloc(1, sizeof(ED4_base*));
392
393    if (memberList == NULL) {
394        aw_popup_exit("ED4_member::ED4_member: memory problem!");
395    }
396
397    memberList[0] = NULL;
398    no_of_members = 0;
399    size_of_list = 1;
400}
401
402
403ED4_members::~ED4_members() {
404    free(memberList);
405}
Note: See TracBrowser for help on using the browser.