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.
This commit is contained in:
Benjamin Otte 2019-11-08 21:23:03 +01:00 committed by Matthias Clasen
parent 9f19699806
commit efcb3a9d67
8 changed files with 291 additions and 11 deletions

View File

@ -29,6 +29,7 @@ private_headers = [
'gtkcolumnviewcolumnprivate.h',
'gtkcolumnviewlayoutprivate.h',
'gtkcolumnviewprivate.h',
'gtkcolumnviewtitleprivate.h',
'gtkcomboboxprivate.h',
'gtkconstraintexpressionprivate.h',
'gtkconstraintguideprivate.h',

View File

@ -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,
minimum, natural,
minimum_baseline, natural_baseline);
&header_min, &header_nat,
NULL, NULL);
gtk_widget_measure (GTK_WIDGET (self->listview),
orientation, for_size,
&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);
}

View File

@ -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]);
}

View File

@ -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);
}

View File

@ -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);

142
gtk/gtkcolumnviewtitle.c Normal file
View File

@ -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;
}

View File

@ -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__ */

View File

@ -40,6 +40,7 @@ gtk_private_sources = files([
'gtkcolumnlistitemfactory.c',
'gtkcolumnviewcell.c',
'gtkcolumnviewlayout.c',
'gtkcolumnviewtitle.c',
'gtkconstraintexpression.c',
'gtkconstraintsolver.c',
'gtkconstraintvflparser.c',