summaryrefslogtreecommitdiff
path: root/demos/gtk-demo/css_blendmodes.c
diff options
context:
space:
mode:
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2016-07-01 19:39:04 -0300
committerMatthias Clasen <mclasen@redhat.com>2016-07-03 17:24:47 -0400
commit1d93cc2b0b88bcc02f8a15d80b8a75d61d0cb24a (patch)
treef796bfe224909a03cf6bbac49ba261646f8f0de9 /demos/gtk-demo/css_blendmodes.c
parent27fea1c4fc7e178fd435a4bb0c5d5c836d72ed09 (diff)
downloadgtk+-1d93cc2b0b88bcc02f8a15d80b8a75d61d0cb24a.tar.gz
demo: add a demo for blend modes
After introducing the CSS blend mode enum values and including the background-blend-mode CSS property, it is very important to actually provide an example of the new feature. This patch adds a new demo to gtk3-demo which shows how the background-blend-mode CSS property works. https://bugzilla.gnome.org/show_bug.cgi?id=768305
Diffstat (limited to 'demos/gtk-demo/css_blendmodes.c')
-rw-r--r--demos/gtk-demo/css_blendmodes.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/demos/gtk-demo/css_blendmodes.c b/demos/gtk-demo/css_blendmodes.c
new file mode 100644
index 0000000000..4c4e6730a8
--- /dev/null
+++ b/demos/gtk-demo/css_blendmodes.c
@@ -0,0 +1,178 @@
+/* Theming/CSS Blend Modes
+ *
+ * You can blend multiple backgrounds using the CSS blend modes available.
+ */
+
+#include <gtk/gtk.h>
+
+#define WID(x) ((GtkWidget*) gtk_builder_get_object (builder, x))
+
+/*
+ * These are the available blend modes.
+ */
+struct {
+ gchar *name;
+ gchar *id;
+} blend_modes[] =
+{
+ { "Color", "color" },
+ { "Color (burn)", "color-burn" },
+ { "Color (dodge)", "color-dodge" },
+ { "Darken", "darken" },
+ { "Difference", "difference" },
+ { "Exclusion", "exclusion" },
+ { "Hard Light", "hard-light" },
+ { "Hue", "hue" },
+ { "Lighten", "lighten" },
+ { "Luminosity", "luminosity" },
+ { "Multiply", "multiply" },
+ { "Normal", "normal" },
+ { "Overlay", "overlay" },
+ { "Saturate", "saturate" },
+ { "Screen", "screen" },
+ { "Soft Light", "soft-light" },
+ { NULL }
+};
+
+/*
+ * The CSS class to be applied in the blended image. Notice that the first %s
+ * is replaced by the content of css_blendmodes.css and the second %s is
+ * replaced by the blend mode.
+ */
+static const gchar *CSS_TEMPLATE =
+"%s\n"
+"\n"
+"image.blend0 {\n"
+" background-image: url('resource://css_blendmodes/ducky.png'),\n"
+" linear-gradient(to right, red 0%, green 50%, blue 100%);\n"
+" background-size: cover;\n"
+" background-blend-mode: %s;\n"
+" min-width: 200px;\n"
+" min-height: 200px;\n"
+"}\n"
+"\n"
+"image.blend1 {\n"
+" background: url('resource://css_blendmodes/blends.png') top center,\n"
+" url('resource://css_blendmodes/blends.png') bottom center;\n"
+" background-blend-mode: %s;\n"
+" min-width: 200px;\n"
+" min-height: 200px;\n"
+"}\n"
+"\n"
+"image.blend2 {\n"
+" background: url('resource://css_blendmodes/cmy.jpg') top center,\n"
+" url('resource://css_blendmodes/cmy.jpg') center center,\n"
+" url('resource://css_blendmodes/cmy.jpg') bottom center;\n"
+" background-blend-mode: %s;\n"
+" min-width: 200px;\n"
+" min-height: 200px;\n"
+"}\n";
+
+static void
+update_css_for_blend_mode (GtkCssProvider *provider,
+ const gchar *blend_mode)
+{
+ GBytes *bytes;
+ gchar *css;
+
+ bytes = g_resources_lookup_data ("/css_blendmodes/css_blendmodes.css", 0, NULL);
+
+ css = g_strdup_printf (CSS_TEMPLATE,
+ (gchar*) g_bytes_get_data (bytes, NULL),
+ blend_mode,
+ blend_mode,
+ blend_mode);
+
+ gtk_css_provider_load_from_data (provider, css, -1, NULL);
+
+ g_bytes_unref (bytes);
+ g_free (css);
+}
+
+static void
+row_activated (GtkListBox *listbox,
+ GtkListBoxRow *row,
+ GtkCssProvider *provider)
+{
+ const gchar *blend_mode;
+
+ blend_mode = blend_modes[gtk_list_box_row_get_index (row)].id;
+
+ update_css_for_blend_mode (provider, blend_mode);
+}
+
+static void
+setup_listbox (GtkBuilder *builder,
+ GtkStyleProvider *provider)
+{
+ GtkWidget *normal_row;
+ GtkWidget *listbox;
+ gint i;
+
+ normal_row = NULL;
+ listbox = gtk_list_box_new ();
+ gtk_container_add (GTK_CONTAINER (WID ("scrolledwindow")), listbox);
+
+ g_signal_connect (listbox, "row-activated", G_CALLBACK (row_activated), provider);
+
+ /* Add a row for each blend mode available */
+ for (i = 0; blend_modes[i].name != NULL; i++)
+ {
+ GtkWidget *label;
+ GtkWidget *row;
+
+ row = gtk_list_box_row_new ();
+ label = g_object_new (GTK_TYPE_LABEL,
+ "label", blend_modes[i].name,
+ "xalign", 0.0,
+ NULL);
+
+ gtk_container_add (GTK_CONTAINER (row), label);
+
+ gtk_container_add (GTK_CONTAINER (listbox), row);
+
+ /* The first selected row is "normal" */
+ if (g_strcmp0 (blend_modes[i].id, "normal") == 0)
+ normal_row = row;
+ }
+
+ /* Select the "normal" row */
+ gtk_list_box_select_row (GTK_LIST_BOX (listbox), GTK_LIST_BOX_ROW (normal_row));
+ g_signal_emit_by_name (G_OBJECT (normal_row), "activate");
+
+ gtk_widget_grab_focus (normal_row);
+}
+
+GtkWidget *
+do_css_blendmodes (GtkWidget *do_widget)
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ GtkStyleProvider *provider;
+ GtkBuilder *builder;
+
+ builder = gtk_builder_new_from_resource ("/css_blendmodes/blendmodes.ui");
+
+ window = WID ("window");
+ gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
+
+ /* Setup the CSS provider for window */
+ provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+
+ gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+ provider,
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ setup_listbox (builder, provider);
+ }
+
+ if (!gtk_widget_get_visible (window))
+ gtk_widget_show_all (window);
+ else
+ gtk_widget_destroy (window);
+
+ return window;
+}