Exemplo n.º 1
0
/**
 * xfdashboard_traverse_actor:
 * @inRootActor: The root #ClutterActor where to begin traversing
 * @inSelector: A #XfdashboardCssSelector to filter actors while traversing or
 *   %NULL to disable filterting
 * @inCallback: Function to call on matching children
 * @inUserData: Data to pass to callback function
 *
 * Iterates through all children of @inRootActor recursively beginning at
 * @inRootActor and for each child matching the selector @inSelector it calls the
 * callback function @inCallback with the matching child and the user-data at
 * @inUserData.
 *
 * If @inRootActor is %NULL it begins at the global stage.
 *
 * If the selector @inSelector is %NULL all children will match and the callback
 * function @inCallback is called for all children.
 */
void xfdashboard_traverse_actor(ClutterActor *inRootActor,
								XfdashboardCssSelector *inSelector,
								XfdashboardTraversalCallback inCallback,
								gpointer inUserData)
{
	g_return_if_fail(!inRootActor || CLUTTER_IS_ACTOR(inRootActor));
	g_return_if_fail(!inSelector || XFDASHBOARD_IS_CSS_SELECTOR(inSelector));
	g_return_if_fail(inCallback);

	/* If root actor where begin traversal is NULL then begin at stage */
	if(!inRootActor)
	{
		inRootActor=CLUTTER_ACTOR(xfdashboard_application_get_stage(NULL));
	}

	/* If no selector is provider create a seletor matching all actors.
	 * Otherwise take an extra ref on provided selector to prevent
	 * destruction when we unref it later.
	 */
	if(!inSelector) inSelector=xfdashboard_css_selector_new_from_string("*");
		else g_object_ref(inSelector);

	/* Do traversal */
	_xfdashboard_traverse_actor_internal(inRootActor, inSelector, inCallback, inUserData);

	/* Release reference on selector */
	g_object_unref(inSelector);
}
Exemplo n.º 2
0
static gboolean _xfdashboard_css_selector_parse(XfdashboardCssSelector *self, GScanner *ioScanner)
{
	GScannerConfig			*oldScannerConfig;
	GScannerConfig			*scannerConfig;
	gboolean				success;
	GTokenType				token;

	g_return_val_if_fail(XFDASHBOARD_IS_CSS_SELECTOR(self), FALSE);
	g_return_val_if_fail(ioScanner, FALSE);

	success=TRUE;

	/* Set up scanner configuration for parsing css selectors:
	 * - Identifiers are allowed to contain '-' (minus sign) as non-first characters
	 * - Disallow scanning float values as we need '.' for identifiers
	 * - Set up single comment line not to include '#' as this character is need for identifiers
	 * - Disable parsing HEX values
	 * - Identifiers cannot be single quoted
	 * - Identifiers cannot be double quoted
	 */
	scannerConfig=(GScannerConfig*)g_memdup(ioScanner->config, sizeof(GScannerConfig));
	scannerConfig->cset_skip_characters=" \n\r\t";
	scannerConfig->cset_identifier_nth=G_CSET_a_2_z "-_0123456789" G_CSET_A_2_Z G_CSET_LATINS G_CSET_LATINC;
	scannerConfig->scan_float=FALSE;
	scannerConfig->cpair_comment_single="\1\n";
	scannerConfig->scan_hex=FALSE;
	scannerConfig->scan_string_sq=FALSE;
	scannerConfig->scan_string_dq=FALSE;

	/* Set new scanner configuration but remember old one to restore it later */
	oldScannerConfig=ioScanner->config;
	ioScanner->config=scannerConfig;

	/* Parse input stream */
	token=g_scanner_peek_next_token(ioScanner);
	if(token!=G_TOKEN_EOF)
	{
		token=_xfdashboard_css_selector_parse_css_rule(self, ioScanner);
		if(token==G_TOKEN_ERROR)
		{
			g_warning(_("Failed to parse css selector."));
			success=FALSE;
		}
	}
		else
		{
			g_warning(_("Failed to parse css selector because stream is empty."));
			success=FALSE;
		}

	/* Restore old scanner configuration */
	ioScanner->config=oldScannerConfig;

	/* Release allocated resources */
	g_free(scannerConfig);

	/* Return success result */
	return(success);
}
Exemplo n.º 3
0
/* Check and score this selector against a stylable node.
 * A score below 0 means that they did not match.
 */
gint xfdashboard_css_selector_score_matching_stylable_node(XfdashboardCssSelector *self, XfdashboardStylable *inStylable)
{
	g_return_val_if_fail(XFDASHBOARD_IS_CSS_SELECTOR(self), -1);
	g_return_val_if_fail(XFDASHBOARD_IS_STYLABLE(inStylable), -1);

	/* Check and score rules */
	return(_xfdashboard_css_selector_score_matching_node(self->priv->rule, inStylable));
}
Exemplo n.º 4
0
/* Get string for selector.
 * Free string returned with g_free().
 */
gchar* xfdashboard_css_selector_to_string(XfdashboardCssSelector *self)
{
	XfdashboardCssSelectorPrivate	*priv;
	gchar							*selector;

	g_return_val_if_fail(XFDASHBOARD_IS_CSS_SELECTOR(self), NULL);

	priv=self->priv;
	selector=NULL;

	/* Get string for selector */
	if(priv->rule)
	{
		selector=_xfdashboard_css_selector_rule_to_string(priv->rule);
	}

	/* Return newly created string for selector */
	return(selector);
}
Exemplo n.º 5
0
/* Adjust source line and position of this selector to an offset */
void xfdashboard_css_selector_adjust_to_offset(XfdashboardCssSelector *self, gint inLine, gint inPosition)
{
	XfdashboardCssSelectorPrivate	*priv;
	gint							newLine;
	gint							newPosition;

	g_return_if_fail(XFDASHBOARD_IS_CSS_SELECTOR(self));

	priv=self->priv;

	/* Adjust to offset */
	if(priv->rule)
	{
		newLine=inLine+priv->rule->origLine;
		priv->rule->line=MAX(0, newLine);

		newPosition=inPosition+priv->rule->origPosition;
		priv->rule->position=MAX(0, newPosition);
	}
}
Exemplo n.º 6
0
/* Internal function to traverse an actor which can be call recursively */
static gboolean _xfdashboard_traverse_actor_internal(ClutterActor *inActor,
														XfdashboardCssSelector *inSelector,
														XfdashboardTraversalCallback inCallback,
														gpointer inUserData)
{
	ClutterActorIter	iter;
	ClutterActor		*child;
	gint				score;
	gboolean			doContinueTraversal;

	g_return_val_if_fail(CLUTTER_IS_ACTOR(inActor), XFDASHBOARD_TRAVERSAL_CONTINUE);
	g_return_val_if_fail(XFDASHBOARD_IS_CSS_SELECTOR(inSelector), XFDASHBOARD_TRAVERSAL_CONTINUE);
	g_return_val_if_fail(inCallback, XFDASHBOARD_TRAVERSAL_CONTINUE);

	/* Check if given actor matches selector if a selector is provided
	 * otherwise each child will match. Call callback for matching children.
	 */
	if(XFDASHBOARD_IS_STYLABLE(inActor))
	{
		score=xfdashboard_css_selector_score_matching_stylable_node(inSelector, XFDASHBOARD_STYLABLE(inActor));
		if(score>=0)
		{
			doContinueTraversal=(inCallback)(inActor, inUserData);
			if(!doContinueTraversal) return(doContinueTraversal);
		}
	}

	/* For each child of actor call ourselve recursive */
	clutter_actor_iter_init(&iter, inActor);
	while(clutter_actor_iter_next(&iter, &child))
	{
		doContinueTraversal=_xfdashboard_traverse_actor_internal(child, inSelector, inCallback, inUserData);
		if(!doContinueTraversal) return(doContinueTraversal);
	}

	/* If we get here return and continue traversal */
	return(XFDASHBOARD_TRAVERSAL_CONTINUE);
}
Exemplo n.º 7
0
static GTokenType _xfdashboard_css_selector_parse_css_rule(XfdashboardCssSelector *self,
															GScanner *inScanner)
{
	XfdashboardCssSelectorPrivate	*priv;
	GTokenType						token;
	XfdashboardCssSelectorRule		*rule, *parentRule;

	g_return_val_if_fail(XFDASHBOARD_IS_CSS_SELECTOR(self), G_TOKEN_ERROR);
	g_return_val_if_fail(inScanner, G_TOKEN_ERROR);

	priv=self->priv;

	/* Parse comma-seperated selectors until a left curly bracket is found */
	parentRule=NULL;
	rule=NULL;

	token=g_scanner_peek_next_token(inScanner);
	while(token!=G_TOKEN_EOF)
	{
		switch((guint)token)
		{
			case G_TOKEN_IDENTIFIER:
			case '*':
			case '#':
			case '.':
			case ':':
				/* Set last selector as parent if available */
				if(rule) parentRule=rule;
					else parentRule=NULL;

				/* Create new selector */
				rule=_xfdashboard_css_selector_rule_new(inScanner->input_name,
														priv->priority,
														g_scanner_cur_line(inScanner),
														g_scanner_cur_position(inScanner));
				priv->rule=rule;

				/* Check if there was a previous selector and if so, the new one
				 * should use the previous selector to match an ancestor
				 */
				if(parentRule)
				{
					rule->parentRule=parentRule;
					rule->parentRuleMode=XFDASHBOARD_CSS_SELECTOR_RULE_MODE_ANCESTOR;
				}

				/* Parse selector */
				token=_xfdashboard_css_selector_parse_css_simple_selector(self, inScanner, rule);
				if(token!=G_TOKEN_NONE) return(token);
				break;

			case '>':
				g_scanner_get_next_token(inScanner);

				/* Set last selector as parent selector */
				if(!rule)
				{
					g_scanner_unexp_token(inScanner,
											G_TOKEN_IDENTIFIER,
											NULL,
											NULL,
											NULL,
											_("No parent when parsing '>'"),
											TRUE);
					return(G_TOKEN_ERROR);
				}
				parentRule=rule;

				/* Create new selector */
				rule=_xfdashboard_css_selector_rule_new(inScanner->input_name,
														priv->priority,
														g_scanner_cur_line(inScanner),
														g_scanner_cur_position(inScanner));
				priv->rule=rule;

				/* Link parent to the new selector as parent selector */
				rule->parentRule=parentRule;
				rule->parentRuleMode=XFDASHBOARD_CSS_SELECTOR_RULE_MODE_PARENT;


				/* Parse selector */
				token=_xfdashboard_css_selector_parse_css_simple_selector(self, inScanner, rule);
				if(token!=G_TOKEN_NONE) return(token);
				break;

			default:
				/* Stop at first invalid character in stream and
				 * return with success result.
				 */
				return(G_TOKEN_NONE);
		}

		/* Continue parsing with next token */
		token=g_scanner_peek_next_token(inScanner);
	}

	/* Eat "eof" token */
	if(token==G_TOKEN_EOF) token=g_scanner_get_next_token(inScanner);

	/* Successfully parsed */
	return(G_TOKEN_EOF);
}
Exemplo n.º 8
0
/* Parse selector */
static GTokenType _xfdashboard_css_selector_parse_css_simple_selector(XfdashboardCssSelector *self,
																		GScanner *inScanner,
																		XfdashboardCssSelectorRule *ioRule)
{
	GTokenType		token;

	g_return_val_if_fail(XFDASHBOARD_IS_CSS_SELECTOR(self), G_TOKEN_ERROR);
	g_return_val_if_fail(inScanner, G_TOKEN_ERROR);
	g_return_val_if_fail(ioRule, G_TOKEN_ERROR);

	/* Parse type of selector. It is optional as '*' can be used as wildcard */
	token=g_scanner_peek_next_token(inScanner);
	switch((guint)token)
	{
		case '*':
			g_scanner_get_next_token(inScanner);
			ioRule->type=g_strdup("*");

			/* Check if next token follows directly after this identifier.
			 * It is determined by checking if scanner needs to move more than
			 * one (the next) character. If there is a gap then either a new
			 * selector follows or it is a new typeless selector.
			 */
			token=g_scanner_peek_next_token(inScanner);
			if(inScanner->next_line==g_scanner_cur_line(inScanner) &&
				(inScanner->next_position-g_scanner_cur_position(inScanner))>1)
			{
				return(G_TOKEN_NONE);
			}
			break;

		case G_TOKEN_IDENTIFIER:
			g_scanner_get_next_token(inScanner);
			ioRule->type=g_strdup(inScanner->value.v_identifier);

			/* Check if next token follows directly after this identifier.
			 * It is determined by checking if scanner needs to move more than
			 * one (the next) character. If there is a gap then either a new
			 * selector follows or it is a new typeless selector.
			 */
			token=g_scanner_peek_next_token(inScanner);
			if(inScanner->next_line==g_scanner_cur_line(inScanner) &&
				(inScanner->next_position-g_scanner_cur_position(inScanner))>1)
			{
				return(G_TOKEN_NONE);
			}
			break;

		default:
			break;
	}

	/* Here we look for '#', '.' or ':' and return if we find anything else */
	token=g_scanner_peek_next_token(inScanner);
	while(token!=G_TOKEN_NONE)
	{
		switch((guint)token)
		{
			/* Parse ID */
			case '#':
				g_scanner_get_next_token(inScanner);
				token=g_scanner_get_next_token(inScanner);
				if(token!=G_TOKEN_IDENTIFIER)
				{
					g_scanner_unexp_token(inScanner,
											G_TOKEN_IDENTIFIER,
											NULL,
											NULL,
											NULL,
											_("Invalid name identifier"),
											TRUE);
					return(G_TOKEN_ERROR);
				}

				ioRule->id=g_strdup(inScanner->value.v_identifier);
				break;

			/* Parse class */
			case '.':
				g_scanner_get_next_token(inScanner);
				token=g_scanner_get_next_token(inScanner);
				if(token!=G_TOKEN_IDENTIFIER)
				{
					g_scanner_unexp_token(inScanner,
											G_TOKEN_IDENTIFIER,
											NULL,
											NULL,
											NULL,
											_("Invalid class identifier"),
											TRUE);
					return(G_TOKEN_ERROR);
				}

				if(ioRule->classes)
				{
					/* Remember old classes as it can only be freed afterwards */
					gchar		*oldClasses=ioRule->classes;

					/* Create new list of classes */
					ioRule->classes=g_strconcat(ioRule->classes,
												".",
												inScanner->value.v_identifier,
												NULL);

					/* Now free old classes */
					g_free(oldClasses);
				}
					else
					{
						ioRule->classes=g_strdup(inScanner->value.v_identifier);
					}
				break;

			/* Parse pseudo-class */
			case ':':
				g_scanner_get_next_token(inScanner);
				token=g_scanner_get_next_token(inScanner);
				if(token!=G_TOKEN_IDENTIFIER)
				{
					g_scanner_unexp_token(inScanner,
											G_TOKEN_IDENTIFIER,
											NULL,
											NULL,
											NULL,
											_("Invalid pseudo-class identifier"),
											TRUE);
					return(G_TOKEN_ERROR);
				}

				if(ioRule->pseudoClasses)
				{
					/* Remember old pseudo-classes as it can only be freed afterwards */
					gchar		*oldPseudoClasses=ioRule->pseudoClasses;

					/* Create new list of pseudo-classes */
					ioRule->pseudoClasses=g_strconcat(ioRule->pseudoClasses,
														":",
														inScanner->value.v_identifier,
														NULL);

					/* Now free old pseudo-classes */
					g_free(oldPseudoClasses);
				}
					else
					{
						ioRule->pseudoClasses=g_strdup(inScanner->value.v_identifier);
					}
				break;

			default:
				return(G_TOKEN_NONE);
		}

		/* Get next token */
		token=g_scanner_peek_next_token(inScanner);
	}

	/* Successfully parsed */
	return(G_TOKEN_NONE);
}
Exemplo n.º 9
0
/* Get rule parsed */
XfdashboardCssSelectorRule* xfdashboard_css_selector_get_rule(XfdashboardCssSelector *self)
{
	g_return_val_if_fail(XFDASHBOARD_IS_CSS_SELECTOR(self), NULL);

	return(self->priv->rule);
}