예제 #1
0
/* Dump actors */
static void _xfdashboard_dump_actor_print(ClutterActor *inActor, gint inLevel)
{
	XfdashboardStylable		*stylable;
	ClutterActorBox			allocation;
	gint					i;

	g_return_if_fail(CLUTTER_IS_ACTOR(inActor));
	g_return_if_fail(inLevel>=0);

	/* Check if actor is stylable to retrieve style configuration */
	stylable=NULL;
	if(XFDASHBOARD_IS_STYLABLE(inActor)) stylable=XFDASHBOARD_STYLABLE(inActor);

	/* Dump actor */
	for(i=0; i<inLevel; i++) g_print("  ");
	clutter_actor_get_allocation_box(inActor, &allocation);
	g_print("+- %s@%p [%s%s%s%s%s%s] - geometry: %.2f,%.2f [%.2fx%.2f], mapped: %s, visible: %s, layout: %s, children: %d\n",
				G_OBJECT_TYPE_NAME(inActor), inActor,
				clutter_actor_get_name(inActor) ? " #" : "",
				clutter_actor_get_name(inActor) ? clutter_actor_get_name(inActor) : "",
				stylable && xfdashboard_stylable_get_classes(stylable) ? "." : "",
				stylable && xfdashboard_stylable_get_classes(stylable) ? xfdashboard_stylable_get_classes(stylable) : "",
				stylable && xfdashboard_stylable_get_pseudo_classes(stylable) ? ":" : "",
				stylable && xfdashboard_stylable_get_pseudo_classes(stylable) ? xfdashboard_stylable_get_pseudo_classes(stylable) : "",
				allocation.x1,
				allocation.y1,
				allocation.x2-allocation.x1,
				allocation.y2-allocation.y1,
				clutter_actor_is_mapped(inActor) ? "yes" : "no",
				clutter_actor_is_visible(inActor) ? "yes" : "no",
				clutter_actor_get_layout_manager(inActor) ? G_OBJECT_TYPE_NAME(clutter_actor_get_layout_manager(inActor)) : "none",
				clutter_actor_get_n_children(inActor));

}
예제 #2
0
/* Adds a class to existing classes of an object */
void xfdashboard_stylable_add_class(XfdashboardStylable *self, const gchar *inClass)
{
	const gchar		*classes;

	g_return_if_fail(XFDASHBOARD_IS_STYLABLE(self));
	g_return_if_fail(inClass && inClass[0]);

	/* If class is already in list of classes do nothing otherwise set new value */
	classes=xfdashboard_stylable_get_classes(self);
	if(!classes ||
		!_xfdashboard_stylable_list_contains(inClass, -1, classes, '.'))
	{
		gchar					*newClasses;

		/* Create new temporary string by concatenating current classes
		 * and new class with dot separator. Set this new string representing
		 * list of classes.
		 */
		if(classes) newClasses=g_strconcat(classes, ".", inClass, NULL);
			else newClasses=g_strdup(inClass);

		xfdashboard_stylable_set_classes(self, newClasses);

		g_free(newClasses);
	}
}
예제 #3
0
/* Removed a class to existing classes of an object */
void xfdashboard_stylable_remove_class(XfdashboardStylable *self, const gchar *inClass)
{
	const gchar		*classes;

	g_return_if_fail(XFDASHBOARD_IS_STYLABLE(self));
	g_return_if_fail(inClass && inClass[0]);

	/* If class is not in list of classes do nothing otherwise set new value */
	classes=xfdashboard_stylable_get_classes(self);
	if(classes &&
		_xfdashboard_stylable_list_contains(inClass, -1, classes, '.'))
	{
		gchar					**oldClasses, **entry;
		gchar					*newClasses, *newClassesTemp;

		/* Create new temporary string with all current classes separated by dot
		 * not matching class to remove. Set this new string representing list
		 * of classes.
		 */
		entry=oldClasses=g_strsplit(classes, ".", -1);
		newClasses=NULL;
		while(*entry)
		{
			if(!strcmp(*entry, inClass))
			{
				entry++;
				continue;
			}

			if(newClasses)
			{
				newClassesTemp=g_strconcat(newClasses, ".", *entry, NULL);
				g_free(newClasses);
				newClasses=newClassesTemp;
			}
				else newClasses=g_strdup(*entry);

			entry++;
		}

		xfdashboard_stylable_set_classes(self, newClasses);

		g_strfreev(oldClasses);
		g_free(newClasses);
	}
}
예제 #4
0
/* Determine if a specific class is being set at object */
gboolean xfdashboard_stylable_has_class(XfdashboardStylable *self, const gchar *inClass)
{
	const gchar		*classes;
	gboolean		result;

	g_return_val_if_fail(XFDASHBOARD_IS_STYLABLE(self), FALSE);
	g_return_val_if_fail(inClass && inClass[0], FALSE);

	result=FALSE;

	/* Get classes set at object and check if it has the expected one */
	classes=xfdashboard_stylable_get_classes(self);
	if(classes &&
		_xfdashboard_stylable_list_contains(inClass, -1, classes, '.'))
	{
		result=TRUE;
	}

	/* Return result */
	return(result);
}
예제 #5
0
/* Check and score this selector against stylable node.
 * A score below 0 means that they did not match.
 */
static gint _xfdashboard_css_selector_score_matching_node(XfdashboardCssSelectorRule *inRule,
															XfdashboardStylable *inStylable)
{
	gint					score;
	gint					a, b, c;
	const gchar				*classes;
	const gchar				*pseudoClasses;
	const gchar				*id;

	g_return_val_if_fail(inRule, -1);
	g_return_val_if_fail(XFDASHBOARD_IS_STYLABLE(inStylable), -1);

	/* For information about how the scoring is done, see documentation
	 * "Cascading Style Sheets, level 1" of W3C, section "3.2 Cascading order"
	 * URL: http://www.w3.org/TR/2008/REC-CSS1-20080411/#cascading-order
	 *
	 * 1. Find all declarations that apply to the element/property in question.
	 *    Declarations apply if the selector matches the element in question.
	 *    If no declarations apply, the inherited value is used. If there is
	 *    no inherited value (this is the case for the 'HTML' element and
	 *    for properties that do not inherit), the initial value is used.
	 * 2. Sort the declarations by explicit weight: declarations marked
	 *    '!important' carry more weight than unmarked (normal) declarations.
	 * 3. Sort by origin: the author's style sheets override the reader's
	 *    style sheet which override the UA's default values. An imported
	 *    style sheet has the same origin as the style sheet from which it
	 *    is imported.
	 * 4. Sort by specificity of selector: more specific selectors will
	 *    override more general ones. To find the specificity, count the
	 *    number of ID attributes in the selector (a), the number of CLASS
	 *    attributes in the selector (b), and the number of tag names in
	 *    the selector (c). Concatenating the three numbers (in a number
	 *    system with a large base) gives the specificity.
	 *    Pseudo-elements and pseudo-classes are counted as normal elements
	 *    and classes, respectively.
	 * 5. Sort by order specified: if two rules have the same weight, the
	 *    latter specified wins. Rules in imported style sheets are considered
	 *    to be before any rules in the style sheet itself.
	 *
	 * NOTE: Keyword '!important' is not supported.
	 */
	a=b=c=0;

	/* Get properties for given stylable */
	id=xfdashboard_stylable_get_name(XFDASHBOARD_STYLABLE(inStylable));
	classes=xfdashboard_stylable_get_classes(XFDASHBOARD_STYLABLE(inStylable));
	pseudoClasses=xfdashboard_stylable_get_pseudo_classes(XFDASHBOARD_STYLABLE(inStylable));

	/* Check and score type of selectors but ignore NULL or universal selectors */
	if(inRule->type && inRule->type[0]!='*')
	{
		GType						ruleTypeID;
		GType						nodeTypeID;

		/* Get type of this rule */
		ruleTypeID=g_type_from_name(inRule->type);
		if(!ruleTypeID) return(-1);

		/* Get type of other rule to check against and score it */
		nodeTypeID=G_OBJECT_TYPE(inStylable);
		if(!nodeTypeID) return(-1);

		/* Check if type of this rule matches type of other rule */
		if(!g_type_is_a(nodeTypeID, ruleTypeID)) return(-1);

		/* Determine depth difference between both types
		 * which is the score of this test with a maximum of 99
		 */
		c=g_type_depth(ruleTypeID)-g_type_depth(nodeTypeID);
		c=MAX(ABS(c), 99);
	}

	/* Check and score ID */
	if(inRule->id)
	{
		/* If node has no ID return immediately */
		if(!id || strcmp(inRule->id, id)) return(-1);

		/* Score ID */
		a+=10;
	}

	/* Check and score classes */
	if(inRule->classes)
	{
		gchar				*needle;
		gint				numberMatches;

		/* If node has no pseudo class return immediately */
		if(!classes) return(-1);

		/* Check that each class from the selector's rule appears in the
		 * list of classes from the node, i.e. the selector's rule class list
		 * is a subset of the node's class list
		 */
		numberMatches=0;
		for(needle=inRule->classes; needle; needle=strchr(needle, '.'))
		{
			gint			needleLength;
			gchar			*nextNeedle;

			/* Move pointer of needle beyond class seperator '.' */
			if(needle[0]=='.') needle++;

			/* Get length of needle */
			nextNeedle=strchr(needle, '.');
			if(nextNeedle) needleLength=nextNeedle-needle;
				else needleLength=strlen(needle);

			/* If pseudo-class from the selector does not appear in the
			 * list of pseudo-classes from the node, then this is not a
			 * match
			 */
			if(!_xfdashboard_css_selector_list_contains(needle, needleLength, classes, '.')) return(-1);
			numberMatches++;
		}

		/* Score matching class */
		b=b+(10*numberMatches);
	}

	/* Check and score pseudo classes */
	if(inRule->pseudoClasses)
	{
		gchar				*needle;
		gint				numberMatches;

		/* If node has no pseudo class return immediately */
		if(!pseudoClasses) return(-1);

		/* Check that each pseudo-class from the selector appears in the
		 * pseudo-classes from the node, i.e. the selector pseudo-class list
		 * is a subset of the node's pseudo-class list
		 */
		numberMatches=0;
		for(needle=inRule->pseudoClasses; needle; needle=strchr(needle, ':'))
		{
			gint			needleLength;
			gchar			*nextNeedle;

			/* Move pointer of needle beyond pseudo-class seperator ':' */
			if(needle[0]==':') needle++;

			/* Get length of needle */
			nextNeedle=strchr(needle, ':');
			if(nextNeedle) needleLength=nextNeedle-needle;
				else needleLength=strlen(needle);

			/* If pseudo-class from the selector does not appear in the
			 * list of pseudo-classes from the node, then this is not a
			 * match
			 */
			if(!_xfdashboard_css_selector_list_contains(needle, needleLength, pseudoClasses, ':')) return(-1);
			numberMatches++;
		}

		/* Score matching pseudo-class */
		b=b+(10*numberMatches);
	}

	/* Check and score parent */
	if(inRule->parentRule &&
		inRule->parentRuleMode==XFDASHBOARD_CSS_SELECTOR_RULE_MODE_PARENT)
	{
		gint					parentScore;
		XfdashboardStylable		*parent;

		/* If node has no parent, no parent can match ;) so return immediately */
		parent=xfdashboard_stylable_get_parent(inStylable);
		if(!parent || !XFDASHBOARD_IS_STYLABLE(parent)) return(-1);

		/* Check if there are matching parents. If not return immediately. */
		parentScore=_xfdashboard_css_selector_score_matching_node(inRule->parentRule, parent);
		if(parentScore<0) return(-1);

		/* Score matching parents */
		c+=parentScore;
	}

	/* Check and score ancestor */
	if(inRule->parentRule &&
		inRule->parentRuleMode==XFDASHBOARD_CSS_SELECTOR_RULE_MODE_ANCESTOR)
	{
		gint					ancestorScore;
		XfdashboardStylable		*ancestor;

		ancestor=inStylable;

		/* If node has no parents, no ancestor can match so return immediately */
		do
		{
			ancestor=xfdashboard_stylable_get_parent(ancestor);
		}
		while(ancestor && !XFDASHBOARD_IS_STYLABLE(ancestor));

		if(!ancestor || !XFDASHBOARD_IS_STYLABLE(ancestor)) return(-1);

		/* Iterate through ancestors and check and score them */
		while(ancestor)
		{
			/* Get number of matches for ancestor and if at least one matches,
			 * stop search and score
			 */
			ancestorScore=_xfdashboard_css_selector_score_matching_node(inRule->parentRule, ancestor);
			if(ancestorScore>=0)
			{
				c+=ancestorScore;
				break;
			}

			/* Get next ancestor to check but skip actors not implementing
			 * the XfdashboardStylable interface
			 */
			do
			{
				ancestor=xfdashboard_stylable_get_parent(ancestor);
			}
			while(ancestor && !XFDASHBOARD_IS_STYLABLE(ancestor));

			if(!ancestor || !XFDASHBOARD_IS_STYLABLE(ancestor)) return(-1);
		}
	}

	/* Calculate final score */
	score=(a*10000)+(b*100)+c;
	return(score);
}