[gtk/wip/otte/symbolic-paintable: 5/5] gtk-demo: Add a symbolic paintable demo
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/symbolic-paintable: 5/5] gtk-demo: Add a symbolic paintable demo
- Date: Sun, 29 Aug 2021 02:29:59 +0000 (UTC)
commit 7cdbdb663c35b72f8934698e8823d96ebef78ce5
Author: Benjamin Otte <otte redhat com>
Date: Sat Aug 28 03:46:55 2021 +0200
gtk-demo: Add a symbolic paintable demo
Don't click the button!
demos/gtk-demo/demo.gresource.xml | 1 +
demos/gtk-demo/meson.build | 1 +
demos/gtk-demo/paintable_symbolic.c | 208 ++++++++++++++++++++++++++++++++++++
3 files changed, 210 insertions(+)
---
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index 09709d48d8..83e798fd25 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -321,6 +321,7 @@
<file>paintable_emblem.c</file>
<file>paintable_mediastream.c</file>
<file>paintable_svg.c</file>
+ <file>paintable_symbolic.c</file>
<file>panes.c</file>
<file>password_entry.c</file>
<file>peg_solitaire.c</file>
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 24e4abe05d..9201655988 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -67,6 +67,7 @@ demos = files([
'paintable_animated.c',
'paintable_emblem.c',
'paintable_mediastream.c',
+ 'paintable_symbolic.c',
'panes.c',
'password_entry.c',
'peg_solitaire.c',
diff --git a/demos/gtk-demo/paintable_symbolic.c b/demos/gtk-demo/paintable_symbolic.c
new file mode 100644
index 0000000000..6be093f6e6
--- /dev/null
+++ b/demos/gtk-demo/paintable_symbolic.c
@@ -0,0 +1,208 @@
+/* Paintable/Symbolic Paintable
+ *
+ * GdkPaintables can be made to follow the theme's colors. GTK calls
+ * icons that do this symbolic icons, paintables that want to have
+ * the same effect can implement the GtkSymbolicPaintable interface.
+ *
+ * We will adapt the original paintable example by adding the ability
+ * to recolor the paintable based on the symbolic colors.
+ */
+
+#include <gtk/gtk.h>
+
+#include "paintable.h"
+
+static GtkWidget *window = NULL;
+
+/* First, add the boilerplate for the object itself.
+ * This part would normally go in the header.
+ */
+#define GTK_TYPE_NUCLEAR_SYMBOLIC (gtk_nuclear_symbolic_get_type ())
+G_DECLARE_FINAL_TYPE (GtkNuclearSymbolic, gtk_nuclear_symbolic, GTK, NUCLEAR_SYMBOLIC, GObject)
+
+/* Declare a few warning levels, so we can pick colors based on them */
+typedef enum
+{
+ WARNING_NONE,
+ WARNING_ALERT,
+ WARNING_EMERGENCY
+} WarningLevel;
+
+/* Declare the struct. */
+struct _GtkNuclearSymbolic
+{
+ GObject parent_instance;
+
+ WarningLevel warning_level;
+};
+
+struct _GtkNuclearSymbolicClass
+{
+ GObjectClass parent_class;
+};
+
+/* Add a function to draw the nuclear icon in the given colors */
+static void
+gtk_nuclear_symbolic_snapshot_symbolic (GtkSymbolicPaintable *paintable,
+ GdkSnapshot *snapshot,
+ double width,
+ double height,
+ const GdkRGBA *colors,
+ gsize n_colors)
+{
+ GtkNuclearSymbolic *self = GTK_NUCLEAR_SYMBOLIC (paintable);
+ static const GdkRGBA transparent = { 0, };
+ const GdkRGBA *bg_color;
+
+ /* select the right background color from the warning level */
+ switch (self->warning_level)
+ {
+ case WARNING_NONE:
+ bg_color = &transparent;
+ break;
+ case WARNING_ALERT:
+ bg_color = &colors[2]; /* warning color */
+ break;
+ case WARNING_EMERGENCY:
+ bg_color = &colors[1]; /* error color */
+ break;
+ default:
+ /* This should never happen, but we better do defensive coding
+ * with this critical icon */
+ g_assert_not_reached ();
+ bg_color = &transparent;
+ break;
+ }
+
+ /* Draw the icon with the selected warning color */
+ gtk_nuclear_snapshot (snapshot,
+ &colors[0], /* foreground color */
+ bg_color,
+ width, height,
+ 0);
+}
+
+static void
+gtk_nuclear_symbolic_symbolic_paintable_init (GtkSymbolicPaintableInterface *iface)
+{
+ iface->snapshot_symbolic = gtk_nuclear_symbolic_snapshot_symbolic;
+}
+
+/* We need to implement the functionality required by the GdkPaintable interface */
+static void
+gtk_nuclear_symbolic_snapshot (GdkPaintable *paintable,
+ GdkSnapshot *snapshot,
+ double width,
+ double height)
+{
+ /* Calling this function without passing a color is a neat trick
+ * to make GTK use default colors and otherwise forward the call
+ * to the snapshotting function above.
+ */
+ gtk_symbolic_paintable_snapshot_symbolic (GTK_SYMBOLIC_PAINTABLE (paintable),
+ snapshot,
+ width, height,
+ NULL, 0);
+}
+
+static GdkPaintableFlags
+gtk_nuclear_symbolic_get_flags (GdkPaintable *paintable)
+{
+ /* This image has a static size, but the contents may change:
+ * We draw different things when the warning level changes.
+ */
+ return GDK_PAINTABLE_STATIC_SIZE;
+}
+
+static void
+gtk_nuclear_symbolic_paintable_init (GdkPaintableInterface *iface)
+{
+ iface->snapshot = gtk_nuclear_symbolic_snapshot;
+ iface->get_flags = gtk_nuclear_symbolic_get_flags;
+}
+
+/* When defining the GType, we need to implement bot the GdkPaintable
+ * and the GtkSymbolicPaintable interface */
+G_DEFINE_TYPE_WITH_CODE (GtkNuclearSymbolic, gtk_nuclear_symbolic, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
+ gtk_nuclear_symbolic_paintable_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_SYMBOLIC_PAINTABLE,
+ gtk_nuclear_symbolic_symbolic_paintable_init))
+
+static void
+gtk_nuclear_symbolic_class_init (GtkNuclearSymbolicClass *klass)
+{
+}
+
+static void
+gtk_nuclear_symbolic_init (GtkNuclearSymbolic *nuclear)
+{
+}
+
+/* And finally, we add the simple constructor we declared in the header. */
+GdkPaintable *
+gtk_nuclear_symbolic_new (void)
+{
+ return g_object_new (GTK_TYPE_NUCLEAR_SYMBOLIC, NULL);
+}
+
+/* Add some fun feature to the button */
+static void
+nuclear_button_clicked (GtkButton *button,
+ GtkNuclearSymbolic *nuclear)
+{
+ if (nuclear->warning_level >= WARNING_EMERGENCY)
+ {
+ /* On maximum warning level, reset the warning */
+ nuclear->warning_level = WARNING_NONE;
+ /* And sometimes (but not always to confuse people)
+ * close the window.
+ */
+ if (g_random_boolean ())
+ gtk_window_close (GTK_WINDOW (window));
+ }
+ else
+ {
+ /* Otherwise just increase the warning level */
+ nuclear->warning_level++;
+ }
+
+ /* Don't forget to emit the signal causing the paintable to redraw.
+ * Changing the warning level changes the background color after all.
+ */
+ gdk_paintable_invalidate_contents (GDK_PAINTABLE (nuclear));
+}
+
+GtkWidget *
+do_paintable_symbolic (GtkWidget *do_widget)
+{
+ GdkPaintable *nuclear;
+ GtkWidget *image, *button;
+
+ if (!window)
+ {
+ window = gtk_window_new ();
+ gtk_window_set_display (GTK_WINDOW (window),
+ gtk_widget_get_display (do_widget));
+ gtk_window_set_title (GTK_WINDOW (window), "Don't click!");
+ gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
+ g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
+
+ button = gtk_button_new ();
+ gtk_window_set_child (GTK_WINDOW (window), button);
+
+ nuclear = gtk_nuclear_symbolic_new ();
+ image = gtk_image_new_from_paintable (nuclear);
+
+ gtk_button_set_child (GTK_BUTTON (button), image);
+ g_signal_connect (button, "clicked", G_CALLBACK (nuclear_button_clicked), nuclear);
+ g_object_unref (nuclear);
+ }
+
+ if (!gtk_widget_get_visible (window))
+ gtk_widget_show (window);
+ else
+ gtk_window_destroy (GTK_WINDOW (window));
+
+ return window;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]