コード例 #1
0
ファイル: textselection.cpp プロジェクト: snorp/moon
void
TextSelection::Insert (TextElement *element)
{
    if (anchor.GetParent() == NULL || moving.GetParent() == NULL)
        // if either are null we're going nowhere fast...
        return;

    // refactor out the "clear out selection" from SetText
    ClearSelection ();

    // at this point both anchor and moving are the same location

    // depending on what the anchor's parent is,
    // and what @element is, we might need to
    // split the tree higher up
    DependencyObject *el = anchor.GetParent ();
    int loc = anchor.ResolveLocation();

    while (el) {
        DependencyObject *el_parent = el->GetParent();
        if (el_parent)
            el_parent = el_parent->GetParent();

        IDocumentNode *node = IDocumentNode::CastToIDocumentNode (el);

        DependencyObjectCollection *children = node->GetDocumentChildren ();
        if (children && element->Is (children->GetElementType())) {
            // we can insert the element here, so let's do it and be done with things
            children->Insert (loc, element);
            return;
        }

        if (!el_parent) {
            g_warning ("new element cannot fit inside element, and we can't split it");
            return;
        }

        // we need to split the current element at
        // @loc, add the new element to el's parent
        // after el, and walk back up to el's parent
        // with new_el's index as @loc.
        IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (el_parent);
        DependencyObjectCollection *parents_children = parent_node ? parent_node->GetDocumentChildren () : NULL;
        DependencyObject *new_el = node ? node->Split (loc) : NULL;

        if (!new_el) {
            g_warning ("split failed");
            return;
        }

        int new_el_loc = parents_children->IndexOf (el) + 1;
        parents_children->Insert (new_el_loc, new_el);
        el = el_parent;
        loc = new_el_loc;
        new_el->unref ();
    }


    printf ("TextSelection::Insert\n");
}
コード例 #2
0
void
ResourceDictionary::SetInternalSourceWithError (const char* source, MoonError *error)
{
	this->source = g_strdup (source);
	if (source == NULL)
		return;

	/* we need to walk up the tree checking for resource
	   dictionaries with the same source, generate an error if it
	   matches */
	DependencyObject *p = GetParent();
	while (p) {
		if (p->Is (Type::RESOURCE_DICTIONARY)) {
			ResourceDictionary* rd = (ResourceDictionary*)p;
			const char *rd_source = rd->GetInternalSource();
			if (rd_source && !strcmp (rd_source, source)) {
				MoonError::FillIn (error,
						   MoonError::INVALID_OPERATION, /* FIXME: verify exception type */
						   "cycle found in resource dictionaries");
				return;
			}
		}
		p = p->GetParent();
	}
}
コード例 #3
0
ファイル: namescope.cpp プロジェクト: snorp/moon
gboolean
NameScope::remove_handler (gpointer key, gpointer value, gpointer data)
{
	DependencyObject *depobj = (DependencyObject*)value;
	depobj->RemoveHandler (EventObject::DestroyedEvent, NameScope::ObjectDestroyedEvent, data);
	return TRUE;
}
コード例 #4
0
bool
ResourceDictionary::Remove (const char *key)
{
	if (!key)
		return false;

	/* check if the item exists first */
	Value* orig_value;
	gpointer orig_key;

	if (!g_hash_table_lookup_extended (hash, key,
					   &orig_key, (gpointer*)&orig_value))
		return false;

	from_resource_dictionary_api = true;
	Collection::Remove (orig_value);
	from_resource_dictionary_api = false;

	DependencyObject *ob = orig_value->Is (GetDeployment (), Type::DEPENDENCY_OBJECT) ? orig_value->AsDependencyObject () : NULL;
	if (ob)
		ob->SetMentor (NULL);

	// No need to strengthen orig_value before clearing
	// because we copy it first.
	Value orig_copy (*orig_value);

	g_hash_table_remove (hash, key);

	EmitChanged (CollectionChangedActionRemove, NULL, &orig_copy, key);

	return true;
}
コード例 #5
0
ファイル: textselection.cpp プロジェクト: snorp/moon
char*
TextSelection::GetXaml ()
{
    if (anchor.GetLocation () == moving.GetLocation())
        return g_strdup ("");

    // I'm guessing this should only include ancestors (up to the
    // root) that are required to serialize the actual selection,
    // but for now let's just serialize the entire contents of the
    // RTB.

    DependencyObject *el = anchor.GetParent();
    while (el) {
        if (el->Is (Type::RICHTEXTBOX))
            break;
        el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
        if (!el)
            break;
    }
    if (el == NULL) {
        g_warning ("this shouldn't happen...");
        return NULL;
    }

    // el should be the RichTextBox now.
    GString *str = g_string_new ("");
    IDocumentNode *node = IDocumentNode::CastToIDocumentNode (el);
    node->SerializeXaml(str);
    return g_string_free (str, FALSE);
}
コード例 #6
0
static gboolean
remove_from_hash_by_value (gpointer  key,
			   gpointer  value,
			   gpointer  user_data)
{
	Value *v = (Value*)value;
	DependencyObject *obj = (DependencyObject *) user_data;
	// FIXME: clearManagedRef
	return (v->GetKind () == obj->GetObjectType () && v->AsDependencyObject() == obj);
}
コード例 #7
0
ファイル: textselection.cpp プロジェクト: 499940913/moon
char*
TextSelection::GetText ()
{
	GString *gstr;
	TextPointer tp;


	if (text)
		goto done;

	if (anchor.GetParent() == NULL ||
	    moving.GetParent() == NULL) {
		text = g_strdup ("");
		goto done;
	}

	if (anchor.GetParent() == moving.GetParent() &&
	    anchor.GetLocation () == moving.GetLocation()) {
		text = g_strdup ("");
		goto done;
	}

	gstr = g_string_new ("");
	tp = anchor;

	while (tp.CompareTo_np (moving) < 0) {
		DependencyObject *parent = tp.GetParent ();

		if (parent && parent->Is (Type::RUN)) {
			Run *run = (Run*)parent;
			if (parent == moving.GetParent()) {
				// tp and moving are in the same element, so we append the substring and set tp = moving.
				g_string_append_len (gstr, run->GetText() + tp.ResolveLocation(), moving.ResolveLocation() - tp.ResolveLocation());
				tp = moving;
			}
			else {
				g_string_append (gstr, run->GetText());
				tp = run->GetContentEnd_np();
				tp = tp.GetPositionAtOffset_np (1, tp.GetLogicalDirection());
			}
		}
		else {
			TextPointer new_tp = tp.GetPositionAtOffset_np (1, tp.GetLogicalDirection());
			if (new_tp.CompareTo_np (tp) == 0)
				break;
			tp = new_tp;
		}
	}

	text = g_string_free (gstr, FALSE);

 done:
	return g_strdup (text);
}
コード例 #8
0
ファイル: textpointer.cpp プロジェクト: 499940913/moon
DependencyObject*
PositionAtOffsetIterator::GetElementParent()
{
	if (element->Is(Type::RICHTEXTBOX))
		return NULL;
	else {
		// element is a TextElement
		DependencyObject *p = element->GetParent(); // this first GetParent returns the parent collection
		if (!p) return NULL;
		return p->GetParent(); // and this the actual parent
	}
}
コード例 #9
0
ファイル: namescope.cpp プロジェクト: snorp/moon
void
NameScope::ObjectDestroyedEvent (EventObject *sender, EventArgs *args, gpointer closure)
{
	NameScope *ns = (NameScope*)closure;
	// XXX this method worries me.. using GetName like this.
	DependencyObject *depobj = (DependencyObject*)sender;
	const char *name = depobj->GetName ();
	if (name != NULL) {
		g_hash_table_remove (ns->names, name);
	} else {
		g_hash_table_foreach_remove (ns->names, remove_object_from_namescope, depobj);
	}
}
コード例 #10
0
ファイル: textpointer.cpp プロジェクト: 499940913/moon
RichTextBox *
TextPointer::GetRichTextBox () const
{
	DependencyObject *el = GetParent();
	while (el) {
		if (el->Is (Type::RICHTEXTBOX))
			return (RichTextBox*)el;
		el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
		if (!el)
			break;
	}

	return NULL;
}
コード例 #11
0
// XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
void
ResourceDictionary::UnregisterAllNamesRootedAt (NameScope *from_ns)
{
	Value *value;
	
	for (guint i = 0; i < array->len; i++) {
		value = (Value *) array->pdata[i];
		if (value->Is (GetDeployment (), Type::DEPENDENCY_OBJECT)) {
			DependencyObject *obj = value->AsDependencyObject ();
			if (obj)
				obj->UnregisterAllNamesRootedAt (from_ns);
		}
	}
	
	Collection::UnregisterAllNamesRootedAt (from_ns);
}
コード例 #12
0
// XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
void
ResourceDictionary::OnIsAttachedChanged (bool attached)
{
	Collection::OnIsAttachedChanged (attached);

	Value *value;
	
	for (guint i = 0; i < array->len; i++) {
		value = (Value *) array->pdata[i];
		if (value->Is (GetDeployment (), Type::DEPENDENCY_OBJECT)) {
			DependencyObject *obj = value->AsDependencyObject ();
			if (obj)
				obj->SetIsAttached (attached);
		}
	}
}
コード例 #13
0
ファイル: namescope.cpp プロジェクト: snorp/moon
void
NameScope::UnregisterName (const char *name)
{
	if (GetIsLocked ())
		return;

	if (!names)
		return;

	DependencyObject *depobj = (DependencyObject*)g_hash_table_lookup (names, name);
	if (depobj) {
		depobj->RemoveHandler (EventObject::DestroyedEvent, ObjectDestroyedEvent, this);

		g_hash_table_remove (names, name);
	}
}
コード例 #14
0
// XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
void
ResourceDictionary::RegisterAllNamesRootedAt (NameScope *to_ns, MoonError *error)
{
	Value *value;
	
	for (guint i = 0; i < array->len; i++) {
		if (error->number)
			break;

		value = (Value *) array->pdata[i];
		if (value->Is (GetDeployment (), Type::DEPENDENCY_OBJECT)) {
			DependencyObject *obj = value->AsDependencyObject ();
			obj->RegisterAllNamesRootedAt (to_ns, error);
		}
	}
	
	Collection::RegisterAllNamesRootedAt (to_ns, error);
}
コード例 #15
0
ファイル: textselection.cpp プロジェクト: snorp/moon
void
TextSelection::ApplyPropertyValue (DependencyProperty *formatting, Value *value)
{
    DependencyObject *el = anchor.GetParent();
    while (el) {
        if (el->Is (Type::RICHTEXTBOX))
            break;
        el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
        if (!el)
            break;
    }
    if (el == NULL) {
        g_warning ("this shouldn't happen...");
        return;
    }

    RichTextBox *rtb = (RichTextBox*)el;

    rtb->ApplyFormattingToSelection (this, formatting, value);
}
コード例 #16
0
Variant GetDPByExpExpression::Evaluate(Expressive::EvalContext* context)
{
	Object* obj = m_object->Evaluate(context);
	DependencyObject* depObj = dynamic_cast<DependencyObject*>(obj);
	if (depObj == NULL)
	{
		VERIFY(0);
	}
	Variant propertyRef = m_exp->Evaluate(context);

	PropertyValue* pProperty;

	if (propertyRef.IsString())
		pProperty = depObj->GetProperty(depObj->GetClass()->GetLocalProperty(propertyRef.ToString()));
	else if (propertyRef.IsInt())
		pProperty = depObj->GetProperty(depObj->GetClass()->GetLocalProperty((int)propertyRef));
	else
		throw new Exception("property not found");

	return pProperty->GetComputedValue();
}
コード例 #17
0
bool GetDPByExpExpression::Set(Expressive::EvalContext* context, Variant value)
{
	Object* obj = m_object->Evaluate(context);
	DependencyObject* depObj = dynamic_cast<DependencyObject*>(obj);
	if (depObj == NULL)
	{
		VERIFY(0);
	}
	Variant propertyRef = m_exp->Evaluate(context);

	PropertyValue* pProperty;

	if (propertyRef.IsString())
		pProperty = depObj->GetProperty(depObj->GetClass()->GetLocalProperty(propertyRef.ToString()));
	else if (propertyRef.IsInt())
		pProperty = depObj->GetProperty(depObj->GetClass()->GetLocalProperty(int(propertyRef)));
	else
		raise(Exception("property not found"));

	pProperty->UpdateValue(value);
	return true;
}
コード例 #18
0
ファイル: control.cpp プロジェクト: snorp/moon
bool
Control::DoApplyTemplateWithError (MoonError *error)
{
    ControlTemplate *t = GetTemplate ();
    if (!t)
        return FrameworkElement::DoApplyTemplateWithError (error);

    // If the template expands to an element which is *not* a UIElement
    // we don't apply the template.
    DependencyObject *root = t->GetVisualTreeWithError (this, error);
    if (root && !root->Is (Type::UIELEMENT)) {
        g_warning ("Control::DoApplyTemplate () Template root was not a UIElement");
        root->unref ();
        root = NULL;
    }

    if (!root)
        return FrameworkElement::DoApplyTemplateWithError (error);

    // No need to ref template_root here as ElementAdded refs it
    // and it is cleared when ElementRemoved is called.
    if (template_root != root && template_root != NULL) {
        template_root->SetParent (NULL, NULL);
        template_root->SetMentor (NULL);
        template_root = NULL;
    }

    template_root = (UIElement *) root;

    ElementAdded (template_root);

    if (IsLoaded ())
        GetDeployment ()->EmitLoadedAsync ();

    root->unref ();

    return true;
}
コード例 #19
0
// XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
void
ResourceDictionary::RemovedFromCollection (Value *value, bool is_value_safe)
{
	if (is_value_safe & value->Is (GetDeployment (), Type::DEPENDENCY_OBJECT)) {
		DependencyObject *obj = value->AsDependencyObject ();

		if (obj) {
			obj->RemovePropertyChangeListener (this);
			obj->RemoveParent (this, NULL);
			obj->SetIsAttached (false);
		}
	}

	Collection::RemovedFromCollection (value, is_value_safe);

	if (is_value_safe && value->Is (GetDeployment (), Type::DEPENDENCY_OBJECT)) {
		if (!from_resource_dictionary_api && value->AsDependencyObject()) {
			g_hash_table_foreach_remove (hash, remove_from_hash_by_value, value->AsDependencyObject ());

			// FIXME we need to EmitChanged something here so the managed RD can remain in sync
		}
	}
}
コード例 #20
0
// XXX this was (mostly, except for the type check) c&p from DependencyObjectCollection
bool
ResourceDictionary::AddedToCollection (Value *value, MoonError *error)
{
	DependencyObject *obj = NULL;
	bool rv = false;
	
	if (value->Is(GetDeployment (), Type::DEPENDENCY_OBJECT)) {
		obj = value->AsDependencyObject ();
		// Call SetSurface() /before/ setting the logical parent
		// because Storyboard::SetSurface() needs to be able to
		// distinguish between the two cases.
		if (obj->GetParent () && !can_be_added_twice (GetDeployment (), value)) {
			MoonError::FillIn (error, MoonError::INVALID_OPERATION, g_strdup_printf ("Element is already a child of another element.  %s", GetTypeName ()));
			return false;
		}
		obj->AddParent (this, error);
		if (error->number)
			return false;
		
		obj->SetIsAttached (IsAttached ());


		obj->AddPropertyChangeListener (this);

		if (!from_resource_dictionary_api) {
			const char *key = obj->GetName();

			if (!key) {
				MoonError::FillIn (error, MoonError::ARGUMENT_NULL, "key was null");
				goto cleanup;
			}

			if (ContainsKey (key)) {
				MoonError::FillIn (error, MoonError::ARGUMENT, "An item with the same key has already been added");
				goto cleanup;
			}
		}
	}

	rv = Collection::AddedToCollection (value, error);

	if (rv && !from_resource_dictionary_api && obj != NULL) {
		const char *key = obj->GetName();

		Value *obj_value = new Value (obj);

		g_hash_table_insert (hash, g_strdup (key), obj_value);

		obj_value->Weaken (GetDeployment ());
		EmitChanged (CollectionChangedActionAdd, obj_value, NULL, key);
	}

cleanup:
	if (!rv) {
		if (obj) {
			/* If we set the parent, but the object wasn't added to the collection, make sure we clear the parent */
			printf ("ResourceDictionary::AddedToCollection (): not added, clearing parent from %p\n", obj);
			obj->RemoveParent (this, NULL);
		}
	}

	return rv;
}
コード例 #21
0
ファイル: textselection.cpp プロジェクト: 499940913/moon
void
TextSelection::ClearSelection ()
{
	// clear out the selection
	if (anchor.GetParent() == moving.GetParent()) {
		bool remove_element = false;

		if (anchor.GetLocation () != moving.GetLocation()) {

			if (anchor.GetParent()->Is (Type::RUN)) {
				Run *run = (Run*)anchor.GetParent();
				char *run_text = g_strdup (run->GetText());

				if (run_text) {
					int length_to_remove = moving.ResolveLocation() - anchor.ResolveLocation();
					
					memmove (run_text + anchor.ResolveLocation(), run_text + moving.ResolveLocation (), strlen (run_text + moving.ResolveLocation()));
					*(run_text + strlen(run_text) - length_to_remove) = 0;

					run->SetText (run_text);

					// we need to remove the run if we've cleared all the text in it
					remove_element = !*run_text;
				} 
				else {
					remove_element = true;
				}
				g_free (run_text);
			}
			else {
				IDocumentNode *node = anchor.GetParentNode();

				int length_to_remove = moving.ResolveLocation() - anchor.ResolveLocation();

				for (int i = 0; i < length_to_remove; i ++)
					node->GetDocumentChildren()->RemoveAt (anchor.ResolveLocation());

				// we need to remove the element if we've removed all the children
				remove_element = node->GetDocumentChildren()->GetCount() == 0;
			}
		}

		DependencyObject *el = anchor.GetParent();
		while (remove_element) {
			if (el->Is (Type::RICHTEXTBOX))
				break;

			DependencyObject* parent = el->GetParent() ? el->GetParent()->GetParent() : NULL;
			if (!parent) {
				g_warning ("shouldn't happen");
				return;
			}

			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			parent_node->GetDocumentChildren()->Remove (Value(el));

			el = parent;
			remove_element = parent_node->GetDocumentChildren()->GetCount() == 0;
		}
	}
	else {
		// harder case, anchor/moving are in different elements
		printf ("NIEX hard case TextSelection::ClearSelection\n");
	}

	g_free (text);
	text = NULL;

	g_free (xaml);
	xaml = NULL;
}
コード例 #22
0
ファイル: textselection.cpp プロジェクト: 499940913/moon
char*
TextSelection::GetXaml ()
{
	const char *header = "<Section xml:space=\"preserve\" HasTrailingParagraphBreakOnPaste=\"False\" xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">";
	const char *trailer = "</Section>";

	GString *str;
	ArrayList ancestors;
	DependencyObject *el;

	if (xaml)
		goto done;

	if (!anchor.GetParent() || !moving.GetParent()) {
		xaml = g_strdup ("");
		goto done;
	}

	if (anchor.GetParent() == moving.GetParent() && anchor.GetLocation () == moving.GetLocation()) {
		xaml = g_strdup ("");
		goto done;
	}

	str = g_string_new (header);

	// first we serialize the xaml start elements for all
	// TextElements that contain the selection start (but not the
	// most deeply nested element itself)

	el = anchor.GetParent();
	if (el && !el->Is (Type::RICHTEXTBOX)) {
		// skip anchor.GetParent() here.
		el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
		while (el) {
			if (el->Is (Type::RICHTEXTBOX))
				break;
			ancestors.Add (el);
			el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
			if (!el)
				break;
		}
	}

	for (int i = ancestors.GetCount() - 1; i >= 0; i --) {
		TextElement *te = (TextElement*)ancestors[i];
		IDocumentNode *node = IDocumentNode::CastToIDocumentNode (te);
		node->SerializeXamlStartElement (str);
	}




	// now we output the start element (and deal with the case where start_element == end_element)
	el = anchor.GetParent ();
	if (el->Is (Type::RUN)) {
		if (el == moving.GetParent()) {
			// if both textpointers are in the same
			// element, we need to use start+length form
			((Run*)el)->SerializeXaml (str, anchor.ResolveLocation (), moving.ResolveLocation () - anchor.ResolveLocation());
		}
		else {
			// since the moving textpointer is outside
			// this run, we just use the start form.
			((Run*)el)->SerializeXaml (str, anchor.ResolveLocation ());
		}
	}
	else {
		((TextElement*)el)->SerializeXaml (str);
	}

	if (anchor.GetParent() != moving.GetParent()) {
		// now walk the document from start element to end element, outputting everything manually along the way.
		DocumentWalker walker (anchor.GetParentNode(), DocumentWalker::Forward);
		IDocumentNode *node;
		DocumentWalker::StepType stepType;

		stepType = walker.Step (); // step out of the start element

		while (stepType != DocumentWalker::Done) {
			stepType = walker.Step (&node);

			if (node == moving.GetParentNode())
				break;
			if (stepType == DocumentWalker::Enter)
				node->SerializeXamlStartElement(str);
			else
				node->SerializeXamlEndElement(str);
		}

		// now we output the end element
		el = moving.GetParent ();
		if (el->Is (Type::RUN)) {
			((Run*)el)->SerializeXaml (str, 0, moving.ResolveLocation ());
		}
		else {
			((TextElement*)el)->SerializeXaml (str);
		}
	}

	// now serialize the xaml end elements for all TextElements
	// that contain the selection end (but not the most deeply
	// nested element itself)

	if (anchor.GetParent() == moving.GetParent ()) {
		// this case is trivial, we just output the same list
		// of end elements that we outputted the start
		// elements before
		for (int i = ancestors.GetCount() - 1; i >= 0; i --) {
			TextElement *te = (TextElement*)ancestors[i];
			IDocumentNode *node = IDocumentNode::CastToIDocumentNode (te);
			node->SerializeXamlEndElement (str);
		}
	}
	else {
		ancestors.SetCount (0);

		DependencyObject *el = moving.GetParent();
		if (el && !el->Is (Type::RICHTEXTBOX)) {
			// skip moving.GetParent() here.
			el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
			while (el) {
				if (el->Is (Type::RICHTEXTBOX))
					break;
				ancestors.Add (el);
				el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
				if (!el)
					break;
			}
		}

		for (int i = ancestors.GetCount() - 1; i >= 0; i --) {
			TextElement *te = (TextElement*)ancestors[i];
			IDocumentNode *node = IDocumentNode::CastToIDocumentNode (te);
			node->SerializeXamlEndElement (str);
		}
	}

	g_string_append (str, trailer);

	xaml = g_string_free (str, FALSE);

 done:
	return g_strdup (xaml);
}
コード例 #23
0
ファイル: dependencyproperty.cpp プロジェクト: lewing/moon
//
// Everything inside of a ( ) resolves to a DependencyProperty, if there is a
// '.' after the property, we get the object, and continue resolving from there
// if there is a [n] after the property, we convert the property to a collection
// and grab the nth item.
//
// Dependency properties can be specified as (PropertyName) of the current object
// or they can be specified as (DependencyObject.PropertyName).
//
// Returns NULL on any error
//
DependencyProperty *
resolve_property_path (DependencyObject **o, PropertyPath *propertypath, GHashTable *promoted_values)
{
	g_return_val_if_fail (o != NULL, NULL);
	g_return_val_if_fail (propertypath != NULL, NULL);
	g_return_val_if_fail (propertypath->path != NULL || propertypath->property != NULL, NULL);
	
	if (propertypath->property)
		return propertypath->property;

	const char *path = propertypath->path;
	if (propertypath->expanded_path)
		path = propertypath->expanded_path;

	const char *inend = path + strlen (path);
	register const char *inptr = path;
	const char *start, *prop = path;
	bool expression_found = false;
	DependencyProperty *res = NULL;
	DependencyObject *lu = *o;
	Collection *collection;
	char *p, *name = NULL;
	Value *value = NULL;
	Type *type = NULL;
	int index;
	bool paren_open = false;
	bool tick_open = false;
	bool cloned = false;

	while (inptr < inend) {
		switch (*inptr++) {
		case '(':
			paren_open = true;
			break;
		case ')':
			paren_open = false;
			break;
		case '\'':
			// Ticks are only legal in expanded paths, so we should just fail here
			if (!propertypath->expanded_path) {
				g_warning ("The ' character is not legal in property paths.");
				break;
			}

			tick_open = !tick_open;
			break;
		case '.':
			if (tick_open)
				continue;

			// resolve the dependency property
			if (res) {
				DependencyObject *new_lu;

				// make sure that we are getting what we expect
				if (!(value = lu->GetValue (res)))
					goto error;

				if (!(new_lu = value->AsDependencyObject ()))
					goto error;

				if (!cloned && !g_hash_table_lookup (promoted_values, value) && !value->Is (lu->GetDeployment (), Type::UIELEMENT)) {
					// we need to clone the value here so that we deep copy any
					// DO subclasses (such as brushes, etc) that we're promoting
					// from a shared space (Styles, default values)
					Value *cloned_value = Value::Clone (value);
					
					DependencyObject *cloned_do = cloned_value->AsDependencyObject();
					if (cloned_do != NULL) {
						new_lu = cloned_do;
						lu->SetValue (res, cloned_value);
						delete cloned_value;
						
						cloned_value = lu->GetValue (res);
						g_hash_table_insert (promoted_values, cloned_value, cloned_value);
					}
				}

				lu = new_lu;
			}
			
			expression_found = false;
			prop = inptr;
			break;
		case '[':
			// Need to be a little more loving
			if (*inptr == '\0')
				break;
			
			index = strtol (inptr, &p, 10);
			if (*p != ']' || *(p + 1) != '.')
				break;
			
			inptr = p + 2;
			prop = inptr;

			if (expression_found) {
				expression_found = false;
				if (!(value = lu->GetValue (res)))
					goto error;
			}
			
			if (value == NULL)
				goto error;
			
			if (!(collection = value->AsCollection ()))
				goto error;

			if (!(value = collection->GetValueAt (index)))
				goto error;
			
			if (!(lu = value->AsDependencyObject ()))
				goto error;
			
			break;
		
		default:
			bool explicit_type = false;
			expression_found = true;
			start = inptr - 1;

			while (inptr < inend && (*inptr != '.' || tick_open) && (!paren_open || *inptr != ')') && *inptr != '[') {
				if (*inptr == '\'') {
					tick_open = !tick_open;
					if (!tick_open) {
						inptr++;
						break;
					}
				}
				inptr++;
			}

			if (inptr == start)
				goto error;

			if (*inptr == '.') {
				// we found a type name, now we need to find the property name
				if ((inptr - start) == 11 && !g_ascii_strncasecmp (start, "TextElement", 11)) {
					// Some Beta versions of Blend had a bug where they would save the TextBlock
					// properties as TextElement instead. Since Silverlight 1.0 works around this
					// bug, we should too. Fixes http://silverlight.timovil.com and
					// http://election.msn.com/podium08.aspx.
					type = Type::Find (lu->GetDeployment (), "TextBlock");
					explicit_type = true;
				} else {
					const char *s = inptr;
					if (*(inptr -1) == '\'' && !tick_open) {
						s = inptr - 1;
					}
					name = g_strndup (start, s - start);
					type = lookup_type (lu, name);
					explicit_type = true;
					if (!type)
						type = lu->GetType ();
					g_free (name);
				}
				
				inptr++;
				start = inptr;
				while (inptr < inend && (!paren_open || *inptr != ')') && (*inptr != '.' || tick_open)) {
					if (*inptr == '\'') {
						tick_open = !tick_open;
						if (!tick_open) {
							inptr++;
							break;
						}
					}
					inptr++;
				}
				
				if (inptr == start)
					goto error;
			} else {
				type = lu->GetType ();
				explicit_type = false;
			}
			
			if ((*inptr != ')' && paren_open) || !type)
				goto error;

			name = g_strndup (start, inptr - start);
			if (!(res = DependencyProperty::GetDependencyProperty (type, name)) && lu)
				res = DependencyProperty::GetDependencyProperty (lu->GetType (), name);

			if (!res) {
				g_free (name);
				goto error;
			}

			if (!res->IsAttached () && !lu->Is (type->GetKind ())) {
				// We try to be gracefull here and do something smart...
				if (!(res = DependencyProperty::GetDependencyProperty (lu->GetType (), name))) {
					g_free (name);
					goto error;
				}
			}
			
			if (res->IsAttached () && explicit_type && !paren_open)
				goto error;
			
			g_free (name);
			break;
		}
	}
	
	*o = lu;
	return res;
	
 error:
	*o = NULL;	
	return NULL;
}
コード例 #24
0
ファイル: textselection.cpp プロジェクト: 499940913/moon
void
TextSelection::Insert (TextElement *element)
{
	if (anchor.GetParent() == NULL || moving.GetParent() == NULL)
		// if either are null we're going nowhere fast...
		return;

	ClearSelection ();

	// at this point both anchor and moving are the same location

	// depending on what the anchor's parent is,
	// and what @element is, we might need to
	// split the tree higher up
	DependencyObject *el = anchor.GetParent ();
	int loc = anchor.ResolveLocation();

	while (el) {
		DependencyObject *el_parent = el->GetParent();
		if (el_parent)
			el_parent = el_parent->GetParent();

		IDocumentNode *node = IDocumentNode::CastToIDocumentNode (el);

		DependencyObjectCollection *children = node->GetDocumentChildren ();
		if (children && element->Is (children->GetElementType())) {
			// we can insert the element here, so let's do it and be done with things
			children->Insert (loc, element);
			return;
		}

		if (!el_parent) {
			g_warning ("new element cannot fit inside element, and we can't split it");
			return;
		}
				
		// we need to split the current element at
		// @loc, add the new element to el's parent
		// after el, and walk back up to el's parent
		// with new_el's index as @loc.
		IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (el_parent);
		DependencyObjectCollection *parents_children = parent_node ? parent_node->GetDocumentChildren () : NULL;

		if (parents_children == NULL)
			return; /* #rtx24 */

		DependencyObject *new_el;
		if (element->Is (el->GetObjectType()) /* a more precise check perhaps?  instead of subclass? */) {
			// we don't need to split the node.  we just
			// need to reach in and reparent children
			// after @loc into element.
			new_el = node ? node->Split (loc, element) : NULL;
		}
		else {
			new_el = node ? node->Split (loc) : NULL;
		}

		int new_el_loc = parents_children->IndexOf (el) + 1;

		if (new_el)
			parents_children->Insert (new_el_loc, new_el);

		el = el_parent;
		loc = new_el_loc;
		if (new_el && new_el != element)
			new_el->unref ();

		if (new_el == element) {
			// we've already inserted the element as part of the split.
			return;
		}
	}

	printf ("NIEX TextSelection::Insert\n");
}
コード例 #25
0
ファイル: textpointer.cpp プロジェクト: 499940913/moon
TextPointer
TextPointer::GetPositionInsideRun (int offset) const
{
	DependencyObject *parent = GetParent ();
	if (parent == NULL)
		return *this;

	if (offset > 0) {
		if (parent->Is(Type::RUN)) {
			int location = ResolveLocation ();
			const char *text = ((Run*)parent)->GetText();
			if ((guint)location < strlen (text))
				return GetPositionAtOffset_np (1, LogicalDirectionForward);
		}

		// we're at the end of the run (or not in a run at all).  we need to walk the document until we hit another run.
		DocumentWalker walker (IDocumentNode::CastToIDocumentNode (parent), DocumentWalker::Forward);
		walker.Step ();

		while (true) {
			IDocumentNode *node;
			DocumentWalker::StepType type = walker.Step (&node);

			switch (type) {
			case DocumentWalker::Done:
				// there is no position beyond this
				return *this;
			case DocumentWalker::Enter:
				if (node->AsDependencyObject()->Is(Type::RUN))
					return ((Run*)node->AsDependencyObject())->GetContentStart_np();
				break;
			case DocumentWalker::Leave:
				// do nothing here
				break;
			}
		}
	}
	else {
		if (parent->Is(Type::RUN)) {
			int location = ResolveLocation ();
			if (location > 0)
				return GetPositionAtOffset_np (-1, LogicalDirectionForward);
		}

		// we're at the start of the run (or not in a run at all).  we need to walk the document until we hit another run.
		DocumentWalker walker (IDocumentNode::CastToIDocumentNode (parent), DocumentWalker::Backward);
		walker.Step ();

		while (true) {
			IDocumentNode *node;
			DocumentWalker::StepType type = walker.Step (&node);

			switch (type) {
			case DocumentWalker::Done:
				// there is no position before this
				return *this;
			case DocumentWalker::Enter:
				if (node->AsDependencyObject()->Is(Type::RUN))
					return ((Run*)node->AsDependencyObject())->GetContentEnd_np();
				break;
			case DocumentWalker::Leave:
				// do nothing here
				break;
			}
		}
	}

	return *this;
}
コード例 #26
0
ファイル: textpointer.cpp プロジェクト: 499940913/moon
bool
PositionAtOffsetIterator::Step (int *offset)
{
	if (element == NULL)
		return false;

	if (*offset == 0) {
		// we're done stepping.  element/location should be valid.
		return false;
	}

	if (*offset < 0) {
		// we're stepping backward

		if (location == CONTENT_START) {
			// we're stepping backward but we're currently
			// at element's ContentStart.  we need to step
			// up into our parent
			DependencyObject *parent = GetElementParent();

			if (!parent) {
				// we can't back up anymore.  result is NULL.
				element = NULL;
				return true;
			}

			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			(*offset) ++;	
			location = parent_node->GetDocumentChildren()->IndexOf (Value (element));
			element = parent;
			return true;
		}

		if (element->Is (Type::RUN)) {
			const char *text = ((Run*)element)->GetText();
			guint32 textlen = strlen (text);

			if (location == CONTENT_END)
				location = textlen;

			if (location + *offset < CONTENT_START) {
				// bump up to the parent after adding the location to our offset
				*offset += location;
				location = CONTENT_START;
				return true;
			}
			else {
				// the operation can be satisfied completely inside this run
				location += *offset;
				*offset = 0;
				return false;
			}
		}
		else {
			IDocumentNode *node = IDocumentNode::CastToIDocumentNode (element);
			DependencyObjectCollection *doc_children = node->GetDocumentChildren();
			int children_count = doc_children ? doc_children->GetCount() : 0;
			if (children_count) {
				if (location == CONTENT_END)
					location = children_count;

				element = node->GetDocumentChildren()->GetValueAt(location-1)->AsTextElement();
				(*offset) ++;
				location = CONTENT_END;
				return true;
			}
			else {
				// not a Run, but also doesn't have children
				DependencyObject *parent = GetElementParent();

				if (!parent) {
					// we can't back up anymore.  result is NULL.
					element = NULL;
					return true;
				}

				IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
				(*offset) ++;
				location = parent_node->GetDocumentChildren()->IndexOf (Value (element));
				element = parent;
				return true;
			}
		}
	}
	else /* if offset > 0 */ {
		if (location == CONTENT_END) {
			// we're stepping forward but we're currently
			// at element's ContentEnd.  we need to step
			// up into our parent
			DependencyObject *parent = GetElementParent();

			if (!parent) {
				// we can't step forward anymore.  result is NULL.
				element = NULL;
				return true;
			}

			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			(*offset) --;
			location = parent_node->GetDocumentChildren()->IndexOf (Value (element));
			if ((int)location == parent_node->GetDocumentChildren()->GetCount() - 1)
				location = CONTENT_END;
			else
				location ++;

			element = parent;
			return true;
		}

		if (element->Is (Type::RUN)) {
			const char *text = ((Run*)element)->GetText();

			if (text == NULL) {
				(*offset) --;
				location = CONTENT_END;
				return true;
			}

			guint32 textlen = strlen (text);

			if (location + *offset >= textlen) {
				// bump up to the parent after subtracting the remaining length of the run from offset
				*offset = location + *offset - textlen;
				location = CONTENT_END;
				return true;
			}
			else {
				// the operation can be satisfied completely inside this run
				location += *offset;
				*offset = 0;
				return false;
			}
		}
		else {
			IDocumentNode *node = IDocumentNode::CastToIDocumentNode (element);
			DependencyObjectCollection *doc_children = node->GetDocumentChildren();
			int children_count = doc_children ? doc_children->GetCount() : 0;

			if (children_count > 0) {
				if ((int)location > children_count - 1) {
					DependencyObject *parent = GetElementParent();

					if (!parent) {
						// we can't step forward anymore.  result is NULL.
						element = NULL;
						return true;
					}

					IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
					(*offset) --;
					location = parent_node->GetDocumentChildren()->IndexOf (Value (element)) + 1;
					if ((int)location == children_count - 1)
						location = CONTENT_END;
					element = parent;
					return true;
				}
				else {
					element = node->GetDocumentChildren()->GetValueAt(location)->AsTextElement();
					(*offset) --;
					location = CONTENT_START;
					return true;
				}
			}
			else {
				// not a Run, but also doesn't have children
				DependencyObject *parent = GetElementParent();

				if (!parent) {
					// we can't step forward anymore.  result is NULL.
					element = NULL;
					return true;
				}

				IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
				(*offset) --;
				location = parent_node->GetDocumentChildren()->IndexOf (Value (element)) + 1;
				if ((int)location == children_count - 1)
					location = CONTENT_END;
				element = parent;
				return true;
			}
		}
	}
}
コード例 #27
0
ファイル: textpointer.cpp プロジェクト: 499940913/moon
int
TextPointer::CompareToWithError (const TextPointer *pointer, MoonError *error) const
{
	if (!verify_textpointer_in_document (this, error) ||
	    !verify_textpointer_in_document (pointer, error))
		return -1;

	if (this->GetParent() == pointer->GetParent()) {
		DependencyObjectCollection *children = this->GetParentNode()->GetDocumentChildren();
		if (children && children->GetCount() > 0)
			return compare_locations (this->GetLocation(), pointer->GetLocation());
		else
			return this->ResolveLocation() - pointer->ResolveLocation();
	}
	else {
		GPtrArray *this_array = g_ptr_array_new();
		GPtrArray *pointer_array = g_ptr_array_new();

		DependencyObject *el = GetParent();
		while (el) {
			g_ptr_array_insert (this_array, 0, el);
			if (el->Is (Type::RICHTEXTBOX))
				break;
			el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
			if (!el)
				break;
		}

		el = pointer->GetParent();
		while (el) {
			g_ptr_array_insert (pointer_array, 0, el);
			if (el->Is (Type::RICHTEXTBOX))
				break;
			el = el->GetParent() ? el->GetParent()->GetParent() : NULL;
			if (!el)
				break;
		}

		guint32 count_to_compare = MIN (this_array->len, pointer_array->len);

		for (guint32 i = 0; i < count_to_compare; i ++) {
			DependencyObject *this_el = (DependencyObject*)g_ptr_array_index (this_array, i);
			DependencyObject *pointer_el = (DependencyObject*)g_ptr_array_index (pointer_array, i);

			if (this_el == pointer_el)
				continue;

			if (i == 0) {
				// this shouldn't happen... there shouldn't be a difference between two paths on the first element, since that should always be a RTB
				int rv = this_array->len < pointer_array->len ? -1 : 1;
				g_ptr_array_free (this_array, TRUE);
				g_ptr_array_free (pointer_array, TRUE);
				return rv;
			}

			/* at this point this_el and pointer_el are
			   different.  check index i-1's idea of their
			   positions */
			DependencyObject *common_parent = (DependencyObject*)g_ptr_array_index (this_array, i-1);
			IDocumentNode *common_parent_node = IDocumentNode::CastToIDocumentNode (common_parent);
			int this_index = common_parent_node->GetDocumentChildren()->IndexOf (Value (this_el));
			int pointer_index = common_parent_node->GetDocumentChildren()->IndexOf (Value (pointer_el));
			g_ptr_array_free (this_array, TRUE);
			g_ptr_array_free (pointer_array, TRUE);
			return this_index < pointer_index ? -1 : 1;
		}

		// if we make it here, it means we've run through
		// "count_to_compare" items that were identical, and
		// one of the paths is longer (so represents a child
		// of items[count_to_compare].

		// so we need to figure out which array has more
		// elements, then compare that against the other
		// TextPointer's location

		if (count_to_compare < this_array->len) {
			// @this's parent is a child of pointer_array[count_to_compare-1]
			DependencyObject *parent = (DependencyObject*)g_ptr_array_index(pointer_array, count_to_compare - 1);
			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			guint32 child_index = parent_node->GetDocumentChildren()->IndexOf (Value ((DependencyObject*)g_ptr_array_index(this_array, count_to_compare)));

			return pointer->GetLocation() > child_index ? -1 : 1;
		}
		else if (count_to_compare < pointer_array->len) {
			// @pointer's parent is a child of this_array[count_to_compare-1]
			DependencyObject *parent = (DependencyObject*)g_ptr_array_index(this_array, count_to_compare - 1);
			IDocumentNode *parent_node = IDocumentNode::CastToIDocumentNode (parent);
			guint32 child_index = parent_node->GetDocumentChildren()->IndexOf (Value ((DependencyObject*)g_ptr_array_index(pointer_array, count_to_compare)));

			return child_index >= this->GetLocation () ? -1 : 1;
		}
	}
	return -1;
}
コード例 #28
0
bool
ResourceDictionary::AddWithError (const char* key, Value *value, MoonError *error)
{
	if (!key) {
		MoonError::FillIn (error, MoonError::ARGUMENT_NULL, "key was null");
		return false;
	}

	Value *v = NULL;
	gpointer orig_key;

	gboolean exists = g_hash_table_lookup_extended (hash, key,
							&orig_key, (gpointer*)&v);

	if (exists) {
		MoonError::FillIn (error, MoonError::ARGUMENT, "An item with the same key has already been added");
		return false;
	}

	v = new Value (*value);
	
	from_resource_dictionary_api = true;
	bool result = Collection::AddWithError (v, error) != -1;
	from_resource_dictionary_api = false;
	if (result) {
		g_hash_table_insert (hash, g_strdup (key), v);

		v->Weaken (GetDeployment ());

		EmitChanged (CollectionChangedActionAdd, v, NULL, key);

		if (!strncmp (key, INTERNAL_TYPE_KEY_MAGIC_COOKIE, sizeof (INTERNAL_TYPE_KEY_MAGIC_COOKIE) - 1)
		    && v->Is (GetDeployment (), Type::STYLE)) {
			DependencyObject *p = GetParent();
			if (!p)
				return result;

			Style *style = v->AsStyle();

			if (p->Is (Type::APPLICATION)) {
				// we modified the application's resources, so we need to traverse all layers

				CollectionIterator *iterator = p->GetDeployment()->GetSurface()->GetLayers()->GetIterator();
				while (iterator->Next (NULL)) {
					Value *v = iterator->GetCurrent(NULL);
					FrameworkElement *fwe = v->AsFrameworkElement();

					fwe->StyleResourceChanged (key, style);
				}

				delete iterator;
			}
			else if (p->Is (Type::FRAMEWORKELEMENT)) {
				// just traverse down from this frameworkelement
				((FrameworkElement*)p)->StyleResourceChanged (key, style);
			}
		}

	} else {
		delete v;
	}
	return result;
}