summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2015-12-11 23:48:34 -0500
committerMatthias Clasen <mclasen@redhat.com>2015-12-15 08:41:16 -0500
commit29accad89a8fc744123e4327aa907417a20ae9fa (patch)
tree7affda2b8476273f42b71a894f24b96401a7a65b
parent9fb3716259b499d3617e96a44acceff2fa134ea9 (diff)
downloadgtk+-29accad89a8fc744123e4327aa907417a20ae9fa.tar.gz
listbox: Convert to gadgets
-rw-r--r--gtk/gtklistbox.c372
1 files changed, 237 insertions, 135 deletions
diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c
index ebcb3614b1..76babbc494 100644
--- a/gtk/gtklistbox.c
+++ b/gtk/gtklistbox.c
@@ -25,6 +25,7 @@
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkwidgetprivate.h"
+#include "gtkcontainerprivate.h"
#include "gtkcsscustomgadgetprivate.h"
#include <float.h>
@@ -76,6 +77,8 @@ typedef struct
GtkWidget *placeholder;
+ GtkCssGadget *gadget;
+
GtkListBoxSortFunc sort_func;
gpointer sort_func_target;
GDestroyNotify sort_func_target_destroy_notify;
@@ -279,6 +282,30 @@ static void gtk_list_box_bound_model_changed (GListMo
gpointer user_data);
static void gtk_list_box_check_model_compat (GtkListBox *box);
+
+static void gtk_list_box_measure (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum_size,
+ gint *natural_size,
+ gint *minimum_baseline,
+ gint *natural_baseline,
+ gpointer data);
+static void gtk_list_box_allocate (GtkCssGadget *gadget,
+ const GtkAllocation *allocation,
+ int baseline,
+ GtkAllocation *out_clip,
+ gpointer data);
+static gboolean gtk_list_box_render (GtkCssGadget *gadget,
+ cairo_t *cr,
+ int x,
+ int y,
+ int width,
+ int height,
+ gpointer data);
+
+
+
static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
static guint signals[LAST_SIGNAL] = { 0 };
static GParamSpec *row_properties[LAST_ROW_PROPERTY] = { NULL, };
@@ -300,33 +327,6 @@ gtk_list_box_new (void)
}
static void
-gtk_list_box_init (GtkListBox *box)
-{
- GtkListBoxPrivate *priv = BOX_PRIV (box);
- GtkWidget *widget = GTK_WIDGET (box);
-
- gtk_widget_set_has_window (widget, TRUE);
- gtk_widget_set_redraw_on_allocate (widget, TRUE);
- priv->selection_mode = GTK_SELECTION_SINGLE;
- priv->activate_single_click = TRUE;
-
- priv->children = g_sequence_new (NULL);
- priv->header_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
-
- priv->multipress_gesture = gtk_gesture_multi_press_new (widget);
- gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->multipress_gesture),
- GTK_PHASE_BUBBLE);
- gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->multipress_gesture),
- FALSE);
- gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->multipress_gesture),
- GDK_BUTTON_PRIMARY);
- g_signal_connect (priv->multipress_gesture, "pressed",
- G_CALLBACK (gtk_list_box_multipress_gesture_pressed), box);
- g_signal_connect (priv->multipress_gesture, "released",
- G_CALLBACK (gtk_list_box_multipress_gesture_released), box);
-}
-
-static void
gtk_list_box_get_property (GObject *obj,
guint property_id,
GValue *value,
@@ -398,6 +398,8 @@ gtk_list_box_finalize (GObject *obj)
g_clear_object (&priv->bound_model);
}
+ g_clear_object (&priv->gadget);
+
G_OBJECT_CLASS (gtk_list_box_parent_class)->finalize (obj);
}
@@ -624,6 +626,44 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
gtk_widget_class_set_css_name (widget_class, "list");
}
+static void
+gtk_list_box_init (GtkListBox *box)
+{
+ GtkListBoxPrivate *priv = BOX_PRIV (box);
+ GtkWidget *widget = GTK_WIDGET (box);
+ GtkCssNode *widget_node;
+
+ gtk_widget_set_has_window (widget, TRUE);
+ gtk_widget_set_redraw_on_allocate (widget, TRUE);
+ priv->selection_mode = GTK_SELECTION_SINGLE;
+ priv->activate_single_click = TRUE;
+
+ priv->children = g_sequence_new (NULL);
+ priv->header_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+
+ priv->multipress_gesture = gtk_gesture_multi_press_new (widget);
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->multipress_gesture),
+ GTK_PHASE_BUBBLE);
+ gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (priv->multipress_gesture),
+ FALSE);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (priv->multipress_gesture),
+ GDK_BUTTON_PRIMARY);
+ g_signal_connect (priv->multipress_gesture, "pressed",
+ G_CALLBACK (gtk_list_box_multipress_gesture_pressed), box);
+ g_signal_connect (priv->multipress_gesture, "released",
+ G_CALLBACK (gtk_list_box_multipress_gesture_released), box);
+
+ widget_node = gtk_widget_get_css_node (GTK_WIDGET (box));
+ priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
+ GTK_WIDGET (box),
+ gtk_list_box_measure,
+ gtk_list_box_allocate,
+ gtk_list_box_render,
+ NULL,
+ NULL);
+
+}
+
/**
* gtk_list_box_get_selected_row:
* @box: a #GtkListBox
@@ -2077,16 +2117,25 @@ static gboolean
gtk_list_box_draw (GtkWidget *widget,
cairo_t *cr)
{
- GtkAllocation allocation;
- GtkStyleContext *context;
+ gtk_css_gadget_draw (BOX_PRIV (widget)->gadget, cr);
- gtk_widget_get_allocation (widget, &allocation);
- context = gtk_widget_get_style_context (widget);
- gtk_render_background (context, cr, 0, 0, allocation.width, allocation.height);
+ return FALSE;
+}
+
+static gboolean
+gtk_list_box_render (GtkCssGadget *gadget,
+ cairo_t *cr,
+ int x,
+ int y,
+ int width,
+ int height,
+ gpointer data)
+{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
GTK_WIDGET_CLASS (gtk_list_box_parent_class)->draw (widget, cr);
- return TRUE;
+ return FALSE;
}
static void
@@ -2493,138 +2542,157 @@ gtk_list_box_get_request_mode (GtkWidget *widget)
static void
gtk_list_box_get_preferred_height (GtkWidget *widget,
- gint *minimum_height,
- gint *natural_height)
+ gint *minimum,
+ gint *natural)
{
- gint min_width, natural_width;
- gtk_list_box_get_preferred_width (widget, &min_width, &natural_width);
- gtk_list_box_get_preferred_height_for_width (widget, natural_width,
- minimum_height, natural_height);
+ gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+ GTK_ORIENTATION_VERTICAL,
+ -1,
+ minimum, natural,
+ NULL, NULL);
}
static void
gtk_list_box_get_preferred_height_for_width (GtkWidget *widget,
gint width,
- gint *minimum_height_out,
- gint *natural_height_out)
+ gint *minimum,
+ gint *natural)
{
- GtkListBoxPrivate *priv = BOX_PRIV (widget);
- GSequenceIter *iter;
- gint minimum_height;
-
- minimum_height = 0;
-
- if (priv->placeholder != NULL && gtk_widget_get_child_visible (priv->placeholder))
- gtk_widget_get_preferred_height_for_width (priv->placeholder, width,
- &minimum_height, NULL);
-
- for (iter = g_sequence_get_begin_iter (priv->children);
- !g_sequence_iter_is_end (iter);
- iter = g_sequence_iter_next (iter))
- {
- GtkListBoxRow *row;
- gint row_min = 0;
-
- row = g_sequence_get (iter);
- if (!row_is_visible (row))
- continue;
+ gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+ GTK_ORIENTATION_VERTICAL,
+ width,
+ minimum, natural,
+ NULL, NULL);
+}
- if (ROW_PRIV (row)->header != NULL)
- {
- gtk_widget_get_preferred_height_for_width (ROW_PRIV (row)->header, width, &row_min, NULL);
- minimum_height += row_min;
- }
- gtk_widget_get_preferred_height_for_width (GTK_WIDGET (row), width, &row_min, NULL);
- minimum_height += row_min;
- }
+static void
+gtk_list_box_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ minimum, natural,
+ NULL, NULL);
+}
- /* We always allocate the minimum height, since handling expanding rows is way too costly,
- * and unlikely to be used, as lists are generally put inside a scrolling window anyway.
- */
- *minimum_height_out = minimum_height;
- *natural_height_out = minimum_height;
+static void
+gtk_list_box_get_preferred_width_for_height (GtkWidget *widget,
+ gint height,
+ gint *minimum,
+ gint *natural)
+{
+ gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ height,
+ minimum, natural,
+ NULL, NULL);
}
static void
-gtk_list_box_get_preferred_width (GtkWidget *widget,
- gint *minimum_width_out,
- gint *natural_width_out)
+gtk_list_box_measure (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline,
+ gpointer unused)
{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
GtkListBoxPrivate *priv = BOX_PRIV (widget);
- gint minimum_width;
- gint natural_width;
GSequenceIter *iter;
- GtkListBoxRow *row;
- gint row_min;
- gint row_nat;
- minimum_width = 0;
- natural_width = 0;
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ *minimum = 0;
+ *natural = 0;
- if (priv->placeholder != NULL && gtk_widget_get_child_visible (priv->placeholder))
- gtk_widget_get_preferred_width (priv->placeholder,
- &minimum_width, &natural_width);
+ if (priv->placeholder && gtk_widget_get_child_visible (priv->placeholder))
+ gtk_widget_get_preferred_width (priv->placeholder, minimum, natural);
- for (iter = g_sequence_get_begin_iter (priv->children);
- !g_sequence_iter_is_end (iter);
- iter = g_sequence_iter_next (iter))
- {
- row = g_sequence_get (iter);
+ for (iter = g_sequence_get_begin_iter (priv->children);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter))
+ {
+ GtkListBoxRow *row;
+ gint row_min;
+ gint row_nat;
- /* We *do* take visible but filtered rows into account here so that
- * the list width doesn't change during filtering
- */
- if (!gtk_widget_get_visible (GTK_WIDGET (row)))
- continue;
+ row = g_sequence_get (iter);
- gtk_widget_get_preferred_width (GTK_WIDGET (row), &row_min, &row_nat);
- minimum_width = MAX (minimum_width, row_min);
- natural_width = MAX (natural_width, row_nat);
+ /* We *do* take visible but filtered rows into account here so that
+ * the list width doesn't change during filtering
+ */
+ if (!gtk_widget_get_visible (GTK_WIDGET (row)))
+ continue;
- if (ROW_PRIV (row)->header != NULL)
- {
- gtk_widget_get_preferred_width (ROW_PRIV (row)->header, &row_min, &row_nat);
- minimum_width = MAX (minimum_width, row_min);
- natural_width = MAX (natural_width, row_nat);
+ gtk_widget_get_preferred_width (GTK_WIDGET (row), &row_min, &row_nat);
+ *minimum = MAX (*minimum, row_min);
+ *natural = MAX (*natural, row_nat);
+
+ if (ROW_PRIV (row)->header != NULL)
+ {
+ gtk_widget_get_preferred_width (ROW_PRIV (row)->header, &row_min, &row_nat);
+ *minimum = MAX (*minimum, row_min);
+ *natural = MAX (*natural, row_nat);
+ }
}
}
+ else
+ {
+ if (for_size < 0)
+ gtk_css_gadget_get_preferred_size (priv->gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ NULL, &for_size,
+ NULL, NULL);
- *minimum_width_out = minimum_width;
- *natural_width_out = natural_width;
-}
+ *minimum = 0;
-static void
-gtk_list_box_get_preferred_width_for_height (GtkWidget *widget,
- gint height,
- gint *minimum_width,
- gint *natural_width)
-{
- gtk_list_box_get_preferred_width (widget, minimum_width, natural_width);
+ if (priv->placeholder && gtk_widget_get_child_visible (priv->placeholder))
+ gtk_widget_get_preferred_height_for_width (priv->placeholder, for_size,
+ minimum, NULL);
+
+ for (iter = g_sequence_get_begin_iter (priv->children);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter))
+ {
+ GtkListBoxRow *row;
+ gint row_min = 0;
+
+ row = g_sequence_get (iter);
+ if (!row_is_visible (row))
+ continue;
+
+ if (ROW_PRIV (row)->header != NULL)
+ {
+ gtk_widget_get_preferred_height_for_width (ROW_PRIV (row)->header, for_size, &row_min, NULL);
+ *minimum += row_min;
+ }
+ gtk_widget_get_preferred_height_for_width (GTK_WIDGET (row), for_size, &row_min, NULL);
+ *minimum += row_min;
+ }
+
+ /* We always allocate the minimum height, since handling expanding rows
+ * is way too costly, and unlikely to be used, as lists are generally put
+ * inside a scrolling window anyway.
+ */
+ *natural = *minimum;
+ }
}
static void
gtk_list_box_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
- GtkListBoxPrivate *priv = BOX_PRIV (widget);
- GtkAllocation child_allocation;
- GtkAllocation header_allocation;
- GtkListBoxRow *row;
+ GtkAllocation clip;
GdkWindow *window;
- GSequenceIter *iter;
- int child_min;
-
- child_allocation.x = 0;
- child_allocation.y = 0;
- child_allocation.width = 0;
- child_allocation.height = 0;
-
- header_allocation.x = 0;
- header_allocation.y = 0;
- header_allocation.width = 0;
- header_allocation.height = 0;
+ GtkAllocation child_allocation;
gtk_widget_set_allocation (widget, allocation);
+
window = gtk_widget_get_window (widget);
if (window != NULL)
gdk_window_move_resize (window,
@@ -2634,17 +2702,49 @@ gtk_list_box_size_allocate (GtkWidget *widget,
child_allocation.x = 0;
child_allocation.y = 0;
child_allocation.width = allocation->width;
- header_allocation.x = 0;
+ child_allocation.height = allocation->height;
+
+ gtk_css_gadget_allocate (BOX_PRIV (widget)->gadget,
+ &child_allocation,
+ gtk_widget_get_allocated_baseline (widget),
+ &clip);
+
+ _gtk_widget_set_simple_clip (widget, &clip);
+}
+
+
+static void
+gtk_list_box_allocate (GtkCssGadget *gadget,
+ const GtkAllocation *allocation,
+ int baseline,
+ GtkAllocation *out_clip,
+ gpointer unused)
+{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
+ GtkListBoxPrivate *priv = BOX_PRIV (widget);
+ GtkAllocation child_allocation;
+ GtkAllocation header_allocation;
+ GtkListBoxRow *row;
+ GSequenceIter *iter;
+ int child_min;
+
+ child_allocation.x = allocation->x;
+ child_allocation.y = allocation->y;
+ child_allocation.width = allocation->width;
+ child_allocation.height = 0;
+
+ header_allocation.x = allocation->x;
+ header_allocation.y = allocation->y;
header_allocation.width = allocation->width;
+ header_allocation.height = 0;
- if (priv->placeholder != NULL && gtk_widget_get_child_visible (priv->placeholder))
+ if (priv->placeholder && gtk_widget_get_child_visible (priv->placeholder))
{
gtk_widget_get_preferred_height_for_width (priv->placeholder,
allocation->width, &child_min, NULL);
header_allocation.height = allocation->height;
header_allocation.y = child_allocation.y;
- gtk_widget_size_allocate (priv->placeholder,
- &header_allocation);
+ gtk_widget_size_allocate (priv->placeholder, &header_allocation);
child_allocation.y += child_min;
}
@@ -2680,6 +2780,8 @@ gtk_list_box_size_allocate (GtkWidget *widget,
gtk_widget_size_allocate (GTK_WIDGET (row), &child_allocation);
child_allocation.y += child_min;
}
+
+ gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip);
}
/**