/**
* \file combox.c
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
*
* \author Alejandro Aguilar Sierra
+ * \author Lars Gullik Bjønnes
+ * \author Jean-Marc Lasgouttes
* \author Angus Leeming
*
+ * Full author contact details are available in file CREDITS
+ *
* This is a rewrite of Alejandro's C++ Combox class, originally written
* for LyX in 1996. The rewrite turns it into a native xforms widget.
*/
#include <config.h>
-#include FORMS_H_LOCATION
+#include "lyx_forms.h"
#include "combox.h"
#include "freebrowser.h"
-
extern void fl_add_child(FL_OBJECT *, FL_OBJECT *);
extern void fl_addto_freelist(void *);
/** A pointer to the parent widget */
FL_OBJECT * combox;
- FL_FREEBROWSER * browser;
+ FL_FREEBROWSER * freebrowser;
int browser_height;
/** The browser will be displayed either below or above the main body. */
static void attrib_change(COMBOX_SPEC * sp);
-FL_OBJECT * fl_create_combox(int type,
- FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
- char const * label)
+FL_OBJECT *
+fl_create_combox(FL_COMBOX_TYPE type,
+ FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
+ char const * label)
{
FL_OBJECT * ob;
FL_OBJECT * button;
FL_Coord const ws = 0.7 * h;
FL_Coord const xs = x + w - ws;
+ /* The width of button_chosen */
+ FL_Coord const wc = (type == FL_DROPLIST_COMBOX) ? (w - ws) : w;
+
ob = fl_make_object(FL_COMBOX, type, x, y, w, h, label, combox_handle);
ob->align = FL_ALIGN_LEFT;
sp->browser_height = 100;
sp->browser_position = FL_FREEBROWSER_BELOW;
- sp->browser = fl_create_freebrowser(sp);
- sp->browser->callback = update_button_chosen;
+ sp->freebrowser = fl_create_freebrowser(sp);
+ sp->freebrowser->callback = update_button_chosen;
- sp->button_state = fl_add_button(FL_NORMAL_BUTTON, xs, y, ws, h, "");
+ sp->button_state = 0;
+ if (type == FL_DROPLIST_COMBOX) {
+ sp->button_state = fl_add_button(FL_NORMAL_BUTTON, xs, y, ws, h, "");
- button = sp->button_state;
- fl_set_object_lalign(button, FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
- fl_set_object_callback(button, state_cb, 0);
- fl_set_object_posthandler(button, combox_post);
- fl_set_object_prehandler(button, combox_pre);
- set_state_label(sp, COMBOX_CLOSED);
+ button = sp->button_state;
+ fl_set_object_lalign(button, FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
+ fl_set_object_callback(button, state_cb, 0);
+ fl_set_object_posthandler(button, combox_post);
+ fl_set_object_prehandler(button, combox_pre);
+ set_state_label(sp, COMBOX_CLOSED);
- set_activation(button, DEACTIVATE);
- button->parent = ob;
- button->u_vdata = sp;
+ set_activation(button, DEACTIVATE);
+ button->parent = ob;
+ button->u_vdata = sp;
+ }
- sp->button_chosen = fl_add_button(FL_NORMAL_TEXT, x, y, (w - ws), h, "");
+ sp->button_chosen = fl_add_button(FL_NORMAL_TEXT, x, y, wc, h, "");
button = sp->button_chosen;
fl_set_object_boxtype(button, FL_FRAME_BOX);
}
-FL_OBJECT * fl_add_combox(int type,
- FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
- char const * label)
+FL_OBJECT *
+fl_add_combox(FL_COMBOX_TYPE type,
+ FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
+ char const * label)
{
FL_OBJECT * ob = fl_create_combox(type, x, y, w, h, label);
COMBOX_SPEC * sp = ob->spec;
- fl_add_child(ob, sp->button_state);
+ if (sp->button_state)
+ fl_add_child(ob, sp->button_state);
fl_add_child(ob, sp->button_chosen);
fl_add_object(fl_current_form, ob);
}
-void fl_set_combox_browser_height(FL_OBJECT * ob, int bh)
+void
+fl_set_combox_browser_height(FL_OBJECT * ob, int bh)
{
COMBOX_SPEC * sp;
}
-void fl_set_combox_position(FL_OBJECT * ob, int position)
+void
+fl_set_combox_position(FL_OBJECT * ob, FL_COMBOX_POSITION position)
{
COMBOX_SPEC * sp;
return;
sp = ob->spec;
- sp->browser_position = (position == FL_FREEBROWSER_ABOVE) ?
+ sp->browser_position = (position == FL_COMBOX_ABOVE) ?
FL_FREEBROWSER_ABOVE : FL_FREEBROWSER_BELOW;
set_state_label(sp, COMBOX_CLOSED);
}
-void fl_clear_combox(FL_OBJECT * ob)
+void
+fl_clear_combox(FL_OBJECT * ob)
{
COMBOX_SPEC * sp;
FL_OBJECT * browser;
return;
sp = ob->spec;
- browser = fl_get_freebrowser_browser(sp->browser);
+ browser = sp->freebrowser->browser;
fl_clear_browser(browser);
fl_set_object_label(sp->button_chosen, "");
}
-void fl_addto_combox(FL_OBJECT * ob, char const * text)
+void
+fl_addto_combox(FL_OBJECT * ob, char const * text)
{
COMBOX_SPEC * sp;
FL_OBJECT * browser;
return;
sp = ob->spec;
- browser = fl_get_freebrowser_browser(sp->browser);
+ browser = sp->freebrowser->browser;
/* Split the string on '|' boundaries. */
i = j = 0;
}
}
- if (j != 0)
- {
+ if (j != 0) {
line[j] = '\0';
fl_add_browser_line(browser, line);
- }
+ }
/* By default the first item is selected */
- if (!fl_get_browser(browser)) {
- fl_set_object_label(sp->button_chosen, text);
+ if (fl_get_browser_maxline(browser)) {
+ char const * const label = fl_get_browser_line(browser, 1);
+ fl_set_object_label(sp->button_chosen, label);
+ fl_select_browser_line(browser, 1);
set_activation(sp->button_chosen, ACTIVATE);
- set_activation(sp->button_state, ACTIVATE);
+ if (sp->button_state)
+ set_activation(sp->button_state, ACTIVATE);
}
}
-void fl_set_combox(FL_OBJECT * ob, int sel)
+void
+fl_set_combox(FL_OBJECT * ob, int sel)
{
COMBOX_SPEC * sp;
FL_OBJECT * browser;
return;
sp = ob->spec;
- browser = fl_get_freebrowser_browser(sp->browser);
+ browser = sp->freebrowser->browser;
if (sel < 1 || sel > fl_get_browser_maxline(browser))
return;
}
-int fl_get_combox(FL_OBJECT * ob)
+int
+fl_get_combox(FL_OBJECT * ob)
{
COMBOX_SPEC * sp;
FL_OBJECT * browser;
return 0;
sp = ob->spec;
- browser = fl_get_freebrowser_browser(sp->browser);
+ browser = sp->freebrowser->browser;
return fl_get_browser(browser);
}
-char const * fl_get_combox_text(FL_OBJECT * ob)
+char const *
+fl_get_combox_text(FL_OBJECT * ob)
{
COMBOX_SPEC * sp;
}
-char const * fl_get_combox_line(FL_OBJECT * ob, int line)
+char const *
+fl_get_combox_line(FL_OBJECT * ob, int line)
{
COMBOX_SPEC * sp;
FL_OBJECT * browser;
return 0;
sp = ob->spec;
- browser = fl_get_freebrowser_browser(sp->browser);
+ browser = sp->freebrowser->browser;
maxlines = fl_get_browser_maxline(browser);
if (line > maxlines)
}
-int fl_get_combox_maxitems(FL_OBJECT * ob)
+int
+fl_get_combox_maxitems(FL_OBJECT * ob)
{
COMBOX_SPEC * sp;
FL_OBJECT * browser;
return 0;
sp = ob->spec;
- browser = fl_get_freebrowser_browser(sp->browser);
+ browser = sp->freebrowser->browser;
return fl_get_browser_maxline(browser);
}
-void fl_show_combox_browser(FL_OBJECT * ob)
+void
+fl_show_combox_browser(FL_OBJECT * ob)
{
if (!ob || ob->objclass != FL_COMBOX)
return;
}
-void fl_hide_combox_browser(FL_OBJECT * ob)
+void
+fl_hide_combox_browser(FL_OBJECT * ob)
{
COMBOX_SPEC * sp;
return;
sp = ob->spec;
- fl_free_freebrowser(sp->browser);
+ fl_free_freebrowser(sp->freebrowser);
}
-static int combox_pre(FL_OBJECT * ob, int ev, FL_Coord mx, FL_Coord my,
- int key, void *xev)
+static int
+combox_pre(FL_OBJECT * ob, int ev, FL_Coord mx, FL_Coord my, int key,
+ void * xev)
{
COMBOX_SPEC * sp = ob->u_vdata;
FL_OBJECT * combox = sp->combox;
}
-static int combox_post(FL_OBJECT * ob, int ev, FL_Coord mx, FL_Coord my,
- int key, void *xev)
+static int
+combox_post(FL_OBJECT * ob, int ev, FL_Coord mx, FL_Coord my, int key,
+ void * xev)
{
COMBOX_SPEC * sp = ob->u_vdata;
FL_OBJECT * combox = sp->combox;
}
-static int combox_handle(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my,
- int key, void * ev)
+static int
+combox_handle(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my, int key,
+ void * ev)
{
if (!ob || ob->objclass != FL_COMBOX)
return 0;
case FL_DRAW:
attrib_change(ob->spec);
/* Fall through */
- case FL_DRAWLABEL:
+ case FL_DRAWLABEL: {
+ COMBOX_SPEC * sp = ob->spec;
+
+ int change =
+ ob->x != sp->button_chosen->x ||
+ ob->y != sp->button_chosen->y;
+
+ FL_Coord xbs = 0;
+ if (sp->button_state) {
+ xbs = ob->x + (sp->button_state->x - sp->button_chosen->x);
+ change = change ||
+ xbs != sp->button_state->x ||
+ ob->y != sp->button_state->y;
+ }
+
+ if (change) {
+ fl_freeze_form(ob->form);
+ fl_set_object_position(sp->button_chosen, ob->x, ob->y);
+ if (sp->button_state)
+ fl_set_object_position(sp->button_state, xbs, ob->y);
+ fl_unfreeze_form(ob->form);
+ }
+
fl_draw_object_label(ob);
- break;
- case FL_SHORTCUT:
+ break;
+ } case FL_SHORTCUT:
show_browser(ob->spec);
break;
case FL_FREEMEM: {
COMBOX_SPEC * sp = ob->spec;
- fl_free_freebrowser(sp->browser);
+ fl_free_freebrowser(sp->freebrowser);
/* children take care of themselves, but we must make sure that
sp itself is free-d eventually. */
fl_addto_freelist(sp);
}
-static void set_activation(FL_OBJECT * ob, int activation)
+static void
+set_activation(FL_OBJECT * ob, int activation)
{
switch (activation) {
case ACTIVATE:
}
-static void show_browser(COMBOX_SPEC * sp)
+static void
+show_browser(COMBOX_SPEC * sp)
{
FL_OBJECT * ob = sp->combox;
abs_y += (sp->browser_position == FL_FREEBROWSER_BELOW) ? ob->h : -bh;
set_state_label(sp, COMBOX_OPEN);
- fl_show_freebrowser(sp->browser, abs_x, abs_y, bw, bh);
+ fl_show_freebrowser(sp->freebrowser, abs_x, abs_y, bw, bh);
}
-static void state_cb(FL_OBJECT * ob, long data)
+static void
+state_cb(FL_OBJECT * ob, long data)
{
show_browser(ob->u_vdata);
}
-static void chosen_cb(FL_OBJECT * ob, long data)
+static void
+chosen_cb(FL_OBJECT * ob, long data)
{
show_browser(ob->u_vdata);
}
-static void update_button_chosen(FL_FREEBROWSER * fb, int action)
+static void
+update_button_chosen(FL_FREEBROWSER * fb, int action)
{
COMBOX_SPEC * sp = fb->parent;
- FL_OBJECT * browser = fl_get_freebrowser_browser(sp->browser);
+ FL_OBJECT * browser = sp->freebrowser->browser;
FL_OBJECT * combox = sp->combox;
if (!browser || !combox) return;
}
-static void set_state_label(COMBOX_SPEC * sp, int state)
+static void
+set_state_label(COMBOX_SPEC * sp, int state)
{
char const * const up = "@2<-";
char const * const down = "@2->";
char const * label = 0;
+
+ if (!sp->button_state)
+ return;
+
if (sp->browser_position == FL_FREEBROWSER_BELOW) {
label = (state == COMBOX_OPEN) ? up : down;
} else {
}
-static void attrib_change(COMBOX_SPEC * sp)
+static void
+attrib_change(COMBOX_SPEC * sp)
{
FL_OBJECT * parent = sp->combox;
FL_OBJECT * button = sp->button_chosen;
button->col2 = parent->col2;
button->bw = parent->bw;
- button = sp->button_state;
+ if (sp->button_state) {
+ button = sp->button_state;
- /* The boxtype is not changed */
- button->col1 = parent->col1;
- button->col2 = parent->col2;
- button->bw = parent->bw;
+ /* The boxtype is not changed */
+ button->col1 = parent->col1;
+ button->col2 = parent->col2;
+ button->bw = parent->bw;
+ }
}