]> git.lyx.org Git - lyx.git/blob - src/WorkArea.C
Some changes to compile new painter code with compaq cxx
[lyx.git] / src / WorkArea.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *        
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12 #include <cmath>
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18 #include "WorkArea.h"
19 #include "up.xpm"
20 #include "down.xpm"
21 #include "debug.h"
22 #include "support/lstrings.h"
23 #include "BufferView.h"
24
25 #ifdef NEW_WA
26 FL_OBJECT * figinset_canvas;
27 #endif
28
29 static inline
30 void waitForX()
31 {
32         XSync(fl_get_display(), 0);
33 }
34
35 extern "C" {
36 // Just a bunch of C wrappers around static members of WorkArea
37         void C_WorkArea_up_cb(FL_OBJECT * ob, long buf)
38         {
39                 WorkArea::up_cb(ob, buf);
40         }
41
42         void C_WorkArea_down_cb(FL_OBJECT * ob, long buf)
43         {
44                 WorkArea::down_cb(ob, buf);
45         }
46
47         void C_WorkArea_scroll_cb(FL_OBJECT * ob, long buf)
48         {
49                 WorkArea::scroll_cb(ob, buf);
50         }
51
52         int C_WorkArea_work_area_handler(FL_OBJECT * ob, int event,
53                                            FL_Coord, FL_Coord, 
54                                            int key, void * xev)
55         {
56                 return WorkArea::work_area_handler(ob, event,
57                                                    0, 0, key, xev);
58         }
59 }
60
61
62
63 WorkArea::WorkArea(BufferView * o, int xpos, int ypos, int width, int height)
64         : owner(o), workareapixmap(0)
65 #ifdef USE_PAINTER
66         , painter_(*this)
67 #endif
68 {
69         fl_freeze_all_forms();
70
71         figinset_canvas = 0;
72         
73         lyxerr << "Creating work area: +"
74                << xpos << '+' << ypos << ' '
75                << width << 'x' << height << endl;
76         //
77         FL_OBJECT * obj;
78         const int bw = int(abs(float(fl_get_border_width())));
79
80         // We really want to get rid of figinset_canvas.
81         ::figinset_canvas = figinset_canvas = obj =
82                   fl_add_canvas(FL_NORMAL_CANVAS,
83                                 xpos + 1, ypos + 1, 1, 1, "");
84         fl_set_object_boxtype(obj, FL_NO_BOX);
85         fl_set_object_resize(obj, FL_RESIZE_ALL);
86         fl_set_object_gravity(obj, NorthWestGravity, NorthWestGravity);
87         
88         // a box
89         lyxerr << "\tbackground box: +"
90                << xpos << '+' << ypos << ' '
91                << width - 15 << 'x' << height << endl;
92         backgroundbox = obj = fl_add_box(FL_BORDER_BOX,
93                                          xpos, ypos,
94                                          width - 15,
95                                          height,"");
96         fl_set_object_resize(obj, FL_RESIZE_ALL);
97         fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
98
99         //
100         // THE SCROLLBAR
101         //
102
103         // up - scrollbar button
104         fl_set_border_width(-1);
105
106         lyxerr << "\tup button: +"
107                << xpos + width - 15 << '+' << ypos << ' '
108                << 15 << 'x' << 15 << endl;
109         button_up = obj = fl_add_pixmapbutton(FL_TOUCH_BUTTON,
110                                               xpos + width - 15,
111                                               ypos,
112                                               15, 15, "");
113         fl_set_object_boxtype(obj,FL_UP_BOX);
114         fl_set_object_color(obj,FL_MCOL,FL_BLUE);
115         fl_set_object_resize(obj, FL_RESIZE_ALL);
116         fl_set_object_gravity(obj,NorthEastGravity, NorthEastGravity);
117         obj->u_vdata = this;
118         fl_set_object_callback(obj,C_WorkArea_up_cb, 0);
119         fl_set_pixmapbutton_data(obj, const_cast<char**>(up_xpm));
120
121         // Remove the blue feedback rectangle
122         fl_set_pixmapbutton_focus_outline(obj,0);
123
124         // the scrollbar slider
125         fl_set_border_width(-bw);
126         lyxerr << "\tscrollbar slider: +"
127                << xpos + width - 15 << '+' << ypos + 15 << ' '
128                << 15 << 'x' << height - 30 << endl;
129         scrollbar = obj = fl_add_slider(FL_VERT_SLIDER,
130                                         xpos + width - 15,
131                                         ypos + 15,
132                                         15, height - 30, "");
133         fl_set_object_color(obj,FL_COL1,FL_MCOL);
134         fl_set_object_boxtype(obj, FL_UP_BOX);
135         fl_set_object_resize(obj, FL_RESIZE_ALL);
136         fl_set_object_gravity(obj, NorthEastGravity, SouthEastGravity);
137         obj->u_vdata = this;
138         fl_set_object_callback(obj, C_WorkArea_scroll_cb, 0);
139         fl_set_slider_precision(obj, 0);
140         
141         // down - scrollbar button
142         fl_set_border_width(-1);
143
144         lyxerr << "\tdown button: +"
145                << xpos + width - 15 << '+' << ypos + height - 15 << ' '
146                << 15 << 'x' << 15 << endl;
147         button_down = obj = fl_add_pixmapbutton(FL_TOUCH_BUTTON,
148                                                 xpos + width - 15,
149                                                 ypos + height - 15,
150                                                 15, 15, "");
151         fl_set_object_boxtype(obj,FL_UP_BOX);
152         fl_set_object_color(obj,FL_MCOL,FL_BLUE);
153         fl_set_object_resize(obj, FL_RESIZE_ALL);
154         fl_set_object_gravity(obj, SouthEastGravity, SouthEastGravity);
155         obj->u_vdata = this;
156         fl_set_object_callback(obj, C_WorkArea_down_cb, 0);
157         fl_set_pixmapbutton_data(obj, const_cast<char**>(down_xpm));
158
159         fl_set_border_width(-bw);
160
161         // Remove the blue feedback rectangle
162         fl_set_pixmapbutton_focus_outline(obj,0);
163
164         ///
165         /// The free object
166
167         // Create the workarea pixmap
168         createPixmap(width - 15 - 2 * bw, height - 2 * bw);
169 #ifdef USE_PAINTER
170         // setup the painter
171         painter_.setDisplay(fl_display);
172         painter_.setDrawable(workareapixmap);
173 #endif
174         
175         // We add this object as late as possible to avoit problems
176         // with drawing.
177         lyxerr << "\tfree object: +"
178                << xpos + bw << '+' << ypos + bw << ' '
179                << width - 15 - 2 * bw << 'x' << height - 2 * bw << endl;
180         work_area = obj = fl_add_free(FL_INPUT_FREE,
181                                       xpos + bw, ypos + bw,
182                                       width - 15 - 2 * bw, // scrollbarwidth
183                                       height - 2 * bw, "",
184                                       C_WorkArea_work_area_handler);
185         obj->wantkey = FL_KEY_TAB;
186         obj->u_vdata = this; /* This is how we pass the WorkArea
187                                        to the work_area_handler. */
188         fl_set_object_boxtype(obj,FL_DOWN_BOX);
189         fl_set_object_resize(obj, FL_RESIZE_ALL);
190         fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
191
192         fl_unfreeze_all_forms();
193 }
194
195
196 WorkArea::~WorkArea()
197 {
198         if (workareapixmap)
199                 XFreePixmap(fl_display, workareapixmap);
200 }
201
202
203 void WorkArea::resize(int xpos, int ypos, int width, int height)
204 {
205         fl_freeze_all_forms();
206         
207         const int bw = int(abs(float(fl_get_border_width())));
208
209         // a box
210         fl_set_object_geometry(backgroundbox, xpos, ypos, width - 15, height);
211         
212         //
213         // THE SCROLLBAR
214         //
215
216         // up - scrollbar button
217         fl_set_object_geometry(button_up, xpos + width - 15,
218                                ypos,
219                                15, 15);
220         // the scrollbar slider
221         fl_set_object_geometry(scrollbar, xpos + width - 15,
222                                ypos + 15,
223                                15, height - 30);
224         // down - scrollbar button
225         fl_set_object_geometry(button_down, xpos + width - 15,
226                                ypos + height - 15,
227                                15, 15);
228
229         // Create the workarea pixmap
230         createPixmap(width - 15 - 2 * bw, height - 2 * bw);
231
232 #ifdef USE_PAINTER
233         // reset the painter
234         painter_.setDrawable(workareapixmap);
235 #endif
236         
237         // the free object
238         fl_set_object_geometry(work_area, xpos + bw, ypos + bw,
239                                width - 15 - 2 * bw,
240                                height - 2 * bw);
241
242         fl_unfreeze_all_forms();
243
244 }
245
246
247 void WorkArea::createPixmap(int width, int height)
248 {
249         static int cur_width = -1;
250         static int cur_height = -1;
251
252         if (cur_width == width && cur_height == height && workareapixmap)
253                 return;
254         
255         cur_width = width;
256         cur_height = height;
257
258         if (workareapixmap)
259                 XFreePixmap(fl_display, workareapixmap);
260         
261         lyxerr << "Creating pixmap (" << width << 'x' << height << ")" << endl;
262         
263         workareapixmap = XCreatePixmap(fl_display,
264                                        RootWindow(fl_display, 0),
265                                        width,
266                                        height, 
267                                        fl_get_visual_depth());
268         lyxerr << "\tpixmap=" << workareapixmap << endl;
269 }
270
271
272 void WorkArea::greyOut() const
273 {
274         fl_winset(FL_ObjWin(work_area));
275         fl_rectangle(1, work_area->x, work_area->y,
276                      work_area->w, work_area->h, FL_GRAY63);
277 }
278
279
280 void WorkArea::setFocus() const
281 {
282         fl_set_focus_object(work_area->form, work_area);
283 }
284
285
286 void WorkArea::setScrollbar(double pos, double length_fraction) const
287 {
288         fl_set_slider_value(scrollbar, pos);
289         fl_set_slider_size(scrollbar, scrollbar->h * length_fraction);
290 }
291
292
293 void WorkArea::setScrollbarBounds(double l1, double l2) const
294 {
295         fl_set_slider_bounds(scrollbar, l1, l2);
296 }
297
298
299 void WorkArea::setScrollbarIncrements(float inc) const
300 {
301         fl_set_slider_increment(scrollbar, work_area->h - inc, inc);
302 }
303
304
305 void WorkArea::up_cb(FL_OBJECT * ob, long)
306 {
307         WorkArea * area = static_cast<WorkArea*>(ob->u_vdata);
308         XEvent const * ev2 = fl_last_event();
309         static long time = 0;
310         ev2 = fl_last_event();
311         if (ev2->type == ButtonPress || ev2->type == ButtonRelease) 
312                 time = 0;
313         //area->up(time++, fl_get_button_numb(ob));
314         area->owner->UpCB(time++, fl_get_button_numb(ob));
315 }
316
317
318 void WorkArea::down_cb(FL_OBJECT * ob, long)
319 {
320         WorkArea * area = static_cast<WorkArea*>(ob->u_vdata);
321         XEvent const * ev2 = fl_last_event();
322         static long time = 0;
323         if (ev2->type == ButtonPress || ev2->type == ButtonRelease)
324                 time = 0;
325         //area->down(time++, fl_get_button_numb(ob));
326         area->owner->DownCB(time++, fl_get_button_numb(ob));
327 }
328
329
330 // Callback for scrollbar slider
331 void WorkArea::scroll_cb(FL_OBJECT * ob, long)
332 {
333         WorkArea * area = static_cast<WorkArea*>(ob->u_vdata);
334
335         //area->scroll(fl_get_slider_value(ob));
336         area->owner->ScrollCB(fl_get_slider_value(ob));
337         waitForX();
338 }
339
340 bool Lgb_bug_find_hack = false;
341
342 int WorkArea::work_area_handler(FL_OBJECT * ob, int event,
343                                   FL_Coord, FL_Coord ,
344                                   int /*key*/, void * xev)
345 {
346         static int x_old = -1;
347         static int y_old = -1;
348         static long scrollbar_value_old = -1;
349         
350         XEvent * ev = static_cast<XEvent*>(xev);
351         WorkArea * area = static_cast<WorkArea*>(ob->u_vdata);
352
353         if (!area) return 1;
354         
355         switch (event){   
356         case FL_DRAW:
357                 if (!area->work_area ||
358                     !area->work_area->form->visible)
359                         return 1;
360                 lyxerr.debug() << "Workarea event: DRAW" << endl;
361                 area->createPixmap(area->workWidth(), area->height());
362                 Lgb_bug_find_hack = true;
363                 //area->expose();
364                 area->owner->workAreaExpose();
365                 Lgb_bug_find_hack = false;
366                 break;
367         case FL_PUSH:
368                 if (!ev) break;
369                 // Should really have used xbutton.state
370                 lyxerr.debug() << "Workarea event: PUSH" << endl;
371                 //area->buttonPress(ev->xbutton.x - ob->x,
372                 //                ev->xbutton.y - ob->y,
373                 //                ev->xbutton.button);
374                 area->owner->WorkAreaButtonPress(ev->xbutton.x - ob->x,
375                                            ev->xbutton.y - ob->y,
376                                            ev->xbutton.button);
377                 break; 
378         case FL_RELEASE:
379                 if (!ev) break;
380                 // Should really have used xbutton.state
381                 lyxerr.debug() << "Workarea event: RELEASE" << endl;
382                 //area->buttonRelease(ev->xbutton.x - ob->x,
383                 //                  ev->xbutton.y - ob->y,
384                 //                  ev->xbutton.button);
385                 area->owner->WorkAreaButtonRelease(ev->xbutton.x - ob->x,
386                                              ev->xbutton.y - ob->y,
387                                              ev->xbutton.button);
388                 break;
389         case FL_MOUSE:
390                 if (!ev || ! area->scrollbar) break;
391                 if (ev->xmotion.x != x_old ||
392                     ev->xmotion.y != y_old ||
393                     fl_get_slider_value(area->scrollbar) != scrollbar_value_old) {
394                         lyxerr.debug() << "Workarea event: MOUSE" << endl;
395                         //area->motion(ev->xmotion.x - ob->x,
396                         //           ev->xmotion.y - ob->y,
397                         //           ev->xbutton.state);
398                         area->owner->WorkAreaMotionNotify(ev->xmotion.x - ob->x,
399                                                     ev->xmotion.y - ob->y,
400                                                     ev->xbutton.state);
401                 }
402                 break;
403         // Done by the raw callback:
404         //  case FL_KEYBOARD: WorkAreaKeyPress(ob, 0,0,0,ev,0); break;
405         case FL_FOCUS:
406                 lyxerr.debug() << "Workarea event: FOCUS" << endl;
407                 //area->focus();
408                 break;
409         case FL_UNFOCUS:
410                 lyxerr.debug() << "Workarea event: UNFOCUS" << endl;
411                 //area->unfocus();
412                 break;
413         case FL_ENTER:
414                 lyxerr.debug() << "Workarea event: ENTER" << endl;
415                 //area->enter();
416                 break;
417         case FL_LEAVE:
418                 lyxerr.debug() << "Workarea event: LEAVE" << endl;
419                 //area->leave();
420                 break;
421         case FL_DBLCLICK:
422                 if (!ev) break;
423                 lyxerr.debug() << "Workarea event: DBLCLICK" << endl;;
424                 //area->doubleclick(ev->xbutton.x,
425                 //                ev->xbutton.y,
426                 //                ev->xbutton.button);
427                 break;
428         case FL_TRPLCLICK:
429                 if (!ev) break;
430                 lyxerr.debug() << "Workarea event: TRPLCLICK" << endl;
431                 //area->trippleclick(ev->xbutton.x,
432                 //                 ev->xbutton.y,
433                 //                 ev->xbutton.button);
434                 break;
435         case FL_OTHER:
436                 if (!ev) break;
437                 if (ev->type == SelectionNotify) {
438                         lyxerr.debug() << "Workarea event: SELECTION" << endl;
439                         //area->selection(area->work_area->form->window, ev);
440                         area->owner->WorkAreaSelectionNotify(area->work_area->form->window, ev);
441                 } else
442                         lyxerr.debug() << "Workarea event: OTHER" << endl;
443
444                 break;
445         }
446   
447         return 1;
448 }