WGroup: support state.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2019-11-17 17:02:52 +03:00
parent f0e13d8fba
commit d38eb77c8c
5 changed files with 157 additions and 72 deletions

View File

@ -505,10 +505,8 @@ dlg_init (WDialog * h)
group_set_current_widget_next (g);
widget_set_state (wh, WST_ACTIVE, TRUE);
widget_draw (wh);
/* focus found widget */
if (g->current != NULL)
widget_set_state (WIDGET (g->current->data), WST_FOCUSED, TRUE);
/* draw dialog and focus found widget */
widget_set_state (wh, WST_FOCUSED, TRUE);
h->ret_value = 0;
}

View File

@ -54,6 +54,12 @@ typedef struct
int scale_y;
} widget_shift_scale_t;
typedef struct
{
widget_state_t state;
gboolean enable;
} widget_state_info_t;
/*** file scope variables ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
@ -121,6 +127,16 @@ group_select_next_or_prev (WGroup * g, gboolean next)
}
}
/* --------------------------------------------------------------------------------------------- */
static void
group_widget_set_state (gpointer data, gpointer user_data)
{
widget_state_info_t *state = (widget_state_info_t *) user_data;
widget_set_state (WIDGET (data), state->state, state->enable);
}
/* --------------------------------------------------------------------------------------------- */
/**
* Send broadcast message to all widgets in the group that have specified options.
@ -525,6 +541,8 @@ group_init (WGroup * g, int y1, int x1, int lines, int cols, widget_cb_fn callba
w->find_by_type = group_default_find_by_type;
w->find_by_id = group_default_find_by_id;
w->set_state = group_default_set_state;
g->mouse_status = MOU_UNHANDLED;
}
@ -570,6 +588,49 @@ group_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm,
/* --------------------------------------------------------------------------------------------- */
/**
* Change state of group.
*
* @param w group
* @param state widget state flag to modify
* @param enable specifies whether to turn the flag on (TRUE) or off (FALSE).
* Only one flag per call can be modified.
* @return MSG_HANDLED if set was handled successfully, MSG_NOT_HANDLED otherwise.
*/
cb_ret_t
group_default_set_state (Widget * w, widget_state_t state, gboolean enable)
{
gboolean ret = MSG_HANDLED;
WGroup *g = GROUP (w);
widget_state_info_t st = {
.state = state,
.enable = enable
};
ret = widget_default_set_state (w, state, enable);
if (state == WST_ACTIVE || state == WST_SUSPENDED || state == WST_CLOSED)
/* inform all child widgets */
g_list_foreach (g->widgets, group_widget_set_state, &st);
if ((w->state & WST_ACTIVE) != 0)
{
if ((w->state & WST_FOCUSED) != 0)
{
/* update current widget */
if (g->current != NULL)
widget_set_state (WIDGET (g->current->data), WST_FOCUSED, enable);
}
else
/* inform all child widgets */
g_list_foreach (g->widgets, group_widget_set_state, &st);
}
return ret;
}
/* --------------------------------------------------------------------------------------------- */
/**
* Handling mouse events.
*

View File

@ -43,6 +43,7 @@ void group_init (WGroup * g, int y1, int x1, int lines, int cols, widget_cb_fn c
/* Default callback for groups */
cb_ret_t group_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm,
void *data);
cb_ret_t group_default_set_state (Widget * w, widget_state_t state, gboolean enable);
int group_handle_mouse_event (Widget * w, Gpm_Event * event);
unsigned long group_add_widget_autopos (WGroup * g, void *w, widget_pos_flags_t pos_flags,

View File

@ -316,6 +316,8 @@ widget_init (Widget * w, int y, int x, int lines, int cols,
w->find = widget_default_find;
w->find_by_type = widget_default_find_by_type;
w->find_by_id = widget_default_find_by_id;
w->set_state = widget_default_set_state;
}
/* --------------------------------------------------------------------------------------------- */
@ -377,73 +379,6 @@ widget_set_options (Widget * w, widget_options_t options, gboolean enable)
/* --------------------------------------------------------------------------------------------- */
/**
* Modify state of widget.
*
* @param w widget
* @param state widget state flag to modify
* @param enable specifies whether to turn the flag on (TRUE) or off (FALSE).
* Only one flag per call can be modified.
* @return MSG_HANDLED if set was handled successfully, MSG_NOT_HANDLED otherwise.
*/
cb_ret_t
widget_set_state (Widget * w, widget_state_t state, gboolean enable)
{
gboolean ret = MSG_HANDLED;
if (enable)
w->state |= state;
else
w->state &= ~state;
if (enable)
{
/* exclusive bits */
if ((state & WST_CONSTRUCT) != 0)
w->state &= ~(WST_ACTIVE | WST_SUSPENDED | WST_CLOSED);
else if ((state & WST_ACTIVE) != 0)
w->state &= ~(WST_CONSTRUCT | WST_SUSPENDED | WST_CLOSED);
else if ((state & WST_SUSPENDED) != 0)
w->state &= ~(WST_CONSTRUCT | WST_ACTIVE | WST_CLOSED);
else if ((state & WST_CLOSED) != 0)
w->state &= ~(WST_CONSTRUCT | WST_ACTIVE | WST_SUSPENDED);
}
if (w->owner == NULL)
return MSG_NOT_HANDLED;
switch (state)
{
case WST_DISABLED:
ret = send_message (w, NULL, enable ? MSG_DISABLE : MSG_ENABLE, 0, NULL);
if (ret == MSG_HANDLED && widget_get_state (WIDGET (w->owner), WST_ACTIVE))
ret = widget_draw (w);
break;
case WST_FOCUSED:
{
widget_msg_t msg;
msg = enable ? MSG_FOCUS : MSG_UNFOCUS;
ret = send_message (w, NULL, msg, 0, NULL);
if (ret == MSG_HANDLED && widget_get_state (WIDGET (w->owner), WST_ACTIVE))
{
widget_draw (w);
/* Notify owner that focus was moved from one widget to another */
send_message (w->owner, w, MSG_CHANGED_FOCUS, 0, NULL);
}
}
break;
default:
break;
}
return ret;
}
/* --------------------------------------------------------------------------------------------- */
void
widget_adjust_position (widget_pos_flags_t pos_flags, int *y, int *x, int *lines, int *cols)
{
@ -773,6 +708,74 @@ widget_default_find_by_id (const Widget * w, unsigned long id)
return (w->id == id ? WIDGET (w) : NULL);
}
/* --------------------------------------------------------------------------------------------- */
/**
* Default callback function to modify state of widget.
*
* @param w widget
* @param state widget state flag to modify
* @param enable specifies whether to turn the flag on (TRUE) or off (FALSE).
* Only one flag per call can be modified.
* @return MSG_HANDLED if set was handled successfully, MSG_NOT_HANDLED otherwise.
*/
cb_ret_t
widget_default_set_state (Widget * w, widget_state_t state, gboolean enable)
{
gboolean ret = MSG_HANDLED;
if (enable)
w->state |= state;
else
w->state &= ~state;
if (enable)
{
/* exclusive bits */
if ((state & WST_CONSTRUCT) != 0)
w->state &= ~(WST_ACTIVE | WST_SUSPENDED | WST_CLOSED);
else if ((state & WST_ACTIVE) != 0)
w->state &= ~(WST_CONSTRUCT | WST_SUSPENDED | WST_CLOSED);
else if ((state & WST_SUSPENDED) != 0)
w->state &= ~(WST_CONSTRUCT | WST_ACTIVE | WST_CLOSED);
else if ((state & WST_CLOSED) != 0)
w->state &= ~(WST_CONSTRUCT | WST_ACTIVE | WST_SUSPENDED);
}
if (w->owner == NULL)
return MSG_NOT_HANDLED;
switch (state)
{
case WST_DISABLED:
ret = send_message (w, NULL, enable ? MSG_DISABLE : MSG_ENABLE, 0, NULL);
if (ret == MSG_HANDLED && widget_get_state (WIDGET (w->owner), WST_ACTIVE))
ret = widget_draw (w);
break;
case WST_FOCUSED:
{
widget_msg_t msg;
msg = enable ? MSG_FOCUS : MSG_UNFOCUS;
ret = send_message (w, NULL, msg, 0, NULL);
if (ret == MSG_HANDLED && widget_get_state (WIDGET (w->owner), WST_ACTIVE))
{
widget_draw (w);
/* Notify owner that focus was moved from one widget to another */
send_message (w->owner, w, MSG_CHANGED_FOCUS, 0, NULL);
}
}
break;
default:
break;
}
return ret;
}
/* --------------------------------------------------------------------------------------------- */
/* get mouse pointer location within widget */

View File

@ -160,6 +160,10 @@ struct Widget
GList *(*find) (const Widget * w, const Widget * what);
Widget *(*find_by_type) (const Widget * w, widget_cb_fn cb);
Widget *(*find_by_id) (const Widget * w, unsigned long id);
/* *INDENT-OFF* */
cb_ret_t (*set_state) (Widget * w, widget_state_t state, gboolean enable);
/* *INDENT-ON* */
};
/* structure for label (caption) with hotkey, if original text does not contain
@ -198,7 +202,6 @@ void widget_destroy (Widget * w);
cb_ret_t widget_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm,
void *data);
void widget_set_options (Widget * w, widget_options_t options, gboolean enable);
cb_ret_t widget_set_state (Widget * w, widget_state_t state, gboolean enable);
void widget_adjust_position (widget_pos_flags_t pos_flags, int *y, int *x, int *lines, int *cols);
void widget_set_size (Widget * w, int y, int x, int lines, int cols);
/* select color for widget in dependance of state */
@ -217,6 +220,8 @@ GList *widget_default_find (const Widget * w, const Widget * what);
Widget *widget_default_find_by_type (const Widget * w, widget_cb_fn cb);
Widget *widget_default_find_by_id (const Widget * w, unsigned long id);
cb_ret_t widget_default_set_state (Widget * w, widget_state_t state, gboolean enable);
/* get mouse pointer location within widget */
Gpm_Event mouse_get_local (const Gpm_Event * global, const Widget * w);
gboolean mouse_global_in_widget (const Gpm_Event * event, const Widget * w);
@ -319,6 +324,23 @@ widget_find_by_id (const Widget * w, unsigned long id)
return w->find_by_id (w, id);
}
/* --------------------------------------------------------------------------------------------- */
/**
* Modify state of widget.
*
* @param w widget
* @param state widget state flag to modify
* @param enable specifies whether to turn the flag on (TRUE) or off (FALSE).
* Only one flag per call can be modified.
* @return MSG_HANDLED if set was handled successfully, MSG_NOT_HANDLED otherwise.
*/
static inline cb_ret_t
widget_set_state (Widget * w, widget_state_t state, gboolean enable)
{
return w->set_state (w, state, enable);
}
/* --------------------------------------------------------------------------------------------- */
/**
* Update cursor position in the specified widget.