[gtk/wip/otte/listview: 119/119] gtk-demo: Introduce awards
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/listview: 119/119] gtk-demo: Introduce awards
- Date: Mon, 3 Jun 2019 18:54:06 +0000 (UTC)
commit 8f3f75aecbf26c3047bd9bb73e96ef48435318e9
Author: Benjamin Otte <otte redhat com>
Date: Fri May 31 04:52:13 2019 +0200
gtk-demo: Introduce awards
We need a way to get a useful listbox, so here we go!
demos/gtk-demo/award.c | 221 ++++++++++++++++++++++++++++++++++++++
demos/gtk-demo/award.h | 18 ++++
demos/gtk-demo/awards.txt | 8 ++
demos/gtk-demo/demo.gresource.xml | 3 +
demos/gtk-demo/listbox.c | 10 +-
demos/gtk-demo/main.c | 4 +
demos/gtk-demo/meson.build | 1 +
demos/gtk-demo/sliding_puzzle.c | 25 ++++-
8 files changed, 286 insertions(+), 4 deletions(-)
---
diff --git a/demos/gtk-demo/award.c b/demos/gtk-demo/award.c
new file mode 100644
index 0000000000..5808b62967
--- /dev/null
+++ b/demos/gtk-demo/award.c
@@ -0,0 +1,221 @@
+/*
+ * 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 *name;
+ char *title;
+ GDateTime *granted; /* or NULL if not granted */
+};
+
+enum {
+ PROP_0,
+ 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_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkAward *self = GTK_AWARD (object);
+
+ switch (prop_id)
+ {
+ 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->get_property = gtk_award_get_property;
+ gobject_class->dispose = gtk_award_dispose;
+
+ properties[PROP_NAME] =
+ g_param_spec_string ("name",
+ "Name",
+ "internal name of the award",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ properties[PROP_TITLE] =
+ g_param_spec_string ("title",
+ "Title",
+ "user-visible title",
+ NULL,
+ G_PARAM_READABLE | 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)
+ {
+ GBytes *data;
+ char **lines;
+ guint i;
+
+ list = G_LIST_MODEL (g_list_store_new (GTK_TYPE_AWARD));
+
+ data = g_resources_lookup_data ("/awards.txt", 0, NULL);
+ lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
+
+ for (i = 0; lines[i] != NULL && *lines[i]; i++)
+ {
+ GtkAward *award = g_object_new (GTK_TYPE_AWARD, NULL);
+ const char *s;
+ s = strchr (lines[i], ' ');
+ g_assert (s);
+ award->name = g_strndup (lines[i], s - lines[i]);
+ while (*s == ' ') s++;
+ award->title = g_strdup (s);
+ g_list_store_append (G_LIST_STORE (list), award);
+ g_object_unref (award);
+ }
+
+ g_strfreev (lines);
+ g_bytes_unref (data);
+ }
+
+ 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);
+}
+
diff --git a/demos/gtk-demo/award.h b/demos/gtk-demo/award.h
new file mode 100644
index 0000000000..0c4cca01f2
--- /dev/null
+++ b/demos/gtk-demo/award.h
@@ -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__ */
diff --git a/demos/gtk-demo/awards.txt b/demos/gtk-demo/awards.txt
new file mode 100644
index 0000000000..ddb699b601
--- /dev/null
+++ b/demos/gtk-demo/awards.txt
@@ -0,0 +1,8 @@
+demo-inspector Launch the inspector
+demo-start Start gtk-demo
+listbox-reshare Reshare a tweet
+listbox-100th-row Select a 100th row in a list
+puzzle-give-up Give up without finishing the puzzle
+puzzle-solve Solve a puzzle
+puzzle-solve-animated Solve an animated puzzle
+puzzle-solve-large Solve a puzzle with at least 20 pieces
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index a71adcee26..776e1f80d3 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
+ <gresource prefix="/">
+ <file>awards.txt</file>
+ </gresource>
<gresource prefix="/ui">
<file preprocess="xml-stripblanks">main.ui</file>
<file preprocess="xml-stripblanks">appmenu.ui</file>
diff --git a/demos/gtk-demo/listbox.c b/demos/gtk-demo/listbox.c
index 4e70c2f979..00e24f5b88 100644
--- a/demos/gtk-demo/listbox.c
+++ b/demos/gtk-demo/listbox.c
@@ -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);
}
diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c
index 6b997f5810..e5ead13b55 100644
--- a/demos/gtk-demo/main.c
+++ b/demos/gtk-demo/main.c
@@ -8,6 +8,7 @@
#include <gtk/gtk.h>
#include <glib/gstdio.h>
+#include "award.h"
#include "demos.h"
static GtkWidget *info_view;
@@ -111,6 +112,7 @@ activate_inspector (GSimpleAction *action,
gpointer user_data)
{
gtk_window_set_interactive_debugging (TRUE);
+ award ("demo-inspector");
}
static void
@@ -1093,6 +1095,8 @@ activate (GApplication *app)
gtk_tree_view_collapse_all (GTK_TREE_VIEW (treeview));
+ award ("demo-start");
+
gtk_widget_show (GTK_WIDGET (window));
g_object_unref (builder);
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index aba44c976c..05f62d77de 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -79,6 +79,7 @@ demos = files([
gtkdemo_deps = [ libgtk_dep, ]
extra_demo_sources = files(['main.c',
+ 'award.c',
'gtkfishbowl.c',
'fontplane.c',
'gtkgears.c',
diff --git a/demos/gtk-demo/sliding_puzzle.c b/demos/gtk-demo/sliding_puzzle.c
index 9486004605..2b3e962bdd 100644
--- a/demos/gtk-demo/sliding_puzzle.c
+++ b/demos/gtk-demo/sliding_puzzle.c
@@ -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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]