]> Pileus Git - ~andy/gtk/blob - gtk/gtkcsssection.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkcsssection.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include "gtkcsssectionprivate.h"
21
22 #include "gtkcssparserprivate.h"
23
24 /**
25  * GtkCssSection:
26  *
27  * Defines a part of a CSS document. Because sections are nested into
28  * one another, you can use gtk_css_section_get_parent() to get the
29  * containing region.
30  *
31  * Since: 3.2
32  */
33
34 struct _GtkCssSection
35 {
36   volatile gint       ref_count;
37   GtkCssSectionType   section_type;
38   GtkCssSection      *parent;
39   GFile              *file;
40   guint               start_line;
41   guint               start_position;
42   GtkCssParser       *parser;         /* parser if section isn't finished parsing yet or %NULL */
43   guint               end_line;       /* end line if parser is %NULL */
44   guint               end_position;   /* end position if parser is %NULL */
45 };
46
47 G_DEFINE_BOXED_TYPE (GtkCssSection, gtk_css_section, gtk_css_section_ref, gtk_css_section_unref)
48
49 GtkCssSection *
50 _gtk_css_section_new (GtkCssSection     *parent,
51                       GtkCssSectionType  type,
52                       GtkCssParser      *parser)
53 {
54   GtkCssSection *section;
55
56   g_return_val_if_fail (parser != NULL, NULL);
57
58   section = g_slice_new0 (GtkCssSection);
59
60   section->ref_count = 1;
61   section->section_type = type;
62   if (parent)
63     section->parent = gtk_css_section_ref (parent);
64   section->file = _gtk_css_parser_get_file (parser);
65   if (section->file)
66     g_object_ref (section->file);
67   section->start_line = _gtk_css_parser_get_line (parser);
68   section->start_position = _gtk_css_parser_get_position (parser);
69   section->parser = parser;
70
71   return section;
72 }
73
74 GtkCssSection *
75 _gtk_css_section_new_for_file (GtkCssSectionType  type,
76                                GFile             *file)
77 {
78   GtkCssSection *section;
79
80   g_return_val_if_fail (G_IS_FILE (file), NULL);
81
82   section = g_slice_new0 (GtkCssSection);
83
84   section->ref_count = 1;
85   section->section_type = type;
86   section->file = g_object_ref (file);
87
88   return section;
89 }
90
91 void
92 _gtk_css_section_end (GtkCssSection *section)
93 {
94   g_return_if_fail (section != NULL);
95   g_return_if_fail (section->parser != NULL);
96
97   section->end_line = _gtk_css_parser_get_line (section->parser);
98   section->end_position = _gtk_css_parser_get_position (section->parser);
99   section->parser = NULL;
100 }
101
102 /**
103  * gtk_css_section_ref:
104  * @section: a #GtkCssSection
105  *
106  * Increments the reference count on @section.
107  *
108  * Returns: @section itself.
109  *
110  * Since: 3.2
111  **/
112 GtkCssSection *
113 gtk_css_section_ref (GtkCssSection *section)
114 {
115   g_return_val_if_fail (section != NULL, NULL);
116
117   g_atomic_int_add (&section->ref_count, 1);
118
119   return section;
120 }
121
122 /**
123  * gtk_css_section_unref:
124  * @section: a #GtkCssSection
125  *
126  * Decrements the reference count on @section, freeing the
127  * structure if the reference count reaches 0.
128  *
129  * Since: 3.2
130  **/
131 void
132 gtk_css_section_unref (GtkCssSection *section)
133 {
134   g_return_if_fail (section != NULL);
135
136   if (!g_atomic_int_dec_and_test (&section->ref_count))
137     return;
138
139   if (section->parent)
140     gtk_css_section_unref (section->parent);
141   if (section->file)
142     g_object_unref (section->file);
143
144   g_slice_free (GtkCssSection, section);
145 }
146
147 /**
148  * gtk_css_section_get_section_type:
149  * @section: the section
150  *
151  * Gets the type of information that @section describes.
152  *
153  * Returns: the type of @section
154  *
155  * Since: 3.2
156  **/
157 GtkCssSectionType
158 gtk_css_section_get_section_type (const GtkCssSection *section)
159 {
160   g_return_val_if_fail (section != NULL, GTK_CSS_SECTION_DOCUMENT);
161
162   return section->section_type;
163 }
164
165 /**
166  * gtk_css_section_get_parent:
167  * @section: the section
168  *
169  * Gets the parent section for the given @section. The parent section is
170  * the section that contains this @section. A special case are sections of
171  * type #GTK_CSS_SECTION_DOCUMENT. Their parent will either be %NULL
172  * if they are the original CSS document that was loaded by
173  * gtk_css_provider_load_from_file() or a section of type
174  * #GTK_CSS_SECTION_IMPORT if it was loaded with an import rule from
175  * a different file.
176  *
177  * Returns: the parent section or %NULL if none
178  *
179  * Since: 3.2
180  **/
181 GtkCssSection *
182 gtk_css_section_get_parent (const GtkCssSection *section)
183 {
184   g_return_val_if_fail (section != NULL, NULL);
185
186   return section->parent;
187 }
188
189 /**
190  * gtk_css_section_get_file:
191  * @section: the section
192  *
193  * Gets the file that @section was parsed from. If no such file exists,
194  * for example because the CSS was loaded via
195  * @gtk_css_provider_load_from_data(), then %NULL is returned.
196  *
197  * Returns: (transfer none): the #GFile that @section was parsed from
198  *     or %NULL if @section was parsed from other data
199  *
200  * Since: 3.2
201  **/
202 GFile *
203 gtk_css_section_get_file (const GtkCssSection *section)
204 {
205   g_return_val_if_fail (section != NULL, NULL);
206
207   return section->file;
208 }
209
210 /**
211  * gtk_css_section_get_start_line:
212  * @section: the section
213  *
214  * Returns the line in the CSS document where this section starts.
215  * The line number is 0-indexed, so the first line of the document
216  * will return 0.
217  *
218  * Returns: the line number
219  *
220  * Since: 3.2
221  **/
222 guint
223 gtk_css_section_get_start_line (const GtkCssSection *section)
224 {
225   g_return_val_if_fail (section != NULL, 0);
226
227   return section->start_line;
228 }
229
230 /**
231  * gtk_css_section_get_start_position:
232  * @section: the section
233  *
234  * Returns the offset in bytes from the start of the current line
235  * returned via gtk_css_section_get_start_line().
236  *
237  * Returns: the offset in bytes from the start of the line.
238  *
239  * Since: 3.2
240  **/
241 guint
242 gtk_css_section_get_start_position (const GtkCssSection *section)
243 {
244   g_return_val_if_fail (section != NULL, 0);
245
246   return section->start_position;
247 }
248
249 /**
250  * gtk_css_section_get_end_line:
251  * @section: the section
252  *
253  * Returns the line in the CSS document where this section end.
254  * The line number is 0-indexed, so the first line of the document
255  * will return 0.
256  * This value may change in future invocations of this function if
257  * @section is not yet parsed completely. This will for example 
258  * happen in the GtkCssProvider::parsing-error signal.
259  * The end position and line may be identical to the start
260  * position and line for sections which failed to parse anything
261  * successfully.
262  *
263  * Returns: the line number
264  *
265  * Since: 3.2
266  **/
267 guint
268 gtk_css_section_get_end_line (const GtkCssSection *section)
269 {
270   g_return_val_if_fail (section != NULL, 0);
271
272   if (section->parser)
273     return _gtk_css_parser_get_line (section->parser);
274   else
275     return section->end_line;
276 }
277
278 /**
279  * gtk_css_section_get_end_position:
280  * @section: the section
281  *
282  * Returns the offset in bytes from the start of the current line
283  * returned via gtk_css_section_get_end_line().
284  * This value may change in future invocations of this function if
285  * @section is not yet parsed completely. This will for example
286  * happen in the GtkCssProvider::parsing-error signal.
287  * The end position and line may be identical to the start
288  * position and line for sections which failed to parse anything
289  * successfully.
290  *
291  * Returns: the offset in bytes from the start of the line.
292  *
293  * Since: 3.2
294  **/
295 guint
296 gtk_css_section_get_end_position (const GtkCssSection *section)
297 {
298   g_return_val_if_fail (section != NULL, 0);
299
300   if (section->parser)
301     return _gtk_css_parser_get_position (section->parser);
302   else
303     return section->end_position;
304 }
305
306 void
307 _gtk_css_section_print (const GtkCssSection  *section,
308                         GString              *string)
309 {
310   if (section->file)
311     {
312       GFileInfo *info;
313
314       info = g_file_query_info (section->file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL);
315
316       if (info)
317         {
318           g_string_append (string, g_file_info_get_display_name (info));
319           g_object_unref (info);
320         }
321       else
322         {
323           g_string_append (string, "<broken file>");
324         }
325     }
326   else
327     {
328       g_string_append (string, "<data>");
329     }
330
331   g_string_append_printf (string, ":%u:%u", 
332                           gtk_css_section_get_end_line (section) + 1,
333                           gtk_css_section_get_end_position (section));
334 }
335
336 char *
337 _gtk_css_section_to_string (const GtkCssSection *section)
338 {
339   GString *string;
340
341   g_return_val_if_fail (section != NULL, NULL);
342
343   string = g_string_new (NULL);
344   _gtk_css_section_print (section, string);
345
346   return g_string_free (string, FALSE);
347 }