]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/css_multiplebgs.c
gtk-demo: Don't use aliases for filenames
[~andy/gtk] / demos / gtk-demo / css_multiplebgs.c
1 /* CSS Theming/Multiple Backgrounds :: css_multiplebgs.css
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
8 #include <gtk/gtk.h>
9
10 static GtkWidget *window = NULL;
11
12 static void
13 show_parsing_error (GtkCssProvider *provider,
14                     GtkCssSection  *section,
15                     const GError   *error,
16                     GtkTextBuffer  *buffer)
17 {
18   GtkTextIter start, end;
19   const char *tag_name;
20
21   gtk_text_buffer_get_iter_at_line_index (buffer,
22                                           &start,
23                                           gtk_css_section_get_start_line (section),
24                                           gtk_css_section_get_start_position (section));
25   gtk_text_buffer_get_iter_at_line_index (buffer,
26                                           &end,
27                                           gtk_css_section_get_end_line (section),
28                                           gtk_css_section_get_end_position (section));
29
30   if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
31     tag_name = "warning";
32   else
33     tag_name = "error";
34
35   gtk_text_buffer_apply_tag_by_name (buffer, tag_name, &start, &end);
36 }
37                     
38 static void
39 css_text_changed (GtkTextBuffer  *buffer,
40                   GtkCssProvider *provider)
41 {
42   GtkTextIter start, end;
43   char *text;
44
45   gtk_text_buffer_get_start_iter (buffer, &start);
46   gtk_text_buffer_get_end_iter (buffer, &end);
47   gtk_text_buffer_remove_all_tags (buffer, &start, &end);
48
49   text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
50   gtk_css_provider_load_from_data (provider, text, -1, NULL);
51   g_free (text);
52
53   gtk_style_context_reset_widgets (gdk_screen_get_default ());
54 }
55
56 static gboolean
57 drawing_area_draw (GtkWidget *widget,
58                    cairo_t *cr)
59 {
60   GtkStyleContext *context = gtk_widget_get_style_context (widget);
61
62   gtk_render_background (context, cr,
63                          0, 0,
64                          gtk_widget_get_allocated_width (widget),
65                          gtk_widget_get_allocated_height (widget));
66   gtk_render_frame (context, cr,
67                     0, 0,
68                     gtk_widget_get_allocated_width (widget),
69                     gtk_widget_get_allocated_height (widget));
70
71   return FALSE;
72 }
73
74 static void
75 apply_css (GtkWidget *widget, GtkStyleProvider *provider)
76 {
77   gtk_style_context_add_provider (gtk_widget_get_style_context (widget), provider, G_MAXUINT);
78   if (GTK_IS_CONTAINER (widget))
79     gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback) apply_css, provider);
80 }
81
82 GtkWidget *
83 do_css_multiplebgs (GtkWidget *do_widget)
84 {
85   if (!window)
86     {
87       GtkWidget *paned, *container, *child;
88       GtkStyleProvider *provider;
89       GtkTextBuffer *text;
90       GBytes *bytes;
91
92       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
93       gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
94       gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
95       g_signal_connect (window, "destroy",
96                         G_CALLBACK (gtk_widget_destroyed), &window);
97
98       container = gtk_overlay_new ();
99       gtk_widget_add_events (container,
100                              GDK_ENTER_NOTIFY_MASK |
101                              GDK_LEAVE_NOTIFY_MASK |
102                              GDK_POINTER_MOTION_MASK);
103       gtk_container_add (GTK_CONTAINER (window), container);
104
105       child = gtk_drawing_area_new ();
106       gtk_widget_set_name (child, "canvas");
107       g_signal_connect (child, "draw",
108                         G_CALLBACK (drawing_area_draw), NULL);
109       gtk_container_add (GTK_CONTAINER (container), child);
110
111       child = gtk_button_new ();
112       gtk_widget_add_events (child,
113                              GDK_ENTER_NOTIFY_MASK |
114                              GDK_LEAVE_NOTIFY_MASK |
115                              GDK_POINTER_MOTION_MASK);
116       gtk_overlay_add_overlay (GTK_OVERLAY (container), child);
117       gtk_widget_set_name (child, "bricks-button");
118       gtk_widget_set_halign (child, GTK_ALIGN_CENTER);
119       gtk_widget_set_valign (child, GTK_ALIGN_CENTER);
120       gtk_widget_set_size_request (child, 200, 80);
121
122       paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
123       gtk_overlay_add_overlay (GTK_OVERLAY (container), paned);
124
125       /* Need a filler so we get a handle */
126       child = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
127       gtk_container_add (GTK_CONTAINER (paned), child);
128
129       text = gtk_text_buffer_new (NULL);
130       gtk_text_buffer_create_tag (text,
131                                   "warning",
132                                   "underline", PANGO_UNDERLINE_SINGLE,
133                                   NULL);
134       gtk_text_buffer_create_tag (text,
135                                   "error",
136                                   "underline", PANGO_UNDERLINE_ERROR,
137                                   NULL);
138
139       provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
140
141       container = gtk_scrolled_window_new (NULL, NULL);
142       gtk_container_add (GTK_CONTAINER (paned), container);
143       child = gtk_text_view_new_with_buffer (text);
144       gtk_container_add (GTK_CONTAINER (container), child);
145       g_signal_connect (text,
146                         "changed",
147                         G_CALLBACK (css_text_changed),
148                         provider);
149
150       bytes = g_resources_lookup_data ("/css_multiplebgs/css_multiplebgs.css", 0, NULL);
151       gtk_text_buffer_set_text (text, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes));
152       g_bytes_unref (bytes);
153
154       g_signal_connect (provider,
155                         "parsing-error",
156                         G_CALLBACK (show_parsing_error),
157                         gtk_text_view_get_buffer (GTK_TEXT_VIEW (child)));
158
159       apply_css (window, provider);
160     }
161
162   if (!gtk_widget_get_visible (window))
163     gtk_widget_show_all (window);
164   else
165     {
166       gtk_widget_destroy (window);
167       window = NULL;
168     }
169
170   return window;
171 }