columnview: Add listitems for the columns

They are not aligned in columns yet, but they do exist.
This commit is contained in:
Benjamin Otte 2019-10-30 18:03:23 +01:00 committed by Matthias Clasen
parent 9caca0b127
commit 8736343544
8 changed files with 345 additions and 8 deletions

View File

@ -24,7 +24,9 @@ private_headers = [
'gtkcolorplaneprivate.h',
'gtkcolorscaleprivate.h',
'gtkcolorswatchprivate.h',
'gtkcolumnlistitemfactoryprivate.h',
'gtkcolumnviewcolumnprivate.h',
'gtkcolumnviewprivate.h',
'gtkcomboboxprivate.h',
'gtkconstraintexpressionprivate.h',
'gtkconstraintguideprivate.h',

View File

@ -0,0 +1,178 @@
/*
* 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 "gtkcolumnlistitemfactoryprivate.h"
#include "gtkboxlayout.h"
#include "gtkcolumnviewcolumnprivate.h"
#include "gtklistitemfactoryprivate.h"
#include "gtklistitemprivate.h"
struct _GtkColumnListItemFactory
{
GtkListItemFactory parent_instance;
GtkColumnView *view; /* no reference, the view references us */
};
struct _GtkColumnListItemFactoryClass
{
GtkListItemFactoryClass parent_class;
};
G_DEFINE_TYPE (GtkColumnListItemFactory, gtk_column_list_item_factory, GTK_TYPE_LIST_ITEM_FACTORY)
static GtkListItemWidget *
get_nth_child (GtkListItemWidget *parent,
guint pos)
{
GtkWidget *child;
guint i;
child = gtk_widget_get_first_child (GTK_WIDGET (parent));
for (i = 1; i < pos && child; i++)
child = gtk_widget_get_next_sibling (child);
return GTK_LIST_ITEM_WIDGET (child);
}
static void
gtk_column_list_item_factory_setup (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item)
{
GtkColumnListItemFactory *self = GTK_COLUMN_LIST_ITEM_FACTORY (factory);
GListModel *columns;
guint i;
gtk_widget_set_layout_manager (GTK_WIDGET (list_item->owner),
gtk_box_layout_new (GTK_ORIENTATION_HORIZONTAL));
GTK_LIST_ITEM_FACTORY_CLASS (gtk_column_list_item_factory_parent_class)->setup (factory, widget, list_item);
columns = gtk_column_view_get_columns (self->view);
for (i = 0; i < g_list_model_get_n_items (columns); i++)
{
GtkColumnViewColumn *column = g_list_model_get_item (columns, i);
gtk_column_list_item_factory_add_column (self,
list_item->owner,
column,
FALSE);
}
}
static void
gtk_column_list_item_factory_teardown (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item)
{
GtkWidget *child;
GTK_LIST_ITEM_FACTORY_CLASS (gtk_column_list_item_factory_parent_class)->teardown (factory, widget, list_item);
for (child = gtk_widget_get_first_child (GTK_WIDGET (list_item->owner));
child;
child = gtk_widget_get_first_child (GTK_WIDGET (list_item->owner)))
{
gtk_list_item_widget_remove_child (list_item->owner, child);
}
}
static void
gtk_column_list_item_factory_update (GtkListItemFactory *factory,
GtkListItemWidget *widget,
GtkListItem *list_item,
guint position,
gpointer item,
gboolean selected)
{
GtkWidget *child;
GTK_LIST_ITEM_FACTORY_CLASS (gtk_column_list_item_factory_parent_class)->update (factory, widget, list_item, position, item, selected);
for (child = gtk_widget_get_first_child (GTK_WIDGET (widget));
child;
child = gtk_widget_get_next_sibling (child))
{
gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (child), position, item, selected);
}
}
static void
gtk_column_list_item_factory_class_init (GtkColumnListItemFactoryClass *klass)
{
GtkListItemFactoryClass *factory_class = GTK_LIST_ITEM_FACTORY_CLASS (klass);
factory_class->setup = gtk_column_list_item_factory_setup;
factory_class->teardown = gtk_column_list_item_factory_teardown;
factory_class->update = gtk_column_list_item_factory_update;
}
static void
gtk_column_list_item_factory_init (GtkColumnListItemFactory *self)
{
}
GtkColumnListItemFactory *
gtk_column_list_item_factory_new (GtkColumnView *view)
{
GtkColumnListItemFactory *result;
result = g_object_new (GTK_TYPE_COLUMN_LIST_ITEM_FACTORY, NULL);
result->view = view;
return result;
}
void
gtk_column_list_item_factory_add_column (GtkColumnListItemFactory *factory,
GtkListItemWidget *list_item,
GtkColumnViewColumn *column,
gboolean check_bind)
{
GtkListItemFactory *column_factory;
GtkWidget *cell;
column_factory = gtk_column_view_column_get_factory (column);
cell = gtk_list_item_widget_new (column_factory, "cell");
gtk_list_item_widget_add_child (GTK_LIST_ITEM_WIDGET (list_item), GTK_WIDGET (cell));
gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (cell),
gtk_list_item_widget_get_position (list_item),
gtk_list_item_widget_get_item (list_item),
gtk_list_item_widget_get_selected (list_item));
}
void
gtk_column_list_item_factory_remove_column (GtkColumnListItemFactory *factory,
GtkListItemWidget *list_item,
guint col_pos,
GtkColumnViewColumn *column)
{
GtkListItemWidget *cell;
cell = get_nth_child (list_item, col_pos);
gtk_list_item_widget_remove_child (GTK_LIST_ITEM_WIDGET (list_item), GTK_WIDGET (cell));
}

View File

@ -0,0 +1,62 @@
/*
* 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_LIST_ITEM_FACTORY_H__
#define __GTK_COLUMN_LIST_ITEM_FACTORY_H__
#include <gtk/gtklistitemwidgetprivate.h>
#include <gtk/gtkcolumnview.h>
G_BEGIN_DECLS
#define GTK_TYPE_COLUMN_LIST_ITEM_FACTORY (gtk_column_list_item_factory_get_type ())
#define GTK_COLUMN_LIST_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLUMN_LIST_ITEM_FACTORY, GtkColumnListItemFactory))
#define GTK_COLUMN_LIST_ITEM_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_COLUMN_LIST_ITEM_FACTORY, GtkColumnListItemFactoryClass))
#define GTK_IS_COLUMN_LIST_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLUMN_LIST_ITEM_FACTORY))
#define GTK_IS_COLUMN_LIST_ITEM_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLUMN_LIST_ITEM_FACTORY))
#define GTK_COLUMN_LIST_ITEM_FACTORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLUMN_LIST_ITEM_FACTORY, GtkColumnListItemFactoryClass))
/**
* GtkColumnListItemFactory:
*
* The object for the #GtkColumnListItemFactory.
**/
typedef struct _GtkColumnListItemFactory GtkColumnListItemFactory;
typedef struct _GtkColumnListItemFactoryClass GtkColumnListItemFactoryClass;
GType gtk_column_list_item_factory_get_type (void) G_GNUC_CONST;
GtkColumnListItemFactory *
gtk_column_list_item_factory_new (GtkColumnView *view);
void gtk_column_list_item_factory_add_column (GtkColumnListItemFactory *factory,
GtkListItemWidget *list_item,
GtkColumnViewColumn *column,
gboolean check_bind);
void gtk_column_list_item_factory_remove_column
(GtkColumnListItemFactory *factory,
GtkListItemWidget *list_item,
guint col_pos,
GtkColumnViewColumn *column);
G_END_DECLS
#endif /* __GTK_COLUMN_LIST_ITEM_FACTORY_H__ */

View File

@ -19,10 +19,11 @@
#include "config.h"
#include "gtkcolumnview.h"
#include "gtkcolumnviewprivate.h"
#include "gtkboxlayout.h"
#include "gtkbuildable.h"
#include "gtkcolumnlistitemfactoryprivate.h"
#include "gtkcolumnviewcolumnprivate.h"
#include "gtkintl.h"
#include "gtklistview.h"
@ -47,6 +48,7 @@ struct _GtkColumnView
GListStore *columns;
GtkListView *listview;
GtkColumnListItemFactory *factory;
};
struct _GtkColumnViewClass
@ -102,12 +104,37 @@ gtk_column_view_buildable_interface_init (GtkBuildableIface *iface)
iface->add_child = gtk_column_view_buildable_add_child;
}
G_DEFINE_TYPE_WITH_CODE (GtkColumnView, gtk_column_view, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_column_view_buildable_interface_init))
static GParamSpec *properties[N_PROPS] = { NULL, };
static guint signals[LAST_SIGNAL] = { 0 };
/* For now we do the iter with the children. We might switch that
* to use the item manager or track children directly in the factory
* later (depending on how code changes), so having this abstraction makes sense.
*/
GtkColumnViewIter *
gtk_column_view_iter_init (GtkColumnView *self)
{
return (GtkColumnViewIter *) gtk_widget_get_first_child (GTK_WIDGET (self->listview));
}
GtkWidget *
gtk_column_view_iter_get_widget (GtkColumnView *self,
GtkColumnViewIter *iter)
{
return GTK_WIDGET (iter);
}
GtkColumnViewIter *
gtk_column_view_iter_next (GtkColumnView *self,
GtkColumnViewIter *iter)
{
return (GtkColumnViewIter *) gtk_widget_get_next_sibling (GTK_WIDGET (iter));
}
static void
gtk_column_view_activate_cb (GtkListView *listview,
guint pos,
@ -129,6 +156,7 @@ gtk_column_view_dispose (GObject *object)
}
g_clear_pointer ((GtkWidget **) &self->listview, gtk_widget_unparent);
g_clear_object (&self->factory);
G_OBJECT_CLASS (gtk_column_view_parent_class)->dispose (object);
}
@ -277,7 +305,11 @@ gtk_column_view_init (GtkColumnView *self)
{
self->columns = g_list_store_new (GTK_TYPE_COLUMN_VIEW_COLUMN);
self->listview = GTK_LIST_VIEW (gtk_list_view_new ());
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))));
gtk_widget_set_hexpand (GTK_WIDGET (self->listview), TRUE);
gtk_widget_set_vexpand (GTK_WIDGET (self->listview), TRUE);
g_signal_connect (self->listview, "activate", G_CALLBACK (gtk_column_view_activate_cb), self);
gtk_widget_set_parent (GTK_WIDGET (self->listview), GTK_WIDGET (self));
}
@ -409,12 +441,24 @@ void
gtk_column_view_append_column (GtkColumnView *self,
GtkColumnViewColumn *column)
{
GtkColumnViewIter *iter;
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (column));
g_return_if_fail (gtk_column_view_column_get_column_view (column) == NULL);
gtk_column_view_column_set_column_view (column, self);
g_list_store_append (self->columns, column);
for (iter = gtk_column_view_iter_init (self);
iter != NULL;
iter = gtk_column_view_iter_next (self, iter))
{
gtk_column_list_item_factory_add_column (self->factory,
GTK_LIST_ITEM_WIDGET (gtk_column_view_iter_get_widget (self, iter)),
column,
TRUE);
}
}
/**
@ -428,6 +472,7 @@ void
gtk_column_view_remove_column (GtkColumnView *self,
GtkColumnViewColumn *column)
{
GtkColumnViewIter *iter;
guint i;
g_return_if_fail (GTK_IS_COLUMN_VIEW (self));
@ -440,13 +485,22 @@ gtk_column_view_remove_column (GtkColumnView *self,
g_object_unref (item);
if (item == column)
break;
}
g_assert (i < g_list_model_get_n_items (G_LIST_MODEL (self->columns)));
for (iter = gtk_column_view_iter_init (self);
iter != NULL;
iter = gtk_column_view_iter_next (self, iter))
{
gtk_column_list_item_factory_remove_column (self->factory,
GTK_LIST_ITEM_WIDGET (gtk_column_view_iter_get_widget (self, iter)),
i,
column);
}
gtk_column_view_column_set_column_view (column, NULL);
g_list_store_remove (self->columns, i);
return;
}
}
g_assert_not_reached ();
}

View File

@ -0,0 +1,35 @@
/*
* 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_PRIVATE_H__
#define __GTK_COLUMN_VIEW_PRIVATE_H__
#include "gtk/gtkcolumnview.h"
/* This is really just a GtkListItemManagerItem for now, but
* proper layering ftw */
typedef struct _GtkColumnViewIter GtkColumnViewIter;
GtkColumnViewIter * gtk_column_view_iter_init (GtkColumnView *self);
GtkWidget * gtk_column_view_iter_get_widget (GtkColumnView *self,
GtkColumnViewIter *iter);
GtkColumnViewIter * gtk_column_view_iter_next (GtkColumnView *self,
GtkColumnViewIter *iter);
#endif /* __GTK_COLUMN_VIEW_PRIVATE_H__ */

View File

@ -319,6 +319,7 @@ gtk_list_item_set_child (GtkListItem *self,
{
g_object_ref_sink (child);
self->child = child;
if (self->owner)
gtk_list_item_widget_add_child (self->owner, child);
}

View File

@ -193,6 +193,7 @@ gtk_public_sources = files([
'gtkcolorchooserdialog.c',
'gtkcolorchooserwidget.c',
'gtkcolorutils.c',
'gtkcolumnlistitemfactory.c',
'gtkcolumnview.c',
'gtkcolumnviewcolumn.c',
'gtkcombobox.c',

View File

@ -239,6 +239,10 @@ test_type (gconstpointer data)
strcmp (pspec->name, "rgba") == 0))
continue;
if (g_type_is_a (type, GTK_TYPE_COLUMN_VIEW) &&
strcmp (pspec->name, "columns") == 0)
continue;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (g_type_is_a (type, GTK_TYPE_COMBO_BOX) &&