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