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