source: branches/profile/EDIT4/ED4_window.cxx

Last change on this file was 12200, checked in by westram, 5 years ago
  • reduce differences between gtk/trunk
    • copy conditional sections (ARB_GTK)
    • take-over some compatible changes
  • 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_menu_modes *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_menu_modes *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.