[gtk/wip/otte/listview] columnview: Add header
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/listview] columnview: Add header
- Date: Sun, 10 Nov 2019 01:42:39 +0000 (UTC)
commit a5ba2c2589c1841135125f4c187d1776bf9294d1
Author: Benjamin Otte <otte redhat com>
Date: Fri Nov 8 21:23:03 2019 +0100
columnview: Add header
This uses a custom GtkColumnViewTitle widget. So far that widget is
pretty boring, but that will change once we added
resizing, reordering, dnd, sorting, hiding/showing of columns or
whatever UIs we want.
gtk/gtkcolumnview.c | 43 ++++++++++--
gtk/gtkcolumnviewcolumn.c | 55 ++++++++++++++--
gtk/gtkcolumnviewlayout.c | 9 ++-
gtk/gtkcolumnviewprivate.h | 4 ++
gtk/gtkcolumnviewtitle.c | 142 ++++++++++++++++++++++++++++++++++++++++
gtk/gtkcolumnviewtitleprivate.h | 47 +++++++++++++
gtk/meson.build | 1 +
7 files changed, 290 insertions(+), 11 deletions(-)
---
diff --git a/gtk/gtkcolumnview.c b/gtk/gtkcolumnview.c
index 8582e7293d..d6170dfc46 100644
--- a/gtk/gtkcolumnview.c
+++ b/gtk/gtkcolumnview.c
@@ -25,6 +25,7 @@
#include "gtkbuildable.h"
#include "gtkcolumnlistitemfactoryprivate.h"
#include "gtkcolumnviewcolumnprivate.h"
+#include "gtkcolumnviewlayoutprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkintl.h"
#include "gtklistview.h"
@@ -49,6 +50,8 @@ struct _GtkColumnView
GListStore *columns;
+ GtkWidget *header;
+
GtkListView *listview;
GtkColumnListItemFactory *factory;
};
@@ -135,10 +138,18 @@ gtk_column_view_measure (GtkWidget *widget,
}
else
{
+ int header_min, header_nat, list_min, list_nat;
+
+ gtk_widget_measure (GTK_WIDGET (self->listview),
+ orientation, for_size,
+ &header_min, &header_nat,
+ NULL, NULL);
gtk_widget_measure (GTK_WIDGET (self->listview),
orientation, for_size,
- minimum, natural,
- minimum_baseline, natural_baseline);
+ &list_min, &list_nat,
+ NULL, NULL);
+ *minimum = header_min + list_min;
+ *natural = header_nat + list_nat;
}
}
@@ -151,7 +162,7 @@ gtk_column_view_allocate_columns (GtkColumnView *self,
guint i;
gtk_column_view_measure_across (self, &col_min, &col_nat);
- gtk_widget_measure (GTK_WIDGET (self->listview),
+ gtk_widget_measure (GTK_WIDGET (self),
GTK_ORIENTATION_HORIZONTAL, -1,
&widget_min, &widget_nat,
NULL, NULL);
@@ -198,11 +209,20 @@ gtk_column_view_allocate (GtkWidget *widget,
int baseline)
{
GtkColumnView *self = GTK_COLUMN_VIEW (widget);
- int full_width;
+ int full_width, header_height, min, nat;
full_width = gtk_column_view_allocate_columns (self, width);
- gtk_widget_allocate (GTK_WIDGET (self->listview), full_width, height, baseline, NULL);
+ gtk_widget_measure (self->header, GTK_ORIENTATION_VERTICAL, full_width, &min, &nat, NULL, NULL);
+ if (gtk_scrollable_get_vscroll_policy (GTK_SCROLLABLE (self->listview)) == GTK_SCROLL_MINIMUM)
+ header_height = min;
+ else
+ header_height = nat;
+ gtk_widget_allocate (self->header, full_width, header_height, -1, NULL);
+
+ gtk_widget_allocate (GTK_WIDGET (self->listview),
+ full_width, height - header_height, -1,
+ gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (0, header_height)));
}
static void
@@ -225,6 +245,8 @@ gtk_column_view_dispose (GObject *object)
g_object_unref (column);
}
+ g_clear_pointer (&self->header, gtk_widget_unparent);
+
g_clear_pointer ((GtkWidget **) &self->listview, gtk_widget_unparent);
g_clear_object (&self->factory);
@@ -441,6 +463,11 @@ gtk_column_view_init (GtkColumnView *self)
{
self->columns = g_list_store_new (GTK_TYPE_COLUMN_VIEW_COLUMN);
+ self->header = gtk_list_item_widget_new (NULL, "header");
+ gtk_widget_set_can_focus (self->header, FALSE);
+ gtk_widget_set_layout_manager (self->header, gtk_column_view_layout_new (self));
+ gtk_widget_set_parent (self->header, GTK_WIDGET (self));
+
self->factory = gtk_column_list_item_factory_new (self);
self->listview = GTK_LIST_VIEW (gtk_list_view_new_with_factory (
GTK_LIST_ITEM_FACTORY (g_object_ref (self->factory))));
@@ -648,3 +675,9 @@ gtk_column_view_measure_across (GtkColumnView *self,
*natural = nat;
}
+GtkListItemWidget *
+gtk_column_view_get_header_widget (GtkColumnView *self)
+{
+ return GTK_LIST_ITEM_WIDGET (self->header);
+}
+
diff --git a/gtk/gtkcolumnviewcolumn.c b/gtk/gtkcolumnviewcolumn.c
index c18cf7716e..0898c54548 100644
--- a/gtk/gtkcolumnviewcolumn.c
+++ b/gtk/gtkcolumnviewcolumn.c
@@ -21,6 +21,8 @@
#include "gtkcolumnviewcolumnprivate.h"
+#include "gtkcolumnviewprivate.h"
+#include "gtkcolumnviewtitleprivate.h"
#include "gtkintl.h"
#include "gtklistbaseprivate.h"
#include "gtklistitemwidgetprivate.h"
@@ -49,6 +51,7 @@ struct _GtkColumnViewColumn
/* data for the view */
GtkColumnView *view;
+ GtkWidget *header;
int minimum_size_request;
int natural_size_request;
@@ -291,6 +294,9 @@ gtk_column_view_column_queue_resize (GtkColumnViewColumn *self)
self->minimum_size_request = -1;
self->natural_size_request = -1;
+ if (self->header)
+ gtk_widget_queue_resize (self->header);
+
for (cell = self->first_cell; cell; cell = gtk_column_view_cell_get_next (cell))
{
gtk_widget_queue_resize (GTK_WIDGET (cell));
@@ -307,8 +313,15 @@ gtk_column_view_column_measure (GtkColumnViewColumn *self,
GtkColumnViewCell *cell;
int min, nat, cell_min, cell_nat;
- min = 0;
- nat = 0;
+ if (self->header)
+ {
+ gtk_widget_measure (self->header, GTK_ORIENTATION_HORIZONTAL, -1, &min, &nat, NULL, NULL);
+ }
+ else
+ {
+ min = 0;
+ nat = 0;
+ }
for (cell = self->first_cell; cell; cell = gtk_column_view_cell_get_next (cell))
{
@@ -385,6 +398,30 @@ gtk_column_view_column_remove_cells (GtkColumnViewColumn *self)
gtk_column_view_cell_remove (self->first_cell);
}
+static void
+gtk_column_view_column_create_header (GtkColumnViewColumn *self)
+{
+ if (self->header != NULL)
+ return;
+
+ self->header = gtk_column_view_title_new (self);
+ gtk_list_item_widget_add_child (gtk_column_view_get_header_widget (self->view),
+ self->header);
+ gtk_column_view_column_queue_resize (self);
+}
+
+static void
+gtk_column_view_column_remove_header (GtkColumnViewColumn *self)
+{
+ if (self->header == NULL)
+ return;
+
+ gtk_list_item_widget_remove_child (gtk_column_view_get_header_widget (self->view),
+ self->header);
+ self->header = NULL;
+ gtk_column_view_column_queue_resize (self);
+}
+
static void
gtk_column_view_column_ensure_cells (GtkColumnViewColumn *self)
{
@@ -392,6 +429,11 @@ gtk_column_view_column_ensure_cells (GtkColumnViewColumn *self)
gtk_column_view_column_create_cells (self);
else
gtk_column_view_column_remove_cells (self);
+
+ if (self->view)
+ gtk_column_view_column_create_header (self);
+ else
+ gtk_column_view_column_remove_header (self);
}
/**
@@ -419,10 +461,12 @@ gtk_column_view_column_set_column_view (GtkColumnViewColumn *self,
if (self->view == view)
return;
+ gtk_column_view_column_remove_cells (self);
+ gtk_column_view_column_remove_header (self);
+
self->view = view;
- if (view)
- gtk_column_view_column_ensure_cells (self);
+ gtk_column_view_column_ensure_cells (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLUMN_VIEW]);
}
@@ -486,6 +530,9 @@ gtk_column_view_column_set_title (GtkColumnViewColumn *self,
g_free (self->title);
self->title = g_strdup (title);
+ if (self->header)
+ gtk_column_view_title_update (GTK_COLUMN_VIEW_TITLE (self->header));
+
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TITLE]);
}
diff --git a/gtk/gtkcolumnviewlayout.c b/gtk/gtkcolumnviewlayout.c
index 3afd6a2af3..c4ba28a112 100644
--- a/gtk/gtkcolumnviewlayout.c
+++ b/gtk/gtkcolumnviewlayout.c
@@ -24,6 +24,7 @@
#include "gtkcolumnviewcellprivate.h"
#include "gtkcolumnviewcolumnprivate.h"
#include "gtkcolumnviewprivate.h"
+#include "gtkcolumnviewtitleprivate.h"
#include "gtkwidgetprivate.h"
struct _GtkColumnViewLayout
@@ -113,10 +114,14 @@ gtk_column_view_layout_allocate (GtkLayoutManager *layout_manager,
child != NULL;
child = _gtk_widget_get_next_sibling (child))
{
- GtkColumnViewCell *cell = GTK_COLUMN_VIEW_CELL (child);
- GtkColumnViewColumn *column = gtk_column_view_cell_get_column (cell);
+ GtkColumnViewColumn *column;
int col_x, col_width;
+ if (GTK_IS_COLUMN_VIEW_CELL (child))
+ column = gtk_column_view_cell_get_column (GTK_COLUMN_VIEW_CELL (child));
+ else
+ column = gtk_column_view_title_get_column (GTK_COLUMN_VIEW_TITLE (child));
+
gtk_column_view_column_get_allocation (column, &col_x, &col_width);
gtk_widget_size_allocate (child, &(GtkAllocation) { col_x, 0, col_width, height }, baseline);
}
diff --git a/gtk/gtkcolumnviewprivate.h b/gtk/gtkcolumnviewprivate.h
index d95577fe98..c356fae508 100644
--- a/gtk/gtkcolumnviewprivate.h
+++ b/gtk/gtkcolumnviewprivate.h
@@ -22,6 +22,10 @@
#include "gtk/gtkcolumnview.h"
+#include "gtk/gtklistitemwidgetprivate.h"
+
+GtkListItemWidget * gtk_column_view_get_header_widget (GtkColumnView *self);
+
void gtk_column_view_measure_across (GtkColumnView *self,
int *minimum,
int *natural);
diff --git a/gtk/gtkcolumnviewtitle.c b/gtk/gtkcolumnviewtitle.c
new file mode 100644
index 0000000000..7170018eb4
--- /dev/null
+++ b/gtk/gtkcolumnviewtitle.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright © 2019 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkcolumnviewtitleprivate.h"
+
+#include "gtkcolumnviewcolumnprivate.h"
+#include "gtkintl.h"
+#include "gtklabel.h"
+#include "gtkwidgetprivate.h"
+
+struct _GtkColumnViewTitle
+{
+ GtkWidget parent_instance;
+
+ GtkColumnViewColumn *column;
+
+ GtkWidget *title;
+};
+
+struct _GtkColumnViewTitleClass
+{
+ GtkWidgetClass parent_class;
+};
+
+G_DEFINE_TYPE (GtkColumnViewTitle, gtk_column_view_title, GTK_TYPE_WIDGET)
+
+static void
+gtk_column_view_title_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ GtkWidget *child = gtk_widget_get_first_child (widget);
+
+ if (child)
+ gtk_widget_measure (child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
+}
+
+static void
+gtk_column_view_title_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
+{
+ GtkWidget *child = gtk_widget_get_first_child (widget);
+
+ if (child)
+ gtk_widget_allocate (child, width, height, baseline, NULL);
+}
+
+static void
+gtk_column_view_title_dispose (GObject *object)
+{
+ GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (object);
+
+ g_clear_pointer(&self->title, gtk_widget_unparent);
+
+ g_clear_object (&self->column);
+
+ G_OBJECT_CLASS (gtk_column_view_title_parent_class)->dispose (object);
+}
+
+static void
+gtk_column_view_title_class_init (GtkColumnViewTitleClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ widget_class->measure = gtk_column_view_title_measure;
+ widget_class->size_allocate = gtk_column_view_title_size_allocate;
+
+ gobject_class->dispose = gtk_column_view_title_dispose;
+
+ gtk_widget_class_set_css_name (widget_class, I_("button"));
+}
+
+static void
+gtk_column_view_title_resize_func (GtkWidget *widget)
+{
+ GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
+
+ if (self->column)
+ gtk_column_view_column_queue_resize (self->column);
+}
+
+static void
+gtk_column_view_title_init (GtkColumnViewTitle *self)
+{
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ widget->priv->resize_func = gtk_column_view_title_resize_func;
+
+ self->title = gtk_label_new (NULL);
+ gtk_widget_set_parent (self->title, widget);
+}
+
+GtkWidget *
+gtk_column_view_title_new (GtkColumnViewColumn *column)
+{
+ GtkColumnViewTitle *title;
+
+ title = g_object_new (GTK_TYPE_COLUMN_VIEW_TITLE,
+ NULL);
+
+ title->column = g_object_ref (column);
+ gtk_column_view_title_update (title);
+
+ return GTK_WIDGET (title);
+}
+
+void
+gtk_column_view_title_update (GtkColumnViewTitle *self)
+{
+ gtk_label_set_label (GTK_LABEL (self->title), gtk_column_view_column_get_title (self->column));
+}
+
+GtkColumnViewColumn *
+gtk_column_view_title_get_column (GtkColumnViewTitle *self)
+{
+ return self->column;
+}
diff --git a/gtk/gtkcolumnviewtitleprivate.h b/gtk/gtkcolumnviewtitleprivate.h
new file mode 100644
index 0000000000..84bc6a4050
--- /dev/null
+++ b/gtk/gtkcolumnviewtitleprivate.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2019 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GTK_COLUMN_VIEW_TITLE_PRIVATE_H__
+#define __GTK_COLUMN_VIEW_TITLE_PRIVATE_H__
+
+#include "gtkcolumnviewcolumn.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_COLUMN_VIEW_TITLE (gtk_column_view_title_get_type ())
+#define GTK_COLUMN_VIEW_TITLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLUMN_VIEW_TITLE,
GtkColumnViewTitle))
+#define GTK_COLUMN_VIEW_TITLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_COLUMN_VIEW_TITLE,
GtkColumnViewTitleClass))
+#define GTK_IS_COLUMN_VIEW_TITLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLUMN_VIEW_TITLE))
+#define GTK_IS_COLUMN_VIEW_TITLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLUMN_VIEW_TITLE))
+#define GTK_COLUMN_VIEW_TITLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLUMN_VIEW_TITLE,
GtkColumnViewTitleClass))
+
+typedef struct _GtkColumnViewTitle GtkColumnViewTitle;
+typedef struct _GtkColumnViewTitleClass GtkColumnViewTitleClass;
+
+GType gtk_column_view_title_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gtk_column_view_title_new (GtkColumnViewColumn *column);
+
+void gtk_column_view_title_update (GtkColumnViewTitle *self);
+
+GtkColumnViewColumn * gtk_column_view_title_get_column (GtkColumnViewTitle *self);
+
+G_END_DECLS
+
+#endif /* __GTK_COLUMN_VIEW_TITLE_PRIVATE_H__ */
diff --git a/gtk/meson.build b/gtk/meson.build
index 1a93429864..8d27c963b9 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -40,6 +40,7 @@ gtk_private_sources = files([
'gtkcolumnlistitemfactory.c',
'gtkcolumnviewcell.c',
'gtkcolumnviewlayout.c',
+ 'gtkcolumnviewtitle.c',
'gtkconstraintexpression.c',
'gtkconstraintsolver.c',
'gtkconstraintvflparser.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]