From d38eb77c8cf25a544b302724b605e4713e4c4e29 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sun, 17 Nov 2019 17:02:52 +0300 Subject: [PATCH] WGroup: support state. Signed-off-by: Andrew Borodin --- lib/widget/dialog.c | 6 +- lib/widget/group.c | 61 +++++++++++++++++ lib/widget/group.h | 1 + lib/widget/widget-common.c | 137 +++++++++++++++++++------------------ lib/widget/widget-common.h | 24 ++++++- 5 files changed, 157 insertions(+), 72 deletions(-) diff --git a/lib/widget/dialog.c b/lib/widget/dialog.c index 4a92a030c..dd140afc5 100644 --- a/lib/widget/dialog.c +++ b/lib/widget/dialog.c @@ -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; } diff --git a/lib/widget/group.c b/lib/widget/group.c index cf960cbc5..f8e318bd9 100644 --- a/lib/widget/group.c +++ b/lib/widget/group.c @@ -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. * diff --git a/lib/widget/group.h b/lib/widget/group.h index ea129c6e2..f4485c265 100644 --- a/lib/widget/group.h +++ b/lib/widget/group.h @@ -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, diff --git a/lib/widget/widget-common.c b/lib/widget/widget-common.c index 8327921eb..635979b58 100644 --- a/lib/widget/widget-common.c +++ b/lib/widget/widget-common.c @@ -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 */ diff --git a/lib/widget/widget-common.h b/lib/widget/widget-common.h index c729e115c..94c55540b 100644 --- a/lib/widget/widget-common.h +++ b/lib/widget/widget-common.h @@ -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.