[recipes] Add a search/filter list for adding ingredients
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes] Add a search/filter list for adding ingredients
- Date: Fri, 23 Dec 2016 15:38:21 +0000 (UTC)
commit 4c743dcd918165c6469ce6d8d994e7bba0ceca0e
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Dec 22 21:42:02 2016 -0500
Add a search/filter list for adding ingredients
This works similarly to our main search filtering, with
some small differences.
src/gr-edit-page.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/gr-edit-page.ui | 110 +++++++++++++++++++++++++++++---------
2 files changed, 226 insertions(+), 31 deletions(-)
---
diff --git a/src/gr-edit-page.c b/src/gr-edit-page.c
index 65133a3..a02b085 100644
--- a/src/gr-edit-page.c
+++ b/src/gr-edit-page.c
@@ -34,6 +34,8 @@
#include "gr-season.h"
#include "gr-images.h"
#include "gr-image-viewer.h"
+#include "gr-ingredient-row.h"
+#include "gr-ingredient.h"
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
@@ -81,12 +83,19 @@ struct _GrEditPage
GtkWidget *author_label;
GtkWidget *ingredients_box;
+ GtkWidget *ing_list;
+ GtkWidget *ing_search_button;
+ GtkWidget *ing_search_button_label;
+ GtkWidget *ing_search_revealer;
+
GtkSizeGroup *group;
guint account_response_signal_id;
GList *segments;
GtkWidget *active_row;
+
+ char *ing_term;
};
G_DEFINE_TYPE (GrEditPage, gr_edit_page, GTK_TYPE_BOX)
@@ -144,6 +153,8 @@ edit_page_finalize (GObject *object)
g_clear_object (&self->group);
g_list_free (self->segments);
+ g_free (self->ing_term);
+
G_OBJECT_CLASS (gr_edit_page_parent_class)->finalize (object);
}
@@ -203,6 +214,9 @@ ingredient_changed (GrEditPage *page)
gtk_widget_set_sensitive (page->new_ingredient_add_button, strlen (text) > 0);
}
+static void hide_ingredients_search_list (GrEditPage *self,
+ gboolean animate);
+
static void
add_ingredient (GtkButton *button, GrEditPage *page)
{
@@ -213,6 +227,8 @@ add_ingredient (GtkButton *button, GrEditPage *page)
gtk_popover_set_relative_to (GTK_POPOVER (page->ingredient_popover), GTK_WIDGET (button));
gtk_button_set_label (GTK_BUTTON (page->new_ingredient_add_button), _("Add"));
ingredient_changed (page);
+
+ hide_ingredients_search_list (page, FALSE);
gtk_popover_popup (GTK_POPOVER (page->ingredient_popover));
}
@@ -244,12 +260,14 @@ edit_ingredients_row (GtkListBoxRow *row,
ingredient = (const char *)g_object_get_data (G_OBJECT (row), "ingredient");
gtk_entry_set_text (GTK_ENTRY (page->new_ingredient_name), ingredient);
+ gtk_label_set_label (GTK_LABEL (page->ing_search_button_label), ingredient);
gtk_entry_set_text (GTK_ENTRY (page->new_ingredient_amount), amount);
gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (page->new_ingredient_unit))), unit);
gtk_popover_set_relative_to (GTK_POPOVER (page->ingredient_popover), GTK_WIDGET (row));
gtk_button_set_label (GTK_BUTTON (page->new_ingredient_add_button), _("Apply"));
ingredient_changed (page);
+ hide_ingredients_search_list (page, FALSE);
gtk_popover_popup (GTK_POPOVER (page->ingredient_popover));
}
@@ -399,7 +417,7 @@ static void
add_ingredient2 (GtkButton *button, GrEditPage *page)
{
const char *ingredient;
- double amount;
+ const char *amount;
const char *unit;
g_autofree char *s = NULL;
GtkWidget *list;
@@ -418,10 +436,9 @@ add_ingredient2 (GtkButton *button, GrEditPage *page)
}
ingredient = gtk_entry_get_text (GTK_ENTRY (page->new_ingredient_name));
- amount = gtk_spin_button_get_value (GTK_SPIN_BUTTON (page->new_ingredient_amount));
+ amount = gtk_entry_get_text (GTK_ENTRY (page->new_ingredient_amount));
unit = gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (page->new_ingredient_unit))));
- s = g_strdup_printf ("%g", amount);
- update_ingredient_row (row, s, unit, ingredient);
+ update_ingredient_row (row, amount, unit, ingredient);
}
static char *
@@ -475,6 +492,118 @@ all_headers (GtkListBoxRow *row,
}
static void
+show_ingredients_search_list (GrEditPage *self)
+{
+ gtk_widget_hide (self->ing_search_button);
+ gtk_widget_show (self->ing_search_revealer);
+ gtk_revealer_set_reveal_child (GTK_REVEALER (self->ing_search_revealer), TRUE);
+}
+
+static void
+hide_ingredients_search_list (GrEditPage *self,
+ gboolean animate)
+{
+ gtk_widget_show (self->ing_search_button);
+ if (!animate)
+ gtk_revealer_set_transition_type (GTK_REVEALER (self->ing_search_revealer),
+ GTK_REVEALER_TRANSITION_TYPE_NONE);
+ gtk_revealer_set_reveal_child (GTK_REVEALER (self->ing_search_revealer), FALSE);
+ if (!animate)
+ gtk_revealer_set_transition_type (GTK_REVEALER (self->ing_search_revealer),
+ GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN);
+}
+
+static void
+ing_search_button_clicked (GtkButton *button,
+ GrEditPage *self)
+{
+ show_ingredients_search_list (self);
+}
+
+static void
+ing_row_activated (GtkListBox *list,
+ GtkListBoxRow *row,
+ GrEditPage *self)
+{
+ const char *ingredient;
+
+ ingredient = gr_ingredient_row_get_ingredient (GR_INGREDIENT_ROW (row));
+ gtk_entry_set_text (GTK_ENTRY (self->new_ingredient_name), ingredient);
+ gtk_label_set_label (GTK_LABEL (self->ing_search_button_label), ingredient);
+ hide_ingredients_search_list (self, TRUE);
+}
+
+static gboolean
+ing_filter_func (GtkListBoxRow *row,
+ gpointer data)
+{
+ GrEditPage *self = data;
+ const char *cf;
+
+ if (!GR_IS_INGREDIENT_ROW (row))
+ return TRUE;
+
+ if (!self->ing_term)
+ return TRUE;
+
+ cf = gr_ingredient_row_get_filter_term (GR_INGREDIENT_ROW (row));
+
+ return g_str_has_prefix (cf, self->ing_term);
+}
+
+static void
+ing_filter_changed (GrEditPage *self)
+{
+ const char *term;
+
+ term = gtk_entry_get_text (GTK_ENTRY (self->new_ingredient_name));
+ g_free (self->ing_term);
+ self->ing_term = g_utf8_casefold (term, -1);
+ gtk_list_box_invalidate_filter (GTK_LIST_BOX (self->ing_list));
+}
+
+static void
+ing_filter_stop (GrEditPage *self)
+{
+ gtk_entry_set_text (GTK_ENTRY (self->new_ingredient_name), "");
+}
+
+static void
+ing_filter_activated (GrEditPage *self)
+{
+ const char *ingredient;
+
+ ingredient = gtk_entry_get_text (GTK_ENTRY (self->new_ingredient_name));
+ gtk_label_set_label (GTK_LABEL (self->ing_search_button_label), ingredient);
+ hide_ingredients_search_list (self, TRUE);
+}
+
+static void
+populate_ingredients_list (GrEditPage *self)
+{
+ int i;
+ const char **ingredients;
+ GtkWidget *row;
+
+ ingredients = gr_ingredient_get_names (NULL);
+ for (i = 0; ingredients[i]; i++) {
+ row = GTK_WIDGET (gr_ingredient_row_new (ingredients[i]));
+ gtk_widget_show (row);
+ gtk_container_add (GTK_CONTAINER (self->ing_list), row);
+ }
+
+ gtk_list_box_set_header_func (GTK_LIST_BOX (self->ing_list),
+ all_headers, self, NULL);
+
+ gtk_list_box_set_filter_func (GTK_LIST_BOX (self->ing_list),
+ ing_filter_func, self, NULL);
+
+ g_signal_connect (self->ing_list, "row-activated",
+ G_CALLBACK (ing_row_activated), self);
+}
+
+
+static void
gr_edit_page_init (GrEditPage *page)
{
gtk_widget_set_has_window (GTK_WIDGET (page), FALSE);
@@ -485,6 +614,7 @@ gr_edit_page_init (GrEditPage *page)
populate_cuisine_combo (page);
populate_category_combo (page);
populate_season_combo (page);
+ populate_ingredients_list (page);
}
static void
@@ -527,6 +657,10 @@ gr_edit_page_class_init (GrEditPageClass *klass)
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, new_ingredient_amount);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, new_ingredient_unit);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage,
new_ingredient_add_button);
+ gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, ing_list);
+ gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, ing_search_button);
+ gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, ing_search_button_label);
+ gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (klass), GrEditPage, ing_search_revealer);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), dismiss_error);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), add_image);
@@ -537,6 +671,11 @@ gr_edit_page_class_init (GrEditPageClass *klass)
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), add_ingredient2);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), remove_ingredient);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), ingredient_changed);
+
+ gtk_widget_class_bind_template_callback (widget_class, ing_filter_changed);
+ gtk_widget_class_bind_template_callback (widget_class, ing_filter_stop);
+ gtk_widget_class_bind_template_callback (widget_class, ing_filter_activated);
+ gtk_widget_class_bind_template_callback (widget_class, ing_search_button_clicked);
}
GtkWidget *
diff --git a/src/gr-edit-page.ui b/src/gr-edit-page.ui
index afea66a..a14be57 100644
--- a/src/gr-edit-page.ui
+++ b/src/gr-edit-page.ui
@@ -622,6 +622,7 @@
</template>
<object class="GtkPopover" id="ingredient_popover">
<property name="position">top</property>
+ <property name="constrain-to">none</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
@@ -637,42 +638,104 @@
</object>
</child>
<child>
- <object class="GtkEntry" id="new_ingredient_name">
+ <object class="GtkButton" id="ing_search_button">
<property name="visible">1</property>
- <signal name="notify::text" handler="ingredient_changed" swapped="yes"/>
- </object>
- </child>
- <child>
- <object class="GtkLabel">
- <property name="visible">1</property>
- <property name="label" translatable="yes">Amount</property>
- <property name="xalign">0</property>
- <style> <class name="dim-label"/> </style>
+ <signal name="clicked" handler="ing_search_button_clicked"/>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">1</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="ing_search_button_label">
+ <property name="visible">1</property>
+ <property name="xalign">0</property>
+ <property name="ellipsize">end</property>
+ <property name="max-width-chars">25</property>
+ <property name="label" translatable="yes">Ingredient</property>
+ </object>
+ <packing>
+ <property name="expand">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">1</property>
+ <property name="icon-name">pan-down-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
</child>
<child>
- <object class="GtkSpinButton" id="new_ingredient_amount">
- <property name="adjustment">amount_adjustment</property>
+ <object class="GtkRevealer" id="ing_search_revealer">
<property name="visible">1</property>
+ <child>
+ <object class="GtkBox">
+ <property name="visible">1</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkSearchEntry" id="new_ingredient_name">
+ <property name="visible">1</property>
+ <property name="placeholder-text" translatable="yes">Search…</property>
+ <signal name="search-changed" handler="ing_filter_changed" swapped="yes"/>
+ <signal name="stop-search" handler="ing_filter_stop" swapped="yes"/>
+ <signal name="activate" handler="ing_filter_activated" swapped="yes"/>
+ <signal name="notify::text" handler="ingredient_changed" swapped="yes"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">1</property>
+ <property name="shadow-type">in</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="propagate-natural-height">1</property>
+ <property name="max-content-height">220</property>
+ <property name="height-request">220</property>
+ <child>
+ <object class="GtkListBox" id="ing_list">
+ <property name="visible">1</property>
+ <property name="selection-mode">none</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">1</property>
- <property name="label" translatable="yes">Units</property>
+ <property name="label" translatable="yes">Amount</property>
<property name="xalign">0</property>
<style> <class name="dim-label"/> </style>
</object>
</child>
<child>
- <object class="GtkComboBoxText" id="new_ingredient_unit">
+ <object class="GtkBox">
<property name="visible">1</property>
- <property name="has-entry">1</property>
- <items>
- <item id="g" translatable="yes">grams</item>
- <item id="kg" translatable="yes">kilograms</item>
- <item id="lb" translatable="yes">pounds</item>
- </items>
+ <property name="orientation">horizontal</property>
+ <style> <class name="linked"/> </style>
+ <child>
+ <object class="GtkEntry" id="new_ingredient_amount">
+ <property name="visible">1</property>
+ <property name="width-chars">6</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="new_ingredient_unit">
+ <property name="visible">1</property>
+ <property name="has-entry">1</property>
+ <items>
+ <item id="g" translatable="yes">grams</item>
+ <item id="kg" translatable="yes">kilograms</item>
+ <item id="lb" translatable="yes">pounds</item>
+ </items>
+ </object>
+ </child>
</object>
</child>
<child>
@@ -686,11 +749,4 @@
</object>
</child>
</object>
- <object class="GtkAdjustment" id="amount_adjustment">
- <property name="lower">0</property>
- <property name="upper">1000</property>
- <property name="page_size">0</property>
- <property name="step_increment">1</property>
- <property name="page_increment">10</property>
- </object>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]