source: branches/tree/EDIT4/ED4_window.cxx

Last change on this file was 18732, checked in by westram, 3 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
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
18int ED4_window::no_of_windows = 0;                  // static variable has to be initialized only once
19
20void 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
52void 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
97ED4_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
107ED4_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
121void 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
131AW::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
144void 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
183ED4_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
208static 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
230static 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
277static 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
291ED4_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
340void 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
349void 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
376static 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
386static 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
395ED4_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
428ED4_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
456ED4_window::~ED4_window() {
457    delete aww;
458    no_of_windows --;
459}
460
Note: See TracBrowser for help on using the repository browser.