1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * xaml.cpp: xaml parser
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
30 #include "animation.h"
31 #include "bitmapimage.h"
33 #include "projection.h"
34 #include "textblock.h"
42 #include "namescope.h"
49 #include "application.h"
50 #include "thickness.h"
51 #include "cornerradius.h"
52 #include "deployment.h"
54 #include "deepzoomimagetilesource.h"
55 #include "managedtypeinfo.h"
58 class XamlElementInfo
;
59 class XamlElementInstance
;
62 class DefaultNamespace
;
65 class PrimitiveNamespace
;
66 class MCIgnorableNamespace
;
67 class XamlElementInfoNative
;
68 class XamlElementInstanceNative
;
69 class XamlElementInstanceValueType
;
70 class XamlElementInfoEnum
;
71 class XamlElementInstanceEnum
;
72 class XamlElementInfoManaged
;
73 class XamlElementInstanceManaged
;
74 class XamlElementInfoImportedManaged
;
75 class XamlElementInstanceTemplate
;
77 #define INTERNAL_IGNORABLE_ELEMENT "MoonlightInternalIgnorableElement"
79 #define IS_NULL_OR_EMPTY(str) (!str || (*str == 0))
81 static DefaultNamespace
*default_namespace
= NULL
;
82 static XNamespace
*x_namespace
= NULL
;
83 static XmlNamespace
*xml_namespace
= NULL
;
85 static const char* default_namespace_names
[] = {
86 "http://schemas.microsoft.com/winfx/2006/xaml/presentation",
87 "http://schemas.microsoft.com/client/2007",
88 "http://schemas.microsoft.com/xps/2005/06",
89 "http://schemas.microsoft.com/client/2007/deployment",
93 #define X_NAMESPACE_URI "http://schemas.microsoft.com/winfx/2006/xaml"
94 #define XML_NAMESPACE_URI "http://www.w3.org/XML/1998/namespace"
95 #define PRIMITIVE_NAMESPACE_URI "clr-namespace:System;assembly=mscorlib"
96 #define MC_IGNORABLE_NAMESPACE_URI "http://schemas.openxmlformats.org/markup-compatibility/2006"
99 static bool value_from_str_with_parser (XamlParserInfo
*p
, Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
, bool *v_set
);
100 static bool dependency_object_set_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
, bool raise_errors
);
101 static bool set_managed_attached_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
);
102 static void dependency_object_add_child (XamlParserInfo
*p
, XamlElementInstance
*parent
, XamlElementInstance
*child
, bool fail_if_no_prop
);
103 static void dependency_object_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
);
104 static void value_type_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
);
105 static bool element_begins_buffering (Type::Kind kind
);
106 static bool is_managed_kind (Type::Kind kind
);
107 static bool kind_requires_managed_load (Type::Kind kind
);
108 static bool is_legal_top_level_kind (Type::Kind kind
);
109 static Value
*lookup_resource_dictionary (ResourceDictionary
*rd
, const char *name
, bool *exists
);
110 static void parser_error (XamlParserInfo
*p
, const char *el
, const char *attr
, int error_code
, const char *format
, ...);
111 static gboolean
namespace_for_prefix (gpointer key
, gpointer value
, gpointer user_data
);
113 static XamlElementInfo
*create_element_info_from_imported_managed_type (XamlParserInfo
*p
, const char *name
, const char **attr
, bool create
);
114 static void destroy_created_namespace (gpointer data
, gpointer user_data
);
117 BUFFER_MODE_TEMPLATE
,
122 class XamlNamespace
{
133 virtual ~XamlNamespace () { }
134 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
) = 0;
135 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
) = 0;
137 virtual const char* GetUri () = 0;
138 virtual const char* GetPrefix () = 0;
142 add_namespace_data (gpointer key
, gpointer value
, gpointer user_data
)
144 XamlNamespace
*ns
= (XamlNamespace
*) value
;
145 GHashTable
*table
= (GHashTable
*) user_data
;
147 if ((void *)ns
!= (void *)default_namespace
)
148 g_hash_table_insert (table
, g_strdup (ns
->GetPrefix ()), g_strdup (ns
->GetUri ()));
152 add_namespace_to_ignorable (gpointer key
, gpointer value
, gpointer user_data
)
154 char *prefix
= (char *) key
;
155 char *uri
= (char *) value
;
156 GString
*str
= (GString
*) user_data
;
158 g_string_append_printf (str
, "xmlns:%s=\"%s\" ", prefix
, uri
);
161 class XamlContextInternal
{
165 FrameworkTemplate
*template_parent
;
166 GHashTable
*imported_namespaces
;
167 XamlLoaderCallbacks callbacks
;
169 XamlContextInternal
*parent_context
;
171 DependencyObject
*source
;
173 XamlContextInternal (XamlLoaderCallbacks callbacks
, Value
*top_element
, FrameworkTemplate
*template_parent
, GHashTable
*namespaces
, GSList
*resources
, XamlContextInternal
*parent_context
)
175 this->callbacks
= callbacks
;
176 this->top_element
= new Value (*top_element
);
177 this->template_parent
= template_parent
;
178 this->resources
= resources
;
179 this->parent_context
= parent_context
;
181 if (this->callbacks
.create_gchandle
)
182 this->callbacks
.create_gchandle ();
183 imported_namespaces
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
184 g_hash_table_foreach (namespaces
, add_namespace_data
, imported_namespaces
);
188 ~XamlContextInternal ()
190 if (imported_namespaces
)
191 g_hash_table_destroy (imported_namespaces
);
193 g_slist_free (resources
);
197 char *CreateIgnorableTagOpen ()
199 GString
*str
= g_string_new ("<" INTERNAL_IGNORABLE_ELEMENT
" ");
200 g_hash_table_foreach (imported_namespaces
, add_namespace_to_ignorable
, str
);
202 str
= g_string_append (str
, ">");
204 char *res
= str
->str
;
205 g_string_free (str
, false);
210 char *CreateIgnorableTagClose ()
212 return g_strdup ("</" INTERNAL_IGNORABLE_ELEMENT
">");
215 bool LookupNamedItem (const char* name
, Value
**v
)
221 GSList
*walk
= resources
;
223 DependencyObject
*dob
= (DependencyObject
*)walk
->data
;
224 if (dob
->Is (Type::RESOURCE_DICTIONARY
))
225 *v
= lookup_resource_dictionary ((ResourceDictionary
*) walk
->data
, name
, &exists
);
226 else /* dob->Is (Type::FRAMEWORKELEMENT) */ {
227 ResourceDictionary
*rd
= dob
->GetValue (UIElement::ResourcesProperty
)->AsResourceDictionary();
228 *v
= lookup_resource_dictionary (rd
, name
, &exists
);
238 else if (!parent_context
)
241 return parent_context
->LookupNamedItem (name
, v
);
244 void SetTemplateBindingSource (DependencyObject
*source
)
246 this->source
= source
;
249 DependencyObject
* GetTemplateBindingSource ()
256 XamlContext::XamlContext (XamlContextInternal
*internal
)
258 this->internal
= internal
;
261 XamlContext::~XamlContext ()
267 XamlContext::SetTemplateBindingSource (DependencyObject
*source
)
269 internal
->SetTemplateBindingSource (source
);
273 XamlContext::GetTemplateBindingSource ()
275 return internal
->GetTemplateBindingSource ();
278 class XamlElementInfo
{
281 Type::Kind property_owner_kind
;
285 XamlElementInfo
*parent
;
289 XamlElementInfo (const char *xmlns
, const char *name
, Type::Kind kind
)
295 this->cdata_verbatim
= false;
297 this->property_owner_kind
= Type::INVALID
;
304 virtual Type::Kind
GetKind () { return kind
; }
306 virtual void SetPropertyOwnerKind (Type::Kind value
) { property_owner_kind
= value
; }
307 virtual Type::Kind
GetPropertyOwnerKind () { return property_owner_kind
; }
309 virtual const char *GetContentProperty (XamlParserInfo
*p
)
311 Type
*t
= Type::Find (Deployment::GetCurrent (), kind
);
313 return t
->GetContentPropertyName ();
317 void SetIsCDataVerbatim (bool flag
)
319 cdata_verbatim
= flag
;
322 bool IsCDataVerbatim ()
324 return cdata_verbatim
;
327 virtual bool RequiresManagedSet () { return false; }
329 virtual XamlElementInstance
*CreateElementInstance (XamlParserInfo
*p
) = 0;
330 virtual XamlElementInstance
*CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
) = 0;
331 virtual XamlElementInstance
*CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
) = 0;
335 struct DelayedProperty
{
340 DelayedProperty (const char *xmlns
, const char *name
, const Value
*value
)
342 this->xmlns
= g_strdup (xmlns
);
343 this->name
= g_strdup (name
);
344 this->value
= new Value (*value
);
356 free_property_list (GSList
*list
)
361 DelayedProperty
*prop
= (DelayedProperty
*) walk
->data
;
370 class XamlElementInstance
: public List::Node
{
373 DependencyObject
*item
;
376 GSList
*delayed_properties
;
379 const char *element_name
;
380 XamlElementInfo
*info
;
382 XamlElementInstance
*parent
;
392 bool requires_managed
;
396 GHashTable
*set_properties
;
398 XamlElementInstance (XamlElementInfo
*info
, const char* element_name
, ElementType type
, bool requires_managed
= false)
400 this->element_name
= element_name
;
401 this->set_properties
= NULL
;
402 this->element_type
= type
;
409 this->cleanup_value
= true;
410 this->requires_managed
= requires_managed
;
411 this->delayed_properties
= NULL
;
413 children
= new List ();
416 virtual ~XamlElementInstance ()
418 children
->Clear (true);
429 g_hash_table_destroy (set_properties
);
431 if (element_name
&& element_type
== PROPERTY
)
432 g_free ((void*) element_name
);
434 free_property_list (delayed_properties
);
437 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) = 0;
438 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
) = 0;
439 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) = 0;
440 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
) = 0;
442 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
);
443 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
);
446 char *GetKey () { return x_key
; }
447 char *GetName () { return x_name
; }
449 void SetName (XamlParserInfo
*p
, const char *name
)
451 this->x_name
= g_strdup (name
);
454 void SetKey (XamlParserInfo
*p
, const char *key
)
456 this->x_key
= g_strdup (key
);
459 virtual bool IsDependencyObject ()
464 virtual bool SetUnknownAttribute (XamlParserInfo
*p
, const char* name
, const char* value
);
466 void SetValue (Value
*v
)
468 if (value
&& cleanup_value
)
473 virtual Value
*GetAsValue ()
476 value
= new Value (item
);
481 virtual DependencyObject
*GetAsDependencyObject ()
486 virtual void SetDependencyObject (DependencyObject
*value
)
491 virtual void* GetManagedPointer ()
496 virtual Value
* GetParentPointer ()
498 XamlElementInstance
*walk
= parent
;
499 while (walk
&& walk
->element_type
!= XamlElementInstance::ELEMENT
)
505 return walk
->GetAsValue ();
508 virtual bool IsTemplate ()
513 virtual XamlElementInfo
* FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
);
515 void SetDelayedProperties (XamlParserInfo
*p
);
517 void DelaySetProperty (const char *xmlns
, const char *name
, const Value
*value
)
519 DelayedProperty
*prop
= new DelayedProperty (xmlns
, name
, value
);
521 delayed_properties
= g_slist_append (delayed_properties
, prop
);
524 bool IsPropertySet (const char *name
)
529 return g_hash_table_lookup (set_properties
, name
) != NULL
;
532 void MarkPropertyAsSet (const char *name
)
535 set_properties
= g_hash_table_new (g_str_hash
, g_str_equal
);
537 g_hash_table_insert (set_properties
, (void *) name
, GINT_TO_POINTER (TRUE
));
542 unref_xaml_element (gpointer data
, gpointer user_data
)
544 DependencyObject
* dob
= (DependencyObject
*) data
;
545 //printf ("unref_xaml_element: %i\n", dob->id);
550 class XamlParserInfo
{
554 const char *file_name
;
556 NameScope
*namescope
;
557 XamlElementInstance
*top_element
;
558 XamlNamespace
*current_namespace
;
559 XamlElementInstance
*current_element
;
560 const char *next_element
;
561 Deployment
*deployment
;
563 GHashTable
*namespace_map
;
567 bool implicit_default_namespace
;
569 ParserErrorEventArgs
*error_args
;
575 // If set, this is used to hydrate an existing object, not to create a new toplevel one
577 Value
*hydrate_expecting
;
580 char* buffer_until_element
;
582 BufferMode buffer_mode
;
584 bool validate_templates
;
587 GList
*created_elements
;
588 GList
*created_namespaces
;
589 const char* xml_buffer
;
590 int multi_buffer_offset
;
591 int xml_buffer_start_index
;
594 XamlParserInfo (XML_Parser parser
, const char *file_name
)
596 this->deployment
= Deployment::GetCurrent ();
597 this->parser
= parser
;
598 this->file_name
= file_name
;
599 this->namescope
= new NameScope ();
602 current_namespace
= NULL
;
603 current_element
= NULL
;
604 cdata_content
= false;
606 implicit_default_namespace
= false;
609 created_elements
= NULL
;
610 created_namespaces
= NULL
;
611 hydrate_expecting
= NULL
;
614 buffer_until_element
= NULL
;
618 multi_buffer_offset
= 0;
619 validate_templates
= false;
621 namespace_map
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
624 void AddCreatedElement (DependencyObject
* element
)
626 // if we have a loader, set the surface and base resource location
628 element
->SetIsAttached (true); /* Some glyphs (DRT 0/Test5, 58) do not show up without this */
629 element
->SetResourceBase (loader
->GetResourceBase());
632 // When instantiating a template, some elements are created which are not explicitly
633 // mentioned in the xaml. Therefore we need to keep walking up the tree until we find
634 // the last element which we set a value for Control::IsTemplateItem and propagate
636 XamlElementInstance
*instance
= current_element
;
638 if (!instance
->IsDependencyObject () || !instance
->GetAsDependencyObject ()) {
639 instance
= instance
->parent
;
642 if (!instance
->GetAsDependencyObject ()->ReadLocalValue (Control::IsTemplateItemProperty
)) {
643 instance
= instance
->parent
;
646 Control::SetIsTemplateItem (element
, Control::GetIsTemplateItem (instance
->GetAsDependencyObject ()));
647 if (DependencyObject
*e
= instance
->GetAsDependencyObject ()->GetTemplateOwner ())
648 element
->SetTemplateOwner (e
);
652 if (instance
== NULL
) {
653 Control::SetIsTemplateItem (element
, loader
->GetExpandingTemplate ());
654 element
->SetTemplateOwner (loader
->GetTemplateOwner ());
657 if (Control::GetIsTemplateItem (element
))
658 NameScope::SetNameScope (element
, namescope
);
659 created_elements
= g_list_prepend (created_elements
, element
);
662 void AddCreatedNamespace (XamlNamespace
* ns
)
664 created_namespaces
= g_list_prepend (created_namespaces
, ns
);
667 void QueueBeginBuffering (char* buffer_until
, BufferMode mode
)
669 buffer_until_element
= buffer_until
;
673 xml_buffer_start_index
= -1;
676 void BeginBuffering ()
678 xml_buffer_start_index
= XML_GetCurrentByteIndex (parser
) - multi_buffer_offset
;
679 buffer
= g_string_new (NULL
);
682 bool ShouldBeginBuffering ()
684 return InBufferingMode () && xml_buffer_start_index
== -1;
687 bool InBufferingMode ()
689 return buffer_until_element
!= NULL
;
692 void AppendCurrentXml ()
696 int pos
= XML_GetCurrentByteIndex (parser
) - multi_buffer_offset
;
697 g_string_append_len (buffer
, xml_buffer
+ xml_buffer_start_index
, pos
- xml_buffer_start_index
);
705 buffer_until_element
= NULL
;
708 return g_strdup ("");
710 char* res
= buffer
->str
;
711 g_string_free (buffer
, FALSE
);
716 void SetXmlBuffer (const char* xml_buffer
)
718 if (InBufferingMode ())
721 if (this->xml_buffer
)
722 multi_buffer_offset
+= strlen (this->xml_buffer
);
724 this->xml_buffer
= xml_buffer
;
725 xml_buffer_start_index
= 0;
728 void ValidateTemplate (const char* buffer
, XamlContext
* context
, FrameworkTemplate
*binding_source
)
730 XamlLoader
*loader
= new XamlLoader (NULL
, buffer
, NULL
, context
);
733 context
->SetTemplateBindingSource (binding_source
);
735 loader
->SetImportDefaultXmlns (true);
738 Value
*result
= loader
->CreateFromStringWithError (buffer
, true, &dummy
, XamlLoader::IMPORT_DEFAULT_XMLNS
| XamlLoader::VALIDATE_TEMPLATES
, &error
);
743 if (error
.number
!= MoonError::NO_ERROR
) {
744 int line_number
= error
.line_number
+ XML_GetCurrentLineNumber (parser
);
745 error_args
= new ParserErrorEventArgs (error
.message
, file_name
, line_number
, error
.char_position
, error
.code
, NULL
, NULL
);
749 FrameworkTemplate
*GetTemplateParent (XamlElementInstance
*item
)
751 XamlElementInstance
*parent
= item
->parent
;
753 while (parent
&& !parent
->IsTemplate ())
754 parent
= parent
->parent
;
757 return (FrameworkTemplate
*) parent
->GetManagedPointer ();
762 XamlContext
*context
= loader
->GetContext ();
766 return context
->internal
->template_parent
;
769 Value
*GetTopElementPtr ()
771 XamlContext
*context
= loader
->GetContext ();
773 return context
->internal
->top_element
;
776 return top_element
->GetAsValue ();
783 created_elements
= g_list_reverse (created_elements
);
784 g_list_foreach (created_elements
, unref_xaml_element
, NULL
);
785 g_list_free (created_elements
);
787 g_list_foreach (created_namespaces
, destroy_created_namespace
, NULL
);
788 g_list_free (created_namespaces
);
790 g_hash_table_destroy (namespace_map
);
793 g_string_free (cdata
, TRUE
);
803 class XamlElementInfoNative
: public XamlElementInfo
{
807 XamlElementInfoNative (Type
*t
) : XamlElementInfo (NULL
, t
->GetName (), t
->GetKind ())
817 const char* GetName ()
819 return type
->GetName ();
822 const char* GetContentProperty (XamlParserInfo
*p
);
824 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
825 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
826 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
830 class XamlElementInstanceNative
: public XamlElementInstance
{
831 XamlElementInfoNative
*element_info
;
832 XamlParserInfo
*parser_info
;
835 XamlElementInstanceNative (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
= true);
837 virtual DependencyObject
*CreateItem ();
839 virtual XamlElementInfo
* FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
);
841 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
);
842 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
);
843 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
);
844 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
848 class XamlElementInstanceValueType
: public XamlElementInstance
{
849 XamlElementInfoNative
*element_info
;
850 XamlParserInfo
*parser_info
;
853 XamlElementInstanceValueType (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
);
855 virtual bool IsDependencyObject ()
860 virtual Value
*GetAsValue ()
863 // we are an empty element (e.g. <sys:String></sys:String>). do type specific magic here.
864 CreateValueItemFromString ("");
870 bool CreateValueItemFromString (const char* str
);
872 // A Value type doesn't really support anything. It's just here so people can do <SolidColorBrush.Color><Color>#FF00FF</Color></SolidColorBrush.Color>
873 virtual DependencyObject
*CreateItem () { return NULL
; }
874 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) { return false; }
875 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
) { return false; }
876 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) { }
877 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
879 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
) { return false; }
880 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
) { return CreateValueItemFromString (value
); }
883 class XamlElementInfoEnum
: public XamlElementInfo
{
885 XamlElementInfoEnum (const char *name
) : XamlElementInfo (NULL
, name
, Type::INT32
)
889 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
890 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
891 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
) { return NULL
; }
894 class XamlElementInstanceEnum
: public XamlElementInstance
{
897 XamlElementInstanceEnum (XamlElementInfoEnum
*element_info
, const char *name
, ElementType type
);
899 virtual bool IsDependencyObject ()
904 virtual Value
*GetAsValue ()
909 bool CreateEnumFromString (const char* str
);
911 // An enum type doesn't really support anything. It's just here so people can do <Visibility>Visible</Visibility>
912 virtual DependencyObject
*CreateItem () { return NULL
; }
913 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) { return false; }
914 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
) { return false; }
915 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) { }
916 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
918 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
) { return false; }
919 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
) { return CreateEnumFromString (value
); }
922 class XamlElementInstanceTemplate
: public XamlElementInstanceNative
{
924 XamlElementInstanceTemplate (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
= true)
925 : XamlElementInstanceNative (element_info
, parser_info
, name
, type
, create_item
)
929 virtual bool IsTemplate ()
936 class DefaultNamespace
: public XamlNamespace
{
938 DefaultNamespace () { }
940 virtual ~DefaultNamespace () { }
942 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
944 Type
* t
= Type::Find (p
->deployment
, el
, false);
945 if (t
&& !kind_requires_managed_load (t
->GetKind ()))
946 return new XamlElementInfoNative (t
);
948 if (enums_is_enum_name (el
))
949 return new XamlElementInfoEnum (g_strdup (el
));
951 XamlElementInfo
* managed_element
= create_element_info_from_imported_managed_type (p
, el
, attr
, create
);
953 return managed_element
;
959 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
964 virtual const char* GetUri () { return "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; }
965 virtual const char* GetPrefix () { return ""; }
968 class XmlNamespace
: public XamlNamespace
{
972 virtual ~XmlNamespace () { }
974 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
979 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
981 if (!strcmp ("lang", attr
)) {
982 if (item
->IsDependencyObject ()) {
983 DependencyObject
*dob
= item
->GetAsDependencyObject ();
984 if (dob
->Is(Type::FRAMEWORKELEMENT
)) {
985 ((FrameworkElement
*)dob
)->SetLanguage (value
);
994 virtual const char* GetUri () { return "http://www.w3.org/XML/1998/namespace"; }
995 virtual const char* GetPrefix () { return "xml"; }
998 class XNamespace
: public XamlNamespace
{
1002 virtual ~XNamespace () { }
1004 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1009 virtual char *FindTypeName (const char **attr
, char **xmlns
)
1016 for (int i
= 0; attr
[i
]; i
+= 2) {
1017 const char *ns
= strchr (attr
[i
], '|');
1021 if (strncmp (GetUri (), attr
[i
], ns
- attr
[i
]) || strcmp ("Class", ns
+ 1))
1024 ns
= strchr (attr
[i
+ 1], ';');
1026 *xmlns
= g_strdup ("");
1027 res
= g_strdup (attr
[i
+ 1]);
1029 *xmlns
= g_strdup (ns
+ 1);
1030 res
= g_strndup (attr
[i
+ 1], attr
[i
+ 1] - ns
);
1037 bool IsParentResourceDictionary (XamlElementInstance
*parent
)
1042 return Type::IsSubclassOf (Deployment::GetCurrent (), parent
->info
->GetKind (), Type::RESOURCE_DICTIONARY
);
1045 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1047 if (!strcmp ("Name", attr
)) {
1049 // Causes breakage in airlines
1050 // Maybe x:Name overwrites but Name does not?
1052 // if (p->namescope->FindName (value)) {
1053 // parser_error (p, p->current_element->element_name, "x:Name", 2028, "The name already exists in the tree: %s.", value);
1058 if (IsParentResourceDictionary (p
->current_element
)) {
1059 if (item
->GetKey ()) {
1060 // XXX don't know the proper values here...
1061 parser_error (p
, item
->element_name
, NULL
, 2028,
1062 "The name already exists in the tree: %s.", value
);
1067 if (item
->GetName ()) {
1068 parser_error (p
, item
->element_name
, NULL
, 2016, "Cannot specify both Name and x:Name attributes.");
1072 item
->SetName (p
, value
);
1074 if (item
->IsDependencyObject ()) {
1075 NameScope
*scope
= p
->namescope
;
1076 if (!item
->GetAsDependencyObject ()->SetName (value
, scope
)) {
1077 if (IsParentResourceDictionary (p
->current_element
)) {
1078 // FIXME: inside of a resource dictionary this has an extremly
1079 // strange behavior. this isn't exactly right, since not only
1080 // does the exception get swallowed, but the name seems to also
1084 parser_error (p
, item
->element_name
, NULL
, 2028,
1085 "The name already exists in the tree: %s.", value
);
1095 if (!strcmp ("Key", attr
)) {
1096 if (item
->GetKey () && IsParentResourceDictionary (p
->current_element
) && !Type::IsSubclassOf (p
->deployment
, item
->info
->GetKind (), Type::STORYBOARD
)) {
1097 // XXX don't know the proper values here...
1098 parser_error (p
, item
->element_name
, NULL
, 2028,
1099 "The name already exists in the tree: %s.", value
);
1102 item
->SetKey (p
, value
);
1106 if (!strcmp ("Class", attr
)) {
1107 if (!is_legal_top_level_kind (item
->info
->GetKind ())) {
1108 // XXX don't know the proper values here...
1109 parser_error (p
, item
->element_name
, attr
, -1,
1110 "Cannot specify x:Class type '%s' on value type element (%s).", value
, item
->element_name
);
1114 if (p
->top_element
!= item
) {
1115 // HAH: what a useless error message
1116 parser_error (p
, item
->element_name
, attr
, 2012,
1117 "Unknown attribute %s on element %s.", attr
, item
->element_name
);
1121 // While hydrating, we do not need to create the toplevel class, its created already
1125 parser_error (p
, item
->element_name
, attr
, 4005,
1126 "Cannot specify x:Class in xaml files outside of a xap.");
1134 virtual const char* GetUri () { return X_NAMESPACE_URI
; }
1135 virtual const char* GetPrefix () { return "x"; }
1139 class PrimitiveNamespace
: public XamlNamespace
{
1146 PrimitiveNamespace (char *prefix
)
1148 this->prefix
= prefix
;
1151 virtual ~PrimitiveNamespace ()
1157 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1159 if (!strcmp ("String", el
)) {
1160 Type
* t
= Type::Find (p
->deployment
, Type::STRING
);
1161 // it's not as easy in this case, because primitive clr strings require that the
1162 // character data be read in verbatim, including all whitespace.
1163 XamlElementInfo
*info
= new XamlElementInfoNative (t
);
1164 info
->SetIsCDataVerbatim (true);
1166 } else if (!strcmp ("Int32", el
)) {
1167 Type
* t
= Type::Find (p
->deployment
, Type::INT32
);
1168 return new XamlElementInfoNative (t
);
1169 } else if (!strcmp ("Double", el
)) {
1170 Type
* t
= Type::Find (p
->deployment
, Type::DOUBLE
);
1171 return new XamlElementInfoNative (t
);
1172 } else if (!strcmp ("Boolean", el
)) {
1173 Type
* t
= Type::Find (p
->deployment
, Type::BOOL
);
1174 return new XamlElementInfoNative (t
);
1175 } else if (!strcmp ("TimeSpan", el
)) {
1176 Type
* t
= Type::Find (p
->deployment
, Type::TIMESPAN
);
1177 return new XamlElementInfoNative (t
);
1183 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1188 virtual const char* GetUri () { return PRIMITIVE_NAMESPACE_URI
; }
1189 virtual const char* GetPrefix () { return prefix
; }
1193 class MCIgnorableNamespace
: public XamlNamespace
{
1199 MCIgnorableNamespace (char *prefix
)
1201 this->prefix
= prefix
;
1204 virtual ~MCIgnorableNamespace ()
1210 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1215 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1217 if (!strcmp ("Ignorable", attr
)) {
1218 const char *start
= value
;
1220 const char *space
= strchr (start
, ' ');
1223 prefix
= g_strndup (start
, space
- start
);
1226 prefix
= g_strdup (start
);
1230 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
1232 ns
->is_ignored
= true;
1242 virtual const char* GetUri () { return MC_IGNORABLE_NAMESPACE_URI
; }
1243 virtual const char* GetPrefix () { return prefix
; }
1248 destroy_created_namespace (gpointer data
, gpointer user_data
)
1250 XamlNamespace
* ns
= (XamlNamespace
*) data
;
1255 class XamlElementInfoManaged
: public XamlElementInfo
{
1257 XamlElementInfoManaged (const char *xmlns
, const char *name
, XamlElementInfo
*parent
, Type::Kind dependency_type
, Value
*obj
) : XamlElementInfo (xmlns
, name
, dependency_type
)
1264 const char* GetName () { return name
; }
1266 const char* GetContentProperty (XamlParserInfo
*p
);
1268 virtual bool RequiresManagedSet () { return true; }
1270 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
1271 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
1272 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
1276 class XamlElementInstanceManaged
: public XamlElementInstance
{
1278 XamlElementInstanceManaged (XamlElementInfo
*info
, const char *name
, ElementType type
, Value
*obj
);
1280 virtual bool IsDependencyObject ()
1282 return is_dependency_object
;
1285 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
);
1286 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
);
1287 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
);
1288 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
1290 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
);
1291 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
);
1293 virtual void* GetManagedPointer ();
1294 virtual Value
* GetParentPointer ();
1296 bool is_dependency_object
;
1300 class XamlElementInfoImportedManaged
: public XamlElementInfoManaged
{
1302 XamlElementInfoImportedManaged (const char *name
, XamlElementInfo
*parent
, Value
*obj
) : XamlElementInfoManaged (NULL
, name
, parent
, obj
->GetKind (), obj
)
1306 const char* GetContentProperty (XamlParserInfo
*p
);
1308 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
1309 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
1310 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
1315 class ManagedNamespace
: public XamlNamespace
{
1320 ManagedNamespace (char *xmlns
, char *prefix
)
1322 this->xmlns
= xmlns
;
1323 this->prefix
= prefix
;
1326 virtual ~ManagedNamespace ()
1332 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1334 char* type_name
= NULL
;
1335 char* type_xmlns
= NULL
;
1336 const char* use_xmlns
= xmlns
;
1342 // We might have an x:Class attribute specified, so we need to use that for the
1343 // type_name that we pass to LookupObject
1344 if (strcmp ("Application", el
)) {
1345 type_name
= x_namespace
->FindTypeName (attr
, &type_xmlns
);
1348 use_xmlns
= type_xmlns
;
1350 if (!p
->hydrating
) {
1351 parser_error (p
, el
, "x:Class", 4005, "Cannot specify x:Class in xaml files outside of a xap.");
1358 Value
*value
= new Value ();
1359 if (!p
->loader
->LookupObject (p
, p
->GetTopElementPtr (), p
->current_element
? p
->current_element
->GetAsValue () : NULL
, use_xmlns
, el
, create
, false, value
)) {
1360 parser_error (p
, el
, NULL
, 2007, "Unable to resolve managed type %s.", el
);
1365 g_free (type_xmlns
);
1369 if (p
->hydrate_expecting
) {
1371 // If we are hydrating a top level managed object, use the Value* passed
1372 // to Hydrate as our value
1375 value
= p
->hydrate_expecting
;
1379 XamlElementInfoManaged
*info
= new XamlElementInfoManaged (xmlns
, g_strdup (el
), NULL
, value
->GetKind (), value
);
1383 g_free (type_xmlns
);
1387 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1393 Value v
= Value (value
);
1394 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), item
->info
->xmlns
, item
->GetAsValue (), item
, item
->GetParentPointer (), xmlns
, attr
, &v
, NULL
);
1400 virtual const char* GetUri () { return xmlns
; }
1401 virtual const char* GetPrefix () { return prefix
; }
1405 XamlLoader::LookupObject (void *p
, Value
*top_level
, Value
*parent
, const char* xmlns
, const char* type_name
, bool create
, bool is_property
, Value
*value
)
1407 if (callbacks
.lookup_object
) {
1408 if (!vm_loaded
&& !LoadVM ())
1411 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1412 bool res
= callbacks
.lookup_object (&data
, parent
, xmlns
, type_name
, create
, is_property
, value
, &error
);
1420 XamlLoader::GetContentPropertyName (void *p
, Value
*top_level
, Value
*object
)
1422 if (callbacks
.get_content_property_name
) {
1424 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1425 return callbacks
.get_content_property_name (&data
, object
, &error
);
1431 XamlLoader::SetProperty (void *p
, Value
*top_level
, const char* xmlns
, Value
*target
, void *target_data
, Value
*target_parent
, const char* prop_xmlns
, const char *name
, Value
*value
, void* value_data
, int flags
)
1433 if (callbacks
.set_property
) {
1435 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
, flags
);
1436 bool res
= callbacks
.set_property (&data
, xmlns
, target
, target_data
, target_parent
, prop_xmlns
, name
, value
, value_data
, &error
);
1438 if (error
.number
!= MoonError::NO_ERROR
) {
1439 parser_error ((XamlParserInfo
*) p
, ((XamlElementInstance
*) target_data
)->element_name
, NULL
, error
.code
, error
.message
);
1450 XamlLoader::AddChild (void *p
, Value
*top_level
, Value
*parent_parent
, bool parent_is_property
, const char* parent_xmlns
, Value
*parent
, void *parent_data
, Value
*child
, void *child_data
)
1452 if (callbacks
.add_child
) {
1454 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1455 bool res
= callbacks
.add_child (&data
, parent_parent
, parent_is_property
, parent_xmlns
, parent
, parent_data
, child
, child_data
, &error
);
1457 if (error
.number
!= MoonError::NO_ERROR
) {
1458 parser_error ((XamlParserInfo
*) p
, ((XamlElementInstance
*) child_data
)->element_name
, NULL
, error
.code
, error
.message
);
1467 XamlLoader::XamlLoader (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1469 Initialize (resourceBase
, filename
, str
, surface
, context
);
1472 XamlLoader::XamlLoader (const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1474 Initialize (NULL
, filename
, str
, surface
, context
);
1478 XamlLoader::Initialize (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1480 this->filename
= g_strdup (filename
);
1481 this->resource_base
= g_strdup (resourceBase
);
1482 this->str
= g_strdup (str
);
1483 this->surface
= surface
;
1486 this->context
= context
;
1487 this->vm_loaded
= false;
1488 this->error_args
= NULL
;
1489 this->expanding_template
= false;
1490 this->template_owner
= NULL
;
1491 this->import_default_xmlns
= false;
1494 callbacks
= context
->internal
->callbacks
;
1495 this->vm_loaded
= true;
1498 if (!surface
&& debug_flags
& RUNTIME_DEBUG_XAML
) {
1499 printf ("XamlLoader::XamlLoader ('%s', '%s', %p): Initializing XamlLoader without a surface.\n",
1500 filename
, str
, surface
);
1505 XamlLoader::~XamlLoader ()
1508 g_free (resource_base
);
1516 error_args
->unref();
1520 XamlLoader::LoadVM ()
1526 xaml_loader_new (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
)
1528 return new XamlLoader (resourceBase
, filename
, str
, surface
);
1532 xaml_loader_free (XamlLoader
* loader
)
1538 xaml_loader_set_callbacks (XamlLoader
* loader
, XamlLoaderCallbacks callbacks
)
1541 LOG_XAML ("Trying to set callbacks for a null object\n");
1545 loader
->callbacks
= callbacks
;
1546 loader
->vm_loaded
= true;
1550 namespace_for_prefix (gpointer key
, gpointer value
, gpointer user_data
)
1552 XamlNamespace
*ns
= (XamlNamespace
*) value
;
1553 const char *prefix
= (const char *) user_data
;
1555 if (!strcmp (prefix
, ns
->GetPrefix ()))
1561 xaml_uri_for_prefix (void *parser
, char* prefix
)
1563 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
1565 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
1569 return g_strdup (ns
->GetUri ());
1573 // Called when we encounter an error. Note that memory ownership is taken for everything
1574 // except the message, this allows you to use g_strdup_printf when creating the error message
1577 parser_error (XamlParserInfo
*p
, const char *el
, const char *attr
, int error_code
, const char *format
, ...)
1586 // if parsing fails too early it's not safe (i.e. sigsegv) to call some functions, e.g. XML_GetCurrentLineNumber
1587 bool report_line_col
= (error_code
!= XML_ERROR_XML_DECL
);
1588 int line_number
= report_line_col
? XML_GetCurrentLineNumber (p
->parser
) : 0;
1589 int char_position
= report_line_col
? XML_GetCurrentColumnNumber (p
->parser
) : 0;
1591 va_start (args
, format
);
1592 message
= g_strdup_vprintf (format
, args
);
1595 p
->error_args
= new ParserErrorEventArgs (message
, p
->file_name
, line_number
, char_position
, error_code
, el
, attr
);
1599 LOG_XAML ("PARSER ERROR, STOPPING PARSING: (%d) %s line: %d char: %d\n", error_code
, message
,
1600 line_number
, char_position
);
1602 XML_StopParser (p
->parser
, FALSE
);
1606 expat_parser_error (XamlParserInfo
*p
, XML_Error expat_error
)
1608 // Already had an error
1612 LOG_XAML ("expat error is: %d\n", expat_error
);
1614 switch (expat_error
) {
1615 case XML_ERROR_DUPLICATE_ATTRIBUTE
:
1616 parser_error (p
, NULL
, NULL
, 7031, "wfc: unique attribute spec");
1618 case XML_ERROR_UNBOUND_PREFIX
:
1619 parser_error (p
, NULL
, NULL
, 7055, "undeclared prefix");
1621 case XML_ERROR_NO_ELEMENTS
:
1622 parser_error (p
, NULL
, NULL
, 7000, "unexpected end of input");
1624 case XML_ERROR_SYNTAX
:
1625 parser_error (p
, NULL
, NULL
, 2103, "syntax error");
1628 parser_error (p
, NULL
, NULL
, expat_error
, "Unhandled XML error %s", XML_ErrorString (expat_error
));
1634 start_element (void *data
, const char *el
, const char **attr
)
1636 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1637 XamlElementInfo
*elem
= NULL
;
1638 XamlElementInstance
*inst
;
1639 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
1641 if (!strcmp (el
, INTERNAL_IGNORABLE_ELEMENT
))
1644 if (p
->ShouldBeginBuffering ()) {
1645 p
->BeginBuffering ();
1649 if (p
->InBufferingMode ()) {
1650 if (!strcmp (p
->buffer_until_element
, el
))
1655 const char *dot
= strchr (el
, '.');
1657 elem
= p
->current_namespace
->FindElement (p
, el
, attr
, p
->hydrate_expecting
== NULL
);
1664 if (p
->hydrate_expecting
){
1666 Type::Kind expecting_type = p->hydrate_expecting->GetObjectType ();
1668 if (!types->IsSubclassOf (expecting_type, elem->GetKind ())) {
1669 parser_error (p, el, NULL, -1, "Invalid top-level element found %s, expecting %s", el,
1670 types->Find (expecting_type)->GetName ());
1675 inst
= elem
->CreateWrappedElementInstance (p
, p
->hydrate_expecting
);
1676 p
->hydrate_expecting
= NULL
;
1678 inst
= elem
->CreateElementInstance (p
);
1683 inst
->parent
= p
->current_element
;
1685 if (!p
->top_element
) {
1686 p
->top_element
= inst
;
1687 if (inst
->GetAsDependencyObject ())
1688 NameScope::SetNameScope (inst
->GetAsDependencyObject (), p
->namescope
);
1691 if (inst
->GetAsDependencyObject ())
1692 inst
->GetAsDependencyObject ()->SetIsBeingParsed (true);
1694 inst
->SetAttributes (p
, attr
);
1698 if (inst
->IsDependencyObject ()) {
1699 if (p
->current_element
){
1700 if (p
->current_element
->info
) {
1701 p
->current_element
->AddChild (p
, inst
);
1708 // it's actually valid (from SL point of view) to have <Ellipse.Triggers> inside a <Rectangle>
1709 // however we can't add properties to something bad, like a <Recta.gle> element
1710 XamlElementInfo
*prop_info
= NULL
;
1712 gchar
*prop_elem
= g_strndup (el
, dot
- el
);
1713 prop_info
= p
->current_element
->FindPropertyElement (p
, el
, dot
);
1717 if (prop_info
!= NULL
) {
1718 inst
= prop_info
->CreatePropertyElementInstance (p
, g_strdup (el
));
1719 inst
->parent
= p
->current_element
;
1721 if (attr
[0] != NULL
) {
1722 // It appears there is a bug in the error string but it matches the MS runtime
1723 parser_error (p
, el
, NULL
, 2018, "The element %s does not support attributes.", attr
[0]);
1727 if (prop_info
&& !strcmp (el
, "TextBox.Text"))
1728 prop_info
->SetIsCDataVerbatim (true);
1730 if (!p
->top_element
) {
1731 if (types
->IsSubclassOf (prop_info
->GetKind (), Type::COLLECTION
)) {
1732 XamlElementInstance
*wrap
= prop_info
->CreateElementInstance (p
);
1733 NameScope::SetNameScope (wrap
->GetAsDependencyObject (), p
->namescope
);
1734 p
->top_element
= wrap
;
1735 p
->current_element
= wrap
;
1740 g_warning ("Unknown element: %s.", el
);
1741 parser_error (p
, el
, NULL
, 2007, "Unknown element: %s.", el
);
1746 if (p
->current_element
) {
1747 p
->current_element
->children
->Append (inst
);
1749 p
->current_element
= inst
;
1751 if (elem
&& element_begins_buffering (elem
->GetKind ())) {
1752 p
->QueueBeginBuffering (g_strdup (el
), BUFFER_MODE_TEMPLATE
);
1757 allow_value_from_str_in_flush (XamlParserInfo
*p
, XamlElementInstance
*parent
)
1759 if (parent
== NULL
|| parent
->element_type
!= XamlElementInstance::PROPERTY
|| parent
->parent
== NULL
|| !parent
->parent
->IsDependencyObject ())
1762 if (parent
->info
->GetKind () == Type::OBJECT
)
1769 flush_char_data (XamlParserInfo
*p
)
1771 if (p
->InBufferingMode ())
1774 if (!p
->cdata
|| !p
->current_element
)
1777 if (p
->current_element
->info
->IsCDataVerbatim()) {
1778 p
->cdata
->str
= g_strstrip (p
->cdata
->str
);
1781 if (p
->current_element
->element_type
== XamlElementInstance::ELEMENT
) {
1782 if (!p
->current_element
->TrySetContentProperty (p
, p
->cdata
->str
) && p
->cdata_content
) {
1783 if (allow_value_from_str_in_flush (p
, p
->current_element
->parent
)) {
1785 if (value_from_str (p
->current_element
->info
->GetKind (), NULL
, p
->cdata
->str
, &v
)) {
1786 p
->current_element
->SetValue (v
);
1790 parser_error (p
, p
->current_element
->element_name
, NULL
, 2011,
1791 "%s does not support text content.", p
->current_element
->element_name
);
1793 } else if (p
->current_element
->element_type
== XamlElementInstance::PROPERTY
) {
1794 if (p
->cdata_content
&& p
->current_element
->parent
&& !p
->current_element
->parent
->SetProperty (p
, p
->current_element
, p
->cdata
->str
)) {
1795 parser_error (p
, p
->current_element
->element_name
, NULL
, 2011,
1796 "%s does not support text content.", p
->current_element
->element_name
);
1802 g_string_free (p
->cdata
, TRUE
);
1803 p
->cdata_content
= false;
1809 element_begins_buffering (Type::Kind kind
)
1811 return Type::IsSubclassOf (Deployment::GetCurrent (), kind
, Type::FRAMEWORKTEMPLATE
);
1815 is_default_namespace (gpointer key
, gpointer value
, gpointer user_data
)
1817 return value
== default_namespace
;
1821 start_element_handler (void *data
, const char *el
, const char **attr
)
1823 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1828 char **name
= g_strsplit (el
, "|", -1);
1829 XamlNamespace
*next_namespace
= NULL
;
1830 char *element
= NULL
;
1832 if (g_strv_length (name
) == 2) {
1833 // Find the proper namespace for our next element
1834 next_namespace
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, name
[0]);
1838 if (!next_namespace
&& p
->implicit_default_namespace
) {
1839 // Use the default namespace for the next element
1840 next_namespace
= default_namespace
;
1842 } else if (!next_namespace
) {
1843 if (!g_hash_table_find (p
->namespace_map
, is_default_namespace
, NULL
))
1844 return parser_error (p
, el
, NULL
, 2263, "AG_E_PARSER_MISSING_DEFAULT_NAMESPACE");
1847 if (next_namespace
&& next_namespace
->is_ignored
) {
1848 p
->current_namespace
= next_namespace
;
1849 if (!p
->InBufferingMode ())
1850 p
->QueueBeginBuffering (g_strdup (element
), BUFFER_MODE_IGNORE
);
1852 start_element (data
, element
, attr
); // This will force the buffering to start/build depth if needed
1856 p
->next_element
= element
;
1858 flush_char_data (p
);
1860 // Now update our namespace
1861 p
->current_namespace
= next_namespace
;
1863 if (!p
->current_namespace
&& !p
->InBufferingMode ()) {
1865 parser_error (p
, name
[1], NULL
, -1, "No handlers available for namespace: '%s' (%s)\n", name
[0], el
);
1867 parser_error (p
, name
[1], NULL
, -1, "No namespace mapping available for element: '%s'\n", el
);
1873 p
->next_element
= NULL
;
1874 start_element (data
, element
, attr
);
1880 get_element_name (XamlParserInfo
* p
, const char *el
)
1882 char **names
= g_strsplit (el
, "|", -1);
1883 char *name
= g_strdup (names
[g_strv_length (names
) - 1]);
1891 create_resource_list (XamlParserInfo
*p
)
1893 GSList
*list
= NULL
;
1894 XamlElementInstance
*walk
= p
->current_element
;
1896 Types
* types
= Deployment::GetCurrent ()->GetTypes ();
1898 if (walk
->element_type
== XamlElementInstance::ELEMENT
&& types
->IsSubclassOf (walk
->info
->GetKind (), Type::FRAMEWORKELEMENT
)) {
1899 FrameworkElement
*fwe
= (FrameworkElement
*)walk
->GetAsDependencyObject ();
1900 if (g_slist_index (list
, fwe
) == -1)
1901 list
= g_slist_prepend (list
, fwe
);
1903 if (walk
->element_type
== XamlElementInstance::ELEMENT
&& types
->IsSubclassOf (walk
->info
->GetKind (), Type::RESOURCE_DICTIONARY
)) {
1904 ResourceDictionary
*rd
= (ResourceDictionary
*) walk
->GetAsDependencyObject ();
1905 if (g_slist_index (list
, rd
) == -1)
1906 list
= g_slist_prepend (list
, walk
->GetAsDependencyObject ());
1908 walk
= walk
->parent
;
1911 list
= g_slist_reverse (list
);
1915 static XamlContext
*
1916 create_xaml_context (XamlParserInfo
*p
, FrameworkTemplate
*template_
, XamlContext
*parent_context
)
1918 GSList
*resources
= create_resource_list (p
);
1919 XamlContextInternal
*ic
= new XamlContextInternal (p
->loader
->callbacks
, p
->GetTopElementPtr (), template_
, p
->namespace_map
, resources
, parent_context
? parent_context
->internal
: NULL
);
1920 return new XamlContext (ic
);
1924 end_element_handler (void *data
, const char *el
)
1926 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1927 DependencyObject
*obj
;
1929 if (!strcmp (el
, INTERNAL_IGNORABLE_ELEMENT
))
1935 if (!p
->current_element
) {
1936 g_warning ("p->current_element == NULL, current_element = %p (%s)\n",
1937 p
->current_element
, p
->current_element
? p
->current_element
->element_name
: "<NULL>");
1941 if (p
->InBufferingMode ()) {
1942 char* name
= get_element_name (p
, el
);
1943 if (!strcmp (p
->buffer_until_element
, name
)) {
1946 if (p
->buffer_depth
== 0) {
1947 if (p
->buffer_mode
== BUFFER_MODE_TEMPLATE
) {
1948 // OK we are done buffering, the element we are buffering for
1949 FrameworkTemplate
* template_
= (FrameworkTemplate
*) p
->current_element
->GetAsDependencyObject ();
1951 char* buffer
= p
->ClearBuffer ();
1953 XamlContext
*context
= create_xaml_context (p
, template_
, p
->loader
->GetContext());
1955 if (p
->validate_templates
) {
1956 p
->ValidateTemplate (buffer
, context
, template_
);
1962 template_
->SetXamlBuffer (context
, buffer
);
1963 p
->current_element
= p
->current_element
->parent
;
1964 } else if (p
->buffer_mode
== BUFFER_MODE_IGNORE
) {
1965 // For now we'll actually keep/clear this buffer because it makes testing easier
1966 char *buffer
= p
->ClearBuffer ();
1976 switch (p
->current_element
->element_type
) {
1977 case XamlElementInstance::ELEMENT
:
1979 p
->current_element
->SetDelayedProperties (p
);
1980 flush_char_data (p
);
1982 // according to http://blogs.msdn.com/devdave/archive/2008/10/11/control-lifecycle.aspx
1983 // default styles are apply when the end tag is read.
1985 if (p
->current_element
->IsDependencyObject () &&
1986 p
->current_element
->GetAsDependencyObject() &&
1987 p
->current_element
->GetAsDependencyObject()->Is(Type::CONTROL
)) {
1989 Control
*control
= (Control
*)p
->current_element
->GetAsDependencyObject();
1990 ManagedTypeInfo
*key
= control
->GetDefaultStyleKey ();
1993 if (Application::GetCurrent () == NULL
)
1994 g_warning ("attempting to use a null application applying default style while parsing.");
1996 Application::GetCurrent()->ApplyDefaultStyle (control
, key
);
1999 else if (!p
->current_element
->IsDependencyObject ()) {
2001 if (p
->current_element
->parent
)
2002 p
->current_element
->parent
->AddChild (p
, p
->current_element
);
2005 case XamlElementInstance::PROPERTY
: {
2006 List::Node
*walk
= p
->current_element
->children
->First ();
2008 XamlElementInstance
*child
= (XamlElementInstance
*) walk
;
2009 if (p
->current_element
->parent
) {
2010 p
->current_element
->parent
->SetProperty (p
, p
->current_element
, child
);
2014 flush_char_data (p
);
2019 if ((obj
= p
->current_element
->GetAsDependencyObject ()))
2020 obj
->SetIsBeingParsed (false);
2022 p
->current_element
= p
->current_element
->parent
;
2026 char_data_handler (void *data
, const char *in
, int inlen
)
2028 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2029 register const char *inptr
= in
;
2030 const char *inend
= in
+ inlen
;
2033 if (p
->InBufferingMode ())
2039 if (p
->current_element
&& p
->current_element
->info
->IsCDataVerbatim()) {
2041 p
->cdata
= g_string_new ("");
2043 g_string_append_len (p
->cdata
, inptr
, inlen
);
2044 p
->cdata_content
= true;
2049 p
->cdata
= g_string_new ("");
2051 if (g_ascii_isspace (*inptr
)) {
2052 g_string_append_c (p
->cdata
, ' ');
2055 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2061 } else if (g_ascii_isspace (p
->cdata
->str
[p
->cdata
->len
- 1])) {
2062 // previous cdata chunk ended with lwsp, skip over leading lwsp for this chunk
2063 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2067 while (inptr
< inend
) {
2069 while (inptr
< inend
&& !g_ascii_isspace (*inptr
))
2072 if (inptr
> start
) {
2073 g_string_append_len (p
->cdata
, start
, inptr
- start
);
2074 p
->cdata_content
= true;
2077 if (inptr
< inend
) {
2078 g_string_append_c (p
->cdata
, ' ');
2081 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2088 start_namespace_handler (void *data
, const char *prefix
, const char *uri
)
2090 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2092 if (p
->InBufferingMode ())
2098 if (p
->loader
!= NULL
&& p
->loader
->callbacks
.import_xaml_xmlns
!= NULL
) {
2100 XamlCallbackData data
= XamlCallbackData (p
->loader
, p
, p
->GetTopElementPtr ());
2101 if (!p
->loader
->callbacks
.import_xaml_xmlns (&data
, uri
, &error
))
2102 return parser_error (p
, p
->current_element
? p
->current_element
->element_name
: NULL
, prefix
, 2005, "Unknown namespace %s", uri
);
2105 for (int i
= 0; default_namespace_names
[i
]; i
++) {
2106 if (!strcmp (default_namespace_names
[i
], uri
)) {
2107 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), default_namespace
);
2112 if (!strcmp (X_NAMESPACE_URI
, uri
)){
2113 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), x_namespace
);
2114 } else if (!strcmp (PRIMITIVE_NAMESPACE_URI
, uri
)) {
2115 PrimitiveNamespace
*pn
= new PrimitiveNamespace (g_strdup (prefix
));
2116 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), pn
);
2117 p
->AddCreatedNamespace (pn
);
2118 } else if (!strcmp (MC_IGNORABLE_NAMESPACE_URI
, uri
)) {
2119 MCIgnorableNamespace
*mc
= new MCIgnorableNamespace (g_strdup (prefix
));
2120 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), mc
);
2121 p
->AddCreatedNamespace (mc
);
2124 return parser_error (p
, (p
->current_element
? p
->current_element
->element_name
: NULL
), prefix
, -1,
2125 "No managed element callback installed to handle %s", uri
);
2129 parser_error (p
, (p
->current_element
? p
->current_element
->element_name
: NULL
), NULL
, 2262,
2130 "AG_E_PARSER_NAMESPACE_NOT_SUPPORTED");
2134 ManagedNamespace
*c
= new ManagedNamespace (g_strdup (uri
), g_strdup (prefix
));
2135 g_hash_table_insert (p
->namespace_map
, g_strdup (c
->xmlns
), c
);
2136 p
->AddCreatedNamespace (c
);
2141 start_doctype_handler (void *data
,
2142 const XML_Char
*doctype_name
,
2143 const XML_Char
*sysid
,
2144 const XML_Char
*pubid
,
2145 int has_internal_subset
)
2147 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2149 if (p
->InBufferingMode ())
2153 return parser_error (p
, NULL
, NULL
, 7050, "DTD was found but is prohibited");
2156 return parser_error (p
, NULL
, NULL
, 7016, "incorrect document syntax.");
2160 add_default_namespaces (XamlParserInfo
*p
, bool sl_xmlns
)
2163 p
->implicit_default_namespace
= true;
2164 g_hash_table_insert (p
->namespace_map
, g_strdup ("http://schemas.microsoft.com/winfx/2006/xaml/presentation"), default_namespace
);
2165 g_hash_table_insert (p
->namespace_map
, g_strdup (X_NAMESPACE_URI
), x_namespace
);
2167 g_hash_table_insert (p
->namespace_map
, g_strdup (XML_NAMESPACE_URI
), xml_namespace
);
2171 print_tree (XamlElementInstance
*el
, int depth
)
2174 if (debug_flags
& RUNTIME_DEBUG_XAML
) {
2175 for (int i
= 0; i
< depth
; i
++)
2178 const char *name
= NULL
;
2181 printf (" -null- \n");
2185 if (el
->element_type
== XamlElementInstance::ELEMENT
&& el
->IsDependencyObject ())
2186 name
= el
->GetAsDependencyObject ()->GetName ();
2187 printf ("%s (%s) (%p) (%s)\n", el
->element_name
, name
? name
: "-no name-", el
->parent
, el
->element_type
== XamlElementInstance::PROPERTY
? "PROPERTY" : "ELEMENT");
2189 for (List::Node
*walk
= el
->children
->First (); walk
!= NULL
; walk
= walk
->next
) {
2190 XamlElementInstance
*el
= (XamlElementInstance
*) walk
;
2191 print_tree (el
, depth
+ 1);
2198 xaml_parse_xmlns (const char* xmlns
, char** type_name
, char** ns
, char** assembly
)
2200 const char delimiters
[] = ";";
2202 char* buffer
= g_strdup (xmlns
);
2208 decl
= strtok (buffer
, delimiters
);
2209 while (decl
!= NULL
) {
2210 if (strstr (decl
, "clr-namespace:") == decl
) {
2213 *ns
= g_strdup (decl
+ 14);
2214 } else if (strstr (decl
, "assembly=") == decl
) {
2217 *assembly
= g_strdup (decl
+ 9);
2220 g_free (*type_name
);
2221 *type_name
= g_strdup (decl
);
2224 decl
= strtok (NULL
, delimiters
);
2230 XamlLoader::CreateFromFile (const char *xaml_file
, bool create_namescope
,
2231 Type::Kind
*element_type
)
2234 XamlParserInfo
*parser_info
= NULL
;
2235 XML_Parser p
= NULL
;
2236 bool first_read
= true;
2237 const char *inptr
, *inend
;
2242 LOG_XAML ("attemtping to load xaml file: %s\n", xaml_file
);
2244 stream
= new TextStream ();
2245 if (!stream
->OpenFile (xaml_file
, false)) {
2246 LOG_XAML ("can not open file\n");
2247 goto cleanup_and_return
;
2250 if (!(p
= XML_ParserCreateNS ("UTF-8", '|'))) {
2251 LOG_XAML ("can not create parser\n");
2252 goto cleanup_and_return
;
2255 parser_info
= new XamlParserInfo (p
, xaml_file
);
2257 parser_info
->namescope
->SetTemporary (!create_namescope
);
2259 parser_info
->loader
= this;
2261 // TODO: This is just in here temporarily, to make life less difficult for everyone
2262 // while we are developing.
2263 add_default_namespaces (parser_info
, false);
2265 XML_SetUserData (p
, parser_info
);
2267 XML_SetElementHandler (p
, start_element_handler
, end_element_handler
);
2268 XML_SetCharacterDataHandler (p
, char_data_handler
);
2269 XML_SetNamespaceDeclHandler(p
, start_namespace_handler
, NULL
);
2270 XML_SetDoctypeDeclHandler(p
, start_doctype_handler
, NULL
);
2273 XML_SetProcessingInstructionHandler (p, proc_handler);
2276 while ((nread
= stream
->Read (buffer
, sizeof (buffer
))) >= 0) {
2280 if (first_read
&& nread
> 0) {
2281 // Remove preceding white space
2282 inend
= buffer
+ nread
;
2284 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2290 n
= (inend
- inptr
);
2294 parser_info
->SetXmlBuffer (inptr
);
2295 if (!XML_Parse (p
, inptr
, n
, nread
== 0)) {
2296 expat_parser_error (parser_info
, XML_GetErrorCode (p
));
2297 goto cleanup_and_return
;
2304 print_tree (parser_info
->top_element
, 0);
2306 if (parser_info
->top_element
) {
2307 res
= parser_info
->top_element
->GetAsValue ();
2308 // We want a copy because the old one is going to be deleted
2309 res
= new Value (*res
);
2312 *element_type
= parser_info
->top_element
->info
->GetKind ();
2314 if (parser_info
->error_args
) {
2315 *element_type
= Type::INVALID
;
2316 goto cleanup_and_return
;
2323 error_args
= new ParserErrorEventArgs ("Error opening xaml file", xaml_file
, 0, 0, 1, "", "");
2324 else if (parser_info
->error_args
) {
2325 error_args
= parser_info
->error_args
;
2341 XamlLoader::CreateFromString (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
, int flags
)
2343 return HydrateFromString (xaml
, NULL
, create_namescope
, element_type
, flags
);
2347 value_to_dependency_object (Value
*value
)
2349 if (!value
|| !value
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
))
2351 return value
->AsDependencyObject ();
2355 XamlLoader::CreateDependencyObjectFromFile (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
)
2357 return value_to_dependency_object (CreateFromFile (xaml
, create_namescope
, element_type
));
2361 XamlLoader::CreateDependencyObjectFromString (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
)
2363 return value_to_dependency_object (CreateFromString (xaml
, create_namescope
, element_type
, IMPORT_DEFAULT_XMLNS
));
2367 * Hydrates an existing DependencyObject (@object) with the contents from the @xaml
2371 XamlLoader::HydrateFromString (const char *xaml
, Value
*object
, bool create_namescope
, Type::Kind
*element_type
, int flags
)
2373 XML_Parser p
= XML_ParserCreateNS ("utf-8", '|');
2374 XamlParserInfo
*parser_info
= NULL
;
2376 char *start
= (char*)xaml
;
2377 char *prepend
= NULL
;
2378 char *append
= NULL
;
2379 char * inputs
[4] = {NULL
, NULL
, NULL
, NULL
};
2384 LOG_XAML ("can not create parser\n");
2385 goto cleanup_and_return
;
2394 sprintf (filename
, "createFromXaml.%d.xaml", id
++);
2395 if ((fp
= fopen (filename
, "wt")) != NULL
) {
2396 fwrite (xaml
, strlen (xaml
), 1, fp
);
2402 parser_info
= new XamlParserInfo (p
, NULL
);
2404 parser_info
->namescope
->SetTemporary (!create_namescope
);
2406 parser_info
->loader
= this;
2407 parser_info
->validate_templates
= (flags
& VALIDATE_TEMPLATES
) == VALIDATE_TEMPLATES
;
2410 // If we are hydrating, we are not null
2412 if (object
!= NULL
) {
2413 parser_info
->hydrate_expecting
= object
;
2414 parser_info
->hydrating
= true;
2415 if (Type::IsSubclassOf (parser_info
->deployment
, object
->GetKind (), Type::DEPENDENCY_OBJECT
)) {
2416 DependencyObject
*dob
= object
->AsDependencyObject ();
2417 dob
->SetIsAttached (true);
2418 dob
->SetResourceBase (GetResourceBase());
2421 parser_info
->hydrate_expecting
= NULL
;
2422 parser_info
->hydrating
= false;
2425 // from_str gets the default namespaces implictly added
2426 add_default_namespaces (parser_info
, (flags
& IMPORT_DEFAULT_XMLNS
) == IMPORT_DEFAULT_XMLNS
);
2428 XML_SetUserData (p
, parser_info
);
2430 XML_SetElementHandler (p
, start_element_handler
, end_element_handler
);
2431 XML_SetCharacterDataHandler (p
, char_data_handler
);
2432 XML_SetNamespaceDeclHandler(p
, start_namespace_handler
, NULL
);
2433 XML_SetDoctypeDeclHandler(p
, start_doctype_handler
, NULL
);
2436 XML_SetProcessingInstructionHandler (p, proc_handler);
2440 prepend
= context
->internal
->CreateIgnorableTagOpen ();
2441 append
= context
->internal
->CreateIgnorableTagClose ();
2443 inputs
[0] = prepend
;
2445 inputs
[2] = append
;
2448 for (int i
= 0; inputs
[i
]; i
++) {
2449 char *start
= inputs
[i
];
2451 // don't freak out if the <?xml ... ?> isn't on the first line (see #328907)
2452 while (g_ascii_isspace (*start
))
2455 parser_info
->SetXmlBuffer (start
);
2456 if (!XML_Parse (p
, start
, strlen (start
), inputs
[i
+ 1] == NULL
)) {
2457 expat_parser_error (parser_info
, XML_GetErrorCode (p
));
2458 LOG_XAML ("error parsing: %s\n\n", xaml
);
2459 goto cleanup_and_return
;
2463 print_tree (parser_info
->top_element
, 0);
2465 if (parser_info
->top_element
) {
2466 if (is_legal_top_level_kind (parser_info
->top_element
->info
->GetKind ())) {
2467 res
= parser_info
->top_element
->GetAsValue ();
2468 res
= new Value (*res
);
2469 if (res
->Is (parser_info
->deployment
, Type::DEPENDENCY_OBJECT
) && object
) {
2470 DependencyObject
*dob
= res
->AsDependencyObject ();
2472 dob
->SetIsHydratedFromXaml (parser_info
->hydrating
);
2477 *element_type
= parser_info
->top_element
->info
->GetKind ();
2479 if (!res
&& !parser_info
->error_args
)
2480 parser_info
->error_args
= new ParserErrorEventArgs ("No DependencyObject found", "", 0, 0, 1, "", "");
2482 if (parser_info
->error_args
) {
2486 *element_type
= Type::INVALID
;
2487 goto cleanup_and_return
;
2493 if (parser_info
->error_args
) {
2494 error_args
= parser_info
->error_args
;
2495 printf ("Could not parse element %s, attribute %s, error: %s\n",
2496 error_args
->xml_element
,
2497 error_args
->xml_attribute
,
2498 error_args
->GetErrorMessage());
2514 XamlLoader::CreateFromFileWithError (const char *xaml_file
, bool create_namescope
, Type::Kind
*element_type
, MoonError
*error
)
2516 Value
*res
= CreateFromFile (xaml_file
, create_namescope
, element_type
);
2517 if (error_args
&& error_args
->GetErrorCode () != -1)
2518 MoonError::FillIn (error
, error_args
);
2523 XamlLoader::CreateFromStringWithError (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
, int flags
, MoonError
*error
)
2525 Value
*res
= CreateFromString (xaml
, create_namescope
, element_type
, flags
);
2526 if (error_args
&& error_args
->GetErrorCode () != -1)
2527 MoonError::FillIn (error
, error_args
);
2532 XamlLoader::HydrateFromStringWithError (const char *xaml
, Value
*object
, bool create_namescope
, Type::Kind
*element_type
, int flags
, MoonError
*error
)
2534 Value
*res
= HydrateFromString (xaml
, object
, create_namescope
, element_type
, flags
);
2535 if (error_args
&& error_args
->GetErrorCode () != -1)
2536 MoonError::FillIn (error
, error_args
);
2541 parse_int (const char **pp
, const char *end
)
2543 const char *p
= *pp
;
2545 if (optional
&& AtEnd
)
2552 while (p
<= end
&& g_ascii_isdigit (*p
)) {
2553 res
= res
* 10 + *p
- '0';
2568 parse_ticks (const char **pp
, const char *end
)
2570 gint64 mag
= 1000000;
2572 bool digitseen
= false;
2574 const char *p
= *pp
;
2576 while (mag
> 0 && p
<= end
&& g_ascii_isdigit (*p
)) {
2577 res
= res
+ (*p
- '0') * mag
;
2593 time_span_from_str (const char *str
, TimeSpan
*res
)
2595 const char *end
= str
+ strlen (str
);
2598 bool negative
= false;
2612 days
= parse_int (&p
, end
);
2616 hours
= parse_int (&p
, end
);
2624 minutes
= parse_int (&p
, end
);
2626 seconds
= parse_int (&p
, end
);
2629 ticks
= parse_ticks (&p
, end
);
2635 gint64 t
= (days
* 86400) + (hours
* 3600) + (minutes
* 60) + seconds
;
2638 *res
= negative
? (-t
- ticks
) : (t
+ ticks
);
2644 repeat_behavior_from_str (const char *str
, RepeatBehavior
*res
)
2646 if (!g_ascii_strcasecmp ("Forever", str
)) {
2647 *res
= RepeatBehavior::Forever
;
2651 // check for "<float>x".
2653 // XXX more validation work is needed here.. but how do we
2655 const char *x
= strchr (str
, 'x');
2657 if (*(x
+ 1) != '\0') {
2663 double d
= g_ascii_strtod (str
, &endptr
);
2665 if (errno
|| endptr
== str
)
2668 *res
= RepeatBehavior (d
);
2673 /* XXX RepeatBehavior='XX:XX:XX' syntax is NOT correctly supported by
2674 Silverlight 1.0 (most likely a bug). It works fine in Silverlight 2.0
2675 though. We currently stick to the 2.0 behavior, not replicating the bug
2679 if (!time_span_from_str (str
, &t
))
2682 *res
= RepeatBehavior (t
);
2688 duration_from_str (const char *str
, Duration
*res
)
2690 if (!g_ascii_strcasecmp ("Automatic", str
)) {
2691 *res
= Duration::Automatic
;
2695 if (!g_ascii_strcasecmp ("Forever", str
)) {
2696 *res
= Duration::Forever
;
2701 if (!time_span_from_str (str
, &ts
))
2704 *res
= Duration (ts
);
2709 keytime_from_str (const char *str
, KeyTime
*res
)
2711 if (!g_ascii_strcasecmp ("Uniform", str
)) {
2712 *res
= KeyTime::Uniform
;
2716 if (!g_ascii_strcasecmp ("Paced", str
)) {
2717 *res
= KeyTime::Paced
;
2721 /* check for a percentage first */
2722 const char *last
= str
+ strlen(str
) - 1;
2725 double pct
= g_ascii_strtod (str
, &ep
);
2727 *res
= KeyTime (pct
);
2733 if (!time_span_from_str (str
, &ts
))
2736 *res
= KeyTime (ts
);
2741 key_spline_from_str (const char *str
, KeySpline
**res
)
2743 PointCollection
*pts
= PointCollection::FromStr (str
);
2748 if (pts
->GetCount () != 2) {
2753 *res
= new KeySpline (*pts
->GetValueAt (0)->AsPoint (), *pts
->GetValueAt (1)->AsPoint ());
2761 matrix_from_str (const char *str
)
2763 if (!g_ascii_strcasecmp ("Identity", str
)) {
2764 return new Matrix ();
2767 DoubleCollection
*values
= DoubleCollection::FromStr (str
);
2771 return new Matrix ();
2773 if (values
->GetCount () < 6) {
2778 matrix
= new Matrix ();
2779 matrix
->SetM11 (values
->GetValueAt (0)->AsDouble ());
2780 matrix
->SetM12 (values
->GetValueAt (1)->AsDouble ());
2781 matrix
->SetM21 (values
->GetValueAt (2)->AsDouble ());
2782 matrix
->SetM22 (values
->GetValueAt (3)->AsDouble ());
2783 matrix
->SetOffsetX (values
->GetValueAt (4)->AsDouble ());
2784 matrix
->SetOffsetY (values
->GetValueAt (5)->AsDouble ());
2792 matrix3d_from_str (const char *str
)
2794 if (!g_ascii_strcasecmp ("Identity", str
)) {
2795 return new Matrix3D ();
2798 DoubleCollection
*values
= DoubleCollection::FromStr (str
);
2802 return new Matrix3D ();
2804 if (values
->GetCount () < 12) {
2809 matrix
= new Matrix3D ();
2810 matrix
->SetM11 (values
->GetValueAt (0)->AsDouble ());
2811 matrix
->SetM12 (values
->GetValueAt (1)->AsDouble ());
2812 matrix
->SetM13 (values
->GetValueAt (2)->AsDouble ());
2813 matrix
->SetM13 (values
->GetValueAt (3)->AsDouble ());
2814 matrix
->SetM21 (values
->GetValueAt (4)->AsDouble ());
2815 matrix
->SetM22 (values
->GetValueAt (5)->AsDouble ());
2816 matrix
->SetM23 (values
->GetValueAt (6)->AsDouble ());
2817 matrix
->SetM24 (values
->GetValueAt (7)->AsDouble ());
2818 matrix
->SetM31 (values
->GetValueAt (8)->AsDouble ());
2819 matrix
->SetM32 (values
->GetValueAt (9)->AsDouble ());
2820 matrix
->SetM33 (values
->GetValueAt (10)->AsDouble ());
2821 matrix
->SetM34 (values
->GetValueAt (11)->AsDouble ());
2822 matrix
->SetOffsetX (values
->GetValueAt (12)->AsDouble ());
2823 matrix
->SetOffsetY (values
->GetValueAt (13)->AsDouble ());
2824 matrix
->SetOffsetZ (values
->GetValueAt (14)->AsDouble ());
2825 matrix
->SetM44 (values
->GetValueAt (15)->AsDouble ());
2833 grid_length_from_str (const char *str
, GridLength
*grid_length
)
2835 if (IS_NULL_OR_EMPTY (str
)) {
2836 *grid_length
= GridLength (0.0, GridUnitTypePixel
);
2840 if (str
[0] == '*') {
2841 *grid_length
= GridLength (1.0, GridUnitTypeStar
);
2845 // unit tests shows that "Auto", "auto", "aUtO"... all works
2846 if (!g_ascii_strcasecmp (str
, "Auto")) {
2847 *grid_length
= GridLength ();
2853 double d
= g_ascii_strtod (str
, &endptr
);
2855 if (errno
|| endptr
== str
)
2858 *grid_length
= GridLength (d
, *endptr
== '*' ? GridUnitTypeStar
: GridUnitTypePixel
);
2867 while (*inptr
&& !g_ascii_isalnum (*inptr
) && *inptr
!= '.' && *inptr
!= '-' && *inptr
!= '+')
2868 inptr
= g_utf8_next_char (inptr
);
2874 get_point (Point
*p
, char **in
)
2876 char *end
, *inptr
= *in
;
2879 x
= g_ascii_strtod (inptr
, &end
);
2884 while (g_ascii_isspace (*inptr
))
2890 while (g_ascii_isspace (*inptr
))
2893 y
= g_ascii_strtod (inptr
, &end
);
2906 make_relative (const Point
*cp
, Point
*mv
)
2913 more_points_available (char **in
)
2917 while (g_ascii_isspace (*inptr
) || *inptr
== ',')
2922 return (g_ascii_isdigit (*inptr
) || *inptr
== '.' || *inptr
== '-' || *inptr
== '+');
2926 geometry_from_str (const char *str
)
2928 char *inptr
= (char *) str
;
2929 Point cp
= Point (0, 0);
2930 Point cp1
, cp2
, cp3
;
2933 PathGeometry
*pg
= NULL
;
2934 FillRule fill_rule
= FillRuleEvenOdd
;
2935 bool cbz
= false; // last figure is a cubic bezier curve
2936 bool qbz
= false; // last figure is a quadratic bezier curve
2937 Point cbzp
, qbzp
; // points needed to create "smooth" beziers
2939 moon_path
*path
= moon_path_new (10);
2942 if (g_ascii_isspace (*inptr
))
2948 bool relative
= false;
2951 inptr
= g_utf8_next_char (inptr
);
2959 fill_rule
= FillRuleEvenOdd
;
2960 else if (*inptr
== '1')
2961 fill_rule
= FillRuleNonzero
;
2963 // FIXME: else it's a bad value and nothing should be rendered
2964 goto bad_pml
; // partial: only this Path won't be rendered
2966 inptr
= g_utf8_next_char (inptr
);
2971 if (!get_point (&cp1
, &inptr
))
2975 make_relative (&cp
, &cp1
);
2978 moon_move_to (path
, cp1
.x
, cp1
.y
);
2980 start
.x
= cp
.x
= cp1
.x
;
2981 start
.y
= cp
.y
= cp1
.y
;
2984 while (more_points_available (&inptr
)) {
2985 if (!get_point (&cp1
, &inptr
))
2989 make_relative (&cp
, &cp1
);
2991 moon_line_to (path
, cp1
.x
, cp1
.y
);
3003 while (more_points_available (&inptr
)) {
3004 if (!get_point (&cp1
, &inptr
))
3008 make_relative (&cp
, &cp1
);
3010 moon_line_to (path
, cp1
.x
, cp1
.y
);
3025 double x
= g_ascii_strtod (inptr
, &end
);
3033 cp
= Point (x
, cp
.y
);
3035 moon_line_to (path
, cp
.x
, cp
.y
);
3044 double y
= g_ascii_strtod (inptr
, &end
);
3052 cp
= Point (cp
.x
, y
);
3054 moon_line_to (path
, cp
.x
, cp
.y
);
3063 while (more_points_available (&inptr
)) {
3064 if (!get_point (&cp1
, &inptr
))
3068 make_relative (&cp
, &cp1
);
3072 if (!get_point (&cp2
, &inptr
))
3076 make_relative (&cp
, &cp2
);
3080 if (!get_point (&cp3
, &inptr
))
3084 make_relative (&cp
, &cp3
);
3088 moon_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
, cp3
.x
, cp3
.y
);
3105 while (more_points_available (&inptr
)) {
3106 if (!get_point (&cp2
, &inptr
))
3110 make_relative (&cp
, &cp2
);
3114 if (!get_point (&cp3
, &inptr
))
3118 make_relative (&cp
, &cp3
);
3121 cp1
.x
= 2 * cp
.x
- cbzp
.x
;
3122 cp1
.y
= 2 * cp
.y
- cbzp
.y
;
3126 moon_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
, cp3
.x
, cp3
.y
);
3143 while (more_points_available (&inptr
)) {
3144 if (!get_point (&cp1
, &inptr
))
3148 make_relative (&cp
, &cp1
);
3152 if (!get_point (&cp2
, &inptr
))
3156 make_relative (&cp
, &cp2
);
3160 moon_quad_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
);
3175 while (more_points_available (&inptr
)) {
3176 if (!get_point (&cp2
, &inptr
))
3180 make_relative (&cp
, &cp2
);
3183 cp1
.x
= 2 * cp
.x
- qbzp
.x
;
3184 cp1
.y
= 2 * cp
.y
- qbzp
.y
;
3188 moon_quad_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
);
3205 while (more_points_available (&inptr
)) {
3206 if (!get_point (&cp1
, &inptr
))
3211 double angle
= g_ascii_strtod (inptr
, &end
);
3218 int is_large
= strtol (inptr
, &end
, 10);
3225 int sweep
= strtol (inptr
, &end
, 10);
3232 if (!get_point (&cp2
, &inptr
))
3236 make_relative (&cp
, &cp2
);
3238 moon_arc_to (path
, cp1
.x
, cp1
.y
, angle
, is_large
, sweep
, cp2
.x
, cp2
.y
);
3250 moon_line_to (path
, start
.x
, start
.y
);
3251 moon_close_path (path
);
3252 moon_move_to (path
, start
.x
, start
.y
);
3263 pg
= new PathGeometry (path
);
3264 pg
->SetFillRule (fill_rule
);
3268 moon_path_destroy (path
);
3273 value_is_explicit_null (const char *str
)
3275 return !strcmp ("{x:Null}", str
);
3279 is_managed_kind (Type::Kind kind
)
3282 if (kind
== Type::MANAGED
||
3283 kind
== Type::OBJECT
||
3284 kind
== Type::URI
||
3285 kind
== Type::MANAGEDTYPEINFO
||
3286 kind
== Type::DEPENDENCYPROPERTY
)
3293 kind_requires_managed_load (Type::Kind kind
)
3295 if (kind
== Type::USERCONTROL
) {
3303 is_legal_top_level_kind (Type::Kind kind
)
3305 if (kind
== Type::MANAGED
|| kind
== Type::OBJECT
|| Type::IsSubclassOf (Deployment::GetCurrent (), kind
, Type::DEPENDENCY_OBJECT
))
3310 // NOTE: Keep definition in sync with class/System.Windows/Mono/NativeMethods.cs
3312 value_from_str_with_typename (const char *type_name
, const char *prop_name
, const char *str
, Value
**v
)
3314 Type
*t
= Type::Find (Deployment::GetCurrent (), type_name
);
3318 return value_from_str (t
->GetKind (), prop_name
, str
, v
);
3322 expand_property_path (XamlParserInfo
*p
, PropertyPath
*path
)
3327 bool expanded
= false;
3328 GString
*res
= g_string_new (path
->path
);
3330 int len
= strlen (res
->str
);
3331 for (int i
= 0; i
< len
; i
++) {
3332 if (res
->str
[i
] == ':') {
3336 for ( ; s
> 0; s
--) {
3337 if (!g_ascii_isalnum (res
->str
[s
]))
3341 for ( ; te
< len
; te
++) {
3342 if (!g_ascii_isalpha (res
->str
[te
]) || res
->str
[te
] == '_')
3346 char *prefix
= g_strndup (res
->str
+ s
+ 1, e
- s
- 1);
3347 char *type
= g_strndup (res
->str
+ e
+ 1, te
- e
- 1);
3349 res
= g_string_erase (res
, s
+ 1, te
- s
- 1);
3351 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
3355 g_string_free (res
, true);
3359 XamlElementInfo
*info
= ns
->FindElement (p
, type
, NULL
, false);
3364 g_string_free (res
, true);
3368 char *uri
= g_strdup_printf ("'%s'", Type::Find (p
->deployment
, info
->GetKind ())->GetName ());
3370 res
= g_string_insert (res
, s
+ 1, uri
);
3371 i
= s
+ 1 + strlen (uri
);
3372 len
= strlen (res
->str
);
3384 g_string_free (res
, true);
3388 char *expanded_str
= res
->str
;
3389 g_string_free (res
, false);
3391 return expanded_str
;
3395 value_from_str (Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
)
3399 value_from_str_with_parser (NULL
, type
, prop_name
, str
, v
, &v_set
);
3405 xaml_bool_from_str (const char *s
, bool *res
)
3410 if (!g_ascii_strcasecmp ("true", s
))
3412 else if (!g_ascii_strcasecmp ("false", s
))
3415 // Check if it's a string representing a decimal value
3419 l
= strtol (s
, &endptr
, 10);
3421 if (errno
|| endptr
== s
|| *endptr
|| l
> G_MAXINT32
|| l
< G_MININT32
)
3435 value_from_str_with_parser (XamlParserInfo
*p
, Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
, bool *v_set
)
3440 if (value_is_explicit_null (str
)) {
3446 char *s
= g_strdup (str
);
3448 if (type
== Type::OBJECT
|| type
== Type::STRING
) {
3449 // object and string use the literal string
3452 // everything else depends on the string being stripped
3457 case Type::OBJECT
: {
3458 // not much more can do here, unless we want to try to
3459 // probe str to see if it's actually meant to be a
3460 // specific type. just assume it's a string.
3469 if (!xaml_bool_from_str (s
, &b
))
3476 case Type::DOUBLE
: {
3479 // empty string should not reset default values with 0
3481 // FIXME: this causes a 2.0 unit test to fail (PrimitiveTest.ParseEmptyDouble)
3482 if (IS_NULL_OR_EMPTY(s
)) {
3487 bool is_nan
= false;
3488 if (!g_ascii_strcasecmp (s
, "NAN"))
3492 d
= g_ascii_strtod (s
, &endptr
);
3495 if (is_nan
|| errno
|| endptr
== s
|| *endptr
) {
3497 && (!strcmp (prop_name
, "Width") || !strcmp (prop_name
, "Height"))
3498 && (!g_ascii_strcasecmp (s
, "Auto") || is_nan
))
3512 l
= strtol (s
, &endptr
, 10);
3514 if (errno
|| endptr
== s
)
3517 *v
= new Value (l
, Type::INT64
);
3521 case Type::TIMESPAN
: {
3524 if (!time_span_from_str (s
, &ts
))
3527 *v
= new Value (ts
, Type::TIMESPAN
);
3534 if (IS_NULL_OR_EMPTY(s
))
3536 else if (g_ascii_isalpha (s
[0]) && prop_name
) {
3537 i
= enums_str_to_int (prop_name
, s
);
3539 // g_warning ("'%s' enum is not valid on '%s' property", str, prop_name);
3544 long l
= strtol (s
, &endptr
, 10);
3546 if (errno
|| endptr
== s
)
3557 gunichar unichar
= g_utf8_get_char_validated (str
, -1);
3560 if ((int) unichar
< 0)
3563 if (!(next
= g_utf8_next_char (str
)) || *next
!= '\0')
3566 *v
= new Value (unichar
, Type::CHAR
);
3570 case Type::STRING
: {
3571 *v
= new Value (str
);
3576 Color
*c
= color_from_str (s
);
3579 *v
= new Value (*c
);
3584 case Type::REPEATBEHAVIOR
: {
3585 RepeatBehavior rb
= RepeatBehavior::Forever
;
3587 if (!repeat_behavior_from_str (s
, &rb
))
3590 *v
= new Value (rb
);
3594 case Type::DURATION
: {
3595 Duration d
= Duration::Forever
;
3597 if (!duration_from_str (s
, &d
))
3604 case Type::KEYTIME
: {
3605 KeyTime kt
= KeyTime::Paced
;
3607 if (!keytime_from_str (s
, &kt
))
3610 *v
= new Value (kt
);
3614 case Type::KEYSPLINE
: {
3617 if (!key_spline_from_str (s
, &ks
))
3620 *v
= Value::CreateUnrefPtr (ks
);
3625 case Type::SOLIDCOLORBRUSH
: {
3626 // Only solid color brushes can be specified using attribute syntax
3627 Color
*c
= color_from_str (s
);
3632 SolidColorBrush
*scb
= new SolidColorBrush ();
3637 *v
= Value::CreateUnrefPtr (scb
);
3644 if (!Point::FromStr (s
, &p
))
3654 if (!Size::FromStr (s
, &size
))
3657 *v
= new Value (size
);
3664 if (!Rect::FromStr (s
, &rect
))
3667 *v
= new Value (rect
);
3674 if (!uri
.Parse (s
)) {
3678 *v
= new Value (uri
);
3682 case Type::DOUBLE_COLLECTION
: {
3683 DoubleCollection
*doubles
= DoubleCollection::FromStr (s
);
3685 *v
= Value::CreateUnrefPtr (new DoubleCollection ());
3690 *v
= Value::CreateUnrefPtr (doubles
);
3694 case Type::POINT_COLLECTION
: {
3695 PointCollection
*points
= PointCollection::FromStr (s
);
3697 *v
= Value::CreateUnrefPtr (new PointCollection ());
3702 *v
= Value::CreateUnrefPtr (points
);
3706 case Type::TRANSFORMGROUP
: {
3707 if (IS_NULL_OR_EMPTY(s
))
3710 Matrix
*mv
= matrix_from_str (s
);
3714 TransformGroup
*tg
= new TransformGroup ();
3715 MatrixTransform
*t
= new MatrixTransform ();
3716 t
->SetValue (MatrixTransform::MatrixProperty
, Value (mv
));
3718 tg
->GetChildren()->Add (t
);
3721 *v
= new Value (tg
);
3727 case Type::TRANSFORM
:
3729 if (!g_ascii_strcasecmp ("Identity", str
)) {
3735 // Intentional fall through, you can create a matrix from a TRANSFORM property, but not using Identity
3736 case Type::MATRIXTRANSFORM
:
3738 if (IS_NULL_OR_EMPTY(s
))
3741 Matrix
*mv
= matrix_from_str (s
);
3745 MatrixTransform
*t
= new MatrixTransform ();
3746 t
->SetValue (MatrixTransform::MatrixProperty
, Value (mv
));
3754 case Type::UNMANAGEDMATRIX
:
3755 case Type::MATRIX
: {
3756 // note: unlike TRANSFORM this creates an empty, identity, matrix for an empty string
3757 Matrix
*matrix
= matrix_from_str (s
);
3761 *v
= new Value (matrix
);
3766 case Type::PROJECTION
:
3768 if (!g_ascii_strcasecmp ("Identity", str
)) {
3774 // Intentional fall through, you can create a matrix from a PROJECTION property, but not using Identity
3775 case Type::MATRIX3DPROJECTION
:
3777 if (IS_NULL_OR_EMPTY(s
))
3780 Matrix3D
*mv
= matrix3d_from_str (s
);
3784 Matrix3DProjection
*p
= new Matrix3DProjection ();
3785 p
->SetValue (Matrix3DProjection::ProjectionMatrixProperty
, Value (mv
));
3793 case Type::UNMANAGEDMATRIX3D
:
3794 case Type::MATRIX3D
: {
3795 Matrix3D
*matrix
= matrix3d_from_str (s
);
3799 *v
= new Value (matrix
);
3804 case Type::PATHGEOMETRY
:
3805 case Type::GEOMETRY
: {
3806 Geometry
*geometry
= geometry_from_str (s
);
3811 *v
= new Value (geometry
);
3816 case Type::THICKNESS
: {
3819 if (!Thickness::FromStr (s
, &t
))
3826 case Type::CORNERRADIUS
: {
3829 if (!CornerRadius::FromStr (s
, &c
))
3836 case Type::GRIDLENGTH
: {
3837 GridLength grid_length
;
3839 if (!grid_length_from_str (s
, &grid_length
))
3842 *v
= new Value (grid_length
);
3846 case Type::IMAGESOURCE
:
3847 case Type::BITMAPIMAGE
: {
3853 BitmapImage
*bi
= new BitmapImage ();
3855 bi
->SetUriSource (&uri
);
3857 *v
= Value::CreateUnrefPtr (bi
);
3862 case Type::MULTISCALETILESOURCE
:
3863 case Type::DEEPZOOMIMAGETILESOURCE
: {
3864 // As far as I know the only thing you can create here is a URI based DeepZoomImageTileSource
3868 *v
= Value::CreateUnrefPtr (new DeepZoomImageTileSource (&uri
));
3873 case Type::FONTFAMILY
: {
3874 *v
= new Value (FontFamily (s
));
3878 case Type::FONTWEIGHT
: {
3879 int fw
= enums_str_to_int ("FontWeight", s
);
3881 *v
= new Value (FontWeight ((FontWeights
)fw
));
3886 case Type::FONTSTYLE
: {
3887 int fs
= enums_str_to_int ("FontStyle", s
);
3889 *v
= new Value (FontStyle ((FontStyles
)fs
));
3894 case Type::FONTSTRETCH
: {
3895 int fs
= enums_str_to_int ("FontStretch", s
);
3897 *v
= new Value (FontStretch ((FontStretches
)fs
));
3902 case Type::PROPERTYPATH
: {
3903 PropertyPath
path (s
);
3904 path
.expanded_path
= expand_property_path (p
, &path
);
3905 *v
= new Value (path
);
3910 // we don't care about NULL or empty values
3911 if (!IS_NULL_OR_EMPTY (s
)) {
3922 XamlElementInstance::TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
)
3924 const char* prop_name
= info
->GetContentProperty (p
);
3929 DependencyProperty
*dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, info
->GetKind ()), prop_name
);
3933 bool is_collection
= Type::IsSubclassOf (p
->deployment
, dep
->GetPropertyType(), Type::DEPENDENCY_OBJECT_COLLECTION
);
3935 if (!is_collection
&& Type::IsSubclassOf (p
->deployment
, value
->info
->GetKind (), dep
->GetPropertyType())) {
3937 if (!item
->SetValueWithError (dep
, value
->GetAsValue (), &err
)) {
3938 parser_error (p
, value
->element_name
, NULL
, err
.code
, err
.message
);
3944 // We only want to enter this if statement if we are NOT dealing with the content property element,
3945 // otherwise, attempting to use explicit property setting, would add the content property element
3946 // to the content property element collection
3947 if (is_collection
&& dep
->GetPropertyType() != value
->info
->GetKind ()) {
3948 Value
*col_v
= item
->GetValue (dep
);
3952 col
= collection_new (dep
->GetPropertyType ());
3953 item
->SetValue (dep
, Value (col
));
3956 col
= (Collection
*) col_v
->AsCollection ();
3960 if (-1 == col
->AddWithError (value
->GetAsValue (), &err
)) {
3961 parser_error (p
, value
->element_name
, NULL
, err
.code
, err
.message
);
3972 XamlElementInstance::TrySetContentProperty (XamlParserInfo
*p
, const char *value
)
3974 const char* prop_name
= info
->GetContentProperty (p
);
3977 if (info
->GetKind () == Type::ICON
) {
3978 printf ("getting the text content of the icon\n");
3979 prop_name
= "Source";
3984 Type::Kind prop_type
= p
->current_element
->info
->GetKind ();
3985 DependencyProperty
*content
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, prop_type
), prop_name
);
3987 // TODO: There might be other types that can be specified here,
3988 // but string is all i have found so far. If you can specify other
3989 // types, i should pull the property setting out of set_attributes
3990 // and use that code
3992 if (content
&& (content
->GetPropertyType ()) == Type::STRING
&& value
) {
3993 item
->SetValue (content
, Value (g_strstrip (p
->cdata
->str
)));
3995 } else if (content
&& (content
->GetPropertyType ()) == Type::URI
&& value
) {
3998 if (!uri
.Parse (g_strstrip (p
->cdata
->str
)))
4001 item
->SetValue (content
, Value (uri
));
4003 } else if (Type::IsSubclassOf (p
->deployment
, info
->GetKind (), Type::TEXTBLOCK
)) {
4004 TextBlock
*textblock
= (TextBlock
*) item
;
4005 InlineCollection
*inlines
= textblock
->GetInlines ();
4006 Inline
*last
= NULL
;
4008 if (inlines
&& inlines
->GetCount () > 0)
4009 last
= inlines
->GetValueAt (inlines
->GetCount () - 1)->AsInline ();
4011 if (!p
->cdata_content
) {
4012 if (p
->next_element
&& !strcmp (p
->next_element
, "Run") && last
&& last
->GetObjectType () == Type::RUN
&&
4013 !last
->GetAutogenerated ()) {
4014 // LWSP between <Run> elements is to be treated as a single-SPACE <Run> element
4015 // Note: p->cdata is already canonicalized
4017 // This is one of the following cases:
4019 // 1. LWSP before the first <Run> element
4020 // 2. LWSP after the last <Run> element
4021 // 3. LWSP between <Run> and <LineBreak> elements
4025 if (!p
->next_element
|| !strcmp (p
->next_element
, "LineBreak"))
4026 g_strchomp (p
->cdata
->str
);
4028 if (!last
|| last
->GetObjectType () != Type::RUN
|| last
->GetAutogenerated ())
4029 g_strchug (p
->cdata
->str
);
4032 Run
*run
= new Run ();
4033 run
->SetText (p
->cdata
->str
);
4036 inlines
= new InlineCollection ();
4037 textblock
->SetInlines (inlines
);
4050 XamlElementInstance::SetUnknownAttribute (XamlParserInfo
*p
, const char *name
, const char *value
)
4055 Value v
= Value (value
);
4056 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, name
, &v
, NULL
)) {
4063 XamlElementInstance::SetDelayedProperties (XamlParserInfo
*p
)
4065 GSList
*walk
= delayed_properties
;
4068 DelayedProperty
*prop
= (DelayedProperty
*) walk
->data
;
4070 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), prop
->xmlns
, prop
->name
, prop
->value
, NULL
, XamlCallbackData::SETTING_DELAYED_PROPERTY
)) {
4071 parser_error (p
, element_name
, prop
->name
, 2012,
4072 "Unknown property %s on element %s.",
4073 prop
->name
, element_name
);
4083 XamlElementInstance::FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
)
4085 // We didn't find anything so try looking up in managed
4089 Value
*v
= new Value ();
4090 if (p
->loader
->LookupObject (p
, p
->GetTopElementPtr (), GetAsValue (), p
->current_namespace
->GetUri (), el
, false, true, v
)) {
4091 char *type_name
= g_strndup (el
, dot
- el
);
4093 XamlElementInfoManaged
*res
= new XamlElementInfoManaged (g_strdup (p
->current_namespace
->GetUri ()), el
, info
, v
->GetKind (), v
);
4094 XamlElementInfo
*container
= p
->current_namespace
->FindElement (p
, type_name
, NULL
, false);
4095 info
->SetPropertyOwnerKind (container
->GetKind ());
4104 static XamlElementInfo
*
4105 create_element_info_from_imported_managed_type (XamlParserInfo
*p
, const char *name
, const char **attr
, bool create
)
4110 char* type_name
= NULL
;
4111 char* type_xmlns
= NULL
;
4112 const char* use_xmlns
= NULL
;
4115 // We might have an x:Class attribute specified, so we need to use that for the
4116 // type_name that we pass to LookupObject
4117 if (strcmp ("Application", name
)) {
4118 type_name
= x_namespace
->FindTypeName (attr
, &type_xmlns
);
4121 use_xmlns
= type_xmlns
;
4123 if (!p
->hydrating
) {
4124 parser_error (p
, name
, "x:Class", 4005, "Cannot specify x:Class in xaml files outside of a xap.");
4131 Value
*v
= new Value ();
4132 if (!p
->loader
->LookupObject (p
, use_xmlns
? p
->GetTopElementPtr () : NULL
, NULL
, use_xmlns
, name
, create
, false, v
)) {
4137 g_free (type_xmlns
);
4141 XamlElementInfoImportedManaged
*info
= new XamlElementInfoImportedManaged (g_strdup (name
), NULL
, v
);
4144 if (v
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4145 p
->AddCreatedElement (v
->AsDependencyObject());
4153 XamlElementInfoNative::GetContentProperty (XamlParserInfo
*p
)
4155 return type
->GetContentPropertyName ();
4158 XamlElementInstance
*
4159 XamlElementInfoNative::CreateElementInstance (XamlParserInfo
*p
)
4161 if (type
->IsValueType ())
4162 return new XamlElementInstanceValueType (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4163 else if (type
->IsSubclassOf (Type::FRAMEWORKTEMPLATE
))
4164 return new XamlElementInstanceTemplate (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4166 return new XamlElementInstanceNative (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4169 XamlElementInstance
*
4170 XamlElementInfoNative::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4172 XamlElementInstance
*res
= new XamlElementInstanceNative (this, p
, GetName (), XamlElementInstance::ELEMENT
, false);
4173 res
->SetDependencyObject (o
->AsDependencyObject ());
4179 XamlElementInstanceNative::FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
)
4181 if (IsDependencyObject ()) {
4182 const char *prop_name
= dot
+ 1;
4183 DependencyProperty
*prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, info
->GetKind ()), prop_name
);
4185 XamlElementInfoNative
*info
= new XamlElementInfoNative (Type::Find (p
->deployment
, prop
->GetPropertyType ()));
4186 info
->SetPropertyOwnerKind (prop
->GetOwnerType ());
4191 return XamlElementInstance::FindPropertyElement (p
, el
, dot
);
4194 XamlElementInstance
*
4195 XamlElementInfoNative::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4197 return new XamlElementInstanceNative (this, p
, name
, XamlElementInstance::PROPERTY
, false);
4200 XamlElementInstanceNative::XamlElementInstanceNative (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
) :
4201 XamlElementInstance (element_info
, name
, type
)
4203 this->element_info
= element_info
;
4204 this->parser_info
= parser_info
;
4206 SetDependencyObject (CreateItem ());
4212 XamlElementInstanceNative::CreateItem ()
4214 XamlElementInstance
*walk
= parser_info
->current_element
;
4215 Type
*type
= element_info
->GetType ();
4217 DependencyObject
*item
= NULL
;
4218 DependencyProperty
*dep
= NULL
;
4220 if (type
->IsSubclassOf (Type::COLLECTION
) || type
->IsSubclassOf (Type::RESOURCE_DICTIONARY
)) {
4221 // If we are creating a collection, try walking up the element tree,
4222 // to find the parent that we belong to and using that instance for
4223 // our collection, instead of creating a new one
4225 // We attempt to advance past the property setter, because we might be dealing with a
4228 if (walk
&& walk
->element_type
== XamlElementInstance::PROPERTY
) {
4229 char **prop_name
= g_strsplit (walk
->element_name
, ".", -1);
4231 walk
= walk
->parent
;
4232 dep
= DependencyProperty::GetDependencyProperty (Type::Find (parser_info
->deployment
, walk
->info
->GetKind ()), prop_name
[1]);
4234 g_strfreev (prop_name
);
4235 } else if (walk
&& walk
->info
->GetContentProperty (parser_info
)) {
4236 dep
= DependencyProperty::GetDependencyProperty (Type::Find (parser_info
->deployment
, walk
->info
->GetKind ()),
4237 (char *) walk
->info
->GetContentProperty (parser_info
));
4240 if (dep
&& Type::IsSubclassOf (parser_info
->deployment
, dep
->GetPropertyType(), type
->GetKind ())) {
4241 Value
*v
= ((DependencyObject
* ) walk
->GetAsDependencyObject ())->GetValue (dep
);
4243 item
= v
->AsDependencyObject ();
4246 // note: if !v then the default collection is NULL (e.g. PathFigureCollection)
4251 item
= element_info
->GetType()->IsCtorVisible() ? element_info
->GetType ()->CreateInstance () : NULL
;
4254 parser_info
->AddCreatedElement (item
);
4256 // in case we must store the collection into the parent
4257 if (dep
&& dep
->GetPropertyType() == type
->GetKind ()) {
4259 Value
item_value (item
);
4260 if (!((DependencyObject
* ) walk
->GetAsDependencyObject ())->SetValueWithError (dep
, &item_value
, &err
))
4261 parser_error (parser_info
, element_name
, NULL
, err
.code
, err
.message
);
4264 parser_error (parser_info
, element_name
, NULL
, 2007, "Unknown element: %s.", element_name
);
4272 XamlElementInstanceNative::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
)
4274 if (property
->info
->RequiresManagedSet () || value
->info
->RequiresManagedSet ())
4275 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, value
->GetAsValue (), NULL
);
4277 return dependency_object_set_property (p
, this, property
, value
, true);
4281 XamlElementInstanceNative::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
)
4283 char **prop_name
= g_strsplit (property
->element_name
, ".", -1);
4284 Type
*owner
= Type::Find (p
->deployment
, prop_name
[0]);
4285 DependencyProperty
*dep
;
4290 dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, owner
->GetKind ()), prop_name
[1]);
4294 return xaml_set_property_from_str (item
, dep
, value
, NULL
/*XXX*/);
4298 XamlElementInstanceNative::AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
)
4300 dependency_object_add_child (p
, this, child
, true);
4304 XamlElementInstanceNative::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4306 dependency_object_set_attributes (p
, this, attr
);
4310 XamlElementInstanceValueType::XamlElementInstanceValueType (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
) :
4311 XamlElementInstance (element_info
, name
, type
)
4313 this->element_info
= element_info
;
4314 this->parser_info
= parser_info
;
4318 XamlElementInstanceValueType::CreateValueItemFromString (const char* str
)
4321 bool res
= value_from_str (element_info
->GetType ()->GetKind (), NULL
, str
, &value
);
4326 XamlElementInstanceValueType::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4328 value_type_set_attributes (p
, this, attr
);
4331 XamlElementInstanceEnum::XamlElementInstanceEnum (XamlElementInfoEnum
*element_info
, const char *name
, ElementType type
) :
4332 XamlElementInstance (element_info
, name
, type
)
4337 XamlElementInstanceEnum::CreateEnumFromString (const char* str
)
4339 int i
= enums_str_to_int (element_name
, str
);
4343 value
= new Value (i
);
4348 XamlElementInstanceEnum::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4350 value_type_set_attributes (p
, this, attr
);
4353 XamlElementInstance
*
4354 XamlElementInfoEnum::CreateElementInstance (XamlParserInfo
*p
)
4356 return new XamlElementInstanceEnum (this, name
, XamlElementInstance::ELEMENT
);
4359 XamlElementInstance
*
4360 XamlElementInfoEnum::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4362 XamlElementInstance
*res
= new XamlElementInstanceEnum (this, name
, XamlElementInstance::ELEMENT
);
4367 XamlElementInfoManaged::GetContentProperty (XamlParserInfo
*p
)
4372 // TODO: We could cache this, but for now lets keep things as simple as possible.
4373 const char *res
= p
->loader
->GetContentPropertyName (p
, p
->GetTopElementPtr (), obj
);
4376 return XamlElementInfo::GetContentProperty (p
);
4379 XamlElementInstance
*
4380 XamlElementInfoManaged::CreateElementInstance (XamlParserInfo
*p
)
4382 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, GetName (), XamlElementInstance::ELEMENT
, obj
);
4384 if (obj
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4385 p
->AddCreatedElement (inst
->GetAsDependencyObject ());
4390 XamlElementInstance
*
4391 XamlElementInfoManaged::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4393 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, GetName (), XamlElementInstance::ELEMENT
, o
);
4398 XamlElementInstance
*
4399 XamlElementInfoManaged::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4401 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::PROPERTY
, obj
);
4406 XamlElementInstanceManaged::XamlElementInstanceManaged (XamlElementInfo
*info
, const char *name
, ElementType type
, Value
*obj
) :
4407 XamlElementInstance (info
, name
, type
)
4409 // The managed code owns our Value objects
4410 cleanup_value
= false;
4414 if (obj
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
)) {
4415 this->is_dependency_object
= true;
4416 this->SetDependencyObject (obj
->AsDependencyObject ());
4419 this->is_dependency_object
= false;
4423 XamlElementInstanceManaged::GetManagedPointer ()
4425 if (value
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
))
4426 return value
->AsDependencyObject ();
4427 return value
->AsManagedObject ();
4431 XamlElementInstanceManaged::GetParentPointer ()
4433 XamlElementInstance
*walk
= parent
;
4434 while (walk
&& walk
->element_type
!= XamlElementInstance::ELEMENT
)
4435 walk
= walk
->parent
;
4441 return walk
->GetAsValue ();
4445 XamlElementInstanceManaged::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
)
4447 if (GetAsDependencyObject () != NULL
&& dependency_object_set_property (p
, this, property
, value
, false))
4449 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, value
->GetAsValue (), value
);
4453 XamlElementInstanceManaged::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
)
4455 Value v
= Value (value
);
4456 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, &v
, NULL
);
4460 XamlElementInstanceManaged::AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
)
4462 if (element_type
== XamlElementInstance::PROPERTY
) {
4463 Value
*prop
= new Value (element_name
);
4464 p
->loader
->AddChild (p
, p
->GetTopElementPtr (), GetParentPointer (), true, info
->xmlns
, prop
, this, child
->GetAsValue (), child
);
4469 p
->loader
->AddChild (p
, p
->GetTopElementPtr (), GetParentPointer (), false, info
->xmlns
, GetAsValue (), this, child
->GetAsValue (), child
);
4473 XamlElementInstanceManaged::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4475 dependency_object_set_attributes (p
, this, attr
);
4479 XamlElementInstanceManaged::TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
)
4481 Value
*v
= value
->GetAsValue ();
4482 const char* prop_name
= info
->GetContentProperty (p
);
4484 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, prop_name
, v
, value
);
4488 XamlElementInstanceManaged::TrySetContentProperty (XamlParserInfo
*p
, const char *value
)
4490 if (Type::IsSubclassOf (p
->deployment
, info
->GetKind (), Type::CONTENTCONTROL
)) {
4491 // Content controls are not allowed to have their content set as text, they need to have a child element
4492 // if you want to set the content of a contentcontrol to text you need to use attribute syntax
4496 if (!XamlElementInstance::TrySetContentProperty (p
, value
)) {
4497 const char* prop_name
= info
->GetContentProperty (p
);
4498 if (!p
->cdata_content
)
4500 Value v
= Value (value
);
4501 bool res
= p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, prop_name
, &v
, NULL
);
4508 XamlElementInstance
*
4509 XamlElementInfoImportedManaged::CreateElementInstance (XamlParserInfo
*p
)
4511 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::ELEMENT
, obj
);
4517 XamlElementInfoImportedManaged::GetContentProperty (XamlParserInfo
*p
)
4522 // TODO: Test, it's possible that managed objects that aren't DOs are allowed to have content properties.
4523 if (!obj
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4524 return XamlElementInfo::GetContentProperty (p
);
4527 // TODO: We could cache this, but for now lets keep things as simple as possible.
4528 const char *res
= p
->loader
->GetContentPropertyName (p
, p
->GetTopElementPtr (), obj
);
4532 return XamlElementInfo::GetContentProperty (p
);
4535 XamlElementInstance
*
4536 XamlElementInfoImportedManaged::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4538 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, Type::Find (p
->deployment
, o
->GetKind ())->GetName (), XamlElementInstance::ELEMENT
, o
);
4543 XamlElementInstance
*
4544 XamlElementInfoImportedManaged::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4546 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::PROPERTY
, obj
);
4557 get_key_from_child (XamlElementInstance
*child
)
4559 const char *key
= child
->GetKey ();
4563 key
= child
->GetName ();
4567 if (child
->IsDependencyObject ()) {
4568 DependencyObject
*c
= child
->GetAsDependencyObject();
4570 if (Type::IsSubclassOf (c
->GetDeployment (), Type::STYLE
, child
->info
->GetKind ())) {
4571 Value
*v
= c
->GetValue (Style::TargetTypeProperty
);
4572 if (v
&& v
->GetKind () == Type::MANAGEDTYPEINFO
)
4573 key
= v
->AsManagedTypeInfo ()->full_name
;
4584 dependency_object_add_child (XamlParserInfo
*p
, XamlElementInstance
*parent
, XamlElementInstance
*child
, bool fail_if_no_prop
)
4586 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4587 if (parent
->element_type
== XamlElementInstance::PROPERTY
) {
4589 if (parent
->info
->RequiresManagedSet ())
4592 char **prop_name
= g_strsplit (parent
->element_name
, ".", -1);
4593 Type
*owner
= types
->Find (prop_name
[0]);
4596 DependencyProperty
*dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, owner
->GetKind ()), prop_name
[1]);
4598 g_strfreev (prop_name
);
4601 g_warning ("Unknown element: %s.", parent
->element_name
);
4602 if (fail_if_no_prop
)
4603 parser_error (p
, parent
->element_name
, NULL
, 2007, "Unknown element: %s.", parent
->element_name
);
4607 // XamlElementInfoEnum has Type::INVALID as
4608 // its kind, which is why that first check is
4610 if (child
->info
->GetKind() != Type::MANAGED
&&
4611 !types
->Find (child
->info
->GetKind())->IsCtorVisible()) {
4612 // we can't instantiate this type
4613 return parser_error (p
, child
->element_name
, NULL
, 2007,
4614 "Unknown element: %s.", child
->element_name
);
4617 // Don't add the child element, if it is the entire collection
4618 if (dep
->GetPropertyType() == child
->info
->GetKind ())
4621 Type::Kind prop_type
= dep
->GetPropertyType ();
4622 if (!types
->IsSubclassOf (prop_type
, Type::DEPENDENCY_OBJECT_COLLECTION
)
4623 && !types
->IsSubclassOf (prop_type
, Type::RESOURCE_DICTIONARY
))
4626 // Most common case, we will have a parent that we can snag the collection from
4627 DependencyObject
*obj
= (DependencyObject
*) parent
->parent
->GetAsDependencyObject ();
4631 Value
*col_v
= obj
->GetValue (dep
);
4633 Type
*col_type
= types
->Find (prop_type
);
4634 DependencyObject
*c_obj
= col_type
->CreateInstance ();
4635 obj
->SetValue (dep
, Value::CreateUnrefPtr (c_obj
));
4636 col_v
= obj
->GetValue (dep
);
4639 Collection
*col
= col_v
->AsCollection ();
4642 if (types
->IsSubclassOf (prop_type
, Type::DEPENDENCY_OBJECT_COLLECTION
)) {
4643 Value
child_val (child
->GetAsDependencyObject ());
4644 if (-1 == col
->AddWithError (&child_val
, &err
))
4645 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4647 else if (types
->IsSubclassOf (prop_type
, Type::RESOURCE_DICTIONARY
)) {
4648 ResourceDictionary
*dict
= (ResourceDictionary
*)col
;
4650 const char *key
= get_key_from_child (child
);
4653 // XXX don't know the proper values here...
4654 return parser_error (p
, child
->element_name
, NULL
, 2007,
4655 "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
4658 Value
*child_as_value
= child
->GetAsValue ();
4660 if (!child_as_value
) {
4661 // XXX don't know the proper values here...
4662 return parser_error (p
, child
->element_name
, NULL
, 2007,
4663 "Error adding child to ResourceDictionary");
4666 bool added
= dict
->AddWithError (key
, child_as_value
, &err
);
4668 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4677 if (types
->IsSubclassOf (parent
->info
->GetKind (), Type::DEPENDENCY_OBJECT_COLLECTION
)) {
4678 Collection
*col
= (Collection
*) parent
->GetAsDependencyObject ();
4680 Value
child_val ((DependencyObject
*)child
->GetAsDependencyObject ());
4682 if (-1 == col
->AddWithError (&child_val
, &err
))
4683 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4686 else if (types
->IsSubclassOf (parent
->info
->GetKind (), Type::RESOURCE_DICTIONARY
)) {
4687 ResourceDictionary
*dict
= (ResourceDictionary
*) parent
->GetAsDependencyObject ();
4690 const char *key
= get_key_from_child (child
);
4693 // XXX don't know the proper values here...
4694 return parser_error (p
, child
->element_name
, NULL
, 2007,
4695 "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
4698 Value
*child_as_value
= child
->GetAsValue ();
4699 bool added
= dict
->AddWithError (key
, child_as_value
, &err
);
4701 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4705 if (parent
->element_type
!= XamlElementInstance::PROPERTY
) {
4706 parent
->TrySetContentProperty (p
, child
);
4709 // Do nothing if we aren't adding to a collection, or a content property collection
4714 /// set property funcs
4717 // these are just a bunch of special cases
4719 dependency_object_missed_property (XamlElementInstance
*item
, XamlElementInstance
*prop
, XamlElementInstance
*value
, char **prop_name
)
4725 set_managed_attached_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*prop
, XamlElementInstance
*value
)
4730 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), item
->info
->xmlns
, item
->GetAsValue (), item
, item
->GetParentPointer (), prop
->info
->xmlns
, prop
->element_name
, value
->GetAsValue (), value
);
4734 dependency_object_set_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
, bool raise_errors
)
4736 char **prop_name
= g_strsplit (property
->element_name
, ".", -1);
4737 DependencyObject
*dep
= item
->GetAsDependencyObject ();
4738 DependencyProperty
*prop
= NULL
;
4740 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4742 if (types
->Find (item
->info
->GetKind ())->IsValueType ()) {
4743 if (raise_errors
) parser_error (p
, item
->element_name
, NULL
, -1, "Value types (%s) do not have properties.", property
->element_name
);
4744 g_strfreev (prop_name
);
4748 if (types
->Find (property
->info
->GetPropertyOwnerKind ())->IsCustomType ()) {
4749 g_strfreev (prop_name
);
4750 return set_managed_attached_property (p
, item
, property
, value
);
4754 // FIXME is this really where this check should live
4756 parser_error (p
, item
->element_name
, NULL
, 2030,
4757 "Property element %s cannot be used inside another property element.",
4758 property
->element_name
);
4760 g_strfreev (prop_name
);
4764 prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, item
->info
->GetKind ()), prop_name
[1]);
4767 if (prop
->IsReadOnly ()) {
4769 parser_error (p
, item
->element_name
, NULL
, 2014,
4770 "The attribute %s is read only and cannot be set.", prop
->GetName ());
4772 } else if (types
->IsSubclassOf (value
->info
->GetKind (), prop
->GetPropertyType())) {
4773 // an empty collection can be NULL and valid
4774 if (item
->IsPropertySet (prop
->GetName())) {
4776 parser_error (p
, item
->element_name
, NULL
, 2033,
4777 "Cannot specify the value multiple times for property: %s.",
4778 property
->element_name
);
4783 // HACK - since the Setter is added to the collection *before* its properties are set
4784 // we find ourselves with a sealed Setter - which should not be possible at the parse time
4785 SetterBase
*sb
= NULL
;
4786 if (types
->IsSubclassOf (dep
->GetObjectType (), Type::SETTERBASE
)) {
4787 sb
= (SetterBase
*) dep
;
4788 sb
->SetIsSealed (false);
4791 if (!is_managed_kind (value
->info
->GetKind ()) && !value
->info
->RequiresManagedSet()) {
4792 if (!dep
->SetValueWithError (prop
, value
->GetAsValue (), &err
)) {
4794 parser_error (p
, item
->element_name
, NULL
, err
.code
, err
.message
);
4800 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, item
->GetAsValue (), item
, item
->GetParentPointer (), NULL
, prop_name
[1], value
->GetAsValue (), NULL
)) {
4802 parser_error (p
, item
->element_name
, NULL
, err
.code
, err
.message
);
4809 // re-seal the Setter (end-HACK)
4811 sb
->SetIsSealed (true);
4813 item
->MarkPropertyAsSet (prop
->GetName());
4816 } else if (types
->IsSubclassOf (prop
->GetPropertyType (), Type::COLLECTION
) || types
->IsSubclassOf (prop
->GetPropertyType (), Type::RESOURCE_DICTIONARY
)) {
4817 // The items were added in add_child
4821 parser_error (p
, item
->element_name
, NULL
, 2010, "does not support %s as content.", value
->element_name
);
4825 dependency_object_missed_property (item
, property
, value
, prop_name
);
4830 g_strfreev (prop_name
);
4835 xaml_set_property_from_str (DependencyObject
*obj
, DependencyProperty
*prop
, const char *value
, MoonError
*error
)
4840 if (!value_from_str (prop
->GetPropertyType(), prop
->GetName(), value
, &v
))
4843 // it's possible for (a valid) value to be NULL (and we must keep the default value)
4845 rv
= obj
->SetValueWithError (prop
, v
, error
);
4853 xaml_is_valid_event_name (Deployment
*deployment
, Type::Kind kind
, const char *name
, bool allow_desktop_events
)
4855 Type
*type
= Type::Find (deployment
, kind
);
4859 int event_id
= type
->LookupEvent (name
);
4863 if (!allow_desktop_events
|| (moonlight_flags
& RUNTIME_INIT_DESKTOP_EXTENSIONS
) == 0) {
4864 // if we're not allowing desktop-only events, or if the user hasn't allowed them,
4865 // return false if the name corresponds to one of them.
4866 if (!strcmp (name
, "MouseRightButtonDown") ||
4867 !strcmp (name
, "MouseRightButtonUp") ||
4868 !strcmp (name
, "MouseWheel"))
4876 value_type_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
)
4878 // the only attributes value on value types seem to be x:Key
4879 // and x:Name, but reuse the generic namespace attribute stuff
4882 for (int i
= 0; attr
[i
]; i
+= 2) {
4884 if (attr
[i
+ 1] == NULL
|| attr
[i
+ 1][0] == '\0')
4887 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4889 if (attr_name
[1]) {
4891 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
4894 return parser_error (p
, item
->element_name
, attr
[i
], 7055, "undeclared prefix");
4896 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
4898 g_strfreev (attr_name
);
4900 // Setting managed attributes can cause errors galore
4907 g_strfreev (attr_name
);
4912 dependency_object_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
)
4914 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4915 GList
*delay_att
= NULL
;
4917 for (int i
= 0; attr
[i
]; i
+= 2) {
4922 // Setting attributes like x:Class can change item->item, so we
4923 // need to make sure we have an up to date pointer
4924 DependencyObject
*dep
= item
->GetAsDependencyObject ();
4925 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4927 if (attr_name
[1]) {
4928 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
4930 if (ns
!= x_namespace
) {
4931 delay_att
= g_list_append (delay_att
, GINT_TO_POINTER (i
));
4932 g_strfreev (attr_name
);
4937 g_strfreev (attr_name
);
4938 return parser_error (p
, item
->element_name
, attr
[i
], 5055, "undeclared prefix");
4941 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
4943 g_strfreev (attr_name
);
4945 // Setting managed attributes can cause errors galore
4952 g_strfreev (attr_name
);
4954 const char *pname
= attr
[i
];
4955 char *atchname
= NULL
;
4956 for (int a
= 0; attr
[i
][a
]; a
++) {
4957 if (attr
[i
][a
] != '.')
4959 atchname
= g_strndup (attr
[i
], a
);
4960 pname
= attr
[i
] + a
+ 1;
4964 DependencyProperty
*prop
= NULL
;
4966 Type
*attached_type
= types
->Find (atchname
);
4968 prop
= DependencyProperty::GetDependencyProperty (attached_type
, pname
);
4970 prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, item
->info
->GetKind ()), pname
);
4974 if (prop
->GetId () == DependencyObject::NameProperty
) {
4976 if (item
->GetName ()) {
4977 parser_error (p
, item
->element_name
, NULL
, 2016, "Cannot specify both Name and x:Name attributes.");
4981 // XXX toshok - I don't like doing this here... but it fixes airlines.
4982 item
->SetKey (p
, attr
[i
+1]);
4984 NameScope
*scope
= p
->namescope
;
4985 if (!item
->GetAsDependencyObject ()->SetName (attr
[i
+1], scope
)) {
4986 parser_error (p
, item
->element_name
, NULL
, 2028,
4987 "The name already exists in the tree: %s.", attr
[i
+1]);
4989 g_list_free (delay_att
);
4995 if (prop
->IsReadOnly ()) {
4996 parser_error (p
, item
->element_name
, NULL
, 2014,
4997 "The attribute %s is read only and cannot be set.", prop
->GetName ());
4999 g_list_free (delay_att
);
5003 if (item
->IsPropertySet (prop
->GetName())) {
5004 parser_error (p
, item
->element_name
, attr
[i
], 2033,
5005 "Cannot specify the value multiple times for property: %s.", prop
->GetName ());
5007 g_list_free (delay_att
);
5013 char *attr_value
= g_strdup (attr
[i
+1]);
5015 bool need_managed
= false;
5016 if (attr
[i
+1][0] == '{') {
5017 if (attr
[i
+1][1] == '}') {
5018 // {} is an escape sequence so you can have strings like {StaticResource}
5019 char *nv
= attr_value
;
5020 attr_value
= g_strdup (attr_value
+ 2);
5023 else if (attr
[i
+1][strlen(attr
[i
+1]) - 1] == '}') {
5024 need_managed
= true;
5028 if (!need_managed
) {
5029 if (!value_from_str_with_parser (p
, prop
->GetPropertyType(), prop
->GetName(), attr_value
, &v
, &v_set
)) {
5031 g_free (attr_value
);
5036 Type::Kind propKind
= prop
->GetPropertyType ();
5038 if (need_managed
|| is_managed_kind (propKind
) || types
->Find (prop
->GetOwnerType ())->IsCustomType () || (v
&& is_managed_kind (v
->GetKind ()))) {
5039 bool str_value
= false;
5041 v
= new Value (attr
[i
+ 1]); // Note that we passed the non escaped value, not attr_value
5046 // printf ("setting managed property: %s::%s to %s=%s\n", dep->GetType ()->GetName (), prop->GetName (), attr [i], attr [i + 1]);
5047 if (p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, item
->GetAsValue (), item
, item
->GetParentPointer (), NULL
, g_strdup (attr
[i
]), v
, NULL
)) {
5049 g_free (attr_value
);
5056 if (!value_from_str_with_parser (p
, prop
->GetPropertyType(), prop
->GetName(), attr_value
, &v
, &v_set
)) {
5058 g_free (attr_value
);
5065 if (!v_set
&& !value_is_explicit_null (attr
[i
+ 1])) { // Check the non escaped value
5066 parser_error (p
, item
->element_name
, attr
[i
], 2024, "Invalid attribute value %s for property %s.", attr
[i
+1], attr
[i
]);
5068 g_free (attr_value
);
5070 g_list_free (delay_att
);
5075 // printf ("settng: %s %s value type: %s prop type: %s\n", attr [i], attr [i+1], v ? Type::Find (v->GetKind ())->GetName () : "--null--", Type::Find (prop->GetPropertyType ())->GetName ());
5076 if (!dep
->SetValueWithError (prop
, v
, &err
))
5077 parser_error (p
, item
->element_name
, attr
[i
], err
.code
, err
.message
);
5079 item
->MarkPropertyAsSet (prop
->GetName());
5082 g_free (attr_value
);
5084 delay_att
= g_list_append (delay_att
, GINT_TO_POINTER (i
));
5091 GList
*walk
= g_list_first (delay_att
);
5093 int i
= GPOINTER_TO_INT (walk
->data
);
5098 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
5100 if (attr_name
[1]) {
5101 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
5103 if (ns
== x_namespace
) {
5104 // Skip these, they are handled earlier
5105 g_strfreev (attr_name
);
5110 g_strfreev (attr_name
);
5111 parser_error (p
, item
->element_name
, attr
[i
], 5055, "undeclared prefix");
5115 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
5117 g_strfreev (attr_name
);
5119 // Setting managed attributes can cause errors galore
5123 if (!item
->SetUnknownAttribute (p
, attr
[i
], attr
[i
+ 1])) {
5124 parser_error (p
, item
->element_name
, attr
[i
], 2012,
5125 "Unknown attribute %s on element %s.",
5126 attr
[i
], item
->element_name
);
5134 g_list_free (delay_att
);
5139 lookup_named_item (XamlElementInstance
*top
, const char *name
)
5141 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
5142 XamlElementInstance
*inst
= top
;
5145 if (inst
->element_type
== XamlElementInstance::ELEMENT
) {
5146 ResourceDictionary
*rd
= NULL
;
5147 Type::Kind kind
= inst
->info
->GetKind ();
5149 if (types
->IsSubclassOf (kind
, Type::FRAMEWORKELEMENT
)) {
5150 rd
= inst
->GetAsDependencyObject ()->GetValue (UIElement::ResourcesProperty
)->AsResourceDictionary ();
5151 } else if (types
->IsSubclassOf (kind
, Type::RESOURCE_DICTIONARY
)) {
5152 rd
= (ResourceDictionary
*) inst
->GetAsDependencyObject ();
5157 Value
*res
= lookup_resource_dictionary (rd
, name
, &exists
);
5163 inst
= inst
->parent
;
5170 lookup_resource_dictionary (ResourceDictionary
*rd
, const char *name
, bool *exists
)
5173 Value
*resource_value
= rd
->Get (name
, exists
);
5174 return *exists
? new Value (*resource_value
) : NULL
;
5178 xaml_lookup_named_item (void *parser
, void *instance
, const char* name
)
5180 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
5181 XamlElementInstance
*inst
= (XamlElementInstance
*) instance
;
5185 res
= lookup_named_item (inst
, name
);
5187 XamlContext
*context
= p
->loader
->GetContext ();
5188 if (!res
&& context
)
5189 context
->internal
->LookupNamedItem (name
, &res
);
5192 Application
*app
= Application::GetCurrent ();
5194 ResourceDictionary
*rd
= app
->GetResources ();
5196 bool exists
= false;
5197 res
= lookup_resource_dictionary (rd
, name
, &exists
);
5199 if (res
&& Type::IsSubclassOf (p
->deployment
, res
->GetKind (), Type::DEPENDENCY_OBJECT
)) {
5200 DependencyObject
*dob
= res
->AsDependencyObject ();
5201 NameScope::SetNameScope (dob
, dob
->FindNameScope ());
5210 xaml_get_template_parent (void *parser
, void *element_instance
)
5212 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
5213 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5215 return p
->GetTemplateParent (item
);
5219 xaml_get_element_key (void *parser
, void *element_instance
)
5221 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5222 const char *key
= item
->GetKey ();
5224 key
= item
->GetName ();
5225 return g_strdup (key
);
5229 xaml_get_element_name (void *parser
, void *element_instance
)
5231 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5232 return g_strdup (item
->element_name
);
5236 xaml_is_property_set (void *parser
, void *element_instance
, char *name
)
5238 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5239 return item
->IsPropertySet (name
);
5243 xaml_mark_property_as_set (void *parser
, void *element_instance
, char *name
)
5245 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5246 item
->MarkPropertyAsSet (g_strdup (name
));
5250 xaml_delay_set_property (void *parser
, void *element_instance
, const char *xmlns
, const char *name
, const Value
*value
)
5252 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5253 item
->DelaySetProperty (xmlns
, name
, value
);
5259 default_namespace
= new DefaultNamespace ();
5260 x_namespace
= new XNamespace ();
5261 xml_namespace
= new XmlNamespace ();