Allow add and remove widgets in runtime.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2011-04-17 14:21:17 +04:00
parent 33d25a0c8f
commit 6ad4b2466b
4 changed files with 133 additions and 39 deletions

View File

@ -178,23 +178,22 @@ dlg_read_history (Dlg_head * h)
/* --------------------------------------------------------------------------------------------- */
static int
static gboolean
dlg_unfocus (Dlg_head * h)
{
/* ... but can unfocus disabled widget */
if ((h->current != NULL) && (h->state == DLG_ACTIVE))
/* we can unfocus disabled widget */
if ((h->current != NULL) && (h->state == DLG_CONSTRUCT || h->state == DLG_ACTIVE))
{
Widget *current = (Widget *) h->current->data;
if (send_message (current, WIDGET_UNFOCUS, 0) == MSG_HANDLED)
{
h->callback (h, current, DLG_UNFOCUS, 0, NULL);
return 1;
return TRUE;
}
}
return 0;
return FALSE;
}
/* --------------------------------------------------------------------------------------------- */
@ -759,6 +758,7 @@ create_dlg (gboolean modal, int y1, int x1, int lines, int cols,
Dlg_head *new_d;
new_d = g_new0 (Dlg_head, 1);
new_d->state = DLG_CONSTRUCT;
new_d->modal = modal;
if (colors != NULL)
memmove (new_d->color, colors, sizeof (dlg_colors_t));
@ -832,12 +832,11 @@ set_idle_proc (Dlg_head * d, int enable)
/* --------------------------------------------------------------------------------------------- */
/**
* Insert widget to dialog before current widget. For dialogs populated
* from the bottom, make the widget current. Return widget number.
* Insert widget to dialog before requested widget. Make the widget current. Return widget ID.
*/
int
add_widget_autopos (Dlg_head * h, void *w, widget_pos_flags_t pos_flags)
unsigned long
add_widget_autopos (Dlg_head * h, void *w, widget_pos_flags_t pos_flags, const void *before)
{
Widget *widget = (Widget *) w;
@ -852,11 +851,59 @@ add_widget_autopos (Dlg_head * h, void *w, widget_pos_flags_t pos_flags)
widget->id = h->widget_id++;
if ((h->flags & DLG_REVERSE) != 0)
h->widgets = g_list_prepend (h->widgets, widget);
else
h->widgets = g_list_append (h->widgets, widget);
{
if (h->widgets == NULL || before == NULL)
{
h->widgets = g_list_prepend (h->widgets, widget);
h->current = h->widgets;
}
else
{
GList *b;
h->current = h->widgets;
b = g_list_find (h->widgets, before);
/* don't accept widget not from dialog. This shouldn't happen */
if (b == NULL)
abort ();
h->widgets = g_list_insert_before (h->widgets, b, widget);
h->current = g_list_previous (b);
}
}
else
{
if (h->widgets == NULL || before == NULL)
{
h->widgets = g_list_append (h->widgets, widget);
h->current = g_list_last (h->widgets);
}
else
{
GList *b;
b = g_list_find (h->widgets, before);
/* don't accept widget not from dialog. This shouldn't happen */
if (b == NULL)
abort ();
b = g_list_next (b);
h->widgets = g_list_insert_before (h->widgets, b, widget);
if (b != NULL)
h->current = g_list_previous (b);
else
h->current = g_list_last (h->widgets);
}
}
/* widget has been added in runtime */
if (h->state == DLG_ACTIVE)
{
send_message (widget, WIDGET_INIT, 0);
send_message (widget, WIDGET_DRAW, 0);
send_message (widget, WIDGET_FOCUS, 0);
}
return widget->id;
}
@ -864,10 +911,53 @@ add_widget_autopos (Dlg_head * h, void *w, widget_pos_flags_t pos_flags)
/* --------------------------------------------------------------------------------------------- */
/** wrapper to simply add lefttop positioned controls */
int
unsigned long
add_widget (Dlg_head * h, void *w)
{
return add_widget_autopos (h, w, WPOS_KEEP_LEFT | WPOS_KEEP_TOP);
return add_widget_autopos (h, w, WPOS_KEEP_LEFT | WPOS_KEEP_TOP,
h->current != NULL ? h->current->data : NULL);
}
/* --------------------------------------------------------------------------------------------- */
unsigned long
add_widget_before (Dlg_head * h, void *w, void *before)
{
return add_widget_autopos (h, w, WPOS_KEEP_LEFT | WPOS_KEEP_TOP, before);
}
/* --------------------------------------------------------------------------------------------- */
/** delete widget from dialog */
void
del_widget (void *w)
{
Dlg_head *h = ((Widget *) w)->owner;
GList *d;
/* Don't accept NULL widget. This shouldn't happen */
if (w == NULL)
abort ();
d = g_list_find (h->widgets, w);
if (d == h->current)
{
if ((h->flags & DLG_REVERSE) != 0)
h->current = dlg_widget_prev (h, d);
else
h->current = dlg_widget_next (h, d);
}
h->widgets = g_list_remove_link (h->widgets, d);
send_message (d->data, WIDGET_DESTROY, 0);
g_list_free_1 (d);
/* widget has been deleted in runtime */
if (h->state == DLG_ACTIVE)
{
dlg_redraw (h);
dlg_focus (h);
}
}
/* --------------------------------------------------------------------------------------------- */
@ -906,12 +996,11 @@ dlg_broadcast_msg (Dlg_head * h, widget_msg_t msg, gboolean reverse)
/* --------------------------------------------------------------------------------------------- */
int
gboolean
dlg_focus (Dlg_head * h)
{
/* cannot focus disabled widget ... */
if ((h->current != NULL) && (h->state == DLG_ACTIVE))
/* cannot focus disabled widget */
if ((h->current != NULL) && (h->state == DLG_CONSTRUCT || h->state == DLG_ACTIVE))
{
Widget *current = (Widget *) h->current->data;
@ -919,11 +1008,11 @@ dlg_focus (Dlg_head * h)
&& (send_message (current, WIDGET_FOCUS, 0) == MSG_HANDLED))
{
h->callback (h, current, DLG_FOCUS, 0, NULL);
return 1;
return TRUE;
}
}
return 0;
return FALSE;
}
/* --------------------------------------------------------------------------------------------- */
@ -1085,7 +1174,7 @@ init_dlg (Dlg_head * h)
top_dlg = g_list_prepend (top_dlg, h);
/* Initialize dialog manager and widgets */
if (h->state == DLG_ACTIVE)
if (h->state == DLG_CONSTRUCT)
{
if (!h->modal)
dialog_switch_add (h);
@ -1095,14 +1184,13 @@ init_dlg (Dlg_head * h)
dlg_read_history (h);
}
h->state = DLG_ACTIVE;
dlg_redraw (h);
/* Select the first widget that takes focus */
while (h->current != NULL && !dlg_focus (h))
h->current = dlg_widget_next (h, h->current);
h->state = DLG_ACTIVE;
dlg_redraw (h);
h->ret_value = 0;
}
@ -1265,7 +1353,8 @@ dlg_replace_widget (Widget * old_w, Widget * new_w)
if (should_focus)
dlg_select_widget (new_w);
send_message (new_w, WIDGET_DRAW, 0);
if (new_w->owner->state == DLG_ACTIVE)
send_message (new_w, WIDGET_DRAW, 0);
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -62,9 +62,10 @@ typedef enum
/* Dialog state */
typedef enum
{
DLG_ACTIVE = 0, /* Dialog is visible and active */
DLG_SUSPENDED = 1, /* Dialog is suspended */
DLG_CLOSED = 2 /* Dialog is closed */
DLG_CONSTRUCT = 0, /* DIalog has been constructed but bot run yet */
DLG_ACTIVE = 1, /* Dialog is visible and active */
DLG_SUSPENDED = 2, /* Dialog is suspended */
DLG_CLOSED = 3 /* Dialog is closed */
} dlg_state_t;
/* Dialog color constants */
@ -159,8 +160,11 @@ Dlg_head *create_dlg (gboolean modal, int y1, int x1, int lines, int cols,
void dlg_set_default_colors (void);
int add_widget_autopos (Dlg_head * dest, void *w, widget_pos_flags_t pos_flags);
int add_widget (Dlg_head * dest, void *w);
unsigned long add_widget_autopos (Dlg_head * dest, void *w, widget_pos_flags_t pos_flags,
const void *before);
unsigned long add_widget (Dlg_head * dest, void *w);
unsigned long add_widget_before (Dlg_head * h, void *w, void *before);
void del_widget (void *w);
/* sets size of dialog, leaving positioning to automatic mehtods
according to dialog flags */
@ -200,7 +204,7 @@ void dlg_stop (Dlg_head * h);
void dlg_select_widget (void *widget);
void dlg_one_up (Dlg_head * h);
void dlg_one_down (Dlg_head * h);
int dlg_focus (Dlg_head * h);
gboolean dlg_focus (Dlg_head * h);
Widget *find_widget_type (const Dlg_head * h, callback_fn callback);
Widget *dlg_find_by_id (const Dlg_head * h, unsigned long id);
void dlg_select_by_id (const Dlg_head * h, unsigned long id);

View File

@ -328,7 +328,7 @@ history_show (GList ** history, Widget * widget)
/* this call makes list stick to all sides of dialog, effectively make
it be resized with dialog */
add_widget_autopos (query_dlg, query_list, WPOS_KEEP_ALL);
add_widget_autopos (query_dlg, query_list, WPOS_KEEP_ALL, NULL);
/* to avoid diplicating of (calculating sizes in two places)
code, call dlg_hist_callback function here, to set dialog and

View File

@ -788,7 +788,8 @@ init_hotlist (int list_type)
hotlist_but[i].ret_cmd,
hotlist_but[i].flags,
hotlist_but[i].text,
hotlist_button_callback), hotlist_but[i].pos_flags);
hotlist_button_callback), hotlist_but[i].pos_flags,
NULL);
}
/* We add the labels.
@ -796,7 +797,7 @@ init_hotlist (int list_type)
* pname_group will hold name of current group
*/
pname = label_new (UY - 11 + LINES, UX + 2, "");
add_widget_autopos (hotlist_dlg, pname, WPOS_KEEP_BOTTOM | WPOS_KEEP_LEFT);
add_widget_autopos (hotlist_dlg, pname, WPOS_KEEP_BOTTOM | WPOS_KEEP_LEFT, NULL);
if (!hotlist_state.moving)
{
char label_text[BUF_TINY];
@ -804,7 +805,7 @@ init_hotlist (int list_type)
g_snprintf (label_text, sizeof (label_text), " %s ", _("Directory path"));
add_widget_autopos (hotlist_dlg,
label_new (UY - 12 + LINES, UX + 2,
label_text), WPOS_KEEP_BOTTOM | WPOS_KEEP_LEFT);
label_text), WPOS_KEEP_BOTTOM | WPOS_KEEP_LEFT, NULL);
/* This one holds the displayed pathname */
pname_group = label_new (UY, UX + 2, _("Directory label"));
@ -824,7 +825,7 @@ init_hotlist (int list_type)
#endif /* !ENABLE_VFS */
fill_listbox ();
add_widget_autopos (hotlist_dlg, l_hotlist, WPOS_KEEP_ALL);
add_widget_autopos (hotlist_dlg, l_hotlist, WPOS_KEEP_ALL, NULL);
/* add listbox to the dialogs */
}