]> git.lyx.org Git - lyx.git/blob - src/combox.C
remove commented HAVE_SSTREAM code
[lyx.git] / src / combox.C
1 // -*- C++ -*-
2 /*
3  *  Combox: A combination of two objects (a button and a browser) is
4  *          encapsulated to get a combobox-like object. All XForms 
5  *          functions are hidden.         
6  * 
7  *  GNU Copyleft 1996 Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
8  *                        and the LyX Team.
9  * 
10  *  Dependencies:  Only XForms, but created to be used with LyX.
11  * 
12  */ 
13
14 /* Change log:
15  *  
16  *  2/06/1996,   Alejandro Aguilar Sierra 
17  *    Created and tested.
18  *  
19  *  4/06/1996,   Alejandro Aguilar Sierra 
20  *    Added droplist mode (a button with a black down arrow at right)
21  *    and support for middle and right buttons, as XForms choice object.
22  *
23  *  6/06/1996,   Lars Gullik Bjønnes
24  *    Added a combox with an input object. and a pre and a post handle.
25  * 
26  *  22/07/96,    Alejandro Aguilar Sierra 
27  *    Assigned to the browser its own popup window. No more need of
28  *    external pre and post handlers to simulate the wanted behaviour.
29  * 
30  */ 
31
32 #include <config.h>
33
34 #ifdef __GNUG__
35 #pragma implementation
36 #endif
37
38 #include "combox.h"
39 #include <cstring>
40
41 #include "debug.h"
42
43 using std::endl;
44
45 // These are C wrappers around static members of Combox, used as
46 // callbacks for xforms.
47 extern "C" void C_Combox_input_cb(FL_OBJECT *ob, long);
48 extern "C" void C_Combox_combo_cb(FL_OBJECT *ob, long data) ;
49 extern "C" int C_Combox_peek_event(FL_FORM * form, void *xev);
50
51 Combox::Combox(combox_type t): type(t)
52 {
53    browser = button = 0;
54    callback = 0;
55    label = 0;
56    cb_arg = 0;
57    _pre = 0;
58    _post = 0;
59    sel = 0;
60    form = 0;
61 }
62
63
64 Combox::~Combox()
65 {
66    remove();
67 }
68
69
70 void Combox::clear()
71 {
72         if (browser) fl_clear_browser(browser);   
73         sel = 0;
74         if (type == FL_COMBOX_INPUT)
75                 fl_set_input(label, "");
76         else
77                 fl_set_object_label(label, "");
78         is_empty = true;
79 }
80
81
82 void Combox::remove()
83 {
84         lyxerr.debug() << "Button: " << button << endl;
85         if (button) {
86                 fl_delete_object(button);
87                 fl_free_object(button); 
88         }
89         
90         lyxerr.debug() << "Label: " << label << endl;
91         if (label && label!= button) {
92                 fl_delete_object(label);
93                 fl_free_object(label); 
94         }
95         
96         lyxerr.debug() << "Form: " << form << endl;
97         lyxerr.debug() << "Browser: " << browser << endl;
98         if (form && browser) {
99            fl_delete_object(browser);
100            fl_free_object(browser);
101            fl_free_form(form);
102         }
103         button = 0; 
104         browser = 0; 
105         label = 0;
106         form = 0;
107         sel = 0;
108         is_empty = true;
109 }
110
111
112 void Combox::addline(string const & text)
113 {
114         if (!browser) return;
115         fl_add_browser_line(browser, text.c_str());
116         
117         // By default the first item is selected
118         if (!sel) {
119                 sel = 1;
120                 if (type == FL_COMBOX_INPUT)
121                         fl_set_input(label, text.c_str());
122                 else
123                         fl_set_object_label(label, text.c_str()); 
124         }
125         is_empty = false;
126 }
127
128
129 bool Combox::select_text(string const & t)
130 {
131         if (!browser || t.empty()) return false;
132         int const maxline = fl_get_browser_maxline(browser);
133         
134         for (int i = 1; i <= maxline; ++i) {
135                 if (t == fl_get_browser_line(browser, i)) {
136                         select(i);
137                         return true;
138                 }
139         }
140         return false;  // t does not exist in browser
141 }
142
143
144 void Combox::select(int i)
145 {
146         if (!browser || !button) return;
147         if (i > 0 && i <= fl_get_browser_maxline(browser)) sel = i; 
148         fl_deactivate_object(button);
149         
150         if (type == FL_COMBOX_INPUT)
151                 fl_set_input(label, fl_get_browser_line(browser, sel));
152         else
153                 fl_set_object_label(label, fl_get_browser_line(browser, sel)); 
154         fl_activate_object(button); 
155 }
156
157
158 void Combox::add(int x, int y, int w, int hmin, int hmax)
159 {  
160         FL_OBJECT * obj;
161         
162         switch(type) {
163         case FL_COMBOX_DROPLIST:
164         {
165                 button = obj = fl_add_button(FL_NORMAL_BUTTON,
166                                              x+w-22, y, 22, hmin, "@2->");
167                 fl_set_object_color(obj, FL_MCOL, FL_MCOL);
168                 fl_set_object_dblbuffer(obj, 1);
169                 fl_set_object_callback(obj, C_Combox_combo_cb, 0);
170                 label = obj = fl_add_button(FL_NORMAL_TEXT, x, y, w-22, hmin, "");
171                 fl_set_object_boxtype(obj, FL_DOWN_BOX);
172                 fl_set_object_color(obj, FL_MCOL, FL_BLACK);
173                 fl_set_object_lalign(obj, FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
174                 fl_set_object_dblbuffer(obj, 1);
175                 fl_set_object_callback(obj, C_Combox_combo_cb, 0);
176                 break;
177         }
178         case FL_COMBOX_NORMAL:
179         {
180                 button = obj = fl_add_button(FL_NORMAL_BUTTON, x, y, w, hmin, "");
181                 fl_set_object_color(obj, FL_MCOL, FL_MCOL);
182                 fl_set_object_boxtype(obj, FL_DOWN_BOX);
183                 fl_set_object_callback(obj, C_Combox_combo_cb, 0);
184                 fl_set_object_color(obj, FL_MCOL, FL_BLACK);
185                 label = button;
186                 break;
187         }
188         case FL_COMBOX_INPUT:
189         {
190                 button = obj = fl_add_button(FL_NORMAL_BUTTON,
191                                              x+w-22, y, 22, hmin, "@2->");
192                 fl_set_object_color(obj, FL_MCOL, FL_MCOL);
193                 fl_set_object_callback(obj, C_Combox_combo_cb, 0);
194                 label = obj = fl_add_input(FL_NORMAL_INPUT, x, y, w-22, hmin, "");
195                 fl_set_object_boxtype(obj, FL_DOWN_BOX);
196                 fl_set_object_return(obj, FL_RETURN_END_CHANGED);
197                 fl_set_object_callback(obj, C_Combox_input_cb, 0);
198                 //fl_set_object_color(obj, FL_MCOL, FL_BLACK);
199                 //fl_set_object_lalign(obj,FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
200                 break;
201         }
202         } // end of switch
203
204         label->u_vdata = this;
205         button->u_vdata = this;
206
207         // Hmm, it seems fl_create_browser is broken in xforms 0.86.
208         // We have to work around that by creating the dropped browser form
209         // at this point already. However, this means that we have
210         // to do a little hacking: (Asger)
211         FL_FORM * current_form = fl_current_form;
212         fl_end_form();
213
214         bw = w + 20; bh = hmax - hmin - 12;
215
216         form = fl_bgn_form(FL_NO_BOX, bw, bh);
217         browser = obj = fl_add_browser(FL_HOLD_BROWSER, 0, 0, bw, bh, "");
218         fl_set_object_boxtype(obj, FL_UP_BOX);
219         fl_set_object_color(obj, FL_MCOL, FL_YELLOW);
220         fl_set_object_gravity(obj, NorthWestGravity, NorthWestGravity);
221         fl_set_object_callback(obj, C_Combox_combo_cb, 2);
222         fl_end_form();
223         browser->u_vdata = this;
224         form->u_vdata = browser;
225         fl_register_raw_callback(form, 
226                                  ButtonPressMask|KeyPressMask,
227                                  C_Combox_peek_event);
228
229         // And revert to adding to the old form (Asger)
230         fl_addto_form(current_form);
231 }
232
233
234 static Window save_window;
235
236
237 void Combox::Redraw()
238 {
239         if (browser) fl_redraw_object(browser);
240         if (button) fl_redraw_object(button);
241         if (label) fl_redraw_object(label);
242 }
243  
244 void Combox::Show()
245 {
246         if (_pre) _pre();
247         
248         int tmp;
249         XGetInputFocus(fl_display, &save_window, &tmp); //BUG-Fix Dietmar
250         XFlush(fl_display);
251         if (button && type != FL_COMBOX_NORMAL) {
252                 fl_set_object_label(button, "@2<-");          
253                 fl_redraw_object(button);
254         }
255         int x = label->form->x + label->x, y = label->form->y + label->y;
256         fl_set_form_position(form, x, y + label->h);
257         fl_show_form(form, FL_PLACE_POSITION, FL_NOBORDER, "");
258         if (sel>0) {
259                 fl_set_browser_topline(browser, sel);
260                 fl_select_browser_line(browser, sel);
261         }
262         XGrabPointer(fl_display, form->window, false,
263                      ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
264                      GrabModeAsync, GrabModeAsync,
265                      0, 0, 0);
266         XFlush(fl_display);
267 }
268
269 void Combox::Hide(int who)
270 {  
271         if (!who && browser && label) {
272                 sel = fl_get_browser(browser);
273                 
274                 if (type == FL_COMBOX_INPUT)
275                         fl_set_input(label, fl_get_browser_line(browser, sel));
276                 else
277                         fl_set_object_label(label,
278                                             fl_get_browser_line(browser, sel));         
279 //              if (callback) callback(sel, cb_arg);
280         }
281         XUngrabPointer(fl_display, 0);
282         XFlush(fl_display);
283         if (!who && browser && label && callback)
284             callback(sel, cb_arg, this);
285         if (form) {
286                 fl_hide_form(form);
287                 XSetInputFocus(fl_display, save_window,
288                                RevertToParent, CurrentTime); // BUG-FIX-Dietmar
289                 XFlush(fl_display);
290         }
291         if (button) {
292                 if (type != FL_COMBOX_NORMAL){
293                         fl_set_object_label(button, "@2->");
294                         fl_redraw_object(button);
295                 }
296         } 
297         if (_post) _post();
298 }
299
300
301 void Combox::activate()
302 {
303         if (browser) fl_activate_object(browser);
304         if (button) fl_activate_object(button);
305         if (label) fl_activate_object(label);
306 }
307
308
309 void Combox::deactivate()
310 {
311         if (browser) fl_deactivate_object(browser);
312         if (button) fl_deactivate_object(button);
313         if (label) fl_deactivate_object(label);
314 }
315
316 void Combox::input_cb(FL_OBJECT * ob, long)
317 {
318         Combox * combo = static_cast<Combox*>(ob->u_vdata);
319
320         char const * text = fl_get_input(ob);
321
322         combo->addto(text);
323         combo->is_empty = false;
324 }
325
326 extern "C" void C_Combox_input_cb(FL_OBJECT * ob, long data)
327 {
328   Combox::input_cb(ob, data);
329 }
330
331
332 void Combox::combo_cb(FL_OBJECT * ob, long data)
333 {
334         Combox * combo = static_cast<Combox*>(ob->u_vdata);
335         switch (data) {
336         case 0:
337         {  
338                 int i = combo->get();
339                 switch (fl_get_button_numb(ob)) {
340                 case 2: 
341                 {
342                         combo->select(--i); 
343                         if (combo->callback)
344                                 combo->callback(combo->sel,
345                                                 combo->cb_arg, combo);
346                         break;
347                 }
348                 case 3: 
349                 {
350                         combo->select(++i);  
351                         if (combo->callback)
352                                 combo->callback(combo->sel,
353                                                 combo->cb_arg, combo);
354                         break;
355                 }
356                 default: combo->Show(); break;
357                 }
358                 break;
359         }
360         case 2:
361                 combo->Hide();
362                 break;
363         }
364 }
365
366 extern "C" void C_Combox_combo_cb(FL_OBJECT * ob, long data) 
367 {
368         Combox::combo_cb(ob, data);
369 }
370
371
372 int Combox::peek_event(FL_FORM * form, void * xev)
373 {
374         FL_OBJECT * ob = static_cast<FL_OBJECT *>(form->u_vdata);
375         Combox * combo = static_cast<Combox*>(ob->u_vdata);
376         
377         // I don't know why belowmouse does not work, but it doesn't. (Asger)
378         // Are we sure? Please verify. (Lgb)
379         if (static_cast<XEvent *>(xev)->type == ButtonPress && (
380                 static_cast<XEvent *>(xev)->xbutton.x - ob->x < 0 ||
381                 static_cast<XEvent *>(xev)->xbutton.x - ob->x > ob->w ||
382                 static_cast<XEvent *>(xev)->xbutton.y - ob->y < 0 ||
383                 static_cast<XEvent *>(xev)->xbutton.y - ob->y > ob->h)) {
384                 combo->Hide(1); 
385                 return 1;
386         }
387                 
388         if (static_cast<XEvent*>(xev)->type != KeyPress) return 0;
389         
390         char s_r[10]; s_r[9] = '\0';
391         static int num_bytes;
392         KeySym keysym_return;
393         num_bytes = XLookupString(&static_cast<XEvent*>(xev)->xkey, s_r, 10, 
394                                   &keysym_return, 0);
395         XFlush(fl_display);
396         switch (keysym_return) {
397         case XK_Down:
398                 if (fl_get_browser(combo->browser) <
399                     fl_get_browser_maxline(combo->browser))
400                         fl_select_browser_line(combo->browser,
401                                                fl_get_browser(combo->browser)+1);
402                 if (fl_get_browser(combo->browser)>= 
403                     fl_get_browser_topline(combo->browser) +
404                     fl_get_browser_screenlines(combo->browser))
405                         fl_set_browser_topline(combo->browser,
406                                                fl_get_browser(combo->browser)
407                                                - fl_get_browser_screenlines(combo->browser)+1);
408                 if (fl_get_browser(combo->browser)<
409                     fl_get_browser_topline(combo->browser))
410                         fl_set_browser_topline(combo->browser,
411                                                fl_get_browser(combo->browser));
412                 return 1; 
413         case XK_Up:
414                 if (fl_get_browser(combo->browser) > 1)
415                         fl_select_browser_line(combo->browser,
416                                                fl_get_browser(combo->browser)-1);
417                 if (fl_get_browser(combo->browser)>= 
418                     fl_get_browser_topline(combo->browser) +
419                     fl_get_browser_screenlines(combo->browser))
420                         fl_set_browser_topline(combo->browser,
421                                                fl_get_browser(combo->browser)
422                                                - fl_get_browser_screenlines(combo->browser)+1);
423                 if (fl_get_browser(combo->browser) <
424                     fl_get_browser_topline(combo->browser))
425                         fl_set_browser_topline(combo->browser,
426                                                fl_get_browser(combo->browser));
427                 return 1;
428         case XK_Return:
429                 combo->Hide();
430                 return 1;
431         case XK_Escape:
432                 combo->Hide(1);
433                 return 1;
434         }
435         return 0;  
436 }
437         
438 extern "C" int C_Combox_peek_event(FL_FORM * form, void *xev)
439 {
440         return Combox::peek_event(form, xev);
441 }
442
443
444 #ifdef TESTCOMBO
445 typedef struct {
446         FL_FORM *test;
447         FL_OBJECT *bar;
448         void *vdata;
449         long ldata;
450 } FD_test;
451
452 //Combox combo(FL_COMBOX_DROPLIST);
453 Combox combo(FL_COMBOX_INPUT);
454
455 FD_test *fd_test;
456    
457 FD_test *create_form_test(void)
458 {
459    FL_OBJECT *obj;
460    FD_test *fdui = (FD_test *) fl_calloc(1, sizeof(*fdui));
461    
462    fdui->test = fl_bgn_form(FL_NO_BOX, 320, 190);
463    obj = fl_add_box(FL_UP_BOX, 0, 0, 320, 190, "");
464    obj = fl_add_box(FL_DOWN_BOX, 10, 50, 300, 110, "");
465    obj = fl_add_button(FL_NORMAL_BUTTON, 250, 10, 50, 30, _("Done"));
466    combo.add(10, 15, 120, 25, 135); 
467    fl_end_form();
468
469   return fdui;
470 }
471
472 void combo_cb(int i)
473 {
474    fprintf(stderr, "selected %d:%s\n", i, combo.getline());
475 }
476
477 int main(int argc, char *argv[])
478 {
479         //int n1;
480    
481    // Same defaults as in lyx 
482    FL_IOPT cntl;
483    cntl.buttonFontSize = FL_NORMAL_SIZE;
484    cntl.browserFontSize = FL_NORMAL_SIZE;
485    cntl.labelFontSize = FL_NORMAL_SIZE;
486    cntl.choiceFontSize = FL_NORMAL_SIZE;
487    cntl.inputFontSize = FL_NORMAL_SIZE;
488    cntl.borderWidth = -2;
489    fl_set_defaults(FL_PDButtonFontSize, &cntl);  
490    fl_set_defaults(FL_PDBrowserFontSize, &cntl);  
491    fl_set_defaults(FL_PDLabelFontSize, &cntl);  
492    fl_set_defaults(FL_PDChoiceFontSize, &cntl);  
493    fl_set_defaults(FL_PDInputFontSize, &cntl);  
494    fl_set_defaults(FL_PDBorderWidth, &cntl);
495    fl_initialize(&argc, argv, 0, 0, 0);
496    
497    fd_test = create_form_test();
498
499    /* fill-in form initialization code */
500    combo.addline("Title");
501    combo.addline("Author");
502    combo.addline("Date");
503    combo.addline("Abstract");
504    combo.addline("Chapter");
505    combo.addline("Section");
506    combo.addline("Subsection");
507    combo.addline("List");
508    combo.addline("Description");
509    combo.addline("Verse");
510    combo.addline("Verbatim");
511    combo.setcallback(combo_cb);
512 //   combo.select(4);
513    
514    /* show the first form */
515    fl_show_form(fd_test->test, FL_PLACE_CENTER, FL_FULLBORDER, "test");
516    fl_do_forms();
517    return 0;
518 }
519
520 #endif