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.
7 * GNU Copyleft 1996 Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
10 * Dependencies: Only XForms, but created to be used with LyX.
16 * 2/06/1996, Alejandro Aguilar Sierra
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.
23 * 6/06/1996, Lars Gullik Bjønnes
24 * Added a combox with an input object. and a pre and a post handle.
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.
35 #pragma implementation
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);
51 Combox::Combox(combox_type t): type(t)
72 if (browser) fl_clear_browser(browser);
74 if (type == FL_COMBOX_INPUT)
75 fl_set_input(label, "");
77 fl_set_object_label(label, "");
84 lyxerr.debug() << "Button: " << button << endl;
86 fl_delete_object(button);
87 fl_free_object(button);
90 lyxerr.debug() << "Label: " << label << endl;
91 if (label && label!= button) {
92 fl_delete_object(label);
93 fl_free_object(label);
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);
112 void Combox::addline(char const* text)
114 if (!browser) return;
115 fl_add_browser_line(browser, text);
117 // By default the first item is selected
120 if (type == FL_COMBOX_INPUT)
121 fl_set_input(label, text);
123 fl_set_object_label(label, text);
129 bool Combox::select_text(char const* t)
131 if (!browser || !t) return false;
132 for (int i = 1; i <= fl_get_browser_maxline(browser); ++i) {
133 if (!strcmp(t, fl_get_browser_line(browser, i))) {
138 return false; // t does not exist in browser
142 void Combox::select(int i)
144 if (!browser || !button) return;
145 if (i>0 && i<= fl_get_browser_maxline(browser)) sel = i;
146 fl_deactivate_object(button);
148 if (type == FL_COMBOX_INPUT)
149 fl_set_input(label, fl_get_browser_line(browser, sel));
151 fl_set_object_label(label, fl_get_browser_line(browser, sel));
152 fl_activate_object(button);
156 void Combox::add(int x, int y, int w, int hmin, int hmax)
161 case FL_COMBOX_DROPLIST:
163 button = obj = fl_add_button(FL_NORMAL_BUTTON,
164 x+w-22, y, 22, hmin, "@2->");
165 fl_set_object_color(obj, FL_MCOL, FL_MCOL);
166 fl_set_object_dblbuffer(obj, 1);
167 fl_set_object_callback(obj, C_Combox_combo_cb, 0);
168 label = obj = fl_add_button(FL_NORMAL_TEXT, x, y, w-22, hmin, "");
169 fl_set_object_boxtype(obj, FL_DOWN_BOX);
170 fl_set_object_color(obj, FL_MCOL, FL_BLACK);
171 fl_set_object_lalign(obj, FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
172 fl_set_object_dblbuffer(obj, 1);
173 fl_set_object_callback(obj, C_Combox_combo_cb, 0);
176 case FL_COMBOX_NORMAL:
178 button = obj = fl_add_button(FL_NORMAL_BUTTON, x, y, w, hmin, "");
179 fl_set_object_color(obj, FL_MCOL, FL_MCOL);
180 fl_set_object_boxtype(obj, FL_DOWN_BOX);
181 fl_set_object_callback(obj, C_Combox_combo_cb, 0);
182 fl_set_object_color(obj, FL_MCOL, FL_BLACK);
186 case FL_COMBOX_INPUT:
188 button = obj = fl_add_button(FL_NORMAL_BUTTON,
189 x+w-22, y, 22, hmin, "@2->");
190 fl_set_object_color(obj, FL_MCOL, FL_MCOL);
191 fl_set_object_callback(obj, C_Combox_combo_cb, 0);
192 label = obj = fl_add_input(FL_NORMAL_INPUT, x, y, w-22, hmin, "");
193 fl_set_object_boxtype(obj, FL_DOWN_BOX);
194 fl_set_object_return(obj, FL_RETURN_END_CHANGED);
195 fl_set_object_callback(obj, C_Combox_input_cb, 0);
196 //fl_set_object_color(obj, FL_MCOL, FL_BLACK);
197 //fl_set_object_lalign(obj,FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
202 label->u_vdata = this;
203 button->u_vdata = this;
205 // Hmm, it seems fl_create_browser is broken in xforms 0.86.
206 // We have to work around that by creating the dropped browser form
207 // at this point already. However, this means that we have
208 // to do a little hacking: (Asger)
209 FL_FORM * current_form = fl_current_form;
212 bw = w + 20; bh = hmax - hmin - 12;
214 form = fl_bgn_form(FL_NO_BOX, bw, bh);
215 browser = obj = fl_add_browser(FL_HOLD_BROWSER, 0, 0, bw, bh, "");
216 fl_set_object_boxtype(obj, FL_UP_BOX);
217 fl_set_object_color(obj, FL_MCOL, FL_YELLOW);
218 fl_set_object_gravity(obj, NorthWestGravity, NorthWestGravity);
219 fl_set_object_callback(obj, C_Combox_combo_cb, 2);
221 browser->u_vdata = this;
222 form->u_vdata = browser;
223 fl_register_raw_callback(form,
224 ButtonPressMask|KeyPressMask,
225 C_Combox_peek_event);
227 // And revert to adding to the old form (Asger)
228 fl_addto_form(current_form);
232 static Window save_window;
235 void Combox::Redraw()
237 if (browser) fl_redraw_object(browser);
238 if (button) fl_redraw_object(button);
239 if (label) fl_redraw_object(label);
247 XGetInputFocus(fl_display, &save_window, &tmp); //BUG-Fix Dietmar
249 if (button && type != FL_COMBOX_NORMAL) {
250 fl_set_object_label(button, "@2<-");
251 fl_redraw_object(button);
253 int x = label->form->x + label->x, y = label->form->y + label->y;
254 fl_set_form_position(form, x, y + label->h);
255 fl_show_form(form, FL_PLACE_POSITION, FL_NOBORDER, "");
257 fl_set_browser_topline(browser, sel);
258 fl_select_browser_line(browser, sel);
260 XGrabPointer(fl_display, form->window, false,
261 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
262 GrabModeAsync, GrabModeAsync,
267 void Combox::Hide(int who)
269 if (!who && browser && label) {
270 sel = fl_get_browser(browser);
272 if (type == FL_COMBOX_INPUT)
273 fl_set_input(label, fl_get_browser_line(browser, sel));
275 fl_set_object_label(label,
276 fl_get_browser_line(browser, sel));
277 // if (callback) callback(sel, cb_arg);
279 XUngrabPointer(fl_display, 0);
281 if (!who && browser && label && callback)
282 callback(sel, cb_arg, this);
285 XSetInputFocus(fl_display, save_window,
286 RevertToParent, CurrentTime); // BUG-FIX-Dietmar
290 if (type != FL_COMBOX_NORMAL){
291 fl_set_object_label(button, "@2->");
292 fl_redraw_object(button);
299 void Combox::activate()
301 if (browser) fl_activate_object(browser);
302 if (button) fl_activate_object(button);
303 if (label) fl_activate_object(label);
307 void Combox::deactivate()
309 if (browser) fl_deactivate_object(browser);
310 if (button) fl_deactivate_object(button);
311 if (label) fl_deactivate_object(label);
314 void Combox::input_cb(FL_OBJECT *ob, long)
316 Combox * combo = static_cast<Combox*>(ob->u_vdata);
318 char const * text = fl_get_input(ob);
321 combo->is_empty = false;
324 extern "C" void C_Combox_input_cb(FL_OBJECT * ob, long data)
326 Combox::input_cb(ob, data);
330 void Combox::combo_cb(FL_OBJECT * ob, long data)
332 Combox * combo = static_cast<Combox*>(ob->u_vdata);
336 int i = combo->get();
337 switch (fl_get_button_numb(ob)) {
342 combo->callback(combo->sel,
343 combo->cb_arg, combo);
350 combo->callback(combo->sel,
351 combo->cb_arg, combo);
354 default: combo->Show(); break;
364 extern "C" void C_Combox_combo_cb(FL_OBJECT * ob, long data)
366 Combox::combo_cb(ob, data);
370 int Combox::peek_event(FL_FORM * form, void * xev)
372 FL_OBJECT * ob = static_cast<FL_OBJECT *>(form->u_vdata);
373 Combox * combo = static_cast<Combox*>(ob->u_vdata);
375 // I don't know why belowmouse does not work, but it doesn't. (Asger)
376 // Are we sure? Please verify. (Lgb)
377 if (static_cast<XEvent *>(xev)->type == ButtonPress && (
378 static_cast<XEvent *>(xev)->xbutton.x - ob->x < 0 ||
379 static_cast<XEvent *>(xev)->xbutton.x - ob->x > ob->w ||
380 static_cast<XEvent *>(xev)->xbutton.y - ob->y < 0 ||
381 static_cast<XEvent *>(xev)->xbutton.y - ob->y > ob->h)) {
386 if (static_cast<XEvent*>(xev)->type != KeyPress) return 0;
388 char s_r[10]; s_r[9] = '\0';
389 static int num_bytes;
390 KeySym keysym_return;
391 num_bytes = XLookupString(&static_cast<XEvent*>(xev)->xkey, s_r, 10,
394 switch (keysym_return) {
396 if (fl_get_browser(combo->browser) <
397 fl_get_browser_maxline(combo->browser))
398 fl_select_browser_line(combo->browser,
399 fl_get_browser(combo->browser)+1);
400 if (fl_get_browser(combo->browser)>=
401 fl_get_browser_topline(combo->browser) +
402 fl_get_browser_screenlines(combo->browser))
403 fl_set_browser_topline(combo->browser,
404 fl_get_browser(combo->browser)
405 - fl_get_browser_screenlines(combo->browser)+1);
406 if (fl_get_browser(combo->browser)<
407 fl_get_browser_topline(combo->browser))
408 fl_set_browser_topline(combo->browser,
409 fl_get_browser(combo->browser));
412 if (fl_get_browser(combo->browser) > 1)
413 fl_select_browser_line(combo->browser,
414 fl_get_browser(combo->browser)-1);
415 if (fl_get_browser(combo->browser)>=
416 fl_get_browser_topline(combo->browser) +
417 fl_get_browser_screenlines(combo->browser))
418 fl_set_browser_topline(combo->browser,
419 fl_get_browser(combo->browser)
420 - fl_get_browser_screenlines(combo->browser)+1);
421 if (fl_get_browser(combo->browser) <
422 fl_get_browser_topline(combo->browser))
423 fl_set_browser_topline(combo->browser,
424 fl_get_browser(combo->browser));
436 extern "C" int C_Combox_peek_event(FL_FORM * form, void *xev)
438 return Combox::peek_event(form, xev);
450 //Combox combo(FL_COMBOX_DROPLIST);
451 Combox combo(FL_COMBOX_INPUT);
455 FD_test *create_form_test(void)
458 FD_test *fdui = (FD_test *) fl_calloc(1, sizeof(*fdui));
460 fdui->test = fl_bgn_form(FL_NO_BOX, 320, 190);
461 obj = fl_add_box(FL_UP_BOX, 0, 0, 320, 190, "");
462 obj = fl_add_box(FL_DOWN_BOX, 10, 50, 300, 110, "");
463 obj = fl_add_button(FL_NORMAL_BUTTON, 250, 10, 50, 30, _("Done"));
464 combo.add(10, 15, 120, 25, 135);
472 fprintf(stderr, "selected %d:%s\n", i, combo.getline());
475 int main(int argc, char *argv[])
479 // Same defaults as in lyx
481 cntl.buttonFontSize = FL_NORMAL_SIZE;
482 cntl.browserFontSize = FL_NORMAL_SIZE;
483 cntl.labelFontSize = FL_NORMAL_SIZE;
484 cntl.choiceFontSize = FL_NORMAL_SIZE;
485 cntl.inputFontSize = FL_NORMAL_SIZE;
486 cntl.borderWidth = -2;
487 fl_set_defaults(FL_PDButtonFontSize, &cntl);
488 fl_set_defaults(FL_PDBrowserFontSize, &cntl);
489 fl_set_defaults(FL_PDLabelFontSize, &cntl);
490 fl_set_defaults(FL_PDChoiceFontSize, &cntl);
491 fl_set_defaults(FL_PDInputFontSize, &cntl);
492 fl_set_defaults(FL_PDBorderWidth, &cntl);
493 fl_initialize(&argc, argv, 0, 0, 0);
495 fd_test = create_form_test();
497 /* fill-in form initialization code */
498 combo.addline("Title");
499 combo.addline("Author");
500 combo.addline("Date");
501 combo.addline("Abstract");
502 combo.addline("Chapter");
503 combo.addline("Section");
504 combo.addline("Subsection");
505 combo.addline("List");
506 combo.addline("Description");
507 combo.addline("Verse");
508 combo.addline("Verbatim");
509 combo.setcallback(combo_cb);
512 /* show the first form */
513 fl_show_form(fd_test->test, FL_PLACE_CENTER, FL_FULLBORDER, "test");