1/* Theming/CSS Basics
2 *
3 * GTK themes are written using CSS. Every widget is build of multiple items
4 * that you can style very similarly to a regular website.
5 */
6
7#include <gtk/gtk.h>
8
9static void
10show_parsing_error (GtkCssProvider *provider,
11 GtkCssSection *section,
12 const GError *error,
13 GtkTextBuffer *buffer)
14{
15 const GtkCssLocation *start_location, *end_location;
16 GtkTextIter start, end;
17 const char *tag_name;
18
19 start_location = gtk_css_section_get_start_location (section);
20 gtk_text_buffer_get_iter_at_line_index (buffer,
21 iter: &start,
22 line_number: start_location->lines,
23 byte_index: start_location->line_bytes);
24 end_location = gtk_css_section_get_end_location (section);
25 gtk_text_buffer_get_iter_at_line_index (buffer,
26 iter: &end,
27 line_number: end_location->lines,
28 byte_index: end_location->line_bytes);
29
30 if (error->domain == GTK_CSS_PARSER_WARNING)
31 tag_name = "warning";
32 else
33 tag_name = "error";
34
35 gtk_text_buffer_apply_tag_by_name (buffer, name: tag_name, start: &start, end: &end);
36}
37
38static void
39css_text_changed (GtkTextBuffer *buffer,
40 GtkCssProvider *provider)
41{
42 GtkTextIter start, end;
43 char *text;
44
45 gtk_text_buffer_get_start_iter (buffer, iter: &start);
46 gtk_text_buffer_get_end_iter (buffer, iter: &end);
47 gtk_text_buffer_remove_all_tags (buffer, start: &start, end: &end);
48
49 text = gtk_text_buffer_get_text (buffer, start: &start, end: &end, FALSE);
50 gtk_css_provider_load_from_data (css_provider: provider, data: text, length: -1);
51 g_free (mem: text);
52}
53
54static void
55apply_css (GtkWidget *widget, GtkStyleProvider *provider)
56{
57 GtkWidget *child;
58
59 gtk_style_context_add_provider (context: gtk_widget_get_style_context (widget), provider, G_MAXUINT);
60 for (child = gtk_widget_get_first_child (widget);
61 child != NULL;
62 child = gtk_widget_get_next_sibling (widget: child))
63 apply_css (widget: child, provider);
64}
65
66GtkWidget *
67do_css_basics (GtkWidget *do_widget)
68{
69 static GtkWidget *window = NULL;
70
71 if (!window)
72 {
73 GtkWidget *container, *child;
74 GtkStyleProvider *provider;
75 GtkTextBuffer *text;
76 GBytes *bytes;
77
78 window = gtk_window_new ();
79 gtk_window_set_title (GTK_WINDOW (window), title: "CSS Basics");
80 gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
81 gtk_window_set_default_size (GTK_WINDOW (window), width: 400, height: 300);
82 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
83
84 text = gtk_text_buffer_new (NULL);
85 gtk_text_buffer_create_tag (buffer: text,
86 tag_name: "warning",
87 first_property_name: "underline", PANGO_UNDERLINE_SINGLE,
88 NULL);
89 gtk_text_buffer_create_tag (buffer: text,
90 tag_name: "error",
91 first_property_name: "underline", PANGO_UNDERLINE_ERROR,
92 NULL);
93
94 provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
95
96 container = gtk_scrolled_window_new ();
97 gtk_window_set_child (GTK_WINDOW (window), child: container);
98 child = gtk_text_view_new_with_buffer (buffer: text);
99 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (container), child);
100 g_signal_connect (text, "changed",
101 G_CALLBACK (css_text_changed), provider);
102
103 bytes = g_resources_lookup_data (path: "/css_basics/css_basics.css", lookup_flags: 0, NULL);
104 gtk_text_buffer_set_text (buffer: text, text: g_bytes_get_data (bytes, NULL), len: g_bytes_get_size (bytes));
105 g_bytes_unref (bytes);
106
107 g_signal_connect (provider,
108 "parsing-error",
109 G_CALLBACK (show_parsing_error),
110 gtk_text_view_get_buffer (GTK_TEXT_VIEW (child)));
111
112 apply_css (widget: window, provider);
113 }
114
115 if (!gtk_widget_get_visible (widget: window))
116 gtk_widget_show (widget: window);
117 else
118 gtk_window_destroy (GTK_WINDOW (window));
119
120 return window;
121}
122

source code of gtk/demos/gtk-demo/css_basics.c