| File: | ctk/ctkcssnode.c |
| Warning: | line 187, column 1 Potential memory leak |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* CTK - The GIMP Toolkit | |||
| 2 | * Copyright (C) 2014 Benjamin Otte <otte@gnome.org> | |||
| 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 "ctkcssnodeprivate.h" | |||
| 21 | ||||
| 22 | #include "ctkcssanimatedstyleprivate.h" | |||
| 23 | #include "ctkcsssectionprivate.h" | |||
| 24 | #include "ctkcssstylepropertyprivate.h" | |||
| 25 | #include "ctkintl.h" | |||
| 26 | #include "ctkmarshalers.h" | |||
| 27 | #include "ctksettingsprivate.h" | |||
| 28 | #include "ctktypebuiltins.h" | |||
| 29 | ||||
| 30 | /* | |||
| 31 | * CSS nodes are the backbone of the CtkStyleContext implementation and | |||
| 32 | * replace the role that CtkWidgetPath played in the past. A CSS node has | |||
| 33 | * an element name and a state, and can have an id and style classes, which | |||
| 34 | * is what is needed to determine the matching CSS selectors. CSS nodes have | |||
| 35 | * a 'visible' property, which makes it possible to temporarily 'hide' them | |||
| 36 | * from CSS matching - e.g. an invisible node will not affect :nth-child | |||
| 37 | * matching and so forth. | |||
| 38 | * | |||
| 39 | * The API to manage states, names, ids and classes of CSS nodes is: | |||
| 40 | * - ctk_css_node_get/set_state. States are represented as CtkStateFlags | |||
| 41 | * - ctk_css_node_get/set_name. Names are represented as interned strings | |||
| 42 | * - ctk_css_node_get/set_id. Ids are represented as interned strings | |||
| 43 | * - ctk_css_node_add/remove/has_class and ctk_css_node_list_classes. Style | |||
| 44 | * classes are represented as quarks. | |||
| 45 | * | |||
| 46 | * CSS nodes are organized in a dom-like tree, and there is API to navigate | |||
| 47 | * and manipulate this tree: | |||
| 48 | * - ctk_css_node_set_parent | |||
| 49 | * - ctk_css_node_insert_before/after | |||
| 50 | * - ctk_css_node_get_parent | |||
| 51 | * - ctk_css_node_get_first/last_child | |||
| 52 | * - ctk_css_node_get_previous/next_sibling | |||
| 53 | * Note that parents keep a reference on their children in this tree. | |||
| 54 | * | |||
| 55 | * Every widget has one or more CSS nodes - the first one gets created | |||
| 56 | * automatically by CtkStyleContext. To set the name of the main node, | |||
| 57 | * call ctk_widget_class_set_css_name() in class_init(). Widget implementations | |||
| 58 | * can and should add subnodes as suitable. | |||
| 59 | * | |||
| 60 | * Best practice is: | |||
| 61 | * - For permanent subnodes, create them in init(), and keep a pointer | |||
| 62 | * to the node (you don't have to keep a reference, cleanup will be | |||
| 63 | * automatic by means of the parent node getting cleaned up by the | |||
| 64 | * style context). | |||
| 65 | * - For transient nodes, create/destroy them when the conditions that | |||
| 66 | * warrant their existence change. | |||
| 67 | * - Keep the state of all your nodes up-to-date. This probably requires | |||
| 68 | * a ::state-flags-changed (and possibly ::direction-changed) handler, | |||
| 69 | * as well as code to update the state in other places. Note that CTK+ | |||
| 70 | * does this automatically for the widget's main CSS node. | |||
| 71 | * - The sibling ordering in the CSS node tree is supposed to correspond | |||
| 72 | * to the visible order of content: top-to-bottom and left-to-right. | |||
| 73 | * Reorder your nodes to maintain this correlation. In particular for | |||
| 74 | * horizontally layed out widgets, this will require listening to | |||
| 75 | * ::direction-changed. | |||
| 76 | * - The draw function should just use ctk_style_context_save_to_node() to | |||
| 77 | * 'switch' to the right node, not make any other changes to the style | |||
| 78 | * context. | |||
| 79 | * | |||
| 80 | * A noteworthy difference between ctk_style_context_save() and | |||
| 81 | * ctk_style_context_save_to_node() is that the former inherits all the | |||
| 82 | * style classes from the main CSS node, which often leads to unintended | |||
| 83 | * inheritance. | |||
| 84 | */ | |||
| 85 | ||||
| 86 | /* When these change we do a full restyling. Otherwise we try to figure out | |||
| 87 | * if we need to change things. */ | |||
| 88 | #define CTK_CSS_RADICAL_CHANGE((1ULL << 2) | (1ULL << 1) | (1ULL << 0) | ( 1ULL << 32) | (1ULL << 33)) (CTK_CSS_CHANGE_ID(1ULL << 2) | CTK_CSS_CHANGE_NAME(1ULL << 1) | CTK_CSS_CHANGE_CLASS(1ULL << 0) | CTK_CSS_CHANGE_SOURCE(1ULL << 32) | CTK_CSS_CHANGE_PARENT_STYLE(1ULL << 33)) | |||
| 89 | ||||
| 90 | G_DEFINE_TYPE (CtkCssNode, ctk_css_node, G_TYPE_OBJECT)static void ctk_css_node_init (CtkCssNode *self); static void ctk_css_node_class_init (CtkCssNodeClass *klass); static GType ctk_css_node_get_type_once (void); static gpointer ctk_css_node_parent_class = ((void*)0); static gint CtkCssNode_private_offset; static void ctk_css_node_class_intern_init (gpointer klass) { ctk_css_node_parent_class = g_type_class_peek_parent (klass); if (CtkCssNode_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkCssNode_private_offset ); ctk_css_node_class_init ((CtkCssNodeClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_css_node_get_instance_private (CtkCssNode *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkCssNode_private_offset)))); } GType ctk_css_node_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0)) ; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = ctk_css_node_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType ctk_css_node_get_type_once (void ) { GType g_define_type_id = g_type_register_static_simple (( (GType) ((20) << (2))), g_intern_static_string ("CtkCssNode" ), sizeof (CtkCssNodeClass), (GClassInitFunc)(void (*)(void)) ctk_css_node_class_intern_init, sizeof (CtkCssNode), (GInstanceInitFunc )(void (*)(void)) ctk_css_node_init, (GTypeFlags) 0); { {{};} } return g_define_type_id; } | |||
| 91 | ||||
| 92 | enum { | |||
| 93 | NODE_ADDED, | |||
| 94 | NODE_REMOVED, | |||
| 95 | STYLE_CHANGED, | |||
| 96 | LAST_SIGNAL | |||
| 97 | }; | |||
| 98 | ||||
| 99 | enum { | |||
| 100 | PROP_0, | |||
| 101 | PROP_CLASSES, | |||
| 102 | PROP_ID, | |||
| 103 | PROP_NAME, | |||
| 104 | PROP_STATE, | |||
| 105 | PROP_VISIBLE, | |||
| 106 | PROP_WIDGET_TYPE, | |||
| 107 | NUM_PROPERTIES | |||
| 108 | }; | |||
| 109 | ||||
| 110 | struct _CtkCssNodeStyleChange { | |||
| 111 | CtkCssStyle *old_style; | |||
| 112 | CtkCssStyle *new_style; | |||
| 113 | }; | |||
| 114 | ||||
| 115 | static guint cssnode_signals[LAST_SIGNAL] = { 0 }; | |||
| 116 | static GParamSpec *cssnode_properties[NUM_PROPERTIES]; | |||
| 117 | ||||
| 118 | static CtkStyleProviderPrivate * | |||
| 119 | ctk_css_node_get_style_provider_or_null (CtkCssNode *cssnode) | |||
| 120 | { | |||
| 121 | return CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->get_style_provider (cssnode); | |||
| 122 | } | |||
| 123 | ||||
| 124 | static void | |||
| 125 | ctk_css_node_set_invalid (CtkCssNode *node, | |||
| 126 | gboolean invalid) | |||
| 127 | { | |||
| 128 | if (node->invalid == invalid) | |||
| 129 | return; | |||
| 130 | ||||
| 131 | node->invalid = invalid; | |||
| 132 | ||||
| 133 | if (node->visible) | |||
| 134 | { | |||
| 135 | if (node->parent) | |||
| 136 | { | |||
| 137 | if (invalid) | |||
| 138 | ctk_css_node_set_invalid (node->parent, TRUE(!(0))); | |||
| 139 | } | |||
| 140 | else | |||
| 141 | { | |||
| 142 | if (invalid) | |||
| 143 | CTK_CSS_NODE_GET_CLASS (node)((((CtkCssNodeClass*) (((GTypeInstance*) ((node)))->g_class ))))->queue_validate (node); | |||
| 144 | else | |||
| 145 | CTK_CSS_NODE_GET_CLASS (node)((((CtkCssNodeClass*) (((GTypeInstance*) ((node)))->g_class ))))->dequeue_validate (node); | |||
| 146 | } | |||
| 147 | } | |||
| 148 | } | |||
| 149 | ||||
| 150 | static void | |||
| 151 | ctk_css_node_get_property (GObject *object, | |||
| 152 | guint property_id, | |||
| 153 | GValue *value, | |||
| 154 | GParamSpec *pspec) | |||
| 155 | { | |||
| 156 | CtkCssNode *cssnode = CTK_CSS_NODE (object)((((CtkCssNode*) (void *) g_type_check_instance_cast ((GTypeInstance *) (object), ((ctk_css_node_get_type ())))))); | |||
| 157 | ||||
| 158 | switch (property_id) | |||
| ||||
| 159 | { | |||
| 160 | case PROP_CLASSES: | |||
| 161 | g_value_take_boxed (value, ctk_css_node_get_classes (cssnode)); | |||
| 162 | break; | |||
| 163 | ||||
| 164 | case PROP_ID: | |||
| 165 | g_value_set_string (value, ctk_css_node_get_id (cssnode)); | |||
| 166 | break; | |||
| 167 | ||||
| 168 | case PROP_NAME: | |||
| 169 | g_value_set_string (value, ctk_css_node_get_name (cssnode)); | |||
| 170 | break; | |||
| 171 | ||||
| 172 | case PROP_STATE: | |||
| 173 | g_value_set_flags (value, ctk_css_node_get_state (cssnode)); | |||
| 174 | break; | |||
| 175 | ||||
| 176 | case PROP_VISIBLE: | |||
| 177 | g_value_set_boolean (value, ctk_css_node_get_visible (cssnode)); | |||
| 178 | break; | |||
| 179 | ||||
| 180 | case PROP_WIDGET_TYPE: | |||
| 181 | g_value_set_gtype (value, ctk_css_node_get_widget_type (cssnode)); | |||
| 182 | break; | |||
| 183 | ||||
| 184 | default: | |||
| 185 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec *_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id = ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'" , "ctkcssnode.c", 185, ("property"), _glib__property_id, _glib__pspec ->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) ( _glib__pspec))->g_class))->g_type)))), (g_type_name ((( (((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class ))->g_type)))))); } while (0); | |||
| 186 | } | |||
| 187 | } | |||
| ||||
| 188 | ||||
| 189 | static void | |||
| 190 | ctk_css_node_set_property (GObject *object, | |||
| 191 | guint property_id, | |||
| 192 | const GValue *value, | |||
| 193 | GParamSpec *pspec) | |||
| 194 | { | |||
| 195 | CtkCssNode *cssnode = CTK_CSS_NODE (object)((((CtkCssNode*) (void *) g_type_check_instance_cast ((GTypeInstance *) (object), ((ctk_css_node_get_type ())))))); | |||
| 196 | ||||
| 197 | switch (property_id) | |||
| 198 | { | |||
| 199 | case PROP_CLASSES: | |||
| 200 | ctk_css_node_set_classes (cssnode, g_value_get_boxed (value)); | |||
| 201 | break; | |||
| 202 | ||||
| 203 | case PROP_ID: | |||
| 204 | ctk_css_node_set_id (cssnode, g_value_get_string (value)); | |||
| 205 | break; | |||
| 206 | ||||
| 207 | case PROP_NAME: | |||
| 208 | ctk_css_node_set_name (cssnode, g_value_get_string (value)); | |||
| 209 | break; | |||
| 210 | ||||
| 211 | case PROP_STATE: | |||
| 212 | ctk_css_node_set_state (cssnode, g_value_get_flags (value)); | |||
| 213 | break; | |||
| 214 | ||||
| 215 | case PROP_VISIBLE: | |||
| 216 | ctk_css_node_set_visible (cssnode, g_value_get_boolean (value)); | |||
| 217 | break; | |||
| 218 | ||||
| 219 | case PROP_WIDGET_TYPE: | |||
| 220 | ctk_css_node_set_widget_type (cssnode, g_value_get_gtype (value)); | |||
| 221 | break; | |||
| 222 | ||||
| 223 | default: | |||
| 224 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec *_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id = ((property_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'" , "ctkcssnode.c", 224, ("property"), _glib__property_id, _glib__pspec ->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) ( _glib__pspec))->g_class))->g_type)))), (g_type_name ((( (((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class ))->g_type)))))); } while (0); | |||
| 225 | } | |||
| 226 | } | |||
| 227 | ||||
| 228 | static void | |||
| 229 | ctk_css_node_dispose (GObject *object) | |||
| 230 | { | |||
| 231 | CtkCssNode *cssnode = CTK_CSS_NODE (object)((((CtkCssNode*) (void *) g_type_check_instance_cast ((GTypeInstance *) (object), ((ctk_css_node_get_type ())))))); | |||
| 232 | ||||
| 233 | while (cssnode->first_child) | |||
| 234 | { | |||
| 235 | ctk_css_node_set_parent (cssnode->first_child, NULL((void*)0)); | |||
| 236 | } | |||
| 237 | ||||
| 238 | ctk_css_node_set_invalid (cssnode, FALSE(0)); | |||
| 239 | ||||
| 240 | g_clear_pointer (&cssnode->cache, ctk_css_node_style_cache_unref)do { _Static_assert (sizeof *(&cssnode->cache) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((& cssnode->cache)) _pp = (&cssnode->cache); __typeof__ (*(&cssnode->cache)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (ctk_css_node_style_cache_unref) (_ptr); } while (0); | |||
| 241 | ||||
| 242 | G_OBJECT_CLASS (ctk_css_node_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_css_node_parent_class)), (((GType) ((20) << (2 ))))))))->dispose (object); | |||
| 243 | } | |||
| 244 | ||||
| 245 | static void | |||
| 246 | ctk_css_node_finalize (GObject *object) | |||
| 247 | { | |||
| 248 | CtkCssNode *cssnode = CTK_CSS_NODE (object)((((CtkCssNode*) (void *) g_type_check_instance_cast ((GTypeInstance *) (object), ((ctk_css_node_get_type ())))))); | |||
| 249 | ||||
| 250 | if (cssnode->style) | |||
| 251 | g_object_unref (cssnode->style); | |||
| 252 | ctk_css_node_declaration_unref (cssnode->decl); | |||
| 253 | ||||
| 254 | G_OBJECT_CLASS (ctk_css_node_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_css_node_parent_class)), (((GType) ((20) << (2 ))))))))->finalize (object); | |||
| 255 | } | |||
| 256 | ||||
| 257 | static gboolean | |||
| 258 | ctk_css_node_is_first_child (CtkCssNode *node) | |||
| 259 | { | |||
| 260 | CtkCssNode *iter; | |||
| 261 | ||||
| 262 | for (iter = node->previous_sibling; | |||
| 263 | iter != NULL((void*)0); | |||
| 264 | iter = iter->previous_sibling) | |||
| 265 | { | |||
| 266 | if (iter->visible) | |||
| 267 | return FALSE(0); | |||
| 268 | } | |||
| 269 | return TRUE(!(0)); | |||
| 270 | } | |||
| 271 | ||||
| 272 | static gboolean | |||
| 273 | ctk_css_node_is_last_child (CtkCssNode *node) | |||
| 274 | { | |||
| 275 | CtkCssNode *iter; | |||
| 276 | ||||
| 277 | for (iter = node->next_sibling; | |||
| 278 | iter != NULL((void*)0); | |||
| 279 | iter = iter->next_sibling) | |||
| 280 | { | |||
| 281 | if (iter->visible) | |||
| 282 | return FALSE(0); | |||
| 283 | } | |||
| 284 | return TRUE(!(0)); | |||
| 285 | } | |||
| 286 | ||||
| 287 | static gboolean | |||
| 288 | may_use_global_parent_cache (CtkCssNode *node) | |||
| 289 | { | |||
| 290 | CtkStyleProviderPrivate *provider; | |||
| 291 | CtkCssNode *parent; | |||
| 292 | ||||
| 293 | parent = ctk_css_node_get_parent (node); | |||
| 294 | if (parent == NULL((void*)0)) | |||
| 295 | return FALSE(0); | |||
| 296 | ||||
| 297 | provider = ctk_css_node_get_style_provider_or_null (node); | |||
| 298 | if (provider != NULL((void*)0) && provider != ctk_css_node_get_style_provider (parent)) | |||
| 299 | return FALSE(0); | |||
| 300 | ||||
| 301 | return TRUE(!(0)); | |||
| 302 | } | |||
| 303 | ||||
| 304 | static CtkCssStyle * | |||
| 305 | lookup_in_global_parent_cache (CtkCssNode *node, | |||
| 306 | const CtkCssNodeDeclaration *decl) | |||
| 307 | { | |||
| 308 | CtkCssNode *parent; | |||
| 309 | ||||
| 310 | parent = node->parent; | |||
| 311 | ||||
| 312 | if (parent == NULL((void*)0) || | |||
| 313 | !may_use_global_parent_cache (node)) | |||
| 314 | return NULL((void*)0); | |||
| 315 | ||||
| 316 | if (parent->cache == NULL((void*)0)) | |||
| 317 | return NULL((void*)0); | |||
| 318 | ||||
| 319 | g_assert (node->cache == NULL)do { if (node->cache == ((void*)0)) ; else g_assertion_message_expr ("Ctk", "ctkcssnode.c", 319, ((const char*) (__func__)), "node->cache == NULL" ); } while (0); | |||
| 320 | node->cache = ctk_css_node_style_cache_lookup (parent->cache, | |||
| 321 | decl, | |||
| 322 | ctk_css_node_is_first_child (node), | |||
| 323 | ctk_css_node_is_last_child (node)); | |||
| 324 | if (node->cache == NULL((void*)0)) | |||
| 325 | return NULL((void*)0); | |||
| 326 | ||||
| 327 | return ctk_css_node_style_cache_get_style (node->cache); | |||
| 328 | } | |||
| 329 | ||||
| 330 | static void | |||
| 331 | store_in_global_parent_cache (CtkCssNode *node, | |||
| 332 | const CtkCssNodeDeclaration *decl, | |||
| 333 | CtkCssStyle *style) | |||
| 334 | { | |||
| 335 | CtkCssNode *parent; | |||
| 336 | ||||
| 337 | g_assert (CTK_IS_CSS_STATIC_STYLE (style))do { if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) (style); GType __t = ((ctk_css_static_style_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } ))))) ; else g_assertion_message_expr ("Ctk", "ctkcssnode.c", 337, ((const char*) (__func__)), "CTK_IS_CSS_STATIC_STYLE (style)" ); } while (0); | |||
| 338 | ||||
| 339 | parent = node->parent; | |||
| 340 | ||||
| 341 | if (parent == NULL((void*)0) || | |||
| 342 | !may_use_global_parent_cache (node)) | |||
| 343 | return; | |||
| 344 | ||||
| 345 | if (parent->cache == NULL((void*)0)) | |||
| 346 | parent->cache = ctk_css_node_style_cache_new (parent->style); | |||
| 347 | ||||
| 348 | node->cache = ctk_css_node_style_cache_insert (parent->cache, | |||
| 349 | (CtkCssNodeDeclaration *) decl, | |||
| 350 | ctk_css_node_is_first_child (node), | |||
| 351 | ctk_css_node_is_last_child (node), | |||
| 352 | style); | |||
| 353 | } | |||
| 354 | ||||
| 355 | static CtkCssStyle * | |||
| 356 | ctk_css_node_create_style (CtkCssNode *cssnode) | |||
| 357 | { | |||
| 358 | const CtkCssNodeDeclaration *decl; | |||
| 359 | CtkCssMatcher matcher; | |||
| 360 | CtkCssStyle *parent; | |||
| 361 | CtkCssStyle *style; | |||
| 362 | ||||
| 363 | decl = ctk_css_node_get_declaration (cssnode); | |||
| 364 | parent = cssnode->parent ? cssnode->parent->style : NULL((void*)0); | |||
| 365 | ||||
| 366 | style = lookup_in_global_parent_cache (cssnode, decl); | |||
| 367 | if (style) | |||
| 368 | return g_object_ref (style)((__typeof__ (style)) (g_object_ref) (style)); | |||
| 369 | ||||
| 370 | if (ctk_css_node_init_matcher (cssnode, &matcher)) | |||
| 371 | style = ctk_css_static_style_new_compute (ctk_css_node_get_style_provider (cssnode), | |||
| 372 | &matcher, | |||
| 373 | parent); | |||
| 374 | else | |||
| 375 | style = ctk_css_static_style_new_compute (ctk_css_node_get_style_provider (cssnode), | |||
| 376 | NULL((void*)0), | |||
| 377 | parent); | |||
| 378 | ||||
| 379 | store_in_global_parent_cache (cssnode, decl, style); | |||
| 380 | ||||
| 381 | return style; | |||
| 382 | } | |||
| 383 | ||||
| 384 | static gboolean | |||
| 385 | should_create_transitions (CtkCssChange change) | |||
| 386 | { | |||
| 387 | return (change & CTK_CSS_CHANGE_ANIMATIONS(1ULL << 35)) == 0; | |||
| 388 | } | |||
| 389 | ||||
| 390 | static gboolean | |||
| 391 | ctk_css_style_needs_recreation (CtkCssStyle *style, | |||
| 392 | CtkCssChange change) | |||
| 393 | { | |||
| 394 | /* Try to avoid invalidating if we can */ | |||
| 395 | if (change & CTK_CSS_RADICAL_CHANGE((1ULL << 2) | (1ULL << 1) | (1ULL << 0) | ( 1ULL << 32) | (1ULL << 33))) | |||
| 396 | return TRUE(!(0)); | |||
| 397 | ||||
| 398 | if (CTK_IS_CSS_ANIMATED_STYLE (style)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( style); GType __t = ((ctk_css_animated_style_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) | |||
| 399 | style = CTK_CSS_ANIMATED_STYLE (style)((((CtkCssAnimatedStyle*) (void *) g_type_check_instance_cast ((GTypeInstance*) (style), ((ctk_css_animated_style_get_type ()))))))->style; | |||
| 400 | ||||
| 401 | if (ctk_css_static_style_get_change (CTK_CSS_STATIC_STYLE (style)((((CtkCssStaticStyle*) (void *) g_type_check_instance_cast ( (GTypeInstance*) (style), ((ctk_css_static_style_get_type ()) )))))) & change) | |||
| 402 | return TRUE(!(0)); | |||
| 403 | else | |||
| 404 | return FALSE(0); | |||
| 405 | } | |||
| 406 | ||||
| 407 | static CtkCssStyle * | |||
| 408 | ctk_css_node_real_update_style (CtkCssNode *cssnode, | |||
| 409 | CtkCssChange change, | |||
| 410 | gint64 timestamp, | |||
| 411 | CtkCssStyle *style) | |||
| 412 | { | |||
| 413 | CtkCssStyle *static_style, *new_static_style, *new_style; | |||
| 414 | ||||
| 415 | if (CTK_IS_CSS_ANIMATED_STYLE (style)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( style); GType __t = ((ctk_css_animated_style_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) | |||
| 416 | { | |||
| 417 | static_style = CTK_CSS_ANIMATED_STYLE (style)((((CtkCssAnimatedStyle*) (void *) g_type_check_instance_cast ((GTypeInstance*) (style), ((ctk_css_animated_style_get_type ()))))))->style; | |||
| 418 | } | |||
| 419 | else | |||
| 420 | { | |||
| 421 | static_style = style; | |||
| 422 | } | |||
| 423 | ||||
| 424 | if (ctk_css_style_needs_recreation (static_style, change)) | |||
| 425 | new_static_style = ctk_css_node_create_style (cssnode); | |||
| 426 | else | |||
| 427 | new_static_style = g_object_ref (static_style)((__typeof__ (static_style)) (g_object_ref) (static_style)); | |||
| 428 | ||||
| 429 | if (new_static_style != static_style || (change & CTK_CSS_CHANGE_ANIMATIONS(1ULL << 35))) | |||
| 430 | { | |||
| 431 | CtkCssNode *parent = ctk_css_node_get_parent (cssnode); | |||
| 432 | new_style = ctk_css_animated_style_new (new_static_style, | |||
| 433 | parent ? ctk_css_node_get_style (parent) : NULL((void*)0), | |||
| 434 | timestamp, | |||
| 435 | ctk_css_node_get_style_provider (cssnode), | |||
| 436 | should_create_transitions (change) ? style : NULL((void*)0)); | |||
| 437 | ||||
| 438 | /* Clear the cache again, the static style we looked up above | |||
| 439 | * may have populated it. */ | |||
| 440 | g_clear_pointer (&cssnode->cache, ctk_css_node_style_cache_unref)do { _Static_assert (sizeof *(&cssnode->cache) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((& cssnode->cache)) _pp = (&cssnode->cache); __typeof__ (*(&cssnode->cache)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (ctk_css_node_style_cache_unref) (_ptr); } while (0); | |||
| 441 | } | |||
| 442 | else if (static_style != style && (change & CTK_CSS_CHANGE_TIMESTAMP(1ULL << 34))) | |||
| 443 | { | |||
| 444 | new_style = ctk_css_animated_style_new_advance (CTK_CSS_ANIMATED_STYLE (style)((((CtkCssAnimatedStyle*) (void *) g_type_check_instance_cast ((GTypeInstance*) (style), ((ctk_css_animated_style_get_type ())))))), | |||
| 445 | static_style, | |||
| 446 | timestamp); | |||
| 447 | } | |||
| 448 | else | |||
| 449 | { | |||
| 450 | new_style = g_object_ref (style)((__typeof__ (style)) (g_object_ref) (style)); | |||
| 451 | } | |||
| 452 | ||||
| 453 | if (!ctk_css_style_is_static (new_style)) | |||
| 454 | ctk_css_node_set_invalid (cssnode, TRUE(!(0))); | |||
| 455 | ||||
| 456 | g_object_unref (new_static_style); | |||
| 457 | ||||
| 458 | return new_style; | |||
| 459 | } | |||
| 460 | ||||
| 461 | static void | |||
| 462 | ctk_css_node_real_invalidate (CtkCssNode *node G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 463 | { | |||
| 464 | } | |||
| 465 | ||||
| 466 | static void | |||
| 467 | ctk_css_node_real_queue_validate (CtkCssNode *node G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 468 | { | |||
| 469 | } | |||
| 470 | ||||
| 471 | static void | |||
| 472 | ctk_css_node_real_dequeue_validate (CtkCssNode *node G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 473 | { | |||
| 474 | } | |||
| 475 | ||||
| 476 | static void | |||
| 477 | ctk_css_node_real_validate (CtkCssNode *node G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 478 | { | |||
| 479 | } | |||
| 480 | ||||
| 481 | gboolean | |||
| 482 | ctk_css_node_real_init_matcher (CtkCssNode *cssnode, | |||
| 483 | CtkCssMatcher *matcher) | |||
| 484 | { | |||
| 485 | _ctk_css_matcher_node_init (matcher, cssnode); | |||
| 486 | ||||
| 487 | return TRUE(!(0)); | |||
| 488 | } | |||
| 489 | ||||
| 490 | static CtkWidgetPath * | |||
| 491 | ctk_css_node_real_create_widget_path (CtkCssNode *cssnode G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 492 | { | |||
| 493 | return ctk_widget_path_new (); | |||
| 494 | } | |||
| 495 | ||||
| 496 | static const CtkWidgetPath * | |||
| 497 | ctk_css_node_real_get_widget_path (CtkCssNode *cssnode G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 498 | { | |||
| 499 | return NULL((void*)0); | |||
| 500 | } | |||
| 501 | ||||
| 502 | static CtkStyleProviderPrivate * | |||
| 503 | ctk_css_node_real_get_style_provider (CtkCssNode *cssnode G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 504 | { | |||
| 505 | return NULL((void*)0); | |||
| 506 | } | |||
| 507 | ||||
| 508 | static CdkFrameClock * | |||
| 509 | ctk_css_node_real_get_frame_clock (CtkCssNode *cssnode G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 510 | { | |||
| 511 | return NULL((void*)0); | |||
| 512 | } | |||
| 513 | ||||
| 514 | static void | |||
| 515 | ctk_css_node_real_node_removed (CtkCssNode *parent G_GNUC_UNUSED__attribute__ ((__unused__)), | |||
| 516 | CtkCssNode *node, | |||
| 517 | CtkCssNode *previous G_GNUC_UNUSED__attribute__ ((__unused__))) | |||
| 518 | { | |||
| 519 | if (node->previous_sibling) | |||
| 520 | node->previous_sibling->next_sibling = node->next_sibling; | |||
| 521 | else | |||
| 522 | node->parent->first_child = node->next_sibling; | |||
| 523 | ||||
| 524 | if (node->next_sibling) | |||
| 525 | node->next_sibling->previous_sibling = node->previous_sibling; | |||
| 526 | else | |||
| 527 | node->parent->last_child = node->previous_sibling; | |||
| 528 | ||||
| 529 | node->previous_sibling = NULL((void*)0); | |||
| 530 | node->next_sibling = NULL((void*)0); | |||
| 531 | node->parent = NULL((void*)0); | |||
| 532 | } | |||
| 533 | ||||
| 534 | static void | |||
| 535 | ctk_css_node_real_node_added (CtkCssNode *parent, | |||
| 536 | CtkCssNode *node, | |||
| 537 | CtkCssNode *new_previous) | |||
| 538 | { | |||
| 539 | if (new_previous) | |||
| 540 | { | |||
| 541 | node->previous_sibling = new_previous; | |||
| 542 | node->next_sibling = new_previous->next_sibling; | |||
| 543 | new_previous->next_sibling = node; | |||
| 544 | } | |||
| 545 | else | |||
| 546 | { | |||
| 547 | node->next_sibling = parent->first_child; | |||
| 548 | parent->first_child = node; | |||
| 549 | } | |||
| 550 | ||||
| 551 | if (node->next_sibling) | |||
| 552 | node->next_sibling->previous_sibling = node; | |||
| 553 | else | |||
| 554 | parent->last_child = node; | |||
| 555 | ||||
| 556 | node->parent = parent; | |||
| 557 | } | |||
| 558 | ||||
| 559 | static void | |||
| 560 | ctk_css_node_real_style_changed (CtkCssNode *cssnode, | |||
| 561 | CtkCssStyleChange *change) | |||
| 562 | { | |||
| 563 | g_set_object (&cssnode->style, ctk_css_style_change_get_new_style (change))(__extension__ ({ _Static_assert (sizeof *(&cssnode->style ) == sizeof (ctk_css_style_change_get_new_style (change)), "Expression evaluates to false" ); union { char *in; GObject **out; } _object_ptr; _object_ptr .in = (char *) (&cssnode->style); (void) (0 ? *(&cssnode ->style) = (ctk_css_style_change_get_new_style (change)), ( 0) : (0)); (g_set_object) (_object_ptr.out, (GObject *) ctk_css_style_change_get_new_style (change)); })); | |||
| 564 | } | |||
| 565 | ||||
| 566 | static void | |||
| 567 | ctk_css_node_class_init (CtkCssNodeClass *klass) | |||
| 568 | { | |||
| 569 | GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); | |||
| 570 | ||||
| 571 | object_class->get_property = ctk_css_node_get_property; | |||
| 572 | object_class->set_property = ctk_css_node_set_property; | |||
| 573 | object_class->dispose = ctk_css_node_dispose; | |||
| 574 | object_class->finalize = ctk_css_node_finalize; | |||
| 575 | ||||
| 576 | klass->update_style = ctk_css_node_real_update_style; | |||
| 577 | klass->invalidate = ctk_css_node_real_invalidate; | |||
| 578 | klass->validate = ctk_css_node_real_validate; | |||
| 579 | klass->queue_validate = ctk_css_node_real_queue_validate; | |||
| 580 | klass->dequeue_validate = ctk_css_node_real_dequeue_validate; | |||
| 581 | klass->init_matcher = ctk_css_node_real_init_matcher; | |||
| 582 | klass->create_widget_path = ctk_css_node_real_create_widget_path; | |||
| 583 | klass->get_widget_path = ctk_css_node_real_get_widget_path; | |||
| 584 | klass->get_style_provider = ctk_css_node_real_get_style_provider; | |||
| 585 | klass->get_frame_clock = ctk_css_node_real_get_frame_clock; | |||
| 586 | ||||
| 587 | klass->node_added = ctk_css_node_real_node_added; | |||
| 588 | klass->node_removed = ctk_css_node_real_node_removed; | |||
| 589 | klass->style_changed = ctk_css_node_real_style_changed; | |||
| 590 | ||||
| 591 | cssnode_signals[NODE_ADDED] = | |||
| 592 | g_signal_new (I_("node-added")g_intern_static_string ("node-added"), | |||
| 593 | G_TYPE_FROM_CLASS (object_class)(((GTypeClass*) (object_class))->g_type), | |||
| 594 | G_SIGNAL_RUN_LAST, | |||
| 595 | G_STRUCT_OFFSET (CtkCssNodeClass, node_added)((glong) __builtin_offsetof(CtkCssNodeClass, node_added)), | |||
| 596 | NULL((void*)0), NULL((void*)0), | |||
| 597 | _ctk_marshal_VOID__OBJECT_OBJECT, | |||
| 598 | G_TYPE_NONE((GType) ((1) << (2))), 2, | |||
| 599 | CTK_TYPE_CSS_NODE(ctk_css_node_get_type ()), CTK_TYPE_CSS_NODE(ctk_css_node_get_type ())); | |||
| 600 | g_signal_set_va_marshaller (cssnode_signals[NODE_ADDED], | |||
| 601 | G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type), | |||
| 602 | _ctk_marshal_VOID__OBJECT_OBJECTv); | |||
| 603 | ||||
| 604 | cssnode_signals[NODE_REMOVED] = | |||
| 605 | g_signal_new (I_("node-removed")g_intern_static_string ("node-removed"), | |||
| 606 | G_TYPE_FROM_CLASS (object_class)(((GTypeClass*) (object_class))->g_type), | |||
| 607 | G_SIGNAL_RUN_LAST, | |||
| 608 | G_STRUCT_OFFSET (CtkCssNodeClass, node_removed)((glong) __builtin_offsetof(CtkCssNodeClass, node_removed)), | |||
| 609 | NULL((void*)0), NULL((void*)0), | |||
| 610 | _ctk_marshal_VOID__OBJECT_OBJECT, | |||
| 611 | G_TYPE_NONE((GType) ((1) << (2))), 2, | |||
| 612 | CTK_TYPE_CSS_NODE(ctk_css_node_get_type ()), CTK_TYPE_CSS_NODE(ctk_css_node_get_type ())); | |||
| 613 | g_signal_set_va_marshaller (cssnode_signals[NODE_REMOVED], | |||
| 614 | G_TYPE_FROM_CLASS (klass)(((GTypeClass*) (klass))->g_type), | |||
| 615 | _ctk_marshal_VOID__OBJECT_OBJECTv); | |||
| 616 | ||||
| 617 | cssnode_signals[STYLE_CHANGED] = | |||
| 618 | g_signal_new (I_("style-changed")g_intern_static_string ("style-changed"), | |||
| 619 | G_TYPE_FROM_CLASS (object_class)(((GTypeClass*) (object_class))->g_type), | |||
| 620 | G_SIGNAL_RUN_LAST, | |||
| 621 | G_STRUCT_OFFSET (CtkCssNodeClass, style_changed)((glong) __builtin_offsetof(CtkCssNodeClass, style_changed)), | |||
| 622 | NULL((void*)0), NULL((void*)0), | |||
| 623 | NULL((void*)0), | |||
| 624 | G_TYPE_NONE((GType) ((1) << (2))), 1, | |||
| 625 | G_TYPE_POINTER((GType) ((17) << (2)))); | |||
| 626 | ||||
| 627 | cssnode_properties[PROP_CLASSES] = | |||
| 628 | g_param_spec_boxed ("classes", P_("Style Classes")g_dgettext("ctk30" "-properties","Style Classes"), P_("List of classes")g_dgettext("ctk30" "-properties","List of classes"), | |||
| 629 | G_TYPE_STRV(g_strv_get_type ()), | |||
| 630 | G_PARAM_READWRITE | |||
| 631 | | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); | |||
| 632 | cssnode_properties[PROP_ID] = | |||
| 633 | g_param_spec_string ("id", P_("ID")g_dgettext("ctk30" "-properties","ID"), P_("Unique ID")g_dgettext("ctk30" "-properties","Unique ID"), | |||
| 634 | NULL((void*)0), | |||
| 635 | G_PARAM_READWRITE | |||
| 636 | | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); | |||
| 637 | cssnode_properties[PROP_NAME] = | |||
| 638 | g_param_spec_string ("name", P_("Name")g_dgettext("ctk30" "-properties","Name"), "Name identifying the type of node", | |||
| 639 | NULL((void*)0), | |||
| 640 | G_PARAM_READWRITE | |||
| 641 | | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); | |||
| 642 | cssnode_properties[PROP_STATE] = | |||
| 643 | g_param_spec_flags ("state", P_("State")g_dgettext("ctk30" "-properties","State"), P_("State flags")g_dgettext("ctk30" "-properties","State flags"), | |||
| 644 | CTK_TYPE_STATE_FLAGS(ctk_state_flags_get_type ()), | |||
| 645 | 0, | |||
| 646 | G_PARAM_READWRITE | |||
| 647 | | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); | |||
| 648 | cssnode_properties[PROP_VISIBLE] = | |||
| 649 | g_param_spec_boolean ("visible", P_("Visible")g_dgettext("ctk30" "-properties","Visible"), P_("If other nodes can see this node")g_dgettext("ctk30" "-properties","If other nodes can see this node" ), | |||
| 650 | TRUE(!(0)), | |||
| 651 | G_PARAM_READWRITE | |||
| 652 | | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); | |||
| 653 | cssnode_properties[PROP_WIDGET_TYPE] = | |||
| 654 | g_param_spec_gtype ("widget-type", P_("Widget type")g_dgettext("ctk30" "-properties","Widget type"), P_("GType of the widget")g_dgettext("ctk30" "-properties","GType of the widget"), | |||
| 655 | G_TYPE_NONE((GType) ((1) << (2))), | |||
| 656 | G_PARAM_READWRITE | |||
| 657 | | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB )); | |||
| 658 | ||||
| 659 | g_object_class_install_properties (object_class, NUM_PROPERTIES, cssnode_properties); | |||
| 660 | } | |||
| 661 | ||||
| 662 | static void | |||
| 663 | ctk_css_node_init (CtkCssNode *cssnode) | |||
| 664 | { | |||
| 665 | cssnode->decl = ctk_css_node_declaration_new (); | |||
| 666 | ||||
| 667 | cssnode->style = g_object_ref (ctk_css_static_style_get_default ())((__typeof__ (ctk_css_static_style_get_default ())) (g_object_ref ) (ctk_css_static_style_get_default ())); | |||
| 668 | ||||
| 669 | cssnode->visible = TRUE(!(0)); | |||
| 670 | } | |||
| 671 | ||||
| 672 | /** | |||
| 673 | * ctk_css_node_new: | |||
| 674 | * | |||
| 675 | * Creates a new CSS node. | |||
| 676 | * | |||
| 677 | * Returns: (transfer full): the new CSS node | |||
| 678 | */ | |||
| 679 | CtkCssNode * | |||
| 680 | ctk_css_node_new (void) | |||
| 681 | { | |||
| 682 | return g_object_new (CTK_TYPE_CSS_NODE(ctk_css_node_get_type ()), NULL((void*)0)); | |||
| 683 | } | |||
| 684 | ||||
| 685 | static CdkFrameClock * | |||
| 686 | ctk_css_node_get_frame_clock_or_null (CtkCssNode *cssnode) | |||
| 687 | { | |||
| 688 | while (cssnode->parent) | |||
| 689 | cssnode = cssnode->parent; | |||
| 690 | ||||
| 691 | return CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->get_frame_clock (cssnode); | |||
| 692 | } | |||
| 693 | ||||
| 694 | static gint64 | |||
| 695 | ctk_css_node_get_timestamp (CtkCssNode *cssnode) | |||
| 696 | { | |||
| 697 | CdkFrameClock *frameclock; | |||
| 698 | ||||
| 699 | frameclock = ctk_css_node_get_frame_clock_or_null (cssnode); | |||
| 700 | if (frameclock == NULL((void*)0)) | |||
| 701 | return 0; | |||
| 702 | ||||
| 703 | return cdk_frame_clock_get_frame_time (frameclock); | |||
| 704 | } | |||
| 705 | ||||
| 706 | static void | |||
| 707 | ctk_css_node_parent_was_unset (CtkCssNode *node) | |||
| 708 | { | |||
| 709 | if (node->visible && node->invalid) | |||
| 710 | CTK_CSS_NODE_GET_CLASS (node)((((CtkCssNodeClass*) (((GTypeInstance*) ((node)))->g_class ))))->queue_validate (node); | |||
| 711 | } | |||
| 712 | ||||
| 713 | static void | |||
| 714 | ctk_css_node_parent_will_be_set (CtkCssNode *node) | |||
| 715 | { | |||
| 716 | if (node->visible && node->invalid) | |||
| 717 | CTK_CSS_NODE_GET_CLASS (node)((((CtkCssNodeClass*) (((GTypeInstance*) ((node)))->g_class ))))->dequeue_validate (node); | |||
| 718 | } | |||
| 719 | ||||
| 720 | static void | |||
| 721 | ctk_css_node_invalidate_style (CtkCssNode *cssnode) | |||
| 722 | { | |||
| 723 | if (cssnode->style_is_invalid) | |||
| 724 | return; | |||
| 725 | ||||
| 726 | cssnode->style_is_invalid = TRUE(!(0)); | |||
| 727 | ctk_css_node_set_invalid (cssnode, TRUE(!(0))); | |||
| 728 | ||||
| 729 | if (cssnode->first_child) | |||
| 730 | ctk_css_node_invalidate_style (cssnode->first_child); | |||
| 731 | ||||
| 732 | if (cssnode->next_sibling) | |||
| 733 | ctk_css_node_invalidate_style (cssnode->next_sibling); | |||
| 734 | } | |||
| 735 | ||||
| 736 | static void | |||
| 737 | ctk_css_node_reposition (CtkCssNode *node, | |||
| 738 | CtkCssNode *new_parent, | |||
| 739 | CtkCssNode *previous) | |||
| 740 | { | |||
| 741 | CtkCssNode *old_parent; | |||
| 742 | ||||
| 743 | g_assert (! (new_parent == NULL && previous != NULL))do { if (! (new_parent == ((void*)0) && previous != ( (void*)0))) ; else g_assertion_message_expr ("Ctk", "ctkcssnode.c" , 743, ((const char*) (__func__)), "! (new_parent == NULL && previous != NULL)" ); } while (0); | |||
| 744 | ||||
| 745 | old_parent = node->parent; | |||
| 746 | /* Take a reference here so the whole function has a reference */ | |||
| 747 | g_object_ref (node)((__typeof__ (node)) (g_object_ref) (node)); | |||
| 748 | ||||
| 749 | if (node->visible) | |||
| 750 | { | |||
| 751 | if (node->next_sibling) | |||
| 752 | ctk_css_node_invalidate (node->next_sibling, | |||
| 753 | CTK_CSS_CHANGE_ANY_SIBLING((1ULL << 8) | (1ULL << 9) | (1ULL << 10) | ((1ULL << 11) | (1ULL << 12) | (1ULL << 13 ) | (1ULL << 14)) | (1ULL << 15)) | |||
| 754 | | CTK_CSS_CHANGE_NTH_CHILD(1ULL << 5) | |||
| 755 | | (node->previous_sibling ? 0 : CTK_CSS_CHANGE_FIRST_CHILD(1ULL << 3))); | |||
| 756 | else if (node->previous_sibling) | |||
| 757 | ctk_css_node_invalidate (node->previous_sibling, CTK_CSS_CHANGE_LAST_CHILD(1ULL << 4)); | |||
| 758 | } | |||
| 759 | ||||
| 760 | if (old_parent != NULL((void*)0)) | |||
| 761 | { | |||
| 762 | g_signal_emit (old_parent, cssnode_signals[NODE_REMOVED], 0, node, node->previous_sibling); | |||
| 763 | if (old_parent->first_child && node->visible) | |||
| 764 | ctk_css_node_invalidate (old_parent->first_child, CTK_CSS_CHANGE_NTH_LAST_CHILD(1ULL << 6)); | |||
| 765 | } | |||
| 766 | ||||
| 767 | if (old_parent != new_parent) | |||
| 768 | { | |||
| 769 | if (old_parent == NULL((void*)0)) | |||
| 770 | { | |||
| 771 | ctk_css_node_parent_will_be_set (node); | |||
| 772 | } | |||
| 773 | else | |||
| 774 | { | |||
| 775 | g_object_unref (node); | |||
| 776 | } | |||
| 777 | ||||
| 778 | if (ctk_css_node_get_style_provider_or_null (node) == NULL((void*)0)) | |||
| 779 | ctk_css_node_invalidate_style_provider (node); | |||
| 780 | ctk_css_node_invalidate (node, CTK_CSS_CHANGE_TIMESTAMP(1ULL << 34) | CTK_CSS_CHANGE_ANIMATIONS(1ULL << 35)); | |||
| 781 | ||||
| 782 | if (new_parent) | |||
| 783 | { | |||
| 784 | g_object_ref (node)((__typeof__ (node)) (g_object_ref) (node)); | |||
| 785 | ||||
| 786 | if (node->pending_changes) | |||
| 787 | new_parent->needs_propagation = TRUE(!(0)); | |||
| 788 | if (node->invalid && node->visible) | |||
| 789 | ctk_css_node_set_invalid (new_parent, TRUE(!(0))); | |||
| 790 | } | |||
| 791 | else | |||
| 792 | { | |||
| 793 | ctk_css_node_parent_was_unset (node); | |||
| 794 | } | |||
| 795 | } | |||
| 796 | ||||
| 797 | if (new_parent) | |||
| 798 | { | |||
| 799 | g_signal_emit (new_parent, cssnode_signals[NODE_ADDED], 0, node, previous); | |||
| 800 | if (node->visible) | |||
| 801 | ctk_css_node_invalidate (new_parent->first_child, CTK_CSS_CHANGE_NTH_LAST_CHILD(1ULL << 6)); | |||
| 802 | } | |||
| 803 | ||||
| 804 | if (node->visible) | |||
| 805 | { | |||
| 806 | if (node->next_sibling) | |||
| 807 | { | |||
| 808 | if (node->previous_sibling == NULL((void*)0)) | |||
| 809 | ctk_css_node_invalidate (node->next_sibling, CTK_CSS_CHANGE_FIRST_CHILD(1ULL << 3)); | |||
| 810 | else | |||
| 811 | ctk_css_node_invalidate_style (node->next_sibling); | |||
| 812 | } | |||
| 813 | else if (node->previous_sibling) | |||
| 814 | { | |||
| 815 | ctk_css_node_invalidate (node->previous_sibling, CTK_CSS_CHANGE_LAST_CHILD(1ULL << 4)); | |||
| 816 | } | |||
| 817 | } | |||
| 818 | else | |||
| 819 | { | |||
| 820 | if (node->next_sibling) | |||
| 821 | ctk_css_node_invalidate_style (node->next_sibling); | |||
| 822 | } | |||
| 823 | ||||
| 824 | ctk_css_node_invalidate (node, CTK_CSS_CHANGE_ANY_PARENT((1ULL << 16) | (1ULL << 24) | (1ULL << 17) | (1ULL << 26) | (1ULL << 18) | (1ULL << 25 ) | ((1ULL << 19) | (1ULL << 20) | (1ULL << 21) | (1ULL << 22)) | ((1ULL << 27) | (1ULL << 28) | (1ULL << 29) | (1ULL << 30)) | (1ULL << 23) | (1ULL << 31)) | |||
| 825 | | CTK_CSS_CHANGE_ANY_SIBLING((1ULL << 8) | (1ULL << 9) | (1ULL << 10) | ((1ULL << 11) | (1ULL << 12) | (1ULL << 13 ) | (1ULL << 14)) | (1ULL << 15)) | |||
| 826 | | CTK_CSS_CHANGE_NTH_CHILD(1ULL << 5) | |||
| 827 | | (node->previous_sibling ? 0 : CTK_CSS_CHANGE_FIRST_CHILD(1ULL << 3)) | |||
| 828 | | (node->next_sibling ? 0 : CTK_CSS_CHANGE_LAST_CHILD(1ULL << 4))); | |||
| 829 | ||||
| 830 | g_object_unref (node); | |||
| 831 | } | |||
| 832 | ||||
| 833 | void | |||
| 834 | ctk_css_node_set_parent (CtkCssNode *node, | |||
| 835 | CtkCssNode *parent) | |||
| 836 | { | |||
| 837 | if (node->parent == parent) | |||
| 838 | return; | |||
| 839 | ||||
| 840 | ctk_css_node_reposition (node, parent, parent ? parent->last_child : NULL((void*)0)); | |||
| 841 | } | |||
| 842 | ||||
| 843 | /* If previous_sibling is NULL, insert at the beginning */ | |||
| 844 | void | |||
| 845 | ctk_css_node_insert_after (CtkCssNode *parent, | |||
| 846 | CtkCssNode *cssnode, | |||
| 847 | CtkCssNode *previous_sibling) | |||
| 848 | { | |||
| 849 | g_return_if_fail (previous_sibling == NULL || previous_sibling->parent == parent)do { if ((previous_sibling == ((void*)0) || previous_sibling-> parent == parent)) { } else { g_return_if_fail_warning ("Ctk" , ((const char*) (__func__)), "previous_sibling == NULL || previous_sibling->parent == parent" ); return; } } while (0); | |||
| 850 | g_return_if_fail (cssnode != previous_sibling)do { if ((cssnode != previous_sibling)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "cssnode != previous_sibling" ); return; } } while (0); | |||
| 851 | ||||
| 852 | if (cssnode->previous_sibling == previous_sibling && | |||
| 853 | cssnode->parent == parent) | |||
| 854 | return; | |||
| 855 | ||||
| 856 | ctk_css_node_reposition (cssnode, | |||
| 857 | parent, | |||
| 858 | previous_sibling); | |||
| 859 | } | |||
| 860 | ||||
| 861 | /* If next_sibling is NULL, insert at the end */ | |||
| 862 | void | |||
| 863 | ctk_css_node_insert_before (CtkCssNode *parent, | |||
| 864 | CtkCssNode *cssnode, | |||
| 865 | CtkCssNode *next_sibling) | |||
| 866 | { | |||
| 867 | g_return_if_fail (next_sibling == NULL || next_sibling->parent == parent)do { if ((next_sibling == ((void*)0) || next_sibling->parent == parent)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "next_sibling == NULL || next_sibling->parent == parent" ); return; } } while (0); | |||
| 868 | g_return_if_fail (cssnode != next_sibling)do { if ((cssnode != next_sibling)) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "cssnode != next_sibling" ); return; } } while (0); | |||
| 869 | ||||
| 870 | if (cssnode->next_sibling == next_sibling && | |||
| 871 | cssnode->parent == parent) | |||
| 872 | return; | |||
| 873 | ||||
| 874 | ctk_css_node_reposition (cssnode, | |||
| 875 | parent, | |||
| 876 | next_sibling ? next_sibling->previous_sibling : parent->last_child); | |||
| 877 | } | |||
| 878 | ||||
| 879 | void | |||
| 880 | ctk_css_node_reverse_children (CtkCssNode *cssnode) | |||
| 881 | { | |||
| 882 | CtkCssNode *end; | |||
| 883 | ||||
| 884 | end = cssnode->last_child; | |||
| 885 | while (cssnode->first_child != end) | |||
| 886 | { | |||
| 887 | ctk_css_node_reposition (cssnode->first_child, | |||
| 888 | cssnode, | |||
| 889 | end); | |||
| 890 | } | |||
| 891 | ||||
| 892 | } | |||
| 893 | ||||
| 894 | CtkCssNode * | |||
| 895 | ctk_css_node_get_parent (CtkCssNode *cssnode) | |||
| 896 | { | |||
| 897 | return cssnode->parent; | |||
| 898 | } | |||
| 899 | ||||
| 900 | CtkCssNode * | |||
| 901 | ctk_css_node_get_first_child (CtkCssNode *cssnode) | |||
| 902 | { | |||
| 903 | return cssnode->first_child; | |||
| 904 | } | |||
| 905 | ||||
| 906 | CtkCssNode * | |||
| 907 | ctk_css_node_get_last_child (CtkCssNode *cssnode) | |||
| 908 | { | |||
| 909 | return cssnode->last_child; | |||
| 910 | } | |||
| 911 | ||||
| 912 | CtkCssNode * | |||
| 913 | ctk_css_node_get_previous_sibling (CtkCssNode *cssnode) | |||
| 914 | { | |||
| 915 | return cssnode->previous_sibling; | |||
| 916 | } | |||
| 917 | ||||
| 918 | CtkCssNode * | |||
| 919 | ctk_css_node_get_next_sibling (CtkCssNode *cssnode) | |||
| 920 | { | |||
| 921 | return cssnode->next_sibling; | |||
| 922 | } | |||
| 923 | ||||
| 924 | static gboolean | |||
| 925 | ctk_css_node_set_style (CtkCssNode *cssnode, | |||
| 926 | CtkCssStyle *style) | |||
| 927 | { | |||
| 928 | CtkCssStyleChange change; | |||
| 929 | gboolean style_changed; | |||
| 930 | ||||
| 931 | if (cssnode->style == style) | |||
| 932 | return FALSE(0); | |||
| 933 | ||||
| 934 | ctk_css_style_change_init (&change, cssnode->style, style); | |||
| 935 | ||||
| 936 | style_changed = ctk_css_style_change_has_change (&change); | |||
| 937 | if (style_changed) | |||
| 938 | { | |||
| 939 | g_signal_emit (cssnode, cssnode_signals[STYLE_CHANGED], 0, &change); | |||
| 940 | } | |||
| 941 | else if (cssnode->style != style && | |||
| 942 | (CTK_IS_CSS_ANIMATED_STYLE (cssnode->style)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( cssnode->style); GType __t = ((ctk_css_animated_style_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))) || CTK_IS_CSS_ANIMATED_STYLE (style)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( style); GType __t = ((ctk_css_animated_style_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) | |||
| 943 | { | |||
| 944 | /* This is when animations are starting/stopping but they didn't change any CSS this frame */ | |||
| 945 | g_set_object (&cssnode->style, style)(__extension__ ({ _Static_assert (sizeof *(&cssnode->style ) == sizeof (style), "Expression evaluates to false"); union { char *in; GObject **out; } _object_ptr; _object_ptr.in = (char *) (&cssnode->style); (void) (0 ? *(&cssnode-> style) = (style), (0) : (0)); (g_set_object) (_object_ptr.out , (GObject *) style); })); | |||
| 946 | } | |||
| 947 | ||||
| 948 | ctk_css_style_change_finish (&change); | |||
| 949 | ||||
| 950 | return style_changed; | |||
| 951 | } | |||
| 952 | ||||
| 953 | static void | |||
| 954 | ctk_css_node_propagate_pending_changes (CtkCssNode *cssnode, | |||
| 955 | gboolean style_changed) | |||
| 956 | { | |||
| 957 | CtkCssChange change, child_change; | |||
| 958 | CtkCssNode *child; | |||
| 959 | ||||
| 960 | change = _ctk_css_change_for_child (cssnode->pending_changes); | |||
| 961 | if (style_changed) | |||
| 962 | change |= CTK_CSS_CHANGE_PARENT_STYLE(1ULL << 33); | |||
| 963 | ||||
| 964 | if (!cssnode->needs_propagation && change == 0) | |||
| 965 | return; | |||
| 966 | ||||
| 967 | for (child = ctk_css_node_get_first_child (cssnode); | |||
| 968 | child; | |||
| 969 | child = ctk_css_node_get_next_sibling (child)) | |||
| 970 | { | |||
| 971 | child_change = child->pending_changes; | |||
| 972 | ctk_css_node_invalidate (child, change); | |||
| 973 | if (child->visible) | |||
| 974 | change |= _ctk_css_change_for_sibling (child_change); | |||
| 975 | } | |||
| 976 | ||||
| 977 | cssnode->needs_propagation = FALSE(0); | |||
| 978 | } | |||
| 979 | ||||
| 980 | static gboolean | |||
| 981 | ctk_css_node_needs_new_style (CtkCssNode *cssnode) | |||
| 982 | { | |||
| 983 | return cssnode->style_is_invalid || cssnode->needs_propagation; | |||
| 984 | } | |||
| 985 | ||||
| 986 | static void | |||
| 987 | ctk_css_node_ensure_style (CtkCssNode *cssnode, | |||
| 988 | gint64 current_time) | |||
| 989 | { | |||
| 990 | gboolean style_changed; | |||
| 991 | ||||
| 992 | if (!ctk_css_node_needs_new_style (cssnode)) | |||
| 993 | return; | |||
| 994 | ||||
| 995 | if (cssnode->parent) | |||
| 996 | ctk_css_node_ensure_style (cssnode->parent, current_time); | |||
| 997 | ||||
| 998 | if (cssnode->style_is_invalid) | |||
| 999 | { | |||
| 1000 | CtkCssStyle *new_style; | |||
| 1001 | ||||
| 1002 | if (cssnode->previous_sibling) | |||
| 1003 | ctk_css_node_ensure_style (cssnode->previous_sibling, current_time); | |||
| 1004 | ||||
| 1005 | g_clear_pointer (&cssnode->cache, ctk_css_node_style_cache_unref)do { _Static_assert (sizeof *(&cssnode->cache) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((& cssnode->cache)) _pp = (&cssnode->cache); __typeof__ (*(&cssnode->cache)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (ctk_css_node_style_cache_unref) (_ptr); } while (0); | |||
| 1006 | ||||
| 1007 | new_style = CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->update_style (cssnode, | |||
| 1008 | cssnode->pending_changes, | |||
| 1009 | current_time, | |||
| 1010 | cssnode->style); | |||
| 1011 | ||||
| 1012 | style_changed = ctk_css_node_set_style (cssnode, new_style); | |||
| 1013 | g_object_unref (new_style); | |||
| 1014 | } | |||
| 1015 | else | |||
| 1016 | { | |||
| 1017 | style_changed = FALSE(0); | |||
| 1018 | } | |||
| 1019 | ||||
| 1020 | ctk_css_node_propagate_pending_changes (cssnode, style_changed); | |||
| 1021 | ||||
| 1022 | cssnode->pending_changes = 0; | |||
| 1023 | cssnode->style_is_invalid = FALSE(0); | |||
| 1024 | } | |||
| 1025 | ||||
| 1026 | CtkCssStyle * | |||
| 1027 | ctk_css_node_get_style (CtkCssNode *cssnode) | |||
| 1028 | { | |||
| 1029 | if (ctk_css_node_needs_new_style (cssnode)) | |||
| 1030 | { | |||
| 1031 | gint64 timestamp = ctk_css_node_get_timestamp (cssnode); | |||
| 1032 | ||||
| 1033 | ctk_css_node_ensure_style (cssnode, timestamp); | |||
| 1034 | } | |||
| 1035 | ||||
| 1036 | return cssnode->style; | |||
| 1037 | } | |||
| 1038 | ||||
| 1039 | void | |||
| 1040 | ctk_css_node_set_visible (CtkCssNode *cssnode, | |||
| 1041 | gboolean visible) | |||
| 1042 | { | |||
| 1043 | CtkCssNode *iter; | |||
| 1044 | ||||
| 1045 | if (cssnode->visible == visible) | |||
| 1046 | return; | |||
| 1047 | ||||
| 1048 | cssnode->visible = visible; | |||
| 1049 | g_object_notify_by_pspec (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2)))))))), cssnode_properties[PROP_VISIBLE]); | |||
| 1050 | ||||
| 1051 | if (cssnode->invalid) | |||
| 1052 | { | |||
| 1053 | if (cssnode->visible) | |||
| 1054 | { | |||
| 1055 | if (cssnode->parent) | |||
| 1056 | ctk_css_node_set_invalid (cssnode->parent, TRUE(!(0))); | |||
| 1057 | else | |||
| 1058 | CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->queue_validate (cssnode); | |||
| 1059 | } | |||
| 1060 | else | |||
| 1061 | { | |||
| 1062 | if (cssnode->parent == NULL((void*)0)) | |||
| 1063 | CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->dequeue_validate (cssnode); | |||
| 1064 | } | |||
| 1065 | } | |||
| 1066 | ||||
| 1067 | if (cssnode->next_sibling) | |||
| 1068 | { | |||
| 1069 | ctk_css_node_invalidate (cssnode->next_sibling, CTK_CSS_CHANGE_ANY_SIBLING((1ULL << 8) | (1ULL << 9) | (1ULL << 10) | ((1ULL << 11) | (1ULL << 12) | (1ULL << 13 ) | (1ULL << 14)) | (1ULL << 15)) | CTK_CSS_CHANGE_NTH_CHILD(1ULL << 5)); | |||
| 1070 | if (ctk_css_node_is_first_child (cssnode)) | |||
| 1071 | { | |||
| 1072 | for (iter = cssnode->next_sibling; | |||
| 1073 | iter != NULL((void*)0); | |||
| 1074 | iter = iter->next_sibling) | |||
| 1075 | { | |||
| 1076 | ctk_css_node_invalidate (iter, CTK_CSS_CHANGE_FIRST_CHILD(1ULL << 3)); | |||
| 1077 | if (iter->visible) | |||
| 1078 | break; | |||
| 1079 | } | |||
| 1080 | } | |||
| 1081 | } | |||
| 1082 | ||||
| 1083 | if (cssnode->previous_sibling) | |||
| 1084 | { | |||
| 1085 | if (ctk_css_node_is_last_child (cssnode)) | |||
| 1086 | { | |||
| 1087 | for (iter = cssnode->previous_sibling; | |||
| 1088 | iter != NULL((void*)0); | |||
| 1089 | iter = iter->previous_sibling) | |||
| 1090 | { | |||
| 1091 | ctk_css_node_invalidate (iter, CTK_CSS_CHANGE_LAST_CHILD(1ULL << 4)); | |||
| 1092 | if (iter->visible) | |||
| 1093 | break; | |||
| 1094 | } | |||
| 1095 | } | |||
| 1096 | ctk_css_node_invalidate (cssnode->parent->first_child, CTK_CSS_CHANGE_NTH_LAST_CHILD(1ULL << 6)); | |||
| 1097 | } | |||
| 1098 | } | |||
| 1099 | ||||
| 1100 | gboolean | |||
| 1101 | ctk_css_node_get_visible (CtkCssNode *cssnode) | |||
| 1102 | { | |||
| 1103 | return cssnode->visible; | |||
| 1104 | } | |||
| 1105 | ||||
| 1106 | void | |||
| 1107 | ctk_css_node_set_name (CtkCssNode *cssnode, | |||
| 1108 | /*interned*/ const char *name) | |||
| 1109 | { | |||
| 1110 | if (ctk_css_node_declaration_set_name (&cssnode->decl, name)) | |||
| 1111 | { | |||
| 1112 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_NAME(1ULL << 1)); | |||
| 1113 | g_object_notify_by_pspec (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2)))))))), cssnode_properties[PROP_NAME]); | |||
| 1114 | } | |||
| 1115 | } | |||
| 1116 | ||||
| 1117 | /* interned */ const char * | |||
| 1118 | ctk_css_node_get_name (CtkCssNode *cssnode) | |||
| 1119 | { | |||
| 1120 | return ctk_css_node_declaration_get_name (cssnode->decl); | |||
| 1121 | } | |||
| 1122 | ||||
| 1123 | void | |||
| 1124 | ctk_css_node_set_widget_type (CtkCssNode *cssnode, | |||
| 1125 | GType widget_type) | |||
| 1126 | { | |||
| 1127 | if (ctk_css_node_declaration_set_type (&cssnode->decl, widget_type)) | |||
| 1128 | { | |||
| 1129 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_NAME(1ULL << 1)); | |||
| 1130 | g_object_notify_by_pspec (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2)))))))), cssnode_properties[PROP_WIDGET_TYPE]); | |||
| 1131 | } | |||
| 1132 | } | |||
| 1133 | ||||
| 1134 | GType | |||
| 1135 | ctk_css_node_get_widget_type (CtkCssNode *cssnode) | |||
| 1136 | { | |||
| 1137 | return ctk_css_node_declaration_get_type (cssnode->decl); | |||
| 1138 | } | |||
| 1139 | ||||
| 1140 | void | |||
| 1141 | ctk_css_node_set_id (CtkCssNode *cssnode, | |||
| 1142 | /* interned */ const char *id) | |||
| 1143 | { | |||
| 1144 | if (ctk_css_node_declaration_set_id (&cssnode->decl, id)) | |||
| 1145 | { | |||
| 1146 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_ID(1ULL << 2)); | |||
| 1147 | g_object_notify_by_pspec (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2)))))))), cssnode_properties[PROP_ID]); | |||
| 1148 | } | |||
| 1149 | } | |||
| 1150 | ||||
| 1151 | /* interned */ const char * | |||
| 1152 | ctk_css_node_get_id (CtkCssNode *cssnode) | |||
| 1153 | { | |||
| 1154 | return ctk_css_node_declaration_get_id (cssnode->decl); | |||
| 1155 | } | |||
| 1156 | ||||
| 1157 | void | |||
| 1158 | ctk_css_node_set_state (CtkCssNode *cssnode, | |||
| 1159 | CtkStateFlags state_flags) | |||
| 1160 | { | |||
| 1161 | if (ctk_css_node_declaration_set_state (&cssnode->decl, state_flags)) | |||
| 1162 | { | |||
| 1163 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_STATE(1ULL << 7)); | |||
| 1164 | g_object_notify_by_pspec (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2)))))))), cssnode_properties[PROP_STATE]); | |||
| 1165 | } | |||
| 1166 | } | |||
| 1167 | ||||
| 1168 | CtkStateFlags | |||
| 1169 | ctk_css_node_get_state (CtkCssNode *cssnode) | |||
| 1170 | { | |||
| 1171 | return ctk_css_node_declaration_get_state (cssnode->decl); | |||
| 1172 | } | |||
| 1173 | ||||
| 1174 | void | |||
| 1175 | ctk_css_node_set_junction_sides (CtkCssNode *cssnode, | |||
| 1176 | CtkJunctionSides junction_sides) | |||
| 1177 | { | |||
| 1178 | ctk_css_node_declaration_set_junction_sides (&cssnode->decl, junction_sides); | |||
| 1179 | } | |||
| 1180 | ||||
| 1181 | CtkJunctionSides | |||
| 1182 | ctk_css_node_get_junction_sides (CtkCssNode *cssnode) | |||
| 1183 | { | |||
| 1184 | return ctk_css_node_declaration_get_junction_sides (cssnode->decl); | |||
| 1185 | } | |||
| 1186 | ||||
| 1187 | static void | |||
| 1188 | ctk_css_node_clear_classes (CtkCssNode *cssnode) | |||
| 1189 | { | |||
| 1190 | if (ctk_css_node_declaration_clear_classes (&cssnode->decl)) | |||
| 1191 | { | |||
| 1192 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_CLASS(1ULL << 0)); | |||
| 1193 | g_object_notify_by_pspec (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2)))))))), cssnode_properties[PROP_CLASSES]); | |||
| 1194 | } | |||
| 1195 | } | |||
| 1196 | ||||
| 1197 | void | |||
| 1198 | ctk_css_node_set_classes (CtkCssNode *cssnode, | |||
| 1199 | const char **classes) | |||
| 1200 | { | |||
| 1201 | guint i; | |||
| 1202 | ||||
| 1203 | g_object_freeze_notify (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2))))))))); | |||
| 1204 | ||||
| 1205 | ctk_css_node_clear_classes (cssnode); | |||
| 1206 | ||||
| 1207 | if (classes) | |||
| 1208 | { | |||
| 1209 | for (i = 0; classes[i] != NULL((void*)0); i++) | |||
| 1210 | { | |||
| 1211 | ctk_css_node_add_class (cssnode, g_quark_from_string (classes[i])); | |||
| 1212 | } | |||
| 1213 | } | |||
| 1214 | ||||
| 1215 | g_object_thaw_notify (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2))))))))); | |||
| 1216 | } | |||
| 1217 | ||||
| 1218 | char ** | |||
| 1219 | ctk_css_node_get_classes (CtkCssNode *cssnode) | |||
| 1220 | { | |||
| 1221 | const GQuark *classes; | |||
| 1222 | char **result; | |||
| 1223 | guint n_classes, i, j; | |||
| 1224 | ||||
| 1225 | classes = ctk_css_node_declaration_get_classes (cssnode->decl, &n_classes); | |||
| 1226 | result = g_new (char *, n_classes + 1)((char * *) g_malloc_n ((n_classes + 1), sizeof (char *))); | |||
| 1227 | ||||
| 1228 | for (i = n_classes, j = 0; i-- > 0; ++j) | |||
| 1229 | { | |||
| 1230 | result[j] = g_strdup (g_quark_to_string (classes[i]))g_strdup_inline (g_quark_to_string (classes[i])); | |||
| 1231 | } | |||
| 1232 | ||||
| 1233 | result[n_classes] = NULL((void*)0); | |||
| 1234 | return result; | |||
| 1235 | } | |||
| 1236 | ||||
| 1237 | void | |||
| 1238 | ctk_css_node_add_class (CtkCssNode *cssnode, | |||
| 1239 | GQuark style_class) | |||
| 1240 | { | |||
| 1241 | if (ctk_css_node_declaration_add_class (&cssnode->decl, style_class)) | |||
| 1242 | { | |||
| 1243 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_CLASS(1ULL << 0)); | |||
| 1244 | g_object_notify_by_pspec (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2)))))))), cssnode_properties[PROP_CLASSES]); | |||
| 1245 | } | |||
| 1246 | } | |||
| 1247 | ||||
| 1248 | void | |||
| 1249 | ctk_css_node_remove_class (CtkCssNode *cssnode, | |||
| 1250 | GQuark style_class) | |||
| 1251 | { | |||
| 1252 | if (ctk_css_node_declaration_remove_class (&cssnode->decl, style_class)) | |||
| 1253 | { | |||
| 1254 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_CLASS(1ULL << 0)); | |||
| 1255 | g_object_notify_by_pspec (G_OBJECT (cssnode)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((cssnode)), (((GType) ((20) << (2)))))))), cssnode_properties[PROP_CLASSES]); | |||
| 1256 | } | |||
| 1257 | } | |||
| 1258 | ||||
| 1259 | gboolean | |||
| 1260 | ctk_css_node_has_class (CtkCssNode *cssnode, | |||
| 1261 | GQuark style_class) | |||
| 1262 | { | |||
| 1263 | return ctk_css_node_declaration_has_class (cssnode->decl, style_class); | |||
| 1264 | } | |||
| 1265 | ||||
| 1266 | const GQuark * | |||
| 1267 | ctk_css_node_list_classes (CtkCssNode *cssnode, | |||
| 1268 | guint *n_classes) | |||
| 1269 | { | |||
| 1270 | return ctk_css_node_declaration_get_classes (cssnode->decl, n_classes); | |||
| 1271 | } | |||
| 1272 | ||||
| 1273 | void | |||
| 1274 | ctk_css_node_add_region (CtkCssNode *cssnode, | |||
| 1275 | GQuark region, | |||
| 1276 | CtkRegionFlags flags) | |||
| 1277 | { | |||
| 1278 | ctk_css_node_declaration_add_region (&cssnode->decl, region, flags); | |||
| 1279 | } | |||
| 1280 | ||||
| 1281 | void | |||
| 1282 | ctk_css_node_remove_region (CtkCssNode *cssnode, | |||
| 1283 | GQuark region) | |||
| 1284 | { | |||
| 1285 | ctk_css_node_declaration_remove_region (&cssnode->decl, region); | |||
| 1286 | } | |||
| 1287 | ||||
| 1288 | gboolean | |||
| 1289 | ctk_css_node_has_region (CtkCssNode *cssnode, | |||
| 1290 | GQuark region, | |||
| 1291 | CtkRegionFlags *out_flags) | |||
| 1292 | { | |||
| 1293 | return ctk_css_node_declaration_has_region (cssnode->decl, region, out_flags); | |||
| 1294 | } | |||
| 1295 | ||||
| 1296 | GList * | |||
| 1297 | ctk_css_node_list_regions (CtkCssNode *cssnode) | |||
| 1298 | { | |||
| 1299 | return ctk_css_node_declaration_list_regions (cssnode->decl); | |||
| 1300 | } | |||
| 1301 | ||||
| 1302 | ||||
| 1303 | const CtkCssNodeDeclaration * | |||
| 1304 | ctk_css_node_get_declaration (CtkCssNode *cssnode) | |||
| 1305 | { | |||
| 1306 | return cssnode->decl; | |||
| 1307 | } | |||
| 1308 | ||||
| 1309 | void | |||
| 1310 | ctk_css_node_invalidate_style_provider (CtkCssNode *cssnode) | |||
| 1311 | { | |||
| 1312 | CtkCssNode *child; | |||
| 1313 | ||||
| 1314 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_SOURCE(1ULL << 32)); | |||
| 1315 | ||||
| 1316 | for (child = cssnode->first_child; | |||
| 1317 | child; | |||
| 1318 | child = child->next_sibling) | |||
| 1319 | { | |||
| 1320 | if (ctk_css_node_get_style_provider_or_null (child) == NULL((void*)0)) | |||
| 1321 | ctk_css_node_invalidate_style_provider (child); | |||
| 1322 | } | |||
| 1323 | } | |||
| 1324 | ||||
| 1325 | static void | |||
| 1326 | ctk_css_node_invalidate_timestamp (CtkCssNode *cssnode) | |||
| 1327 | { | |||
| 1328 | CtkCssNode *child; | |||
| 1329 | ||||
| 1330 | if (!cssnode->invalid) | |||
| 1331 | return; | |||
| 1332 | ||||
| 1333 | if (!ctk_css_style_is_static (cssnode->style)) | |||
| 1334 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_TIMESTAMP(1ULL << 34)); | |||
| 1335 | ||||
| 1336 | for (child = cssnode->first_child; child; child = child->next_sibling) | |||
| 1337 | { | |||
| 1338 | ctk_css_node_invalidate_timestamp (child); | |||
| 1339 | } | |||
| 1340 | } | |||
| 1341 | ||||
| 1342 | void | |||
| 1343 | ctk_css_node_invalidate_frame_clock (CtkCssNode *cssnode, | |||
| 1344 | gboolean just_timestamp) | |||
| 1345 | { | |||
| 1346 | /* frame clock is handled by the top level */ | |||
| 1347 | if (cssnode->parent) | |||
| 1348 | return; | |||
| 1349 | ||||
| 1350 | ctk_css_node_invalidate_timestamp (cssnode); | |||
| 1351 | ||||
| 1352 | if (!just_timestamp) | |||
| 1353 | ctk_css_node_invalidate (cssnode, CTK_CSS_CHANGE_ANIMATIONS(1ULL << 35)); | |||
| 1354 | } | |||
| 1355 | ||||
| 1356 | void | |||
| 1357 | ctk_css_node_invalidate (CtkCssNode *cssnode, | |||
| 1358 | CtkCssChange change) | |||
| 1359 | { | |||
| 1360 | if (!cssnode->invalid) | |||
| 1361 | change &= ~CTK_CSS_CHANGE_TIMESTAMP(1ULL << 34); | |||
| 1362 | ||||
| 1363 | if (change == 0) | |||
| 1364 | return; | |||
| 1365 | ||||
| 1366 | cssnode->pending_changes |= change; | |||
| 1367 | ||||
| 1368 | CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->invalidate (cssnode); | |||
| 1369 | ||||
| 1370 | if (cssnode->parent) | |||
| 1371 | cssnode->parent->needs_propagation = TRUE(!(0)); | |||
| 1372 | ctk_css_node_invalidate_style (cssnode); | |||
| 1373 | } | |||
| 1374 | ||||
| 1375 | void | |||
| 1376 | ctk_css_node_validate_internal (CtkCssNode *cssnode, | |||
| 1377 | gint64 timestamp) | |||
| 1378 | { | |||
| 1379 | CtkCssNode *child; | |||
| 1380 | ||||
| 1381 | if (!cssnode->invalid) | |||
| 1382 | return; | |||
| 1383 | ||||
| 1384 | ctk_css_node_ensure_style (cssnode, timestamp); | |||
| 1385 | ||||
| 1386 | /* need to set to FALSE then to TRUE here to make it chain up */ | |||
| 1387 | ctk_css_node_set_invalid (cssnode, FALSE(0)); | |||
| 1388 | if (!ctk_css_style_is_static (cssnode->style)) | |||
| 1389 | ctk_css_node_set_invalid (cssnode, TRUE(!(0))); | |||
| 1390 | ||||
| 1391 | CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->validate (cssnode); | |||
| 1392 | ||||
| 1393 | for (child = ctk_css_node_get_first_child (cssnode); | |||
| 1394 | child; | |||
| 1395 | child = ctk_css_node_get_next_sibling (child)) | |||
| 1396 | { | |||
| 1397 | if (child->visible) | |||
| 1398 | ctk_css_node_validate_internal (child, timestamp); | |||
| 1399 | } | |||
| 1400 | } | |||
| 1401 | ||||
| 1402 | void | |||
| 1403 | ctk_css_node_validate (CtkCssNode *cssnode) | |||
| 1404 | { | |||
| 1405 | gint64 timestamp; | |||
| 1406 | ||||
| 1407 | timestamp = ctk_css_node_get_timestamp (cssnode); | |||
| 1408 | ||||
| 1409 | ctk_css_node_validate_internal (cssnode, timestamp); | |||
| 1410 | } | |||
| 1411 | ||||
| 1412 | gboolean | |||
| 1413 | ctk_css_node_init_matcher (CtkCssNode *cssnode, | |||
| 1414 | CtkCssMatcher *matcher) | |||
| 1415 | { | |||
| 1416 | return CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->init_matcher (cssnode, matcher); | |||
| 1417 | } | |||
| 1418 | ||||
| 1419 | CtkWidgetPath * | |||
| 1420 | ctk_css_node_create_widget_path (CtkCssNode *cssnode) | |||
| 1421 | { | |||
| 1422 | return CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->create_widget_path (cssnode); | |||
| 1423 | } | |||
| 1424 | ||||
| 1425 | const CtkWidgetPath * | |||
| 1426 | ctk_css_node_get_widget_path (CtkCssNode *cssnode) | |||
| 1427 | { | |||
| 1428 | return CTK_CSS_NODE_GET_CLASS (cssnode)((((CtkCssNodeClass*) (((GTypeInstance*) ((cssnode)))->g_class ))))->get_widget_path (cssnode); | |||
| 1429 | } | |||
| 1430 | ||||
| 1431 | CtkStyleProviderPrivate * | |||
| 1432 | ctk_css_node_get_style_provider (CtkCssNode *cssnode) | |||
| 1433 | { | |||
| 1434 | CtkStyleProviderPrivate *result; | |||
| 1435 | CtkSettings *settings; | |||
| 1436 | ||||
| 1437 | result = ctk_css_node_get_style_provider_or_null (cssnode); | |||
| 1438 | if (result) | |||
| 1439 | return result; | |||
| 1440 | ||||
| 1441 | if (cssnode->parent) | |||
| 1442 | return ctk_css_node_get_style_provider (cssnode->parent); | |||
| 1443 | ||||
| 1444 | settings = ctk_settings_get_default (); | |||
| 1445 | if (!settings) | |||
| 1446 | return NULL((void*)0); | |||
| 1447 | ||||
| 1448 | return CTK_STYLE_PROVIDER_PRIVATE (_ctk_settings_get_style_cascade (settings, 1))((((CtkStyleProviderPrivate*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((_ctk_settings_get_style_cascade (settings , 1))), ((_ctk_style_provider_private_get_type ())))))); | |||
| 1449 | } | |||
| 1450 | ||||
| 1451 | void | |||
| 1452 | ctk_css_node_print (CtkCssNode *cssnode, | |||
| 1453 | CtkStyleContextPrintFlags flags, | |||
| 1454 | GString *string, | |||
| 1455 | guint indent) | |||
| 1456 | { | |||
| 1457 | gboolean need_newline = FALSE(0); | |||
| 1458 | ||||
| 1459 | g_string_append_printf (string, "%*s", indent, ""); | |||
| 1460 | ||||
| 1461 | if (!cssnode->visible) | |||
| 1462 | g_string_append_c (string, '[')g_string_append_c_inline (string, '['); | |||
| 1463 | ||||
| 1464 | ctk_css_node_declaration_print (cssnode->decl, string); | |||
| 1465 | ||||
| 1466 | if (!cssnode->visible) | |||
| 1467 | g_string_append_c (string, ']')g_string_append_c_inline (string, ']'); | |||
| 1468 | ||||
| 1469 | g_string_append_c (string, '\n')g_string_append_c_inline (string, '\n'); | |||
| 1470 | ||||
| 1471 | if (flags & CTK_STYLE_CONTEXT_PRINT_SHOW_STYLE) | |||
| 1472 | need_newline = ctk_css_style_print (ctk_css_node_get_style (cssnode), string, indent + 2, TRUE(!(0))); | |||
| 1473 | ||||
| 1474 | if (flags & CTK_STYLE_CONTEXT_PRINT_RECURSE) | |||
| 1475 | { | |||
| 1476 | CtkCssNode *node; | |||
| 1477 | ||||
| 1478 | if (need_newline && ctk_css_node_get_first_child (cssnode)) | |||
| 1479 | g_string_append_c (string, '\n')g_string_append_c_inline (string, '\n'); | |||
| 1480 | ||||
| 1481 | for (node = ctk_css_node_get_first_child (cssnode); node; node = ctk_css_node_get_next_sibling (node)) | |||
| 1482 | ctk_css_node_print (node, flags, string, indent + 2); | |||
| 1483 | } | |||
| 1484 | } |