Compare commits
266 Commits
matthiasc/
...
prop-list
Author | SHA1 | Date | |
---|---|---|---|
|
d080a2c482 | ||
|
682dbe1c9c | ||
|
3f5d6bd8b5 | ||
|
98aedb7592 | ||
|
b1fdd77ede | ||
|
ed7f507206 | ||
|
a101e8079f | ||
|
b8faadec64 | ||
|
51b4768fd7 | ||
|
8febf5e98a | ||
|
1d9e09aaca | ||
|
eecb8092dc | ||
|
ddd504ddfe | ||
|
4044a8cc6c | ||
|
05c869d19b | ||
|
57d635e1a1 | ||
|
2c1a0d3d2e | ||
|
d5d3b4b991 | ||
|
19166f15e3 | ||
|
fe31c2221c | ||
|
50e8ccf030 | ||
|
7539fe1acc | ||
|
ee03ae8b9b | ||
|
7bf21cf9d2 | ||
|
466aec41f5 | ||
|
5e9adeb9bf | ||
|
c7b2307a0b | ||
|
6e838098cb | ||
|
ee76623e54 | ||
|
36aaece297 | ||
|
4c8de636ce | ||
|
8c086dbdc7 | ||
|
f86aeaf8cd | ||
|
c814864a3f | ||
|
9e9d4d914e | ||
|
8f2351d5d3 | ||
|
4817c7757b | ||
|
a44c4b4877 | ||
|
f8a14427ea | ||
|
9d0904a445 | ||
|
4a659c169d | ||
|
5ca53555c7 | ||
|
0bbc074e08 | ||
|
7af244944a | ||
|
ae084d2929 | ||
|
fe3dd5cd8b | ||
|
3dbac6b133 | ||
|
2cb5ce8c72 | ||
|
8ae6e58e0c | ||
|
6eebc9183a | ||
|
b84780cc98 | ||
|
46a6ab68f2 | ||
|
e5c57d10d7 | ||
|
9aed6a2b56 | ||
|
843fa70bef | ||
|
2ea918a5e7 | ||
|
f7608a2119 | ||
|
f55528fd10 | ||
|
1d7322ed63 | ||
|
f3dc528e7d | ||
|
6265a60663 | ||
|
08bbf44602 | ||
|
640f165a81 | ||
|
34cbaa9057 | ||
|
2f666332ea | ||
|
972090f34d | ||
|
6ab8b1cfe5 | ||
|
84fd2290a6 | ||
|
55f9e86d67 | ||
|
9892831d52 | ||
|
baff649ca6 | ||
|
921ff0460b | ||
|
cab09d27db | ||
|
65b3a9358a | ||
|
649bcc69e3 | ||
|
2357771bd9 | ||
|
d53a0ba584 | ||
|
e2f78e95b2 | ||
|
dea3c8aed0 | ||
|
f2a82e7d35 | ||
|
9ff85899d0 | ||
|
602d141a7b | ||
|
0bed5a8b9d | ||
|
f2a50fa590 | ||
|
f833959acd | ||
|
02168260e0 | ||
|
68fbb59f82 | ||
|
e7f3a4f61a | ||
|
e32ae895e3 | ||
|
44c5d47ed8 | ||
|
a9f963b5d9 | ||
|
0a711ec0b2 | ||
|
1630482d13 | ||
|
bdaa41184f | ||
|
0a36ba0611 | ||
|
cc39cc2e8d | ||
|
51e2a51dfd | ||
|
90b32cac0b | ||
|
b56cfc5293 | ||
|
7bb1f036d6 | ||
|
0cd203b07d | ||
|
86b29d4d7a | ||
|
3ffb005135 | ||
|
a4b15d205e | ||
|
0b4f75cf25 | ||
|
163477acfb | ||
|
f80335505e | ||
|
ffdcde53f5 | ||
|
5d836b5e15 | ||
|
539213133f | ||
|
6977a03f65 | ||
|
0875374b1d | ||
|
fe1ce2aaf8 | ||
|
a81429c10f | ||
|
2f52d98ef4 | ||
|
5a076b0c2f | ||
|
69f59109ee | ||
|
6bf508ce73 | ||
|
ae26ce017b | ||
|
0a126f65fb | ||
|
6d0695260d | ||
|
a43e0b1e62 | ||
|
01d4a28c9f | ||
|
052343ca7d | ||
|
7f4260f97e | ||
|
2b42f0fcb3 | ||
|
f46c405351 | ||
|
8f4a0391b3 | ||
|
5b282411c4 | ||
|
e4392bdf5a | ||
|
e845e93f58 | ||
|
98b4269abd | ||
|
9b132b80ae | ||
|
7c402bcf2c | ||
|
6d73e3a6fa | ||
|
730575677f | ||
|
d4d07bcb2a | ||
|
01cdc67db0 | ||
|
77c9d0d0fb | ||
|
3cc9fa9f67 | ||
|
181b9655ef | ||
|
1eab9ba350 | ||
|
d1d0adeae9 | ||
|
64a2f04006 | ||
|
c835bb30d1 | ||
|
96d333f649 | ||
|
66142ae74f | ||
|
75f539b3a4 | ||
|
ad12914c55 | ||
|
f614011569 | ||
|
013db26d22 | ||
|
9fab1b3d25 | ||
|
c3bb95d7d9 | ||
|
27a891adb8 | ||
|
94b162829c | ||
|
e54f3f68a0 | ||
|
ddc665bb01 | ||
|
d0495e36e6 | ||
|
4444bb3d98 | ||
|
b9616124cb | ||
|
6218a27daf | ||
|
51ecc2d566 | ||
|
050bd6d5e3 | ||
|
0229f11784 | ||
|
cee950b455 | ||
|
3a5f47c3b8 | ||
|
484f804ba6 | ||
|
5b96335956 | ||
|
61362af27b | ||
|
fc82f5fe29 | ||
|
5ae2c1fdca | ||
|
eba9ec613d | ||
|
61fc0a6a59 | ||
|
250760468b | ||
|
9d5063cf68 | ||
|
c4af364bfb | ||
|
3e1cad5755 | ||
|
42c077443e | ||
|
7a49d2e848 | ||
|
462953cac0 | ||
|
5b5ab5c592 | ||
|
d89f9b6684 | ||
|
71f104782a | ||
|
297a2795c3 | ||
|
081645186d | ||
|
20201662f1 | ||
|
3c97226e66 | ||
|
6b4b1e1921 | ||
|
246421f92c | ||
|
603055b70d | ||
|
6a26bb0e2f | ||
|
81bc2117b2 | ||
|
f307f99275 | ||
|
8157408df8 | ||
|
9630b9f244 | ||
|
4b277dd47a | ||
|
5fcdf00a1a | ||
|
48e1a3cc06 | ||
|
8c5b077555 | ||
|
023ff509b2 | ||
|
a0a7da2e3b | ||
|
b7ae37ab3d | ||
|
6d8c6bb2f7 | ||
|
b00c04a986 | ||
|
62da088018 | ||
|
6d93197f08 | ||
|
72ce2ff512 | ||
|
cfd503893c | ||
|
a2ec02875a | ||
|
07036e28c0 | ||
|
0b3135bf14 | ||
|
2ea5607f79 | ||
|
35e516f996 | ||
|
b856fe66b9 | ||
|
7d01e25558 | ||
|
b99db2a60b | ||
|
085e4ad273 | ||
|
72dea0d5e9 | ||
|
6dd18fafaa | ||
|
9b9aec360e | ||
|
0db67c9709 | ||
|
c935bf5648 | ||
|
94a9752c43 | ||
|
de005bd1d6 | ||
|
134db60479 | ||
|
662b142c86 | ||
|
22a9001103 | ||
|
42b62c7ba2 | ||
|
8bf19f7cbf | ||
|
15dce5c26c | ||
|
742dfd919d | ||
|
b5e54c1e7d | ||
|
9756330b75 | ||
|
8126b24a78 | ||
|
9520a04d26 | ||
|
aa1d21a7ae | ||
|
1c354586d0 | ||
|
90277fba71 | ||
|
830939d8c7 | ||
|
900616ec7a | ||
|
2c047aa76f | ||
|
c1071d8c5d | ||
|
7c9ebaef3d | ||
|
90c75c8b9a | ||
|
3c96f65094 | ||
|
06fbc82ddf | ||
|
575b42c481 | ||
|
10631c979d | ||
|
c4ce8ef60f | ||
|
04df027567 | ||
|
fc0751a909 | ||
|
03815102d5 | ||
|
e8613aab9c | ||
|
b603f472ab | ||
|
b4b6be9f6e | ||
|
bb12d3d8ca | ||
|
52e385672a | ||
|
ca2ebaf90f | ||
|
46c042ed06 | ||
|
e462a2bdcc | ||
|
bb59b48871 | ||
|
da413fa72d | ||
|
75556a3485 | ||
|
53401e5d89 | ||
|
56838cab86 | ||
|
0a551b9b2a |
@@ -169,6 +169,7 @@ constraint_view_init (ConstraintView *self)
|
||||
GListModel *guides;
|
||||
GListModel *children;
|
||||
GListModel *constraints;
|
||||
GtkFilter *filter;
|
||||
|
||||
manager = gtk_constraint_layout_new ();
|
||||
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
|
||||
@@ -176,8 +177,12 @@ constraint_view_init (ConstraintView *self)
|
||||
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
|
||||
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, omit_internal, NULL, NULL);
|
||||
children = (GListModel *)gtk_filter_list_model_new (all_children, omit_internal, NULL, NULL);
|
||||
filter = gtk_custom_filter_new (omit_internal, NULL, NULL);
|
||||
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, filter);
|
||||
g_object_unref (filter);
|
||||
filter = gtk_custom_filter_new (omit_internal, NULL, NULL);
|
||||
children = (GListModel *)gtk_filter_list_model_new (all_children, filter);
|
||||
g_object_unref (filter);
|
||||
|
||||
list = g_list_store_new (G_TYPE_LIST_MODEL);
|
||||
g_list_store_append (list, children);
|
||||
|
@@ -184,58 +184,6 @@ max_input (GtkSpinButton *spin_button,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
min_output (GtkSpinButton *spin_button)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
double value;
|
||||
GtkWidget *box, *text;
|
||||
|
||||
adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
value = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
|
||||
text = gtk_widget_get_first_child (box);
|
||||
|
||||
if (value == 0.0)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
max_output (GtkSpinButton *spin_button)
|
||||
{
|
||||
GtkAdjustment *adjustment;
|
||||
double value;
|
||||
GtkWidget *box, *text;
|
||||
|
||||
adjustment = gtk_spin_button_get_adjustment (spin_button);
|
||||
value = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
|
||||
text = gtk_widget_get_first_child (box);
|
||||
|
||||
if (value == (double)G_MAXINT)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
guide_editor_constructed (GObject *object)
|
||||
{
|
||||
@@ -244,16 +192,12 @@ guide_editor_constructed (GObject *object)
|
||||
guide_strength_combo (editor->strength);
|
||||
|
||||
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
|
||||
g_signal_connect (editor->min_width, "output", G_CALLBACK (min_output), NULL);
|
||||
|
||||
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
|
||||
g_signal_connect (editor->min_height, "output", G_CALLBACK (min_output), NULL);
|
||||
|
||||
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_width, "output", G_CALLBACK (max_output), NULL);
|
||||
|
||||
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
|
||||
g_signal_connect (editor->max_height, "output", G_CALLBACK (max_output), NULL);
|
||||
|
||||
if (editor->guide)
|
||||
{
|
||||
|
247
demos/gtk-demo/award.c
Normal file
247
demos/gtk-demo/award.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright © 2018 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 "award.h"
|
||||
|
||||
struct _GtkAward
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
char *explanation;
|
||||
char *name;
|
||||
char *title;
|
||||
GDateTime *granted; /* or NULL if not granted */
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_EXPLANATION,
|
||||
PROP_NAME,
|
||||
PROP_TITLE,
|
||||
PROP_GRANTED,
|
||||
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
G_DEFINE_TYPE (GtkAward, gtk_award, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gtk_award_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_EXPLANATION:
|
||||
self->explanation = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
self->name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
self->title = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_EXPLANATION:
|
||||
g_value_set_string (value, self->explanation);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
case PROP_GRANTED:
|
||||
g_value_set_boxed (value, self->granted);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_dispose (GObject *object)
|
||||
{
|
||||
GtkAward *self = GTK_AWARD (object);
|
||||
|
||||
g_clear_pointer (&self->name, g_free);
|
||||
g_clear_pointer (&self->title, g_free);
|
||||
g_clear_pointer (&self->granted, g_date_time_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_award_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_class_init (GtkAwardClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = gtk_award_set_property;
|
||||
gobject_class->get_property = gtk_award_get_property;
|
||||
gobject_class->dispose = gtk_award_dispose;
|
||||
|
||||
properties[PROP_EXPLANATION] =
|
||||
g_param_spec_string ("explanation",
|
||||
"Explanation",
|
||||
"How to get the title",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
"Name",
|
||||
"internal name of the award",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"Title",
|
||||
"user-visible title",
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_GRANTED] =
|
||||
g_param_spec_boxed ("granted",
|
||||
"Granted",
|
||||
"Timestamp the award was granted or NULL if not granted yet",
|
||||
G_TYPE_DATE_TIME,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_award_init (GtkAward *self)
|
||||
{
|
||||
}
|
||||
|
||||
GListModel *
|
||||
gtk_award_get_list (void)
|
||||
{
|
||||
static GListModel *list = NULL;
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
|
||||
g_type_ensure (GTK_TYPE_AWARD);
|
||||
builder = gtk_builder_new_from_resource ("/awards.ui");
|
||||
list = G_LIST_MODEL (gtk_builder_get_object (builder, "list"));
|
||||
g_object_ref (list);
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
return g_object_ref (list);
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_award_get_name (GtkAward *award)
|
||||
{
|
||||
return award->name;
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_award_get_title (GtkAward *award)
|
||||
{
|
||||
return award->title;
|
||||
}
|
||||
|
||||
GDateTime *
|
||||
gtk_award_get_granted (GtkAward *award)
|
||||
{
|
||||
return award->granted;
|
||||
}
|
||||
|
||||
GtkAward *
|
||||
award_find (const char *name)
|
||||
{
|
||||
GListModel *list;
|
||||
GtkAward *self;
|
||||
guint i;
|
||||
|
||||
list = gtk_award_get_list ();
|
||||
g_object_unref (list);
|
||||
|
||||
for (i = 0; i < g_list_model_get_n_items (list); i++)
|
||||
{
|
||||
self = g_list_model_get_item (list, i);
|
||||
g_object_unref (self);
|
||||
|
||||
if (g_ascii_strcasecmp (name, self->name) == 0)
|
||||
return self;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
award (const char *name)
|
||||
{
|
||||
GtkAward *self;
|
||||
GNotification *notification;
|
||||
|
||||
self = award_find (name);
|
||||
if (self == NULL)
|
||||
{
|
||||
g_warning ("Did not find award \"%s\"", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->granted)
|
||||
return;
|
||||
|
||||
self->granted = g_date_time_new_now_utc ();
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_GRANTED]);
|
||||
|
||||
notification = g_notification_new ("You won an award!");
|
||||
g_notification_set_body (notification, self->title);
|
||||
g_application_send_notification (g_application_get_default (), NULL, notification);
|
||||
g_object_unref (notification);
|
||||
}
|
||||
|
18
demos/gtk-demo/award.h
Normal file
18
demos/gtk-demo/award.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef __AWARD_H__
|
||||
#define __AWARD_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_AWARD (gtk_award_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkAward, gtk_award, GTK, AWARD, GObject)
|
||||
|
||||
GListModel * gtk_award_get_list (void);
|
||||
|
||||
const char * gtk_award_get_name (GtkAward *award);
|
||||
const char * gtk_award_get_title (GtkAward *award);
|
||||
GDateTime * gtk_award_get_granted (GtkAward *award);
|
||||
|
||||
void award (const char *name);
|
||||
|
||||
#endif /* __AWARD_H__ */
|
11
demos/gtk-demo/awardlistitem.ui
Normal file
11
demos/gtk-demo/awardlistitem.ui
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface domain="gtk40">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="label" bind-source="GtkListItem" bind-property="position"></property>
|
||||
<property name="margin">6</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
89
demos/gtk-demo/awards.ui
Normal file
89
demos/gtk-demo/awards.ui
Normal file
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GListStore" id="list">
|
||||
<property name="item-type">GtkAward</property>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">demo-inspector</property>
|
||||
<!-- Transformers -->
|
||||
<property name="title" translatable="yes">You got a high-rise double-pump carburetor.</property>
|
||||
<property name="explanation" translatable="yes">Launch the inspector</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">demo-start</property>
|
||||
<!-- The Matrix -->
|
||||
<property name="title" translatable="yes">After this, there is no turning back.</property>
|
||||
<property name="explanation" translatable="yes">Start gtk-demo</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">listbox-reshare</property>
|
||||
<!-- Mean Girls -->
|
||||
<property name="title" translatable="yes">Trying to make fetch happen</property>
|
||||
<property name="explanation" translatable="yes">Reshare a tweet</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">listbox-100th-row</property>
|
||||
<!-- Aladdin -->
|
||||
<property name="title" translatable="yes">The ever impressive, long contained, often imitated, but never duplicated Genie of the lamp.</property>
|
||||
<property name="explanation" translatable="yes">Select a 100th row in a list</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">password-best</property>
|
||||
<!-- Spaceballs -->
|
||||
<property name="title" translatable="yes">I've got the same combination on my luggage!</property>
|
||||
<property name="explanation" translatable="yes">Use "12345" as the password</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">password-correct</property>
|
||||
<!-- Stanley Parable -->
|
||||
<property name="title" translatable="yes">Night Shark 1-1-5</property>
|
||||
<property name="explanation" translatable="yes">Correctly enter a password</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-give-up</property>
|
||||
<!-- Pretty Woman -->
|
||||
<property name="title" translatable="yes">Big Mistake. Big. Huge!</property>
|
||||
<property name="explanation" translatable="yes">Close the puzzle without finishing it</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve</property>
|
||||
<!-- The Incredibles -->
|
||||
<property name="title" translatable="yes">That was totally wicked!</property>
|
||||
<property name="explanation" translatable="yes">Solve a puzzle</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve-animated</property>
|
||||
<!-- The Phantom Menace -->
|
||||
<property name="title" translatable="yes">A surprise to be sure but a welcome one.</property>
|
||||
<property name="explanation" translatable="yes">Solve an animated puzzle</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkAward">
|
||||
<property name="name">puzzle-solve-large</property>
|
||||
<!-- Portal -->
|
||||
<property name="title" translatable="yes">Science isn't about WHY. It's about WHY NOT?!</property>
|
||||
<property name="explanation" translatable="yes">Solve a puzzle with at least 20 pieces</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
49
demos/gtk-demo/awardview.c
Normal file
49
demos/gtk-demo/awardview.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Awards
|
||||
*
|
||||
* This demo demonstrates how to use lists to show the awards you have collected
|
||||
* while exploring this demo.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* Include the header for accessing the awards */
|
||||
#include "award.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_awardview (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *sw, *listview;
|
||||
GListModel *list;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Awards");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
|
||||
listview = gtk_list_view_new_with_factory (
|
||||
gtk_builder_list_item_factory_new_from_resource (NULL, "/awardview/awardlistitem.ui"));
|
||||
list = gtk_award_get_list ();
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), list);
|
||||
g_object_unref (list);
|
||||
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (sw), listview);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
9344
demos/gtk-demo/color.names.txt
Normal file
9344
demos/gtk-demo/color.names.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gresources>
|
||||
<gresource prefix="/">
|
||||
<file>awards.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/ui">
|
||||
<file preprocess="xml-stripblanks">main.ui</file>
|
||||
<file preprocess="xml-stripblanks">main-listitem.ui</file>
|
||||
<file preprocess="xml-stripblanks">appmenu.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/application_demo">
|
||||
@@ -9,6 +13,9 @@
|
||||
<file>application.ui</file>
|
||||
<file>menus.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/awardview">
|
||||
<file>awardlistitem.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/builder">
|
||||
<file>demo.ui</file>
|
||||
</gresource>
|
||||
@@ -111,6 +118,22 @@
|
||||
<file>gnome-fs-directory.png</file>
|
||||
<file>gnome-fs-regular.png</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_filebrowser">
|
||||
<file>listview_filebrowser.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_minesweeper">
|
||||
<file>listview_minesweeper.ui</file>
|
||||
<file>listview_minesweeper_cell.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_settings">
|
||||
<file>listview_settings.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_weather">
|
||||
<file compressed="true">listview_weather.txt</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_colors">
|
||||
<file compressed="true">color.names.txt</file>
|
||||
</gresource>
|
||||
<gresource prefix="/shortcuts">
|
||||
<file>shortcuts.ui</file>
|
||||
<file>shortcuts-builder.ui</file>
|
||||
@@ -147,6 +170,7 @@
|
||||
</gresource>
|
||||
<gresource prefix="/sources">
|
||||
<file>application_demo.c</file>
|
||||
<file>awardview.c</file>
|
||||
<file>assistant.c</file>
|
||||
<file>builder.c</file>
|
||||
<file>changedisplay.c</file>
|
||||
@@ -189,6 +213,13 @@
|
||||
<file>infobar.c</file>
|
||||
<file>links.c</file>
|
||||
<file>listbox.c</file>
|
||||
<file>listview_applauncher.c</file>
|
||||
<file>listview_colors.c</file>
|
||||
<file>listview_clocks.c</file>
|
||||
<file>listview_filebrowser.c</file>
|
||||
<file>listview_minesweeper.c</file>
|
||||
<file>listview_settings.c</file>
|
||||
<file>listview_weather.c</file>
|
||||
<file>list_store.c</file>
|
||||
<file>markup.c</file>
|
||||
<file>menus.c</file>
|
||||
|
@@ -265,6 +265,14 @@ fishbowl_changes_toggled_cb (GtkToggleButton *button,
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "changes-allow");
|
||||
}
|
||||
|
||||
char *
|
||||
format_header_cb (GObject *object,
|
||||
guint count,
|
||||
double fps)
|
||||
{
|
||||
return g_strdup_printf ("%u Icons, %.2f fps", count, fps);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_fishbowl (GtkWidget *do_widget)
|
||||
{
|
||||
|
@@ -28,22 +28,12 @@
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">fps</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel">
|
||||
<property name="label" bind-source="bowl" bind-property="framerate-string"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Icons, </property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel">
|
||||
<property name="label" bind-source="bowl" bind-property="count"/>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="format_header_cb">
|
||||
<lookup name="count">bowl</lookup>
|
||||
<lookup name="framerate">bowl</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
|
@@ -4,6 +4,8 @@
|
||||
* as needed and support sorting and filtering.
|
||||
*
|
||||
* The children of a GtkFlowBox are regular widgets
|
||||
*
|
||||
* The dataset used here has 665 colors.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
@@ -13,17 +13,16 @@ in_files = sys.argv[2:]
|
||||
file_output = """
|
||||
typedef GtkWidget *(*GDoDemoFunc) (GtkWidget *do_widget);
|
||||
|
||||
typedef struct _Demo Demo;
|
||||
typedef struct _DemoData DemoData;
|
||||
|
||||
struct _Demo
|
||||
struct _DemoData
|
||||
{
|
||||
gchar *name;
|
||||
gchar *title;
|
||||
gchar *filename;
|
||||
char *name;
|
||||
char *title;
|
||||
char *filename;
|
||||
GDoDemoFunc func;
|
||||
Demo *children;
|
||||
DemoData *children;
|
||||
};
|
||||
|
||||
"""
|
||||
|
||||
# Demo = namedtuple('Demo', ['name', 'title', 'file', 'func'])
|
||||
@@ -67,7 +66,7 @@ for demo in demos:
|
||||
i = 0
|
||||
for parent in parents:
|
||||
id = parent_ids[i]
|
||||
file_output += "\nDemo child" + str(id) + "[] = {\n"
|
||||
file_output += "\nDemoData child" + str(id) + "[] = {\n"
|
||||
# iterate over all demos and check if the name starts with the given parent name
|
||||
for child in demos:
|
||||
if child[1].startswith(parent + "/"):
|
||||
@@ -82,7 +81,7 @@ for parent in parents:
|
||||
# Sort demos by title
|
||||
demos = sorted(demos, key=lambda x: x[1])
|
||||
|
||||
file_output += "\nDemo gtk_demos[] = {\n"
|
||||
file_output += "\nDemoData gtk_demos[] = {\n"
|
||||
for demo in demos:
|
||||
# Do not generate one of these for demos with a parent demo
|
||||
if "/" not in demo[1]:
|
||||
|
@@ -53,7 +53,6 @@ enum {
|
||||
PROP_BENCHMARK,
|
||||
PROP_COUNT,
|
||||
PROP_FRAMERATE,
|
||||
PROP_FRAMERATE_STRING,
|
||||
PROP_UPDATE_DELAY,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
@@ -289,14 +288,6 @@ gtk_fishbowl_get_property (GObject *object,
|
||||
g_value_set_double (value, gtk_fishbowl_get_framerate (fishbowl));
|
||||
break;
|
||||
|
||||
case PROP_FRAMERATE_STRING:
|
||||
{
|
||||
char *s = g_strdup_printf ("%.2f", gtk_fishbowl_get_framerate (fishbowl));
|
||||
g_value_set_string (value, s);
|
||||
g_free (s);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_DELAY:
|
||||
g_value_set_int64 (value, gtk_fishbowl_get_update_delay (fishbowl));
|
||||
break;
|
||||
@@ -350,13 +341,6 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
|
||||
0,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
props[PROP_FRAMERATE_STRING] =
|
||||
g_param_spec_string ("framerate-string",
|
||||
"Framerate as string",
|
||||
"Framerate as string, with 2 decimals",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
props[PROP_UPDATE_DELAY] =
|
||||
g_param_spec_int64 ("update-delay",
|
||||
"Update delay",
|
||||
@@ -508,7 +492,6 @@ gtk_fishbowl_do_update (GtkFishbowl *fishbowl)
|
||||
priv->framerate = ((int)(priv->framerate * 100))/100.0;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE]);
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE_STRING]);
|
||||
|
||||
if (!priv->benchmark)
|
||||
return;
|
||||
|
@@ -12,7 +12,7 @@ static GtkWidget *window = NULL;
|
||||
static GtkWidget *scrolledwindow;
|
||||
static int selected;
|
||||
|
||||
#define N_WIDGET_TYPES 4
|
||||
#define N_WIDGET_TYPES 6
|
||||
|
||||
|
||||
static int hincrement = 5;
|
||||
@@ -61,6 +61,7 @@ populate_icons (void)
|
||||
gtk_grid_attach (GTK_GRID (grid), create_icon (), left, top, 1, 1);
|
||||
|
||||
hincrement = 0;
|
||||
vincrement = 5;
|
||||
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
|
||||
GTK_POLICY_NEVER,
|
||||
@@ -97,6 +98,7 @@ populate_text (gboolean hilight)
|
||||
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
|
||||
|
||||
hincrement = 0;
|
||||
vincrement = 5;
|
||||
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
|
||||
GTK_POLICY_NEVER,
|
||||
@@ -121,6 +123,7 @@ populate_image (void)
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (image), FALSE);
|
||||
|
||||
hincrement = 5;
|
||||
vincrement = 5;
|
||||
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
@@ -128,6 +131,42 @@ populate_image (void)
|
||||
gtk_container_add (GTK_CONTAINER (scrolledwindow), image);
|
||||
}
|
||||
|
||||
extern GtkWidget *create_weather_view (void);
|
||||
|
||||
static void
|
||||
populate_list (void)
|
||||
{
|
||||
GtkWidget *list;
|
||||
|
||||
list = create_weather_view ();
|
||||
|
||||
hincrement = 5;
|
||||
vincrement = 0;
|
||||
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_container_add (GTK_CONTAINER (scrolledwindow), list);
|
||||
}
|
||||
|
||||
extern GtkWidget *create_color_grid (void);
|
||||
|
||||
static void
|
||||
populate_grid (void)
|
||||
{
|
||||
GtkWidget *list;
|
||||
|
||||
list = create_color_grid ();
|
||||
|
||||
hincrement = 0;
|
||||
vincrement = 5;
|
||||
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_container_add (GTK_CONTAINER (scrolledwindow), list);
|
||||
}
|
||||
|
||||
static void
|
||||
set_widget_type (int type)
|
||||
{
|
||||
@@ -162,6 +201,16 @@ set_widget_type (int type)
|
||||
populate_image ();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a list");
|
||||
populate_list ();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a grid");
|
||||
populate_grid ();
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "award.h"
|
||||
|
||||
static GdkPixbuf *avatar_pixbuf_other;
|
||||
static GtkWidget *window = NULL;
|
||||
@@ -234,9 +235,9 @@ reshare_clicked (GtkMessageRow *row,
|
||||
{
|
||||
GtkMessageRowPrivate *priv = row->priv;
|
||||
|
||||
award ("listbox-reshare");
|
||||
priv->message->n_reshares++;
|
||||
gtk_message_row_update (row);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -255,11 +256,14 @@ gtk_message_row_state_flags_changed (GtkWidget *widget,
|
||||
{
|
||||
GtkMessageRowPrivate *priv = GTK_MESSAGE_ROW (widget)->priv;
|
||||
GtkStateFlags flags;
|
||||
gboolean visible;
|
||||
|
||||
flags = gtk_widget_get_state_flags (widget);
|
||||
|
||||
gtk_widget_set_visible (priv->extra_buttons_box,
|
||||
flags & (GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED));
|
||||
visible = flags & (GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED) ? TRUE : FALSE;
|
||||
gtk_widget_set_visible (priv->extra_buttons_box, visible);
|
||||
if (visible && gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (widget)) % 100 == 99)
|
||||
award ("listbox-100th-row");
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_message_row_parent_class)->state_flags_changed (widget, previous_state_flags);
|
||||
}
|
||||
|
200
demos/gtk-demo/listview_applauncher.c
Normal file
200
demos/gtk-demo/listview_applauncher.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/* Lists/Application launcher
|
||||
*
|
||||
* This demo uses the GtkCoverFlow widget as a fancy application launcher.
|
||||
*
|
||||
* It is also a very small introduction to listviews.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* This is the function that creates the #GListModel that we need.
|
||||
* GTK list widgets need a #GListModel to display, as models support change
|
||||
* notifications.
|
||||
* Unfortunately various older APIs do not provide list models, so we create
|
||||
* our own.
|
||||
*/
|
||||
static GListModel *
|
||||
create_application_list (void)
|
||||
{
|
||||
GListStore *store;
|
||||
GList *apps, *l;
|
||||
|
||||
/* We use a #GListStore here, which is a simple array-like list implementation
|
||||
* for manual management.
|
||||
* List models need to know what type of data they provide, so we need to
|
||||
* provide the type here. As we want to do a list of applications, #GAppInfo
|
||||
* is the object we provide.
|
||||
*/
|
||||
store = g_list_store_new (G_TYPE_APP_INFO);
|
||||
|
||||
apps = g_app_info_get_all ();
|
||||
|
||||
for (l = apps; l; l = l->next)
|
||||
{
|
||||
g_list_store_append (store, l->data);
|
||||
}
|
||||
|
||||
g_list_free_full (apps, g_object_unref);
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
/* This is the function we use for setting up new listitems to display.
|
||||
* We add just a #GtkImage here to display the application's icon as this is just
|
||||
* a simple demo.
|
||||
*/
|
||||
static void
|
||||
setup_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *image;
|
||||
|
||||
image = gtk_image_new ();
|
||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||
|
||||
gtk_list_item_set_child (list_item, image);
|
||||
}
|
||||
|
||||
/* Here we need to prepare the listitem for displaying its item. We get the
|
||||
* listitem already set up from the previous function, so we can reuse the
|
||||
* #GtkImage widget we set up above.
|
||||
* We get the item - which we know is a #GAppInfo because it comes out of
|
||||
* the model we set up above, grab its icon and display it.
|
||||
*/
|
||||
static void
|
||||
bind_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GAppInfo *app_info;
|
||||
|
||||
image = gtk_list_item_get_child (list_item);
|
||||
app_info = gtk_list_item_get_item (list_item);
|
||||
|
||||
gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (app_info));
|
||||
}
|
||||
|
||||
/* In more complex code, we would also need functions to unbind and teardown
|
||||
* the listitem, but this is simple code, so the default implementations are
|
||||
* enough. If we had connected signals, this step would have been necessary.
|
||||
*
|
||||
* The #GtkSignalListItemFactory documentation contains more information about
|
||||
* this step.
|
||||
*/
|
||||
|
||||
/* This function is called whenever an item in the list is activated. This is
|
||||
* the simple way to allow reacting to the Enter key or double-clicking on a
|
||||
* listitem.
|
||||
* Of course, it is possible to use far more complex interactions by turning
|
||||
* off activation and adding buttons or other widgets in the setup function
|
||||
* above, but this is a simple demo, so we'll use the simple way.
|
||||
*/
|
||||
static void
|
||||
activate_cb (GtkCoverFlow *coverflow,
|
||||
guint position,
|
||||
gpointer unused)
|
||||
{
|
||||
GAppInfo *app_info;
|
||||
GdkAppLaunchContext *context;
|
||||
GError *error = NULL;
|
||||
|
||||
app_info = g_list_model_get_item (gtk_cover_flow_get_model (coverflow), position);
|
||||
|
||||
/* Prepare the context for launching the application and launch it. This
|
||||
* code is explained in detail in the documentation for #GdkAppLaunchContext
|
||||
* and #GAppInfo.
|
||||
*/
|
||||
context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (coverflow)));
|
||||
if (!g_app_info_launch (app_info,
|
||||
NULL,
|
||||
G_APP_LAUNCH_CONTEXT (context),
|
||||
&error))
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
/* And because error handling is important, even a simple demo has it:
|
||||
* We display an error dialog that something went wrong.
|
||||
*/
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (coverflow))),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
"Could not launch %s", g_app_info_get_display_name (app_info));
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
|
||||
g_clear_error (&error);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
g_object_unref (context);
|
||||
g_object_unref (app_info);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_applauncher (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *coverflow, *sw;;
|
||||
GListModel *model;
|
||||
GtkListItemFactory *factory;
|
||||
|
||||
/* Create a window and set a few defaults */
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 640, 320);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Application Launcher");
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK(gtk_widget_destroyed), &window);
|
||||
|
||||
/* The #GtkListitemFactory is what is used to create #GtkListItems
|
||||
* to display the data from the model. So it is absolutely necessary
|
||||
* to create one.
|
||||
* We will use a #GtkSignalListItemFactory because it is the simplest
|
||||
* one to use. Different ones are available for different use cases.
|
||||
* The most powerful one is #GtkBuilderListItemFactory which uses
|
||||
* #GtkBuilder .ui files, so it requires little code.
|
||||
*/
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL);
|
||||
|
||||
/* Create the list widget here: We use a coverflow widget because it's
|
||||
* the coolest one. We could just as well use other list widgets such
|
||||
* as a #GtkListView or a #GtkGridView and the code would look very
|
||||
* similar.
|
||||
*/
|
||||
coverflow = gtk_cover_flow_new_with_factory (factory);
|
||||
/* We connect the activate signal here. It's the function we defined
|
||||
* above for launching the selected application.
|
||||
*/
|
||||
g_signal_connect (coverflow, "activate", G_CALLBACK (activate_cb), NULL);
|
||||
|
||||
/* And of course we need to set the data model. Here we call the function
|
||||
* we wrote above that gives us the list of applications. Then we set
|
||||
* it on the coverflow list widget.
|
||||
* The coverflow will now take items from the model and use the factory
|
||||
* to create as many listitems as it needs to show itself to the user.
|
||||
*/
|
||||
model = create_application_list ();
|
||||
gtk_cover_flow_set_model (GTK_COVER_FLOW (coverflow), model);
|
||||
g_object_unref (model);
|
||||
|
||||
/* List widgets should always be contained in a #GtkScrolledWindow,
|
||||
* because otherwise they might get too large or they might not
|
||||
* be scrollable.
|
||||
*/
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
gtk_container_add (GTK_CONTAINER (sw), coverflow);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
491
demos/gtk-demo/listview_clocks.c
Normal file
491
demos/gtk-demo/listview_clocks.c
Normal file
@@ -0,0 +1,491 @@
|
||||
/* Lists/Clocks
|
||||
*
|
||||
* This demo displays the time in different timezones.
|
||||
*
|
||||
* It is using a GtkGridView.
|
||||
*
|
||||
* The goal is to show how to set up expressions that track changes
|
||||
* in objects and make them update widgets. For that, we create a
|
||||
* GtkClock object that updates its time every second and then use
|
||||
* various ways to display that time.
|
||||
*
|
||||
* Typically, this will be done using GtkBuilder .ui files with the
|
||||
* help of the <binding> tag, but this demo shows the code that runs
|
||||
* behind that.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_CLOCK (gtk_clock_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkClock, gtk_clock, GTK, CLOCK, GObject)
|
||||
|
||||
/* This is our object. It's just a timezone */
|
||||
typedef struct _GtkClock GtkClock;
|
||||
struct _GtkClock
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
/* We allow this to be NULL for the local timezone */
|
||||
GTimeZone *timezone;
|
||||
/* Name of the location we're displaying time for */
|
||||
char *location;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LOCATION,
|
||||
PROP_TIME,
|
||||
PROP_TIMEZONE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
/* This function returns the current time in the clock's timezone.
|
||||
* Note that this returns a new object every time, so we need to
|
||||
* remember to unref it after use. */
|
||||
static GDateTime *
|
||||
gtk_clock_get_time (GtkClock *clock)
|
||||
{
|
||||
if (clock->timezone)
|
||||
return g_date_time_new_now (clock->timezone);
|
||||
else
|
||||
return g_date_time_new_now_local ();
|
||||
}
|
||||
|
||||
/* Here, we implement the functionality required by the GdkPaintable interface.
|
||||
* This way we have a trivial way to display an analog clock.
|
||||
* It also allows demonstrating how to directly use objects in the listview
|
||||
* later by making this object do something interesting. */
|
||||
static void
|
||||
gtk_clock_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
GtkClock *self = GTK_CLOCK (paintable);
|
||||
GDateTime *time;
|
||||
GskRoundedRect outline;
|
||||
|
||||
#define BLACK ((GdkRGBA) { 0, 0, 0, 1 })
|
||||
|
||||
/* save/restore() is necessary so we can undo the transforms we start
|
||||
* out with. */
|
||||
gtk_snapshot_save (snapshot);
|
||||
|
||||
/* First, we move the (0, 0) point to the center of the area so
|
||||
* we can draw everything relative to it. */
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2, height / 2));
|
||||
/* Next we scale it, so that we can pretend that the clock is
|
||||
* 100px in size. That way, we don't need to do any complicated
|
||||
* math later.
|
||||
* We use MIN() here so that we use the smaller dimension for sizing.
|
||||
* That way we don't overdraw but keep the aspect ratio. */
|
||||
gtk_snapshot_scale (snapshot, MIN (width, height) / 100.0, MIN (width, height) / 100.0);
|
||||
/* Now we have a circle with diameter 100px (and radius 50px) that
|
||||
* has its (0, 0) point at the center.
|
||||
* Let's draw a simple clock into it. */
|
||||
|
||||
time = gtk_clock_get_time (self);
|
||||
|
||||
/* First, draw a circle. This is a neat little trick to draw a circle
|
||||
* without requiring Cairo. */
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-50, -50, 100, 100), 50);
|
||||
gtk_snapshot_append_border (snapshot,
|
||||
&outline,
|
||||
(float[4]) { 4, 4, 4, 4 },
|
||||
(GdkRGBA [4]) { BLACK, BLACK, BLACK, BLACK });
|
||||
|
||||
/* Next, draw the hour hand.
|
||||
* We do this using tranforms again: Instead of computing where the angle points
|
||||
* to, we just rotate everything and then draw the hand as if if was :00.
|
||||
* We don't even need to care about am/pm here because rotations just work. */
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_rotate (snapshot, 30 * g_date_time_get_hour (time) + 0.5 * g_date_time_get_minute (time));
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -23, 4, 25), 2);
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &outline);
|
||||
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
/* And the same as above for the minute hand. Just make this one longer
|
||||
* so people can tell the hands apart. */
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_minute (time));
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 45), 2);
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &outline);
|
||||
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
/* and finally, the second indicator. */
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_second (time));
|
||||
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 10), 2);
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &outline);
|
||||
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
/* And finally, don't forget to restore the initial save() that we did for
|
||||
* the initial transformations. */
|
||||
gtk_snapshot_restore (snapshot);
|
||||
|
||||
g_date_time_unref (time);
|
||||
}
|
||||
|
||||
/* Our desired size is 100px. That sounds okay for an analog clock */
|
||||
static int
|
||||
gtk_clock_get_intrinsic_width (GdkPaintable *paintable)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_clock_get_intrinsic_height (GdkPaintable *paintable)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
/* Initialize the paintable interface. This way we turn our clock objects
|
||||
* into objects that can be drawn.
|
||||
* There are more functions to this interface to define desired size,
|
||||
* but this is enough.
|
||||
*/
|
||||
static void
|
||||
gtk_clock_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = gtk_clock_snapshot;
|
||||
iface->get_intrinsic_width = gtk_clock_get_intrinsic_width;
|
||||
iface->get_intrinsic_height = gtk_clock_get_intrinsic_height;
|
||||
}
|
||||
|
||||
/* Finally, we define the type. The important part is adding the paintable
|
||||
* interface, so GTK knows that this object can indeed be drawm.
|
||||
*/
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkClock, gtk_clock, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gtk_clock_paintable_init))
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_clock_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkClock *self = GTK_CLOCK (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_LOCATION:
|
||||
g_value_set_string (value, self->location);
|
||||
break;
|
||||
|
||||
case PROP_TIME:
|
||||
g_value_take_boxed (value, gtk_clock_get_time (self));
|
||||
break;
|
||||
|
||||
case PROP_TIMEZONE:
|
||||
g_value_set_boxed (value, self->timezone);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkClock *self = GTK_CLOCK (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_LOCATION:
|
||||
self->location = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_TIMEZONE:
|
||||
self->timezone = g_value_dup_boxed (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the list of all the ticking clocks */
|
||||
static GSList *ticking_clocks = NULL;
|
||||
/* This is the id of the timeout source that is updating all ticking clocks */
|
||||
static guint ticking_clock_id = 0;
|
||||
|
||||
/* Every second, this function is called to tell everybody that the
|
||||
* clocks are ticking.
|
||||
*/
|
||||
static gboolean
|
||||
gtk_clock_tick (gpointer unused)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = ticking_clocks; l; l = l->next)
|
||||
{
|
||||
GtkClock *clock = l->data;
|
||||
|
||||
/* We will now return a different value for the time porperty,
|
||||
* so notify about that.
|
||||
*/
|
||||
g_object_notify_by_pspec (G_OBJECT (clock), properties[PROP_TIME]);
|
||||
/* We will also draw the hands of the clock differently.
|
||||
* So notify about that, too.
|
||||
*/
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (clock));
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_stop_ticking (GtkClock *self)
|
||||
{
|
||||
ticking_clocks = g_slist_remove (ticking_clocks, self);
|
||||
|
||||
/* If no clock is remaining, stop running the tick updates */
|
||||
if (ticking_clocks == NULL && ticking_clock_id != 0)
|
||||
g_clear_handle_id (&ticking_clock_id, g_source_remove);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_start_ticking (GtkClock *self)
|
||||
{
|
||||
/* if no clock is ticking yet, start */
|
||||
if (ticking_clock_id == 0)
|
||||
ticking_clock_id = g_timeout_add_seconds (1, gtk_clock_tick, NULL);
|
||||
|
||||
ticking_clocks = g_slist_prepend (ticking_clocks, self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_finalize (GObject *object)
|
||||
{
|
||||
GtkClock *self = GTK_CLOCK (object);
|
||||
|
||||
gtk_clock_stop_ticking (self);
|
||||
|
||||
g_free (self->location);
|
||||
g_clear_pointer (&self->timezone, g_time_zone_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_clock_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_class_init (GtkClockClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = gtk_clock_get_property;
|
||||
gobject_class->set_property = gtk_clock_set_property;
|
||||
gobject_class->finalize = gtk_clock_finalize;
|
||||
|
||||
properties[PROP_LOCATION] =
|
||||
g_param_spec_string ("location", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
properties[PROP_TIME] =
|
||||
g_param_spec_boxed ("time", NULL, NULL, G_TYPE_DATE_TIME, G_PARAM_READABLE);
|
||||
properties[PROP_TIMEZONE] =
|
||||
g_param_spec_boxed ("timezone", NULL, NULL, G_TYPE_TIME_ZONE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_clock_init (GtkClock *self)
|
||||
{
|
||||
gtk_clock_start_ticking (self);
|
||||
}
|
||||
|
||||
static GtkClock *
|
||||
gtk_clock_new (const char *location,
|
||||
GTimeZone *timezone)
|
||||
{
|
||||
GtkClock *result;
|
||||
|
||||
result = g_object_new (GTK_TYPE_CLOCK,
|
||||
"location", location,
|
||||
"timezone", timezone,
|
||||
NULL);
|
||||
|
||||
g_clear_pointer (&timezone, g_time_zone_unref);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_clocks_model (void)
|
||||
{
|
||||
GListStore *result;
|
||||
GtkClock *clock;
|
||||
|
||||
result = g_list_store_new (GTK_TYPE_CLOCK);
|
||||
|
||||
/* local time */
|
||||
clock = gtk_clock_new ("local", NULL);
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
/* UTC time */
|
||||
clock = gtk_clock_new ("UTC", g_time_zone_new_utc ());
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
/* A bunch of timezones with GTK hackers */
|
||||
clock = gtk_clock_new ("San Francisco", g_time_zone_new ("America/Los_Angeles"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Boston", g_time_zone_new ("America/New_York"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("London", g_time_zone_new ("Europe/London"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Berlin", g_time_zone_new ("Europe/Berlin"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Moscow", g_time_zone_new ("Europe/Moscow"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("New Delhi", g_time_zone_new ("Asia/Kolkata"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
clock = gtk_clock_new ("Shanghai", g_time_zone_new ("Asia/Shanghai"));
|
||||
g_list_store_append (result, clock);
|
||||
g_object_unref (clock);
|
||||
|
||||
return G_LIST_MODEL (result);
|
||||
}
|
||||
|
||||
static char *
|
||||
convert_time_to_string (GObject *image,
|
||||
GDateTime *time,
|
||||
gpointer unused)
|
||||
{
|
||||
return g_date_time_format (time, "%x\n%X");
|
||||
}
|
||||
|
||||
/* And this function is the crux for this whole demo.
|
||||
* It shows how to use expressions to set up bindings.
|
||||
*/
|
||||
static void
|
||||
setup_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box, *picture, *location_label, *time_label;
|
||||
GtkExpression *clock_expression, *expression;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_list_item_set_child (list_item, box);
|
||||
|
||||
/* First, we create an expression that gets us the clock from the listitem:
|
||||
* 1. Create an expression that gets the list item.
|
||||
* 2. Use that expression's "item" property to get the clock
|
||||
*/
|
||||
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
|
||||
clock_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
|
||||
|
||||
/* Bind the clock's location to a label.
|
||||
* This is easy: We just get the "location" property of the clock.
|
||||
*/
|
||||
expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
|
||||
gtk_expression_ref (clock_expression),
|
||||
"location");
|
||||
/* Now create the label and bind the expression to it. */
|
||||
location_label = gtk_label_new (NULL);
|
||||
gtk_expression_bind (expression, location_label, "label", location_label);
|
||||
gtk_container_add (GTK_CONTAINER (box), location_label);
|
||||
|
||||
|
||||
/* Here we bind the item itself to a GdkPicture.
|
||||
* This is simply done by using the clock expression itself.
|
||||
*/
|
||||
expression = gtk_expression_ref (clock_expression);
|
||||
/* Now create the widget and bind the expression to it. */
|
||||
picture = gtk_picture_new ();
|
||||
gtk_expression_bind (expression, picture, "paintable", picture);
|
||||
gtk_container_add (GTK_CONTAINER (box), picture);
|
||||
|
||||
|
||||
/* And finally, everything comes together.
|
||||
* We create a label for displaying the time as text.
|
||||
* For that, we need to transform the "GDateTime" of the
|
||||
* time property into a string so that the label can display it.
|
||||
*/
|
||||
expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
|
||||
gtk_expression_ref (clock_expression),
|
||||
"time");
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
|
||||
NULL,
|
||||
1, (GtkExpression *[1]) { expression },
|
||||
G_CALLBACK (convert_time_to_string),
|
||||
NULL, NULL);
|
||||
/* Now create the label and bind the expression to it. */
|
||||
time_label = gtk_label_new (NULL);
|
||||
gtk_expression_bind (expression, time_label, "label", time_label);
|
||||
gtk_container_add (GTK_CONTAINER (box), time_label);
|
||||
|
||||
gtk_expression_unref (clock_expression);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_clocks (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *gridview, *sw;
|
||||
GtkListItemFactory *factory;
|
||||
GListModel *model;
|
||||
GtkNoSelection *selection;
|
||||
|
||||
/* This is the normal window setup code every demo does */
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Clocks");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
/* List widgets go into a scrolled window. Always. */
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
|
||||
/* Create the factory that creates the listitems. Because we
|
||||
* used bindings above during setup, we only need to connect
|
||||
* to the setup signal.
|
||||
* The bindings take care of the bind step.
|
||||
*/
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
|
||||
|
||||
gridview = gtk_grid_view_new_with_factory (factory);
|
||||
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
gtk_scrollable_set_vscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
|
||||
model = create_clocks_model ();
|
||||
selection = gtk_no_selection_new (model);
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), G_LIST_MODEL (selection));
|
||||
gtk_container_add (GTK_CONTAINER (sw), gridview);
|
||||
g_object_unref (selection);
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
593
demos/gtk-demo/listview_colors.c
Normal file
593
demos/gtk-demo/listview_colors.c
Normal file
@@ -0,0 +1,593 @@
|
||||
/* Lists/Colors
|
||||
*
|
||||
* This demo displays a named colors.
|
||||
*
|
||||
* It is using a GtkGridView, and shows
|
||||
* how to sort the data in various ways.
|
||||
*
|
||||
* The dataset used here has 9283 items.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_COLOR (gtk_color_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkColor, gtk_color, GTK, COLOR, GObject)
|
||||
|
||||
/* This is our object. It's just a color */
|
||||
typedef struct _GtkColor GtkColor;
|
||||
struct _GtkColor
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *name;
|
||||
GdkRGBA *color;
|
||||
int h, s, v;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_COLOR,
|
||||
PROP_RED,
|
||||
PROP_GREEN,
|
||||
PROP_BLUE,
|
||||
PROP_HUE,
|
||||
PROP_SATURATION,
|
||||
PROP_VALUE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_color_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
GtkColor *self = GTK_COLOR (paintable);
|
||||
|
||||
gtk_snapshot_append_color (snapshot, self->color, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_color_get_intrinsic_width (GdkPaintable *paintable)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_color_get_intrinsic_height (GdkPaintable *paintable)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = gtk_color_snapshot;
|
||||
iface->get_intrinsic_width = gtk_color_get_intrinsic_width;
|
||||
iface->get_intrinsic_height = gtk_color_get_intrinsic_height;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, we define the type. The important part is adding the paintable
|
||||
* interface, so GTK knows that this object can indeed be drawm.
|
||||
*/
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkColor, gtk_color, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gtk_color_paintable_init))
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_color_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkColor *self = GTK_COLOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
case PROP_COLOR:
|
||||
g_value_set_boxed (value, self->color);
|
||||
break;
|
||||
|
||||
case PROP_RED:
|
||||
g_value_set_float (value, self->color->red);
|
||||
break;
|
||||
|
||||
case PROP_GREEN:
|
||||
g_value_set_float (value, self->color->green);
|
||||
break;
|
||||
|
||||
case PROP_BLUE:
|
||||
g_value_set_float (value, self->color->blue);
|
||||
break;
|
||||
|
||||
case PROP_HUE:
|
||||
g_value_set_int (value, self->h);
|
||||
break;
|
||||
|
||||
case PROP_SATURATION:
|
||||
g_value_set_int (value, self->s);
|
||||
break;
|
||||
|
||||
case PROP_VALUE:
|
||||
g_value_set_int (value, self->v);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkColor *self = GTK_COLOR (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_NAME:
|
||||
self->name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_COLOR:
|
||||
self->color = g_value_dup_boxed (value);
|
||||
break;
|
||||
|
||||
case PROP_HUE:
|
||||
self->h = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_SATURATION:
|
||||
self->s = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_VALUE:
|
||||
self->v = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_finalize (GObject *object)
|
||||
{
|
||||
GtkColor *self = GTK_COLOR (object);
|
||||
|
||||
g_free (self->name);
|
||||
g_clear_pointer (&self->color, gdk_rgba_free);
|
||||
|
||||
G_OBJECT_CLASS (gtk_color_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_class_init (GtkColorClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = gtk_color_get_property;
|
||||
gobject_class->set_property = gtk_color_set_property;
|
||||
gobject_class->finalize = gtk_color_finalize;
|
||||
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
properties[PROP_COLOR] =
|
||||
g_param_spec_boxed ("color", NULL, NULL, GDK_TYPE_RGBA, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
properties[PROP_RED] =
|
||||
g_param_spec_float ("red", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
|
||||
properties[PROP_GREEN] =
|
||||
g_param_spec_float ("green", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
|
||||
properties[PROP_BLUE] =
|
||||
g_param_spec_float ("blue", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
|
||||
properties[PROP_HUE] =
|
||||
g_param_spec_int ("hue", NULL, NULL, 0, 360, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
properties[PROP_SATURATION] =
|
||||
g_param_spec_int ("saturation", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
properties[PROP_VALUE] =
|
||||
g_param_spec_int ("value", NULL, NULL, 0, 100, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_color_init (GtkColor *self)
|
||||
{
|
||||
}
|
||||
|
||||
static GtkColor *
|
||||
gtk_color_new (const char *name,
|
||||
float r, float g, float b,
|
||||
int h, int s, int v)
|
||||
{
|
||||
GtkColor *result;
|
||||
GdkRGBA color = { r, g, b, 1.0 };
|
||||
|
||||
result = g_object_new (GTK_TYPE_COLOR,
|
||||
"name", name,
|
||||
"color", &color,
|
||||
"hue", h,
|
||||
"saturation", s,
|
||||
"value", v,
|
||||
NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_colors_model (void)
|
||||
{
|
||||
GListStore *result;
|
||||
GtkColor *color;
|
||||
GBytes *data;
|
||||
char **lines;
|
||||
guint i;
|
||||
|
||||
result = g_list_store_new (GTK_TYPE_COLOR);
|
||||
data = g_resources_lookup_data ("/listview_colors/color.names.txt", 0, NULL);
|
||||
lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
|
||||
|
||||
for (i = 0; lines[i]; i++)
|
||||
{
|
||||
const char *name;
|
||||
char **fields;
|
||||
int red, green, blue;
|
||||
int h, s, v;
|
||||
|
||||
if (lines[i][0] == '#' || lines[i][0] == '\0')
|
||||
continue;
|
||||
|
||||
fields = g_strsplit (lines[i], " ", 0);
|
||||
name = fields[1];
|
||||
red = atoi (fields[3]);
|
||||
green = atoi (fields[4]);
|
||||
blue = atoi (fields[5]);
|
||||
h = atoi (fields[9]);
|
||||
s = atoi (fields[10]);
|
||||
v = atoi (fields[11]);
|
||||
|
||||
color = gtk_color_new (name, red / 255., green / 255., blue / 255., h, s, v);
|
||||
g_list_store_append (result, color);
|
||||
g_object_unref (color);
|
||||
|
||||
g_strfreev (fields);
|
||||
}
|
||||
g_strfreev (lines);
|
||||
|
||||
g_bytes_unref (data);
|
||||
|
||||
return G_LIST_MODEL (result);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_rgb_markup (gpointer this,
|
||||
GtkColor *color)
|
||||
{
|
||||
if (!color)
|
||||
return NULL;
|
||||
|
||||
return g_strdup_printf ("<b>R:</b> %d <b>G:</b> %d <b>B:</b> %d",
|
||||
(int)(color->color->red * 255),
|
||||
(int)(color->color->green * 255),
|
||||
(int)(color->color->blue * 255));
|
||||
}
|
||||
|
||||
static char *
|
||||
get_hsv_markup (gpointer this,
|
||||
GtkColor *color)
|
||||
{
|
||||
if (!color)
|
||||
return NULL;
|
||||
|
||||
return g_strdup_printf ("<b>H:</b> %d <b>S:</b> %d <b>V:</b> %d",
|
||||
color->h,
|
||||
color->s,
|
||||
color->v);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_simple_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
GtkExpression *color_expression, *expression;
|
||||
|
||||
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
|
||||
color_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
|
||||
|
||||
picture = gtk_picture_new ();
|
||||
gtk_widget_set_size_request (picture, 32, 32);
|
||||
gtk_expression_bind (color_expression, picture, "paintable", NULL);
|
||||
|
||||
gtk_list_item_set_child (list_item, picture);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box, *picture, *name_label, *rgb_label, *hsv_label;;
|
||||
GtkExpression *color_expression, *expression;
|
||||
GtkExpression *params[1];
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_list_item_set_child (list_item, box);
|
||||
|
||||
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
|
||||
color_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
|
||||
|
||||
expression = gtk_property_expression_new (GTK_TYPE_COLOR,
|
||||
gtk_expression_ref (color_expression),
|
||||
"name");
|
||||
name_label = gtk_label_new (NULL);
|
||||
gtk_expression_bind (expression, name_label, "label", NULL);
|
||||
gtk_container_add (GTK_CONTAINER (box), name_label);
|
||||
|
||||
expression = gtk_expression_ref (color_expression);
|
||||
picture = gtk_picture_new ();
|
||||
gtk_expression_bind (expression, picture, "paintable", NULL);
|
||||
gtk_container_add (GTK_CONTAINER (box), picture);
|
||||
|
||||
params[0] = gtk_expression_ref (color_expression);
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
|
||||
NULL,
|
||||
1, params,
|
||||
(GCallback)get_rgb_markup,
|
||||
NULL, NULL);
|
||||
|
||||
rgb_label = gtk_label_new (NULL);
|
||||
gtk_label_set_use_markup (GTK_LABEL (rgb_label), TRUE);
|
||||
gtk_expression_bind (expression, rgb_label, "label", NULL);
|
||||
gtk_container_add (GTK_CONTAINER (box), rgb_label);
|
||||
|
||||
params[0] = gtk_expression_ref (color_expression);
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
|
||||
NULL,
|
||||
1, params,
|
||||
(GCallback)get_hsv_markup,
|
||||
NULL, NULL);
|
||||
|
||||
hsv_label = gtk_label_new (NULL);
|
||||
gtk_label_set_use_markup (GTK_LABEL (hsv_label), TRUE);
|
||||
gtk_expression_bind (expression, hsv_label, "label", NULL);
|
||||
gtk_container_add (GTK_CONTAINER (box), hsv_label);
|
||||
|
||||
gtk_expression_unref (color_expression);
|
||||
}
|
||||
|
||||
static void
|
||||
set_title (gpointer item,
|
||||
const char *title)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (item), "title", (gpointer)title);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_title (gpointer item)
|
||||
{
|
||||
return g_strdup ((char *)g_object_get_data (G_OBJECT (item), "title"));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_item (GBinding *binding,
|
||||
const GValue *from,
|
||||
GValue *to,
|
||||
gpointer data)
|
||||
{
|
||||
GObject *source = g_binding_get_source (binding);
|
||||
GListModel *model;
|
||||
guint selected;
|
||||
gpointer item;
|
||||
|
||||
selected = g_value_get_uint (from);
|
||||
|
||||
model = gtk_drop_down_get_model (GTK_DROP_DOWN (source));
|
||||
item = g_list_model_get_item (model, selected);
|
||||
|
||||
g_value_set_object (to, item);
|
||||
|
||||
g_clear_object (&item);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
create_color_grid (void)
|
||||
{
|
||||
GtkWidget *gridview;
|
||||
GtkListItemFactory *factory;
|
||||
GListModel *model, *selection;
|
||||
|
||||
gridview = gtk_grid_view_new ();
|
||||
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
gtk_scrollable_set_vscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_simple_listitem_cb), NULL);
|
||||
gtk_grid_view_set_factory (GTK_GRID_VIEW (gridview), factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (gridview), 24);
|
||||
gtk_grid_view_set_enable_rubberband (GTK_GRID_VIEW (gridview), TRUE);
|
||||
|
||||
model = G_LIST_MODEL (gtk_sort_list_model_new (create_colors_model (), NULL));
|
||||
selection = G_LIST_MODEL (gtk_multi_selection_new (model));
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
|
||||
g_object_unref (selection);
|
||||
g_object_unref (model);
|
||||
|
||||
return gridview;
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_colors (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *header, *gridview, *sw, *box, *dropdown;
|
||||
GtkListItemFactory *factory;
|
||||
GListStore *factories;
|
||||
GListModel *model;
|
||||
|
||||
GtkSorter *sorter;
|
||||
GtkSorter *multi_sorter;
|
||||
GListStore *sorters;
|
||||
GtkExpression *expression;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Colors");
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
|
||||
gridview = create_color_grid ();
|
||||
gtk_container_add (GTK_CONTAINER (sw), gridview);
|
||||
model = gtk_grid_view_get_model (GTK_GRID_VIEW (gridview));
|
||||
g_object_get (model, "model", &model, NULL);
|
||||
|
||||
sorters = g_list_store_new (GTK_TYPE_SORTER);
|
||||
|
||||
sorter = gtk_string_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "name"));
|
||||
set_title (sorter, "Name");
|
||||
g_list_store_append (sorters, sorter);
|
||||
g_object_unref (sorter);
|
||||
|
||||
multi_sorter = gtk_multi_sorter_new ();
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "red"));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Red");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "green"));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Green");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "blue"));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Blue");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
set_title (multi_sorter, "RGB");
|
||||
g_list_store_append (sorters, multi_sorter);
|
||||
g_object_unref (multi_sorter);
|
||||
|
||||
multi_sorter = gtk_multi_sorter_new ();
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "hue"));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Hue");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "saturation"));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Saturation");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "value"));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Value");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
set_title (multi_sorter, "HSV");
|
||||
g_list_store_append (sorters, multi_sorter);
|
||||
g_object_unref (multi_sorter);
|
||||
|
||||
dropdown = gtk_drop_down_new ();
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
gtk_container_add (GTK_CONTAINER (box), gtk_label_new ("Sort by:"));
|
||||
gtk_container_add (GTK_CONTAINER (box), dropdown);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), box);
|
||||
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
|
||||
NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_title,
|
||||
NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (dropdown), expression);
|
||||
gtk_expression_unref (expression);
|
||||
|
||||
gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (sorters));
|
||||
g_object_unref (sorters);
|
||||
|
||||
g_object_bind_property_full (dropdown, "selected",
|
||||
model, "sorter",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
set_item, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
factories = g_list_store_new (GTK_TYPE_LIST_ITEM_FACTORY);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_simple_listitem_cb), NULL);
|
||||
set_title (factory, "Colors");
|
||||
g_list_store_append (factories, factory);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
|
||||
set_title (factory, "Everything");
|
||||
g_list_store_append (factories, factory);
|
||||
|
||||
dropdown = gtk_drop_down_new ();
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
gtk_container_add (GTK_CONTAINER (box), gtk_label_new ("Show:"));
|
||||
gtk_container_add (GTK_CONTAINER (box), dropdown);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), box);
|
||||
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
|
||||
NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_title,
|
||||
NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (dropdown), expression);
|
||||
gtk_expression_unref (expression);
|
||||
|
||||
gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (factories));
|
||||
g_object_unref (factories);
|
||||
|
||||
g_object_bind_property_full (dropdown, "selected",
|
||||
gridview, "factory",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
set_item, NULL,
|
||||
NULL, NULL);
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
256
demos/gtk-demo/listview_filebrowser.c
Normal file
256
demos/gtk-demo/listview_filebrowser.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/* Lists/File browser
|
||||
*
|
||||
* This demo shows off the different layouts that are quickly achievable
|
||||
* with GtkListview and GtkGridView by implementing a file browser with
|
||||
* different views.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
/* Create a simple object that holds the data for the different views */
|
||||
typedef struct _FileBrowserView FileBrowserView;
|
||||
struct _FileBrowserView
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GtkListItemFactory *factory;
|
||||
char *icon_name;
|
||||
GtkOrientation orientation;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_FACTORY,
|
||||
PROP_ICON_NAME,
|
||||
PROP_ORIENTATION,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
#define FILE_BROWSER_TYPE_VIEW (file_browser_view_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (FileBrowserView, file_browser_view, FILE_BROWSER, VIEW, GObject);
|
||||
|
||||
G_DEFINE_TYPE (FileBrowserView, file_browser_view, G_TYPE_OBJECT);
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
file_browser_view_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
FileBrowserView *self = FILE_BROWSER_VIEW (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FACTORY:
|
||||
g_value_set_object (value, self->factory);
|
||||
break;
|
||||
|
||||
case PROP_ICON_NAME:
|
||||
g_value_set_string (value, self->icon_name);
|
||||
break;
|
||||
|
||||
case PROP_ORIENTATION:
|
||||
g_value_set_enum (value, self->orientation);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
file_browser_view_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
FileBrowserView *self = FILE_BROWSER_VIEW (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FACTORY:
|
||||
g_set_object (&self->factory, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_ICON_NAME:
|
||||
g_free (self->icon_name);
|
||||
self->icon_name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_ORIENTATION:
|
||||
self->orientation = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
file_browser_view_finalize (GObject *object)
|
||||
{
|
||||
FileBrowserView *self = FILE_BROWSER_VIEW (object);
|
||||
|
||||
g_object_unref (self->factory);
|
||||
g_free (self->icon_name);
|
||||
|
||||
G_OBJECT_CLASS (file_browser_view_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
file_browser_view_class_init (FileBrowserViewClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = file_browser_view_get_property;
|
||||
gobject_class->set_property = file_browser_view_set_property;
|
||||
gobject_class->finalize = file_browser_view_finalize;
|
||||
|
||||
properties[PROP_FACTORY] =
|
||||
g_param_spec_object ("factory",
|
||||
"factory",
|
||||
"factory to use in the main view",
|
||||
GTK_TYPE_LIST_ITEM_FACTORY,
|
||||
G_PARAM_READWRITE);
|
||||
properties[PROP_ICON_NAME] =
|
||||
g_param_spec_string ("icon-name",
|
||||
"icon name",
|
||||
"icon to display for selecting this view",
|
||||
NULL,
|
||||
G_PARAM_READWRITE);
|
||||
properties[PROP_ORIENTATION] =
|
||||
g_param_spec_enum ("orientation",
|
||||
"orientation",
|
||||
"orientation of the view",
|
||||
GTK_TYPE_ORIENTATION,
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void file_browser_view_init (FileBrowserView *self)
|
||||
{
|
||||
}
|
||||
|
||||
char *
|
||||
filebrowser_get_display_name (GObject *object,
|
||||
GFileInfo *info)
|
||||
{
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return g_strdup (g_file_info_get_attribute_string (info, "standard::display-name"));
|
||||
}
|
||||
|
||||
char *
|
||||
filebrowser_get_content_type (GObject *object,
|
||||
GFileInfo *info)
|
||||
{
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return g_strdup (g_file_info_get_attribute_string (info, "standard::content-type"));
|
||||
}
|
||||
|
||||
char *
|
||||
filebrowser_get_size (GObject *object,
|
||||
GFileInfo *info)
|
||||
{
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return g_format_size (g_file_info_get_attribute_uint64 (info, "standard::size"));
|
||||
}
|
||||
|
||||
GIcon *
|
||||
filebrowser_get_icon (GObject *object,
|
||||
GFileInfo *info)
|
||||
{
|
||||
GIcon *icon;
|
||||
|
||||
if (info)
|
||||
icon = G_ICON (g_file_info_get_attribute_object (info, "standard::icon"));
|
||||
else
|
||||
icon = NULL;
|
||||
|
||||
if (icon)
|
||||
g_object_ref (icon);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
void
|
||||
filebrowser_up_clicked_cb (GtkButton *button,
|
||||
GtkDirectoryList *list)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = g_file_get_parent (gtk_directory_list_get_file (list));
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
gtk_directory_list_set_file (list, file);
|
||||
}
|
||||
|
||||
void
|
||||
filebrowser_view_activated_cb (GtkGridView *view,
|
||||
guint pos,
|
||||
GtkDirectoryList *list)
|
||||
{
|
||||
GFileInfo *info;
|
||||
|
||||
info = g_list_model_get_item (gtk_grid_view_get_model (view), pos);
|
||||
if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
|
||||
gtk_directory_list_set_file (list, G_FILE (g_file_info_get_attribute_object (info, "standard::file")));
|
||||
|
||||
g_object_unref (info);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_listview_filebrowser (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *view;
|
||||
GtkBuilder *builder;
|
||||
GtkDirectoryList *dirlist;
|
||||
GFile *file;
|
||||
char *cwd;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/listview_filebrowser/listview_filebrowser.ui");
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
/* Create the model and fill it with the contents of the current directory */
|
||||
cwd = g_get_current_dir ();
|
||||
file = g_file_new_for_path (cwd);
|
||||
g_free (cwd);
|
||||
dirlist = GTK_DIRECTORY_LIST (gtk_builder_get_object (builder, "dirlist"));
|
||||
gtk_directory_list_set_file (dirlist, file);
|
||||
g_object_unref (file);
|
||||
|
||||
/* grab focus in the view */
|
||||
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
|
||||
gtk_widget_grab_focus (view);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
240
demos/gtk-demo/listview_filebrowser.ui
Normal file
240
demos/gtk-demo/listview_filebrowser.ui
Normal file
@@ -0,0 +1,240 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GListStore" id="viewlist">
|
||||
<property name="item-type">FileBrowserView</property>
|
||||
<child>
|
||||
<object class="FileBrowserView">
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<binding name="gicon">
|
||||
<closure type="GIcon" function="filebrowser_get_icon">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_display_name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="icon-name">view-list-symbolic</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="FileBrowserView">
|
||||
<property name="icon-name">view-grid-symbolic</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-size">large</property>
|
||||
<binding name="gicon">
|
||||
<closure type="GIcon" function="filebrowser_get_icon">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="wrap">1</property>
|
||||
<property name="wrap-mode">word-char</property>
|
||||
<property name="lines">2</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="width-chars">10</property>
|
||||
<property name="max-width-chars">30</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_display_name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="FileBrowserView">
|
||||
<property name="icon-name">view-paged-symbolic</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="icon-size">large</property>
|
||||
<binding name="gicon">
|
||||
<closure type="GIcon" function="filebrowser_get_icon">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_display_name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_size">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<closure type="gchararray" function="filebrowser_get_content_type">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDirectoryList" id="dirlist">
|
||||
<property name="attributes">standard::name,standard::display-name,standard::icon,standard::size,standard::content-type</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="title" translatable="yes">File browser</property>
|
||||
<property name="default-width">600</property>
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">go-up</property>
|
||||
<signal name="clicked" handler="filebrowser_up_clicked_cb" object="dirlist" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkListView">
|
||||
<property name="valign">center</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
<property name="model">
|
||||
<object class="GtkSingleSelection" id="selected-view">
|
||||
<property name="model">viewlist</property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkImage">
|
||||
<binding name="icon-name">
|
||||
<lookup type="FileBrowserView" name="icon-name">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="can-focus">1</property>
|
||||
<child>
|
||||
<object class="GtkGridView" id="view">
|
||||
<property name="model">dirlist</property>
|
||||
<property name="max-columns">15</property>
|
||||
<binding name="factory">
|
||||
<lookup name="factory" type="FileBrowserView">
|
||||
<lookup name="selected-item">selected-view</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<binding name="orientation">
|
||||
<lookup name="orientation" type="FileBrowserView">
|
||||
<lookup name="selected-item">selected-view</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<signal name="activate" handler="filebrowser_view_activated_cb" object="dirlist" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
473
demos/gtk-demo/listview_minesweeper.c
Normal file
473
demos/gtk-demo/listview_minesweeper.c
Normal file
@@ -0,0 +1,473 @@
|
||||
/* Lists/Minesweeper
|
||||
*
|
||||
* This demo shows how to develop a user interface for small game using a
|
||||
* gridview.
|
||||
*
|
||||
* It demonstrates how to use the activate signal and single-press behavior
|
||||
* to implement rather different interaction behavior to a typical list.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/*** The cell object ***/
|
||||
|
||||
/* Create an object that holds the data for a cell in the game */
|
||||
typedef struct _SweeperCell SweeperCell;
|
||||
struct _SweeperCell
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean is_mine;
|
||||
gboolean is_visible;
|
||||
guint neighbor_mines;
|
||||
};
|
||||
|
||||
enum {
|
||||
CELL_PROP_0,
|
||||
CELL_PROP_LABEL,
|
||||
|
||||
N_CELL_PROPS
|
||||
};
|
||||
|
||||
#define SWEEPER_TYPE_CELL (sweeper_cell_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (SweeperCell, sweeper_cell, SWEEPER, CELL, GObject);
|
||||
|
||||
G_DEFINE_TYPE (SweeperCell, sweeper_cell, G_TYPE_OBJECT);
|
||||
static GParamSpec *cell_properties[N_CELL_PROPS] = { NULL, };
|
||||
|
||||
static const char *
|
||||
sweeper_cell_get_label (SweeperCell *self)
|
||||
{
|
||||
static const char *minecount_labels[10] = { "", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||
|
||||
if (!self->is_visible)
|
||||
return "?";
|
||||
|
||||
if (self->is_mine)
|
||||
return "💣";
|
||||
|
||||
return minecount_labels[self->neighbor_mines];
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_cell_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SweeperCell *self = SWEEPER_CELL (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case CELL_PROP_LABEL:
|
||||
g_value_set_string (value, sweeper_cell_get_label (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_cell_class_init (SweeperCellClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = sweeper_cell_get_property;
|
||||
|
||||
cell_properties[CELL_PROP_LABEL] =
|
||||
g_param_spec_string ("label",
|
||||
"label",
|
||||
"label to display for this row",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_CELL_PROPS, cell_properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_cell_init (SweeperCell *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_cell_reveal (SweeperCell *self)
|
||||
{
|
||||
if (self->is_visible)
|
||||
return;
|
||||
|
||||
self->is_visible = TRUE;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), cell_properties[CELL_PROP_LABEL]);
|
||||
}
|
||||
|
||||
static SweeperCell *
|
||||
sweeper_cell_new ()
|
||||
{
|
||||
return g_object_new (SWEEPER_TYPE_CELL, NULL);
|
||||
}
|
||||
|
||||
/*** The board object ***/
|
||||
|
||||
/* Create an object that holds the data for the game */
|
||||
typedef struct _SweeperGame SweeperGame;
|
||||
struct _SweeperGame
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GPtrArray *cells;
|
||||
guint width;
|
||||
guint height;
|
||||
gboolean playing;
|
||||
gboolean win;
|
||||
};
|
||||
|
||||
enum {
|
||||
GAME_PROP_0,
|
||||
GAME_PROP_HEIGHT,
|
||||
GAME_PROP_PLAYING,
|
||||
GAME_PROP_WIDTH,
|
||||
GAME_PROP_WIN,
|
||||
|
||||
N_GAME_PROPS
|
||||
};
|
||||
|
||||
#define SWEEPER_TYPE_GAME (sweeper_game_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (SweeperGame, sweeper_game, SWEEPER, GAME, GObject);
|
||||
|
||||
static GType
|
||||
sweeper_game_list_model_get_item_type (GListModel *model)
|
||||
{
|
||||
return SWEEPER_TYPE_GAME;
|
||||
}
|
||||
|
||||
static guint
|
||||
sweeper_game_list_model_get_n_items (GListModel *model)
|
||||
{
|
||||
SweeperGame *self = SWEEPER_GAME (model);
|
||||
|
||||
return self->width * self->height;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
sweeper_game_list_model_get_item (GListModel *model,
|
||||
guint position)
|
||||
{
|
||||
SweeperGame *self = SWEEPER_GAME (model);
|
||||
|
||||
return g_object_ref (g_ptr_array_index (self->cells, position));
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_list_model_init (GListModelInterface *iface)
|
||||
{
|
||||
iface->get_item_type = sweeper_game_list_model_get_item_type;
|
||||
iface->get_n_items = sweeper_game_list_model_get_n_items;
|
||||
iface->get_item = sweeper_game_list_model_get_item;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (SweeperGame, sweeper_game, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, sweeper_game_list_model_init))
|
||||
|
||||
static GParamSpec *game_properties[N_GAME_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
sweeper_game_dispose (GObject *object)
|
||||
{
|
||||
SweeperGame *self = SWEEPER_GAME (object);
|
||||
|
||||
g_clear_pointer (&self->cells, g_ptr_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (sweeper_game_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SweeperGame *self = SWEEPER_GAME (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case GAME_PROP_HEIGHT:
|
||||
g_value_set_uint (value, self->height);
|
||||
break;
|
||||
|
||||
case GAME_PROP_PLAYING:
|
||||
g_value_set_boolean (value, self->playing);
|
||||
break;
|
||||
|
||||
case GAME_PROP_WIDTH:
|
||||
g_value_set_uint (value, self->width);
|
||||
break;
|
||||
|
||||
case GAME_PROP_WIN:
|
||||
g_value_set_boolean (value, self->win);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_class_init (SweeperGameClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = sweeper_game_dispose;
|
||||
gobject_class->get_property = sweeper_game_get_property;
|
||||
|
||||
game_properties[GAME_PROP_HEIGHT] =
|
||||
g_param_spec_uint ("height",
|
||||
"height",
|
||||
"height of the game grid",
|
||||
1, G_MAXUINT, 8,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
game_properties[GAME_PROP_PLAYING] =
|
||||
g_param_spec_boolean ("playing",
|
||||
"playing",
|
||||
"if the game is still going on",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
game_properties[GAME_PROP_WIDTH] =
|
||||
g_param_spec_uint ("width",
|
||||
"width",
|
||||
"width of the game grid",
|
||||
1, G_MAXUINT, 8,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
game_properties[GAME_PROP_WIN] =
|
||||
g_param_spec_boolean ("win",
|
||||
"win",
|
||||
"if the game was won",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_GAME_PROPS, game_properties);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_reset_board (SweeperGame *self,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_ptr_array_set_size (self->cells, 0);
|
||||
|
||||
for (i = 0; i < width * height; i++)
|
||||
{
|
||||
g_ptr_array_add (self->cells, sweeper_cell_new ());
|
||||
}
|
||||
|
||||
if (self->width != width)
|
||||
{
|
||||
self->width = width;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIDTH]);
|
||||
}
|
||||
if (self->height != height)
|
||||
{
|
||||
self->height = height;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_HEIGHT]);
|
||||
}
|
||||
if (!self->playing)
|
||||
{
|
||||
self->playing = TRUE;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_PLAYING]);
|
||||
}
|
||||
if (self->win)
|
||||
{
|
||||
self->win = FALSE;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIN]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_place_mines (SweeperGame *self,
|
||||
guint n_mines)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < n_mines; i++)
|
||||
{
|
||||
SweeperCell *cell;
|
||||
|
||||
do {
|
||||
cell = g_ptr_array_index (self->cells, g_random_int_range (0, self->cells->len));
|
||||
} while (cell->is_mine);
|
||||
|
||||
cell->is_mine = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static SweeperCell *
|
||||
get_cell (SweeperGame *self,
|
||||
guint x,
|
||||
guint y)
|
||||
{
|
||||
return g_ptr_array_index (self->cells, y * self->width + x);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_count_neighbor_mines (SweeperGame *self,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
guint x, y, x2, y2;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
SweeperCell *cell = get_cell (self, x, y);
|
||||
|
||||
for (y2 = MAX (1, y) - 1; y2 < MIN (height, y + 2); y2++)
|
||||
{
|
||||
for (x2 = MAX (1, x) - 1; x2 < MIN (width, x + 2); x2++)
|
||||
{
|
||||
SweeperCell *other = get_cell (self, x2, y2);
|
||||
|
||||
if (other->is_mine)
|
||||
cell->neighbor_mines++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_new_game (SweeperGame *self,
|
||||
guint width,
|
||||
guint height,
|
||||
guint n_mines)
|
||||
{
|
||||
guint n_items_before;
|
||||
|
||||
g_return_if_fail (n_mines <= width * height);
|
||||
|
||||
n_items_before = self->width * self->height;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
sweeper_game_reset_board (self, width, height);
|
||||
sweeper_game_place_mines (self, n_mines);
|
||||
sweeper_game_count_neighbor_mines (self, width, height);
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items_before, width * height);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_init (SweeperGame *self)
|
||||
{
|
||||
self->cells = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
sweeper_game_new_game (self, 8, 8, 10);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_end (SweeperGame *self,
|
||||
gboolean win)
|
||||
{
|
||||
if (self->playing)
|
||||
{
|
||||
self->playing = FALSE;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_PLAYING]);
|
||||
}
|
||||
if (self->win != win)
|
||||
{
|
||||
self->win = win;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIN]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_check_finished (SweeperGame *self)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!self->playing)
|
||||
return;
|
||||
|
||||
for (i = 0; i < self->cells->len; i++)
|
||||
{
|
||||
SweeperCell *cell = g_ptr_array_index (self->cells, i);
|
||||
|
||||
/* There's still a non-revealed cell that isn't a mine */
|
||||
if (!cell->is_visible && !cell->is_mine)
|
||||
return;
|
||||
}
|
||||
|
||||
sweeper_game_end (self, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
sweeper_game_reveal_cell (SweeperGame *self,
|
||||
guint position)
|
||||
{
|
||||
SweeperCell *cell;
|
||||
|
||||
if (!self->playing)
|
||||
return;
|
||||
|
||||
cell = g_ptr_array_index (self->cells, position);
|
||||
sweeper_cell_reveal (cell);
|
||||
|
||||
if (cell->is_mine)
|
||||
sweeper_game_end (self, FALSE);
|
||||
|
||||
sweeper_game_check_finished (self);
|
||||
}
|
||||
|
||||
void
|
||||
minesweeper_cell_clicked_cb (GtkGridView *gridview,
|
||||
guint pos,
|
||||
SweeperGame *game)
|
||||
{
|
||||
sweeper_game_reveal_cell (game, pos);
|
||||
}
|
||||
|
||||
void
|
||||
minesweeper_new_game_cb (GtkButton *button,
|
||||
SweeperGame *game)
|
||||
{
|
||||
sweeper_game_new_game (game, 8, 8, 10);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_minesweeper (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
|
||||
g_type_ensure (SWEEPER_TYPE_GAME);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/listview_minesweeper/listview_minesweeper.ui");
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
48
demos/gtk-demo/listview_minesweeper.ui
Normal file
48
demos/gtk-demo/listview_minesweeper.ui
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="SweeperGame" id="game">
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="title" translatable="yes">Minesweeper</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">New Game</property>
|
||||
<signal name="clicked" handler="minesweeper_new_game_cb" object="game" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child type="title">
|
||||
<object class="GtkImage">
|
||||
<property name="icon-name">trophy-gold</property>
|
||||
<binding name="visible">
|
||||
<lookup name="win">game</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGridView" id="view">
|
||||
<property name="model">
|
||||
<object class="GtkNoSelection">
|
||||
<property name="model">game</property>
|
||||
</object>
|
||||
</property>
|
||||
<binding name="max-columns">
|
||||
<lookup name="width">game</lookup>
|
||||
</binding>
|
||||
<binding name="min-columns">
|
||||
<lookup name="width">game</lookup>
|
||||
</binding>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/listview_minesweeper/listview_minesweeper_cell.ui</property>
|
||||
</object>
|
||||
</property>
|
||||
<signal name="activate" handler="minesweeper_cell_clicked_cb" object="game" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
16
demos/gtk-demo/listview_minesweeper_cell.ui
Normal file
16
demos/gtk-demo/listview_minesweeper_cell.ui
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<binding name="label">
|
||||
<lookup name="label" type="SweeperCell">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
398
demos/gtk-demo/listview_settings.c
Normal file
398
demos/gtk-demo/listview_settings.c
Normal file
@@ -0,0 +1,398 @@
|
||||
/* Lists/Settings
|
||||
*
|
||||
* This demo shows a settings viewer for GSettings.
|
||||
*
|
||||
* It demonstrates how to implement support for trees with GtkListView.
|
||||
*
|
||||
* It also shows how to set up sorting for columns in a GtkColumnView.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* Create an object that wraps GSettingsSchemaKey because that's a boxed type */
|
||||
typedef struct _SettingsKey SettingsKey;
|
||||
struct _SettingsKey
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GSettings *settings;
|
||||
GSettingsSchemaKey *key;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_SUMMARY,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_VALUE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
#define SETTINGS_TYPE_KEY (settings_key_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (SettingsKey, settings_key, SETTINGS, KEY, GObject);
|
||||
|
||||
G_DEFINE_TYPE (SettingsKey, settings_key, G_TYPE_OBJECT);
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
settings_key_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SettingsKey *self = SETTINGS_KEY (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_DESCRIPTION:
|
||||
g_value_set_string (value, g_settings_schema_key_get_description (self->key));
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, g_settings_schema_key_get_name (self->key));
|
||||
break;
|
||||
|
||||
case PROP_SUMMARY:
|
||||
g_value_set_string (value, g_settings_schema_key_get_summary (self->key));
|
||||
break;
|
||||
|
||||
case PROP_VALUE:
|
||||
{
|
||||
GVariant *variant = g_settings_get_value (self->settings, g_settings_schema_key_get_name (self->key));
|
||||
g_value_take_string (value, g_variant_print (variant, FALSE));
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_finalize (GObject *object)
|
||||
{
|
||||
SettingsKey *self = SETTINGS_KEY (object);
|
||||
|
||||
g_object_unref (self->settings);
|
||||
g_settings_schema_key_unref (self->key);
|
||||
|
||||
G_OBJECT_CLASS (settings_key_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_class_init (SettingsKeyClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = settings_key_finalize;
|
||||
gobject_class->get_property = settings_key_get_property;
|
||||
|
||||
properties[PROP_DESCRIPTION] =
|
||||
g_param_spec_string ("description", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_SUMMARY] =
|
||||
g_param_spec_string ("summary", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_VALUE] =
|
||||
g_param_spec_string ("value", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_init (SettingsKey *self)
|
||||
{
|
||||
}
|
||||
|
||||
static SettingsKey *
|
||||
settings_key_new (GSettings *settings,
|
||||
GSettingsSchemaKey *key)
|
||||
{
|
||||
SettingsKey *result = g_object_new (SETTINGS_TYPE_KEY, NULL);
|
||||
|
||||
result->settings = g_object_ref (settings);
|
||||
result->key = g_settings_schema_key_ref (key);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
strvcmp (gconstpointer p1,
|
||||
gconstpointer p2)
|
||||
{
|
||||
const char * const *s1 = p1;
|
||||
const char * const *s2 = p2;
|
||||
|
||||
return strcmp (*s1, *s2);
|
||||
}
|
||||
|
||||
static GtkFilter *current_filter;
|
||||
|
||||
static gboolean
|
||||
transform_settings_to_keys (GBinding *binding,
|
||||
const GValue *from_value,
|
||||
GValue *to_value,
|
||||
gpointer data)
|
||||
{
|
||||
GtkTreeListRow *treelistrow;
|
||||
GSettings *settings;
|
||||
GSettingsSchema *schema;
|
||||
GListStore *store;
|
||||
GtkSortListModel *sort_model;
|
||||
GtkFilterListModel *filter_model;
|
||||
GtkFilter *filter;
|
||||
GtkExpression *expression;
|
||||
char **keys;
|
||||
guint i;
|
||||
|
||||
treelistrow = g_value_get_object (from_value);
|
||||
if (treelistrow == NULL)
|
||||
return TRUE;
|
||||
settings = gtk_tree_list_row_get_item (treelistrow);
|
||||
g_object_get (settings, "settings-schema", &schema, NULL);
|
||||
|
||||
store = g_list_store_new (SETTINGS_TYPE_KEY);
|
||||
|
||||
keys = g_settings_schema_list_keys (schema);
|
||||
|
||||
for (i = 0; keys[i] != NULL; i++)
|
||||
{
|
||||
GSettingsSchemaKey *almost_there = g_settings_schema_get_key (schema, keys[i]);
|
||||
SettingsKey *finally = settings_key_new (settings, almost_there);
|
||||
g_list_store_append (store, finally);
|
||||
g_object_unref (finally);
|
||||
g_settings_schema_key_unref (almost_there);
|
||||
}
|
||||
|
||||
g_strfreev (keys);
|
||||
g_settings_schema_unref (schema);
|
||||
g_object_unref (settings);
|
||||
|
||||
sort_model = gtk_sort_list_model_new (G_LIST_MODEL (store),
|
||||
gtk_column_view_get_sorter (GTK_COLUMN_VIEW (data)));
|
||||
g_object_unref (store);
|
||||
expression = gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name");
|
||||
filter = gtk_string_filter_new ();
|
||||
gtk_string_filter_set_expression (GTK_STRING_FILTER (filter), expression);
|
||||
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), filter);
|
||||
gtk_expression_unref (expression);
|
||||
g_object_unref (sort_model);
|
||||
|
||||
g_set_object (¤t_filter, filter);
|
||||
|
||||
g_object_unref (filter);
|
||||
|
||||
g_value_take_object (to_value, filter_model);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_settings_model (gpointer item,
|
||||
gpointer unused)
|
||||
{
|
||||
GSettings *settings = item;
|
||||
char **schemas;
|
||||
GListStore *result;
|
||||
guint i;
|
||||
|
||||
if (settings == NULL)
|
||||
{
|
||||
g_settings_schema_source_list_schemas (g_settings_schema_source_get_default (),
|
||||
TRUE,
|
||||
&schemas,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
schemas = g_settings_list_children (settings);
|
||||
}
|
||||
|
||||
if (schemas == NULL || schemas[0] == NULL)
|
||||
{
|
||||
g_free (schemas);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qsort (schemas, g_strv_length (schemas), sizeof (char *), strvcmp);
|
||||
|
||||
result = g_list_store_new (G_TYPE_SETTINGS);
|
||||
for (i = 0; schemas[i] != NULL; i++)
|
||||
{
|
||||
GSettings *child;
|
||||
|
||||
if (settings == NULL)
|
||||
child = g_settings_new (schemas[i]);
|
||||
else
|
||||
child = g_settings_get_child (settings, schemas[i]);
|
||||
|
||||
g_list_store_append (result, child);
|
||||
g_object_unref (child);
|
||||
}
|
||||
|
||||
g_strfreev (schemas);
|
||||
|
||||
return G_LIST_MODEL (result);
|
||||
}
|
||||
|
||||
static void
|
||||
search_enabled (GtkSearchEntry *entry)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), "");
|
||||
}
|
||||
|
||||
static void
|
||||
search_changed (GtkSearchEntry *entry,
|
||||
gpointer data)
|
||||
{
|
||||
const char *text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
|
||||
if (current_filter)
|
||||
gtk_string_filter_set_search (GTK_STRING_FILTER (current_filter), text);
|
||||
}
|
||||
|
||||
static void
|
||||
stop_search (GtkSearchEntry *entry,
|
||||
gpointer data)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), "");
|
||||
|
||||
if (current_filter)
|
||||
gtk_string_filter_set_search (GTK_STRING_FILTER (current_filter), "");
|
||||
}
|
||||
|
||||
static void
|
||||
move_column (GtkListView *columns_list, gboolean down)
|
||||
{
|
||||
GListModel *columns;
|
||||
guint position;
|
||||
GtkColumnViewColumn *selected;
|
||||
GtkColumnView *view;
|
||||
|
||||
columns = gtk_list_view_get_model (columns_list);
|
||||
position = gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (columns));
|
||||
selected = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (columns));
|
||||
view = gtk_column_view_column_get_column_view (selected);
|
||||
|
||||
if (down && position + 1 < g_list_model_get_n_items (columns))
|
||||
position++;
|
||||
else if (!down && position > 0)
|
||||
position--;
|
||||
else
|
||||
return;
|
||||
|
||||
gtk_column_view_insert_column (view, position, selected);
|
||||
gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (columns), position);
|
||||
}
|
||||
|
||||
static void
|
||||
move_column_down (GtkListView *columns_list)
|
||||
{
|
||||
move_column (columns_list, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
move_column_up (GtkListView *columns_list)
|
||||
{
|
||||
move_column (columns_list, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
column_visible_toggled (GtkListItem *item, GtkToggleButton *button)
|
||||
{
|
||||
GtkColumnViewColumn *column = gtk_list_item_get_item (item);
|
||||
|
||||
gtk_column_view_column_set_visible (column, gtk_toggle_button_get_active (button));
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_settings (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *listview, *columnview;
|
||||
GListModel *model;
|
||||
GtkTreeListModel *treemodel;
|
||||
GtkSingleSelection *selection;
|
||||
GtkBuilderScope *scope;
|
||||
GtkBuilder *builder;
|
||||
GtkColumnViewColumn *name_column;
|
||||
GtkSorter *sorter;
|
||||
GtkWidget *menubutton, *popover;
|
||||
GtkWidget *columns_list;
|
||||
|
||||
g_type_ensure (SETTINGS_TYPE_KEY);
|
||||
|
||||
scope = gtk_builder_cscope_new ();
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_enabled", (GCallback)search_enabled);
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_changed", (GCallback)search_changed);
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "stop_search", (GCallback)stop_search);
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "move_column_down", (GCallback)move_column_down);
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "move_column_up", (GCallback)move_column_up);
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "column_visible_toggled", (GCallback)column_visible_toggled);
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_set_scope (builder, scope);
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
gtk_builder_add_from_resource (builder, "/listview_settings/listview_settings.ui", &error);
|
||||
if (error)
|
||||
g_warning ("%s", error->message);
|
||||
}
|
||||
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
listview = GTK_WIDGET (gtk_builder_get_object (builder, "listview"));
|
||||
columnview = GTK_WIDGET (gtk_builder_get_object (builder, "columnview"));
|
||||
model = create_settings_model (NULL, NULL);
|
||||
treemodel = gtk_tree_list_model_new (FALSE,
|
||||
model,
|
||||
TRUE,
|
||||
create_settings_model,
|
||||
NULL,
|
||||
NULL);
|
||||
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
|
||||
g_object_bind_property_full (selection, "selected-item",
|
||||
columnview, "model",
|
||||
G_BINDING_SYNC_CREATE,
|
||||
transform_settings_to_keys,
|
||||
NULL,
|
||||
columnview, NULL);
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
g_object_unref (treemodel);
|
||||
g_object_unref (model);
|
||||
|
||||
name_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "name_column"));
|
||||
sorter = gtk_string_sorter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
|
||||
gtk_column_view_column_set_sorter (name_column, sorter);
|
||||
g_object_unref (sorter);
|
||||
|
||||
menubutton = GTK_WIDGET (gtk_builder_get_object (builder, "menubutton"));
|
||||
popover = GTK_WIDGET (gtk_builder_get_object (builder, "column_popover"));
|
||||
gtk_menu_button_set_popover (GTK_MENU_BUTTON (menubutton), popover);
|
||||
|
||||
columns_list = GTK_WIDGET (gtk_builder_get_object (builder, "columns_list"));
|
||||
model = G_LIST_MODEL (gtk_single_selection_new (gtk_column_view_get_columns (GTK_COLUMN_VIEW (columnview))));
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (columns_list), model);
|
||||
g_object_unref (model);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
262
demos/gtk-demo/listview_settings.ui
Normal file
262
demos/gtk-demo/listview_settings.ui
Normal file
@@ -0,0 +1,262 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="title" translatable="yes">Settings</property>
|
||||
<property name="default-width">640</property>
|
||||
<property name="default-height">480</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="end">
|
||||
<object class="GtkMenuButton" id="menubutton">
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkToggleButton" id="search_button">
|
||||
<property name="icon-name">system-search-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPaned">
|
||||
<property name="position">300</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<child>
|
||||
<object class="GtkListView" id="listview">
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkTreeExpander" id="expander">
|
||||
<binding name="list-row">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="schema" type="GSettings">
|
||||
<lookup name="item">expander</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSearchBar">
|
||||
<property name="search-mode-enabled" bind-source="search_button" bind-property="active" bind-flags="bidirectional"/>
|
||||
<signal name="notify::search-mode-enabled" handler="search_enabled" object="entry"/>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="entry">
|
||||
<signal name="search-changed" handler="search_changed"/>
|
||||
<signal name="stop-search" handler="stop_search"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="expand">1</property>
|
||||
<child>
|
||||
<object class="GtkColumnView" id="columnview">
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="name_column">
|
||||
<property name="title">Name</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="name" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="value_column">
|
||||
<property name="title">Value</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="value" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="summary_column">
|
||||
<property name="title">Summary</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="summary" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn" id="description_column">
|
||||
<property name="title">Description</property>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="description" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkPopover" id="column_popover">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="columns_list">
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton">
|
||||
<signal name="toggled" handler="column_visible_toggled" object="GtkListItem"/>
|
||||
<binding name="active">
|
||||
<lookup name="visible" type="GtkColumnViewColumn">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<property name="label">label</property>
|
||||
<binding name="label">
|
||||
<lookup name="title" type="GtkColumnViewColumn">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="halign">center</property>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">go-down-symbolic</property>
|
||||
<signal name="clicked" handler="move_column_down" object="columns_list"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">go-up-symbolic</property>
|
||||
<signal name="clicked" handler="move_column_up" object="columns_list"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
329
demos/gtk-demo/listview_weather.c
Normal file
329
demos/gtk-demo/listview_weather.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/* Lists/Weather
|
||||
*
|
||||
* This demo shows a few of the rarer features of GtkListView and
|
||||
* how they can be used to display weather information.
|
||||
*
|
||||
* The hourly weather info uses a horizontal listview. This is easy
|
||||
* to achieve because GtkListView implements the GtkOrientable interface.
|
||||
* To make the items in the list stand out more, the listview uses
|
||||
* separators.
|
||||
*
|
||||
* A GtkNoSelectionModel is used to make sure no item in the list can be
|
||||
* selected. All other interactions with the items is still possible.
|
||||
*
|
||||
* The dataset used here has 70000 items.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GTK_TYPE_WEATHER_INFO (gtk_weather_info_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkWeatherInfo, gtk_weather_info, GTK, WEATHER_INFO, GObject)
|
||||
|
||||
typedef enum {
|
||||
GTK_WEATHER_CLEAR,
|
||||
GTK_WEATHER_FEW_CLOUDS,
|
||||
GTK_WEATHER_FOG,
|
||||
GTK_WEATHER_OVERCAST,
|
||||
GTK_WEATHER_SCATTERED_SHOWERS,
|
||||
GTK_WEATHER_SHOWERS,
|
||||
GTK_WEATHER_SNOW,
|
||||
GTK_WEATHER_STORM
|
||||
} GtkWeatherType;
|
||||
|
||||
struct _GtkWeatherInfo
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gint64 timestamp;
|
||||
int temperature;
|
||||
GtkWeatherType weather_type;
|
||||
};
|
||||
|
||||
struct _GtkWeatherInfoClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_weather_info_class_init (GtkWeatherInfoClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_weather_info_init (GtkWeatherInfo *self)
|
||||
{
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (GtkWeatherInfo, gtk_weather_info, G_TYPE_OBJECT);
|
||||
|
||||
static GtkWeatherInfo *
|
||||
gtk_weather_info_new (GDateTime *timestamp,
|
||||
GtkWeatherInfo *copy_from)
|
||||
{
|
||||
GtkWeatherInfo *result;
|
||||
|
||||
result = g_object_new (GTK_TYPE_WEATHER_INFO, NULL);
|
||||
|
||||
result->timestamp = g_date_time_to_unix (timestamp);
|
||||
if (copy_from)
|
||||
{
|
||||
result->temperature = copy_from->temperature;
|
||||
result->weather_type = copy_from->weather_type;
|
||||
g_object_unref (copy_from);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GDateTime *
|
||||
parse_timestamp (const char *string,
|
||||
GTimeZone *timezone)
|
||||
{
|
||||
char *with_seconds;
|
||||
GDateTime *result;
|
||||
|
||||
with_seconds = g_strconcat (string, ":00", NULL);
|
||||
result = g_date_time_new_from_iso8601 (with_seconds, timezone);
|
||||
g_free (with_seconds);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GtkWeatherType
|
||||
parse_weather_type (const char *clouds,
|
||||
const char *precip,
|
||||
GtkWeatherType fallback)
|
||||
{
|
||||
if (strstr (precip, "SN"))
|
||||
return GTK_WEATHER_SNOW;
|
||||
|
||||
if (strstr (precip, "TS"))
|
||||
return GTK_WEATHER_STORM;
|
||||
|
||||
if (strstr (precip, "DZ"))
|
||||
return GTK_WEATHER_SCATTERED_SHOWERS;
|
||||
|
||||
if (strstr (precip, "SH") || strstr (precip, "RA"))
|
||||
return GTK_WEATHER_SHOWERS;
|
||||
|
||||
if (strstr (precip, "FG"))
|
||||
return GTK_WEATHER_FOG;
|
||||
|
||||
if (g_str_equal (clouds, "M") ||
|
||||
g_str_equal (clouds, ""))
|
||||
return fallback;
|
||||
|
||||
if (strstr (clouds, "OVC") ||
|
||||
strstr (clouds, "BKN"))
|
||||
return GTK_WEATHER_OVERCAST;
|
||||
|
||||
if (strstr (clouds, "BKN") ||
|
||||
strstr (clouds, "SCT"))
|
||||
return GTK_WEATHER_FEW_CLOUDS;
|
||||
|
||||
if (strstr (clouds, "VV"))
|
||||
return GTK_WEATHER_FOG;
|
||||
|
||||
return GTK_WEATHER_CLEAR;
|
||||
}
|
||||
|
||||
static double
|
||||
parse_temperature (const char *s,
|
||||
double fallback)
|
||||
{
|
||||
char *endptr;
|
||||
double d;
|
||||
|
||||
d = g_ascii_strtod (s, &endptr);
|
||||
if (*endptr != '\0')
|
||||
return fallback;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_weather_model (void)
|
||||
{
|
||||
GListStore *store;
|
||||
GTimeZone *utc;
|
||||
GDateTime *timestamp;
|
||||
GtkWeatherInfo *info;
|
||||
GBytes *data;
|
||||
char **lines;
|
||||
guint i;
|
||||
|
||||
store = g_list_store_new (GTK_TYPE_WEATHER_INFO);
|
||||
data = g_resources_lookup_data ("/listview_weather/listview_weather.txt", 0, NULL);
|
||||
lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
|
||||
|
||||
utc = g_time_zone_new_utc ();
|
||||
timestamp = g_date_time_new (utc, 2011, 1, 1, 0, 0, 0);
|
||||
info = gtk_weather_info_new (timestamp, NULL);
|
||||
g_list_store_append (store, info);
|
||||
|
||||
for (i = 0; lines[i] != NULL && *lines[i]; i++)
|
||||
{
|
||||
char **fields;
|
||||
GDateTime *date;
|
||||
|
||||
fields = g_strsplit (lines[i], ",", 0);
|
||||
date = parse_timestamp (fields[0], utc);
|
||||
while (g_date_time_difference (date, timestamp) > 30 * G_TIME_SPAN_MINUTE)
|
||||
{
|
||||
GDateTime *new_timestamp = g_date_time_add_hours (timestamp, 1);
|
||||
g_date_time_unref (timestamp);
|
||||
timestamp = new_timestamp;
|
||||
info = gtk_weather_info_new (timestamp, info);
|
||||
g_list_store_append (store, info);
|
||||
}
|
||||
|
||||
info->temperature = parse_temperature (fields[1], info->temperature);
|
||||
info->weather_type = parse_weather_type (fields[2], fields[3], info->weather_type);
|
||||
g_date_time_unref (date);
|
||||
g_strfreev (fields);
|
||||
}
|
||||
|
||||
g_strfreev (lines);
|
||||
g_bytes_unref (data);
|
||||
g_time_zone_unref (utc);
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_list_item_set_child (list_item, box);
|
||||
|
||||
child = gtk_label_new (NULL);
|
||||
gtk_label_set_width_chars (GTK_LABEL (child), 5);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
|
||||
child = gtk_image_new ();
|
||||
gtk_image_set_icon_size (GTK_IMAGE (child), GTK_ICON_SIZE_LARGE);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
|
||||
child = gtk_label_new (NULL);
|
||||
gtk_widget_set_vexpand (child, TRUE);
|
||||
gtk_widget_set_valign (child, GTK_ALIGN_END);
|
||||
gtk_label_set_width_chars (GTK_LABEL (child), 4);
|
||||
gtk_container_add (GTK_CONTAINER (box), child);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
GtkWeatherInfo *info;
|
||||
GDateTime *timestamp;
|
||||
char *s;
|
||||
|
||||
box = gtk_list_item_get_child (list_item);
|
||||
info = gtk_list_item_get_item (list_item);
|
||||
|
||||
child = gtk_widget_get_first_child (box);
|
||||
timestamp = g_date_time_new_from_unix_utc (info->timestamp);
|
||||
s = g_date_time_format (timestamp, "%R");
|
||||
gtk_label_set_text (GTK_LABEL (child), s);
|
||||
g_free (s);
|
||||
g_date_time_unref (timestamp);
|
||||
|
||||
child = gtk_widget_get_next_sibling (child);
|
||||
switch (info->weather_type)
|
||||
{
|
||||
case GTK_WEATHER_CLEAR:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-clear-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_FEW_CLOUDS:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-few-clouds-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_FOG:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-fog-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_OVERCAST:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-overcast-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_SCATTERED_SHOWERS:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-showers-scattered-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_SHOWERS:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-showers-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_SNOW:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-snow-symbolic");
|
||||
break;
|
||||
case GTK_WEATHER_STORM:
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-storm-symbolic");
|
||||
break;
|
||||
default:
|
||||
gtk_image_clear (GTK_IMAGE (child));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
child = gtk_widget_get_next_sibling (child);
|
||||
s = g_strdup_printf ("%d°", info->temperature);
|
||||
gtk_label_set_text (GTK_LABEL (child), s);
|
||||
g_free (s);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
create_weather_view (void)
|
||||
{
|
||||
GtkWidget *listview;
|
||||
GListModel *model, *selection;
|
||||
|
||||
listview = gtk_list_view_new_with_factory (
|
||||
gtk_functions_list_item_factory_new (setup_widget,
|
||||
bind_widget,
|
||||
NULL, NULL));
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (listview), GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
|
||||
model = create_weather_model ();
|
||||
selection = G_LIST_MODEL (gtk_no_selection_new (model));
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), selection);
|
||||
g_object_unref (selection);
|
||||
g_object_unref (model);
|
||||
|
||||
return listview;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_listview_weather (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *listview, *sw;;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Weather");
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Weather");
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK(gtk_widget_destroyed), &window);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
|
||||
listview = create_weather_view ();
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (sw), listview);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
70116
demos/gtk-demo/listview_weather.txt
Normal file
70116
demos/gtk-demo/listview_weather.txt
Normal file
File diff suppressed because it is too large
Load Diff
22
demos/gtk-demo/main-listitem.ui
Normal file
22
demos/gtk-demo/main-listitem.ui
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkTreeExpander" id="expander">
|
||||
<binding name="list-row">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</binding>
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">start</property>
|
||||
<binding name="label">
|
||||
<lookup name="title" type="GtkDemo">
|
||||
<lookup name="item">expander</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
@@ -8,6 +8,7 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "award.h"
|
||||
#include "demos.h"
|
||||
|
||||
static GtkWidget *info_view;
|
||||
@@ -15,19 +16,99 @@ static GtkWidget *source_view;
|
||||
|
||||
static gchar *current_file = NULL;
|
||||
|
||||
static GtkWidget *window;
|
||||
static GtkWidget *notebook;
|
||||
static GtkWidget *treeview;
|
||||
static GtkWidget *listview;
|
||||
static GtkSingleSelection *selection;
|
||||
static GtkWidget *headerbar;
|
||||
|
||||
enum {
|
||||
NAME_COLUMN,
|
||||
TITLE_COLUMN,
|
||||
FILENAME_COLUMN,
|
||||
FUNC_COLUMN,
|
||||
STYLE_COLUMN,
|
||||
NUM_COLUMNS
|
||||
typedef struct _GtkDemo GtkDemo;
|
||||
struct _GtkDemo
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
const char *name;
|
||||
const char *title;
|
||||
const char *filename;
|
||||
GDoDemoFunc func;
|
||||
GListModel *children_model;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_FILENAME,
|
||||
PROP_NAME,
|
||||
PROP_TITLE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
# define GTK_TYPE_DEMO (gtk_demo_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkDemo, gtk_demo, GTK, DEMO, GObject);
|
||||
|
||||
G_DEFINE_TYPE (GtkDemo, gtk_demo, G_TYPE_OBJECT);
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_demo_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkDemo *self = GTK_DEMO (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FILENAME:
|
||||
g_value_set_string (value, self->filename);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, self->name);
|
||||
break;
|
||||
|
||||
case PROP_TITLE:
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gtk_demo_class_init (GtkDemoClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->get_property = gtk_demo_get_property;
|
||||
|
||||
properties[PROP_FILENAME] =
|
||||
g_param_spec_string ("filename",
|
||||
"filename",
|
||||
"filename",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name",
|
||||
"name",
|
||||
"name",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
properties[PROP_TITLE] =
|
||||
g_param_spec_string ("title",
|
||||
"title",
|
||||
"title",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void gtk_demo_init (GtkDemo *self)
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct _CallbackData CallbackData;
|
||||
struct _CallbackData
|
||||
{
|
||||
@@ -35,6 +116,27 @@ struct _CallbackData
|
||||
GtkTreePath *path;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
gtk_demo_run (GtkDemo *self,
|
||||
GtkWidget *window)
|
||||
{
|
||||
GtkWidget *result;
|
||||
|
||||
if (!self->func)
|
||||
return FALSE;
|
||||
|
||||
result = self->func (window);
|
||||
if (result == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (GTK_IS_WINDOW (result))
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (result), GTK_WINDOW (window));
|
||||
gtk_window_set_modal (GTK_WINDOW (result), TRUE);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_about (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
@@ -111,69 +213,7 @@ activate_inspector (GSimpleAction *action,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_window_set_interactive_debugging (TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
window_closed_cb (GtkWidget *window, gpointer data)
|
||||
{
|
||||
CallbackData *cbdata = data;
|
||||
GtkTreeIter iter;
|
||||
PangoStyle style;
|
||||
|
||||
gtk_tree_model_get_iter (cbdata->model, &iter, cbdata->path);
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (cbdata->model), &iter,
|
||||
STYLE_COLUMN, &style,
|
||||
-1);
|
||||
if (style == PANGO_STYLE_ITALIC)
|
||||
gtk_tree_store_set (GTK_TREE_STORE (cbdata->model), &iter,
|
||||
STYLE_COLUMN, PANGO_STYLE_NORMAL,
|
||||
-1);
|
||||
|
||||
gtk_tree_path_free (cbdata->path);
|
||||
g_free (cbdata);
|
||||
}
|
||||
|
||||
static void
|
||||
run_example_for_row (GtkWidget *window,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
PangoStyle style;
|
||||
GDoDemoFunc func;
|
||||
GtkWidget *demo;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (model),
|
||||
iter,
|
||||
FUNC_COLUMN, &func,
|
||||
STYLE_COLUMN, &style,
|
||||
-1);
|
||||
|
||||
if (func)
|
||||
{
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model),
|
||||
iter,
|
||||
STYLE_COLUMN, (style == PANGO_STYLE_ITALIC ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC),
|
||||
-1);
|
||||
demo = (func) (window);
|
||||
|
||||
if (demo != NULL)
|
||||
{
|
||||
CallbackData *cbdata;
|
||||
|
||||
cbdata = g_new (CallbackData, 1);
|
||||
cbdata->model = model;
|
||||
cbdata->path = gtk_tree_model_get_path (model, iter);
|
||||
|
||||
if (GTK_IS_WINDOW (demo))
|
||||
{
|
||||
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
|
||||
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
|
||||
}
|
||||
|
||||
g_signal_connect (demo, "destroy",
|
||||
G_CALLBACK (window_closed_cb), cbdata);
|
||||
}
|
||||
}
|
||||
award ("demo-inspector");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -181,14 +221,10 @@ activate_run (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *window = user_data;
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeListRow *row = gtk_single_selection_get_selected_item (selection);
|
||||
GtkDemo *demo = gtk_tree_list_row_get_item (row);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
run_example_for_row (window, model, &iter);
|
||||
gtk_demo_run (demo, window);
|
||||
}
|
||||
|
||||
/* Stupid syntax highlighting.
|
||||
@@ -893,81 +929,72 @@ load_file (const gchar *demoname,
|
||||
}
|
||||
|
||||
static void
|
||||
selection_cb (GtkTreeSelection *selection,
|
||||
GtkTreeModel *model)
|
||||
|
||||
selection_cb (GtkSingleSelection *selection,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
char *name;
|
||||
char *filename;
|
||||
char *title;
|
||||
GtkTreeListRow *row = gtk_single_selection_get_selected_item (selection);
|
||||
GtkDemo *demo = gtk_tree_list_row_get_item (row);
|
||||
|
||||
if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
|
||||
return;
|
||||
if (demo->filename)
|
||||
load_file (demo->name, demo->filename);
|
||||
|
||||
gtk_tree_model_get (model, &iter,
|
||||
NAME_COLUMN, &name,
|
||||
TITLE_COLUMN, &title,
|
||||
FILENAME_COLUMN, &filename,
|
||||
-1);
|
||||
|
||||
if (filename)
|
||||
load_file (name, filename);
|
||||
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar), title);
|
||||
|
||||
g_free (name);
|
||||
g_free (title);
|
||||
g_free (filename);
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar), demo->title);
|
||||
}
|
||||
|
||||
static void
|
||||
populate_model (GtkTreeModel *model)
|
||||
static GListModel *
|
||||
create_demo_model (void)
|
||||
{
|
||||
Demo *d = gtk_demos;
|
||||
GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
|
||||
DemoData *demo = gtk_demos;
|
||||
|
||||
/* this code only supports 1 level of children. If we
|
||||
* want more we probably have to use a recursing function.
|
||||
*/
|
||||
while (d->title)
|
||||
while (demo->title)
|
||||
{
|
||||
Demo *children = d->children;
|
||||
GtkTreeIter iter;
|
||||
GtkDemo *d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
DemoData *children = demo->children;
|
||||
|
||||
gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
|
||||
d->name = demo->name;
|
||||
d->title = demo->title;
|
||||
d->filename = demo->filename;
|
||||
d->func = demo->func;
|
||||
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model),
|
||||
&iter,
|
||||
NAME_COLUMN, d->name,
|
||||
TITLE_COLUMN, d->title,
|
||||
FILENAME_COLUMN, d->filename,
|
||||
FUNC_COLUMN, d->func,
|
||||
STYLE_COLUMN, PANGO_STYLE_NORMAL,
|
||||
-1);
|
||||
g_list_store_append (store, d);
|
||||
|
||||
d++;
|
||||
|
||||
if (!children)
|
||||
continue;
|
||||
|
||||
while (children->title)
|
||||
if (children)
|
||||
{
|
||||
GtkTreeIter child_iter;
|
||||
d->children_model = G_LIST_MODEL (g_list_store_new (GTK_TYPE_DEMO));
|
||||
|
||||
gtk_tree_store_append (GTK_TREE_STORE (model), &child_iter, &iter);
|
||||
while (children->title)
|
||||
{
|
||||
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
|
||||
gtk_tree_store_set (GTK_TREE_STORE (model),
|
||||
&child_iter,
|
||||
NAME_COLUMN, children->name,
|
||||
TITLE_COLUMN, children->title,
|
||||
FILENAME_COLUMN, children->filename,
|
||||
FUNC_COLUMN, children->func,
|
||||
STYLE_COLUMN, PANGO_STYLE_NORMAL,
|
||||
-1);
|
||||
child->name = children->name;
|
||||
child->title = children->title;
|
||||
child->filename = children->filename;
|
||||
child->func = children->func;
|
||||
|
||||
children++;
|
||||
g_list_store_append (G_LIST_STORE (d->children_model), child);
|
||||
children++;
|
||||
}
|
||||
}
|
||||
|
||||
demo++;
|
||||
}
|
||||
|
||||
return G_LIST_MODEL (store);
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
get_child_model (gpointer item,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkDemo *demo = item;
|
||||
|
||||
if (demo->children_model)
|
||||
return g_object_ref (G_LIST_MODEL (demo->children_model));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -987,22 +1014,6 @@ startup (GApplication *app)
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
row_activated_cb (GtkWidget *tree_view,
|
||||
GtkTreePath *path,
|
||||
GtkTreeViewColumn *column)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *window;
|
||||
GtkTreeModel *model;
|
||||
|
||||
window = GTK_WIDGET (gtk_widget_get_root (tree_view));
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
|
||||
gtk_tree_model_get_iter (model, &iter, path);
|
||||
|
||||
run_example_for_row (window, model, &iter);
|
||||
}
|
||||
|
||||
static void
|
||||
start_cb (GtkMenuItem *item, GtkWidget *scrollbar)
|
||||
{
|
||||
@@ -1029,18 +1040,27 @@ scrollbar_popup (GtkWidget *scrollbar, GtkWidget *menu)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
main_activate_cb (GtkListView *listview,
|
||||
guint position,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTreeListRow *row = g_list_model_get_item (gtk_list_view_get_model (listview), position);
|
||||
GtkDemo *demo = gtk_tree_list_row_get_item (row);
|
||||
|
||||
gtk_demo_run (demo, window);
|
||||
}
|
||||
|
||||
static void
|
||||
activate (GApplication *app)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWindow *window;
|
||||
GtkWidget *widget;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *scrollbar;
|
||||
GtkWidget *menu;
|
||||
GtkWidget *item;
|
||||
GListModel *listmodel;
|
||||
GtkTreeListModel *treemodel;
|
||||
|
||||
static GActionEntry win_entries[] = {
|
||||
{ "run", activate_run, NULL, NULL, NULL }
|
||||
@@ -1048,8 +1068,8 @@ activate (GApplication *app)
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/ui/main.ui");
|
||||
|
||||
window = (GtkWindow *)gtk_builder_get_object (builder, "window");
|
||||
gtk_application_add_window (GTK_APPLICATION (app), window);
|
||||
window = (GtkWidget *)gtk_builder_get_object (builder, "window");
|
||||
gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (window));
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (window),
|
||||
win_entries, G_N_ELEMENTS (win_entries),
|
||||
window);
|
||||
@@ -1059,8 +1079,7 @@ activate (GApplication *app)
|
||||
info_view = (GtkWidget *)gtk_builder_get_object (builder, "info-textview");
|
||||
source_view = (GtkWidget *)gtk_builder_get_object (builder, "source-textview");
|
||||
headerbar = (GtkWidget *)gtk_builder_get_object (builder, "headerbar");
|
||||
treeview = (GtkWidget *)gtk_builder_get_object (builder, "treeview");
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
|
||||
listview = (GtkWidget *)gtk_builder_get_object (builder, "listview");
|
||||
|
||||
sw = (GtkWidget *)gtk_builder_get_object (builder, "source-scrolledwindow");
|
||||
scrollbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (sw));
|
||||
@@ -1079,17 +1098,19 @@ activate (GApplication *app)
|
||||
|
||||
load_file (gtk_demos[0].name, gtk_demos[0].filename);
|
||||
|
||||
populate_model (model);
|
||||
listmodel = create_demo_model ();
|
||||
treemodel = gtk_tree_list_model_new (FALSE,
|
||||
G_LIST_MODEL (listmodel),
|
||||
FALSE,
|
||||
get_child_model,
|
||||
NULL,
|
||||
NULL);
|
||||
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
|
||||
g_signal_connect (selection, "notify::selected-item", G_CALLBACK (selection_cb), NULL);
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview),
|
||||
G_LIST_MODEL (selection));
|
||||
|
||||
g_signal_connect (treeview, "row-activated", G_CALLBACK (row_activated_cb), model);
|
||||
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "treeview-selection");
|
||||
g_signal_connect (widget, "changed", G_CALLBACK (selection_cb), model);
|
||||
|
||||
gtk_tree_model_get_iter_first (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)), &iter);
|
||||
gtk_tree_selection_select_iter (GTK_TREE_SELECTION (widget), &iter);
|
||||
|
||||
gtk_tree_view_collapse_all (GTK_TREE_VIEW (treeview));
|
||||
award ("demo-start");
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (window));
|
||||
|
||||
@@ -1106,7 +1127,7 @@ auto_quit (gpointer data)
|
||||
static void
|
||||
list_demos (void)
|
||||
{
|
||||
Demo *d, *c;
|
||||
DemoData *d, *c;
|
||||
|
||||
d = gtk_demos;
|
||||
|
||||
@@ -1133,7 +1154,7 @@ command_line (GApplication *app,
|
||||
const gchar *name = NULL;
|
||||
gboolean autoquit = FALSE;
|
||||
gboolean list = FALSE;
|
||||
Demo *d, *c;
|
||||
DemoData *d, *c;
|
||||
GDoDemoFunc func = 0;
|
||||
GtkWidget *window, *demo;
|
||||
|
||||
|
@@ -28,7 +28,6 @@
|
||||
<property name="default-width">800</property>
|
||||
<property name="default-height">600</property>
|
||||
<property name="title">GTK Demo</property>
|
||||
<signal name="destroy" handler="gtk_main_quit" swapped="no"/>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
@@ -66,32 +65,15 @@
|
||||
<property name="can-focus">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="min-content-width">150</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkTreeView" id="treeview">
|
||||
<property name="can-focus">1</property>
|
||||
<property name="model">treestore</property>
|
||||
<property name="headers-visible">0</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection">
|
||||
<property name="mode">browse</property>
|
||||
<object class="GtkListView" id="listview">
|
||||
<signal name="activate" handler="main_activate_cb" swapped="no" />
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/ui/main-listitem.ui</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="style">4</attribute>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="text"> </property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -3,6 +3,7 @@
|
||||
demos = files([
|
||||
'application_demo.c',
|
||||
'assistant.c',
|
||||
'awardview.c',
|
||||
'builder.c',
|
||||
'changedisplay.c',
|
||||
'clipboard.c',
|
||||
@@ -43,6 +44,13 @@ demos = files([
|
||||
'listbox.c',
|
||||
'flowbox.c',
|
||||
'list_store.c',
|
||||
'listview_applauncher.c',
|
||||
'listview_clocks.c',
|
||||
'listview_colors.c',
|
||||
'listview_filebrowser.c',
|
||||
'listview_minesweeper.c',
|
||||
'listview_settings.c',
|
||||
'listview_weather.c',
|
||||
'markup.c',
|
||||
'menus.c',
|
||||
'modelbutton.c',
|
||||
@@ -86,6 +94,7 @@ demos = files([
|
||||
gtkdemo_deps = [ libgtk_dep, ]
|
||||
|
||||
extra_demo_sources = files(['main.c',
|
||||
'award.c',
|
||||
'gtkfishbowl.c',
|
||||
'fontplane.c',
|
||||
'gtkgears.c',
|
||||
@@ -96,7 +105,7 @@ extra_demo_sources = files(['main.c',
|
||||
if harfbuzz_dep.found() and pangoft_dep.found()
|
||||
demos += files('font_features.c')
|
||||
extra_demo_sources += files(['script-names.c', 'language-names.c'])
|
||||
gtkdemo_deps += [ harfbuzz_dep, ]
|
||||
gtkdemo_deps += [ harfbuzz_dep, epoxy_dep ]
|
||||
endif
|
||||
|
||||
if os_unix
|
||||
|
@@ -11,6 +11,8 @@
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "award.h"
|
||||
|
||||
static GtkWidget *entry;
|
||||
static GtkWidget *entry2;
|
||||
static GtkWidget *button;
|
||||
@@ -25,6 +27,18 @@ update_button (GObject *object,
|
||||
|
||||
gtk_widget_set_sensitive (button,
|
||||
text[0] != '\0' && g_str_equal (text, text2));
|
||||
|
||||
if (g_str_equal (text, text2) &&
|
||||
g_ascii_strcasecmp (text, "12345") == 0)
|
||||
award ("password-best");
|
||||
}
|
||||
|
||||
static void
|
||||
button_pressed (GtkButton *button,
|
||||
GtkWidget *window)
|
||||
{
|
||||
award ("password-correct");
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
@@ -72,7 +86,7 @@ do_password_entry (GtkWidget *do_widget)
|
||||
|
||||
button = gtk_button_new_with_mnemonic ("_Done");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (button), "suggested-action");
|
||||
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (button_pressed), window);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button);
|
||||
|
||||
|
@@ -11,6 +11,9 @@
|
||||
#include "puzzlepiece.h"
|
||||
#include "paintable.h"
|
||||
|
||||
/* Give out awards */
|
||||
#include "award.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
static GtkWidget *frame = NULL;
|
||||
static GtkWidget *choices = NULL;
|
||||
@@ -156,6 +159,14 @@ check_solved (GtkWidget *grid)
|
||||
picture = gtk_grid_get_child_at (GTK_GRID (grid), pos_x, pos_y);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture), piece);
|
||||
|
||||
/* Hand out a bunch of awards
|
||||
*/
|
||||
award ("puzzle-solve");
|
||||
if ((gdk_paintable_get_flags (piece) & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
|
||||
award ("puzzle-solve-animated");
|
||||
if (height * width > 20)
|
||||
award ("puzzle-solve-large");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -401,6 +412,18 @@ add_choice (GtkWidget *choices,
|
||||
gtk_container_add (GTK_CONTAINER (choices), icon);
|
||||
}
|
||||
|
||||
static void
|
||||
widget_destroyed (GtkWidget *widget,
|
||||
GtkWidget **widget_pointer)
|
||||
{
|
||||
if (widget_pointer)
|
||||
*widget_pointer = NULL;
|
||||
|
||||
if (!solved)
|
||||
award ("puzzle-give-up");
|
||||
}
|
||||
|
||||
|
||||
GtkWidget *
|
||||
do_sliding_puzzle (GtkWidget *do_widget)
|
||||
{
|
||||
@@ -469,7 +492,7 @@ do_sliding_puzzle (GtkWidget *do_widget)
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
G_CALLBACK (widget_destroyed), &window);
|
||||
|
||||
frame = gtk_aspect_frame_new (NULL, 0.5, 0.5, (float) gdk_paintable_get_intrinsic_aspect_ratio (puzzle), FALSE);
|
||||
gtk_container_add (GTK_CONTAINER (window), frame);
|
||||
|
@@ -44,19 +44,51 @@
|
||||
|
||||
<chapter id="Lists">
|
||||
<title>GListModel support</title>
|
||||
<xi:include href="xml/gtkexpression.xml" />
|
||||
<xi:include href="xml/gtkfilterlistmodel.xml" />
|
||||
<section>
|
||||
<xi:include href="xml/gtkfilter.xml" />
|
||||
<xi:include href="xml/gtkcustomfilter.xml" />
|
||||
<xi:include href="xml/gtkstringfilter.xml" />
|
||||
<xi:include href="xml/gtkmultifilter.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkflattenlistmodel.xml" />
|
||||
<xi:include href="xml/gtkmaplistmodel.xml" />
|
||||
<xi:include href="xml/gtkslicelistmodel.xml" />
|
||||
<xi:include href="xml/gtksortlistmodel.xml" />
|
||||
<section>
|
||||
<xi:include href="xml/gtksorter.xml" />
|
||||
<xi:include href="xml/gtkcustomsorter.xml" />
|
||||
<xi:include href="xml/gtkstringsorter.xml" />
|
||||
<xi:include href="xml/gtknumericsorter.xml" />
|
||||
<xi:include href="xml/gtkmultisorter.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkselectionmodel.xml" />
|
||||
<xi:include href="xml/gtknoselection.xml" />
|
||||
<xi:include href="xml/gtksingleselection.xml" />
|
||||
<xi:include href="xml/gtkdirectorylist.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="ListContainers">
|
||||
<title>List-based Widgets</title>
|
||||
<xi:include href="xml/gtklistitem.xml" />
|
||||
<xi:include href="xml/gtklistitemfactory.xml" />
|
||||
<section>
|
||||
<xi:include href="xml/gtksignallistitemfactory.xml" />
|
||||
<xi:include href="xml/gtkbuilderlistitemfactory.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtklistview.xml" />
|
||||
<xi:include href="xml/gtkgridview.xml" />
|
||||
<xi:include href="xml/gtkcolumnview.xml" />
|
||||
<xi:include href="xml/gtkcolumnviewcolumn.xml" />
|
||||
<xi:include href="xml/gtkdropdown.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="Trees">
|
||||
<xi:include href="xml/gtktreelistrow.xml" />
|
||||
<xi:include href="xml/gtktreelistmodel.xml" />
|
||||
<xi:include href="xml/gtktreelistrowsorter.xml" />
|
||||
<xi:include href="xml/gtktreeexpander.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="Application">
|
||||
@@ -234,6 +266,7 @@
|
||||
<xi:include href="xml/gtkpopover.xml" />
|
||||
<xi:include href="xml/gtkpopovermenu.xml" />
|
||||
<xi:include href="xml/gtkpopovermenubar.xml" />
|
||||
<xi:include href="xml/gtkdropdown.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="SelectorWidgets">
|
||||
|
@@ -490,6 +490,190 @@ gtk_single_selection_set_can_unselect
|
||||
gtk_single_selection_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtklistitem</FILE>
|
||||
<TITLE>GtkListItem</TITLE>
|
||||
GtkListItem
|
||||
gtk_list_item_get_item
|
||||
gtk_list_item_get_position
|
||||
gtk_list_item_get_child
|
||||
gtk_list_item_set_child
|
||||
gtk_list_item_get_selected
|
||||
gtk_list_item_get_selectable
|
||||
gtk_list_item_set_selectable
|
||||
<SUBSECTION Standard>
|
||||
GTK_LIST_ITEM
|
||||
GTK_LIST_ITEM_CLASS
|
||||
GTK_LIST_ITEM_GET_CLASS
|
||||
GTK_IS_LIST_ITEM
|
||||
GTK_IS_LIST_ITEM_CLASS
|
||||
GTK_TYPE_LIST_ITEM
|
||||
<SUBSECTION Private>
|
||||
gtk_list_item_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtklistitemfactory</FILE>
|
||||
<TITLE>GtkListItemFactory</TITLE>
|
||||
GtkListItemFactory
|
||||
<SUBSECTION Standard>
|
||||
GTK_LIST_ITEM_FACTORY
|
||||
GTK_LIST_ITEM_FACTORY_CLASS
|
||||
GTK_LIST_ITEM_FACTORY_GET_CLASS
|
||||
GTK_IS_LIST_ITEM_FACTORY
|
||||
GTK_IS_LIST_ITEM_FACTORY_CLASS
|
||||
GTK_TYPE_LIST_ITEM_FACTORY
|
||||
<SUBSECTION Private>
|
||||
gtk_list_item_factory_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkbuilderlistitemfactory</FILE>
|
||||
<TITLE>GtkBuilderListItemFactory</TITLE>
|
||||
GtkBuilderListItemFactory
|
||||
gtk_builder_list_item_factory_new_from_bytes
|
||||
gtk_builder_list_item_factory_new_from_resource
|
||||
gtk_builder_list_item_factory_get_bytes
|
||||
gtk_builder_list_item_factory_get_resource
|
||||
gtk_builder_list_item_factory_get_scope
|
||||
<SUBSECTION Standard>
|
||||
GTK_BUILDER_LIST_ITEM_FACTORY
|
||||
GTK_BUILDER_LIST_ITEM_FACTORY_CLASS
|
||||
GTK_BUILDER_LIST_ITEM_FACTORY_GET_CLASS
|
||||
GTK_IS_BUILDER_LIST_ITEM_FACTORY
|
||||
GTK_IS_BUILDER_LIST_ITEM_FACTORY_CLASS
|
||||
GTK_TYPE_BUILDER_LIST_ITEM_FACTORY
|
||||
<SUBSECTION Private>
|
||||
gtk_builder_list_item_factory_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtksignallistitemfactory</FILE>
|
||||
<TITLE>GtkSignalListItemFactory</TITLE>
|
||||
GtkSignalListItemFactory
|
||||
gtk_signal_list_item_factory_new
|
||||
<SUBSECTION Standard>
|
||||
GTK_SIGNAL_LIST_ITEM_FACTORY
|
||||
GTK_SIGNAL_LIST_ITEM_FACTORY_CLASS
|
||||
GTK_SIGNAL_LIST_ITEM_FACTORY_GET_CLASS
|
||||
GTK_IS_SIGNAL_LIST_ITEM_FACTORY
|
||||
GTK_IS_SIGNAL_LIST_ITEM_FACTORY_CLASS
|
||||
GTK_TYPE_SIGNAL_LIST_ITEM_FACTORY
|
||||
<SUBSECTION Private>
|
||||
gtk_signal_list_item_factory_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtklistview</FILE>
|
||||
<TITLE>GtkListView</TITLE>
|
||||
GtkListView
|
||||
gtk_list_view_new
|
||||
gtk_list_view_new_with_factory
|
||||
gtk_list_view_set_factory
|
||||
gtk_list_view_get_factory
|
||||
gtk_list_view_set_model
|
||||
gtk_list_view_get_model
|
||||
gtk_list_view_set_show_separators
|
||||
gtk_list_view_get_show_separators
|
||||
gtk_list_view_set_single_click_activate
|
||||
gtk_list_view_get_single_click_activate
|
||||
gtk_list_view_set_enable_rubberband
|
||||
gtk_list_view_get_enable_rubberband
|
||||
<SUBSECTION Standard>
|
||||
GTK_LIST_VIEW
|
||||
GTK_LIST_VIEW_CLASS
|
||||
GTK_LIST_VIEW_GET_CLASS
|
||||
GTK_IS_LIST_VIEW
|
||||
GTK_IS_LIST_VIEW_CLASS
|
||||
GTK_TYPE_LIST_VIEW
|
||||
<SUBSECTION Private>
|
||||
gtk_list_view_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkcolumnview</FILE>
|
||||
<TITLE>GtkColumnView</TITLE>
|
||||
GtkColumnView
|
||||
gtk_column_view_new
|
||||
gtk_column_view_append_column
|
||||
gtk_column_view_insert_column
|
||||
gtk_column_view_remove_column
|
||||
gtk_column_view_get_columns
|
||||
gtk_column_view_get_model
|
||||
gtk_column_view_set_model
|
||||
gtk_column_view_get_sorter
|
||||
gtk_column_view_get_show_separators
|
||||
gtk_column_view_set_show_separators
|
||||
gtk_column_view_set_single_click_activate
|
||||
gtk_column_view_get_single_click_activate
|
||||
gtk_column_view_set_enable_rubberband
|
||||
gtk_column_view_get_enable_rubberband
|
||||
gtk_column_view_sort_by_column
|
||||
<SUBSECTION Standard>
|
||||
GTK_COLUMN_VIEW
|
||||
GTK_COLUMN_VIEW_CLASS
|
||||
GTK_COLUMN_VIEW_GET_CLASS
|
||||
GTK_IS_COLUMN_VIEW
|
||||
GTK_IS_COLUMN_VIEW_CLASS
|
||||
GTK_TYPE_COLUMN_VIEW
|
||||
<SUBSECTION Private>
|
||||
gtk_column_view_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkcolumnviewcolumn</FILE>
|
||||
<TITLE>GtkColumnViewColumn</TITLE>
|
||||
GtkColumnViewColumn
|
||||
gtk_column_view_column_new
|
||||
gtk_column_view_column_new_with_factory
|
||||
gtk_column_view_column_get_column_view
|
||||
gtk_column_view_column_set_factory
|
||||
gtk_column_view_column_get_factory
|
||||
gtk_column_view_column_set_title
|
||||
gtk_column_view_column_get_title
|
||||
gtk_column_view_column_set_sorter
|
||||
gtk_column_view_column_get_sorter
|
||||
gtk_column_view_column_set_visible
|
||||
gtk_column_view_column_get_visible
|
||||
gtk_column_view_column_set_fixed_width
|
||||
gtk_column_view_column_get_fixed_width
|
||||
<SUBSECTION Standard>
|
||||
GTK_COLUMN_VIEW_COLUMN
|
||||
GTK_COLUMN_VIEW_COLUMN_CLASS
|
||||
GTK_COLUMN_VIEW_COLUMN_GET_CLASS
|
||||
GTK_IS_COLUMN_VIEW_COLUMN
|
||||
GTK_IS_COLUMN_VIEW_COLUMN_CLASS
|
||||
GTK_TYPE_COLUMN_VIEW_COLUMN
|
||||
<SUBSECTION Private>
|
||||
gtk_column_view_column_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkgridview</FILE>
|
||||
<TITLE>GtkGridView</TITLE>
|
||||
GtkGridView
|
||||
gtk_grid_view_new
|
||||
gtk_grid_view_set_model
|
||||
gtk_grid_view_get_model
|
||||
gtk_grid_view_set_max_columns
|
||||
gtk_grid_view_get_max_columns
|
||||
gtk_grid_view_set_min_columns
|
||||
gtk_grid_view_get_min_columns
|
||||
gtk_grid_view_set_single_click_activate
|
||||
gtk_grid_view_get_single_click_activate
|
||||
gtk_grid_view_set_enable_rubberband
|
||||
gtk_grid_view_get_enable_rubberband
|
||||
<SUBSECTION Standard>
|
||||
GTK_GRID_VIEW
|
||||
GTK_GRID_VIEW_CLASS
|
||||
GTK_GRID_VIEW_GET_CLASS
|
||||
GTK_IS_GRID_VIEW
|
||||
GTK_IS_GRID_VIEW_CLASS
|
||||
GTK_TYPE_GRID_VIEW
|
||||
<SUBSECTION Private>
|
||||
gtk_grid_view_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkbuildable</FILE>
|
||||
GtkBuildable
|
||||
@@ -1339,6 +1523,92 @@ GTK_TYPE_FILE_FILTER
|
||||
gtk_file_filter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkdirectorylist</FILE>
|
||||
<TITLE>GtkDirectoryList</TITLE>
|
||||
GtkDirectoryList
|
||||
gtk_directory_list_new
|
||||
gtk_directory_list_get_attributes
|
||||
gtk_directory_list_set_attributes
|
||||
gtk_directory_list_get_file
|
||||
gtk_directory_list_set_file
|
||||
gtk_directory_list_get_io_priority
|
||||
gtk_directory_list_set_io_priority
|
||||
gtk_directory_list_is_loading
|
||||
gtk_directory_list_get_error
|
||||
<SUBSECTION Standard>
|
||||
GTK_DIRECTORY_LIST
|
||||
GTK_IS_DIRECTORY_LIST
|
||||
GTK_TYPE_DIRECTORY_LIST
|
||||
GTK_DIRECTORY_LIST_CLASS
|
||||
GTK_IS_DIRECTORY_LIST_CLASS
|
||||
GTK_DIRECTORY_LIST_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_directory_list_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkfilter</FILE>
|
||||
<TITLE>GtkFilter</TITLE>
|
||||
GtkFilter
|
||||
gtk_filter_match
|
||||
gtk_filter_get_strictness
|
||||
<SUBSECTION>
|
||||
GtkFilterChange
|
||||
gtk_filter_changed
|
||||
<SUBSECTION>
|
||||
gtk_custom_filter_new
|
||||
<SUBSECTION Standard>
|
||||
GTK_FILTER
|
||||
GTK_IS_FILTER
|
||||
GTK_TYPE_FILTER
|
||||
GTK_FILTER_CLASS
|
||||
GTK_IS_FILTER_CLASS
|
||||
GTK_FILTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_filter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkcustomfilter</FILE>
|
||||
<TITLE>GtkCustomFilter</TITLE>
|
||||
GtkCustomFilter
|
||||
GtkCustomFilterFunc
|
||||
gtk_custom_filter_new
|
||||
<SUBSECTION Standard>
|
||||
GTK_CUSTOM_FILTER
|
||||
GTK_IS_CUSTOM_FILTER
|
||||
GTK_TYPE_CUSTOM_FILTER
|
||||
GTK_CUSTOM_FILTER_CLASS
|
||||
GTK_IS_CUSTOM_FILTER_CLASS
|
||||
GTK_CUSTOM_FILTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_custom_filter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkmultifilter</FILE>
|
||||
<TITLE>GtkMultiFilter</TITLE>
|
||||
GtkMultiFilter
|
||||
gtk_multi_filter_append
|
||||
gtk_multi_filter_remove
|
||||
<SUBSECTION>
|
||||
GtkAnyFilter
|
||||
gtk_any_filter_new
|
||||
<SUBSECTION>
|
||||
GtkEveryFilter
|
||||
gtk_every_filter_new
|
||||
<SUBSECTION Standard>
|
||||
GTK_CUSTOM_FILTER
|
||||
GTK_IS_CUSTOM_FILTER
|
||||
GTK_TYPE_CUSTOM_FILTER
|
||||
GTK_CUSTOM_FILTER_CLASS
|
||||
GTK_IS_CUSTOM_FILTER_CLASS
|
||||
GTK_CUSTOM_FILTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_custom_filter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkfilterlistmodel</FILE>
|
||||
<TITLE>GtkFilterListModel</TITLE>
|
||||
@@ -1347,9 +1617,8 @@ gtk_filter_list_model_new
|
||||
gtk_filter_list_model_new_for_type
|
||||
gtk_filter_list_model_set_model
|
||||
gtk_filter_list_model_get_model
|
||||
gtk_filter_list_model_set_filter_func
|
||||
gtk_filter_list_model_has_filter
|
||||
gtk_filter_list_model_refilter
|
||||
gtk_filter_list_model_set_filter
|
||||
gtk_filter_list_model_get_filter
|
||||
<SUBSECTION Standard>
|
||||
GTK_FILTER_LIST_MODEL
|
||||
GTK_IS_FILTER_LIST_MODEL
|
||||
@@ -2340,8 +2609,6 @@ gtk_recent_manager_move_item
|
||||
gtk_recent_manager_get_items
|
||||
gtk_recent_manager_purge_items
|
||||
<SUBSECTION>
|
||||
gtk_recent_info_ref
|
||||
gtk_recent_info_unref
|
||||
gtk_recent_info_get_uri
|
||||
gtk_recent_info_get_display_name
|
||||
gtk_recent_info_get_description
|
||||
@@ -2672,17 +2939,123 @@ GTK_SLICE_LIST_MODEL_GET_CLASS
|
||||
gtk_slice_list_model_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtksorter</FILE>
|
||||
<TITLE>GtkSorter</TITLE>
|
||||
GtkSorter
|
||||
GtkSorterOrder
|
||||
GtkSorterChange
|
||||
gtk_sorter_compare
|
||||
gtk_sorter_get_order
|
||||
gtk_sorter_changed
|
||||
<SUBSECTION Standard>
|
||||
GTK_SORTER
|
||||
GTK_IS_SORTER
|
||||
GTK_TYPE_SORTER
|
||||
GTK_SORTER_CLASS
|
||||
GTK_IS_SORTER_CLASS
|
||||
GTK_SORTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_sorter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkstringsorter</FILE>
|
||||
<TITLE>GtkStringSorter</TITLE>
|
||||
GtkStringSorter
|
||||
gtk_string_sorter_new
|
||||
gtk_string_sorter_get_expression
|
||||
gtk_string_sorter_set_expression
|
||||
gtk_string_sorter_get_ignore_case
|
||||
gtk_string_sorter_set_ignore_case
|
||||
<SUBSECTION Standard>
|
||||
GTK_STRING_SORTER
|
||||
GTK_IS_STRING_SORTER
|
||||
GTK_TYPE_STRING_SORTER
|
||||
GTK_IS_STRING_SORTER_CLASS
|
||||
GTK_STRING_SORTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_string_sorter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtknumericsorter</FILE>
|
||||
<TITLE>GtkNumericSorter</TITLE>
|
||||
GtkNumericSorter
|
||||
gtk_numeric_sorter_new
|
||||
gtk_numeric_sorter_get_expression
|
||||
gtk_numeric_sorter_set_expression
|
||||
gtk_numeric_sorter_get_sort_order
|
||||
gtk_numeric_sorter_set_sort_order
|
||||
<SUBSECTION Standard>
|
||||
GTK_NUMERIC_SORTER
|
||||
GTK_IS_NUMERIC_SORTER
|
||||
GTK_TYPE_NUMERIC_SORTER
|
||||
GTK_IS_NUMERIC_SORTER_CLASS
|
||||
GTK_NUMERIC_SORTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_numeric_sorter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkcustomsorter</FILE>
|
||||
<TITLE>GtkCustomSorter</TITLE>
|
||||
GtkCustomSorter
|
||||
gtk_custom_sorter_new
|
||||
<SUBSECTION Standard>
|
||||
GTK_CUSTOM_SORTER
|
||||
GTK_IS_CUSTOM_SORTER
|
||||
GTK_TYPE_CUSTOM_SORTER
|
||||
GTK_IS_CUSTOM_SORTER_CLASS
|
||||
GTK_CUSTOM_SORTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_custom_sorter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkmultisorter</FILE>
|
||||
<TITLE>GtkMultiSorter</TITLE>
|
||||
GtkMultiSorter
|
||||
gtk_multi_sorter_new
|
||||
gtk_multi_sorter_append
|
||||
gtk_multi_sorter_remove
|
||||
<SUBSECTION Standard>
|
||||
GTK_MULTI_SORTER
|
||||
GTK_IS_MULTI_SORTER
|
||||
GTK_TYPE_MULTI_SORTER
|
||||
GTK_IS_MULTI_SORTER_CLASS
|
||||
GTK_MULTI_SORTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_multi_sorter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtktreelistrowsorter</FILE>
|
||||
<TITLE>GtkTreeListRowSorter</TITLE>
|
||||
GtkTreeListRowSorter
|
||||
gtk_tree_list_row_sorter_new
|
||||
gtk_tree_list_row_sorter_get_sorter
|
||||
gtk_tree_list_row_sorter_set_sorter
|
||||
<SUBSECTION Standard>
|
||||
GTK_TREE_LIST_ROW_SORTER
|
||||
GTK_IS_TREE_LIST_ROW_SORTER
|
||||
GTK_TYPE_TREE_LIST_ROW_SORTER
|
||||
GTK_IS_TREE_LIST_ROW_SORTER_CLASS
|
||||
GTK_TREE_LIST_ROW_SORTER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_tree_list_row_sorter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtksortlistmodel</FILE>
|
||||
<TITLE>GtkSortListModel</TITLE>
|
||||
GtkSortListModel
|
||||
gtk_sort_list_model_new
|
||||
gtk_sort_list_model_new_for_type
|
||||
gtk_sort_list_model_set_sort_func
|
||||
gtk_sort_list_model_has_sort
|
||||
gtk_sort_list_model_set_sorter
|
||||
gtk_sort_list_model_get_sorter
|
||||
gtk_sort_list_model_set_model
|
||||
gtk_sort_list_model_get_model
|
||||
gtk_sort_list_model_resort
|
||||
<SUBSECTION Standard>
|
||||
GTK_SORT_LIST_MODEL
|
||||
GTK_IS_SORT_LIST_MODEL
|
||||
@@ -3481,6 +3854,26 @@ GTK_TREE_LIST_MODEL_GET_CLASS
|
||||
gtk_tree_list_row_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtktreeexpander</FILE>
|
||||
<TITLE>GtkTreeExpander</TITLE>
|
||||
gtk_tree_expander_new
|
||||
gtk_tree_expander_get_child
|
||||
gtk_tree_expander_set_child
|
||||
gtk_tree_expander_get_item
|
||||
gtk_tree_expander_get_list_row
|
||||
gtk_tree_expander_set_list_row
|
||||
<SUBSECTION Standard>
|
||||
GTK_TREE_EXPANDER
|
||||
GTK_IS_TREE_EXPANDER
|
||||
GTK_TYPE_TREE_EXPANDER
|
||||
GTK_TREE_EXPANDER_CLASS
|
||||
GTK_IS_TREE_EXPANDER_CLASS
|
||||
GTK_TREE_EXPANDER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_tree_expander_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtktreemodel</FILE>
|
||||
<TITLE>GtkTreeModel</TITLE>
|
||||
@@ -4563,6 +4956,7 @@ gtk_widget_get_allocation
|
||||
gtk_widget_get_allocated_baseline
|
||||
gtk_widget_get_width
|
||||
gtk_widget_get_height
|
||||
gtk_widget_get_size
|
||||
gtk_widget_compute_bounds
|
||||
gtk_widget_compute_transform
|
||||
gtk_widget_compute_point
|
||||
@@ -5274,6 +5668,8 @@ GtkDeleteType
|
||||
GtkDirectionType
|
||||
GtkJustification
|
||||
GtkMovementStep
|
||||
GtkOrdering
|
||||
gtk_ordering_from_cmpfunc
|
||||
GtkOrientation
|
||||
GtkPackType
|
||||
GtkPositionType
|
||||
@@ -7393,3 +7789,77 @@ gtk_constraint_guide_get_max_size
|
||||
GTK_TYPE_CONSTRAINT_GUIDE
|
||||
gtk_constraint_guide_get_tyoe
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkexpression</FILE>
|
||||
GtkExpression
|
||||
GtkExpressionWatch
|
||||
GtkExpressionNotify
|
||||
gtk_expression_ref
|
||||
gtk_expression_unref
|
||||
gtk_expression_get_value_type
|
||||
gtk_expression_is_static
|
||||
gtk_expression_evaluate
|
||||
gtk_expression_watch
|
||||
gtk_expression_bind
|
||||
gtk_expression_watch_ref
|
||||
gtk_expression_watch_unref
|
||||
gtk_expression_watch_evaluate
|
||||
gtk_expression_watch_unwatch
|
||||
|
||||
<SUBSECTION>
|
||||
gtk_property_expression_new
|
||||
gtk_constant_expression_new
|
||||
gtk_constant_expression_new_for_value
|
||||
gtk_object_expression_new
|
||||
gtk_closure_expression_new
|
||||
gtk_cclosure_expression_new
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_IS_EXPRESSION
|
||||
GTK_TYPE_EXPRESSION
|
||||
<SUBSECTION Private>
|
||||
gtk_expression_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkstringfilter</FILE>
|
||||
GtkStringFilter
|
||||
GtkStringFilterMatchMode
|
||||
gtk_string_filter_new
|
||||
gtk_string_filter_get_search
|
||||
gtk_string_filter_set_search
|
||||
gtk_string_filter_get_expression
|
||||
gtk_string_filter_set_expression
|
||||
gtk_string_filter_get_ignore_case
|
||||
gtk_string_filter_set_ignore_case
|
||||
gtk_string_filter_get_match_mode
|
||||
gtk_string_filter_set_match_mode
|
||||
|
||||
<SUBSECTION Private>
|
||||
gtk_string_filter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkdropdown</FILE>
|
||||
<TITLE>GtkDropDown</TITLE>
|
||||
GtkDropDown
|
||||
gtk_drop_down_new
|
||||
gtk_drop_down_set_from_strings
|
||||
gtk_drop_down_set_model
|
||||
gtk_drop_down_get_model
|
||||
gtk_drop_down_set_selected
|
||||
gtk_drop_down_get_selected
|
||||
gtk_drop_down_set_factory
|
||||
gtk_drop_down_get_factory
|
||||
gtk_drop_down_set_list_factory
|
||||
gtk_drop_down_get_list_factory
|
||||
gtk_drop_down_set_expression
|
||||
gtk_drop_down_get_expression
|
||||
gtk_drop_down_set_enable_search
|
||||
gtk_drop_down_get_enable_search
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_DROP_DOWN
|
||||
<SUBSECTION Private>
|
||||
gtk_drop_down_get_type
|
||||
</SECTION>
|
||||
|
@@ -9,6 +9,7 @@ gtk_accessible_get_type
|
||||
gtk_actionable_get_type
|
||||
gtk_action_bar_get_type
|
||||
gtk_adjustment_get_type
|
||||
gtk_any_filter_get_type
|
||||
gtk_app_chooser_get_type
|
||||
gtk_app_chooser_button_get_type
|
||||
gtk_app_chooser_dialog_get_type
|
||||
@@ -22,10 +23,11 @@ gtk_bin_get_type
|
||||
gtk_bin_layout_get_type
|
||||
gtk_box_get_type
|
||||
gtk_box_layout_get_type
|
||||
gtk_buildable_get_type
|
||||
gtk_builder_cscope_get_type
|
||||
gtk_builder_get_type
|
||||
gtk_builder_list_item_factory_get_type
|
||||
gtk_builder_scope_get_type
|
||||
gtk_buildable_get_type
|
||||
gtk_button_get_type
|
||||
gtk_calendar_get_type
|
||||
gtk_cell_area_get_type
|
||||
@@ -49,6 +51,8 @@ gtk_color_button_get_type
|
||||
gtk_color_chooser_get_type
|
||||
gtk_color_chooser_dialog_get_type
|
||||
gtk_color_chooser_widget_get_type
|
||||
gtk_column_view_get_type
|
||||
gtk_column_view_column_get_type
|
||||
gtk_combo_box_get_type
|
||||
gtk_combo_box_text_get_type
|
||||
gtk_constraint_get_type
|
||||
@@ -56,9 +60,13 @@ gtk_constraint_guide_get_type
|
||||
gtk_constraint_layout_get_type
|
||||
gtk_constraint_target_get_type
|
||||
gtk_container_get_type
|
||||
gtk_custom_sorter_get_type
|
||||
gtk_css_provider_get_type
|
||||
gtk_custom_filter_get_type
|
||||
gtk_dialog_get_type
|
||||
gtk_directory_list_get_type
|
||||
gtk_drawing_area_get_type
|
||||
gtk_drop_down_get_type
|
||||
gtk_editable_get_type
|
||||
gtk_entry_buffer_get_type
|
||||
gtk_entry_completion_get_type
|
||||
@@ -68,12 +76,14 @@ gtk_event_controller_key_get_type
|
||||
gtk_event_controller_legacy_get_type
|
||||
gtk_event_controller_motion_get_type
|
||||
gtk_event_controller_scroll_get_type
|
||||
gtk_every_filter_get_type
|
||||
gtk_expander_get_type
|
||||
gtk_file_chooser_button_get_type
|
||||
gtk_file_chooser_dialog_get_type
|
||||
gtk_file_chooser_get_type
|
||||
gtk_file_chooser_widget_get_type
|
||||
gtk_file_filter_get_type
|
||||
gtk_filter_get_type
|
||||
gtk_filter_list_model_get_type
|
||||
gtk_fixed_get_type
|
||||
gtk_fixed_layout_get_type
|
||||
@@ -99,6 +109,7 @@ gtk_gl_area_get_type
|
||||
gtk_grid_get_type
|
||||
gtk_grid_layout_child_get_type
|
||||
gtk_grid_layout_get_type
|
||||
gtk_grid_view_get_type
|
||||
gtk_header_bar_get_type
|
||||
gtk_icon_theme_get_type
|
||||
gtk_icon_view_get_type
|
||||
@@ -111,9 +122,12 @@ gtk_label_get_type
|
||||
gtk_layout_child_get_type
|
||||
gtk_layout_manager_get_type
|
||||
gtk_link_button_get_type
|
||||
gtk_list_item_get_type
|
||||
gtk_list_item_factory_get_type
|
||||
gtk_list_store_get_type
|
||||
gtk_list_box_get_type
|
||||
gtk_list_box_row_get_type
|
||||
gtk_list_view_get_type
|
||||
gtk_lock_button_get_type
|
||||
gtk_map_list_model_get_type
|
||||
gtk_media_controls_get_type
|
||||
@@ -127,10 +141,13 @@ gtk_menu_shell_get_type
|
||||
gtk_menu_tool_button_get_type
|
||||
gtk_message_dialog_get_type
|
||||
gtk_mount_operation_get_type
|
||||
gtk_multi_filter_get_type
|
||||
gtk_multi_sorter_get_type
|
||||
gtk_native_get_type
|
||||
gtk_no_selection_get_type
|
||||
gtk_notebook_get_type
|
||||
gtk_notebook_page_get_type
|
||||
gtk_numeric_sorter_get_type
|
||||
gtk_orientable_get_type
|
||||
gtk_overlay_get_type
|
||||
gtk_pad_controller_get_type
|
||||
@@ -175,11 +192,13 @@ gtk_shortcuts_window_get_type
|
||||
gtk_shortcuts_section_get_type
|
||||
gtk_shortcuts_group_get_type
|
||||
gtk_shortcuts_shortcut_get_type
|
||||
gtk_signal_list_item_factory_get_type
|
||||
gtk_single_selection_get_type
|
||||
gtk_size_group_get_type
|
||||
gtk_slice_list_model_get_type
|
||||
gtk_snapshot_get_type
|
||||
gtk_sort_list_model_get_type
|
||||
gtk_sorter_get_type
|
||||
gtk_spin_button_get_type
|
||||
gtk_spinner_get_type
|
||||
gtk_stack_get_type
|
||||
@@ -187,6 +206,8 @@ gtk_stack_page_get_type
|
||||
gtk_stack_sidebar_get_type
|
||||
gtk_stack_switcher_get_type
|
||||
gtk_statusbar_get_type
|
||||
gtk_string_filter_get_type
|
||||
gtk_string_sorter_get_type
|
||||
gtk_switch_get_type
|
||||
gtk_level_bar_get_type
|
||||
gtk_style_context_get_type
|
||||
@@ -209,6 +230,7 @@ gtk_tree_drag_source_get_type
|
||||
gtk_tree_expander_get_type
|
||||
gtk_tree_list_model_get_type
|
||||
gtk_tree_list_row_get_type
|
||||
gtk_tree_list_row_sorter_get_type
|
||||
gtk_tree_model_filter_get_type
|
||||
gtk_tree_model_get_type
|
||||
gtk_tree_model_sort_get_type
|
||||
|
@@ -21,6 +21,13 @@ private_headers = [
|
||||
'gtkcolorplaneprivate.h',
|
||||
'gtkcolorscaleprivate.h',
|
||||
'gtkcolorswatchprivate.h',
|
||||
'gtkcolumnviewcellprivate.h',
|
||||
'gtkcolumnviewcolumnprivate.h',
|
||||
'gtkcolumnviewlayoutprivate.h',
|
||||
'gtkcolumnlistitemfactoryprivate.h',
|
||||
'gtkcolumviewprivate.h',
|
||||
'gtkcolumnviewsorterprivate.h',
|
||||
'gtkcolumnviewtitleprivate.h',
|
||||
'gtkcomboboxprivate.h',
|
||||
'gtkcontainerprivate.h',
|
||||
'gtkconstraintexpressionprivate.h',
|
||||
@@ -131,6 +138,11 @@ private_headers = [
|
||||
'gtkimmoduleprivate.h',
|
||||
'gtkkineticscrollingprivate.h',
|
||||
'gtklabelprivate.h',
|
||||
'gtklistbaseprivate.h',
|
||||
'gtklistitemprivate.h',
|
||||
'gtklistitemfactoryprivate.h',
|
||||
'gtklistitemmanagerprivate.h',
|
||||
'gtklistitemwidgetprivate.h',
|
||||
'gtklockbuttonprivate.h',
|
||||
'gtkmagnifierprivate.h',
|
||||
'gtkmediafileprivate.h',
|
||||
|
@@ -22,20 +22,12 @@
|
||||
#ifndef __GI_SCANNER__
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkAppLaunchContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkClipboard, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkContentProvider, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkCursor, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDevice, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplay, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDisplayManager, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrag, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrawContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkFrameClock, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkGLContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkKeymap, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkMonitor, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkSeat, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkVulkanContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkSurface, g_object_unref)
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkContentFormats, gdk_content_formats_unref)
|
||||
|
@@ -32,14 +32,11 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_CAIRO_CONTEXT (gdk_cairo_context_get_type ())
|
||||
#define GDK_CAIRO_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CAIRO_CONTEXT, GdkCairoContext))
|
||||
#define GDK_IS_CAIRO_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CAIRO_CONTEXT))
|
||||
|
||||
#define GDK_CAIRO_ERROR (gdk_cairo_error_quark ())
|
||||
|
||||
#define GDK_TYPE_CAIRO_CONTEXT (gdk_cairo_context_get_type ())
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_cairo_context_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkCairoContext, gdk_cairo_context, GDK, CAIRO_CONTEXT)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
cairo_t * gdk_cairo_context_cairo_create (GdkCairoContext *self);
|
||||
|
@@ -29,12 +29,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_CAIRO_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CAIRO_CONTEXT, GdkCairoContextClass))
|
||||
#define GDK_IS_CAIRO_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CAIRO_CONTEXT))
|
||||
#define GDK_CAIRO_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CAIRO_CONTEXT, GdkCairoContextClass))
|
||||
|
||||
typedef struct _GdkCairoContextClass GdkCairoContextClass;
|
||||
|
||||
struct _GdkCairoContext
|
||||
{
|
||||
GdkDrawContext parent_instance;
|
||||
|
@@ -31,11 +31,8 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_CLIPBOARD (gdk_clipboard_get_type ())
|
||||
#define GDK_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CLIPBOARD, GdkClipboard))
|
||||
#define GDK_IS_CLIPBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CLIPBOARD))
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_clipboard_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkClipboard, gdk_clipboard, GDK, CLIPBOARD)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_clipboard_get_display (GdkClipboard *clipboard);
|
||||
|
@@ -22,12 +22,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_CLIPBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CLIPBOARD, GdkClipboardClass))
|
||||
#define GDK_IS_CLIPBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CLIPBOARD))
|
||||
#define GDK_CLIPBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CLIPBOARD, GdkClipboardClass))
|
||||
|
||||
typedef struct _GdkClipboardClass GdkClipboardClass;
|
||||
|
||||
struct _GdkClipboard
|
||||
{
|
||||
GObject parent;
|
||||
|
@@ -35,14 +35,8 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_CURSOR (gdk_cursor_get_type ())
|
||||
#define GDK_CURSOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_CURSOR, GdkCursor))
|
||||
#define GDK_IS_CURSOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_CURSOR))
|
||||
|
||||
/* Cursors
|
||||
*/
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_cursor_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkCursor, gdk_cursor, GDK, CURSOR)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkCursor* gdk_cursor_new_from_texture (GdkTexture *texture,
|
||||
|
@@ -29,12 +29,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_CURSOR, GdkCursorClass))
|
||||
#define GDK_IS_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_CURSOR))
|
||||
#define GDK_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_CURSOR, GdkCursorClass))
|
||||
|
||||
typedef struct _GdkCursorClass GdkCursorClass;
|
||||
|
||||
struct _GdkCursor
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
@@ -29,8 +29,8 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_DEVICE (gdk_device_get_type ())
|
||||
#define GDK_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_DEVICE, GdkDevice))
|
||||
#define GDK_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_DEVICE))
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkDevice, gdk_device, GDK, DEVICE)
|
||||
|
||||
typedef struct _GdkTimeCoord GdkTimeCoord;
|
||||
|
||||
@@ -121,9 +121,6 @@ struct _GdkTimeCoord
|
||||
gdouble axes[GDK_MAX_TIMECOORD_AXES];
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_device_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const gchar * gdk_device_get_name (GdkDevice *device);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@@ -25,11 +25,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_DEVICE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_DEVICE, GdkDeviceClass))
|
||||
#define GDK_IS_DEVICE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_DEVICE))
|
||||
#define GDK_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_DEVICE, GdkDeviceClass))
|
||||
|
||||
typedef struct _GdkDeviceClass GdkDeviceClass;
|
||||
typedef struct _GdkDeviceKey GdkDeviceKey;
|
||||
|
||||
struct _GdkDeviceKey
|
||||
|
@@ -34,12 +34,10 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_DISPLAY (gdk_display_get_type ())
|
||||
#define GDK_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DISPLAY, GdkDisplay))
|
||||
#define GDK_IS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DISPLAY))
|
||||
|
||||
#define GDK_TYPE_DISPLAY (gdk_display_get_type ())
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_display_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkDisplay, gdk_display, GDK, DISPLAY)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay *gdk_display_open (const gchar *display_name);
|
||||
|
||||
|
@@ -30,13 +30,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DISPLAY, GdkDisplayClass))
|
||||
#define GDK_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY))
|
||||
#define GDK_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY, GdkDisplayClass))
|
||||
|
||||
|
||||
typedef struct _GdkDisplayClass GdkDisplayClass;
|
||||
|
||||
/* Tracks information about the device grab on this display */
|
||||
typedef struct
|
||||
{
|
||||
|
@@ -36,8 +36,8 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_DRAG (gdk_drag_get_type ())
|
||||
#define GDK_DRAG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DRAG, GdkDrag))
|
||||
#define GDK_IS_DRAG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DRAG))
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkDrag, gdk_drag, GDK, DRAG)
|
||||
|
||||
/**
|
||||
* GdkDragCancelReason:
|
||||
@@ -53,9 +53,6 @@ typedef enum {
|
||||
GDK_DRAG_CANCEL_ERROR
|
||||
} GdkDragCancelReason;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_drag_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_drag_get_display (GdkDrag *drag);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@@ -23,13 +23,6 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GDK_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAG, GdkDragClass))
|
||||
#define GDK_IS_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAG))
|
||||
#define GDK_DRAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAG, GdkDragClass))
|
||||
|
||||
typedef struct _GdkDragClass GdkDragClass;
|
||||
|
||||
|
||||
struct _GdkDragClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
|
@@ -30,12 +30,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_DRAW_CONTEXT (gdk_draw_context_get_type ())
|
||||
#define GDK_DRAW_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_DRAW_CONTEXT, GdkDrawContext))
|
||||
#define GDK_IS_DRAW_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_DRAW_CONTEXT))
|
||||
|
||||
#define GDK_TYPE_DRAW_CONTEXT (gdk_draw_context_get_type ())
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_draw_context_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkDrawContext, gdk_draw_context, GDK, DRAW_CONTEXT)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_draw_context_get_display (GdkDrawContext *context);
|
||||
|
@@ -25,12 +25,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_DRAW_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAW_CONTEXT, GdkDrawContextClass))
|
||||
#define GDK_IS_DRAW_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DRAW_CONTEXT))
|
||||
#define GDK_DRAW_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DRAW_CONTEXT, GdkDrawContextClass))
|
||||
|
||||
typedef struct _GdkDrawContextClass GdkDrawContextClass;
|
||||
|
||||
struct _GdkDrawContext
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
@@ -30,14 +30,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrop, g_object_unref)
|
||||
|
||||
#define GDK_TYPE_DROP (gdk_drop_get_type ())
|
||||
#define GDK_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_DROP, GdkDrop))
|
||||
#define GDK_IS_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_DROP))
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_drop_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkDrop, gdk_drop, GDK, DROP)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_drop_get_display (GdkDrop *self);
|
||||
|
@@ -25,13 +25,6 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define GDK_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DROP, GdkDropClass))
|
||||
#define GDK_IS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DROP))
|
||||
#define GDK_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DROP, GdkDropClass))
|
||||
|
||||
typedef struct _GdkDropClass GdkDropClass;
|
||||
|
||||
|
||||
struct _GdkDrop {
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
@@ -30,18 +30,15 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_GL_CONTEXT (gdk_gl_context_get_type ())
|
||||
#define GDK_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContext))
|
||||
#define GDK_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_CONTEXT))
|
||||
|
||||
#define GDK_GL_ERROR (gdk_gl_error_quark ())
|
||||
|
||||
#define GDK_TYPE_GL_CONTEXT (gdk_gl_context_get_type ())
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkGLContext, gdk_gl_context, GDK, GL_CONTEXT)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GQuark gdk_gl_error_quark (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_gl_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
@@ -26,12 +26,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
|
||||
#define GDK_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_CONTEXT))
|
||||
#define GDK_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
|
||||
|
||||
typedef struct _GdkGLContextClass GdkGLContextClass;
|
||||
|
||||
struct _GdkGLContext
|
||||
{
|
||||
GdkDrawContext parent_instance;
|
||||
|
@@ -29,17 +29,8 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_GL_TEXTURE (gdk_gl_texture_get_type ())
|
||||
|
||||
#define GDK_GL_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_TEXTURE, GdkGLTexture))
|
||||
#define GDK_IS_GL_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_TEXTURE))
|
||||
|
||||
typedef struct _GdkGLTexture GdkGLTexture;
|
||||
typedef struct _GdkGLTextureClass GdkGLTextureClass;
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkGLTexture, g_object_unref)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_gl_texture_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkGLTexture, gdk_gl_texture, GDK, GL_TEXTURE)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTexture * gdk_gl_texture_new (GdkGLContext *context,
|
||||
|
@@ -87,18 +87,8 @@ typedef enum {
|
||||
#endif
|
||||
|
||||
#define GDK_TYPE_MEMORY_TEXTURE (gdk_memory_texture_get_type ())
|
||||
|
||||
#define GDK_MEMORY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_MEMORY_TEXTURE, GdkMemoryTexture))
|
||||
#define GDK_IS_MEMORY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_MEMORY_TEXTURE))
|
||||
|
||||
typedef struct _GdkMemoryTexture GdkMemoryTexture;
|
||||
typedef struct _GdkMemoryTextureClass GdkMemoryTextureClass;
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkMemoryTexture, g_object_unref)
|
||||
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_memory_texture_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkMemoryTexture, gdk_memory_texture, GDK, MEMORY_TEXTURE)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTexture * gdk_memory_texture_new (int width,
|
||||
|
@@ -136,6 +136,16 @@ static double gdk_paintable_default_get_intrinsic_aspect_ratio (GdkPaintable *pa
|
||||
return (double) width / height;
|
||||
};
|
||||
|
||||
static void
|
||||
g_value_object_transform_value (const GValue *src_value,
|
||||
GValue *dest_value)
|
||||
{
|
||||
if (src_value->data[0].v_pointer && g_type_is_a (G_OBJECT_TYPE (src_value->data[0].v_pointer), G_VALUE_TYPE (dest_value)))
|
||||
dest_value->data[0].v_pointer = g_object_ref (src_value->data[0].v_pointer);
|
||||
else
|
||||
dest_value->data[0].v_pointer = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_paintable_default_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
@@ -146,6 +156,9 @@ gdk_paintable_default_init (GdkPaintableInterface *iface)
|
||||
iface->get_intrinsic_height = gdk_paintable_default_get_intrinsic_height;
|
||||
iface->get_intrinsic_aspect_ratio = gdk_paintable_default_get_intrinsic_aspect_ratio;
|
||||
|
||||
g_value_register_transform_func (G_TYPE_OBJECT, GDK_TYPE_PAINTABLE, g_value_object_transform_value);
|
||||
g_value_register_transform_func (GDK_TYPE_PAINTABLE, G_TYPE_OBJECT, g_value_object_transform_value);
|
||||
|
||||
/**
|
||||
* GdkPaintable::invalidate-contents
|
||||
* @paintable: a #GdkPaintable
|
||||
|
@@ -30,17 +30,8 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_TEXTURE (gdk_texture_get_type ())
|
||||
|
||||
#define GDK_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_TEXTURE, GdkTexture))
|
||||
#define GDK_IS_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_TEXTURE))
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkTexture, g_object_unref)
|
||||
|
||||
typedef struct _GdkTextureClass GdkTextureClass;
|
||||
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_texture_get_type (void) G_GNUC_CONST;
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkTexture, gdk_texture, GDK, TEXTURE)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTexture * gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf);
|
||||
|
@@ -5,10 +5,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_TEXTURE, GdkTextureClass))
|
||||
#define GDK_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_TEXTURE))
|
||||
#define GDK_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_TEXTURE, GdkTextureClass))
|
||||
|
||||
struct _GdkTexture
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
@@ -591,6 +591,26 @@ typedef enum
|
||||
*/
|
||||
#define GDK_ACTION_ALL (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)
|
||||
|
||||
#define GDK_DECLARE_EXPORTED_TYPE(ModuleObjName, module_obj_name, MODULE, OBJ_NAME) \
|
||||
GType module_obj_name##_get_type (void) G_GNUC_CONST; \
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
|
||||
typedef struct _##ModuleObjName ModuleObjName; \
|
||||
typedef struct _##ModuleObjName##Class ModuleObjName##Class; \
|
||||
\
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(ModuleObjName, g_object_unref) \
|
||||
\
|
||||
G_GNUC_UNUSED static inline ModuleObjName * MODULE##_##OBJ_NAME (gconstpointer ptr) { \
|
||||
return G_TYPE_CHECK_INSTANCE_CAST (ptr, module_obj_name##_get_type (), ModuleObjName); } \
|
||||
G_GNUC_UNUSED static inline ModuleObjName##Class * MODULE##_##OBJ_NAME##_CLASS (gconstpointer ptr) { \
|
||||
return G_TYPE_CHECK_CLASS_CAST (ptr, module_obj_name##_get_type (), ModuleObjName##Class); } \
|
||||
G_GNUC_UNUSED static inline gboolean MODULE##_IS_##OBJ_NAME (gpointer ptr) { \
|
||||
return G_TYPE_CHECK_INSTANCE_TYPE (ptr, module_obj_name##_get_type ()); } \
|
||||
G_GNUC_UNUSED static inline gboolean MODULE##_IS_##OBJ_NAME##_CLASS (gpointer ptr) { \
|
||||
return G_TYPE_CHECK_CLASS_TYPE (ptr, module_obj_name##_get_type ()); } \
|
||||
G_GNUC_UNUSED static inline ModuleObjName##Class * MODULE##_##OBJ_NAME##_GET_CLASS (gpointer ptr) { \
|
||||
return G_TYPE_INSTANCE_GET_CLASS (ptr, module_obj_name##_get_type (), ModuleObjName##Class); } \
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_TYPES_H__ */
|
||||
|
@@ -35,17 +35,14 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_VULKAN_CONTEXT (gdk_vulkan_context_get_type ())
|
||||
#define GDK_VULKAN_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_VULKAN_CONTEXT, GdkVulkanContext))
|
||||
#define GDK_IS_VULKAN_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_VULKAN_CONTEXT))
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DECLARE_EXPORTED_TYPE (GdkVulkanContext, gdk_vulkan_context, GDK, VULKAN_CONTEXT)
|
||||
|
||||
#define GDK_VULKAN_ERROR (gdk_vulkan_error_quark ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GQuark gdk_vulkan_error_quark (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_vulkan_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
#ifndef __GI_SCANNER__
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
|
||||
|
@@ -32,12 +32,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_VULKAN_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_VULKAN_CONTEXT, GdkVulkanContextClass))
|
||||
#define GDK_IS_VULKAN_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_VULKAN_CONTEXT))
|
||||
#define GDK_VULKAN_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_VULKAN_CONTEXT, GdkVulkanContextClass))
|
||||
|
||||
typedef struct _GdkVulkanContextClass GdkVulkanContextClass;
|
||||
|
||||
struct _GdkVulkanContext
|
||||
{
|
||||
GdkDrawContext parent_instance;
|
||||
|
@@ -45,9 +45,6 @@ typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_wayland_surface_get_type (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_wayland_surface_new_subsurface (GdkDisplay *display,
|
||||
const GdkRectangle *position);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
struct wl_surface *gdk_wayland_surface_get_wl_surface (GdkSurface *surface);
|
||||
|
||||
|
@@ -67,7 +67,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEditable, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntry, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntryBuffer, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEntryCompletion, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkEventController, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkExpander, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserButton, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFileChooserDialog, g_object_unref)
|
||||
@@ -82,16 +81,8 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFontChooserDialog, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFontChooserWidget, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkFrame, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGLArea, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGesture, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureDrag, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureLongPress, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureClick, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGesturePan, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureRotate, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureSingle, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureSwipe, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGestureZoom, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGrid, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkGridView, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkHeaderBar, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkIMContext, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkIMContextSimple, g_object_unref)
|
||||
@@ -104,6 +95,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkInfoBar, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLevelBar, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLinkButton, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkListStore, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkListView, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkLockButton, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkMenuBar, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkMenuButton, g_object_unref)
|
||||
@@ -177,7 +169,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkViewport, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkVolumeButton, g_object_unref)
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPaperSize, gtk_paper_size_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRecentInfo, gtk_recent_info_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSelectionData, gtk_selection_data_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTextIter, gtk_text_iter_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTreeIter, gtk_tree_iter_free)
|
||||
|
26
gtk/gtk.h
26
gtk/gtk.h
@@ -55,6 +55,7 @@
|
||||
#include <gtk/gtkbox.h>
|
||||
#include <gtk/gtkbuildable.h>
|
||||
#include <gtk/gtkbuilder.h>
|
||||
#include <gtk/gtkbuilderlistitemfactory.h>
|
||||
#include <gtk/gtkbuilderscope.h>
|
||||
#include <gtk/gtkbutton.h>
|
||||
#include <gtk/gtkcalendar.h>
|
||||
@@ -82,19 +83,25 @@
|
||||
#include <gtk/gtkcolorchooserdialog.h>
|
||||
#include <gtk/gtkcolorchooserwidget.h>
|
||||
#include <gtk/gtkcolorutils.h>
|
||||
#include <gtk/gtkcolumnview.h>
|
||||
#include <gtk/gtkcolumnviewcolumn.h>
|
||||
#include <gtk/gtkcombobox.h>
|
||||
#include <gtk/gtkcomboboxtext.h>
|
||||
#include <gtk/gtkconstraintlayout.h>
|
||||
#include <gtk/gtkconstraint.h>
|
||||
#include <gtk/gtkcontainer.h>
|
||||
#include <gtk/gtkcoverflow.h>
|
||||
#include <gtk/gtkcssprovider.h>
|
||||
#include <gtk/gtkcustomlayout.h>
|
||||
#include <gtk/gtkcustomsorter.h>
|
||||
#include <gtk/gtkdebug.h>
|
||||
#include <gtk/gtkdialog.h>
|
||||
#include <gtk/gtkdirectorylist.h>
|
||||
#include <gtk/gtkdnd.h>
|
||||
#include <gtk/gtkdragdest.h>
|
||||
#include <gtk/gtkdragsource.h>
|
||||
#include <gtk/gtkdrawingarea.h>
|
||||
#include <gtk/gtkdropdown.h>
|
||||
#include <gtk/gtkeditable.h>
|
||||
#include <gtk/gtkentry.h>
|
||||
#include <gtk/gtkentrybuffer.h>
|
||||
@@ -106,6 +113,7 @@
|
||||
#include <gtk/gtkeventcontrollermotion.h>
|
||||
#include <gtk/gtkeventcontrollerscroll.h>
|
||||
#include <gtk/gtkexpander.h>
|
||||
#include <gtk/gtkexpression.h>
|
||||
#include <gtk/gtkfixed.h>
|
||||
#include <gtk/gtkfixedlayout.h>
|
||||
#include <gtk/gtkfilechooser.h>
|
||||
@@ -114,7 +122,9 @@
|
||||
#include <gtk/gtkfilechoosernative.h>
|
||||
#include <gtk/gtkfilechooserwidget.h>
|
||||
#include <gtk/gtkfilefilter.h>
|
||||
#include <gtk/gtkfilter.h>
|
||||
#include <gtk/gtkfilterlistmodel.h>
|
||||
#include <gtk/gtkcustomfilter.h>
|
||||
#include <gtk/gtkflattenlistmodel.h>
|
||||
#include <gtk/gtkflowbox.h>
|
||||
#include <gtk/gtkfontbutton.h>
|
||||
@@ -122,6 +132,7 @@
|
||||
#include <gtk/gtkfontchooserdialog.h>
|
||||
#include <gtk/gtkfontchooserwidget.h>
|
||||
#include <gtk/gtkframe.h>
|
||||
#include <gtk/gtkfunctionslistitemfactory.h>
|
||||
#include <gtk/gtkgesture.h>
|
||||
#include <gtk/gtkgestureclick.h>
|
||||
#include <gtk/gtkgesturedrag.h>
|
||||
@@ -135,6 +146,7 @@
|
||||
#include <gtk/gtkglarea.h>
|
||||
#include <gtk/gtkgrid.h>
|
||||
#include <gtk/gtkgridlayout.h>
|
||||
#include <gtk/gtkgridview.h>
|
||||
#include <gtk/gtkheaderbar.h>
|
||||
#include <gtk/gtkicontheme.h>
|
||||
#include <gtk/gtkiconview.h>
|
||||
@@ -147,9 +159,13 @@
|
||||
#include <gtk/gtklayoutmanager.h>
|
||||
#include <gtk/gtklayoutchild.h>
|
||||
#include <gtk/gtklevelbar.h>
|
||||
#include <gtk/gtklistbase.h>
|
||||
#include <gtk/gtklinkbutton.h>
|
||||
#include <gtk/gtklistbox.h>
|
||||
#include <gtk/gtklistitem.h>
|
||||
#include <gtk/gtklistitemfactory.h>
|
||||
#include <gtk/gtkliststore.h>
|
||||
#include <gtk/gtklistview.h>
|
||||
#include <gtk/gtklockbutton.h>
|
||||
#include <gtk/gtkmain.h>
|
||||
#include <gtk/gtkmaplistmodel.h>
|
||||
@@ -164,10 +180,14 @@
|
||||
#include <gtk/gtkmenutoolbutton.h>
|
||||
#include <gtk/gtkmessagedialog.h>
|
||||
#include <gtk/gtkmountoperation.h>
|
||||
#include <gtk/gtkmultifilter.h>
|
||||
#include <gtk/gtkmultiselection.h>
|
||||
#include <gtk/gtkmultisorter.h>
|
||||
#include <gtk/gtknative.h>
|
||||
#include <gtk/gtknativedialog.h>
|
||||
#include <gtk/gtknoselection.h>
|
||||
#include <gtk/gtknotebook.h>
|
||||
#include <gtk/gtknumericsorter.h>
|
||||
#include <gtk/gtkorientable.h>
|
||||
#include <gtk/gtkoverlay.h>
|
||||
#include <gtk/gtkpadcontroller.h>
|
||||
@@ -211,9 +231,11 @@
|
||||
#include <gtk/gtkshortcutsshortcut.h>
|
||||
#include <gtk/gtkshortcutswindow.h>
|
||||
#include <gtk/gtkshow.h>
|
||||
#include <gtk/gtksignallistitemfactory.h>
|
||||
#include <gtk/gtksingleselection.h>
|
||||
#include <gtk/gtkslicelistmodel.h>
|
||||
#include <gtk/gtksnapshot.h>
|
||||
#include <gtk/gtksorter.h>
|
||||
#include <gtk/gtksortlistmodel.h>
|
||||
#include <gtk/gtkstacksidebar.h>
|
||||
#include <gtk/gtksizegroup.h>
|
||||
@@ -223,6 +245,8 @@
|
||||
#include <gtk/gtkstack.h>
|
||||
#include <gtk/gtkstackswitcher.h>
|
||||
#include <gtk/gtkstatusbar.h>
|
||||
#include <gtk/gtkstringfilter.h>
|
||||
#include <gtk/gtkstringsorter.h>
|
||||
#include <gtk/gtkstylecontext.h>
|
||||
#include <gtk/gtkstyleprovider.h>
|
||||
#include <gtk/gtkswitch.h>
|
||||
@@ -243,7 +267,9 @@
|
||||
#include <gtk/gtktooltip.h>
|
||||
#include <gtk/gtktestutils.h>
|
||||
#include <gtk/gtktreednd.h>
|
||||
#include <gtk/gtktreeexpander.h>
|
||||
#include <gtk/gtktreelistmodel.h>
|
||||
#include <gtk/gtktreelistrowsorter.h>
|
||||
#include <gtk/gtktreemodel.h>
|
||||
#include <gtk/gtktreemodelfilter.h>
|
||||
#include <gtk/gtktreemodelsort.h>
|
||||
|
128
gtk/gtkbuilder.c
128
gtk/gtkbuilder.c
@@ -216,8 +216,10 @@
|
||||
#include "gtkbuilderprivate.h"
|
||||
|
||||
#include "gtkbuildable.h"
|
||||
#include "gtkbuilderlistitemfactory.h"
|
||||
#include "gtkbuilderscopeprivate.h"
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkexpression.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
@@ -520,7 +522,18 @@ gtk_builder_get_parameters (GtkBuilder *builder,
|
||||
const char *property_name = g_intern_string (prop->pspec->name);
|
||||
GValue property_value = G_VALUE_INIT;
|
||||
|
||||
if (G_IS_PARAM_SPEC_OBJECT (prop->pspec) &&
|
||||
if (prop->value)
|
||||
{
|
||||
g_value_init (&property_value, G_PARAM_SPEC_VALUE_TYPE (prop->pspec));
|
||||
|
||||
if (G_PARAM_SPEC_VALUE_TYPE (prop->pspec) == GTK_TYPE_EXPRESSION)
|
||||
g_value_set_boxed (&property_value, prop->value);
|
||||
else
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
else if (G_IS_PARAM_SPEC_OBJECT (prop->pspec) &&
|
||||
(G_PARAM_SPEC_VALUE_TYPE (prop->pspec) != GDK_TYPE_PIXBUF) &&
|
||||
(G_PARAM_SPEC_VALUE_TYPE (prop->pspec) != GDK_TYPE_TEXTURE) &&
|
||||
(G_PARAM_SPEC_VALUE_TYPE (prop->pspec) != GDK_TYPE_PAINTABLE) &&
|
||||
@@ -665,13 +678,43 @@ gtk_builder_take_bindings (GtkBuilder *builder,
|
||||
|
||||
for (l = bindings; l; l = l->next)
|
||||
{
|
||||
BindingInfo *info = l->data;
|
||||
info->target = target;
|
||||
CommonInfo *common_info = l->data;
|
||||
|
||||
if (common_info->tag_type == TAG_BINDING)
|
||||
{
|
||||
BindingInfo *info = l->data;
|
||||
info->target = target;
|
||||
}
|
||||
else if (common_info->tag_type == TAG_BINDING_EXPRESSION)
|
||||
{
|
||||
BindingExpressionInfo *info = l->data;
|
||||
info->target = target;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
priv->bindings = g_slist_concat (priv->bindings, bindings);
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_special_construct_parameters (GtkBuilder *builder,
|
||||
GType object_type,
|
||||
ObjectProperties *construct_parameters)
|
||||
{
|
||||
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
if (g_type_is_a (object_type, GTK_TYPE_BUILDER_LIST_ITEM_FACTORY))
|
||||
{
|
||||
g_value_init (&value, GTK_TYPE_BUILDER_SCOPE);
|
||||
g_value_set_object (&value, priv->scope);
|
||||
object_properties_add (construct_parameters, "scope", &value);
|
||||
}
|
||||
}
|
||||
|
||||
GObject *
|
||||
_gtk_builder_construct (GtkBuilder *builder,
|
||||
ObjectInfo *info,
|
||||
@@ -769,6 +812,8 @@ _gtk_builder_construct (GtkBuilder *builder,
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_special_construct_parameters (builder, info->type, construct_parameters);
|
||||
|
||||
obj = g_object_new_with_properties (info->type,
|
||||
construct_parameters->len,
|
||||
(const char **) construct_parameters->names->pdata,
|
||||
@@ -993,17 +1038,6 @@ gtk_builder_apply_delayed_properties (GtkBuilder *builder,
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void
|
||||
free_binding_info (gpointer data,
|
||||
gpointer user)
|
||||
{
|
||||
BindingInfo *info = data;
|
||||
|
||||
g_free (info->source);
|
||||
g_free (info->source_property);
|
||||
g_slice_free (BindingInfo, data);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gtk_builder_create_bindings (GtkBuilder *builder,
|
||||
GError **error)
|
||||
@@ -1014,26 +1048,68 @@ gtk_builder_create_bindings (GtkBuilder *builder,
|
||||
|
||||
for (l = priv->bindings; l; l = l->next)
|
||||
{
|
||||
BindingInfo *info = l->data;
|
||||
GObject *source;
|
||||
CommonInfo *common_info = l->data;
|
||||
|
||||
if (result)
|
||||
if (common_info->tag_type == TAG_BINDING)
|
||||
{
|
||||
BindingInfo *info = l->data;
|
||||
GObject *source;
|
||||
|
||||
source = gtk_builder_lookup_object (builder, info->source, info->line, info->col, error);
|
||||
if (source)
|
||||
g_object_bind_property (source, info->source_property,
|
||||
info->target, info->target_pspec->name,
|
||||
info->flags);
|
||||
else
|
||||
result = FALSE;
|
||||
}
|
||||
error = NULL;
|
||||
|
||||
free_binding_info (info, NULL);
|
||||
_free_binding_info (info, NULL);
|
||||
}
|
||||
else if (common_info->tag_type == TAG_BINDING_EXPRESSION)
|
||||
{
|
||||
BindingExpressionInfo *info = l->data;
|
||||
GtkExpression *expression;
|
||||
GObject *object;
|
||||
|
||||
if (info->object_name)
|
||||
{
|
||||
object = gtk_builder_lookup_object (builder, info->object_name, info->line, info->col, error);
|
||||
if (object == NULL)
|
||||
{
|
||||
error = NULL;
|
||||
result = FALSE;
|
||||
}
|
||||
}
|
||||
else if (priv->current_object)
|
||||
{
|
||||
object = priv->current_object;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = info->target;
|
||||
}
|
||||
|
||||
if (object)
|
||||
{
|
||||
expression = expression_info_construct (builder, info->expr, error);
|
||||
if (expression == NULL)
|
||||
{
|
||||
g_prefix_error (error, "%s:%d:%d: ", priv->filename, info->line, info->col);
|
||||
error = NULL;
|
||||
result = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_expression_bind (expression, info->target, info->target_pspec->name, object);
|
||||
}
|
||||
}
|
||||
|
||||
free_binding_expression_info (info);
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free (priv->bindings);
|
||||
priv->bindings = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1195,7 +1271,7 @@ gtk_builder_add_objects_from_file (GtkBuilder *builder,
|
||||
/**
|
||||
* gtk_builder_extend_with_template:
|
||||
* @builder: a #GtkBuilder
|
||||
* @widget: the widget that is being extended
|
||||
* @object: the object that is being extended
|
||||
* @template_type: the type that the template is for
|
||||
* @buffer: the string to parse
|
||||
* @length: the length of @buffer (may be -1 if @buffer is nul-terminated)
|
||||
@@ -1211,7 +1287,7 @@ gtk_builder_add_objects_from_file (GtkBuilder *builder,
|
||||
*/
|
||||
gboolean
|
||||
gtk_builder_extend_with_template (GtkBuilder *builder,
|
||||
GtkWidget *widget,
|
||||
GObject *object,
|
||||
GType template_type,
|
||||
const gchar *buffer,
|
||||
gssize length,
|
||||
@@ -1221,9 +1297,9 @@ gtk_builder_extend_with_template (GtkBuilder *builder,
|
||||
GError *tmp_error;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_BUILDER (builder), 0);
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
|
||||
g_return_val_if_fail (G_IS_OBJECT (object), 0);
|
||||
g_return_val_if_fail (g_type_name (template_type) != NULL, 0);
|
||||
g_return_val_if_fail (g_type_is_a (G_OBJECT_TYPE (widget), template_type), 0);
|
||||
g_return_val_if_fail (g_type_is_a (G_OBJECT_TYPE (object), template_type), 0);
|
||||
g_return_val_if_fail (buffer && buffer[0], 0);
|
||||
|
||||
tmp_error = NULL;
|
||||
@@ -1234,7 +1310,7 @@ gtk_builder_extend_with_template (GtkBuilder *builder,
|
||||
priv->resource_prefix = NULL;
|
||||
priv->template_type = template_type;
|
||||
|
||||
gtk_builder_expose_object (builder, g_type_name (template_type), G_OBJECT (widget));
|
||||
gtk_builder_expose_object (builder, g_type_name (template_type), object);
|
||||
_gtk_builder_parser_parse_buffer (builder, "<input>",
|
||||
buffer, length,
|
||||
NULL,
|
||||
|
@@ -197,7 +197,7 @@ GClosure * gtk_builder_create_closure (GtkBuilder *builder,
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_builder_extend_with_template (GtkBuilder *builder,
|
||||
GtkWidget *widget,
|
||||
GObject *object,
|
||||
GType template_type,
|
||||
const gchar *buffer,
|
||||
gssize length,
|
||||
|
401
gtk/gtkbuilderlistitemfactory.c
Normal file
401
gtk/gtkbuilderlistitemfactory.c
Normal file
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
* 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 "gtkbuilderlistitemfactory.h"
|
||||
|
||||
#include "gtkbuilder.h"
|
||||
#include "gtkbuilderprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtklistitemfactoryprivate.h"
|
||||
#include "gtklistitemprivate.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkbuilderlistitemfactory
|
||||
* @Tiitle: GtkBuilderListItemFactory
|
||||
* @Short_description: A listitem factory using ui files
|
||||
*
|
||||
* #GtkBuilderListItemFactory is a #GtkListItemFactory that creates
|
||||
* widgets by instantiating #GtkBuilder UI templates. The templates
|
||||
* must be extending #GtkListItem, and typically use #GtkExpressions
|
||||
* to obtain data from the items in the model.
|
||||
*
|
||||
* Example:
|
||||
* |[
|
||||
* <interface>
|
||||
* <template class="GtkListItem">
|
||||
* <property name="child">
|
||||
* <object class="GtkLabel">
|
||||
* <property name="xalign">0</property>
|
||||
* <binding name="label">
|
||||
* <lookup name="name" type="SettingsKey">
|
||||
* <lookup name="item">GtkListItem</lookup>
|
||||
* </lookup>
|
||||
* </binding>
|
||||
* </object>
|
||||
* </property>
|
||||
* </template>
|
||||
* </interface>
|
||||
* ]|
|
||||
*/
|
||||
|
||||
struct _GtkBuilderListItemFactory
|
||||
{
|
||||
GtkListItemFactory parent_instance;
|
||||
|
||||
GtkBuilderScope *scope;
|
||||
GBytes *bytes;
|
||||
GBytes *data;
|
||||
char *resource;
|
||||
};
|
||||
|
||||
struct _GtkBuilderListItemFactoryClass
|
||||
{
|
||||
GtkListItemFactoryClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_BYTES,
|
||||
PROP_RESOURCE,
|
||||
PROP_SCOPE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkBuilderListItemFactory, gtk_builder_list_item_factory, GTK_TYPE_LIST_ITEM_FACTORY)
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_builder_list_item_factory_setup (GtkListItemFactory *factory,
|
||||
GtkListItemWidget *widget,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkBuilderListItemFactory *self = GTK_BUILDER_LIST_ITEM_FACTORY (factory);
|
||||
GtkBuilder *builder;
|
||||
GError *error = NULL;
|
||||
|
||||
GTK_LIST_ITEM_FACTORY_CLASS (gtk_builder_list_item_factory_parent_class)->setup (factory, widget, list_item);
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
|
||||
gtk_builder_set_current_object (builder, G_OBJECT (list_item));
|
||||
if (self->scope)
|
||||
gtk_builder_set_scope (builder, self->scope);
|
||||
|
||||
if (!gtk_builder_extend_with_template (builder, G_OBJECT (list_item), GTK_TYPE_LIST_ITEM,
|
||||
(const gchar *)g_bytes_get_data (self->data, NULL),
|
||||
g_bytes_get_size (self->data),
|
||||
&error))
|
||||
{
|
||||
g_critical ("Error building template for list item: %s", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
/* This should never happen, if the template XML cannot be built
|
||||
* then it is a critical programming error.
|
||||
*/
|
||||
g_object_unref (builder);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_builder_list_item_factory_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkBuilderListItemFactory *self = GTK_BUILDER_LIST_ITEM_FACTORY (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_BYTES:
|
||||
g_value_set_boxed (value, self->bytes);
|
||||
break;
|
||||
|
||||
case PROP_RESOURCE:
|
||||
g_value_set_string (value, self->resource);
|
||||
break;
|
||||
|
||||
case PROP_SCOPE:
|
||||
g_value_set_object (value, self->scope);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_builder_list_item_factory_set_bytes (GtkBuilderListItemFactory *self,
|
||||
GBytes *bytes)
|
||||
{
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (self->bytes)
|
||||
{
|
||||
g_critical ("Data for GtkBuilderListItemFactory has already been set.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->bytes = g_bytes_ref (bytes);
|
||||
|
||||
if (!_gtk_buildable_parser_is_precompiled (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes)))
|
||||
{
|
||||
GError *error = NULL;
|
||||
GBytes *data;
|
||||
|
||||
data = _gtk_buildable_parser_precompile (g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
&error);
|
||||
if (data == NULL)
|
||||
{
|
||||
g_warning ("Failed to precompile template for GtkBuilderListItemFactory: %s", error->message);
|
||||
g_error_free (error);
|
||||
self->data = g_bytes_ref (bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->data = data;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_builder_list_item_factory_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkBuilderListItemFactory *self = GTK_BUILDER_LIST_ITEM_FACTORY (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_BYTES:
|
||||
gtk_builder_list_item_factory_set_bytes (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_RESOURCE:
|
||||
{
|
||||
GError *error = NULL;
|
||||
GBytes *bytes;
|
||||
const char *resource;
|
||||
|
||||
resource = g_value_get_string (value);
|
||||
if (resource == NULL)
|
||||
break;
|
||||
|
||||
bytes = g_resources_lookup_data (resource, 0, &error);
|
||||
if (bytes)
|
||||
{
|
||||
if (gtk_builder_list_item_factory_set_bytes (self, bytes))
|
||||
self->resource = g_strdup (resource);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_critical ("Unable to load resource for list item template: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_SCOPE:
|
||||
self->scope = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_builder_list_item_factory_finalize (GObject *object)
|
||||
{
|
||||
GtkBuilderListItemFactory *self = GTK_BUILDER_LIST_ITEM_FACTORY (object);
|
||||
|
||||
g_clear_object (&self->scope);
|
||||
g_bytes_unref (self->bytes);
|
||||
g_bytes_unref (self->data);
|
||||
g_free (self->resource);
|
||||
|
||||
G_OBJECT_CLASS (gtk_builder_list_item_factory_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_builder_list_item_factory_class_init (GtkBuilderListItemFactoryClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GtkListItemFactoryClass *factory_class = GTK_LIST_ITEM_FACTORY_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = gtk_builder_list_item_factory_finalize;
|
||||
gobject_class->get_property = gtk_builder_list_item_factory_get_property;
|
||||
gobject_class->set_property = gtk_builder_list_item_factory_set_property;
|
||||
|
||||
factory_class->setup = gtk_builder_list_item_factory_setup;
|
||||
|
||||
/**
|
||||
* GtkBuilderListItemFactory:bytes:
|
||||
*
|
||||
* bytes containing the UI definition
|
||||
*/
|
||||
properties[PROP_BYTES] =
|
||||
g_param_spec_boxed ("bytes",
|
||||
P_("Bytes"),
|
||||
P_("bytes containing the UI definition"),
|
||||
G_TYPE_BYTES,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GtkBuilderListItemFactory:resource:
|
||||
*
|
||||
* resource containing the UI definition
|
||||
*/
|
||||
properties[PROP_RESOURCE] =
|
||||
g_param_spec_string ("resource",
|
||||
P_("Resource"),
|
||||
P_("resource containing the UI definition"),
|
||||
NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GtkBuilderListItemFactory:scope:
|
||||
*
|
||||
* scope to use when instantiating listitems
|
||||
*/
|
||||
properties[PROP_SCOPE] =
|
||||
g_param_spec_object ("scope",
|
||||
P_("Scope"),
|
||||
P_("scope to use when instantiating listitems"),
|
||||
GTK_TYPE_BUILDER_SCOPE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_builder_list_item_factory_init (GtkBuilderListItemFactory *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_builder_list_item_factory_new_from_bytes:
|
||||
* @scope: (nullable) (transfer none): A scope to use when instantiating
|
||||
* @bytes: the bytes containing the ui file to instantiate
|
||||
*
|
||||
* Creates s new #GtkBuilderListItemFactory that instantiates widgets
|
||||
* using @bytes as the data to pass to #GtkBuilder.
|
||||
*
|
||||
* Returns: a new #GtkBuilderListItemFactory
|
||||
**/
|
||||
GtkListItemFactory *
|
||||
gtk_builder_list_item_factory_new_from_bytes (GtkBuilderScope *scope,
|
||||
GBytes *bytes)
|
||||
{
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_BUILDER_LIST_ITEM_FACTORY,
|
||||
"bytes", bytes,
|
||||
"scope", scope,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_builder_list_item_factory_new_from_resource:
|
||||
* @scope: (nullable) (transfer none): A scope to use when instantiating
|
||||
* @resource_path: valid path to a resource that contains the data
|
||||
*
|
||||
* Creates s new #GtkBuilderListItemFactory that instantiates widgets
|
||||
* using data read from the given @resource_path to pass to #GtkBuilder.
|
||||
*
|
||||
* Returns: a new #GtkBuilderListItemFactory
|
||||
**/
|
||||
GtkListItemFactory *
|
||||
gtk_builder_list_item_factory_new_from_resource (GtkBuilderScope *scope,
|
||||
const char *resource_path)
|
||||
{
|
||||
g_return_val_if_fail (scope == NULL || GTK_IS_BUILDER_SCOPE (scope), NULL);
|
||||
g_return_val_if_fail (resource_path != NULL, NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_BUILDER_LIST_ITEM_FACTORY,
|
||||
"resource", resource_path,
|
||||
"scope", scope,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_builder_list_item_factory_get_bytes:
|
||||
* @self: a #GtkBuilderListItemFactory
|
||||
*
|
||||
* Gets the data used as the #GtkBuilder UI template for constructing
|
||||
* listitems.
|
||||
*
|
||||
* Returns: (transfer none): The GtkBuilder data
|
||||
*
|
||||
**/
|
||||
GBytes *
|
||||
gtk_builder_list_item_factory_get_bytes (GtkBuilderListItemFactory *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_BUILDER_LIST_ITEM_FACTORY (self), NULL);
|
||||
|
||||
return self->bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_builder_list_item_factory_get_resource:
|
||||
* @self: a #GtkBuilderListItemFactory
|
||||
*
|
||||
* If the data references a resource, gets the path of that resource.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The path to the resource or %NULL
|
||||
* if none
|
||||
**/
|
||||
const char *
|
||||
gtk_builder_list_item_factory_get_resource (GtkBuilderListItemFactory *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_BUILDER_LIST_ITEM_FACTORY (self), NULL);
|
||||
|
||||
return self->resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_builder_list_item_factory_get_scope:
|
||||
* @self: a #GtkBuilderListItemFactory
|
||||
*
|
||||
* Gets the scope used when constructing listitems.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): The scope used when constructing listitems
|
||||
**/
|
||||
GtkBuilderScope *
|
||||
gtk_builder_list_item_factory_get_scope (GtkBuilderListItemFactory *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_BUILDER_LIST_ITEM_FACTORY (self), NULL);
|
||||
|
||||
return self->scope;
|
||||
}
|
||||
|
60
gtk/gtkbuilderlistitemfactory.h
Normal file
60
gtk/gtkbuilderlistitemfactory.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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_BUILDER_LIST_ITEM_FACTORY_H__
|
||||
#define __GTK_BUILDER_LIST_ITEM_FACTORY_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtklistitemfactory.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_BUILDER_LIST_ITEM_FACTORY (gtk_builder_list_item_factory_get_type ())
|
||||
#define GTK_BUILDER_LIST_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_BUILDER_LIST_ITEM_FACTORY, GtkBuilderListItemFactory))
|
||||
#define GTK_BUILDER_LIST_ITEM_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_BUILDER_LIST_ITEM_FACTORY, GtkBuilderListItemFactoryClass))
|
||||
#define GTK_IS_BUILDER_LIST_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_BUILDER_LIST_ITEM_FACTORY))
|
||||
#define GTK_IS_BUILDER_LIST_ITEM_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_BUILDER_LIST_ITEM_FACTORY))
|
||||
#define GTK_BUILDER_LIST_ITEM_FACTORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_BUILDER_LIST_ITEM_FACTORY, GtkBuilderListItemFactoryClass))
|
||||
|
||||
typedef struct _GtkBuilderListItemFactory GtkBuilderListItemFactory;
|
||||
typedef struct _GtkBuilderListItemFactoryClass GtkBuilderListItemFactoryClass;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_builder_list_item_factory_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkListItemFactory * gtk_builder_list_item_factory_new_from_bytes (GtkBuilderScope *scope,
|
||||
GBytes *bytes);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkListItemFactory * gtk_builder_list_item_factory_new_from_resource (GtkBuilderScope *scope,
|
||||
const char *resource_path);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GBytes * gtk_builder_list_item_factory_get_bytes (GtkBuilderListItemFactory *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * gtk_builder_list_item_factory_get_resource (GtkBuilderListItemFactory *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkBuilderScope * gtk_builder_list_item_factory_get_scope (GtkBuilderListItemFactory *self) G_GNUC_PURE;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_BUILDER_LIST_ITEM_FACTORY_H__ */
|
@@ -913,7 +913,8 @@ parse_property (ParserData *data,
|
||||
{
|
||||
BindingInfo *binfo;
|
||||
|
||||
binfo = g_slice_new (BindingInfo);
|
||||
binfo = g_slice_new0 (BindingInfo);
|
||||
binfo->tag_type = TAG_BINDING;
|
||||
binfo->target = NULL;
|
||||
binfo->target_pspec = pspec;
|
||||
binfo->source = g_strdup (bind_source);
|
||||
@@ -932,7 +933,7 @@ parse_property (ParserData *data,
|
||||
return;
|
||||
}
|
||||
|
||||
info = g_slice_new (PropertyInfo);
|
||||
info = g_slice_new0 (PropertyInfo);
|
||||
info->tag_type = TAG_PROPERTY;
|
||||
info->pspec = pspec;
|
||||
info->text = g_string_new ("");
|
||||
@@ -945,14 +946,504 @@ parse_property (ParserData *data,
|
||||
state_push (data, info);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_binding (ParserData *data,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
BindingExpressionInfo *info;
|
||||
const char *name = NULL;
|
||||
const char *object_name = NULL;
|
||||
ObjectInfo *object_info;
|
||||
GParamSpec *pspec = NULL;
|
||||
|
||||
object_info = state_peek_info (data, ObjectInfo);
|
||||
if (!object_info ||
|
||||
!(object_info->tag_type == TAG_OBJECT ||
|
||||
object_info->tag_type == TAG_TEMPLATE))
|
||||
{
|
||||
error_invalid_tag (data, element_name, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, names, values, error,
|
||||
G_MARKUP_COLLECT_STRING, "name", &name,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "object", &object_name,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
pspec = g_object_class_find_property (object_info->oclass, name);
|
||||
|
||||
if (!pspec)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_PROPERTY,
|
||||
"Invalid property: %s.%s",
|
||||
g_type_name (object_info->type), name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
else if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_PROPERTY,
|
||||
"%s.%s is a construct-only property",
|
||||
g_type_name (object_info->type), name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
else if (!(pspec->flags & G_PARAM_WRITABLE))
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_PROPERTY,
|
||||
"%s.%s is a non-writable property",
|
||||
g_type_name (object_info->type), name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
info = g_slice_new0 (BindingExpressionInfo);
|
||||
info->tag_type = TAG_BINDING_EXPRESSION;
|
||||
info->target = NULL;
|
||||
info->target_pspec = pspec;
|
||||
info->object_name = g_strdup (object_name);
|
||||
gtk_buildable_parse_context_get_position (&data->ctx, &info->line, &info->col);
|
||||
|
||||
state_push (data, info);
|
||||
}
|
||||
|
||||
static void
|
||||
free_property_info (PropertyInfo *info)
|
||||
{
|
||||
if (info->value)
|
||||
{
|
||||
if (G_PARAM_SPEC_VALUE_TYPE (info->pspec) == GTK_TYPE_EXPRESSION)
|
||||
gtk_expression_unref (info->value);
|
||||
else
|
||||
g_assert_not_reached();
|
||||
}
|
||||
g_string_free (info->text, TRUE);
|
||||
g_free (info->context);
|
||||
g_slice_free (PropertyInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
free_expression_info (ExpressionInfo *info)
|
||||
{
|
||||
switch (info->expression_type)
|
||||
{
|
||||
case EXPRESSION_EXPRESSION:
|
||||
g_clear_pointer (&info->expression, gtk_expression_unref);
|
||||
break;
|
||||
|
||||
case EXPRESSION_CONSTANT:
|
||||
g_string_free (info->constant.text, TRUE);
|
||||
break;
|
||||
|
||||
case EXPRESSION_CLOSURE:
|
||||
g_free (info->closure.function_name);
|
||||
g_free (info->closure.object_name);
|
||||
g_slist_free_full (info->closure.params, (GDestroyNotify) free_expression_info);
|
||||
break;
|
||||
|
||||
case EXPRESSION_PROPERTY:
|
||||
g_clear_pointer (&info->property.expression, free_expression_info);
|
||||
g_free (info->property.property_name);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
g_slice_free (ExpressionInfo, info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_expression_parent (ParserData *data)
|
||||
{
|
||||
CommonInfo *common_info = state_peek_info (data, CommonInfo);
|
||||
|
||||
if (common_info == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (common_info->tag_type == TAG_PROPERTY)
|
||||
{
|
||||
PropertyInfo *prop_info = (PropertyInfo *) common_info;
|
||||
|
||||
return G_PARAM_SPEC_VALUE_TYPE (prop_info->pspec) == GTK_TYPE_EXPRESSION;
|
||||
}
|
||||
else if (common_info->tag_type == TAG_BINDING_EXPRESSION)
|
||||
{
|
||||
BindingExpressionInfo *expr_info = (BindingExpressionInfo *) common_info;
|
||||
|
||||
return expr_info->expr == NULL;
|
||||
}
|
||||
else if (common_info->tag_type == TAG_EXPRESSION)
|
||||
{
|
||||
ExpressionInfo *expr_info = (ExpressionInfo *) common_info;
|
||||
|
||||
switch (expr_info->expression_type)
|
||||
{
|
||||
case EXPRESSION_CLOSURE:
|
||||
return TRUE;
|
||||
case EXPRESSION_CONSTANT:
|
||||
return FALSE;
|
||||
case EXPRESSION_PROPERTY:
|
||||
return expr_info->property.expression == NULL;
|
||||
case EXPRESSION_EXPRESSION:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_constant_expression (ParserData *data,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
ExpressionInfo *info;
|
||||
const char *type_name = NULL;
|
||||
GType type;
|
||||
|
||||
if (!check_expression_parent (data))
|
||||
{
|
||||
error_invalid_tag (data, element_name, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, names, values, error,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "type", &type_name,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type_name == NULL)
|
||||
type = G_TYPE_INVALID;
|
||||
else
|
||||
{
|
||||
type = gtk_builder_get_type_from_name (data->builder, type_name);
|
||||
if (type == G_TYPE_INVALID)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_VALUE,
|
||||
"Invalid type '%s'", type_name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
info = g_slice_new0 (ExpressionInfo);
|
||||
info->tag_type = TAG_EXPRESSION;
|
||||
info->expression_type = EXPRESSION_CONSTANT;
|
||||
info->constant.type = type;
|
||||
info->constant.text = g_string_new (NULL);
|
||||
|
||||
state_push (data, info);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_closure_expression (ParserData *data,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
ExpressionInfo *info;
|
||||
const char *type_name;
|
||||
const char *function_name;
|
||||
const char *object_name = NULL;
|
||||
gboolean swapped = -1;
|
||||
GType type;
|
||||
|
||||
if (!check_expression_parent (data))
|
||||
{
|
||||
error_invalid_tag (data, element_name, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, names, values, error,
|
||||
G_MARKUP_COLLECT_STRING, "type", &type_name,
|
||||
G_MARKUP_COLLECT_STRING, "function", &function_name,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "object", &object_name,
|
||||
G_MARKUP_COLLECT_TRISTATE|G_MARKUP_COLLECT_OPTIONAL, "swapped", &swapped,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
type = gtk_builder_get_type_from_name (data->builder, type_name);
|
||||
if (type == G_TYPE_INVALID)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_VALUE,
|
||||
"Invalid type '%s'", type_name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Swapped defaults to FALSE except when object is set */
|
||||
if (swapped == -1)
|
||||
{
|
||||
if (object_name)
|
||||
swapped = TRUE;
|
||||
else
|
||||
swapped = FALSE;
|
||||
}
|
||||
|
||||
info = g_slice_new0 (ExpressionInfo);
|
||||
info->tag_type = TAG_EXPRESSION;
|
||||
info->expression_type = EXPRESSION_CLOSURE;
|
||||
info->closure.type = type;
|
||||
info->closure.swapped = swapped;
|
||||
info->closure.function_name = g_strdup (function_name);
|
||||
info->closure.object_name = g_strdup (object_name);
|
||||
|
||||
state_push (data, info);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_lookup_expression (ParserData *data,
|
||||
const gchar *element_name,
|
||||
const gchar **names,
|
||||
const gchar **values,
|
||||
GError **error)
|
||||
{
|
||||
ExpressionInfo *info;
|
||||
const char *property_name;
|
||||
const char *type_name = NULL;
|
||||
GType type;
|
||||
|
||||
if (!check_expression_parent (data))
|
||||
{
|
||||
error_invalid_tag (data, element_name, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, names, values, error,
|
||||
G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "type", &type_name,
|
||||
G_MARKUP_COLLECT_STRING, "name", &property_name,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
{
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type_name == NULL)
|
||||
{
|
||||
type = G_TYPE_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = gtk_builder_get_type_from_name (data->builder, type_name);
|
||||
if (type == G_TYPE_INVALID)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_VALUE,
|
||||
"Invalid type '%s'", type_name);
|
||||
_gtk_builder_prefix_error (data->builder, &data->ctx, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
info = g_slice_new0 (ExpressionInfo);
|
||||
info->tag_type = TAG_EXPRESSION;
|
||||
info->expression_type = EXPRESSION_PROPERTY;
|
||||
info->property.this_type = type;
|
||||
info->property.property_name = g_strdup (property_name);
|
||||
|
||||
state_push (data, info);
|
||||
}
|
||||
|
||||
GtkExpression *
|
||||
expression_info_construct (GtkBuilder *builder,
|
||||
ExpressionInfo *info,
|
||||
GError **error)
|
||||
{
|
||||
switch (info->expression_type)
|
||||
{
|
||||
case EXPRESSION_EXPRESSION:
|
||||
break;
|
||||
|
||||
case EXPRESSION_CONSTANT:
|
||||
{
|
||||
GtkExpression *expr;
|
||||
|
||||
if (info->constant.type == G_TYPE_INVALID)
|
||||
{
|
||||
GObject *o = gtk_builder_lookup_object (builder, info->constant.text->str, 0, 0, error);
|
||||
if (o == NULL)
|
||||
return NULL;
|
||||
|
||||
expr = gtk_object_expression_new (o);
|
||||
}
|
||||
else
|
||||
{
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
if (!gtk_builder_value_from_string_type (builder,
|
||||
info->constant.type,
|
||||
info->constant.text->str,
|
||||
&value,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
if (G_VALUE_HOLDS_OBJECT (&value))
|
||||
expr = gtk_object_expression_new (g_value_get_object (&value));
|
||||
else
|
||||
expr = gtk_constant_expression_new_for_value (&value);
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
g_string_free (info->constant.text, TRUE);
|
||||
info->expression_type = EXPRESSION_EXPRESSION;
|
||||
info->expression = expr;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPRESSION_CLOSURE:
|
||||
{
|
||||
GObject *object;
|
||||
GClosure *closure;
|
||||
guint i, n_params;
|
||||
GtkExpression **params;
|
||||
GtkExpression *expression;
|
||||
GSList *l;
|
||||
|
||||
if (info->closure.object_name)
|
||||
{
|
||||
object = gtk_builder_lookup_object (builder, info->closure.object_name, 0, 0, error);
|
||||
if (object == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
closure = gtk_builder_create_closure (builder,
|
||||
info->closure.function_name,
|
||||
info->closure.swapped,
|
||||
object,
|
||||
error);
|
||||
if (closure == NULL)
|
||||
return NULL;
|
||||
n_params = g_slist_length (info->closure.params);
|
||||
params = g_newa (GtkExpression *, n_params);
|
||||
i = n_params;
|
||||
for (l = info->closure.params; l; l = l->next)
|
||||
{
|
||||
params[--i] = expression_info_construct (builder, l->data, error);
|
||||
if (params[i] == NULL)
|
||||
return NULL;
|
||||
}
|
||||
expression = gtk_closure_expression_new (info->closure.type, closure, n_params, params);
|
||||
g_free (info->closure.function_name);
|
||||
g_free (info->closure.object_name);
|
||||
g_slist_free_full (info->closure.params, (GDestroyNotify) free_expression_info);
|
||||
info->expression_type = EXPRESSION_EXPRESSION;
|
||||
info->expression = expression;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPRESSION_PROPERTY:
|
||||
{
|
||||
GtkExpression *expression;
|
||||
GType type;
|
||||
GParamSpec *pspec;
|
||||
|
||||
if (info->property.expression)
|
||||
{
|
||||
expression = expression_info_construct (builder, info->property.expression, error);
|
||||
if (expression == NULL)
|
||||
return NULL;
|
||||
free_expression_info (info->property.expression);
|
||||
info->property.expression = NULL;
|
||||
}
|
||||
else
|
||||
expression = NULL;
|
||||
|
||||
if (info->property.this_type != G_TYPE_INVALID)
|
||||
type = info->property.this_type;
|
||||
else if (expression != NULL)
|
||||
type = gtk_expression_get_value_type (expression);
|
||||
else
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
|
||||
"Lookups require a type attribute if they don't have an expression.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_type_is_a (type, G_TYPE_OBJECT))
|
||||
{
|
||||
GObjectClass *class = g_type_class_ref (type);
|
||||
pspec = g_object_class_find_property (class, info->property.property_name);
|
||||
g_type_class_unref (class);
|
||||
}
|
||||
else if (g_type_is_a (type, G_TYPE_INTERFACE))
|
||||
{
|
||||
GTypeInterface *iface = g_type_default_interface_ref (type);
|
||||
pspec = g_object_interface_find_property (iface, info->property.property_name);
|
||||
g_type_default_interface_unref (iface);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
|
||||
"Type `%s` does not support properties",
|
||||
g_type_name (type));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_MISSING_ATTRIBUTE,
|
||||
"Type `%s` does not have a property name `%s`",
|
||||
g_type_name (type), info->property.property_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expression = gtk_property_expression_new_for_pspec (expression, pspec);
|
||||
|
||||
g_free (info->property.property_name);
|
||||
info->expression_type = EXPRESSION_EXPRESSION;
|
||||
info->expression = expression;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
return gtk_expression_ref (info->expression);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_signal (ParserData *data,
|
||||
const gchar *element_name,
|
||||
@@ -1037,6 +1528,24 @@ _free_signal_info (SignalInfo *info,
|
||||
g_slice_free (SignalInfo, info);
|
||||
}
|
||||
|
||||
void
|
||||
_free_binding_info (BindingInfo *info,
|
||||
gpointer user)
|
||||
{
|
||||
g_free (info->source);
|
||||
g_free (info->source_property);
|
||||
g_slice_free (BindingInfo, info);
|
||||
}
|
||||
|
||||
void
|
||||
free_binding_expression_info (BindingExpressionInfo *info)
|
||||
{
|
||||
if (info->expr)
|
||||
free_expression_info (info->expr);
|
||||
g_free (info->object_name);
|
||||
g_slice_free (BindingExpressionInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
free_requires_info (RequiresInfo *info,
|
||||
gpointer user_data)
|
||||
@@ -1277,6 +1786,8 @@ start_element (GtkBuildableParseContext *context,
|
||||
}
|
||||
else if (strcmp (element_name, "property") == 0)
|
||||
parse_property (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "binding") == 0)
|
||||
parse_binding (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "child") == 0)
|
||||
parse_child (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "signal") == 0)
|
||||
@@ -1287,6 +1798,12 @@ start_element (GtkBuildableParseContext *context,
|
||||
parse_requires (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "interface") == 0)
|
||||
parse_interface (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "constant") == 0)
|
||||
parse_constant_expression (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "closure") == 0)
|
||||
parse_closure_expression (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "lookup") == 0)
|
||||
parse_lookup_expression (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "menu") == 0)
|
||||
_gtk_builder_menu_start (data, element_name, names, values, error);
|
||||
else if (strcmp (element_name, "placeholder") == 0)
|
||||
@@ -1362,6 +1879,30 @@ end_element (GtkBuildableParseContext *context,
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
else if (strcmp (element_name, "binding") == 0)
|
||||
{
|
||||
BindingExpressionInfo *binfo = state_pop_info (data, BindingExpressionInfo);
|
||||
CommonInfo *info = state_peek_info (data, CommonInfo);
|
||||
|
||||
g_assert (info != NULL);
|
||||
|
||||
if (binfo->expr == NULL)
|
||||
{
|
||||
g_set_error (error,
|
||||
GTK_BUILDER_ERROR,
|
||||
GTK_BUILDER_ERROR_INVALID_TAG,
|
||||
"Binding tag requires an expression");
|
||||
free_binding_expression_info (binfo);
|
||||
}
|
||||
else if (info->tag_type == TAG_OBJECT ||
|
||||
info->tag_type == TAG_TEMPLATE)
|
||||
{
|
||||
ObjectInfo *object_info = (ObjectInfo*)info;
|
||||
object_info->bindings = g_slist_prepend (object_info->bindings, binfo);
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
else if (strcmp (element_name, "object") == 0 ||
|
||||
strcmp (element_name, "template") == 0)
|
||||
{
|
||||
@@ -1422,6 +1963,49 @@ end_element (GtkBuildableParseContext *context,
|
||||
signal_info->object_name = g_strdup (object_info->id);
|
||||
object_info->signals = g_slist_prepend (object_info->signals, signal_info);
|
||||
}
|
||||
else if (strcmp (element_name, "constant") == 0 ||
|
||||
strcmp (element_name, "closure") == 0 ||
|
||||
strcmp (element_name, "lookup") == 0)
|
||||
{
|
||||
ExpressionInfo *expression_info = state_pop_info (data, ExpressionInfo);
|
||||
CommonInfo *parent_info = state_peek_info (data, CommonInfo);
|
||||
|
||||
if (parent_info->tag_type == TAG_BINDING_EXPRESSION)
|
||||
{
|
||||
BindingExpressionInfo *expr_info = (BindingExpressionInfo *) parent_info;
|
||||
|
||||
expr_info->expr = expression_info;
|
||||
}
|
||||
else if (parent_info->tag_type == TAG_PROPERTY)
|
||||
{
|
||||
PropertyInfo *prop_info = (PropertyInfo *) parent_info;
|
||||
|
||||
prop_info->value = expression_info_construct (data->builder, expression_info, error);
|
||||
}
|
||||
else if (parent_info->tag_type == TAG_EXPRESSION)
|
||||
{
|
||||
ExpressionInfo *expr_info = (ExpressionInfo *) parent_info;
|
||||
|
||||
switch (expr_info->expression_type)
|
||||
{
|
||||
case EXPRESSION_CLOSURE:
|
||||
expr_info->closure.params = g_slist_prepend (expr_info->closure.params, expression_info);
|
||||
break;
|
||||
case EXPRESSION_PROPERTY:
|
||||
expr_info->property.expression = expression_info;
|
||||
break;
|
||||
case EXPRESSION_EXPRESSION:
|
||||
case EXPRESSION_CONSTANT:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
else if (strcmp (element_name, "requires") == 0)
|
||||
{
|
||||
RequiresInfo *req_info = state_pop_info (data, RequiresInfo);
|
||||
@@ -1502,6 +2086,33 @@ text (GtkBuildableParseContext *context,
|
||||
|
||||
g_string_append_len (prop_info->text, text, text_len);
|
||||
}
|
||||
else if (strcmp (gtk_buildable_parse_context_get_element (context), "constant") == 0)
|
||||
{
|
||||
ExpressionInfo *expr_info = (ExpressionInfo *) info;
|
||||
|
||||
g_string_append_len (expr_info->constant.text, text, text_len);
|
||||
}
|
||||
else if (strcmp (gtk_buildable_parse_context_get_element (context), "lookup") == 0)
|
||||
{
|
||||
ExpressionInfo *expr_info = (ExpressionInfo *) info;
|
||||
|
||||
while (g_ascii_isspace (*text) && text_len > 0)
|
||||
{
|
||||
text++;
|
||||
text_len--;
|
||||
}
|
||||
while (text_len > 0 && g_ascii_isspace (text[text_len - 1]))
|
||||
text_len--;
|
||||
if (expr_info->property.expression == NULL && text_len > 0)
|
||||
{
|
||||
ExpressionInfo *constant = g_slice_new0 (ExpressionInfo);
|
||||
constant->tag_type = TAG_EXPRESSION;
|
||||
constant->expression_type = EXPRESSION_CONSTANT;
|
||||
constant->constant.type = G_TYPE_INVALID;
|
||||
constant->constant.text = g_string_new_len (text, text_len);
|
||||
expr_info->property.expression = constant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1516,6 +2127,12 @@ free_info (CommonInfo *info)
|
||||
case TAG_CHILD:
|
||||
free_child_info ((ChildInfo *)info);
|
||||
break;
|
||||
case TAG_BINDING:
|
||||
_free_binding_info ((BindingInfo *)info, NULL);
|
||||
break;
|
||||
case TAG_BINDING_EXPRESSION:
|
||||
free_binding_expression_info ((BindingExpressionInfo *) info);
|
||||
break;
|
||||
case TAG_PROPERTY:
|
||||
free_property_info ((PropertyInfo *)info);
|
||||
break;
|
||||
@@ -1525,6 +2142,9 @@ free_info (CommonInfo *info)
|
||||
case TAG_REQUIRES:
|
||||
free_requires_info ((RequiresInfo *)info, NULL);
|
||||
break;
|
||||
case TAG_EXPRESSION:
|
||||
free_expression_info ((ExpressionInfo *)info);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
@@ -21,16 +21,19 @@
|
||||
|
||||
#include "gtkbuilder.h"
|
||||
#include "gtkbuildable.h"
|
||||
#include "gtkexpression.h"
|
||||
|
||||
enum {
|
||||
TAG_PROPERTY,
|
||||
TAG_MENU,
|
||||
TAG_BINDING,
|
||||
TAG_BINDING_EXPRESSION,
|
||||
TAG_REQUIRES,
|
||||
TAG_OBJECT,
|
||||
TAG_CHILD,
|
||||
TAG_SIGNAL,
|
||||
TAG_INTERFACE,
|
||||
TAG_TEMPLATE,
|
||||
TAG_EXPRESSION,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -64,6 +67,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
guint tag_type;
|
||||
GParamSpec *pspec;
|
||||
gpointer value;
|
||||
GString *text;
|
||||
gboolean translatable:1;
|
||||
gboolean bound:1;
|
||||
@@ -72,6 +76,36 @@ typedef struct {
|
||||
gint col;
|
||||
} PropertyInfo;
|
||||
|
||||
typedef struct _ExpressionInfo ExpressionInfo;
|
||||
struct _ExpressionInfo {
|
||||
guint tag_type;
|
||||
enum {
|
||||
EXPRESSION_EXPRESSION,
|
||||
EXPRESSION_CONSTANT,
|
||||
EXPRESSION_CLOSURE,
|
||||
EXPRESSION_PROPERTY
|
||||
} expression_type;
|
||||
union {
|
||||
GtkExpression *expression;
|
||||
struct {
|
||||
GType type;
|
||||
GString *text;
|
||||
} constant;
|
||||
struct {
|
||||
GType type;
|
||||
char *function_name;
|
||||
char *object_name;
|
||||
gboolean swapped;
|
||||
GSList *params;
|
||||
} closure;
|
||||
struct {
|
||||
GType this_type;
|
||||
char *property_name;
|
||||
ExpressionInfo *expression;
|
||||
} property;
|
||||
};
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
guint tag_type;
|
||||
gchar *object_name;
|
||||
@@ -84,6 +118,7 @@ typedef struct {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint tag_type;
|
||||
GObject *target;
|
||||
GParamSpec *target_pspec;
|
||||
gchar *source;
|
||||
@@ -93,6 +128,17 @@ typedef struct
|
||||
gint col;
|
||||
} BindingInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint tag_type;
|
||||
GObject *target;
|
||||
GParamSpec *target_pspec;
|
||||
char *object_name;
|
||||
ExpressionInfo *expr;
|
||||
gint line;
|
||||
gint col;
|
||||
} BindingExpressionInfo;
|
||||
|
||||
typedef struct {
|
||||
guint tag_type;
|
||||
gchar *library;
|
||||
@@ -179,6 +225,12 @@ gboolean _gtk_builder_finish (GtkBuilder *builder,
|
||||
GError **error);
|
||||
void _free_signal_info (SignalInfo *info,
|
||||
gpointer user_data);
|
||||
void _free_binding_info (BindingInfo *info,
|
||||
gpointer user_data);
|
||||
void free_binding_expression_info (BindingExpressionInfo *info);
|
||||
GtkExpression * expression_info_construct (GtkBuilder *builder,
|
||||
ExpressionInfo *info,
|
||||
GError **error);
|
||||
|
||||
/* Internal API which might be made public at some point */
|
||||
gboolean _gtk_builder_boolean_from_string (const gchar *string,
|
||||
|
148
gtk/gtkcolumnlistitemfactory.c
Normal file
148
gtk/gtkcolumnlistitemfactory.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 "gtkcolumnviewlayoutprivate.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 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;
|
||||
|
||||
/* FIXME: evil */
|
||||
gtk_widget_set_layout_manager (GTK_WIDGET (widget),
|
||||
gtk_column_view_layout_new (self->view));
|
||||
|
||||
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);
|
||||
|
||||
while ((child = gtk_widget_get_first_child (GTK_WIDGET (widget))))
|
||||
{
|
||||
gtk_list_item_widget_remove_child (GTK_LIST_ITEM_WIDGET (widget), 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)
|
||||
{
|
||||
GtkWidget *cell;
|
||||
|
||||
cell = gtk_column_view_cell_new (column);
|
||||
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));
|
||||
}
|
62
gtk/gtkcolumnlistitemfactoryprivate.h
Normal file
62
gtk/gtkcolumnlistitemfactoryprivate.h
Normal 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__ */
|
1445
gtk/gtkcolumnview.c
Normal file
1445
gtk/gtkcolumnview.c
Normal file
File diff suppressed because it is too large
Load Diff
114
gtk/gtkcolumnview.h
Normal file
114
gtk/gtkcolumnview.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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_H__
|
||||
#define __GTK_COLUMN_VIEW_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtktypes.h>
|
||||
#include <gtk/gtksortlistmodel.h>
|
||||
#include <gtk/gtksorter.h>
|
||||
#include <gtk/gtkfilter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_COLUMN_VIEW (gtk_column_view_get_type ())
|
||||
#define GTK_COLUMN_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLUMN_VIEW, GtkColumnView))
|
||||
#define GTK_COLUMN_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_COLUMN_VIEW, GtkColumnViewClass))
|
||||
#define GTK_IS_COLUMN_VIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLUMN_VIEW))
|
||||
#define GTK_IS_COLUMN_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLUMN_VIEW))
|
||||
#define GTK_COLUMN_VIEW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLUMN_VIEW, GtkColumnViewClass))
|
||||
|
||||
/**
|
||||
* GtkColumnView:
|
||||
*
|
||||
* GtkColumnView is the simple list implementation for GTK's list widgets.
|
||||
*/
|
||||
typedef struct _GtkColumnView GtkColumnView;
|
||||
typedef struct _GtkColumnViewClass GtkColumnViewClass;
|
||||
/* forward declaration */
|
||||
typedef struct _GtkColumnViewColumn GtkColumnViewColumn;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_column_view_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_column_view_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_column_view_get_columns (GtkColumnView *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_append_column (GtkColumnView *self,
|
||||
GtkColumnViewColumn *column);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_remove_column (GtkColumnView *self,
|
||||
GtkColumnViewColumn *column);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_insert_column (GtkColumnView *self,
|
||||
guint position,
|
||||
GtkColumnViewColumn *column);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_column_view_get_model (GtkColumnView *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_set_model (GtkColumnView *self,
|
||||
GListModel *model);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_column_view_get_show_separators (GtkColumnView *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_set_show_separators (GtkColumnView *self,
|
||||
gboolean show_separators);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkSorter * gtk_column_view_get_sorter (GtkColumnView *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_sort_by_column (GtkColumnView *self,
|
||||
GtkColumnViewColumn *column,
|
||||
GtkSortType direction);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_set_single_click_activate (GtkColumnView *self,
|
||||
gboolean single_click_activate);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_column_view_get_single_click_activate (GtkColumnView *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_set_enable_rubberband (GtkColumnView *self,
|
||||
gboolean enable_rubberband);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_column_view_get_enable_rubberband (GtkColumnView *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_set_search_filter (GtkColumnView *self,
|
||||
GtkFilter *filter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFilter * gtk_column_view_get_search_filter (GtkColumnView *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_select_next_match (GtkColumnView *self,
|
||||
gboolean forward);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_COLUMN_VIEW_H__ */
|
199
gtk/gtkcolumnviewcell.c
Normal file
199
gtk/gtkcolumnviewcell.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* 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 "gtkcolumnviewcellprivate.h"
|
||||
|
||||
#include "gtkcolumnviewcolumnprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtklistitemwidgetprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
struct _GtkColumnViewCell
|
||||
{
|
||||
GtkListItemWidget parent_instance;
|
||||
|
||||
GtkColumnViewColumn *column;
|
||||
|
||||
/* This list isn't sorted - next/prev refer to list elements, not rows in the list */
|
||||
GtkColumnViewCell *next_cell;
|
||||
GtkColumnViewCell *prev_cell;
|
||||
};
|
||||
|
||||
struct _GtkColumnViewCellClass
|
||||
{
|
||||
GtkListItemWidgetClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkColumnViewCell, gtk_column_view_cell, GTK_TYPE_LIST_ITEM_WIDGET)
|
||||
|
||||
static void
|
||||
gtk_column_view_cell_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkColumnViewCell *cell = GTK_COLUMN_VIEW_CELL (widget);
|
||||
GtkWidget *child = gtk_widget_get_first_child (widget);
|
||||
|
||||
if (child)
|
||||
gtk_widget_measure (child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
int fixed_width = gtk_column_view_column_get_fixed_width (cell->column);
|
||||
if (fixed_width > -1)
|
||||
*minimum = *natural = fixed_width;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_cell_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_cell_root (GtkWidget *widget)
|
||||
{
|
||||
GtkColumnViewCell *self = GTK_COLUMN_VIEW_CELL (widget);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_column_view_cell_parent_class)->root (widget);
|
||||
|
||||
self->next_cell = gtk_column_view_column_get_first_cell (self->column);
|
||||
if (self->next_cell)
|
||||
self->next_cell->prev_cell = self;
|
||||
|
||||
gtk_column_view_column_add_cell (self->column, self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_cell_unroot (GtkWidget *widget)
|
||||
{
|
||||
GtkColumnViewCell *self = GTK_COLUMN_VIEW_CELL (widget);
|
||||
|
||||
gtk_column_view_column_remove_cell (self->column, self);
|
||||
|
||||
if (self->prev_cell)
|
||||
self->prev_cell->next_cell = self->next_cell;
|
||||
if (self->next_cell)
|
||||
self->next_cell->prev_cell = self->prev_cell;
|
||||
|
||||
self->prev_cell = NULL;
|
||||
self->next_cell = NULL;
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_column_view_cell_parent_class)->unroot (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_cell_dispose (GObject *object)
|
||||
{
|
||||
GtkColumnViewCell *self = GTK_COLUMN_VIEW_CELL (object);
|
||||
|
||||
g_clear_object (&self->column);
|
||||
|
||||
G_OBJECT_CLASS (gtk_column_view_cell_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_cell_class_init (GtkColumnViewCellClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
widget_class->root = gtk_column_view_cell_root;
|
||||
widget_class->unroot = gtk_column_view_cell_unroot;
|
||||
widget_class->measure = gtk_column_view_cell_measure;
|
||||
widget_class->size_allocate = gtk_column_view_cell_size_allocate;
|
||||
|
||||
gobject_class->dispose = gtk_column_view_cell_dispose;
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, I_("cell"));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_cell_resize_func (GtkWidget *widget)
|
||||
{
|
||||
GtkColumnViewCell *self = GTK_COLUMN_VIEW_CELL (widget);
|
||||
|
||||
if (self->column)
|
||||
gtk_column_view_column_queue_resize (self->column);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_cell_init (GtkColumnViewCell *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
|
||||
gtk_widget_set_can_focus (widget, FALSE);
|
||||
/* FIXME: Figure out if settting the manager class to INVALID should work */
|
||||
gtk_widget_set_layout_manager (widget, NULL);
|
||||
widget->priv->resize_func = gtk_column_view_cell_resize_func;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_column_view_cell_new (GtkColumnViewColumn *column)
|
||||
{
|
||||
GtkColumnViewCell *cell;
|
||||
|
||||
cell = g_object_new (GTK_TYPE_COLUMN_VIEW_CELL,
|
||||
"factory", gtk_column_view_column_get_factory (column),
|
||||
"visible", gtk_column_view_column_get_visible (column),
|
||||
NULL);
|
||||
|
||||
cell->column = g_object_ref (column);
|
||||
|
||||
return GTK_WIDGET (cell);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_column_view_cell_remove (GtkColumnViewCell *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
|
||||
gtk_list_item_widget_remove_child (GTK_LIST_ITEM_WIDGET (gtk_widget_get_parent (widget)), widget);
|
||||
}
|
||||
|
||||
GtkColumnViewCell *
|
||||
gtk_column_view_cell_get_next (GtkColumnViewCell *self)
|
||||
{
|
||||
return self->next_cell;
|
||||
}
|
||||
|
||||
GtkColumnViewCell *
|
||||
gtk_column_view_cell_get_prev (GtkColumnViewCell *self)
|
||||
{
|
||||
return self->prev_cell;
|
||||
}
|
||||
|
||||
GtkColumnViewColumn *
|
||||
gtk_column_view_cell_get_column (GtkColumnViewCell *self)
|
||||
{
|
||||
return self->column;
|
||||
}
|
49
gtk/gtkcolumnviewcellprivate.h
Normal file
49
gtk/gtkcolumnviewcellprivate.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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_CELL_PRIVATE_H__
|
||||
#define __GTK_COLUMN_VIEW_CELL_PRIVATE_H__
|
||||
|
||||
#include "gtkcolumnviewcolumn.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_COLUMN_VIEW_CELL (gtk_column_view_cell_get_type ())
|
||||
#define GTK_COLUMN_VIEW_CELL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLUMN_VIEW_CELL, GtkColumnViewCell))
|
||||
#define GTK_COLUMN_VIEW_CELL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_COLUMN_VIEW_CELL, GtkColumnViewCellClass))
|
||||
#define GTK_IS_COLUMN_VIEW_CELL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLUMN_VIEW_CELL))
|
||||
#define GTK_IS_COLUMN_VIEW_CELL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLUMN_VIEW_CELL))
|
||||
#define GTK_COLUMN_VIEW_CELL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLUMN_VIEW_CELL, GtkColumnViewCellClass))
|
||||
|
||||
typedef struct _GtkColumnViewCell GtkColumnViewCell;
|
||||
typedef struct _GtkColumnViewCellClass GtkColumnViewCellClass;
|
||||
|
||||
GType gtk_column_view_cell_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * gtk_column_view_cell_new (GtkColumnViewColumn *column);
|
||||
|
||||
void gtk_column_view_cell_remove (GtkColumnViewCell *self);
|
||||
|
||||
GtkColumnViewCell * gtk_column_view_cell_get_next (GtkColumnViewCell *self);
|
||||
GtkColumnViewCell * gtk_column_view_cell_get_prev (GtkColumnViewCell *self);
|
||||
GtkColumnViewColumn * gtk_column_view_cell_get_column (GtkColumnViewCell *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_COLUMN_VIEW_CELL_PRIVATE_H__ */
|
1095
gtk/gtkcolumnviewcolumn.c
Normal file
1095
gtk/gtkcolumnviewcolumn.c
Normal file
File diff suppressed because it is too large
Load Diff
112
gtk/gtkcolumnviewcolumn.h
Normal file
112
gtk/gtkcolumnviewcolumn.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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_COLUMN_H__
|
||||
#define __GTK_COLUMN_VIEW_COLUMN_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkcolumnview.h>
|
||||
#include <gtk/gtksorter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_COLUMN_VIEW_COLUMN (gtk_column_view_column_get_type ())
|
||||
#define GTK_COLUMN_VIEW_COLUMN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COLUMN_VIEW_COLUMN, GtkColumnViewColumn))
|
||||
#define GTK_COLUMN_VIEW_COLUMN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_COLUMN_VIEW_COLUMN, GtkColumnViewColumnClass))
|
||||
#define GTK_IS_COLUMN_VIEW_COLUMN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COLUMN_VIEW_COLUMN))
|
||||
#define GTK_IS_COLUMN_VIEW_COLUMN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COLUMN_VIEW_COLUMN))
|
||||
#define GTK_COLUMN_VIEW_COLUMN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COLUMN_VIEW_COLUMN, GtkColumnViewColumnClass))
|
||||
|
||||
/**
|
||||
* GtkColumnViewColumn:
|
||||
*
|
||||
* GtkColumnViewColumns are added to #GtkColumnViews.
|
||||
*/
|
||||
typedef struct _GtkColumnViewColumnClass GtkColumnViewColumnClass;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_column_view_column_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkColumnViewColumn * gtk_column_view_column_new (const char *title);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkColumnViewColumn * gtk_column_view_column_new_with_factory (const char *title,
|
||||
GtkListItemFactory *factory);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkColumnView * gtk_column_view_column_get_column_view (GtkColumnViewColumn *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_factory (GtkColumnViewColumn *self,
|
||||
GtkListItemFactory *factory);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkListItemFactory * gtk_column_view_column_get_factory (GtkColumnViewColumn *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_title (GtkColumnViewColumn *self,
|
||||
const char *title);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * gtk_column_view_column_get_title (GtkColumnViewColumn *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_sorter (GtkColumnViewColumn *self,
|
||||
GtkSorter *sorter);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkSorter * gtk_column_view_column_get_sorter (GtkColumnViewColumn *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_visible (GtkColumnViewColumn *self,
|
||||
gboolean visible);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_column_view_column_get_visible (GtkColumnViewColumn *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_fixed_width (GtkColumnViewColumn *self,
|
||||
int fixed_width);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gtk_column_view_column_get_fixed_width (GtkColumnViewColumn *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_resizable (GtkColumnViewColumn *self,
|
||||
gboolean resizable);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_column_view_column_get_resizable (GtkColumnViewColumn *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_expand (GtkColumnViewColumn *self,
|
||||
gboolean expand);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_column_view_column_get_expand (GtkColumnViewColumn *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_reorderable (GtkColumnViewColumn *self,
|
||||
gboolean reorderable);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_column_view_column_get_reorderable (GtkColumnViewColumn *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_column_view_column_set_header_menu (GtkColumnViewColumn *self,
|
||||
GMenuModel *menu);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GMenuModel * gtk_column_view_column_get_header_menu (GtkColumnViewColumn *self);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_COLUMN_VIEW_COLUMN_H__ */
|
57
gtk/gtkcolumnviewcolumnprivate.h
Normal file
57
gtk/gtkcolumnviewcolumnprivate.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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_COLUMN_PRIVATE_H__
|
||||
#define __GTK_COLUMN_VIEW_COLUMN_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcolumnviewcolumn.h"
|
||||
|
||||
#include "gtk/gtkcolumnviewcellprivate.h"
|
||||
|
||||
|
||||
void gtk_column_view_column_set_column_view (GtkColumnViewColumn *self,
|
||||
GtkColumnView *view);
|
||||
|
||||
void gtk_column_view_column_add_cell (GtkColumnViewColumn *self,
|
||||
GtkColumnViewCell *cell);
|
||||
void gtk_column_view_column_remove_cell (GtkColumnViewColumn *self,
|
||||
GtkColumnViewCell *cell);
|
||||
GtkColumnViewCell * gtk_column_view_column_get_first_cell (GtkColumnViewColumn *self);
|
||||
GtkWidget * gtk_column_view_column_get_header (GtkColumnViewColumn *self);
|
||||
|
||||
void gtk_column_view_column_queue_resize (GtkColumnViewColumn *self);
|
||||
void gtk_column_view_column_measure (GtkColumnViewColumn *self,
|
||||
int *minimum,
|
||||
int *natural);
|
||||
void gtk_column_view_column_allocate (GtkColumnViewColumn *self,
|
||||
int offset,
|
||||
int size);
|
||||
void gtk_column_view_column_get_allocation (GtkColumnViewColumn *self,
|
||||
int *offset,
|
||||
int *size);
|
||||
|
||||
void gtk_column_view_column_notify_sort (GtkColumnViewColumn *self);
|
||||
|
||||
void gtk_column_view_column_set_header_position (GtkColumnViewColumn *self,
|
||||
int offset);
|
||||
void gtk_column_view_column_get_header_allocation (GtkColumnViewColumn *self,
|
||||
int *offset,
|
||||
int *size);
|
||||
|
||||
#endif /* __GTK_COLUMN_VIEW_COLUMN_PRIVATE_H__ */
|
159
gtk/gtkcolumnviewlayout.c
Normal file
159
gtk/gtkcolumnviewlayout.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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 "gtkcolumnviewlayoutprivate.h"
|
||||
|
||||
#include "gtkcolumnviewcellprivate.h"
|
||||
#include "gtkcolumnviewcolumnprivate.h"
|
||||
#include "gtkcolumnviewprivate.h"
|
||||
#include "gtkcolumnviewtitleprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
struct _GtkColumnViewLayout
|
||||
{
|
||||
GtkLayoutManager parent_instance;
|
||||
|
||||
GtkColumnView *view; /* no reference */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkColumnViewLayout, gtk_column_view_layout, GTK_TYPE_LAYOUT_MANAGER)
|
||||
|
||||
static void
|
||||
gtk_column_view_layout_measure_along (GtkColumnViewLayout *self,
|
||||
GtkWidget *widget,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkOrientation orientation = GTK_ORIENTATION_VERTICAL;
|
||||
GtkWidget *child;
|
||||
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
int child_min = 0;
|
||||
int child_nat = 0;
|
||||
int child_min_baseline = -1;
|
||||
int child_nat_baseline = -1;
|
||||
|
||||
gtk_widget_measure (child, orientation, for_size,
|
||||
&child_min, &child_nat,
|
||||
&child_min_baseline, &child_nat_baseline);
|
||||
|
||||
*minimum = MAX (*minimum, child_min);
|
||||
*natural = MAX (*natural, child_nat);
|
||||
|
||||
if (child_min_baseline > -1)
|
||||
*minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
|
||||
if (child_nat_baseline > -1)
|
||||
*natural_baseline = MAX (*natural_baseline, child_nat_baseline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_layout_measure (GtkLayoutManager *layout,
|
||||
GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkColumnViewLayout *self = GTK_COLUMN_VIEW_LAYOUT (layout);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
gtk_column_view_measure_across (GTK_COLUMN_VIEW (self->view),
|
||||
minimum,
|
||||
natural);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_column_view_layout_measure_along (self,
|
||||
widget,
|
||||
for_size,
|
||||
minimum,
|
||||
natural,
|
||||
minimum_baseline,
|
||||
natural_baseline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
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));
|
||||
gtk_column_view_column_get_allocation (column, &col_x, &col_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
column = gtk_column_view_title_get_column (GTK_COLUMN_VIEW_TITLE (child));
|
||||
gtk_column_view_column_get_header_allocation (column, &col_x, &col_width);
|
||||
}
|
||||
|
||||
gtk_widget_size_allocate (child, &(GtkAllocation) { col_x, 0, col_width, height }, baseline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_layout_class_init (GtkColumnViewLayoutClass *klass)
|
||||
{
|
||||
GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
|
||||
|
||||
layout_manager_class->measure = gtk_column_view_layout_measure;
|
||||
layout_manager_class->allocate = gtk_column_view_layout_allocate;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_layout_init (GtkColumnViewLayout *self)
|
||||
{
|
||||
}
|
||||
|
||||
GtkLayoutManager *
|
||||
gtk_column_view_layout_new (GtkColumnView *view)
|
||||
{
|
||||
GtkColumnViewLayout *result;
|
||||
|
||||
result = g_object_new (GTK_TYPE_COLUMN_VIEW_LAYOUT, NULL);
|
||||
|
||||
result->view = view;
|
||||
|
||||
return GTK_LAYOUT_MANAGER (result);
|
||||
}
|
35
gtk/gtkcolumnviewlayoutprivate.h
Normal file
35
gtk/gtkcolumnviewlayoutprivate.h
Normal 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_LAYOUT_PRIVATE_H__
|
||||
#define __GTK_COLUMN_VIEW_LAYOUT_PRIVATE_H__
|
||||
|
||||
#include <gtk/gtkcolumnview.h>
|
||||
#include <gtk/gtklayoutmanager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_COLUMN_VIEW_LAYOUT (gtk_column_view_layout_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkColumnViewLayout, gtk_column_view_layout, GTK, COLUMN_VIEW_LAYOUT, GtkLayoutManager)
|
||||
|
||||
GtkLayoutManager * gtk_column_view_layout_new (GtkColumnView *view);
|
||||
|
||||
|
||||
#endif /* __GTK_COLUMN_VIEW_LAYOUT_PRIVATE_H__ */
|
36
gtk/gtkcolumnviewprivate.h
Normal file
36
gtk/gtkcolumnviewprivate.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "gtk/gtklistview.h"
|
||||
|
||||
#include "gtk/gtkcolumnviewsorterprivate.h"
|
||||
#include "gtk/gtklistitemwidgetprivate.h"
|
||||
|
||||
GtkListItemWidget * gtk_column_view_get_header_widget (GtkColumnView *self);
|
||||
GtkListView * gtk_column_view_get_list_view (GtkColumnView *self);
|
||||
|
||||
void gtk_column_view_measure_across (GtkColumnView *self,
|
||||
int *minimum,
|
||||
int *natural);
|
||||
|
||||
#endif /* __GTK_COLUMN_VIEW_PRIVATE_H__ */
|
323
gtk/gtkcolumnviewsorter.c
Normal file
323
gtk/gtkcolumnviewsorter.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright © 2019 Matthias Clasen
|
||||
*
|
||||
* 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: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcolumnviewsorterprivate.h"
|
||||
|
||||
#include "gtkcolumnviewcolumnprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkColumnViewColumn *column;
|
||||
GtkSorter *sorter;
|
||||
gboolean inverted;
|
||||
gulong changed_id;
|
||||
} Sorter;
|
||||
|
||||
static void
|
||||
free_sorter (gpointer data)
|
||||
{
|
||||
Sorter *s = data;
|
||||
|
||||
g_signal_handler_disconnect (s->sorter, s->changed_id);
|
||||
g_object_unref (s->sorter);
|
||||
g_object_unref (s->column);
|
||||
g_free (s);
|
||||
}
|
||||
|
||||
struct _GtkColumnViewSorter
|
||||
{
|
||||
GtkSorter parent_instance;
|
||||
|
||||
GSequence *sorters;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkColumnViewSorter, gtk_column_view_sorter, GTK_TYPE_SORTER)
|
||||
|
||||
static GtkOrdering
|
||||
gtk_column_view_sorter_compare (GtkSorter *sorter,
|
||||
gpointer item1,
|
||||
gpointer item2)
|
||||
{
|
||||
GtkColumnViewSorter *self = GTK_COLUMN_VIEW_SORTER (sorter);
|
||||
GtkOrdering result = GTK_ORDERING_EQUAL;
|
||||
GSequenceIter *iter;
|
||||
|
||||
for (iter = g_sequence_get_begin_iter (self->sorters);
|
||||
!g_sequence_iter_is_end (iter);
|
||||
iter = g_sequence_iter_next (iter))
|
||||
{
|
||||
Sorter *s = g_sequence_get (iter);
|
||||
|
||||
result = gtk_sorter_compare (s->sorter, item1, item2);
|
||||
if (s->inverted)
|
||||
result = - result;
|
||||
|
||||
if (result != GTK_ORDERING_EQUAL)
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GtkSorterOrder
|
||||
gtk_column_view_sorter_get_order (GtkSorter *sorter)
|
||||
{
|
||||
GtkColumnViewSorter *self = GTK_COLUMN_VIEW_SORTER (sorter);
|
||||
GtkSorterOrder result = GTK_SORTER_ORDER_NONE;
|
||||
GSequenceIter *iter;
|
||||
|
||||
for (iter = g_sequence_get_begin_iter (self->sorters);
|
||||
!g_sequence_iter_is_end (iter);
|
||||
iter = g_sequence_iter_next (iter))
|
||||
{
|
||||
Sorter *s = g_sequence_get (iter);
|
||||
|
||||
switch (gtk_sorter_get_order (s->sorter))
|
||||
{
|
||||
case GTK_SORTER_ORDER_PARTIAL:
|
||||
result = GTK_SORTER_ORDER_PARTIAL;
|
||||
break;
|
||||
case GTK_SORTER_ORDER_NONE:
|
||||
break;
|
||||
case GTK_SORTER_ORDER_TOTAL:
|
||||
return GTK_SORTER_ORDER_TOTAL;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_sorter_dispose (GObject *object)
|
||||
{
|
||||
GtkColumnViewSorter *self = GTK_COLUMN_VIEW_SORTER (object);
|
||||
|
||||
g_clear_pointer (&self->sorters, g_sequence_free);
|
||||
|
||||
G_OBJECT_CLASS (gtk_column_view_sorter_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_sorter_class_init (GtkColumnViewSorterClass *class)
|
||||
{
|
||||
GtkSorterClass *sorter_class = GTK_SORTER_CLASS (class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
sorter_class->compare = gtk_column_view_sorter_compare;
|
||||
sorter_class->get_order = gtk_column_view_sorter_get_order;
|
||||
|
||||
object_class->dispose = gtk_column_view_sorter_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_sorter_init (GtkColumnViewSorter *self)
|
||||
{
|
||||
self->sorters = g_sequence_new (free_sorter);
|
||||
}
|
||||
|
||||
GtkSorter *
|
||||
gtk_column_view_sorter_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_COLUMN_VIEW_SORTER, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_sorter_changed_cb (GtkSorter *sorter, int change, gpointer data)
|
||||
{
|
||||
gtk_sorter_changed (GTK_SORTER (data), GTK_SORTER_CHANGE_DIFFERENT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
remove_column (GtkColumnViewSorter *self,
|
||||
GtkColumnViewColumn *column)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
|
||||
for (iter = g_sequence_get_begin_iter (self->sorters);
|
||||
!g_sequence_iter_is_end (iter);
|
||||
iter = g_sequence_iter_next (iter))
|
||||
{
|
||||
Sorter *s = g_sequence_get (iter);
|
||||
|
||||
if (s->column == column)
|
||||
{
|
||||
g_sequence_remove (iter);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_column_view_sorter_add_column (GtkColumnViewSorter *self,
|
||||
GtkColumnViewColumn *column)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
GtkSorter *sorter;
|
||||
Sorter *s, *first;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (column), FALSE);
|
||||
|
||||
sorter = gtk_column_view_column_get_sorter (column);
|
||||
if (sorter == NULL)
|
||||
return FALSE;
|
||||
|
||||
iter = g_sequence_get_begin_iter (self->sorters);
|
||||
if (!g_sequence_iter_is_end (iter))
|
||||
{
|
||||
first = g_sequence_get (iter);
|
||||
if (first->column == column)
|
||||
{
|
||||
first->inverted = !first->inverted;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
first = NULL;
|
||||
|
||||
remove_column (self, column);
|
||||
|
||||
s = g_new (Sorter, 1);
|
||||
s->column = g_object_ref (column);
|
||||
s->sorter = g_object_ref (sorter);
|
||||
s->changed_id = g_signal_connect (sorter, "changed", G_CALLBACK (gtk_column_view_sorter_changed_cb), self);
|
||||
s->inverted = FALSE;
|
||||
|
||||
g_sequence_insert_before (iter, s);
|
||||
|
||||
/* notify the previous first column to stop drawing an arrow */
|
||||
if (first)
|
||||
gtk_column_view_column_notify_sort (first->column);
|
||||
|
||||
out:
|
||||
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
|
||||
|
||||
gtk_column_view_column_notify_sort (column);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_column_view_sorter_remove_column (GtkColumnViewSorter *self,
|
||||
GtkColumnViewColumn *column)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (column), FALSE);
|
||||
|
||||
if (remove_column (self, column))
|
||||
{
|
||||
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
|
||||
gtk_column_view_column_notify_sort (column);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_column_view_sorter_set_column (GtkColumnViewSorter *self,
|
||||
GtkColumnViewColumn *column,
|
||||
gboolean inverted)
|
||||
{
|
||||
GtkSorter *sorter;
|
||||
Sorter *s;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (column), FALSE);
|
||||
|
||||
sorter = gtk_column_view_column_get_sorter (column);
|
||||
if (sorter == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_object_ref (column);
|
||||
|
||||
g_sequence_remove_range (g_sequence_get_begin_iter (self->sorters),
|
||||
g_sequence_get_end_iter (self->sorters));
|
||||
|
||||
s = g_new (Sorter, 1);
|
||||
s->column = g_object_ref (column);
|
||||
s->sorter = g_object_ref (sorter);
|
||||
s->changed_id = g_signal_connect (sorter, "changed", G_CALLBACK (gtk_column_view_sorter_changed_cb), self);
|
||||
s->inverted = inverted;
|
||||
|
||||
g_sequence_prepend (self->sorters, s);
|
||||
|
||||
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
|
||||
|
||||
gtk_column_view_column_notify_sort (column);
|
||||
|
||||
g_object_unref (column);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_column_view_sorter_clear (GtkColumnViewSorter *self)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
Sorter *s;
|
||||
GtkColumnViewColumn *column;
|
||||
|
||||
g_return_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self));
|
||||
|
||||
if (g_sequence_is_empty (self->sorters))
|
||||
return;
|
||||
|
||||
iter = g_sequence_get_begin_iter (self->sorters);
|
||||
s = g_sequence_get (iter);
|
||||
|
||||
column = g_object_ref (s->column);
|
||||
|
||||
g_sequence_remove_range (iter, g_sequence_get_end_iter (self->sorters));
|
||||
|
||||
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
|
||||
|
||||
gtk_column_view_column_notify_sort (column);
|
||||
|
||||
g_object_unref (column);
|
||||
}
|
||||
|
||||
GtkColumnViewColumn *
|
||||
gtk_column_view_sorter_get_sort_column (GtkColumnViewSorter *self,
|
||||
gboolean *inverted)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
Sorter *s;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_COLUMN_VIEW_SORTER (self), NULL);
|
||||
|
||||
if (g_sequence_is_empty (self->sorters))
|
||||
return NULL;
|
||||
|
||||
iter = g_sequence_get_begin_iter (self->sorters);
|
||||
s = g_sequence_get (iter);
|
||||
|
||||
*inverted = s->inverted;
|
||||
|
||||
return s->column;
|
||||
}
|
57
gtk/gtkcolumnviewsorterprivate.h
Normal file
57
gtk/gtkcolumnviewsorterprivate.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright © 2019 Matthias Clasen
|
||||
*
|
||||
* 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: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_COLUMN_VIEW_SORTER_H__
|
||||
#define __GTK_COLUMN_VIEW_SORTER_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtksorter.h>
|
||||
#include <gtk/gtkcolumnviewcolumn.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_COLUMN_VIEW_SORTER (gtk_column_view_sorter_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkColumnViewSorter, gtk_column_view_sorter, GTK, COLUMN_VIEW_SORTER, GtkSorter)
|
||||
|
||||
GtkSorter * gtk_column_view_sorter_new (void);
|
||||
|
||||
gboolean gtk_column_view_sorter_add_column (GtkColumnViewSorter *self,
|
||||
GtkColumnViewColumn *column);
|
||||
gboolean gtk_column_view_sorter_remove_column (GtkColumnViewSorter *self,
|
||||
GtkColumnViewColumn *column);
|
||||
|
||||
void gtk_column_view_sorter_clear (GtkColumnViewSorter *self);
|
||||
|
||||
GtkColumnViewColumn * gtk_column_view_sorter_get_sort_column (GtkColumnViewSorter *self,
|
||||
gboolean *inverted);
|
||||
|
||||
gboolean gtk_column_view_sorter_set_column (GtkColumnViewSorter *self,
|
||||
GtkColumnViewColumn *column,
|
||||
gboolean inverted);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SORTER_H__ */
|
||||
|
273
gtk/gtkcolumnviewtitle.c
Normal file
273
gtk/gtkcolumnviewtitle.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* 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 "gtkcolumnviewprivate.h"
|
||||
#include "gtkcolumnviewcolumnprivate.h"
|
||||
#include "gtkcolumnviewsorterprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkbox.h"
|
||||
#include "gtkimage.h"
|
||||
#include "gtkgestureclick.h"
|
||||
#include "gtkpopovermenu.h"
|
||||
#include "gtknative.h"
|
||||
|
||||
struct _GtkColumnViewTitle
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkColumnViewColumn *column;
|
||||
|
||||
GtkWidget *box;
|
||||
GtkWidget *title;
|
||||
GtkWidget *sort;
|
||||
GtkWidget *popup_menu;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
|
||||
GtkWidget *child = gtk_widget_get_first_child (widget);
|
||||
|
||||
if (child)
|
||||
gtk_widget_measure (child, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
int fixed_width = gtk_column_view_column_get_fixed_width (self->column);
|
||||
if (fixed_width > -1)
|
||||
*minimum = *natural = fixed_width;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_title_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
|
||||
GtkWidget *child = gtk_widget_get_first_child (widget);
|
||||
|
||||
if (child)
|
||||
gtk_widget_allocate (child, width, height, baseline, NULL);
|
||||
|
||||
if (self->popup_menu)
|
||||
gtk_native_check_resize (GTK_NATIVE (self->popup_menu));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_title_dispose (GObject *object)
|
||||
{
|
||||
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (object);
|
||||
|
||||
g_clear_pointer (&self->box, gtk_widget_unparent);
|
||||
g_clear_pointer (&self->popup_menu, 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
|
||||
activate_sort (GtkColumnViewTitle *self)
|
||||
{
|
||||
GtkSorter *sorter;
|
||||
GtkColumnView *view;
|
||||
GtkColumnViewSorter *view_sorter;
|
||||
|
||||
sorter = gtk_column_view_column_get_sorter (self->column);
|
||||
if (sorter == NULL)
|
||||
return;
|
||||
|
||||
view = gtk_column_view_column_get_column_view (self->column);
|
||||
view_sorter = GTK_COLUMN_VIEW_SORTER (gtk_column_view_get_sorter (view));
|
||||
gtk_column_view_sorter_add_column (view_sorter, self->column);
|
||||
}
|
||||
|
||||
static void
|
||||
show_menu (GtkColumnViewTitle *self,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
g_print ("show menu\n");
|
||||
if (!self->popup_menu)
|
||||
{
|
||||
GMenuModel *model;
|
||||
|
||||
model = gtk_column_view_column_get_header_menu (self->column);
|
||||
if (!model)
|
||||
return;
|
||||
|
||||
g_print ("got a model\n");
|
||||
self->popup_menu = gtk_popover_menu_new_from_model (GTK_WIDGET (self), model);
|
||||
gtk_popover_set_position (GTK_POPOVER (self->popup_menu), GTK_POS_BOTTOM);
|
||||
|
||||
gtk_popover_set_has_arrow (GTK_POPOVER (self->popup_menu), FALSE);
|
||||
gtk_widget_set_halign (self->popup_menu, GTK_ALIGN_START);
|
||||
}
|
||||
|
||||
if (x != -1 && y != -1)
|
||||
{
|
||||
GdkRectangle rect = { x, y, 1, 1 };
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (self->popup_menu), &rect);
|
||||
}
|
||||
else
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (self->popup_menu), NULL);
|
||||
|
||||
gtk_popover_popup (GTK_POPOVER (self->popup_menu));
|
||||
}
|
||||
|
||||
static void
|
||||
click_released_cb (GtkGestureClick *gesture,
|
||||
guint n_press,
|
||||
double x,
|
||||
double y,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget);
|
||||
guint button;
|
||||
|
||||
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
|
||||
|
||||
if (button == GDK_BUTTON_PRIMARY)
|
||||
activate_sort (self);
|
||||
else if (button == GDK_BUTTON_SECONDARY)
|
||||
show_menu (self, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_column_view_title_init (GtkColumnViewTitle *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
GtkGesture *gesture;
|
||||
|
||||
widget->priv->resize_func = gtk_column_view_title_resize_func;
|
||||
|
||||
self->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_parent (self->box, widget);
|
||||
|
||||
self->title = gtk_label_new (NULL);
|
||||
gtk_container_add (GTK_CONTAINER (self->box), self->title);
|
||||
|
||||
self->sort = gtk_image_new ();
|
||||
gtk_container_add (GTK_CONTAINER (self->box), self->sort);
|
||||
|
||||
gesture = gtk_gesture_click_new ();
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
|
||||
g_signal_connect (gesture, "released", G_CALLBACK (click_released_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
GtkSorter *sorter;
|
||||
GtkColumnView *view;
|
||||
GtkColumnViewSorter *view_sorter;
|
||||
gboolean inverted;
|
||||
GtkColumnViewColumn *active;
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (self->title), gtk_column_view_column_get_title (self->column));
|
||||
|
||||
sorter = gtk_column_view_column_get_sorter (self->column);
|
||||
|
||||
if (sorter)
|
||||
{
|
||||
view = gtk_column_view_column_get_column_view (self->column);
|
||||
view_sorter = GTK_COLUMN_VIEW_SORTER (gtk_column_view_get_sorter (view));
|
||||
active = gtk_column_view_sorter_get_sort_column (view_sorter, &inverted);
|
||||
|
||||
gtk_widget_show (self->sort);
|
||||
if (self->column == active)
|
||||
{
|
||||
if (inverted)
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->sort), "pan-down-symbolic");
|
||||
else
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (self->sort), "pan-up-symbolic");
|
||||
}
|
||||
else
|
||||
gtk_image_clear (GTK_IMAGE (self->sort));
|
||||
}
|
||||
else
|
||||
gtk_widget_hide (self->sort);
|
||||
|
||||
g_clear_pointer (&self->popup_menu, gtk_widget_unparent);
|
||||
}
|
||||
|
||||
GtkColumnViewColumn *
|
||||
gtk_column_view_title_get_column (GtkColumnViewTitle *self)
|
||||
{
|
||||
return self->column;
|
||||
}
|
47
gtk/gtkcolumnviewtitleprivate.h
Normal file
47
gtk/gtkcolumnviewtitleprivate.h
Normal 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__ */
|
704
gtk/gtkcoverflow.c
Normal file
704
gtk/gtkcoverflow.c
Normal file
@@ -0,0 +1,704 @@
|
||||
/*
|
||||
* Copyright © 2018 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 "gtkcoverflow.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtklistbaseprivate.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtkorientable.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkrbtreeprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
/* Extra items to display at most above + below the central item */
|
||||
#define GTK_COVER_FLOW_DISPLAY_ITEMS 5
|
||||
|
||||
/* Number of extra space we leave around the covers */
|
||||
#define GTK_COVER_FLOW_SCALE_ALONG 3
|
||||
#define GTK_COVER_FLOW_SCALE_ACROSS 2
|
||||
|
||||
/**
|
||||
* SECTION:gtkcoverflow
|
||||
* @title: GtkCoverFlow
|
||||
* @short_description: A coverflow list widget
|
||||
* @see_also: #GListModel
|
||||
*
|
||||
* GtkCoverFlow is a widget to present a coverflow list
|
||||
*/
|
||||
|
||||
struct _GtkCoverFlow
|
||||
{
|
||||
GtkListBase parent_instance;
|
||||
|
||||
int size_across;
|
||||
int size_along;
|
||||
};
|
||||
|
||||
struct _GtkCoverFlowClass
|
||||
{
|
||||
GtkListBaseClass parent_class;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_FACTORY,
|
||||
PROP_MODEL,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTIVATE,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkCoverFlow, gtk_cover_flow, GTK_TYPE_LIST_BASE)
|
||||
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static gboolean
|
||||
gtk_cover_flow_get_allocation_along (GtkListBase *base,
|
||||
guint pos,
|
||||
int *offset,
|
||||
int *size)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (base);
|
||||
|
||||
if (offset)
|
||||
*offset = pos * self->size_along;
|
||||
if (size)
|
||||
*size = self->size_along;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_cover_flow_get_allocation_across (GtkListBase *base,
|
||||
guint pos,
|
||||
int *offset,
|
||||
int *size)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (base);
|
||||
|
||||
if (offset)
|
||||
*offset = pos * self->size_across;
|
||||
if (size)
|
||||
*size = self->size_across;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_cover_flow_move_focus_along (GtkListBase *base,
|
||||
guint pos,
|
||||
int steps)
|
||||
{
|
||||
if (steps < 0)
|
||||
return pos - MIN (pos, -steps);
|
||||
else
|
||||
{
|
||||
pos += MIN (gtk_list_base_get_n_items (base) - pos - 1, steps);
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_cover_flow_move_focus_across (GtkListBase *base,
|
||||
guint pos,
|
||||
int steps)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_cover_flow_get_position_from_allocation (GtkListBase *base,
|
||||
int across,
|
||||
int along,
|
||||
guint *pos,
|
||||
cairo_rectangle_int_t *area)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (base);
|
||||
|
||||
if (across >= self->size_across ||
|
||||
along >= self->size_along * gtk_list_base_get_n_items (base))
|
||||
return FALSE;
|
||||
|
||||
*pos = along / self->size_along;
|
||||
|
||||
if (area)
|
||||
{
|
||||
area->x = 0;
|
||||
area->width = self->size_across;
|
||||
area->y = *pos * self->size_along;
|
||||
area->height = self->size_along;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_measure_children (GtkCoverFlow *self,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural)
|
||||
{
|
||||
GtkListItemManagerItem *item;
|
||||
int min, nat, child_min, child_nat;
|
||||
|
||||
min = 0;
|
||||
nat = 0;
|
||||
|
||||
for (item = gtk_list_item_manager_get_first (gtk_list_base_get_manager (GTK_LIST_BASE (self)));
|
||||
item != NULL;
|
||||
item = gtk_rb_tree_node_get_next (item))
|
||||
{
|
||||
/* ignore unavailable items */
|
||||
if (item->widget == NULL)
|
||||
continue;
|
||||
|
||||
gtk_widget_measure (item->widget,
|
||||
orientation, for_size,
|
||||
&child_min, &child_nat, NULL, NULL);
|
||||
min = MAX (min, child_min);
|
||||
nat = MAX (nat, child_nat);
|
||||
}
|
||||
|
||||
*minimum = min;
|
||||
*natural = nat;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_measure_across (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (widget);
|
||||
|
||||
if (for_size > 0)
|
||||
for_size /= GTK_COVER_FLOW_SCALE_ALONG;
|
||||
|
||||
gtk_cover_flow_measure_children (self, orientation, for_size, minimum, natural);
|
||||
|
||||
*minimum *= GTK_COVER_FLOW_SCALE_ACROSS;
|
||||
*natural *= GTK_COVER_FLOW_SCALE_ACROSS;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_measure_along (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (widget);
|
||||
|
||||
if (for_size > 0)
|
||||
for_size /= GTK_COVER_FLOW_SCALE_ACROSS;
|
||||
|
||||
gtk_cover_flow_measure_children (self, orientation, for_size, minimum, natural);
|
||||
|
||||
*minimum *= GTK_COVER_FLOW_SCALE_ALONG;
|
||||
*natural *= GTK_COVER_FLOW_SCALE_ALONG;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (widget);
|
||||
|
||||
if (orientation == gtk_list_base_get_orientation (GTK_LIST_BASE (self)))
|
||||
gtk_cover_flow_measure_along (widget, orientation, for_size, minimum, natural);
|
||||
else
|
||||
gtk_cover_flow_measure_across (widget, orientation, for_size, minimum, natural);
|
||||
}
|
||||
|
||||
static GskTransform *
|
||||
transform_translate_oriented (GskTransform *transform,
|
||||
GtkOrientation orientation,
|
||||
GtkTextDirection dir,
|
||||
float across,
|
||||
float along)
|
||||
{
|
||||
if (orientation == GTK_ORIENTATION_VERTICAL)
|
||||
return gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (across, along));
|
||||
else if (dir == GTK_TEXT_DIR_LTR)
|
||||
return gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (along, across));
|
||||
else
|
||||
return gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (-along, across));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_size_allocate_child (GtkWidget *child,
|
||||
GtkOrientation orientation,
|
||||
GtkTextDirection dir,
|
||||
GskTransform *transform,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (orientation == GTK_ORIENTATION_VERTICAL)
|
||||
{
|
||||
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (-width / 2, -height / 2));
|
||||
gtk_widget_allocate (child, width, height, -1, transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (-height / 2, -width / 2));
|
||||
gtk_widget_allocate (child, height, width, -1, transform);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (widget);
|
||||
GtkOrientation orientation, opposite_orientation;
|
||||
GtkTextDirection dir;
|
||||
GtkListItemManagerItem *item;
|
||||
GtkListItemManager *manager;
|
||||
guint i, pos;
|
||||
int x, y, along, across;
|
||||
|
||||
manager = gtk_list_base_get_manager (GTK_LIST_BASE (self));
|
||||
orientation = gtk_list_base_get_orientation (GTK_LIST_BASE (self));
|
||||
opposite_orientation = OPPOSITE_ORIENTATION (orientation);
|
||||
|
||||
/* step 0: exit early if list is empty */
|
||||
if (gtk_list_item_manager_get_root (manager) == NULL)
|
||||
return;
|
||||
|
||||
/* step 1: determine size of children */
|
||||
along = orientation == GTK_ORIENTATION_HORIZONTAL ? width : height;
|
||||
across = opposite_orientation == GTK_ORIENTATION_HORIZONTAL ? width : height;
|
||||
self->size_along = along / GTK_COVER_FLOW_SCALE_ALONG;
|
||||
self->size_across = across / GTK_COVER_FLOW_SCALE_ACROSS;
|
||||
|
||||
/* step 2: update the adjustments */
|
||||
gtk_list_base_update_adjustments (GTK_LIST_BASE (self),
|
||||
self->size_across,
|
||||
self->size_along * gtk_list_base_get_n_items (GTK_LIST_BASE (self)),
|
||||
self->size_across,
|
||||
self->size_along,
|
||||
&x, &y);
|
||||
pos = gtk_list_base_get_anchor (GTK_LIST_BASE (self));
|
||||
|
||||
/* step 4: actually allocate the widgets */
|
||||
dir = _gtk_widget_get_direction (widget);
|
||||
i = 0;
|
||||
|
||||
for (item = gtk_list_item_manager_get_first (manager);
|
||||
item != NULL;
|
||||
item = gtk_rb_tree_node_get_next (item))
|
||||
{
|
||||
if (item->widget)
|
||||
{
|
||||
/* start at the center */
|
||||
GskTransform *transform = transform_translate_oriented (NULL, orientation, dir, across / 2, along / 2);
|
||||
|
||||
if (i == pos)
|
||||
{
|
||||
/* nothing to do, we're already centered */
|
||||
}
|
||||
else if (MAX (pos, i) - MIN (pos, i) < GTK_COVER_FLOW_DISPLAY_ITEMS) /* ABS() doesn't work with guint */
|
||||
{
|
||||
int diff = i - pos;
|
||||
transform = gsk_transform_perspective (transform, MAX (width, height) * 2);
|
||||
transform = transform_translate_oriented (transform,
|
||||
orientation, dir,
|
||||
0,
|
||||
diff * self->size_along / 4);
|
||||
transform = transform_translate_oriented (transform,
|
||||
orientation, dir,
|
||||
0,
|
||||
(diff < 0 ? -1 : 1) * self->size_along / 2);
|
||||
if (orientation == GTK_ORIENTATION_VERTICAL)
|
||||
transform = gsk_transform_rotate_3d (transform,
|
||||
diff > 0 ? 60 : -60,
|
||||
graphene_vec3_x_axis ());
|
||||
else
|
||||
transform = gsk_transform_rotate_3d (transform,
|
||||
diff < 0 ? 60 : -60,
|
||||
graphene_vec3_y_axis ());
|
||||
transform = transform_translate_oriented (transform,
|
||||
orientation, dir,
|
||||
0,
|
||||
(diff < 0 ? 1 : -1) * self->size_along / 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = transform_translate_oriented (transform,
|
||||
orientation, dir,
|
||||
- 2 * self->size_across,
|
||||
- 2 * self->size_along);
|
||||
}
|
||||
gtk_cover_flow_size_allocate_child (item->widget,
|
||||
orientation, dir,
|
||||
transform,
|
||||
self->size_across,
|
||||
self->size_along);
|
||||
}
|
||||
|
||||
i += item->n_items;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkListBase *base = GTK_LIST_BASE (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FACTORY:
|
||||
g_value_set_object (value, gtk_list_item_manager_get_factory (gtk_list_base_get_manager (base)));
|
||||
break;
|
||||
|
||||
case PROP_MODEL:
|
||||
g_value_set_object (value, gtk_list_base_get_model (base));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkWidget *child;
|
||||
GtkListItemManagerItem *item;
|
||||
|
||||
item = gtk_list_item_manager_get_nth (gtk_list_base_get_manager (GTK_LIST_BASE (widget)),
|
||||
gtk_list_base_get_anchor (GTK_LIST_BASE (widget)),
|
||||
NULL);
|
||||
if (item == NULL || item->widget == NULL)
|
||||
{
|
||||
GTK_WIDGET_CLASS (gtk_cover_flow_parent_class)->snapshot (widget, snapshot);
|
||||
return;
|
||||
}
|
||||
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
child != item->widget;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
gtk_widget_snapshot_child (widget, child, snapshot);
|
||||
|
||||
for (child = _gtk_widget_get_last_child (widget);
|
||||
child != item->widget;
|
||||
child = _gtk_widget_get_prev_sibling (child))
|
||||
gtk_widget_snapshot_child (widget, child, snapshot);
|
||||
|
||||
gtk_widget_snapshot_child (widget, item->widget, snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_FACTORY:
|
||||
gtk_cover_flow_set_factory (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_MODEL:
|
||||
gtk_cover_flow_set_model (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_activate_item (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
GtkCoverFlow *self = GTK_COVER_FLOW (widget);
|
||||
guint pos;
|
||||
|
||||
if (!g_variant_check_format_string (parameter, "u", FALSE))
|
||||
return;
|
||||
|
||||
g_variant_get (parameter, "u", &pos);
|
||||
if (pos >= gtk_list_base_get_n_items (GTK_LIST_BASE (self)))
|
||||
return;
|
||||
|
||||
g_signal_emit (widget, signals[ACTIVATE], 0, pos);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_class_init (GtkCoverFlowClass *klass)
|
||||
{
|
||||
GtkListBaseClass *list_base_class = GTK_LIST_BASE_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
list_base_class->list_item_name = "cover";
|
||||
list_base_class->list_item_size = sizeof (GtkListItemManagerItem);
|
||||
list_base_class->list_item_augment_size = sizeof (GtkListItemManagerItemAugment);
|
||||
list_base_class->list_item_augment_func = gtk_list_item_manager_augment_node;
|
||||
list_base_class->get_allocation_along = gtk_cover_flow_get_allocation_along;
|
||||
list_base_class->get_allocation_across = gtk_cover_flow_get_allocation_across;
|
||||
list_base_class->get_position_from_allocation = gtk_cover_flow_get_position_from_allocation;
|
||||
list_base_class->move_focus_along = gtk_cover_flow_move_focus_along;
|
||||
list_base_class->move_focus_across = gtk_cover_flow_move_focus_across;
|
||||
|
||||
widget_class->measure = gtk_cover_flow_measure;
|
||||
widget_class->size_allocate = gtk_cover_flow_size_allocate;
|
||||
widget_class->snapshot = gtk_cover_flow_snapshot;
|
||||
|
||||
gobject_class->get_property = gtk_cover_flow_get_property;
|
||||
gobject_class->set_property = gtk_cover_flow_set_property;
|
||||
|
||||
/**
|
||||
* GtkCoverFlow:factory:
|
||||
*
|
||||
* Factory for populating list items
|
||||
*/
|
||||
properties[PROP_FACTORY] =
|
||||
g_param_spec_object ("factory",
|
||||
P_("Factory"),
|
||||
P_("Factory for populating list items"),
|
||||
GTK_TYPE_LIST_ITEM_FACTORY,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GtkCoverFlow:model:
|
||||
*
|
||||
* Model for the items displayed
|
||||
*/
|
||||
properties[PROP_MODEL] =
|
||||
g_param_spec_object ("model",
|
||||
P_("Model"),
|
||||
P_("Model for the items displayed"),
|
||||
G_TYPE_LIST_MODEL,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
|
||||
/**
|
||||
* GtkCoverFlow::activate:
|
||||
* @self: The #GtkCoverFlow
|
||||
* @position: position of item to activate
|
||||
*
|
||||
* The ::activate signal is emitted when an item has been activated by the user,
|
||||
* usually via activating the GtkCoverFlow|list.activate-item action.
|
||||
*
|
||||
* This allows for a convenient way to handle activation in a listview.
|
||||
* See gtk_list_item_set_activatable() for details on how to use this signal.
|
||||
*/
|
||||
signals[ACTIVATE] =
|
||||
g_signal_new (I_("activate"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__UINT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_UINT);
|
||||
g_signal_set_va_marshaller (signals[ACTIVATE],
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
g_cclosure_marshal_VOID__UINTv);
|
||||
|
||||
/**
|
||||
* GtkCoverFlow|list.activate-item:
|
||||
* @position: position of item to activate
|
||||
*
|
||||
* Activates the item given in @position by emitting the GtkCoverFlow::activate
|
||||
* signal.
|
||||
*/
|
||||
gtk_widget_class_install_action (widget_class,
|
||||
"list.activate-item",
|
||||
"u",
|
||||
gtk_cover_flow_activate_item);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, I_("coverflow"));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cover_flow_init (GtkCoverFlow *self)
|
||||
{
|
||||
gtk_list_base_set_anchor_max_widgets (GTK_LIST_BASE (self),
|
||||
0,
|
||||
GTK_COVER_FLOW_DISPLAY_ITEMS);
|
||||
|
||||
/* FIXME: this should overwrite the property default, but gobject properties... */
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cover_flow_new:
|
||||
*
|
||||
* Creates a new empty #GtkCoverFlow.
|
||||
*
|
||||
* You most likely want to call gtk_cover_flow_set_factory() to
|
||||
* set up a way to map its items to widgets and gtk_cover_flow_set_model()
|
||||
* to set a model to provide items next.
|
||||
*
|
||||
* Returns: a new #GtkCoverFlow
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_cover_flow_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_COVER_FLOW, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cover_flow_new_with_factory:
|
||||
* @factory: (transfer full): The factory to populate items with
|
||||
*
|
||||
* Creates a new #GtkCoverFlow that uses the given @factory for
|
||||
* mapping items to widgets.
|
||||
*
|
||||
* You most likely want to call gtk_cover_flow_set_model() to set
|
||||
* a model next.
|
||||
*
|
||||
* The function takes ownership of the
|
||||
* argument, so you can write code like
|
||||
* ```
|
||||
* cover_flow = gtk_cover_flow_new_with_factory (
|
||||
* gtk_builder_list_item_factory_newfrom_resource ("/resource.ui"));
|
||||
* ```
|
||||
*
|
||||
* Returns: a new #GtkCoverFlow using the given @factory
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_cover_flow_new_with_factory (GtkListItemFactory *factory)
|
||||
{
|
||||
GtkWidget *result;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_LIST_ITEM_FACTORY (factory), NULL);
|
||||
|
||||
result = g_object_new (GTK_TYPE_COVER_FLOW,
|
||||
"factory", factory,
|
||||
NULL);
|
||||
|
||||
g_object_unref (factory);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cover_flow_get_model:
|
||||
* @self: a #GtkCoverFlow
|
||||
*
|
||||
* Gets the model that's currently used to read the items displayed.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): The model in use
|
||||
**/
|
||||
GListModel *
|
||||
gtk_cover_flow_get_model (GtkCoverFlow *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_COVER_FLOW (self), NULL);
|
||||
|
||||
return gtk_list_base_get_model (GTK_LIST_BASE (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cover_flow_set_model:
|
||||
* @self: a #GtkCoverFlow
|
||||
* @model: (allow-none) (transfer none): the model to use or %NULL for none
|
||||
*
|
||||
* Sets the #GListModel to use.
|
||||
*
|
||||
* If the @model is a #GtkSelectionModel, it is used for managing the selection.
|
||||
* Otherwise, @self creates a #GtkSingleSelection for the selection.
|
||||
**/
|
||||
void
|
||||
gtk_cover_flow_set_model (GtkCoverFlow *self,
|
||||
GListModel *model)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_COVER_FLOW (self));
|
||||
g_return_if_fail (model == NULL || G_IS_LIST_MODEL (model));
|
||||
|
||||
if (!gtk_list_base_set_model (GTK_LIST_BASE (self), model))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cover_flow_get_factory:
|
||||
* @self: a #GtkCoverFlow
|
||||
*
|
||||
* Gets the factory that's currently used to populate list items.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): The factory in use
|
||||
**/
|
||||
GtkListItemFactory *
|
||||
gtk_cover_flow_get_factory (GtkCoverFlow *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_COVER_FLOW (self), NULL);
|
||||
|
||||
return gtk_list_item_manager_get_factory (gtk_list_base_get_manager (GTK_LIST_BASE (self)));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cover_flow_set_factory:
|
||||
* @self: a #GtkCoverFlow
|
||||
* @factory: (allow-none) (transfer none): the factory to use or %NULL for none
|
||||
*
|
||||
* Sets the #GtkListItemFactory to use for populating list items.
|
||||
**/
|
||||
void
|
||||
gtk_cover_flow_set_factory (GtkCoverFlow *self,
|
||||
GtkListItemFactory *factory)
|
||||
{
|
||||
GtkListItemManager *manager;
|
||||
|
||||
g_return_if_fail (GTK_IS_COVER_FLOW (self));
|
||||
g_return_if_fail (factory == NULL || GTK_LIST_ITEM_FACTORY (factory));
|
||||
|
||||
manager = gtk_list_base_get_manager (GTK_LIST_BASE (self));
|
||||
|
||||
if (factory == gtk_list_item_manager_get_factory (manager))
|
||||
return;
|
||||
|
||||
gtk_list_item_manager_set_factory (manager, factory);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FACTORY]);
|
||||
}
|
68
gtk/gtkcoverflow.h
Normal file
68
gtk/gtkcoverflow.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright © 2018 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_COVER_FLOW_H__
|
||||
#define __GTK_COVER_FLOW_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtklistbase.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_COVER_FLOW (gtk_cover_flow_get_type ())
|
||||
#define GTK_COVER_FLOW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_COVER_FLOW, GtkCoverFlow))
|
||||
#define GTK_COVER_FLOW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_COVER_FLOW, GtkCoverFlowClass))
|
||||
#define GTK_IS_COVER_FLOW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_COVER_FLOW))
|
||||
#define GTK_IS_COVER_FLOW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_COVER_FLOW))
|
||||
#define GTK_COVER_FLOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_COVER_FLOW, GtkCoverFlowClass))
|
||||
|
||||
/**
|
||||
* GtkCoverFlow:
|
||||
*
|
||||
* GtkCoverFlow is the simple list implementation for GTK's list widgets.
|
||||
*/
|
||||
typedef struct _GtkCoverFlow GtkCoverFlow;
|
||||
typedef struct _GtkCoverFlowClass GtkCoverFlowClass;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_cover_flow_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_cover_flow_new (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_cover_flow_new_with_factory (GtkListItemFactory *factory);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_cover_flow_get_model (GtkCoverFlow *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_cover_flow_set_model (GtkCoverFlow *self,
|
||||
GListModel *model);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_cover_flow_set_factory (GtkCoverFlow *self,
|
||||
GtkListItemFactory *factory);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkListItemFactory *
|
||||
gtk_cover_flow_get_factory (GtkCoverFlow *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_COVER_FLOW_H__ */
|
157
gtk/gtkcustomfilter.c
Normal file
157
gtk/gtkcustomfilter.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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 "gtkcustomfilter.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkcustomfilter
|
||||
* @Title: GtkCustomFilter
|
||||
* @Short_description: Filtering with callbacks
|
||||
*
|
||||
* #GtkCustomFilter is a #GtkFilter that uses a callback to determine whether
|
||||
* to include an item or not.
|
||||
*/
|
||||
struct _GtkCustomFilter
|
||||
{
|
||||
GtkFilter parent_instance;
|
||||
|
||||
GtkCustomFilterFunc match_func;
|
||||
gpointer user_data;
|
||||
GDestroyNotify user_destroy;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkCustomFilter, gtk_custom_filter, GTK_TYPE_FILTER)
|
||||
|
||||
static gboolean
|
||||
gtk_custom_filter_match (GtkFilter *filter,
|
||||
gpointer item)
|
||||
{
|
||||
GtkCustomFilter *self = GTK_CUSTOM_FILTER (filter);
|
||||
|
||||
if (!self->match_func)
|
||||
return TRUE;
|
||||
|
||||
return self->match_func (item, self->user_data);
|
||||
}
|
||||
|
||||
static GtkFilterMatch
|
||||
gtk_custom_filter_get_strictness (GtkFilter *filter)
|
||||
{
|
||||
GtkCustomFilter *self = GTK_CUSTOM_FILTER (filter);
|
||||
|
||||
if (!self->match_func)
|
||||
return GTK_FILTER_MATCH_ALL;
|
||||
|
||||
return GTK_FILTER_MATCH_SOME;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_custom_filter_dispose (GObject *object)
|
||||
{
|
||||
GtkCustomFilter *self = GTK_CUSTOM_FILTER (object);
|
||||
|
||||
if (self->user_destroy)
|
||||
self->user_destroy (self->user_data);
|
||||
|
||||
G_OBJECT_CLASS (gtk_custom_filter_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_custom_filter_class_init (GtkCustomFilterClass *class)
|
||||
{
|
||||
GtkFilterClass *filter_class = GTK_FILTER_CLASS (class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
filter_class->match = gtk_custom_filter_match;
|
||||
filter_class->get_strictness = gtk_custom_filter_get_strictness;
|
||||
|
||||
object_class->dispose = gtk_custom_filter_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_custom_filter_init (GtkCustomFilter *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_custom_filter_new:
|
||||
* @match_func: (nullable): function to filter items
|
||||
* @user_data: (nullable): user data to pass to @match_func
|
||||
* @user_destroy: destory notify
|
||||
*
|
||||
* Creates a new filter using the given @match_func to filter
|
||||
* items.
|
||||
*
|
||||
* If the filter func changes its filtering behavior,
|
||||
* gtk_filter_changed() needs to be called.
|
||||
*
|
||||
* Returns: a new #GtkFilter
|
||||
**/
|
||||
GtkFilter *
|
||||
gtk_custom_filter_new (GtkCustomFilterFunc match_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy)
|
||||
{
|
||||
GtkCustomFilter *result;
|
||||
|
||||
result = g_object_new (GTK_TYPE_CUSTOM_FILTER, NULL);
|
||||
|
||||
gtk_custom_filter_set_filter_func (result, match_func, user_data, user_destroy);
|
||||
|
||||
return GTK_FILTER (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_custom_filter_set_filter_func:
|
||||
* @self: a #GtkCustomFilter
|
||||
* @match_func: (nullable): function to filter items
|
||||
* @user_data: (nullable): user data to pass to @match_func
|
||||
* @user_destroy: destory notify
|
||||
*
|
||||
* Sets (or unsets) the function used for filtering items.
|
||||
*
|
||||
* If the filter func changes its filtering behavior,
|
||||
* gtk_filter_changed() needs to be called.
|
||||
*
|
||||
* If a previous function was set, its @user_destroy will be
|
||||
* called now.
|
||||
**/
|
||||
void
|
||||
gtk_custom_filter_set_filter_func (GtkCustomFilter *self,
|
||||
GtkCustomFilterFunc match_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CUSTOM_FILTER (self));
|
||||
g_return_if_fail (match_func || (user_data == NULL && !user_destroy));
|
||||
|
||||
if (self->user_destroy)
|
||||
self->user_destroy (self->user_data);
|
||||
|
||||
self->match_func = match_func;
|
||||
self->user_data = user_data;
|
||||
self->user_destroy = user_destroy;
|
||||
|
||||
gtk_filter_changed (GTK_FILTER (self), GTK_FILTER_CHANGE_DIFFERENT);
|
||||
}
|
60
gtk/gtkcustomfilter.h
Normal file
60
gtk/gtkcustomfilter.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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_CUSTOM_FILTER_H__
|
||||
#define __GTK_CUSTOM_FILTER_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkfilter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GtkCustomFilterFunc:
|
||||
* @item: (type GObject): The item to be matched
|
||||
* @user_data: user data
|
||||
*
|
||||
* User function that is called to determine if the @item should be matched.
|
||||
* If the filter matches the item, this function must return %TRUE. If the
|
||||
* item should be filtered out, %FALSE must be returned.
|
||||
*
|
||||
* Returns: %TRUE to keep the item around
|
||||
*/
|
||||
typedef gboolean (* GtkCustomFilterFunc) (gpointer item, gpointer user_data);
|
||||
|
||||
#define GTK_TYPE_CUSTOM_FILTER (gtk_custom_filter_get_type ())
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkCustomFilter, gtk_custom_filter, GTK, CUSTOM_FILTER, GtkFilter)
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkFilter * gtk_custom_filter_new (GtkCustomFilterFunc match_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_custom_filter_set_filter_func (GtkCustomFilter *self,
|
||||
GtkCustomFilterFunc match_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CUSTOM_FILTER_H__ */
|
159
gtk/gtkcustomsorter.c
Normal file
159
gtk/gtkcustomsorter.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright © 2019 Matthias Clasen
|
||||
*
|
||||
* 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: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcustomsorter.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkcustomsorter
|
||||
* @Title: GtkCustomSorter
|
||||
* @Short_description: Sorting with a callback
|
||||
*
|
||||
* GtkCustomSorter is a #GtkSorter implementation that sorts
|
||||
* via a traditional #GCompareDataFunc callback.
|
||||
*/
|
||||
struct _GtkCustomSorter
|
||||
{
|
||||
GtkSorter parent_instance;
|
||||
|
||||
GCompareDataFunc sort_func;
|
||||
gpointer user_data;
|
||||
GDestroyNotify user_destroy;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkCustomSorter, gtk_custom_sorter, GTK_TYPE_SORTER)
|
||||
|
||||
static GtkOrdering
|
||||
gtk_custom_sorter_compare (GtkSorter *sorter,
|
||||
gpointer item1,
|
||||
gpointer item2)
|
||||
{
|
||||
GtkCustomSorter *self = GTK_CUSTOM_SORTER (sorter);
|
||||
|
||||
if (!self->sort_func)
|
||||
return GTK_ORDERING_EQUAL;
|
||||
|
||||
return gtk_ordering_from_cmpfunc (self->sort_func (item1, item2, self->user_data));
|
||||
}
|
||||
|
||||
static GtkSorterOrder
|
||||
gtk_custom_sorter_get_order (GtkSorter *sorter)
|
||||
{
|
||||
GtkCustomSorter *self = GTK_CUSTOM_SORTER (sorter);
|
||||
|
||||
if (!self->sort_func)
|
||||
return GTK_SORTER_ORDER_NONE;
|
||||
|
||||
return GTK_SORTER_ORDER_PARTIAL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_custom_sorter_dispose (GObject *object)
|
||||
{
|
||||
GtkCustomSorter *self = GTK_CUSTOM_SORTER (object);
|
||||
|
||||
if (self->user_destroy)
|
||||
self->user_destroy (self->user_data);
|
||||
|
||||
self->sort_func = NULL;
|
||||
self->user_destroy = NULL;
|
||||
self->user_data = NULL;
|
||||
|
||||
G_OBJECT_CLASS (gtk_custom_sorter_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_custom_sorter_class_init (GtkCustomSorterClass *class)
|
||||
{
|
||||
GtkSorterClass *sorter_class = GTK_SORTER_CLASS (class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
sorter_class->compare = gtk_custom_sorter_compare;
|
||||
sorter_class->get_order = gtk_custom_sorter_get_order;
|
||||
|
||||
object_class->dispose = gtk_custom_sorter_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_custom_sorter_init (GtkCustomSorter *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_custom_sorter_new:
|
||||
* @sort_func: the #GCompareDataFunc to use for sorting
|
||||
* @user_data: (nullable): user data to pass to @sort_func
|
||||
* @user_destroy: (nullable): destroy notify for @user_data
|
||||
*
|
||||
* Creates a new #GtkSorter that works by calling
|
||||
* @sort_func to compare items.
|
||||
*
|
||||
* Returns: a new #GTkSorter
|
||||
*/
|
||||
GtkSorter *
|
||||
gtk_custom_sorter_new (GCompareDataFunc sort_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy)
|
||||
{
|
||||
GtkCustomSorter *sorter;
|
||||
|
||||
sorter = g_object_new (GTK_TYPE_CUSTOM_SORTER, NULL);
|
||||
|
||||
gtk_custom_sorter_set_sort_func (sorter, sort_func, user_data, user_destroy);
|
||||
|
||||
return GTK_SORTER (sorter);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_custom_sorter_set_sort_func:
|
||||
* @self: a #GtkCustomSorter
|
||||
* @sort_func: (nullable): function to sort items
|
||||
* @user_data: (nullable): user data to pass to @match_func
|
||||
* @user_destroy: destory notify
|
||||
*
|
||||
* Sets (or unsets) the function used for sorting items.
|
||||
*
|
||||
* If the sort func changes its sorting behavior,
|
||||
* gtk_sorter_changed() needs to be called.
|
||||
*
|
||||
* If a previous function was set, its @user_destroy will be
|
||||
* called now.
|
||||
**/
|
||||
void
|
||||
gtk_custom_sorter_set_sort_func (GtkCustomSorter *self,
|
||||
GCompareDataFunc sort_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_CUSTOM_SORTER (self));
|
||||
g_return_if_fail (sort_func || (user_data == NULL && !user_destroy));
|
||||
|
||||
if (self->user_destroy)
|
||||
self->user_destroy (self->user_data);
|
||||
|
||||
self->sort_func = sort_func;
|
||||
self->user_data = user_data;
|
||||
self->user_destroy = user_destroy;
|
||||
|
||||
gtk_sorter_changed (GTK_SORTER (self), GTK_SORTER_CHANGE_DIFFERENT);
|
||||
}
|
49
gtk/gtkcustomsorter.h
Normal file
49
gtk/gtkcustomsorter.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright © 2019 Matthias Clasen
|
||||
*
|
||||
* 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: Matthias Clasen <mclasen@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CUSTOM_SORTER_H__
|
||||
#define __GTK_CUSTOM_SORTER_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkexpression.h>
|
||||
#include <gtk/gtksorter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CUSTOM_SORTER (gtk_custom_sorter_get_type ())
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkCustomSorter, gtk_custom_sorter, GTK, CUSTOM_SORTER, GtkSorter)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkSorter * gtk_custom_sorter_new (GCompareDataFunc sort_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_custom_sorter_set_sort_func (GtkCustomSorter *self,
|
||||
GCompareDataFunc sort_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CUSTOM_SORTER_H__ */
|
681
gtk/gtkdirectorylist.c
Normal file
681
gtk/gtkdirectorylist.c
Normal file
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
* 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 "gtkdirectorylist.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkdirectorylist
|
||||
* @title: GtkDirectoryList
|
||||
* @short_description: A list model for directory listings
|
||||
* @see_also: #GListModel, g_file_enumerate_children()
|
||||
*
|
||||
* #GtkDirectoryList is a list model that wraps g_file_enumerate_children_async().
|
||||
* It presents a #GListModel and fills it asynchronously with the #GFileInfos
|
||||
* returned from that function.
|
||||
*
|
||||
* Enumeration will start automatically when a the GtkDirectoryList:file property
|
||||
* is set.
|
||||
*
|
||||
* While the #GtkDirectoryList is being filled, the GtkDirectoryList:loading
|
||||
* property will be set to %TRUE. You can listen to that property if you want
|
||||
* to show information like a #GtkSpinner or a "Loading..." text.
|
||||
* If loading fails at any point, the GtkDirectoryList:error property will be set
|
||||
* to give more indication about the failure.
|
||||
*
|
||||
* The #GFileInfos returned from a #GtkDirectoryList have the "standard::file"
|
||||
* attribute set to the #GFile they refer to. This way you can get at the file
|
||||
* that is referred to in the same way you would via g_file_enumerator_get_child().
|
||||
* This means you do not need access to the #GtkDirectoryList but can access
|
||||
* the #GFile directly from the #GFileInfo when operating with a #GtkListView or
|
||||
* similar.
|
||||
*/
|
||||
|
||||
/* random number that everyone else seems to use, too */
|
||||
#define FILES_PER_QUERY 100
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ATTRIBUTES,
|
||||
PROP_ERROR,
|
||||
PROP_FILE,
|
||||
PROP_IO_PRIORITY,
|
||||
PROP_ITEM_TYPE,
|
||||
PROP_LOADING,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
struct _GtkDirectoryList
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
char *attributes;
|
||||
int io_priority;
|
||||
GFile *file;
|
||||
|
||||
GCancellable *cancellable;
|
||||
GError *error; /* Error while loading */
|
||||
GSequence *items; /* Use GPtrArray or GListStore here? */
|
||||
};
|
||||
|
||||
struct _GtkDirectoryListClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
static GType
|
||||
gtk_directory_list_get_item_type (GListModel *list)
|
||||
{
|
||||
return G_TYPE_FILE_INFO;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_directory_list_get_n_items (GListModel *list)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (list);
|
||||
|
||||
return g_sequence_get_length (self->items);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gtk_directory_list_get_item (GListModel *list,
|
||||
guint position)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (list);
|
||||
GSequenceIter *iter;
|
||||
|
||||
iter = g_sequence_get_iter_at_pos (self->items, position);
|
||||
|
||||
if (g_sequence_iter_is_end (iter))
|
||||
return NULL;
|
||||
else
|
||||
return g_object_ref (g_sequence_get (iter));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_model_init (GListModelInterface *iface)
|
||||
{
|
||||
iface->get_item_type = gtk_directory_list_get_item_type;
|
||||
iface->get_n_items = gtk_directory_list_get_n_items;
|
||||
iface->get_item = gtk_directory_list_get_item;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkDirectoryList, gtk_directory_list, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_directory_list_model_init))
|
||||
|
||||
static void
|
||||
gtk_directory_list_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ATTRIBUTES:
|
||||
gtk_directory_list_set_attributes (self, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_FILE:
|
||||
gtk_directory_list_set_file (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_IO_PRIORITY:
|
||||
gtk_directory_list_set_io_priority (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ATTRIBUTES:
|
||||
g_value_set_string (value, self->attributes);
|
||||
break;
|
||||
|
||||
case PROP_ERROR:
|
||||
g_value_set_boxed (value, self->error);
|
||||
break;
|
||||
|
||||
case PROP_FILE:
|
||||
g_value_set_object (value, self->file);
|
||||
break;
|
||||
|
||||
case PROP_IO_PRIORITY:
|
||||
g_value_set_int (value, self->io_priority);
|
||||
break;
|
||||
|
||||
case PROP_ITEM_TYPE:
|
||||
g_value_set_gtype (value, G_TYPE_FILE_INFO);
|
||||
break;
|
||||
|
||||
case PROP_LOADING:
|
||||
g_value_set_boolean (value, gtk_directory_list_is_loading (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_directory_list_stop_loading (GtkDirectoryList *self)
|
||||
{
|
||||
if (self->cancellable == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
g_clear_object (&self->cancellable);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_dispose (GObject *object)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (object);
|
||||
|
||||
gtk_directory_list_stop_loading (self);
|
||||
|
||||
g_clear_object (&self->file);
|
||||
g_clear_pointer (&self->attributes, g_free);
|
||||
|
||||
g_clear_error (&self->error);
|
||||
g_clear_pointer (&self->items, g_sequence_free);
|
||||
|
||||
G_OBJECT_CLASS (gtk_directory_list_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_class_init (GtkDirectoryListClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = gtk_directory_list_set_property;
|
||||
gobject_class->get_property = gtk_directory_list_get_property;
|
||||
gobject_class->dispose = gtk_directory_list_dispose;
|
||||
|
||||
/**
|
||||
* GtkDirectoryList:attributes:
|
||||
*
|
||||
* The attributes to query
|
||||
*/
|
||||
properties[PROP_ATTRIBUTES] =
|
||||
g_param_spec_string ("attributes",
|
||||
P_("attributes"),
|
||||
P_("Attributes to query"),
|
||||
NULL,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkDirectoryList:error:
|
||||
*
|
||||
* Error encountered while loading files
|
||||
*/
|
||||
properties[PROP_ERROR] =
|
||||
g_param_spec_boxed ("error",
|
||||
P_("error"),
|
||||
P_("Error encountered while loading files"),
|
||||
G_TYPE_ERROR,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkDirectoryList:file:
|
||||
*
|
||||
* File to query
|
||||
*/
|
||||
properties[PROP_FILE] =
|
||||
g_param_spec_object ("file",
|
||||
P_("File"),
|
||||
P_("The file to query"),
|
||||
G_TYPE_FILE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkDirectoryList:io-priority:
|
||||
*
|
||||
* Priority used when loading
|
||||
*/
|
||||
properties[PROP_IO_PRIORITY] =
|
||||
g_param_spec_int ("io-priority",
|
||||
P_("IO priority"),
|
||||
P_("Priority used when loading"),
|
||||
-G_MAXINT, G_MAXINT, G_PRIORITY_DEFAULT,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkDirectoryList:item-type:
|
||||
*
|
||||
* The #GType for elements of this object
|
||||
*/
|
||||
properties[PROP_ITEM_TYPE] =
|
||||
g_param_spec_gtype ("item-type",
|
||||
P_("Item type"),
|
||||
P_("The type of elements of this object"),
|
||||
G_TYPE_FILE_INFO,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkDirectoryList:loading:
|
||||
*
|
||||
* %TRUE if files are being loaded
|
||||
*/
|
||||
properties[PROP_LOADING] =
|
||||
g_param_spec_boolean ("loading",
|
||||
P_("loading"),
|
||||
P_("TRUE if files are being loaded"),
|
||||
FALSE,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_init (GtkDirectoryList *self)
|
||||
{
|
||||
self->items = g_sequence_new (g_object_unref);
|
||||
self->io_priority = G_PRIORITY_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_new:
|
||||
* @file: (allow-none): The file to query
|
||||
* @attributes: (allow-none): The attributes to query with
|
||||
*
|
||||
* Creates a new #GtkDirectoryList querying the given @file with the given
|
||||
* @attributes.
|
||||
*
|
||||
* Returns: a new #GtkDirectoryList
|
||||
**/
|
||||
GtkDirectoryList *
|
||||
gtk_directory_list_new (const char *attributes,
|
||||
GFile *file)
|
||||
|
||||
{
|
||||
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_DIRECTORY_LIST,
|
||||
"attributes", attributes,
|
||||
"file", file,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_clear_items (GtkDirectoryList *self)
|
||||
{
|
||||
guint n_items;
|
||||
|
||||
n_items = g_sequence_get_length (self->items);
|
||||
if (n_items > 0)
|
||||
{
|
||||
g_sequence_remove_range (g_sequence_get_begin_iter (self->items),
|
||||
g_sequence_get_end_iter (self->items));
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, 0);
|
||||
}
|
||||
|
||||
if (self->error)
|
||||
{
|
||||
g_clear_error (&self->error);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_enumerator_closed_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_file_enumerator_close_finish (G_FILE_ENUMERATOR (source), res, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_got_files_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkDirectoryList *self = user_data; /* invalid if cancelled */
|
||||
GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source);
|
||||
GError *error = NULL;
|
||||
GList *l, *files;
|
||||
guint n;
|
||||
|
||||
files = g_file_enumerator_next_files_finish (enumerator, res, &error);
|
||||
|
||||
if (files == NULL)
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_file_enumerator_close_async (enumerator,
|
||||
self->io_priority,
|
||||
NULL,
|
||||
gtk_directory_list_enumerator_closed_cb,
|
||||
NULL);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
g_clear_object (&self->cancellable);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
|
||||
|
||||
if (error)
|
||||
{
|
||||
self->error = error;
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
|
||||
}
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
return;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
for (l = files; l; l = l->next)
|
||||
{
|
||||
GFileInfo *info;
|
||||
GFile *file;
|
||||
|
||||
info = l->data;
|
||||
file = g_file_enumerator_get_child (enumerator, info);
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
g_object_unref (file);
|
||||
g_sequence_append (self->items, info);
|
||||
n++;
|
||||
}
|
||||
g_list_free (files);
|
||||
|
||||
g_file_enumerator_next_files_async (enumerator,
|
||||
g_file_is_native (self->file) ? 50 * FILES_PER_QUERY : FILES_PER_QUERY,
|
||||
self->io_priority,
|
||||
self->cancellable,
|
||||
gtk_directory_list_got_files_cb,
|
||||
self);
|
||||
|
||||
if (n > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), g_sequence_get_length (self->items) - n, 0, n);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_got_enumerator_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkDirectoryList *self = user_data; /* invalid if cancelled */
|
||||
GFile *file = G_FILE (source);
|
||||
GFileEnumerator *enumerator;
|
||||
GError *error = NULL;
|
||||
|
||||
enumerator = g_file_enumerate_children_finish (file, res, &error);
|
||||
if (enumerator == NULL)
|
||||
{
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
self->error = error;
|
||||
g_clear_object (&self->cancellable);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]);
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
return;
|
||||
}
|
||||
|
||||
g_file_enumerator_next_files_async (enumerator,
|
||||
g_file_is_native (file) ? 50 * FILES_PER_QUERY : FILES_PER_QUERY,
|
||||
self->io_priority,
|
||||
self->cancellable,
|
||||
gtk_directory_list_got_files_cb,
|
||||
self);
|
||||
g_object_unref (enumerator);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_start_loading (GtkDirectoryList *self)
|
||||
{
|
||||
gboolean was_loading;
|
||||
|
||||
was_loading = gtk_directory_list_stop_loading (self);
|
||||
gtk_directory_list_clear_items (self);
|
||||
|
||||
if (self->file == NULL)
|
||||
{
|
||||
if (was_loading)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
|
||||
return;
|
||||
}
|
||||
|
||||
self->cancellable = g_cancellable_new ();
|
||||
g_file_enumerate_children_async (self->file,
|
||||
self->attributes,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
self->io_priority,
|
||||
self->cancellable,
|
||||
gtk_directory_list_got_enumerator_cb,
|
||||
self);
|
||||
|
||||
if (!was_loading)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_set_file:
|
||||
* @self: a #GtkDirectoryList
|
||||
* @file: (allow-none): the #GFile to be enumerated
|
||||
*
|
||||
* Sets the @file to be enumerated and starts the enumeration.
|
||||
*
|
||||
* If @file is %NULL, the result will be an empty list.
|
||||
*/
|
||||
void
|
||||
gtk_directory_list_set_file (GtkDirectoryList *self,
|
||||
GFile *file)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_DIRECTORY_LIST (self));
|
||||
g_return_if_fail (file == NULL || G_IS_FILE (file));
|
||||
|
||||
if (self->file == file ||
|
||||
(self->file && file && g_file_equal (self->file, file)))
|
||||
return;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
g_set_object (&self->file, file);
|
||||
|
||||
gtk_directory_list_start_loading (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_get_file:
|
||||
* @self: a #GtkDirectoryList
|
||||
*
|
||||
* Gets the file whose children are currently enumerated.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): The file whose children are enumerated
|
||||
**/
|
||||
GFile *
|
||||
gtk_directory_list_get_file (GtkDirectoryList *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DIRECTORY_LIST (self), NULL);
|
||||
|
||||
return self->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_set_attributes:
|
||||
* @self: a #GtkDirectoryList
|
||||
* @attributes: (allow-none): the attributes to enumerate
|
||||
*
|
||||
* Sets the @attributes to be enumerated and starts the enumeration.
|
||||
*
|
||||
* If @attributes is %NULL, no attributes will be queried, but a list
|
||||
* of #GFileInfos will still be created.
|
||||
*/
|
||||
void
|
||||
gtk_directory_list_set_attributes (GtkDirectoryList *self,
|
||||
const char *attributes)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_DIRECTORY_LIST (self));
|
||||
|
||||
if (self->attributes == attributes)
|
||||
return;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
g_free (self->attributes);
|
||||
self->attributes = g_strdup (attributes);
|
||||
|
||||
gtk_directory_list_start_loading (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ATTRIBUTES]);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_get_attributes:
|
||||
* @self: a #GtkDirectoryList
|
||||
*
|
||||
* Gets the attributes queried on the children.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): The queried attributes
|
||||
*/
|
||||
const char *
|
||||
gtk_directory_list_get_attributes (GtkDirectoryList *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DIRECTORY_LIST (self), NULL);
|
||||
|
||||
return self->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_set_io_priority:
|
||||
* @self: a #GtkDirectoryList
|
||||
* @io_priority: IO priority to use
|
||||
*
|
||||
* Sets the IO priority to use while loading directories.
|
||||
*
|
||||
* Setting the priority while @self is loading will reprioritize the
|
||||
* ongoing load as soon as possible.
|
||||
*
|
||||
* The default IO priority is %G_PRIORITY_DEFAULT, which is higher than
|
||||
* the GTK redraw priority. If you are loading a lot of directories in
|
||||
* parrallel, lowering it to something like %G_PRIORITY_DEFAULT_IDLE
|
||||
* may increase responsiveness.
|
||||
*/
|
||||
void
|
||||
gtk_directory_list_set_io_priority (GtkDirectoryList *self,
|
||||
int io_priority)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_DIRECTORY_LIST (self));
|
||||
|
||||
if (self->io_priority == io_priority)
|
||||
return;
|
||||
|
||||
self->io_priority = io_priority;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_IO_PRIORITY]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_get_io_priority:
|
||||
* @self: a #GtkDirectoryList
|
||||
*
|
||||
* Gets the IO priority set via gtk_directory_list_set_io_priority().
|
||||
*
|
||||
* Returns: The IO priority.
|
||||
*/
|
||||
int
|
||||
gtk_directory_list_get_io_priority (GtkDirectoryList *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DIRECTORY_LIST (self), G_PRIORITY_DEFAULT);
|
||||
|
||||
return self->io_priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_is_loading:
|
||||
* @self: a #GtkDirectoryList
|
||||
*
|
||||
* Returns %TRUE if the children enumeration is currently in
|
||||
* progress.
|
||||
* Files will be added to @self from time to time while loading is
|
||||
* going on. The order in which are added is undefined and may change
|
||||
* inbetween runs.
|
||||
*
|
||||
* Returns: %TRUE if @self is loading
|
||||
*/
|
||||
gboolean
|
||||
gtk_directory_list_is_loading (GtkDirectoryList *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DIRECTORY_LIST (self), FALSE);
|
||||
|
||||
return self->cancellable != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_get_error:
|
||||
* @self: a #GtkDirectoryList
|
||||
*
|
||||
* Gets the loading error, if any.
|
||||
*
|
||||
* If an error occurs during the loading process, the loading process
|
||||
* will finish and this property allows querying the error that happened.
|
||||
* This error will persist until a file is loaded again.
|
||||
*
|
||||
* An error being set does not mean that no files were loaded, and all
|
||||
* successfully queried files will remain in the list.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): The loading error or %NULL if
|
||||
* loading finished successfully.
|
||||
*/
|
||||
const GError *
|
||||
gtk_directory_list_get_error (GtkDirectoryList *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DIRECTORY_LIST (self), FALSE);
|
||||
|
||||
return self->error;
|
||||
}
|
||||
|
67
gtk/gtkdirectorylist.h
Normal file
67
gtk/gtkdirectorylist.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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_DIRECTORY_LIST_H__
|
||||
#define __GTK_DIRECTORY_LIST_H__
|
||||
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gio/gio.h>
|
||||
/* for GDK_AVAILABLE_IN_ALL */
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_DIRECTORY_LIST (gtk_directory_list_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkDirectoryList, gtk_directory_list, GTK, DIRECTORY_LIST, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkDirectoryList * gtk_directory_list_new (const char *attributes,
|
||||
GFile *file);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_directory_list_set_file (GtkDirectoryList *self,
|
||||
GFile *file);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GFile * gtk_directory_list_get_file (GtkDirectoryList *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_directory_list_set_attributes (GtkDirectoryList *self,
|
||||
const char *attributes);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * gtk_directory_list_get_attributes (GtkDirectoryList *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_directory_list_set_io_priority (GtkDirectoryList *self,
|
||||
int io_priority);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gtk_directory_list_get_io_priority (GtkDirectoryList *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_directory_list_is_loading (GtkDirectoryList *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GError * gtk_directory_list_get_error (GtkDirectoryList *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_DIRECTORY_LIST_H__ */
|
1207
gtk/gtkdropdown.c
Normal file
1207
gtk/gtkdropdown.c
Normal file
File diff suppressed because it is too large
Load Diff
80
gtk/gtkdropdown.h
Normal file
80
gtk/gtkdropdown.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright © 2018 Red Hat, Inc.
|
||||
*
|
||||
* 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: Matthias Clasen
|
||||
*/
|
||||
|
||||
#ifndef __GTK_DROP_DOWN_H__
|
||||
#define __GTK_DROP_DOWN_H__
|
||||
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include <gtk/gtkexpression.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_DROP_DOWN (gtk_drop_down_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkDropDown, gtk_drop_down, GTK, DROP_DOWN, GtkWidget)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget * gtk_drop_down_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drop_down_set_from_strings (GtkDropDown *self,
|
||||
const char *const *texts);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drop_down_set_model (GtkDropDown *self,
|
||||
GListModel *model);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_drop_down_get_model (GtkDropDown *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drop_down_set_selected (GtkDropDown *self,
|
||||
guint position);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
guint gtk_drop_down_get_selected (GtkDropDown *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drop_down_set_factory (GtkDropDown *self,
|
||||
GtkListItemFactory *factory);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkListItemFactory *
|
||||
gtk_drop_down_get_factory (GtkDropDown *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drop_down_set_list_factory (GtkDropDown *self,
|
||||
GtkListItemFactory *factory);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkListItemFactory *
|
||||
gtk_drop_down_get_list_factory (GtkDropDown *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drop_down_set_expression (GtkDropDown *self,
|
||||
GtkExpression *expression);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkExpression * gtk_drop_down_get_expression (GtkDropDown *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_drop_down_set_enable_search (GtkDropDown *self,
|
||||
gboolean enable_search);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_drop_down_get_enable_search (GtkDropDown *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_DROP_DOWN_H__ */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user