static void _xfdashboard_actor_stylable_set_pseudo_classes(XfdashboardStylable *inStylable, const gchar *inStylePseudoClasses) { XfdashboardActor *self; XfdashboardActorPrivate *priv; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inStylable)); self=XFDASHBOARD_ACTOR(inStylable); priv=self->priv; /* Set value if changed */ if(g_strcmp0(priv->stylePseudoClasses, inStylePseudoClasses)) { /* Set value */ if(priv->stylePseudoClasses) { g_free(priv->stylePseudoClasses); priv->stylePseudoClasses=NULL; } if(inStylePseudoClasses) priv->stylePseudoClasses=g_strdup(inStylePseudoClasses); /* Invalidate style to get it restyled and redrawn. Also invalidate * children as they might reference the old, invalid pseudo-classes * or the new, valid ones. */ _xfdashboard_actor_invalidate_recursive(CLUTTER_ACTOR(self)); /* Notify about property change */ g_object_notify(G_OBJECT(self), "style-pseudo-classes"); } }
static void _xfdashboard_actor_get_property(GObject *inObject, guint inPropID, GValue *outValue, GParamSpec *inSpec) { XfdashboardActor *self=XFDASHBOARD_ACTOR(inObject); XfdashboardActorPrivate *priv=self->priv; switch(inPropID) { case PROP_CAN_FOCUS: g_value_set_boolean(outValue, priv->canFocus); break; case PROP_EFFECTS: g_value_set_string(outValue, priv->effects); break; case PROP_STYLE_CLASSES: g_value_set_string(outValue, priv->styleClasses); break; case PROP_STYLE_PSEUDO_CLASSES: g_value_set_string(outValue, priv->stylePseudoClasses); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec); break; } }
/* Set/get properties */ static void _xfdashboard_actor_set_property(GObject *inObject, guint inPropID, const GValue *inValue, GParamSpec *inSpec) { XfdashboardActor *self=XFDASHBOARD_ACTOR(inObject); switch(inPropID) { case PROP_CAN_FOCUS: xfdashboard_actor_set_can_focus(self, g_value_get_boolean(inValue)); break; case PROP_EFFECTS: xfdashboard_actor_set_effects(self, g_value_get_string(inValue)); break; case PROP_STYLE_CLASSES: _xfdashboard_actor_stylable_set_classes(XFDASHBOARD_STYLABLE(self), g_value_get_string(inValue)); break; case PROP_STYLE_PSEUDO_CLASSES: _xfdashboard_actor_stylable_set_pseudo_classes(XFDASHBOARD_STYLABLE(self), g_value_get_string(inValue)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(inObject, inPropID, inSpec); break; } }
/* Actor's reactive state changed */ static void _xfdashboard_actor_on_reactive_changed(GObject *inObject, GParamSpec *inSpec, gpointer inUserData) { XfdashboardActor *self; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inObject)); self=XFDASHBOARD_ACTOR(inObject); /* Add pseudo-class ':insensitive' if actor is now not reactive * and remove this pseudo-class if actor is now reactive. */ if(clutter_actor_get_reactive(CLUTTER_ACTOR(self))) { xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(self), "insensitive"); } else { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(self), "insensitive"); } /* Invalide styling to get it recomputed */ _xfdashboard_actor_invalidate_recursive(CLUTTER_ACTOR(self)); }
/* Dispose this object */ static void _xfdashboard_actor_dispose(GObject *inObject) { XfdashboardActor *self=XFDASHBOARD_ACTOR(inObject); XfdashboardActorPrivate *priv=self->priv; /* Release allocated variables */ if(priv->effects) { g_free(priv->effects); priv->effects=NULL; } if(priv->styleClasses) { g_free(priv->styleClasses); priv->styleClasses=NULL; } if(priv->stylePseudoClasses) { g_free(priv->stylePseudoClasses); priv->stylePseudoClasses=NULL; } if(priv->lastThemeStyleSet) { g_hash_table_destroy(priv->lastThemeStyleSet); priv->lastThemeStyleSet=NULL; } /* Call parent's class dispose method */ G_OBJECT_CLASS(xfdashboard_actor_parent_class)->dispose(inObject); }
/* Get/set style pseudo-classes of actor */ static const gchar* _xfdashboard_actor_stylable_get_pseudo_classes(XfdashboardStylable *inStylable) { XfdashboardActor *self; g_return_val_if_fail(XFDASHBOARD_IS_ACTOR(inStylable), NULL); self=XFDASHBOARD_ACTOR(inStylable); return(self->priv->stylePseudoClasses); }
/* Unset focus from actor */ static void _xfdashboard_actor_focusable_unset_focus(XfdashboardFocusable *self) { XfdashboardActor *actor; g_return_if_fail(XFDASHBOARD_IS_FOCUSABLE(self)); g_return_if_fail(XFDASHBOARD_IS_ACTOR(self)); actor=XFDASHBOARD_ACTOR(self); /* Set focus and style for focus */ xfdashboard_stylable_remove_class(XFDASHBOARD_STYLABLE(actor), "focus"); }
/* Actor was mapped or unmapped */ static void _xfdashboard_actor_on_mapped_changed(GObject *inObject, GParamSpec *inSpec, gpointer inUserData) { XfdashboardActor *self; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inObject)); self=XFDASHBOARD_ACTOR(inObject); /* Invalide styling to get it recomputed */ xfdashboard_stylable_invalidate(XFDASHBOARD_STYLABLE(self)); }
/* Actor was (re)named */ static void _xfdashboard_actor_on_name_changed(GObject *inObject, GParamSpec *inSpec, gpointer inUserData) { XfdashboardActor *self; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inObject)); self=XFDASHBOARD_ACTOR(inObject); /* Invalide styling to get it recomputed because its ID (from point * of view of css) has changed. Also invalidate children as they * might reference the old, invalid ID or the new, valid one. */ _xfdashboard_actor_invalidate_recursive(CLUTTER_ACTOR(self)); }
/* Object initialization * Create private structure and set up default values */ static void xfdashboard_view_init(XfdashboardView *self) { XfdashboardViewPrivate *priv; priv=self->priv=XFDASHBOARD_VIEW_GET_PRIVATE(self); /* Set up default values */ priv->viewName=NULL; priv->viewIcon=NULL; priv->viewIconImage=NULL; priv->fitMode=XFDASHBOARD_FIT_MODE_NONE; priv->isEnabled=TRUE; /* Set up actor */ clutter_actor_set_reactive(CLUTTER_ACTOR(self), TRUE); xfdashboard_actor_invalidate(XFDASHBOARD_ACTOR(self)); }
/* Actor was (re)parented */ static void _xfdashboard_actor_parent_set(ClutterActor *inActor, ClutterActor *inOldParent) { XfdashboardActor *self; XfdashboardActorPrivate *priv; ClutterActorClass *parentClass; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inActor)); self=XFDASHBOARD_ACTOR(inActor); priv=self->priv; /* Call parent's virtual function */ parentClass=CLUTTER_ACTOR_CLASS(xfdashboard_actor_parent_class); if(parentClass->parent_set) { parentClass->parent_set(inActor, inOldParent); } /* Check if it is a newly created actor which is parented for the first time. * Then emit 'actor-created' signal on stage. */ if(priv->isFirstParent && !inOldParent && clutter_actor_get_parent(inActor)) { ClutterActor *stage; /* Get stage where this actor belongs to and emit signal at stage */ stage=clutter_actor_get_stage(inActor); if(XFDASHBOARD_IS_STAGE(stage)) { g_signal_emit_by_name(stage, "actor-created", inActor, NULL); } /* Set flag that a parent set and signal was emitted */ priv->isFirstParent=FALSE; } /* Invalide styling to get it recomputed because its ID (from point * of view of css) has changed. Also invalidate children as they might * reference the old, invalid parent or the new, valid one. */ _xfdashboard_actor_invalidate_recursive(CLUTTER_ACTOR(self)); }
/* Actor is hidden */ static void _xfdashboard_actor_hide(ClutterActor *inActor) { XfdashboardActor *self; ClutterActorClass *parentClass; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inActor)); self=XFDASHBOARD_ACTOR(inActor); /* Call parent's virtual function */ parentClass=CLUTTER_ACTOR_CLASS(xfdashboard_actor_parent_class); if(parentClass->hide) { parentClass->hide(inActor); } /* Actor is hidden now so remove pseudo-class ":hover" because pointer cannot * be in an actor hidden. */ xfdashboard_stylable_remove_pseudo_class(XFDASHBOARD_STYLABLE(self), "hover"); }
/* Pointer entered actor */ static gboolean _xfdashboard_actor_enter_event(ClutterActor *inActor, ClutterCrossingEvent *inEvent) { XfdashboardActor *self; ClutterActorClass *parentClass; g_return_val_if_fail(XFDASHBOARD_IS_ACTOR(inActor), CLUTTER_EVENT_PROPAGATE); self=XFDASHBOARD_ACTOR(inActor); /* Call parent's virtual function */ parentClass=CLUTTER_ACTOR_CLASS(xfdashboard_actor_parent_class); if(parentClass->enter_event) { parentClass->enter_event(inActor, inEvent); } /* Add pseudo-class ":hover" because pointer entered actor */ xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(self), "hover"); return(CLUTTER_EVENT_PROPAGATE); }
/* Actor was (re)parented */ static void _xfdashboard_actor_parent_set(ClutterActor *inActor, ClutterActor *inOldParent) { XfdashboardActor *self; ClutterActorClass *parentClass; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inActor)); self=XFDASHBOARD_ACTOR(inActor); /* Call parent's virtual function */ parentClass=CLUTTER_ACTOR_CLASS(xfdashboard_actor_parent_class); if(parentClass->parent_set) { parentClass->parent_set(inActor, inOldParent); } /* Invalide styling to get it recomputed because its ID (from point * of view of css) has changed. Also invalidate children as they might * reference the old, invalid parent or the new, valid one. */ _xfdashboard_actor_invalidate_recursive(CLUTTER_ACTOR(self)); }
/* Check if actor can get focus */ static gboolean _xfdashboard_actor_focusable_can_focus(XfdashboardFocusable *inFocusable) { XfdashboardActor *self; XfdashboardActorPrivate *priv; g_return_val_if_fail(XFDASHBOARD_IS_FOCUSABLE(inFocusable), FALSE); g_return_val_if_fail(XFDASHBOARD_IS_ACTOR(inFocusable), FALSE); self=XFDASHBOARD_ACTOR(inFocusable); priv=self->priv; /* This actor can only be focused if it is mapped, visible and reactive */ if(priv->canFocus && clutter_actor_is_mapped(CLUTTER_ACTOR(self)) && clutter_actor_is_visible(CLUTTER_ACTOR(self)) && clutter_actor_get_reactive(CLUTTER_ACTOR(self))) { return(TRUE); } /* If we get here this actor does not fulfill the requirements to get focus */ return(FALSE); }
/* Actor is shown */ static void _xfdashboard_actor_show(ClutterActor *inActor) { XfdashboardActor *self; ClutterActorClass *parentClass; g_return_if_fail(XFDASHBOARD_IS_ACTOR(inActor)); self=XFDASHBOARD_ACTOR(inActor); /* Call parent's virtual function */ parentClass=CLUTTER_ACTOR_CLASS(xfdashboard_actor_parent_class); if(parentClass->show) { parentClass->show(inActor); } /* If actor is visible now check if pointer is inside this actor * then add pseudo-class ":hover" to it */ if(clutter_actor_has_pointer(inActor)) { xfdashboard_stylable_add_pseudo_class(XFDASHBOARD_STYLABLE(self), "hover"); } }
/* Invalidate style to recompute styles */ static void _xfdashboard_actor_stylable_invalidate(XfdashboardStylable *inStylable) { XfdashboardActor *self; XfdashboardActorPrivate *priv; XfdashboardActorClass *klass; XfdashboardTheme *theme; XfdashboardThemeCSS *themeCSS; GHashTable *possibleStyleSet; GParamSpec *paramSpec; GHashTableIter hashIter; GHashTable *themeStyleSet; gchar *styleName; XfdashboardThemeCSSValue *styleValue; gboolean didChange; #ifdef DEBUG gboolean doDebug=FALSE; #endif g_return_if_fail(XFDASHBOARD_IS_ACTOR(inStylable)); self=XFDASHBOARD_ACTOR(inStylable); priv=self->priv; klass=XFDASHBOARD_ACTOR_GET_CLASS(self); didChange=FALSE; /* Only recompute style for mapped actors or if revalidation was forced */ if(!priv->forceStyleRevalidation && !clutter_actor_is_mapped(CLUTTER_ACTOR(self))) return; /* Get theme CSS */ theme=xfdashboard_application_get_theme(NULL); themeCSS=xfdashboard_theme_get_css(theme); /* First get list of all stylable properties of this and parent classes. * It is used to determine if key in theme style sets are valid. */ possibleStyleSet=xfdashboard_actor_get_stylable_properties_full(klass); #ifdef DEBUG if(doDebug) { gint i=0; gchar *defaultsKey; GValue defaultsVal=G_VALUE_INIT; gchar *defaultsValStr; GParamSpec *realParamSpec; XFDASHBOARD_DEBUG(self, STYLE, "Got param specs for %p (%s) with class '%s' and pseudo-class '%s'", self, G_OBJECT_TYPE_NAME(self), priv->styleClasses, priv->stylePseudoClasses); g_hash_table_iter_init(&hashIter, possibleStyleSet); while(g_hash_table_iter_next(&hashIter, (gpointer*)&defaultsKey, (gpointer*)¶mSpec)) { realParamSpec=(GParamSpec*)g_param_spec_get_qdata(paramSpec, XFDASHBOARD_ACTOR_PARAM_SPEC_REF); g_value_init(&defaultsVal, G_PARAM_SPEC_VALUE_TYPE(realParamSpec)); g_param_value_set_default(realParamSpec, &defaultsVal); defaultsValStr=g_strdup_value_contents(&defaultsVal); XFDASHBOARD_DEBUG(self, STYLE, "%d: param spec [%s] %s=%s\n", ++i, G_OBJECT_CLASS_NAME(klass), defaultsKey, defaultsValStr); g_free(defaultsValStr); g_value_unset(&defaultsVal); } XFDASHBOARD_DEBUG(self, STYLE, "End of param specs"); } #endif /* Get style information from theme */ themeStyleSet=xfdashboard_theme_css_get_properties(themeCSS, XFDASHBOARD_STYLABLE(self)); #ifdef DEBUG if(doDebug) { gint i=0; XFDASHBOARD_DEBUG(self, STYLE, "Got styles from theme for %p (%s) with class '%s' and pseudo-class '%s'", self, G_OBJECT_TYPE_NAME(self), priv->styleClasses, priv->stylePseudoClasses); g_hash_table_iter_init(&hashIter, themeStyleSet); while(g_hash_table_iter_next(&hashIter, (gpointer*)&styleName, (gpointer*)&styleValue)) { XFDASHBOARD_DEBUG(self, STYLE, "%d: [%s] %s=%s\n", ++i, styleValue->source, (gchar*)styleName, styleValue->string); } XFDASHBOARD_DEBUG(self, STYLE, "End of styles from theme"); } #endif /* The 'property-changed' notification will be freezed and thawed * (fired at once) after all stylable properties of this instance are set. */ g_object_freeze_notify(G_OBJECT(self)); /* Iterate through style information retrieved from theme and * set the corresponding property in object instance if key * is valid. */ g_hash_table_iter_init(&hashIter, themeStyleSet); while(g_hash_table_iter_next(&hashIter, (gpointer*)&styleName, (gpointer*)&styleValue)) { GValue cssValue=G_VALUE_INIT; GValue propertyValue=G_VALUE_INIT; GParamSpec *realParamSpec; /* Check if key is a valid object property name */ if(!g_hash_table_lookup_extended(possibleStyleSet, styleName, NULL, (gpointer*)¶mSpec)) continue; /* Get original referenced parameter specification. It does not need * to be referenced while converting because it is valid as this * value is stored in hashtable. */ realParamSpec=(GParamSpec*)g_param_spec_get_qdata(paramSpec, XFDASHBOARD_ACTOR_PARAM_SPEC_REF); /* Convert style value to type of object property and set value * if conversion was successful. Otherwise do nothing. */ g_value_init(&cssValue, G_TYPE_STRING); g_value_set_string(&cssValue, styleValue->string); g_value_init(&propertyValue, G_PARAM_SPEC_VALUE_TYPE(realParamSpec)); if(g_param_value_convert(realParamSpec, &cssValue, &propertyValue, FALSE)) { g_object_set_property(G_OBJECT(self), styleName, &propertyValue); didChange=TRUE; #ifdef DEBUG if(doDebug) { gchar *valstr; valstr=g_strdup_value_contents(&propertyValue); XFDASHBOARD_DEBUG(self, STYLE, "Setting theme value of style property [%s] %s=%s\n", G_OBJECT_CLASS_NAME(klass), styleName, valstr); g_free(valstr); } #endif } else { g_warning(_("Could not transform CSS string value for property '%s' to type %s of class %s"), styleName, g_type_name(G_PARAM_SPEC_VALUE_TYPE(realParamSpec)), G_OBJECT_CLASS_NAME(klass)); } /* Release allocated resources */ g_value_unset(&propertyValue); g_value_unset(&cssValue); } /* Now remove all duplicate keys in set of properties changed we set the last * time. The remaining keys determine the properties which were set the last * time but not this time and should be restored to their default values. */ if(priv->lastThemeStyleSet) { /* Remove duplicate keys from set of last changed properties */ g_hash_table_foreach_remove(priv->lastThemeStyleSet, (GHRFunc)_xfdashboard_actor_hashtable_is_duplicate_key, themeStyleSet); /* Iterate through remaining key and restore corresponding object properties * to their default values. */ g_hash_table_iter_init(&hashIter, priv->lastThemeStyleSet); while(g_hash_table_iter_next(&hashIter, (gpointer*)&styleName, (gpointer*)¶mSpec)) { GValue propertyValue=G_VALUE_INIT; GParamSpec *realParamSpec; /* Check if key is a valid object property name */ if(!g_hash_table_lookup_extended(possibleStyleSet, styleName, NULL, (gpointer*)¶mSpec)) continue; /* Get original referenced parameter specification. It does not need * to be referenced while converting because it is valid as this * value is stored in hashtable. */ realParamSpec=(GParamSpec*)g_param_spec_get_qdata(paramSpec, XFDASHBOARD_ACTOR_PARAM_SPEC_REF); /* Initialize property value to its type and default value */ g_value_init(&propertyValue, G_PARAM_SPEC_VALUE_TYPE(realParamSpec)); g_param_value_set_default(realParamSpec, &propertyValue); /* Set value at object property */ g_object_set_property(G_OBJECT(self), styleName, &propertyValue); didChange=TRUE; #ifdef DEBUG if(doDebug) { gchar *valstr; valstr=g_strdup_value_contents(&propertyValue); XFDASHBOARD_DEBUG(self, STYLE, "Restoring default value of style property [%s] %s=%s\n", G_OBJECT_CLASS_NAME(klass), styleName, valstr); g_free(valstr); } #endif /* Release allocated resources */ g_value_unset(&propertyValue); } /* Release resources of set of last changed properties as we do not need * it anymore. */ g_hash_table_destroy(priv->lastThemeStyleSet); priv->lastThemeStyleSet=NULL; } /* Remember this set of changed properties for next time to determine properties * which need to be restored to their default value. */ priv->lastThemeStyleSet=themeStyleSet; /* Release allocated resources */ g_hash_table_destroy(possibleStyleSet); /* Force a redraw if any change was made at this actor */ if(didChange) clutter_actor_queue_redraw(CLUTTER_ACTOR(self)); /* Reset force style revalidation flag because it's done now */ priv->forceStyleRevalidation=FALSE; /* All stylable properties are set now. So thaw 'property-changed' * notification now and fire all notifications at once. */ g_object_thaw_notify(G_OBJECT(self)); }