1 | // =============================================================== // |
---|
2 | // // |
---|
3 | // File : ED4_window.cxx // |
---|
4 | // Purpose : // |
---|
5 | // // |
---|
6 | // Institute of Microbiology (Technical University Munich) // |
---|
7 | // http://www.arb-home.de/ // |
---|
8 | // // |
---|
9 | // =============================================================== // |
---|
10 | |
---|
11 | #include <arbdb.h> |
---|
12 | #include <ed4_extern.hxx> |
---|
13 | #include "ed4_class.hxx" |
---|
14 | #include "ed4_tools.hxx" |
---|
15 | #include <aw_awar.hxx> |
---|
16 | #include <aw_root.hxx> |
---|
17 | |
---|
18 | int ED4_window::no_of_windows = 0; // static variable has to be initialized only once |
---|
19 | |
---|
20 | void ED4_window::reset_all_for_new_config() { |
---|
21 | scrolled_rect.reset(*this); |
---|
22 | e4_assert(ED4_foldable::is_reset()); |
---|
23 | |
---|
24 | slider_pos_horizontal = 0; |
---|
25 | slider_pos_vertical = 0; |
---|
26 | |
---|
27 | coords.top_area_x = 0; |
---|
28 | coords.top_area_y = 0; |
---|
29 | coords.top_area_height = 0; |
---|
30 | |
---|
31 | coords.middle_area_x = 0; |
---|
32 | coords.middle_area_y = 0; |
---|
33 | |
---|
34 | coords.window_width = 0; |
---|
35 | coords.window_height = 0; |
---|
36 | |
---|
37 | coords.window_upper_clip_point = 0; |
---|
38 | coords.window_lower_clip_point = 0; |
---|
39 | coords.window_left_clip_point = 0; |
---|
40 | coords.window_right_clip_point = 0; |
---|
41 | |
---|
42 | ED4_ROOT->aw_root->awar(awar_path_for_cursor)->write_int(0); |
---|
43 | ED4_ROOT->aw_root->awar(awar_path_for_Ecoli)->write_int(0); |
---|
44 | ED4_ROOT->aw_root->awar(awar_path_for_basePos)->write_int(0); |
---|
45 | ED4_ROOT->aw_root->awar(awar_path_for_IUPAC)->write_string(ED4_IUPAC_EMPTY); |
---|
46 | ED4_ROOT->aw_root->awar(awar_path_for_helixNr)->write_string(""); |
---|
47 | |
---|
48 | if (next) next->reset_all_for_new_config(); |
---|
49 | } |
---|
50 | |
---|
51 | |
---|
52 | void ED4_window::update_window_coords() { |
---|
53 | AW_pos x, y; |
---|
54 | AW_screen_area area_size; |
---|
55 | |
---|
56 | ED4_ROOT->top_area_man->calc_world_coords(&x, &y); |
---|
57 | |
---|
58 | coords.top_area_x = (long) x; |
---|
59 | coords.top_area_y = (long) y; |
---|
60 | coords.top_area_height = (long) ED4_ROOT->top_area_man->extension.size[HEIGHT]; |
---|
61 | |
---|
62 | ED4_ROOT->middle_area_man->calc_world_coords(&x, &y); |
---|
63 | |
---|
64 | coords.middle_area_x = (long) x; |
---|
65 | coords.middle_area_y = (long) y; |
---|
66 | |
---|
67 | aww->_get_area_size (AW_MIDDLE_AREA, &area_size); |
---|
68 | |
---|
69 | coords.window_width = area_size.r; |
---|
70 | coords.window_height = area_size.b; |
---|
71 | |
---|
72 | // world coordinates |
---|
73 | coords.window_upper_clip_point = coords.middle_area_y + aww->slider_pos_vertical; // coordinate of upper clipping point of middle area |
---|
74 | coords.window_lower_clip_point = coords.window_upper_clip_point + coords.window_height - coords.middle_area_y; |
---|
75 | |
---|
76 | if (ED4_ROOT->scroll_links.link_for_hor_slider) { |
---|
77 | ED4_ROOT->scroll_links.link_for_hor_slider->calc_world_coords(&x, &y); |
---|
78 | coords.window_left_clip_point = (long) x + aww->slider_pos_horizontal; |
---|
79 | coords.window_right_clip_point = coords.window_left_clip_point + coords.window_width - (long) x; |
---|
80 | } |
---|
81 | |
---|
82 | #if defined(DEBUG) && 0 |
---|
83 | printf("left %d right %d (xdiff=%d) upper %d lower %d (ydiff=%d) width=%d height=%d\n", |
---|
84 | coords.window_left_clip_point, |
---|
85 | coords.window_right_clip_point, |
---|
86 | coords.window_right_clip_point-coords.window_left_clip_point, |
---|
87 | coords.window_upper_clip_point, |
---|
88 | coords.window_lower_clip_point, |
---|
89 | coords.window_lower_clip_point-coords.window_upper_clip_point, |
---|
90 | coords.window_width, |
---|
91 | coords.window_height); |
---|
92 | #endif |
---|
93 | } |
---|
94 | |
---|
95 | |
---|
96 | |
---|
97 | ED4_folding_line* ED4_foldable::insert_folding_line(AW_pos world_pos, AW_pos dimension, ED4_properties prop) { |
---|
98 | ED4_folding_line *fl = NULp; |
---|
99 | |
---|
100 | if (prop == PROP_VERTICAL || prop == PROP_HORIZONTAL) { |
---|
101 | fl = new ED4_folding_line(world_pos, dimension); |
---|
102 | fl->insertAs(prop == PROP_VERTICAL ? vertical_fl : horizontal_fl); |
---|
103 | } |
---|
104 | return fl; |
---|
105 | } |
---|
106 | |
---|
107 | ED4_window *ED4_window::get_matching_ed4w(AW_window *aw) { |
---|
108 | e4_assert(aw); |
---|
109 | |
---|
110 | ED4_window *window = ED4_ROOT->first_window; |
---|
111 | while (window && window->aww != aw) { |
---|
112 | window = window->next; |
---|
113 | } |
---|
114 | |
---|
115 | e4_assert(window); // aw is not an edit-window |
---|
116 | return window; |
---|
117 | } |
---|
118 | |
---|
119 | |
---|
120 | |
---|
121 | void ED4_foldable::delete_folding_line(ED4_folding_line *fl, ED4_properties prop) { |
---|
122 | if (prop == PROP_HORIZONTAL) { |
---|
123 | horizontal_fl = horizontal_fl->delete_member(fl); |
---|
124 | } |
---|
125 | else { |
---|
126 | e4_assert(prop == PROP_VERTICAL); |
---|
127 | vertical_fl = vertical_fl->delete_member(fl); |
---|
128 | } |
---|
129 | } |
---|
130 | |
---|
131 | AW::Rectangle ED4_scrolled_rectangle::get_world_rect() const { |
---|
132 | e4_assert(is_linked()); |
---|
133 | |
---|
134 | AW_pos x, y, dummy; |
---|
135 | x_link->calc_world_coords(&x, &dummy); |
---|
136 | y_link->calc_world_coords(&dummy, &y); |
---|
137 | |
---|
138 | AW::Vector size(width_link->extension.size[WIDTH], |
---|
139 | height_link->extension.size[HEIGHT]); |
---|
140 | |
---|
141 | return AW::Rectangle(AW::Position(x, y), size); |
---|
142 | } |
---|
143 | |
---|
144 | void ED4_window::update_scrolled_rectangle() { |
---|
145 | if (scrolled_rect.exists()) { |
---|
146 | e4_assert(scrolled_rect.is_linked()); |
---|
147 | |
---|
148 | AW::Rectangle srect = scrolled_rect.get_world_rect(); |
---|
149 | scrolled_rect.set_rect_and_update_folding_line_positions(srect); |
---|
150 | |
---|
151 | // if slider positions stored in AW_window and ED4_window differ, |
---|
152 | // we correct folding line dimensions: |
---|
153 | |
---|
154 | { |
---|
155 | // update dimension and window position of folding lines at the borders of scrolled rectangle |
---|
156 | int dx = aww->slider_pos_horizontal - slider_pos_horizontal; |
---|
157 | int dy = aww->slider_pos_vertical - slider_pos_vertical; |
---|
158 | |
---|
159 | scrolled_rect.add_to_top_left_dimension(dx, dy); |
---|
160 | } |
---|
161 | |
---|
162 | AW_world rect = { 0, srect.height(), 0, srect.width() }; |
---|
163 | aww->tell_scrolled_picture_size(rect); |
---|
164 | |
---|
165 | const AW_screen_area& area_size = get_device()->get_area_size(); |
---|
166 | scrolled_rect.calc_bottomRight_folding_dimensions(area_size.r, area_size.b); |
---|
167 | |
---|
168 | update_window_coords(); // @@@ do at end of this function? (since it uses aww-slider_pos_horizontal, |
---|
169 | // which might get modified by calculate_scrollbars below); |
---|
170 | |
---|
171 | // update window scrollbars |
---|
172 | set_scrollbar_indents(); |
---|
173 | aww->calculate_scrollbars(); |
---|
174 | |
---|
175 | check_valid_scrollbar_values(); // test that AW_window slider positions and folding line dimensions are in sync |
---|
176 | } |
---|
177 | |
---|
178 | // store synced slider positions in ED4_window |
---|
179 | slider_pos_vertical = aww->slider_pos_vertical; |
---|
180 | slider_pos_horizontal = aww->slider_pos_horizontal; |
---|
181 | } |
---|
182 | |
---|
183 | ED4_returncode ED4_window::set_scrolled_rectangle(ED4_base *x_link, ED4_base *y_link, ED4_base *width_link, ED4_base *height_link) { |
---|
184 | e4_assert(x_link); |
---|
185 | e4_assert(y_link); |
---|
186 | e4_assert(width_link); |
---|
187 | e4_assert(height_link); |
---|
188 | |
---|
189 | scrolled_rect.destroy_folding_lines(*this); // first remove existing scrolled rectangle |
---|
190 | |
---|
191 | x_link->update_info.linked_to_scrolled_rectangle = 1; |
---|
192 | y_link->update_info.linked_to_scrolled_rectangle = 1; |
---|
193 | width_link->update_info.linked_to_scrolled_rectangle = 1; |
---|
194 | height_link->update_info.linked_to_scrolled_rectangle = 1; |
---|
195 | |
---|
196 | scrolled_rect.link(x_link, y_link, width_link, height_link); |
---|
197 | |
---|
198 | const AW_screen_area& area_size = get_device()->get_area_size(); |
---|
199 | |
---|
200 | AW::Rectangle rect = scrolled_rect.get_world_rect(); |
---|
201 | scrolled_rect.create_folding_lines(*this, rect, area_size.r, area_size.b); |
---|
202 | |
---|
203 | scrolled_rect.set_rect(rect); |
---|
204 | |
---|
205 | return ED4_R_OK; |
---|
206 | } |
---|
207 | |
---|
208 | static inline void clear_and_update_rectangle(AW_pos x1, AW_pos y1, AW_pos x2, AW_pos y2) { |
---|
209 | // clears and updates any range of the screen (in win coordinates) |
---|
210 | // clipping range should be set correctly |
---|
211 | AW_screen_area rect; |
---|
212 | |
---|
213 | rect.t = int(y1); |
---|
214 | rect.b = int(y2); |
---|
215 | rect.l = int(x1); |
---|
216 | rect.r = int(x2); |
---|
217 | ED4_set_clipping_rectangle(&rect); |
---|
218 | |
---|
219 | #if defined(DEBUG) && 0 |
---|
220 | static int toggle = 0; |
---|
221 | current_device()->box(ED4_G_COLOR_2+toggle, true, x1, y1, x2-x1, y2-y1, AW_ALL_DEVICES_SCALED); // fill range with color (for testing) |
---|
222 | toggle = (toggle+1)&7; |
---|
223 | #else |
---|
224 | current_device()->clear_part(x1, y1, x2-x1, y2-y1, AW_ALL_DEVICES); |
---|
225 | #endif |
---|
226 | |
---|
227 | ED4_ROOT->main_manager->Show(true, true); // direct call to Show (critical) |
---|
228 | } |
---|
229 | |
---|
230 | static inline void move_and_update_rectangle(AW_pos x1, AW_pos y1, AW_pos x2, AW_pos y2, int dx, int dy) { |
---|
231 | // x1/y1=upper-left-corner (win coordinates) |
---|
232 | // x2/y2=lower-right-corner |
---|
233 | // dx/dy=movement |
---|
234 | AW_pos fx = dx<0 ? x1-dx : x1; // move from position .. |
---|
235 | AW_pos fy = dy<0 ? y1-dy : y1; |
---|
236 | AW_pos tx = dx>0 ? x1+dx : x1; // ..to position .. |
---|
237 | AW_pos ty = dy>0 ? y1+dy : y1; |
---|
238 | int xs = int(x2-x1-abs(dx)); // ..size |
---|
239 | int ys = int(y2-y1-abs(dy)); |
---|
240 | |
---|
241 | { |
---|
242 | AW_screen_area rect; |
---|
243 | rect.t = int(ty); |
---|
244 | rect.b = int(ty+ys-1); |
---|
245 | rect.l = int(tx); |
---|
246 | rect.r = int(tx+xs-1); |
---|
247 | ED4_set_clipping_rectangle(&rect); |
---|
248 | } |
---|
249 | |
---|
250 | AW_device *device = current_device(); |
---|
251 | device->move_region(fx, fy, xs, ys, tx, ty); |
---|
252 | |
---|
253 | if (dy<0) { // scroll to the top |
---|
254 | device->set_top_font_overlap(true); |
---|
255 | clear_and_update_rectangle(x1, y2+dy, x2, y2); |
---|
256 | device->set_top_font_overlap(false); |
---|
257 | } |
---|
258 | else if (dy>0) { // scroll to the bottom |
---|
259 | device->set_bottom_font_overlap(true); |
---|
260 | clear_and_update_rectangle(x1, y1, x2, y1+dy); |
---|
261 | device->set_bottom_font_overlap(false); |
---|
262 | } |
---|
263 | |
---|
264 | int char_width = ED4_ROOT->font_group.get_max_width() * 2; |
---|
265 | if (dx<0) { // scroll left |
---|
266 | device->set_left_font_overlap(true); |
---|
267 | clear_and_update_rectangle(x2+dx-char_width, y1, x2, y2); |
---|
268 | device->set_left_font_overlap(false); |
---|
269 | } |
---|
270 | else if (dx>0) { // scroll right |
---|
271 | device->set_right_font_overlap(true); |
---|
272 | clear_and_update_rectangle(x1, y1, x1+dx+char_width, y2); |
---|
273 | device->set_right_font_overlap(false); |
---|
274 | } |
---|
275 | } |
---|
276 | |
---|
277 | static inline void update_rectangle(AW_pos x1, AW_pos y1, AW_pos x2, AW_pos y2) { |
---|
278 | // x1/y1=upper-left-corner |
---|
279 | // x2/y2=lower-right-corner |
---|
280 | AW_screen_area rect; |
---|
281 | rect.t = int(y1); |
---|
282 | rect.b = int(y2); |
---|
283 | rect.l = int(x1); |
---|
284 | rect.r = int(x2); |
---|
285 | |
---|
286 | ED4_set_clipping_rectangle(&rect); |
---|
287 | clear_and_update_rectangle(x1, y1, x2, y2); |
---|
288 | } |
---|
289 | |
---|
290 | |
---|
291 | ED4_returncode ED4_window::scroll_rectangle(int dx, int dy) { |
---|
292 | int skip_move; |
---|
293 | |
---|
294 | if (!dx && !dy) return ED4_R_OK; // scroll not |
---|
295 | |
---|
296 | AW::Rectangle rect = scrolled_rect.get_window_rect(); |
---|
297 | |
---|
298 | AW::Position ul = rect.upper_left_corner(); |
---|
299 | AW::Position lr = rect.lower_right_corner(); |
---|
300 | |
---|
301 | AW_pos left_x = ul.xpos(); |
---|
302 | AW_pos top_y = ul.ypos(); |
---|
303 | AW_pos right_x = lr.xpos(); |
---|
304 | AW_pos bottom_y = lr.ypos(); |
---|
305 | |
---|
306 | scrolled_rect.scroll(dx, dy); |
---|
307 | |
---|
308 | skip_move = (abs(int(dy)) > (bottom_y - top_y - 20)) || (abs(int(dx)) > (right_x - left_x - 20)); |
---|
309 | |
---|
310 | AW_pos leftmost_x = coords.middle_area_x; |
---|
311 | AW_pos toptop_y = coords.top_area_y; |
---|
312 | AW_pos topbottom_y = toptop_y + coords.top_area_height - 1; |
---|
313 | |
---|
314 | get_device()->push_clip_scale(); |
---|
315 | |
---|
316 | // main area |
---|
317 | |
---|
318 | if (skip_move) update_rectangle(left_x, top_y, right_x, bottom_y); // main area |
---|
319 | else move_and_update_rectangle(left_x, top_y, right_x, bottom_y, int(dx), int(dy)); // main area |
---|
320 | |
---|
321 | // name area (scroll only vertically) |
---|
322 | |
---|
323 | if (dy) { |
---|
324 | if (skip_move) update_rectangle(leftmost_x, top_y, left_x, bottom_y); |
---|
325 | else move_and_update_rectangle(leftmost_x, top_y, left_x, bottom_y, 0, int(dy)); |
---|
326 | } |
---|
327 | |
---|
328 | // top area (scroll only horizontally) |
---|
329 | |
---|
330 | if (dx) { |
---|
331 | if (skip_move) update_rectangle(left_x, toptop_y, right_x, topbottom_y); |
---|
332 | else move_and_update_rectangle(left_x, toptop_y, right_x, topbottom_y, int(dx), 0); |
---|
333 | } |
---|
334 | |
---|
335 | get_device()->pop_clip_scale(); |
---|
336 | |
---|
337 | return ED4_R_OK; |
---|
338 | } |
---|
339 | |
---|
340 | void ED4_window::set_scrollbar_indents() { |
---|
341 | if (scrolled_rect.exists()) { |
---|
342 | AW::Rectangle rect = scrolled_rect.get_window_rect(); |
---|
343 | aww->set_vertical_scrollbar_top_indent(rect.top() + SLIDER_OFFSET); |
---|
344 | aww->set_horizontal_scrollbar_left_indent(rect.left() + SLIDER_OFFSET); |
---|
345 | } |
---|
346 | } |
---|
347 | |
---|
348 | |
---|
349 | void ED4_window::delete_window(ED4_window *window) { |
---|
350 | // delete from window list |
---|
351 | ED4_window *temp, *temp2; |
---|
352 | |
---|
353 | if (window == ED4_ROOT->first_window) { |
---|
354 | temp = ED4_ROOT->first_window; // delete temp afterwards |
---|
355 | ED4_ROOT->first_window = ED4_ROOT->first_window->next; |
---|
356 | } |
---|
357 | else { |
---|
358 | temp = temp2 = ED4_ROOT->first_window; |
---|
359 | |
---|
360 | while (temp != window) { |
---|
361 | temp2 = temp; |
---|
362 | temp = temp->next; |
---|
363 | } |
---|
364 | |
---|
365 | temp2->next = temp->next; |
---|
366 | } |
---|
367 | |
---|
368 | ED4_ROOT->aw_root->awar(temp->awar_path_for_cursor)->write_int(0); // save in database |
---|
369 | ED4_ROOT->aw_root->awar(temp->awar_path_for_Ecoli)->write_int(0); |
---|
370 | ED4_ROOT->aw_root->awar(temp->awar_path_for_basePos)->write_int(0); |
---|
371 | ED4_ROOT->aw_root->awar(temp->awar_path_for_IUPAC)->write_string(ED4_IUPAC_EMPTY); |
---|
372 | ED4_ROOT->aw_root->awar(temp->awar_path_for_helixNr)->write_string(""); |
---|
373 | delete temp; |
---|
374 | } |
---|
375 | |
---|
376 | static void ED4_expose_cb(AW_window *aww) { |
---|
377 | ED4_LocalWinContext uses(aww); |
---|
378 | GB_transaction ta(ED4_ROOT->get_gb_main()); |
---|
379 | |
---|
380 | current_ed4w()->update_scrolled_rectangle(); |
---|
381 | |
---|
382 | current_device()->reset(); |
---|
383 | ED4_ROOT->special_window_refresh(true); |
---|
384 | } |
---|
385 | |
---|
386 | static void ED4_resize_cb(AW_window *aww) { |
---|
387 | ED4_LocalWinContext uses(aww); |
---|
388 | GB_transaction ta(ED4_ROOT->get_gb_main()); |
---|
389 | |
---|
390 | current_device()->reset(); |
---|
391 | current_ed4w()->update_scrolled_rectangle(); |
---|
392 | } |
---|
393 | |
---|
394 | |
---|
395 | ED4_window *ED4_window::insert_window(AW_window_menu_modes *new_aww) { |
---|
396 | ED4_window *last, *temp; |
---|
397 | |
---|
398 | temp = ED4_ROOT->first_window; // append at end of window list |
---|
399 | last = temp; |
---|
400 | while (temp) { |
---|
401 | last = temp; |
---|
402 | temp = temp->next; |
---|
403 | } |
---|
404 | |
---|
405 | temp = new ED4_window (new_aww); |
---|
406 | |
---|
407 | if (!ED4_ROOT->first_window) { // this is the first window |
---|
408 | ED4_ROOT->first_window = temp; |
---|
409 | } |
---|
410 | else if (last) { |
---|
411 | last->next = temp; |
---|
412 | } |
---|
413 | |
---|
414 | // treat devices |
---|
415 | new_aww->set_expose_callback(AW_MIDDLE_AREA, makeWindowCallback(ED4_expose_cb)); |
---|
416 | new_aww->set_resize_callback(AW_MIDDLE_AREA, makeWindowCallback(ED4_resize_cb)); |
---|
417 | new_aww->set_input_callback (AW_MIDDLE_AREA, makeWindowCallback(ED4_input_cb)); |
---|
418 | new_aww->set_motion_callback(AW_MIDDLE_AREA, makeWindowCallback(ED4_motion_cb)); |
---|
419 | |
---|
420 | new_aww->set_horizontal_change_callback(makeWindowCallback(ED4_horizontal_change_cb)); |
---|
421 | new_aww->set_vertical_change_callback (makeWindowCallback(ED4_vertical_change_cb)); |
---|
422 | |
---|
423 | ED4_ROOT->temp_gc = ED4_G_STANDARD; |
---|
424 | |
---|
425 | return temp; |
---|
426 | } |
---|
427 | |
---|
428 | ED4_window::ED4_window(AW_window_menu_modes *window) |
---|
429 | : aww(window), |
---|
430 | next(NULp), |
---|
431 | slider_pos_horizontal(0), |
---|
432 | slider_pos_vertical(0), |
---|
433 | id(++no_of_windows), |
---|
434 | is_hidden(false), |
---|
435 | cursor(this) |
---|
436 | { |
---|
437 | coords.clear(); |
---|
438 | |
---|
439 | sprintf(awar_path_for_cursor, AWAR_EDIT_SEQ_POSITION, id); |
---|
440 | ED4_ROOT->aw_root->awar_int(awar_path_for_cursor, 0, AW_ROOT_DEFAULT); |
---|
441 | |
---|
442 | sprintf(awar_path_for_Ecoli, AWAR_EDIT_ECOLI_POSITION, id); |
---|
443 | ED4_ROOT->aw_root->awar_int(awar_path_for_Ecoli, 0, AW_ROOT_DEFAULT); |
---|
444 | |
---|
445 | sprintf(awar_path_for_basePos, AWAR_EDIT_BASE_POSITION, id); |
---|
446 | ED4_ROOT->aw_root->awar_int(awar_path_for_basePos, 0, AW_ROOT_DEFAULT); |
---|
447 | |
---|
448 | sprintf(awar_path_for_IUPAC, AWAR_EDIT_IUPAC, id); |
---|
449 | ED4_ROOT->aw_root->awar_string(awar_path_for_IUPAC, ED4_IUPAC_EMPTY, AW_ROOT_DEFAULT); |
---|
450 | |
---|
451 | sprintf(awar_path_for_helixNr, AWAR_EDIT_HELIXNR, id); |
---|
452 | ED4_ROOT->aw_root->awar_string(awar_path_for_helixNr, "", AW_ROOT_DEFAULT); |
---|
453 | } |
---|
454 | |
---|
455 | |
---|
456 | ED4_window::~ED4_window() { |
---|
457 | delete aww; |
---|
458 | no_of_windows --; |
---|
459 | } |
---|
460 | |
---|