[gtk/suggestion-entry: 2/4] suggestionentry: Add an optional button
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/suggestion-entry: 2/4] suggestionentry: Add an optional button
- Date: Sat, 27 Jun 2020 21:20:15 +0000 (UTC)
commit 33a89cd64868c233100c87487ef46ac6e66f8515
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Jun 26 17:41:33 2020 -0400
suggestionentry: Add an optional button
This is useful for comboboxtext-like use cases.
To simulate comboboxtext behavior, set
use-filter = FALSE
show-button = TRUE
insert-selection = TRUE
docs/reference/gtk/gtk4-sections.txt | 2 +
gtk/gtksuggestionentry.c | 154 +++++++++++++++++++++++++++++++----
gtk/gtksuggestionentry.h | 6 ++
3 files changed, 144 insertions(+), 18 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index f68396dbea..7763c7d6ad 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -7617,4 +7617,6 @@ gtk_suggestion_entry_set_insert_selection
gtk_suggestion_entry_get_insert_selection
gtk_suggestion_entry_set_insert_prefix
gtk_suggestion_entry_get_insert_prefix
+gtk_suggestion_entry_set_show_button
+gtk_suggestion_entry_get_show_button
</SECTION>
diff --git a/gtk/gtksuggestionentry.c b/gtk/gtksuggestionentry.c
index 61d61adc3a..5b1b6d16e5 100644
--- a/gtk/gtksuggestionentry.c
+++ b/gtk/gtksuggestionentry.c
@@ -44,6 +44,9 @@
#include "gtkscrolledwindow.h"
#include "gtkeventcontrollerkey.h"
#include "gtkeventcontrollerfocus.h"
+#include "gtkbox.h"
+#include "gtkgizmoprivate.h"
+#include "gtkactionable.h"
/**
@@ -75,14 +78,19 @@
* # CSS Nodes
*
* |[<!-- language="plain" -->
- * entry.suggestion
- * ├── text
- * ╰── popover
+ * widget
+ * ╰── box
+ * ├── entry.suggestion
+ * │ ├── text
+ * │ ╰── popover
+ * ╰── [button]
* ]|
*
* GtkSuggestionEntry has a single CSS node with name entry that carries
* a .sugggestion style class, and the text and popover nodes are children
- * of that.
+ * of that. The parent of the entry node is a box node, which also contains
+ * the CSS node for the button (which may be hidden). The parent of the box
+ * node is a widget node.
*/
struct _GtkSuggestionEntry
@@ -96,6 +104,9 @@ struct _GtkSuggestionEntry
GtkFilterListModel *filter_model;
GtkSingleSelection *selection;
+ GtkWidget *box;
+ GtkWidget *gizmo;
+ GtkWidget *button;
GtkWidget *entry;
GtkWidget *popup;
GtkWidget *list;
@@ -107,6 +118,7 @@ struct _GtkSuggestionEntry
guint use_filter : 1;
guint insert_selection : 1;
guint insert_prefix : 1;
+ guint show_button : 1;
};
typedef struct _GtkSuggestionEntryClass GtkSuggestionEntryClass;
@@ -127,6 +139,7 @@ enum
PROP_USE_FILTER,
PROP_INSERT_PREFIX,
PROP_INSERT_SELECTION,
+ PROP_SHOW_BUTTON,
N_PROPERTIES,
};
@@ -162,8 +175,7 @@ gtk_suggestion_entry_dispose (GObject *object)
g_signal_handler_disconnect (self->entry, self->changed_id);
self->changed_id = 0;
}
- g_clear_pointer (&self->popup, gtk_widget_unparent);
- g_clear_pointer (&self->entry, gtk_widget_unparent);
+ g_clear_pointer (&self->box, gtk_widget_unparent);
g_clear_pointer (&self->expression, gtk_expression_unref);
g_clear_object (&self->factory);
@@ -207,7 +219,7 @@ gtk_suggestion_entry_get_property (GObject *object,
break;
case PROP_POPUP_VISIBLE:
- g_value_set_boolean (value, gtk_widget_get_visible (self->popup));
+ g_value_set_boolean (value, self->popup && gtk_widget_get_visible (self->popup));
break;
case PROP_USE_FILTER:
@@ -222,6 +234,10 @@ gtk_suggestion_entry_get_property (GObject *object,
g_value_set_boolean (value, gtk_suggestion_entry_get_insert_prefix (self));
break;
+ case PROP_SHOW_BUTTON:
+ g_value_set_boolean (value, gtk_suggestion_entry_get_show_button (self));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -273,6 +289,10 @@ gtk_suggestion_entry_set_property (GObject *object,
gtk_suggestion_entry_set_insert_prefix (self, g_value_get_boolean (value));
break;
+ case PROP_SHOW_BUTTON:
+ gtk_suggestion_entry_set_show_button (self, g_value_get_boolean (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -290,7 +310,7 @@ gtk_suggestion_entry_measure (GtkWidget *widget,
{
GtkSuggestionEntry *self = GTK_SUGGESTION_ENTRY (widget);
- gtk_widget_measure (self->entry,
+ gtk_widget_measure (self->box,
orientation,
size,
minimum, natural,
@@ -305,11 +325,8 @@ gtk_suggestion_entry_size_allocate (GtkWidget *widget,
{
GtkSuggestionEntry *self = GTK_SUGGESTION_ENTRY (widget);
- gtk_widget_size_allocate (self->entry, &(GtkAllocation) { 0, 0, width, height }, baseline);
+ gtk_widget_size_allocate (self->box, &(GtkAllocation) { 0, 0, width, height }, baseline);
- gtk_widget_set_size_request (self->popup, gtk_widget_get_allocated_width (widget), -1);
-
- gtk_native_check_resize (GTK_NATIVE (self->popup));
}
static gboolean
@@ -431,11 +448,16 @@ gtk_suggestion_entry_class_init (GtkSuggestionEntryClass *klass)
FALSE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+ properties[PROP_SHOW_BUTTON] =
+ g_param_spec_boolean ("show-button",
+ P_("Show button"),
+ P_("Whether to show a button for presenting the popup"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
gtk_editable_install_properties (object_class, N_PROPERTIES);
- gtk_widget_class_set_css_name (widget_class, I_("entry"));
-
/**
* GtkSuggestionEntry|popup.show:
*
@@ -775,6 +797,46 @@ set_default_factory (GtkSuggestionEntry *self)
g_object_unref (factory);
}
+static void
+measure_entry (GtkGizmo *gizmo,
+ GtkOrientation orientation,
+ gint size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ gtk_widget_measure (gtk_widget_get_first_child (GTK_WIDGET (gizmo)),
+ orientation, size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
+}
+
+static void
+allocate_entry (GtkGizmo *gizmo,
+ int width,
+ int height,
+ int baseline)
+{
+ GtkSuggestionEntry *self;
+
+ self = GTK_SUGGESTION_ENTRY (gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (gizmo))));
+
+ gtk_widget_size_allocate (gtk_widget_get_first_child (GTK_WIDGET (gizmo)),
+ &(GtkAllocation){ 0, 0, width, height },
+ baseline);
+
+ gtk_widget_set_size_request (self->popup, gtk_widget_get_allocated_width (GTK_WIDGET (gizmo)), -1);
+
+ gtk_native_check_resize (GTK_NATIVE (self->popup));
+}
+
+static gboolean
+grab_focus_entry (GtkGizmo *gizmo)
+{
+ return gtk_widget_grab_focus (gtk_widget_get_first_child (GTK_WIDGET (gizmo)));
+}
+
static void
gtk_suggestion_entry_init (GtkSuggestionEntry *self)
{
@@ -783,19 +845,38 @@ gtk_suggestion_entry_init (GtkSuggestionEntry *self)
self->use_filter = TRUE;
+ self->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_add_css_class (self->box, "linked");
+ gtk_widget_set_hexpand (self->box, TRUE);
+ gtk_widget_set_parent (self->box, GTK_WIDGET (self));
+
+ self->gizmo = gtk_gizmo_new ("entry", measure_entry, allocate_entry, NULL, NULL,
+ (GtkGizmoFocusFunc)gtk_widget_focus_child,
+ grab_focus_entry);
+ gtk_widget_add_css_class (self->gizmo, "suggestion");
+ gtk_widget_set_hexpand (self->gizmo, TRUE);
+ gtk_box_append (GTK_BOX (self->box), self->gizmo);
+
self->entry = gtk_text_new ();
- gtk_widget_set_parent (self->entry, GTK_WIDGET (self));
+ gtk_widget_set_parent (self->entry, self->gizmo);
gtk_widget_set_hexpand (self->entry, TRUE);
gtk_editable_init_delegate (GTK_EDITABLE (self));
self->changed_id = g_signal_connect (self->entry, "notify::text", G_CALLBACK (text_changed), self);
+ self->button = gtk_toggle_button_new ();
+ gtk_button_set_icon_name (GTK_BUTTON (self->button), "pan-down-symbolic");
+ gtk_widget_set_focus_on_click (self->button, FALSE);
+ gtk_actionable_set_action_name (GTK_ACTIONABLE (self->button), "popup.show");
+ gtk_box_append (GTK_BOX (self->box), self->button);
+ gtk_widget_hide (self->button);
+
self->popup = gtk_popover_new ();
gtk_popover_set_position (GTK_POPOVER (self->popup), GTK_POS_BOTTOM);
gtk_popover_set_autohide (GTK_POPOVER (self->popup), FALSE);
gtk_popover_set_has_arrow (GTK_POPOVER (self->popup), FALSE);
gtk_widget_set_halign (self->popup, GTK_ALIGN_START);
gtk_widget_add_css_class (self->popup, "menu");
- gtk_widget_set_parent (self->popup, GTK_WIDGET (self));
+ gtk_widget_set_parent (self->popup, self->gizmo);
sw = gtk_scrolled_window_new ();
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_NEVER,
@@ -812,8 +893,6 @@ gtk_suggestion_entry_init (GtkSuggestionEntry *self)
set_default_factory (self);
- gtk_widget_add_css_class (GTK_WIDGET (self), I_("suggestion"));
-
controller = gtk_event_controller_key_new ();
gtk_event_controller_set_name (controller, "gtk-suggestion-entry");
g_signal_connect (controller, "key-pressed",
@@ -1383,3 +1462,42 @@ gtk_suggestion_entry_get_insert_prefix (GtkSuggestionEntry *self)
return self->insert_prefix;
}
+
+/**
+ * gtk_suggestion_entry_set_show_button:
+ * @self: a #GtkSuggestionEntry
+ * @show_button: %TRUE to show a button
+ *
+ * Sets whether the GtkSuggestionEntry should show a button
+ * for opening the popup with suggestions.
+ */
+void
+gtk_suggestion_entry_set_show_button (GtkSuggestionEntry *self,
+ gboolean show_button)
+{
+ g_return_if_fail (GTK_IS_SUGGESTION_ENTRY (self));
+
+ if (self->show_button == show_button)
+ return;
+
+ if (self->button)
+ gtk_widget_set_visible (self->button, show_button);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_BUTTON]);
+}
+
+/**
+ * gtk_suggestion_entry_get_show_button:
+ * @self: a #GtkSuggestionEntry
+ *
+ * Gets the value set by gtk_suggestion_entry_set_show_button().
+ *
+ * Returns: %TRUE if @self is showing a button for suggestions
+ */
+gboolean
+gtk_suggestion_entry_get_show_button (GtkSuggestionEntry *self)
+{
+ g_return_val_if_fail (GTK_IS_SUGGESTION_ENTRY (self), FALSE);
+
+ return self->show_button;
+}
diff --git a/gtk/gtksuggestionentry.h b/gtk/gtksuggestionentry.h
index e04a46e38b..25ad7074da 100644
--- a/gtk/gtksuggestionentry.h
+++ b/gtk/gtksuggestionentry.h
@@ -84,6 +84,12 @@ void gtk_suggestion_entry_set_insert_prefix (GtkSuggestionEntry *
GDK_AVAILABLE_IN_ALL
gboolean gtk_suggestion_entry_get_insert_prefix (GtkSuggestionEntry *self);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_suggestion_entry_set_show_button (GtkSuggestionEntry *self,
+ gboolean show_button);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_suggestion_entry_get_show_button (GtkSuggestionEntry *self);
G_END_DECLS
#endif /* __GTK_SUGGESTION_ENTRY_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]