gtk/tests/testlistdnd.c
Matthias Clasen 386b63b85d scrolledwindow: Don't take adjustments in new()
In 99.9% of all cases, these are just NULL, NULL.
So just do away with these arguments, people can
use the setters for the rare cases where they want
the scrolled window to use a different adjustment.
2020-06-24 11:25:09 -04:00

442 lines
12 KiB
C

#include <gtk/gtk.h>
#define TEST_TYPE_OBJECT (test_object_get_type ())
G_DECLARE_FINAL_TYPE (TestObject, test_object, TEST, OBJECT, GObject)
struct _TestObject {
GObject parent_instance;
char *string;
guint number;
gboolean allow_children;
};
enum {
PROP_STRING = 1,
PROP_NUMBER,
PROP_ALLOW_CHILDREN,
PROP_NUM_PROPERTIES
};
G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT);
static void
test_object_init (TestObject *obj)
{
}
static void
test_object_finalize (GObject *object)
{
TestObject *obj = TEST_OBJECT (object);
g_free (obj->string);
G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
}
static void
test_object_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
TestObject *obj = TEST_OBJECT (object);
switch (property_id)
{
case PROP_STRING:
g_free (obj->string);
obj->string = g_value_dup_string (value);
break;
case PROP_NUMBER:
obj->number = g_value_get_uint (value);
break;
case PROP_ALLOW_CHILDREN:
obj->allow_children = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
test_object_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
TestObject *obj = TEST_OBJECT (object);
switch (property_id)
{
case PROP_STRING:
g_value_set_string (value, obj->string);
break;
case PROP_NUMBER:
g_value_set_uint (value, obj->number);
break;
case PROP_ALLOW_CHILDREN:
g_value_set_boolean (value, obj->allow_children);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
test_object_class_init (TestObjectClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = test_object_finalize;
object_class->set_property = test_object_set_property;
object_class->get_property = test_object_get_property;
g_object_class_install_property (object_class, PROP_STRING,
g_param_spec_string ("string", "String", "String",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_NUMBER,
g_param_spec_uint ("number", "Number", "Number",
0, G_MAXUINT, 0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_ALLOW_CHILDREN,
g_param_spec_boolean ("allow-children", "Allow children", "Allow children",
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static TestObject *
test_object_new (const char *string,
guint number,
gboolean allow_children)
{
return g_object_new (TEST_TYPE_OBJECT,
"string", string,
"number", number,
"allow-children", allow_children,
NULL);
}
static const char *
test_object_get_string (TestObject *obj)
{
return obj->string;
}
static guint
test_object_get_number (TestObject *obj)
{
return obj->number;
}
static gboolean
test_object_get_allow_children (TestObject *obj)
{
return obj->allow_children;
}
/* * * */
static GListModel *
create_model (guint base,
guint n,
guint increment,
gboolean allow_children)
{
GListStore *store;
guint i;
store = g_list_store_new (TEST_TYPE_OBJECT);
for (i = 0; i < n; i++)
{
char *string;
guint number;
TestObject *obj;
number = base + i * increment;
string = g_strdup_printf ("%u", number);
obj = test_object_new (string, number, allow_children);
g_list_store_append (store, obj);
g_object_unref (obj);
g_free (string);
}
return G_LIST_MODEL (store);
}
static GListModel *
create_child_model (gpointer item,
gpointer user_data)
{
guint size = GPOINTER_TO_UINT (user_data);
guint base = test_object_get_number (TEST_OBJECT (item));
if (test_object_get_allow_children (TEST_OBJECT (item)))
return create_model (base, size, 1, FALSE);
else
return NULL;
}
static GListModel *
create_tree_model (guint n, guint m)
{
return G_LIST_MODEL (gtk_tree_list_model_new (FALSE,
create_model (0, n, m, TRUE),
FALSE,
create_child_model,
GUINT_TO_POINTER (m), NULL));
}
static void
setup_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *entry;
entry = gtk_editable_label_new ("");
gtk_editable_set_width_chars (GTK_EDITABLE (entry), 3);
gtk_list_item_set_child (item, entry);
}
static void
text_changed (GObject *object,
GParamSpec *pspec,
gpointer data)
{
const char *text;
text = gtk_editable_get_text (GTK_EDITABLE (object));
g_print ("text changed to '%s'\n", text);
g_object_set (data, "string", text, NULL);
}
static void
bind_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
TestObject *obj;
GtkWidget *entry;
obj = gtk_list_item_get_item (item);
entry = gtk_list_item_get_child (item);
gtk_editable_set_text (GTK_EDITABLE (entry), test_object_get_string (obj));
g_signal_connect (entry, "notify::text", G_CALLBACK (text_changed), obj);
}
static void
unbind_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
TestObject *obj;
GtkWidget *entry;
obj = gtk_list_item_get_item (item);
entry = gtk_list_item_get_child (item);
g_signal_handlers_disconnect_by_func (entry, text_changed, obj);
}
static void
setup_tree_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *expander;
GtkWidget *entry;
entry = gtk_editable_label_new ("");
gtk_editable_set_width_chars (GTK_EDITABLE (entry), 3);
expander = gtk_tree_expander_new ();
gtk_tree_expander_set_child (GTK_TREE_EXPANDER (expander), entry);
gtk_list_item_set_child (item, expander);
}
static void
bind_tree_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkTreeListRow *row;
GtkTreeExpander *expander;
TestObject *obj;
GtkWidget *entry;
row = gtk_list_item_get_item (item);
expander = GTK_TREE_EXPANDER (gtk_list_item_get_child (item));
gtk_tree_expander_set_list_row (expander, row);
obj = gtk_tree_list_row_get_item (row);
entry = gtk_tree_expander_get_child (expander);
gtk_editable_set_text (GTK_EDITABLE (entry), test_object_get_string (obj));
g_signal_connect (entry, "notify::text", G_CALLBACK (text_changed), obj);
}
static void
unbind_tree_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkTreeListRow *row;
GtkTreeExpander *expander;
TestObject *obj;
GtkWidget *entry;
row = gtk_list_item_get_item (item);
expander = GTK_TREE_EXPANDER (gtk_list_item_get_child (item));
obj = gtk_tree_list_row_get_item (row);
entry = gtk_tree_expander_get_child (expander);
g_signal_handlers_disconnect_by_func (entry, text_changed, obj);
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *box;
GtkWidget *label;
GtkWidget *box2;
GtkWidget *stack;
GtkWidget *switcher;
GtkWidget *sw;
GtkWidget *grid;
GtkWidget *list;
GtkWidget *cv;
GListModel *model;
GtkListItemFactory *factory;
gtk_init ();
window = gtk_window_new ();
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_window_set_child (GTK_WINDOW (window), box2);
switcher = gtk_stack_switcher_new ();
gtk_widget_set_halign (GTK_WIDGET (switcher), GTK_ALIGN_CENTER);
gtk_widget_set_margin_top (GTK_WIDGET (switcher), 10);
gtk_widget_set_margin_bottom (GTK_WIDGET (switcher), 10);
gtk_box_append (GTK_BOX (box2), switcher);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
gtk_box_append (GTK_BOX (box2), box);
label = gtk_editable_label_new ("Drag me");
gtk_box_append (GTK_BOX (box), label);
stack = gtk_stack_new ();
gtk_widget_set_vexpand (stack, TRUE);
gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER (switcher), GTK_STACK (stack));
gtk_box_append (GTK_BOX (box), stack);
/* grid */
sw = gtk_scrolled_window_new ();
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_stack_add_titled (GTK_STACK (stack), sw, "grid", "GtkGridView");
grid = gtk_grid_view_new ();
gtk_grid_view_set_min_columns (GTK_GRID_VIEW (grid), 20);
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (grid), 20);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), grid);
model = create_model (0, 400, 1, FALSE);
gtk_grid_view_set_model (GTK_GRID_VIEW (grid), model);
g_object_unref (model);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
g_signal_connect (factory, "unbind", G_CALLBACK (unbind_item), NULL);
gtk_grid_view_set_factory (GTK_GRID_VIEW (grid), factory);
g_object_unref (factory);
/* list */
sw = gtk_scrolled_window_new ();
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_stack_add_titled (GTK_STACK (stack), sw, "list", "GtkListView");
list = gtk_list_view_new ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list);
model = create_model (0, 400, 1, FALSE);
gtk_list_view_set_model (GTK_LIST_VIEW (list), model);
g_object_unref (model);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
g_signal_connect (factory, "unbind", G_CALLBACK (unbind_item), NULL);
gtk_list_view_set_factory (GTK_LIST_VIEW (list), factory);
g_object_unref (factory);
/* columnview */
sw = gtk_scrolled_window_new ();
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_stack_add_titled (GTK_STACK (stack), sw, "column", "GtkColumnView");
cv = gtk_column_view_new ();
model = create_model (0, 400, 1, FALSE);
gtk_column_view_set_model (GTK_COLUMN_VIEW (cv), model);
g_object_unref (model);
for (guint i = 0; i < 20; i++)
{
GtkColumnViewColumn *column;
char *title;
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
g_signal_connect (factory, "unbind", G_CALLBACK (unbind_item), NULL);
title = g_strdup_printf ("Column %u", i);
column = gtk_column_view_column_new_with_factory (title, factory);
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
g_object_unref (column);
g_free (title);
}
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), cv);
/* tree */
sw = gtk_scrolled_window_new ();
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_stack_add_titled (GTK_STACK (stack), sw, "tree", "Tree");
list = gtk_list_view_new ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list);
model = create_tree_model (20, 20);
gtk_list_view_set_model (GTK_LIST_VIEW (list), model);
g_object_unref (model);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_tree_item), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_tree_item), NULL);
g_signal_connect (factory, "unbind", G_CALLBACK (unbind_tree_item), NULL);
gtk_list_view_set_factory (GTK_LIST_VIEW (list), factory);
g_object_unref (factory);
gtk_window_present (GTK_WINDOW (window));
while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
g_main_context_iteration (NULL, TRUE);
gtk_window_destroy (GTK_WINDOW (window));
return 0;
}