ReferenceCountable& ReferenceCountable::operator=(const ReferenceCountable& /*copy*/)
{
    ROCKET_ERRORMSG("Attempting to copy a reference counted object. This is not advisable.");
    return *this;
}
示例#2
0
// Returns true if this node is applicable to the given element, given its IDs, classes and heritage.
bool StyleSheetNode::IsApplicable(const Element* element) const
{
	// This function is called with an element that matches a style node only with the tag name. We have to determine
	// here whether or not it also matches the required hierarchy.

	// We must have a parent; if not, something's amok with the style tree.
	if (parent == NULL)
	{
		ROCKET_ERRORMSG("Invalid RCSS hierarchy.");
		return false;
	}

	// If we've hit a child of the root of the style sheet tree, then we're done; no more lineage to resolve.
	if (parent->type == ROOT)
		return true;

	// Determine the tag (and possibly id / class as well) of the next required parent in the RCSS hierarchy.
	const StyleSheetNode* parent_node = parent;
	String ancestor_id;
	StringList ancestor_classes;
	StringList ancestor_pseudo_classes;
	std::vector< const StyleSheetNode* > ancestor_structural_pseudo_classes;

	while (parent_node != NULL && parent_node->type != TAG)
	{
		switch (parent_node->type)
		{
			case ID:						ancestor_id = parent_node->name; break;
			case CLASS:						ancestor_classes.push_back(parent_node->name); break;
			case PSEUDO_CLASS:				ancestor_pseudo_classes.push_back(parent_node->name); break;
			case STRUCTURAL_PSEUDO_CLASS:	ancestor_structural_pseudo_classes.push_back(parent_node); break;
			default:						ROCKET_ERRORMSG("Invalid RCSS hierarchy."); return false;
		}

		parent_node = parent_node->parent;
	}

	// Check for an invalid RCSS hierarchy.
	if (parent_node == NULL)
	{
		ROCKET_ERRORMSG("Invalid RCSS hierarchy.");
		return false;
	}

	// Now we know the name / class / ID / pseudo-class / structural requirements for the next ancestor requirement of
	// the element. So we look back through the element's ancestors to find one that matches.
	for (const Element* ancestor_element = element->GetParentNode(); ancestor_element != NULL; ancestor_element = ancestor_element->GetParentNode())
	{
		// Skip this ancestor if the name of the next style node doesn't match its tag name, and one was specified.
		if (!parent_node->name.Empty() 
			&& parent_node->name != ancestor_element->GetTagName())
			continue;

		// Skip this ancestor if the ID of the next style node doesn't match its ID, and one was specified.
		if (!ancestor_id.Empty() &&
			ancestor_id != ancestor_element->GetId())
			continue;

		// Skip this ancestor if the class of the next style node don't match its classes.
		bool resolved_requirements = true;
		for (size_t i = 0; i < ancestor_classes.size(); ++i)
		{
			if (!ancestor_element->IsClassSet(ancestor_classes[i]))
			{
				resolved_requirements = false;
				break;
			}
		}
		if (!resolved_requirements)
			continue;

		// Skip this ancestor if the required pseudo-classes of the style node aren't set on it.
		resolved_requirements = true;
		for (size_t i = 0; i < ancestor_pseudo_classes.size(); ++i)
		{
			if (!ancestor_element->IsPseudoClassSet(ancestor_pseudo_classes[i]))
			{
				resolved_requirements = false;
				break;
			}
		}
		if (!resolved_requirements)
			continue;

		// Skip this ancestor if the required structural pseudo-classes of the style node aren't applicable to it.
		resolved_requirements = true;
		for (size_t i = 0; i < ancestor_structural_pseudo_classes.size(); ++i)
		{
			if (!ancestor_structural_pseudo_classes[i]->selector->IsApplicable(ancestor_element, ancestor_structural_pseudo_classes[i]->a, ancestor_structural_pseudo_classes[i]->b))
			{
				resolved_requirements = false;
				break;
			}
		}
		if (!resolved_requirements)
			continue;

		return parent_node->IsApplicable(ancestor_element);
	}

	// We hit the end of the hierarchy before matching the required ancestor, so bail.
	return false;
}