source: tags/arb-6.0-rc1/EDIT4/ED4_window.cxx

Last change on this file was 10883, checked in by epruesse, 12 years ago

tell aww about the changed picture size before updating the folding lines
In Motif, this has no effect. In GTK, it is required because it may cause
a scroll to keep the scroll-position within bounds. Doing this after
calc_bottomRight_folding_dimension would result in double-correction of
top_dim().

(All of this is a mess…)

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