]> git.ozlabs.org Git - petitboot/blobdiff - ui/ncurses/nc-widgets.c
ui/ncurses/nc-widgets: Unify select key
[petitboot] / ui / ncurses / nc-widgets.c
index d96480e960ab4d54e876a75655f2909777c1e0cd..a6773cd39d34496b620c0e43953482b672b62cf9 100644 (file)
@@ -85,10 +85,12 @@ struct nc_widget {
        bool    (*process_key)(struct nc_widget *, FORM *, int);
        void    (*set_visible)(struct nc_widget *, bool);
        void    (*move)(struct nc_widget *, int, int);
+       void    (*field_focus)(struct nc_widget *, FIELD *);
        int     focussed_attr;
        int     unfocussed_attr;
        int     height;
        int     width;
+       int     focus_y;
        int     x;
        int     y;
 };
@@ -128,6 +130,12 @@ struct nc_widget_button {
 };
 
 static void widgetset_add_field(struct nc_widgetset *set, FIELD *field);
+static void widgetset_remove_field(struct nc_widgetset *set, FIELD *field);
+
+static bool key_is_select(int key)
+{
+       return key == ' ' || key == '\r' || key == '\n' || key == KEY_ENTER;
+}
 
 static bool process_key_nop(struct nc_widget *widget __attribute__((unused)),
                FORM *form __attribute((unused)),
@@ -203,7 +211,7 @@ static bool checkbox_process_key(struct nc_widget *widget,
 {
        struct nc_widget_checkbox *checkbox = to_checkbox(widget);
 
-       if (key != ' ')
+       if (!key_is_select(key))
                return false;
 
        checkbox->checked = !checkbox->checked;
@@ -358,13 +366,8 @@ static bool select_process_key(struct nc_widget *w, FORM *form, int key)
        int i, new_idx;
        FIELD *field;
 
-       switch (key) {
-       case ' ':
-       case KEY_ENTER:
-               break;
-       default:
+       if (!key_is_select(key))
                return false;
-       }
 
        field = current_field(form);
        new_opt = NULL;
@@ -414,6 +417,19 @@ static void select_move(struct nc_widget *widget, int y, int x)
                field_move(select->options[i].field, y + i, x);
 }
 
+static void select_field_focus(struct nc_widget *widget, FIELD *field)
+{
+       struct nc_widget_select *select = to_select(widget);
+       int i;
+
+       for (i = 0; i < select->n_options; i++) {
+               if (field != select->options[i].field)
+                       continue;
+               widget->focus_y = i;
+               return;
+       }
+}
+
 static int select_destructor(void *ptr)
 {
        struct nc_widget_select *select = ptr;
@@ -438,6 +454,7 @@ struct nc_widget_select *widget_new_select(struct nc_widgetset *set,
        select->widget.process_key = select_process_key;
        select->widget.set_visible = select_set_visible;
        select->widget.move = select_move;
+       select->widget.field_focus = select_field_focus;
        select->widget.focussed_attr = A_REVERSE;
        select->widget.unfocussed_attr = A_NORMAL;
        select->top = y;
@@ -510,6 +527,27 @@ void widget_select_on_change(struct nc_widget_select *select,
        select->on_change_arg = arg;
 }
 
+void widget_select_drop_options(struct nc_widget_select *select)
+{
+       struct nc_widgetset *set = select->set;
+       int i;
+
+       for (i = 0; i < select->n_options; i++) {
+               FIELD *field = select->options[i].field;
+               widgetset_remove_field(set, field);
+               if (field == set->cur_field)
+                       set->cur_field = NULL;
+               free_field(select->options[i].field);
+       }
+
+       talloc_free(select->options);
+       select->options = NULL;
+       select->n_options = 0;
+       select->widget.height = 0;
+       select->widget.focus_y = 0;
+
+}
+
 static bool button_process_key(struct nc_widget *widget,
                FORM *form __attribute__((unused)), int key)
 {
@@ -518,15 +556,11 @@ static bool button_process_key(struct nc_widget *widget,
        if (!button->click)
                return false;
 
-       switch (key) {
-       case ' ':
-       case '\r':
-       case '\n':
-               button->click(button->arg);
-               return true;
-       }
+       if (!key_is_select(key))
+               return false;
 
-       return false;
+       button->click(button->arg);
+       return true;
 }
 
 static int button_destructor(void *ptr)
@@ -622,6 +656,8 @@ bool widgetset_process_key(struct nc_widgetset *set, int key)
                field = current_field(set->form);
                widget = field_userptr(field);
                widget_focus_change(widget, field, true);
+               if (widget->field_focus)
+                       widget->field_focus(widget, field);
                if (set->widget_focus)
                        set->widget_focus(widget, set->widget_focus_arg);
                return true;
@@ -654,6 +690,13 @@ struct nc_widgetset *widgetset_create(void *ctx, WINDOW *main, WINDOW *sub)
        return set;
 }
 
+void widgetset_set_windows(struct nc_widgetset *set,
+               WINDOW *main, WINDOW *sub)
+{
+       set->mainwin = main;
+       set->subwin = sub;
+}
+
 void widgetset_set_widget_focus(struct nc_widgetset *set,
                widget_focus_cb cb, void *arg)
 {
@@ -705,6 +748,23 @@ static void widgetset_add_field(struct nc_widgetset *set, FIELD *field)
        set->fields[set->n_fields] = NULL;
 }
 
+static void widgetset_remove_field(struct nc_widgetset *set, FIELD *field)
+{
+       int i;
+
+       for (i = 0; i < set->n_fields; i++) {
+               if (set->fields[i] == field)
+                       break;
+       }
+
+       if (i == set->n_fields)
+               return;
+
+       memmove(&set->fields[i], &set->fields[i+i],
+                       (set->n_fields - i) * sizeof(set->fields[i]));
+       set->n_fields--;
+}
+
 #define DECLARE_BASEFN(type) \
        struct nc_widget *widget_ ## type ## _base              \
                (struct nc_widget_ ## type *w)                  \
@@ -755,3 +815,8 @@ int widget_y(struct nc_widget *widget)
        return widget->y;
 }
 
+int widget_focus_y(struct nc_widget *widget)
+{
+       return widget->focus_y;
+}
+