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"
56 #include "bitmapcache.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
{
138 GSList
*w
= prefixes
;
141 char *p
= (char *) w
->data
;
147 g_slist_free (prefixes
);
152 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
) = 0;
153 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
) = 0;
156 virtual const char* GetUri () = 0;
158 void AddPrefix (const char *prefix
)
160 prefixes
= g_slist_append (prefixes
, g_strdup (prefix
));
163 bool HasPrefix (const char *prefix
)
165 return g_slist_find_custom (prefixes
, prefix
, (GCompareFunc
) strcmp
) != NULL
;
168 GSList
* GetPrefixes ()
175 add_namespace_data (gpointer key
, gpointer value
, gpointer user_data
)
177 XamlNamespace
*ns
= (XamlNamespace
*) value
;
178 GHashTable
*table
= (GHashTable
*) user_data
;
180 if ((void *)ns
!= (void *)default_namespace
) {
181 GSList
*p
= ns
->GetPrefixes ();
184 g_hash_table_insert (table
, g_strdup ((char *)p
->data
), g_strdup (ns
->GetUri ()));
192 add_namespace_to_ignorable (gpointer key
, gpointer value
, gpointer user_data
)
194 char *prefix
= (char *) key
;
195 char *uri
= (char *) value
;
196 GString
*str
= (GString
*) user_data
;
198 g_string_append_printf (str
, "xmlns:%s=\"%s\" ", prefix
, uri
);
201 class XamlContextInternal
{
205 FrameworkTemplate
*template_parent
;
206 GHashTable
*imported_namespaces
;
207 XamlLoaderCallbacks callbacks
;
209 XamlContextInternal
*parent_context
;
211 DependencyObject
*source
;
213 XamlContextInternal (XamlLoaderCallbacks callbacks
, Value
*top_element
, FrameworkTemplate
*template_parent
, GHashTable
*namespaces
, GSList
*resources
, XamlContextInternal
*parent_context
)
215 this->callbacks
= callbacks
;
216 this->top_element
= new Value (*top_element
);
217 this->template_parent
= template_parent
;
218 this->resources
= resources
;
219 this->parent_context
= parent_context
;
221 if (this->callbacks
.create_gchandle
)
222 this->callbacks
.create_gchandle ();
223 imported_namespaces
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
224 g_hash_table_foreach (namespaces
, add_namespace_data
, imported_namespaces
);
228 ~XamlContextInternal ()
230 if (imported_namespaces
)
231 g_hash_table_destroy (imported_namespaces
);
233 g_slist_free (resources
);
237 char *CreateIgnorableTagOpen ()
239 GString
*str
= g_string_new ("<" INTERNAL_IGNORABLE_ELEMENT
" ");
240 g_hash_table_foreach (imported_namespaces
, add_namespace_to_ignorable
, str
);
242 str
= g_string_append (str
, ">");
244 char *res
= str
->str
;
245 g_string_free (str
, false);
250 char *CreateIgnorableTagClose ()
252 return g_strdup ("</" INTERNAL_IGNORABLE_ELEMENT
">");
255 bool LookupNamedItem (const char* name
, Value
**v
)
261 GSList
*walk
= resources
;
263 DependencyObject
*dob
= (DependencyObject
*)walk
->data
;
264 if (dob
->Is (Type::RESOURCE_DICTIONARY
))
265 *v
= lookup_resource_dictionary ((ResourceDictionary
*) walk
->data
, name
, &exists
);
266 else /* dob->Is (Type::FRAMEWORKELEMENT) */ {
267 ResourceDictionary
*rd
= dob
->GetValue (UIElement::ResourcesProperty
)->AsResourceDictionary();
268 *v
= lookup_resource_dictionary (rd
, name
, &exists
);
278 else if (!parent_context
)
281 return parent_context
->LookupNamedItem (name
, v
);
284 void SetTemplateBindingSource (DependencyObject
*source
)
286 this->source
= source
;
289 DependencyObject
* GetTemplateBindingSource ()
296 XamlContext::XamlContext (XamlContextInternal
*internal
)
298 this->internal
= internal
;
301 XamlContext::~XamlContext ()
307 XamlContext::SetTemplateBindingSource (DependencyObject
*source
)
309 internal
->SetTemplateBindingSource (source
);
313 XamlContext::GetTemplateBindingSource ()
315 return internal
->GetTemplateBindingSource ();
318 class XamlElementInfo
{
321 Type::Kind property_owner_kind
;
325 XamlElementInfo
*parent
;
329 XamlElementInfo (const char *xmlns
, const char *name
, Type::Kind kind
)
335 this->cdata_verbatim
= false;
337 this->property_owner_kind
= Type::INVALID
;
344 virtual Type::Kind
GetKind () { return kind
; }
346 virtual void SetPropertyOwnerKind (Type::Kind value
) { property_owner_kind
= value
; }
347 virtual Type::Kind
GetPropertyOwnerKind () { return property_owner_kind
; }
349 virtual const char *GetContentProperty (XamlParserInfo
*p
)
351 Type
*t
= Type::Find (Deployment::GetCurrent (), kind
);
353 return t
->GetContentPropertyName ();
357 void SetIsCDataVerbatim (bool flag
)
359 cdata_verbatim
= flag
;
362 bool IsCDataVerbatim ()
364 return cdata_verbatim
;
367 virtual bool RequiresManagedSet () { return false; }
369 virtual XamlElementInstance
*CreateElementInstance (XamlParserInfo
*p
) = 0;
370 virtual XamlElementInstance
*CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
) = 0;
371 virtual XamlElementInstance
*CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
) = 0;
375 struct DelayedProperty
{
380 DelayedProperty (const char *xmlns
, const char *name
, const Value
*value
)
382 this->xmlns
= g_strdup (xmlns
);
383 this->name
= g_strdup (name
);
384 this->value
= new Value (*value
);
396 free_property_list (GSList
*list
)
401 DelayedProperty
*prop
= (DelayedProperty
*) walk
->data
;
410 class XamlElementInstance
: public List::Node
{
413 DependencyObject
*item
;
416 GSList
*delayed_properties
;
419 const char *element_name
;
420 XamlElementInfo
*info
;
422 XamlElementInstance
*parent
;
432 bool requires_managed
;
436 GHashTable
*set_properties
;
438 XamlElementInstance (XamlElementInfo
*info
, const char* element_name
, ElementType type
, bool requires_managed
= false)
440 this->element_name
= element_name
;
441 this->set_properties
= NULL
;
442 this->element_type
= type
;
449 this->cleanup_value
= true;
450 this->requires_managed
= requires_managed
;
451 this->delayed_properties
= NULL
;
453 children
= new List ();
456 virtual ~XamlElementInstance ()
458 children
->Clear (true);
469 g_hash_table_destroy (set_properties
);
471 if (element_name
&& element_type
== PROPERTY
)
472 g_free ((void*) element_name
);
474 free_property_list (delayed_properties
);
477 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) = 0;
478 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
) = 0;
479 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) = 0;
480 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
) = 0;
482 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
);
483 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
);
486 char *GetKey () { return x_key
; }
487 char *GetName () { return x_name
; }
489 void SetName (XamlParserInfo
*p
, const char *name
)
491 this->x_name
= g_strdup (name
);
494 void SetKey (XamlParserInfo
*p
, const char *key
)
496 this->x_key
= g_strdup (key
);
499 virtual bool IsDependencyObject ()
504 virtual bool SetUnknownAttribute (XamlParserInfo
*p
, const char* name
, const char* value
);
506 void SetValue (Value
*v
)
508 if (value
&& cleanup_value
)
513 virtual Value
*GetAsValue ()
516 value
= new Value (item
);
521 virtual DependencyObject
*GetAsDependencyObject ()
526 virtual void SetDependencyObject (DependencyObject
*value
)
531 virtual void* GetManagedPointer ()
536 virtual Value
* GetParentPointer ()
538 XamlElementInstance
*walk
= parent
;
539 while (walk
&& walk
->element_type
!= XamlElementInstance::ELEMENT
)
545 return walk
->GetAsValue ();
548 virtual bool IsTemplate ()
553 virtual XamlElementInfo
* FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
);
555 void SetDelayedProperties (XamlParserInfo
*p
);
557 void DelaySetProperty (const char *xmlns
, const char *name
, const Value
*value
)
559 DelayedProperty
*prop
= new DelayedProperty (xmlns
, name
, value
);
561 delayed_properties
= g_slist_append (delayed_properties
, prop
);
564 bool IsPropertySet (const char *name
)
569 return g_hash_table_lookup (set_properties
, name
) != NULL
;
572 void MarkPropertyAsSet (const char *name
)
575 set_properties
= g_hash_table_new (g_str_hash
, g_str_equal
);
577 g_hash_table_insert (set_properties
, (void *) name
, GINT_TO_POINTER (TRUE
));
582 unref_xaml_element (gpointer data
, gpointer user_data
)
584 DependencyObject
* dob
= (DependencyObject
*) data
;
585 //printf ("unref_xaml_element: %i\n", dob->id);
590 class XamlParserInfo
{
594 const char *file_name
;
596 NameScope
*namescope
;
597 XamlElementInstance
*top_element
;
598 XamlNamespace
*current_namespace
;
599 XamlElementInstance
*current_element
;
600 const char *next_element
;
601 Deployment
*deployment
;
603 GHashTable
*namespace_map
;
607 bool implicit_default_namespace
;
609 ParserErrorEventArgs
*error_args
;
615 // If set, this is used to hydrate an existing object, not to create a new toplevel one
617 Value
*hydrate_expecting
;
620 char* buffer_until_element
;
622 BufferMode buffer_mode
;
624 bool validate_templates
;
627 GList
*created_elements
;
628 GList
*created_namespaces
;
629 const char* xml_buffer
;
630 int multi_buffer_offset
;
631 int xml_buffer_start_index
;
634 XamlParserInfo (XML_Parser parser
, const char *file_name
)
636 this->deployment
= Deployment::GetCurrent ();
637 this->parser
= parser
;
638 this->file_name
= file_name
;
639 this->namescope
= new NameScope ();
642 current_namespace
= NULL
;
643 current_element
= NULL
;
644 cdata_content
= false;
646 implicit_default_namespace
= false;
649 created_elements
= NULL
;
650 created_namespaces
= NULL
;
651 hydrate_expecting
= NULL
;
654 buffer_until_element
= NULL
;
658 multi_buffer_offset
= 0;
659 validate_templates
= false;
661 namespace_map
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
664 void AddCreatedElement (DependencyObject
* element
)
666 // if we have a loader, set the surface and base resource location
668 element
->SetIsAttached (true); /* Some glyphs (DRT 0/Test5, 58) do not show up without this */
669 element
->SetResourceBase (loader
->GetResourceBase());
672 // When instantiating a template, some elements are created which are not explicitly
673 // mentioned in the xaml. Therefore we need to keep walking up the tree until we find
674 // the last element which we set a value for Control::IsTemplateItem and propagate
676 XamlElementInstance
*instance
= current_element
;
678 if (!instance
->IsDependencyObject () || !instance
->GetAsDependencyObject ()) {
679 instance
= instance
->parent
;
682 if (!instance
->GetAsDependencyObject ()->ReadLocalValue (Control::IsTemplateItemProperty
)) {
683 instance
= instance
->parent
;
686 Control::SetIsTemplateItem (element
, Control::GetIsTemplateItem (instance
->GetAsDependencyObject ()));
687 if (DependencyObject
*e
= instance
->GetAsDependencyObject ()->GetTemplateOwner ())
688 element
->SetTemplateOwner (e
);
692 if (instance
== NULL
) {
693 Control::SetIsTemplateItem (element
, loader
->GetExpandingTemplate ());
694 element
->SetTemplateOwner (loader
->GetTemplateOwner ());
697 if (Control::GetIsTemplateItem (element
))
698 NameScope::SetNameScope (element
, namescope
);
699 created_elements
= g_list_prepend (created_elements
, element
);
702 void AddCreatedNamespace (XamlNamespace
* ns
)
704 created_namespaces
= g_list_prepend (created_namespaces
, ns
);
707 void QueueBeginBuffering (char* buffer_until
, BufferMode mode
)
709 buffer_until_element
= buffer_until
;
713 xml_buffer_start_index
= -1;
716 void BeginBuffering ()
718 xml_buffer_start_index
= XML_GetCurrentByteIndex (parser
) - multi_buffer_offset
;
719 buffer
= g_string_new (NULL
);
722 bool ShouldBeginBuffering ()
724 return InBufferingMode () && xml_buffer_start_index
== -1;
727 bool InBufferingMode ()
729 return buffer_until_element
!= NULL
;
732 void AppendCurrentXml ()
736 int pos
= XML_GetCurrentByteIndex (parser
) - multi_buffer_offset
;
737 g_string_append_len (buffer
, xml_buffer
+ xml_buffer_start_index
, pos
- xml_buffer_start_index
);
745 buffer_until_element
= NULL
;
748 return g_strdup ("");
750 char* res
= buffer
->str
;
751 g_string_free (buffer
, FALSE
);
756 void SetXmlBuffer (const char* xml_buffer
)
758 if (InBufferingMode ())
761 if (this->xml_buffer
)
762 multi_buffer_offset
+= strlen (this->xml_buffer
);
764 this->xml_buffer
= xml_buffer
;
765 xml_buffer_start_index
= 0;
768 void ValidateTemplate (const char* buffer
, XamlContext
* context
, FrameworkTemplate
*binding_source
)
770 XamlLoader
*loader
= new XamlLoader (NULL
, buffer
, NULL
, context
);
773 context
->SetTemplateBindingSource (binding_source
);
775 loader
->SetImportDefaultXmlns (true);
778 Value
*result
= loader
->CreateFromStringWithError (buffer
, true, &dummy
, XamlLoader::IMPORT_DEFAULT_XMLNS
| XamlLoader::VALIDATE_TEMPLATES
, &error
);
783 if (error
.number
!= MoonError::NO_ERROR
) {
784 int line_number
= error
.line_number
+ XML_GetCurrentLineNumber (parser
);
785 error_args
= new ParserErrorEventArgs (error
.message
, file_name
, line_number
, error
.char_position
, error
.code
, NULL
, NULL
);
789 FrameworkTemplate
*GetTemplateParent (XamlElementInstance
*item
)
791 XamlElementInstance
*parent
= item
->parent
;
793 while (parent
&& !parent
->IsTemplate ())
794 parent
= parent
->parent
;
797 return (FrameworkTemplate
*) parent
->GetManagedPointer ();
802 XamlContext
*context
= loader
->GetContext ();
806 return context
->internal
->template_parent
;
809 Value
*GetTopElementPtr ()
811 XamlContext
*context
= loader
->GetContext ();
813 return context
->internal
->top_element
;
816 return top_element
->GetAsValue ();
823 created_elements
= g_list_reverse (created_elements
);
824 g_list_foreach (created_elements
, unref_xaml_element
, NULL
);
825 g_list_free (created_elements
);
827 g_list_foreach (created_namespaces
, destroy_created_namespace
, NULL
);
828 g_list_free (created_namespaces
);
830 g_hash_table_destroy (namespace_map
);
833 g_string_free (cdata
, TRUE
);
843 class XamlElementInfoNative
: public XamlElementInfo
{
847 XamlElementInfoNative (Type
*t
) : XamlElementInfo (NULL
, t
->GetName (), t
->GetKind ())
857 const char* GetName ()
859 return type
->GetName ();
862 const char* GetContentProperty (XamlParserInfo
*p
);
864 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
865 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
866 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
870 class XamlElementInstanceNative
: public XamlElementInstance
{
871 XamlElementInfoNative
*element_info
;
872 XamlParserInfo
*parser_info
;
875 XamlElementInstanceNative (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
= true);
877 virtual DependencyObject
*CreateItem ();
879 virtual XamlElementInfo
* FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
);
881 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
);
882 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
);
883 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
);
884 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
888 class XamlElementInstanceValueType
: public XamlElementInstance
{
889 XamlElementInfoNative
*element_info
;
890 XamlParserInfo
*parser_info
;
893 XamlElementInstanceValueType (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
);
895 virtual bool IsDependencyObject ()
900 virtual Value
*GetAsValue ()
903 // we are an empty element (e.g. <sys:String></sys:String>). do type specific magic here.
904 CreateValueItemFromString ("");
910 bool CreateValueItemFromString (const char* str
);
912 // A Value type doesn't really support anything. It's just here so people can do <SolidColorBrush.Color><Color>#FF00FF</Color></SolidColorBrush.Color>
913 virtual DependencyObject
*CreateItem () { return NULL
; }
914 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) { return false; }
915 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
) { return false; }
916 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) { }
917 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
919 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
) { return false; }
920 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
) { return CreateValueItemFromString (value
); }
923 class XamlElementInfoEnum
: public XamlElementInfo
{
925 XamlElementInfoEnum (const char *name
) : XamlElementInfo (NULL
, name
, Type::INT32
)
929 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
930 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
931 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
) { return NULL
; }
934 class XamlElementInstanceEnum
: public XamlElementInstance
{
937 XamlElementInstanceEnum (XamlElementInfoEnum
*element_info
, const char *name
, ElementType type
);
939 virtual bool IsDependencyObject ()
944 virtual Value
*GetAsValue ()
949 bool CreateEnumFromString (const char* str
);
951 // An enum type doesn't really support anything. It's just here so people can do <Visibility>Visible</Visibility>
952 virtual DependencyObject
*CreateItem () { return NULL
; }
953 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
) { return false; }
954 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
) { return false; }
955 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
) { }
956 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
958 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
) { return false; }
959 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
) { return CreateEnumFromString (value
); }
962 class XamlElementInstanceTemplate
: public XamlElementInstanceNative
{
964 XamlElementInstanceTemplate (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
= true)
965 : XamlElementInstanceNative (element_info
, parser_info
, name
, type
, create_item
)
969 virtual bool IsTemplate ()
976 class DefaultNamespace
: public XamlNamespace
{
983 virtual ~DefaultNamespace () { }
985 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
987 Type
* t
= Type::Find (p
->deployment
, el
, false);
988 if (t
&& !kind_requires_managed_load (t
->GetKind ()))
989 return new XamlElementInfoNative (t
);
991 if (enums_is_enum_name (el
))
992 return new XamlElementInfoEnum (g_strdup (el
));
994 XamlElementInfo
* managed_element
= create_element_info_from_imported_managed_type (p
, el
, attr
, create
);
996 return managed_element
;
1002 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1007 virtual const char* GetUri () { return "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; }
1010 class XmlNamespace
: public XamlNamespace
{
1017 virtual ~XmlNamespace () { }
1019 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1024 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1026 if (!strcmp ("lang", attr
)) {
1027 if (item
->IsDependencyObject ()) {
1028 DependencyObject
*dob
= item
->GetAsDependencyObject ();
1029 if (dob
->Is(Type::FRAMEWORKELEMENT
)) {
1030 ((FrameworkElement
*)dob
)->SetLanguage (value
);
1039 virtual const char* GetUri () { return "http://www.w3.org/XML/1998/namespace"; }
1042 class XNamespace
: public XamlNamespace
{
1049 virtual ~XNamespace () { }
1051 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1056 virtual char *FindTypeName (const char **attr
, char **xmlns
)
1063 for (int i
= 0; attr
[i
]; i
+= 2) {
1064 const char *ns
= strchr (attr
[i
], '|');
1068 if (strncmp (GetUri (), attr
[i
], ns
- attr
[i
]) || strcmp ("Class", ns
+ 1))
1071 ns
= strchr (attr
[i
+ 1], ';');
1073 *xmlns
= g_strdup ("");
1074 res
= g_strdup (attr
[i
+ 1]);
1076 *xmlns
= g_strdup (ns
+ 1);
1077 res
= g_strndup (attr
[i
+ 1], attr
[i
+ 1] - ns
);
1084 bool IsParentResourceDictionary (XamlElementInstance
*parent
)
1089 return Type::IsSubclassOf (Deployment::GetCurrent (), parent
->info
->GetKind (), Type::RESOURCE_DICTIONARY
);
1092 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1094 if (!strcmp ("Name", attr
)) {
1096 // Causes breakage in airlines
1097 // Maybe x:Name overwrites but Name does not?
1099 // if (p->namescope->FindName (value)) {
1100 // parser_error (p, p->current_element->element_name, "x:Name", 2028, "The name already exists in the tree: %s.", value);
1105 if (IsParentResourceDictionary (p
->current_element
)) {
1106 if (item
->GetKey ()) {
1107 // XXX don't know the proper values here...
1108 parser_error (p
, item
->element_name
, NULL
, 2028,
1109 "The name already exists in the tree: %s.", value
);
1114 if (item
->GetName ()) {
1115 parser_error (p
, item
->element_name
, NULL
, 2016, "Cannot specify both Name and x:Name attributes.");
1119 item
->SetName (p
, value
);
1121 if (item
->IsDependencyObject ()) {
1122 NameScope
*scope
= p
->namescope
;
1123 if (!item
->GetAsDependencyObject ()->SetName (value
, scope
)) {
1124 if (IsParentResourceDictionary (p
->current_element
)) {
1125 // FIXME: inside of a resource dictionary this has an extremly
1126 // strange behavior. this isn't exactly right, since not only
1127 // does the exception get swallowed, but the name seems to also
1131 parser_error (p
, item
->element_name
, NULL
, 2028,
1132 "The name already exists in the tree: %s.", value
);
1142 if (!strcmp ("Key", attr
)) {
1143 if (item
->GetKey () && IsParentResourceDictionary (p
->current_element
) && !Type::IsSubclassOf (p
->deployment
, item
->info
->GetKind (), Type::STORYBOARD
)) {
1144 // XXX don't know the proper values here...
1145 parser_error (p
, item
->element_name
, NULL
, 2028,
1146 "The name already exists in the tree: %s.", value
);
1149 item
->SetKey (p
, value
);
1153 if (!strcmp ("Class", attr
)) {
1154 if (!is_legal_top_level_kind (item
->info
->GetKind ())) {
1155 // XXX don't know the proper values here...
1156 parser_error (p
, item
->element_name
, attr
, -1,
1157 "Cannot specify x:Class type '%s' on value type element (%s).", value
, item
->element_name
);
1161 if (p
->top_element
!= item
) {
1162 // HAH: what a useless error message
1163 parser_error (p
, item
->element_name
, attr
, 2012,
1164 "Unknown attribute %s on element %s.", attr
, item
->element_name
);
1168 // While hydrating, we do not need to create the toplevel class, its created already
1172 parser_error (p
, item
->element_name
, attr
, 4005,
1173 "Cannot specify x:Class in xaml files outside of a xap.");
1181 virtual const char* GetUri () { return X_NAMESPACE_URI
; }
1185 class PrimitiveNamespace
: public XamlNamespace
{
1188 PrimitiveNamespace (char *prefix
)
1193 virtual ~PrimitiveNamespace ()
1197 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1199 if (!strcmp ("String", el
)) {
1200 Type
* t
= Type::Find (p
->deployment
, Type::STRING
);
1201 // it's not as easy in this case, because primitive clr strings require that the
1202 // character data be read in verbatim, including all whitespace.
1203 XamlElementInfo
*info
= new XamlElementInfoNative (t
);
1204 info
->SetIsCDataVerbatim (true);
1206 } else if (!strcmp ("Int32", el
)) {
1207 Type
* t
= Type::Find (p
->deployment
, Type::INT32
);
1208 return new XamlElementInfoNative (t
);
1209 } else if (!strcmp ("Double", el
)) {
1210 Type
* t
= Type::Find (p
->deployment
, Type::DOUBLE
);
1211 return new XamlElementInfoNative (t
);
1212 } else if (!strcmp ("Boolean", el
)) {
1213 Type
* t
= Type::Find (p
->deployment
, Type::BOOL
);
1214 return new XamlElementInfoNative (t
);
1215 } else if (!strcmp ("TimeSpan", el
)) {
1216 Type
* t
= Type::Find (p
->deployment
, Type::TIMESPAN
);
1217 return new XamlElementInfoNative (t
);
1223 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1228 virtual const char* GetUri () { return PRIMITIVE_NAMESPACE_URI
; }
1232 class MCIgnorableNamespace
: public XamlNamespace
{
1235 MCIgnorableNamespace (char *prefix
)
1240 virtual ~MCIgnorableNamespace ()
1244 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1249 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1251 if (!strcmp ("Ignorable", attr
)) {
1252 const char *start
= value
;
1254 const char *space
= strchr (start
, ' ');
1257 prefix
= g_strndup (start
, space
- start
);
1260 prefix
= g_strdup (start
);
1264 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
1266 ns
->is_ignored
= true;
1276 virtual const char* GetUri () { return MC_IGNORABLE_NAMESPACE_URI
; }
1281 destroy_created_namespace (gpointer data
, gpointer user_data
)
1283 XamlNamespace
* ns
= (XamlNamespace
*) data
;
1288 class XamlElementInfoManaged
: public XamlElementInfo
{
1290 XamlElementInfoManaged (const char *xmlns
, const char *name
, XamlElementInfo
*parent
, Type::Kind dependency_type
, Value
*obj
) : XamlElementInfo (xmlns
, name
, dependency_type
)
1297 const char* GetName () { return name
; }
1299 const char* GetContentProperty (XamlParserInfo
*p
);
1301 virtual bool RequiresManagedSet () { return true; }
1303 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
1304 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
1305 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
1309 class XamlElementInstanceManaged
: public XamlElementInstance
{
1311 XamlElementInstanceManaged (XamlElementInfo
*info
, const char *name
, ElementType type
, Value
*obj
);
1313 virtual bool IsDependencyObject ()
1315 return is_dependency_object
;
1318 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
);
1319 virtual bool SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char* value
);
1320 virtual void AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
);
1321 virtual void SetAttributes (XamlParserInfo
*p
, const char **attr
);
1323 virtual bool TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
);
1324 virtual bool TrySetContentProperty (XamlParserInfo
*p
, const char *value
);
1326 virtual void* GetManagedPointer ();
1327 virtual Value
* GetParentPointer ();
1329 bool is_dependency_object
;
1333 class XamlElementInfoImportedManaged
: public XamlElementInfoManaged
{
1335 XamlElementInfoImportedManaged (const char *name
, XamlElementInfo
*parent
, Value
*obj
) : XamlElementInfoManaged (NULL
, name
, parent
, obj
->GetKind (), obj
)
1339 const char* GetContentProperty (XamlParserInfo
*p
);
1341 XamlElementInstance
* CreateElementInstance (XamlParserInfo
*p
);
1342 XamlElementInstance
* CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
);
1343 XamlElementInstance
* CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
);
1348 class ManagedNamespace
: public XamlNamespace
{
1352 ManagedNamespace (char *xmlns
, char *prefix
)
1354 this->xmlns
= xmlns
;
1358 virtual ~ManagedNamespace ()
1363 virtual XamlElementInfo
* FindElement (XamlParserInfo
*p
, const char *el
, const char **attr
, bool create
)
1365 char* type_name
= NULL
;
1366 char* type_xmlns
= NULL
;
1367 const char* use_xmlns
= xmlns
;
1373 // We might have an x:Class attribute specified, so we need to use that for the
1374 // type_name that we pass to LookupObject
1375 if (strcmp ("Application", el
)) {
1376 type_name
= x_namespace
->FindTypeName (attr
, &type_xmlns
);
1379 use_xmlns
= type_xmlns
;
1381 if (!p
->hydrating
) {
1382 parser_error (p
, el
, "x:Class", 4005, "Cannot specify x:Class in xaml files outside of a xap.");
1389 Value
*value
= new Value ();
1390 if (!p
->loader
->LookupObject (p
, p
->GetTopElementPtr (), p
->current_element
? p
->current_element
->GetAsValue () : NULL
, use_xmlns
, el
, create
, false, value
)) {
1391 parser_error (p
, el
, NULL
, 2007, "Unable to resolve managed type %s.", el
);
1396 g_free (type_xmlns
);
1400 if (p
->hydrate_expecting
) {
1402 // If we are hydrating a top level managed object, use the Value* passed
1403 // to Hydrate as our value
1406 value
= p
->hydrate_expecting
;
1410 XamlElementInfoManaged
*info
= new XamlElementInfoManaged (xmlns
, g_strdup (el
), NULL
, value
->GetKind (), value
);
1414 g_free (type_xmlns
);
1418 virtual bool SetAttribute (XamlParserInfo
*p
, XamlElementInstance
*item
, const char *attr
, const char *value
)
1424 Value v
= Value (value
);
1425 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), item
->info
->xmlns
, item
->GetAsValue (), item
, item
->GetParentPointer (), xmlns
, attr
, &v
, NULL
);
1431 virtual const char* GetUri () { return xmlns
; }
1435 XamlLoader::LookupObject (void *p
, Value
*top_level
, Value
*parent
, const char* xmlns
, const char* type_name
, bool create
, bool is_property
, Value
*value
)
1437 if (callbacks
.lookup_object
) {
1438 if (!vm_loaded
&& !LoadVM ())
1441 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1442 bool res
= callbacks
.lookup_object (&data
, parent
, xmlns
, type_name
, create
, is_property
, value
, &error
);
1450 XamlLoader::GetContentPropertyName (void *p
, Value
*top_level
, Value
*object
)
1452 if (callbacks
.get_content_property_name
) {
1454 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1455 return callbacks
.get_content_property_name (&data
, object
, &error
);
1461 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
)
1463 if (callbacks
.set_property
) {
1465 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
, flags
);
1466 bool res
= callbacks
.set_property (&data
, xmlns
, target
, target_data
, target_parent
, prop_xmlns
, name
, value
, value_data
, &error
);
1468 if (error
.number
!= MoonError::NO_ERROR
) {
1469 parser_error ((XamlParserInfo
*) p
, ((XamlElementInstance
*) target_data
)->element_name
, NULL
, error
.code
, error
.message
);
1480 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
)
1482 if (callbacks
.add_child
) {
1484 XamlCallbackData data
= XamlCallbackData (this, p
, top_level
);
1485 bool res
= callbacks
.add_child (&data
, parent_parent
, parent_is_property
, parent_xmlns
, parent
, parent_data
, child
, child_data
, &error
);
1487 if (error
.number
!= MoonError::NO_ERROR
) {
1488 parser_error ((XamlParserInfo
*) p
, ((XamlElementInstance
*) child_data
)->element_name
, NULL
, error
.code
, error
.message
);
1497 XamlLoader::XamlLoader (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1499 Initialize (resourceBase
, filename
, str
, surface
, context
);
1502 XamlLoader::XamlLoader (const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1504 Initialize (NULL
, filename
, str
, surface
, context
);
1508 XamlLoader::Initialize (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
, XamlContext
*context
)
1510 this->filename
= g_strdup (filename
);
1511 this->resource_base
= g_strdup (resourceBase
);
1512 this->str
= g_strdup (str
);
1513 this->surface
= surface
;
1516 this->context
= context
;
1517 this->vm_loaded
= false;
1518 this->error_args
= NULL
;
1519 this->expanding_template
= false;
1520 this->template_owner
= NULL
;
1521 this->import_default_xmlns
= false;
1524 callbacks
= context
->internal
->callbacks
;
1525 this->vm_loaded
= true;
1528 if (!surface
&& debug_flags
& RUNTIME_DEBUG_XAML
) {
1529 printf ("XamlLoader::XamlLoader ('%s', '%s', %p): Initializing XamlLoader without a surface.\n",
1530 filename
, str
, surface
);
1535 XamlLoader::~XamlLoader ()
1538 g_free (resource_base
);
1546 error_args
->unref();
1550 XamlLoader::LoadVM ()
1556 xaml_loader_new (const char *resourceBase
, const char* filename
, const char* str
, Surface
* surface
)
1558 return new XamlLoader (resourceBase
, filename
, str
, surface
);
1562 xaml_loader_free (XamlLoader
* loader
)
1568 xaml_loader_set_callbacks (XamlLoader
* loader
, XamlLoaderCallbacks callbacks
)
1571 LOG_XAML ("Trying to set callbacks for a null object\n");
1575 loader
->callbacks
= callbacks
;
1576 loader
->vm_loaded
= true;
1580 namespace_for_prefix (gpointer key
, gpointer value
, gpointer user_data
)
1582 XamlNamespace
*ns
= (XamlNamespace
*) value
;
1583 const char *prefix
= (const char *) user_data
;
1585 return ns
->HasPrefix (prefix
);
1589 xaml_uri_for_prefix (void *parser
, char* prefix
)
1591 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
1593 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
1597 return g_strdup (ns
->GetUri ());
1601 // Called when we encounter an error. Note that memory ownership is taken for everything
1602 // except the message, this allows you to use g_strdup_printf when creating the error message
1605 parser_error (XamlParserInfo
*p
, const char *el
, const char *attr
, int error_code
, const char *format
, ...)
1614 // if parsing fails too early it's not safe (i.e. sigsegv) to call some functions, e.g. XML_GetCurrentLineNumber
1615 bool report_line_col
= (error_code
!= XML_ERROR_XML_DECL
);
1616 int line_number
= report_line_col
? XML_GetCurrentLineNumber (p
->parser
) : 0;
1617 int char_position
= report_line_col
? XML_GetCurrentColumnNumber (p
->parser
) : 0;
1619 va_start (args
, format
);
1620 message
= g_strdup_vprintf (format
, args
);
1623 p
->error_args
= new ParserErrorEventArgs (message
, p
->file_name
, line_number
, char_position
, error_code
, el
, attr
);
1627 LOG_XAML ("PARSER ERROR, STOPPING PARSING: (%d) %s line: %d char: %d\n", error_code
, message
,
1628 line_number
, char_position
);
1630 XML_StopParser (p
->parser
, FALSE
);
1634 expat_parser_error (XamlParserInfo
*p
, XML_Error expat_error
)
1636 // Already had an error
1640 LOG_XAML ("expat error is: %d\n", expat_error
);
1642 switch (expat_error
) {
1643 case XML_ERROR_DUPLICATE_ATTRIBUTE
:
1644 parser_error (p
, NULL
, NULL
, 7031, "wfc: unique attribute spec");
1646 case XML_ERROR_UNBOUND_PREFIX
:
1647 parser_error (p
, NULL
, NULL
, 7055, "undeclared prefix");
1649 case XML_ERROR_NO_ELEMENTS
:
1650 parser_error (p
, NULL
, NULL
, 7000, "unexpected end of input");
1652 case XML_ERROR_SYNTAX
:
1653 parser_error (p
, NULL
, NULL
, 2103, "syntax error");
1656 parser_error (p
, NULL
, NULL
, expat_error
, "Unhandled XML error %s", XML_ErrorString (expat_error
));
1662 start_element (void *data
, const char *el
, const char **attr
)
1664 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1665 XamlElementInfo
*elem
= NULL
;
1666 XamlElementInstance
*inst
;
1667 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
1669 if (!strcmp (el
, INTERNAL_IGNORABLE_ELEMENT
))
1672 if (p
->ShouldBeginBuffering ()) {
1673 p
->BeginBuffering ();
1677 if (p
->InBufferingMode ()) {
1678 if (!strcmp (p
->buffer_until_element
, el
))
1683 const char *dot
= strchr (el
, '.');
1685 elem
= p
->current_namespace
->FindElement (p
, el
, attr
, p
->hydrate_expecting
== NULL
);
1692 if (p
->hydrate_expecting
){
1694 Type::Kind expecting_type = p->hydrate_expecting->GetObjectType ();
1696 if (!types->IsSubclassOf (expecting_type, elem->GetKind ())) {
1697 parser_error (p, el, NULL, -1, "Invalid top-level element found %s, expecting %s", el,
1698 types->Find (expecting_type)->GetName ());
1703 inst
= elem
->CreateWrappedElementInstance (p
, p
->hydrate_expecting
);
1704 p
->hydrate_expecting
= NULL
;
1706 inst
= elem
->CreateElementInstance (p
);
1711 inst
->parent
= p
->current_element
;
1713 if (!p
->top_element
) {
1714 p
->top_element
= inst
;
1715 if (inst
->GetAsDependencyObject ())
1716 NameScope::SetNameScope (inst
->GetAsDependencyObject (), p
->namescope
);
1719 if (inst
->GetAsDependencyObject ())
1720 inst
->GetAsDependencyObject ()->SetIsBeingParsed (true);
1722 inst
->SetAttributes (p
, attr
);
1726 if (inst
->IsDependencyObject ()) {
1727 if (p
->current_element
){
1728 if (p
->current_element
->info
) {
1729 p
->current_element
->AddChild (p
, inst
);
1736 // it's actually valid (from SL point of view) to have <Ellipse.Triggers> inside a <Rectangle>
1737 // however we can't add properties to something bad, like a <Recta.gle> element
1738 XamlElementInfo
*prop_info
= NULL
;
1740 gchar
*prop_elem
= g_strndup (el
, dot
- el
);
1741 prop_info
= p
->current_element
->FindPropertyElement (p
, el
, dot
);
1745 if (prop_info
!= NULL
) {
1746 inst
= prop_info
->CreatePropertyElementInstance (p
, g_strdup (el
));
1747 inst
->parent
= p
->current_element
;
1749 if (attr
[0] != NULL
) {
1750 // It appears there is a bug in the error string but it matches the MS runtime
1751 parser_error (p
, el
, NULL
, 2018, "The element %s does not support attributes.", attr
[0]);
1755 if (prop_info
&& !strcmp (el
, "TextBox.Text"))
1756 prop_info
->SetIsCDataVerbatim (true);
1758 if (!p
->top_element
) {
1759 if (types
->IsSubclassOf (prop_info
->GetKind (), Type::COLLECTION
)) {
1760 XamlElementInstance
*wrap
= prop_info
->CreateElementInstance (p
);
1761 NameScope::SetNameScope (wrap
->GetAsDependencyObject (), p
->namescope
);
1762 p
->top_element
= wrap
;
1763 p
->current_element
= wrap
;
1768 g_warning ("Unknown element: %s.", el
);
1769 parser_error (p
, el
, NULL
, 2007, "Unknown element: %s.", el
);
1774 if (p
->current_element
) {
1775 p
->current_element
->children
->Append (inst
);
1777 p
->current_element
= inst
;
1779 if (elem
&& element_begins_buffering (elem
->GetKind ())) {
1780 p
->QueueBeginBuffering (g_strdup (el
), BUFFER_MODE_TEMPLATE
);
1785 allow_value_from_str_in_flush (XamlParserInfo
*p
, XamlElementInstance
*parent
)
1787 if (parent
== NULL
|| parent
->element_type
!= XamlElementInstance::PROPERTY
|| parent
->parent
== NULL
|| !parent
->parent
->IsDependencyObject ())
1790 if (parent
->info
->GetKind () == Type::OBJECT
)
1797 flush_char_data (XamlParserInfo
*p
)
1799 if (p
->InBufferingMode ())
1802 if (!p
->cdata
|| !p
->current_element
)
1805 if (p
->current_element
->info
->IsCDataVerbatim()) {
1806 p
->cdata
->str
= g_strstrip (p
->cdata
->str
);
1809 if (p
->current_element
->element_type
== XamlElementInstance::ELEMENT
) {
1810 if (!p
->current_element
->TrySetContentProperty (p
, p
->cdata
->str
) && p
->cdata_content
) {
1811 if (allow_value_from_str_in_flush (p
, p
->current_element
->parent
)) {
1813 if (value_from_str (p
->current_element
->info
->GetKind (), NULL
, p
->cdata
->str
, &v
)) {
1814 p
->current_element
->SetValue (v
);
1818 parser_error (p
, p
->current_element
->element_name
, NULL
, 2011,
1819 "%s does not support text content.", p
->current_element
->element_name
);
1821 } else if (p
->current_element
->element_type
== XamlElementInstance::PROPERTY
) {
1822 if (p
->cdata_content
&& p
->current_element
->parent
&& !p
->current_element
->parent
->SetProperty (p
, p
->current_element
, p
->cdata
->str
)) {
1823 parser_error (p
, p
->current_element
->element_name
, NULL
, 2011,
1824 "%s does not support text content.", p
->current_element
->element_name
);
1830 g_string_free (p
->cdata
, TRUE
);
1831 p
->cdata_content
= false;
1837 element_begins_buffering (Type::Kind kind
)
1839 return Type::IsSubclassOf (Deployment::GetCurrent (), kind
, Type::FRAMEWORKTEMPLATE
);
1843 is_default_namespace (gpointer key
, gpointer value
, gpointer user_data
)
1845 return value
== default_namespace
;
1849 start_element_handler (void *data
, const char *el
, const char **attr
)
1851 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1856 char **name
= g_strsplit (el
, "|", -1);
1857 XamlNamespace
*next_namespace
= NULL
;
1858 char *element
= NULL
;
1860 if (g_strv_length (name
) == 2) {
1861 // Find the proper namespace for our next element
1862 next_namespace
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, name
[0]);
1866 if (!next_namespace
&& p
->implicit_default_namespace
) {
1867 // Use the default namespace for the next element
1868 next_namespace
= default_namespace
;
1870 } else if (!next_namespace
) {
1871 if (!g_hash_table_find (p
->namespace_map
, is_default_namespace
, NULL
))
1872 return parser_error (p
, el
, NULL
, 2263, "AG_E_PARSER_MISSING_DEFAULT_NAMESPACE");
1875 if (next_namespace
&& next_namespace
->is_ignored
) {
1876 p
->current_namespace
= next_namespace
;
1877 if (!p
->InBufferingMode ())
1878 p
->QueueBeginBuffering (g_strdup (element
), BUFFER_MODE_IGNORE
);
1880 start_element (data
, element
, attr
); // This will force the buffering to start/build depth if needed
1884 p
->next_element
= element
;
1886 flush_char_data (p
);
1888 // Now update our namespace
1889 p
->current_namespace
= next_namespace
;
1891 if (!p
->current_namespace
&& !p
->InBufferingMode ()) {
1893 parser_error (p
, name
[1], NULL
, -1, "No handlers available for namespace: '%s' (%s)\n", name
[0], el
);
1895 parser_error (p
, name
[1], NULL
, -1, "No namespace mapping available for element: '%s'\n", el
);
1901 p
->next_element
= NULL
;
1902 start_element (data
, element
, attr
);
1908 get_element_name (XamlParserInfo
* p
, const char *el
)
1910 char **names
= g_strsplit (el
, "|", -1);
1911 char *name
= g_strdup (names
[g_strv_length (names
) - 1]);
1919 create_resource_list (XamlParserInfo
*p
)
1921 GSList
*list
= NULL
;
1922 XamlElementInstance
*walk
= p
->current_element
;
1924 Types
* types
= Deployment::GetCurrent ()->GetTypes ();
1926 if (walk
->element_type
== XamlElementInstance::ELEMENT
&& types
->IsSubclassOf (walk
->info
->GetKind (), Type::FRAMEWORKELEMENT
)) {
1927 FrameworkElement
*fwe
= (FrameworkElement
*)walk
->GetAsDependencyObject ();
1928 if (g_slist_index (list
, fwe
) == -1)
1929 list
= g_slist_prepend (list
, fwe
);
1931 if (walk
->element_type
== XamlElementInstance::ELEMENT
&& types
->IsSubclassOf (walk
->info
->GetKind (), Type::RESOURCE_DICTIONARY
)) {
1932 ResourceDictionary
*rd
= (ResourceDictionary
*) walk
->GetAsDependencyObject ();
1933 if (g_slist_index (list
, rd
) == -1)
1934 list
= g_slist_prepend (list
, walk
->GetAsDependencyObject ());
1936 walk
= walk
->parent
;
1939 list
= g_slist_reverse (list
);
1943 static XamlContext
*
1944 create_xaml_context (XamlParserInfo
*p
, FrameworkTemplate
*template_
, XamlContext
*parent_context
)
1946 GSList
*resources
= create_resource_list (p
);
1947 XamlContextInternal
*ic
= new XamlContextInternal (p
->loader
->callbacks
, p
->GetTopElementPtr (), template_
, p
->namespace_map
, resources
, parent_context
? parent_context
->internal
: NULL
);
1948 return new XamlContext (ic
);
1952 end_element_handler (void *data
, const char *el
)
1954 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
1955 DependencyObject
*obj
;
1957 if (!strcmp (el
, INTERNAL_IGNORABLE_ELEMENT
))
1963 if (!p
->current_element
) {
1964 g_warning ("p->current_element == NULL, current_element = %p (%s)\n",
1965 p
->current_element
, p
->current_element
? p
->current_element
->element_name
: "<NULL>");
1969 if (p
->InBufferingMode ()) {
1970 char* name
= get_element_name (p
, el
);
1971 if (!strcmp (p
->buffer_until_element
, name
)) {
1974 if (p
->buffer_depth
== 0) {
1975 if (p
->buffer_mode
== BUFFER_MODE_TEMPLATE
) {
1976 // OK we are done buffering, the element we are buffering for
1977 FrameworkTemplate
* template_
= (FrameworkTemplate
*) p
->current_element
->GetAsDependencyObject ();
1979 char* buffer
= p
->ClearBuffer ();
1981 XamlContext
*context
= create_xaml_context (p
, template_
, p
->loader
->GetContext());
1983 if (p
->validate_templates
) {
1984 p
->ValidateTemplate (buffer
, context
, template_
);
1990 template_
->SetXamlBuffer (context
, buffer
);
1991 p
->current_element
= p
->current_element
->parent
;
1992 } else if (p
->buffer_mode
== BUFFER_MODE_IGNORE
) {
1993 // For now we'll actually keep/clear this buffer because it makes testing easier
1994 char *buffer
= p
->ClearBuffer ();
2004 switch (p
->current_element
->element_type
) {
2005 case XamlElementInstance::ELEMENT
:
2007 p
->current_element
->SetDelayedProperties (p
);
2008 flush_char_data (p
);
2010 // according to http://blogs.msdn.com/devdave/archive/2008/10/11/control-lifecycle.aspx
2011 // default styles are apply when the end tag is read.
2013 if (p
->current_element
->IsDependencyObject () &&
2014 p
->current_element
->GetAsDependencyObject() &&
2015 p
->current_element
->GetAsDependencyObject()->Is(Type::CONTROL
)) {
2017 Control
*control
= (Control
*)p
->current_element
->GetAsDependencyObject();
2018 ManagedTypeInfo
*key
= control
->GetDefaultStyleKey ();
2021 if (Application::GetCurrent () == NULL
)
2022 g_warning ("attempting to use a null application applying default style while parsing.");
2024 Application::GetCurrent()->ApplyDefaultStyle (control
, key
);
2027 else if (!p
->current_element
->IsDependencyObject ()) {
2029 if (p
->current_element
->parent
)
2030 p
->current_element
->parent
->AddChild (p
, p
->current_element
);
2033 case XamlElementInstance::PROPERTY
: {
2034 List::Node
*walk
= p
->current_element
->children
->First ();
2036 XamlElementInstance
*child
= (XamlElementInstance
*) walk
;
2037 if (p
->current_element
->parent
) {
2038 p
->current_element
->parent
->SetProperty (p
, p
->current_element
, child
);
2042 flush_char_data (p
);
2047 if ((obj
= p
->current_element
->GetAsDependencyObject ()))
2048 obj
->SetIsBeingParsed (false);
2050 p
->current_element
= p
->current_element
->parent
;
2054 char_data_handler (void *data
, const char *in
, int inlen
)
2056 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2057 register const char *inptr
= in
;
2058 const char *inend
= in
+ inlen
;
2061 if (p
->InBufferingMode ())
2067 if (p
->current_element
&& p
->current_element
->info
->IsCDataVerbatim()) {
2069 p
->cdata
= g_string_new ("");
2071 g_string_append_len (p
->cdata
, inptr
, inlen
);
2072 p
->cdata_content
= true;
2077 p
->cdata
= g_string_new ("");
2079 if (g_ascii_isspace (*inptr
)) {
2080 g_string_append_c (p
->cdata
, ' ');
2083 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2089 } else if (g_ascii_isspace (p
->cdata
->str
[p
->cdata
->len
- 1])) {
2090 // previous cdata chunk ended with lwsp, skip over leading lwsp for this chunk
2091 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2095 while (inptr
< inend
) {
2097 while (inptr
< inend
&& !g_ascii_isspace (*inptr
))
2100 if (inptr
> start
) {
2101 g_string_append_len (p
->cdata
, start
, inptr
- start
);
2102 p
->cdata_content
= true;
2105 if (inptr
< inend
) {
2106 g_string_append_c (p
->cdata
, ' ');
2109 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2116 start_namespace_handler (void *data
, const char *prefix
, const char *uri
)
2118 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2120 if (p
->InBufferingMode ())
2126 if (p
->loader
!= NULL
&& p
->loader
->callbacks
.import_xaml_xmlns
!= NULL
) {
2128 XamlCallbackData data
= XamlCallbackData (p
->loader
, p
, p
->GetTopElementPtr ());
2129 if (!p
->loader
->callbacks
.import_xaml_xmlns (&data
, uri
, &error
))
2130 return parser_error (p
, p
->current_element
? p
->current_element
->element_name
: NULL
, prefix
, 2005, "Unknown namespace %s", uri
);
2133 for (int i
= 0; default_namespace_names
[i
]; i
++) {
2134 if (!strcmp (default_namespace_names
[i
], uri
)) {
2135 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), default_namespace
);
2140 if (!strcmp (X_NAMESPACE_URI
, uri
)){
2141 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), x_namespace
);
2142 } else if (!strcmp (PRIMITIVE_NAMESPACE_URI
, uri
)) {
2143 PrimitiveNamespace
*pn
= new PrimitiveNamespace (g_strdup (prefix
));
2144 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), pn
);
2145 p
->AddCreatedNamespace (pn
);
2146 } else if (!strcmp (MC_IGNORABLE_NAMESPACE_URI
, uri
)) {
2147 MCIgnorableNamespace
*mc
= new MCIgnorableNamespace (g_strdup (prefix
));
2148 g_hash_table_insert (p
->namespace_map
, g_strdup (uri
), mc
);
2149 p
->AddCreatedNamespace (mc
);
2152 return parser_error (p
, (p
->current_element
? p
->current_element
->element_name
: NULL
), prefix
, -1,
2153 "No managed element callback installed to handle %s", uri
);
2157 parser_error (p
, (p
->current_element
? p
->current_element
->element_name
: NULL
), NULL
, 2262,
2158 "AG_E_PARSER_NAMESPACE_NOT_SUPPORTED");
2162 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, uri
);
2165 ns
->AddPrefix (prefix
);
2169 ManagedNamespace
*c
= new ManagedNamespace (g_strdup (uri
), g_strdup (prefix
));
2170 g_hash_table_insert (p
->namespace_map
, g_strdup (c
->xmlns
), c
);
2171 p
->AddCreatedNamespace (c
);
2176 start_doctype_handler (void *data
,
2177 const XML_Char
*doctype_name
,
2178 const XML_Char
*sysid
,
2179 const XML_Char
*pubid
,
2180 int has_internal_subset
)
2182 XamlParserInfo
*p
= (XamlParserInfo
*) data
;
2184 if (p
->InBufferingMode ())
2188 return parser_error (p
, NULL
, NULL
, 7050, "DTD was found but is prohibited");
2191 return parser_error (p
, NULL
, NULL
, 7016, "incorrect document syntax.");
2195 add_default_namespaces (XamlParserInfo
*p
, bool sl_xmlns
)
2198 p
->implicit_default_namespace
= true;
2199 g_hash_table_insert (p
->namespace_map
, g_strdup ("http://schemas.microsoft.com/winfx/2006/xaml/presentation"), default_namespace
);
2200 g_hash_table_insert (p
->namespace_map
, g_strdup (X_NAMESPACE_URI
), x_namespace
);
2202 g_hash_table_insert (p
->namespace_map
, g_strdup (XML_NAMESPACE_URI
), xml_namespace
);
2206 print_tree (XamlElementInstance
*el
, int depth
)
2209 if (debug_flags
& RUNTIME_DEBUG_XAML
) {
2210 for (int i
= 0; i
< depth
; i
++)
2213 const char *name
= NULL
;
2216 printf (" -null- \n");
2220 if (el
->element_type
== XamlElementInstance::ELEMENT
&& el
->IsDependencyObject ())
2221 name
= el
->GetAsDependencyObject ()->GetName ();
2222 printf ("%s (%s) (%p) (%s)\n", el
->element_name
, name
? name
: "-no name-", el
->parent
, el
->element_type
== XamlElementInstance::PROPERTY
? "PROPERTY" : "ELEMENT");
2224 for (List::Node
*walk
= el
->children
->First (); walk
!= NULL
; walk
= walk
->next
) {
2225 XamlElementInstance
*el
= (XamlElementInstance
*) walk
;
2226 print_tree (el
, depth
+ 1);
2233 xaml_parse_xmlns (const char* xmlns
, char** type_name
, char** ns
, char** assembly
)
2235 const char delimiters
[] = ";";
2237 char* buffer
= g_strdup (xmlns
);
2243 decl
= strtok (buffer
, delimiters
);
2244 while (decl
!= NULL
) {
2245 if (strstr (decl
, "clr-namespace:") == decl
) {
2248 *ns
= g_strdup (decl
+ 14);
2249 } else if (strstr (decl
, "assembly=") == decl
) {
2252 *assembly
= g_strdup (decl
+ 9);
2255 g_free (*type_name
);
2256 *type_name
= g_strdup (decl
);
2259 decl
= strtok (NULL
, delimiters
);
2265 XamlLoader::CreateFromFile (const char *xaml_file
, bool create_namescope
,
2266 Type::Kind
*element_type
)
2269 XamlParserInfo
*parser_info
= NULL
;
2270 XML_Parser p
= NULL
;
2271 bool first_read
= true;
2272 const char *inptr
, *inend
;
2277 LOG_XAML ("attemtping to load xaml file: %s\n", xaml_file
);
2279 stream
= new TextStream ();
2280 if (!stream
->OpenFile (xaml_file
, false)) {
2281 LOG_XAML ("can not open file\n");
2282 goto cleanup_and_return
;
2285 if (!(p
= XML_ParserCreateNS ("UTF-8", '|'))) {
2286 LOG_XAML ("can not create parser\n");
2287 goto cleanup_and_return
;
2290 parser_info
= new XamlParserInfo (p
, xaml_file
);
2292 parser_info
->namescope
->SetTemporary (!create_namescope
);
2294 parser_info
->loader
= this;
2296 // TODO: This is just in here temporarily, to make life less difficult for everyone
2297 // while we are developing.
2298 add_default_namespaces (parser_info
, false);
2300 XML_SetUserData (p
, parser_info
);
2302 XML_SetElementHandler (p
, start_element_handler
, end_element_handler
);
2303 XML_SetCharacterDataHandler (p
, char_data_handler
);
2304 XML_SetNamespaceDeclHandler(p
, start_namespace_handler
, NULL
);
2305 XML_SetDoctypeDeclHandler(p
, start_doctype_handler
, NULL
);
2308 XML_SetProcessingInstructionHandler (p, proc_handler);
2311 while ((nread
= stream
->Read (buffer
, sizeof (buffer
))) >= 0) {
2315 if (first_read
&& nread
> 0) {
2316 // Remove preceding white space
2317 inend
= buffer
+ nread
;
2319 while (inptr
< inend
&& g_ascii_isspace (*inptr
))
2325 n
= (inend
- inptr
);
2329 parser_info
->SetXmlBuffer (inptr
);
2330 if (!XML_Parse (p
, inptr
, n
, nread
== 0)) {
2331 expat_parser_error (parser_info
, XML_GetErrorCode (p
));
2332 goto cleanup_and_return
;
2339 print_tree (parser_info
->top_element
, 0);
2341 if (parser_info
->top_element
) {
2342 res
= parser_info
->top_element
->GetAsValue ();
2343 // We want a copy because the old one is going to be deleted
2344 res
= new Value (*res
);
2347 *element_type
= parser_info
->top_element
->info
->GetKind ();
2349 if (parser_info
->error_args
) {
2350 *element_type
= Type::INVALID
;
2351 goto cleanup_and_return
;
2358 error_args
= new ParserErrorEventArgs ("Error opening xaml file", xaml_file
, 0, 0, 1, "", "");
2359 else if (parser_info
->error_args
) {
2360 error_args
= parser_info
->error_args
;
2376 XamlLoader::CreateFromString (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
, int flags
)
2378 return HydrateFromString (xaml
, NULL
, create_namescope
, element_type
, flags
);
2382 value_to_dependency_object (Value
*value
)
2384 if (!value
|| !value
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
))
2386 return value
->AsDependencyObject ();
2390 XamlLoader::CreateDependencyObjectFromFile (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
)
2392 return value_to_dependency_object (CreateFromFile (xaml
, create_namescope
, element_type
));
2396 XamlLoader::CreateDependencyObjectFromString (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
)
2398 return value_to_dependency_object (CreateFromString (xaml
, create_namescope
, element_type
, IMPORT_DEFAULT_XMLNS
));
2402 * Hydrates an existing DependencyObject (@object) with the contents from the @xaml
2406 XamlLoader::HydrateFromString (const char *xaml
, Value
*object
, bool create_namescope
, Type::Kind
*element_type
, int flags
)
2408 XML_Parser p
= XML_ParserCreateNS ("utf-8", '|');
2409 XamlParserInfo
*parser_info
= NULL
;
2411 char *start
= (char*)xaml
;
2412 char *prepend
= NULL
;
2413 char *append
= NULL
;
2414 char * inputs
[4] = {NULL
, NULL
, NULL
, NULL
};
2419 LOG_XAML ("can not create parser\n");
2420 goto cleanup_and_return
;
2429 sprintf (filename
, "createFromXaml.%d.xaml", id
++);
2430 if ((fp
= fopen (filename
, "wt")) != NULL
) {
2431 fwrite (xaml
, strlen (xaml
), 1, fp
);
2437 parser_info
= new XamlParserInfo (p
, NULL
);
2439 parser_info
->namescope
->SetTemporary (!create_namescope
);
2441 parser_info
->loader
= this;
2442 parser_info
->validate_templates
= (flags
& VALIDATE_TEMPLATES
) == VALIDATE_TEMPLATES
;
2445 // If we are hydrating, we are not null
2447 if (object
!= NULL
) {
2448 parser_info
->hydrate_expecting
= object
;
2449 parser_info
->hydrating
= true;
2450 if (Type::IsSubclassOf (parser_info
->deployment
, object
->GetKind (), Type::DEPENDENCY_OBJECT
)) {
2451 DependencyObject
*dob
= object
->AsDependencyObject ();
2452 dob
->SetIsAttached (true);
2453 dob
->SetResourceBase (GetResourceBase());
2456 parser_info
->hydrate_expecting
= NULL
;
2457 parser_info
->hydrating
= false;
2460 // from_str gets the default namespaces implictly added
2461 add_default_namespaces (parser_info
, (flags
& IMPORT_DEFAULT_XMLNS
) == IMPORT_DEFAULT_XMLNS
);
2463 XML_SetUserData (p
, parser_info
);
2465 XML_SetElementHandler (p
, start_element_handler
, end_element_handler
);
2466 XML_SetCharacterDataHandler (p
, char_data_handler
);
2467 XML_SetNamespaceDeclHandler(p
, start_namespace_handler
, NULL
);
2468 XML_SetDoctypeDeclHandler(p
, start_doctype_handler
, NULL
);
2471 XML_SetProcessingInstructionHandler (p, proc_handler);
2475 prepend
= context
->internal
->CreateIgnorableTagOpen ();
2476 append
= context
->internal
->CreateIgnorableTagClose ();
2478 inputs
[0] = prepend
;
2480 inputs
[2] = append
;
2483 for (int i
= 0; inputs
[i
]; i
++) {
2484 char *start
= inputs
[i
];
2486 // don't freak out if the <?xml ... ?> isn't on the first line (see #328907)
2487 while (g_ascii_isspace (*start
))
2490 parser_info
->SetXmlBuffer (start
);
2491 if (!XML_Parse (p
, start
, strlen (start
), inputs
[i
+ 1] == NULL
)) {
2492 expat_parser_error (parser_info
, XML_GetErrorCode (p
));
2493 LOG_XAML ("error parsing: %s\n\n", xaml
);
2494 goto cleanup_and_return
;
2498 print_tree (parser_info
->top_element
, 0);
2500 if (parser_info
->top_element
) {
2501 if (is_legal_top_level_kind (parser_info
->top_element
->info
->GetKind ())) {
2502 res
= parser_info
->top_element
->GetAsValue ();
2503 res
= new Value (*res
);
2504 if (res
->Is (parser_info
->deployment
, Type::DEPENDENCY_OBJECT
) && object
) {
2505 DependencyObject
*dob
= res
->AsDependencyObject ();
2507 dob
->SetIsHydratedFromXaml (parser_info
->hydrating
);
2512 *element_type
= parser_info
->top_element
->info
->GetKind ();
2514 if (!res
&& !parser_info
->error_args
)
2515 parser_info
->error_args
= new ParserErrorEventArgs ("No DependencyObject found", "", 0, 0, 1, "", "");
2517 if (parser_info
->error_args
) {
2521 *element_type
= Type::INVALID
;
2522 goto cleanup_and_return
;
2528 if (parser_info
->error_args
) {
2529 error_args
= parser_info
->error_args
;
2530 printf ("Could not parse element %s, attribute %s, error: %s\n",
2531 error_args
->xml_element
,
2532 error_args
->xml_attribute
,
2533 error_args
->GetErrorMessage());
2549 XamlLoader::CreateFromFileWithError (const char *xaml_file
, bool create_namescope
, Type::Kind
*element_type
, MoonError
*error
)
2551 Value
*res
= CreateFromFile (xaml_file
, create_namescope
, element_type
);
2552 if (error_args
&& error_args
->GetErrorCode () != -1)
2553 MoonError::FillIn (error
, error_args
);
2558 XamlLoader::CreateFromStringWithError (const char *xaml
, bool create_namescope
, Type::Kind
*element_type
, int flags
, MoonError
*error
)
2560 Value
*res
= CreateFromString (xaml
, create_namescope
, element_type
, flags
);
2561 if (error_args
&& error_args
->GetErrorCode () != -1)
2562 MoonError::FillIn (error
, error_args
);
2567 XamlLoader::HydrateFromStringWithError (const char *xaml
, Value
*object
, bool create_namescope
, Type::Kind
*element_type
, int flags
, MoonError
*error
)
2569 Value
*res
= HydrateFromString (xaml
, object
, create_namescope
, element_type
, flags
);
2570 if (error_args
&& error_args
->GetErrorCode () != -1)
2571 MoonError::FillIn (error
, error_args
);
2576 parse_int (const char **pp
, const char *end
)
2578 const char *p
= *pp
;
2580 if (optional
&& AtEnd
)
2587 while (p
<= end
&& g_ascii_isdigit (*p
)) {
2588 res
= res
* 10 + *p
- '0';
2603 parse_ticks (const char **pp
, const char *end
)
2605 gint64 mag
= 1000000;
2607 bool digitseen
= false;
2609 const char *p
= *pp
;
2611 while (mag
> 0 && p
<= end
&& g_ascii_isdigit (*p
)) {
2612 res
= res
+ (*p
- '0') * mag
;
2628 time_span_from_str (const char *str
, TimeSpan
*res
)
2630 const char *end
= str
+ strlen (str
);
2633 bool negative
= false;
2647 days
= parse_int (&p
, end
);
2651 hours
= parse_int (&p
, end
);
2659 minutes
= parse_int (&p
, end
);
2661 seconds
= parse_int (&p
, end
);
2664 ticks
= parse_ticks (&p
, end
);
2670 gint64 t
= (days
* 86400) + (hours
* 3600) + (minutes
* 60) + seconds
;
2673 *res
= negative
? (-t
- ticks
) : (t
+ ticks
);
2679 repeat_behavior_from_str (const char *str
, RepeatBehavior
*res
)
2681 if (!g_ascii_strcasecmp ("Forever", str
)) {
2682 *res
= RepeatBehavior::Forever
;
2686 // check for "<float>x".
2688 // XXX more validation work is needed here.. but how do we
2690 const char *x
= strchr (str
, 'x');
2692 if (*(x
+ 1) != '\0') {
2698 double d
= g_ascii_strtod (str
, &endptr
);
2700 if (errno
|| endptr
== str
)
2703 *res
= RepeatBehavior (d
);
2708 /* XXX RepeatBehavior='XX:XX:XX' syntax is NOT correctly supported by
2709 Silverlight 1.0 (most likely a bug). It works fine in Silverlight 2.0
2710 though. We currently stick to the 2.0 behavior, not replicating the bug
2714 if (!time_span_from_str (str
, &t
))
2717 *res
= RepeatBehavior (t
);
2723 duration_from_str (const char *str
, Duration
*res
)
2725 if (!g_ascii_strcasecmp ("Automatic", str
)) {
2726 *res
= Duration::Automatic
;
2730 if (!g_ascii_strcasecmp ("Forever", str
)) {
2731 *res
= Duration::Forever
;
2736 if (!time_span_from_str (str
, &ts
))
2739 *res
= Duration (ts
);
2744 keytime_from_str (const char *str
, KeyTime
*res
)
2746 if (!g_ascii_strcasecmp ("Uniform", str
)) {
2747 *res
= KeyTime::Uniform
;
2751 if (!g_ascii_strcasecmp ("Paced", str
)) {
2752 *res
= KeyTime::Paced
;
2756 /* check for a percentage first */
2757 const char *last
= str
+ strlen(str
) - 1;
2760 double pct
= g_ascii_strtod (str
, &ep
);
2762 *res
= KeyTime (pct
);
2768 if (!time_span_from_str (str
, &ts
))
2771 *res
= KeyTime (ts
);
2776 key_spline_from_str (const char *str
, KeySpline
**res
)
2778 PointCollection
*pts
= PointCollection::FromStr (str
);
2783 if (pts
->GetCount () != 2) {
2788 *res
= new KeySpline (*pts
->GetValueAt (0)->AsPoint (), *pts
->GetValueAt (1)->AsPoint ());
2796 matrix_from_str (const char *str
)
2798 if (!g_ascii_strcasecmp ("Identity", str
)) {
2799 return new Matrix ();
2802 DoubleCollection
*values
= DoubleCollection::FromStr (str
);
2806 return new Matrix ();
2808 if (values
->GetCount () < 6) {
2813 matrix
= new Matrix ();
2814 matrix
->SetM11 (values
->GetValueAt (0)->AsDouble ());
2815 matrix
->SetM12 (values
->GetValueAt (1)->AsDouble ());
2816 matrix
->SetM21 (values
->GetValueAt (2)->AsDouble ());
2817 matrix
->SetM22 (values
->GetValueAt (3)->AsDouble ());
2818 matrix
->SetOffsetX (values
->GetValueAt (4)->AsDouble ());
2819 matrix
->SetOffsetY (values
->GetValueAt (5)->AsDouble ());
2827 matrix3d_from_str (const char *str
)
2829 if (!g_ascii_strcasecmp ("Identity", str
)) {
2830 return new Matrix3D ();
2833 DoubleCollection
*values
= DoubleCollection::FromStr (str
);
2837 return new Matrix3D ();
2839 if (values
->GetCount () < 12) {
2844 matrix
= new Matrix3D ();
2845 matrix
->SetM11 (values
->GetValueAt (0)->AsDouble ());
2846 matrix
->SetM12 (values
->GetValueAt (1)->AsDouble ());
2847 matrix
->SetM13 (values
->GetValueAt (2)->AsDouble ());
2848 matrix
->SetM13 (values
->GetValueAt (3)->AsDouble ());
2849 matrix
->SetM21 (values
->GetValueAt (4)->AsDouble ());
2850 matrix
->SetM22 (values
->GetValueAt (5)->AsDouble ());
2851 matrix
->SetM23 (values
->GetValueAt (6)->AsDouble ());
2852 matrix
->SetM24 (values
->GetValueAt (7)->AsDouble ());
2853 matrix
->SetM31 (values
->GetValueAt (8)->AsDouble ());
2854 matrix
->SetM32 (values
->GetValueAt (9)->AsDouble ());
2855 matrix
->SetM33 (values
->GetValueAt (10)->AsDouble ());
2856 matrix
->SetM34 (values
->GetValueAt (11)->AsDouble ());
2857 matrix
->SetOffsetX (values
->GetValueAt (12)->AsDouble ());
2858 matrix
->SetOffsetY (values
->GetValueAt (13)->AsDouble ());
2859 matrix
->SetOffsetZ (values
->GetValueAt (14)->AsDouble ());
2860 matrix
->SetM44 (values
->GetValueAt (15)->AsDouble ());
2868 grid_length_from_str (const char *str
, GridLength
*grid_length
)
2870 if (IS_NULL_OR_EMPTY (str
)) {
2871 *grid_length
= GridLength (0.0, GridUnitTypePixel
);
2875 if (str
[0] == '*') {
2876 *grid_length
= GridLength (1.0, GridUnitTypeStar
);
2880 // unit tests shows that "Auto", "auto", "aUtO"... all works
2881 if (!g_ascii_strcasecmp (str
, "Auto")) {
2882 *grid_length
= GridLength ();
2888 double d
= g_ascii_strtod (str
, &endptr
);
2890 if (errno
|| endptr
== str
)
2893 *grid_length
= GridLength (d
, *endptr
== '*' ? GridUnitTypeStar
: GridUnitTypePixel
);
2902 while (*inptr
&& !g_ascii_isalnum (*inptr
) && *inptr
!= '.' && *inptr
!= '-' && *inptr
!= '+')
2903 inptr
= g_utf8_next_char (inptr
);
2909 get_point (Point
*p
, char **in
)
2911 char *end
, *inptr
= *in
;
2914 x
= g_ascii_strtod (inptr
, &end
);
2919 while (g_ascii_isspace (*inptr
))
2925 while (g_ascii_isspace (*inptr
))
2928 y
= g_ascii_strtod (inptr
, &end
);
2941 make_relative (const Point
*cp
, Point
*mv
)
2948 more_points_available (char **in
)
2952 while (g_ascii_isspace (*inptr
) || *inptr
== ',')
2957 return (g_ascii_isdigit (*inptr
) || *inptr
== '.' || *inptr
== '-' || *inptr
== '+');
2961 geometry_from_str (const char *str
)
2963 char *inptr
= (char *) str
;
2964 Point cp
= Point (0, 0);
2965 Point cp1
, cp2
, cp3
;
2968 PathGeometry
*pg
= NULL
;
2969 FillRule fill_rule
= FillRuleEvenOdd
;
2970 bool cbz
= false; // last figure is a cubic bezier curve
2971 bool qbz
= false; // last figure is a quadratic bezier curve
2972 Point cbzp
, qbzp
; // points needed to create "smooth" beziers
2974 moon_path
*path
= moon_path_new (10);
2977 if (g_ascii_isspace (*inptr
))
2983 bool relative
= false;
2986 inptr
= g_utf8_next_char (inptr
);
2994 fill_rule
= FillRuleEvenOdd
;
2995 else if (*inptr
== '1')
2996 fill_rule
= FillRuleNonzero
;
2998 // FIXME: else it's a bad value and nothing should be rendered
2999 goto bad_pml
; // partial: only this Path won't be rendered
3001 inptr
= g_utf8_next_char (inptr
);
3006 if (!get_point (&cp1
, &inptr
))
3010 make_relative (&cp
, &cp1
);
3013 moon_move_to (path
, cp1
.x
, cp1
.y
);
3015 start
.x
= cp
.x
= cp1
.x
;
3016 start
.y
= cp
.y
= cp1
.y
;
3019 while (more_points_available (&inptr
)) {
3020 if (!get_point (&cp1
, &inptr
))
3024 make_relative (&cp
, &cp1
);
3026 moon_line_to (path
, cp1
.x
, cp1
.y
);
3038 while (more_points_available (&inptr
)) {
3039 if (!get_point (&cp1
, &inptr
))
3043 make_relative (&cp
, &cp1
);
3045 moon_line_to (path
, cp1
.x
, cp1
.y
);
3060 double x
= g_ascii_strtod (inptr
, &end
);
3068 cp
= Point (x
, cp
.y
);
3070 moon_line_to (path
, cp
.x
, cp
.y
);
3079 double y
= g_ascii_strtod (inptr
, &end
);
3087 cp
= Point (cp
.x
, y
);
3089 moon_line_to (path
, cp
.x
, cp
.y
);
3098 while (more_points_available (&inptr
)) {
3099 if (!get_point (&cp1
, &inptr
))
3103 make_relative (&cp
, &cp1
);
3107 if (!get_point (&cp2
, &inptr
))
3111 make_relative (&cp
, &cp2
);
3115 if (!get_point (&cp3
, &inptr
))
3119 make_relative (&cp
, &cp3
);
3123 moon_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
, cp3
.x
, cp3
.y
);
3140 while (more_points_available (&inptr
)) {
3141 if (!get_point (&cp2
, &inptr
))
3145 make_relative (&cp
, &cp2
);
3149 if (!get_point (&cp3
, &inptr
))
3153 make_relative (&cp
, &cp3
);
3156 cp1
.x
= 2 * cp
.x
- cbzp
.x
;
3157 cp1
.y
= 2 * cp
.y
- cbzp
.y
;
3161 moon_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
, cp3
.x
, cp3
.y
);
3178 while (more_points_available (&inptr
)) {
3179 if (!get_point (&cp1
, &inptr
))
3183 make_relative (&cp
, &cp1
);
3187 if (!get_point (&cp2
, &inptr
))
3191 make_relative (&cp
, &cp2
);
3195 moon_quad_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
);
3210 while (more_points_available (&inptr
)) {
3211 if (!get_point (&cp2
, &inptr
))
3215 make_relative (&cp
, &cp2
);
3218 cp1
.x
= 2 * cp
.x
- qbzp
.x
;
3219 cp1
.y
= 2 * cp
.y
- qbzp
.y
;
3223 moon_quad_curve_to (path
, cp1
.x
, cp1
.y
, cp2
.x
, cp2
.y
);
3240 while (more_points_available (&inptr
)) {
3241 if (!get_point (&cp1
, &inptr
))
3246 double angle
= g_ascii_strtod (inptr
, &end
);
3253 int is_large
= strtol (inptr
, &end
, 10);
3260 int sweep
= strtol (inptr
, &end
, 10);
3267 if (!get_point (&cp2
, &inptr
))
3271 make_relative (&cp
, &cp2
);
3273 moon_arc_to (path
, cp1
.x
, cp1
.y
, angle
, is_large
, sweep
, cp2
.x
, cp2
.y
);
3285 moon_line_to (path
, start
.x
, start
.y
);
3286 moon_close_path (path
);
3287 moon_move_to (path
, start
.x
, start
.y
);
3298 pg
= new PathGeometry (path
);
3299 pg
->SetFillRule (fill_rule
);
3303 moon_path_destroy (path
);
3308 value_is_explicit_null (const char *str
)
3310 return !strcmp ("{x:Null}", str
);
3314 is_managed_kind (Type::Kind kind
)
3317 if (kind
== Type::MANAGED
||
3318 kind
== Type::OBJECT
||
3319 kind
== Type::URI
||
3320 kind
== Type::MANAGEDTYPEINFO
||
3321 kind
== Type::DEPENDENCYPROPERTY
)
3328 kind_requires_managed_load (Type::Kind kind
)
3330 if (kind
== Type::USERCONTROL
) {
3338 is_legal_top_level_kind (Type::Kind kind
)
3340 if (kind
== Type::MANAGED
|| kind
== Type::OBJECT
|| Type::IsSubclassOf (Deployment::GetCurrent (), kind
, Type::DEPENDENCY_OBJECT
))
3345 // NOTE: Keep definition in sync with class/System.Windows/Mono/NativeMethods.cs
3347 value_from_str_with_typename (const char *type_name
, const char *prop_name
, const char *str
, Value
**v
)
3349 Type
*t
= Type::Find (Deployment::GetCurrent (), type_name
);
3353 return value_from_str (t
->GetKind (), prop_name
, str
, v
);
3357 expand_property_path (XamlParserInfo
*p
, PropertyPath
*path
)
3362 bool expanded
= false;
3363 GString
*res
= g_string_new (path
->path
);
3365 int len
= strlen (res
->str
);
3366 for (int i
= 0; i
< len
; i
++) {
3367 if (res
->str
[i
] == ':') {
3371 for ( ; s
> 0; s
--) {
3372 if (!g_ascii_isalnum (res
->str
[s
]))
3376 for ( ; te
< len
; te
++) {
3377 if (!g_ascii_isalpha (res
->str
[te
]) || res
->str
[te
] == '_')
3381 char *prefix
= g_strndup (res
->str
+ s
+ 1, e
- s
- 1);
3382 char *type
= g_strndup (res
->str
+ e
+ 1, te
- e
- 1);
3384 res
= g_string_erase (res
, s
+ 1, te
- s
- 1);
3386 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_find (p
->namespace_map
, namespace_for_prefix
, prefix
);
3390 g_string_free (res
, true);
3394 XamlElementInfo
*info
= ns
->FindElement (p
, type
, NULL
, false);
3399 g_string_free (res
, true);
3403 char *uri
= g_strdup_printf ("'%s'", Type::Find (p
->deployment
, info
->GetKind ())->GetName ());
3405 res
= g_string_insert (res
, s
+ 1, uri
);
3406 i
= s
+ 1 + strlen (uri
);
3407 len
= strlen (res
->str
);
3419 g_string_free (res
, true);
3423 char *expanded_str
= res
->str
;
3424 g_string_free (res
, false);
3426 return expanded_str
;
3430 value_from_str (Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
)
3434 value_from_str_with_parser (NULL
, type
, prop_name
, str
, v
, &v_set
);
3440 xaml_bool_from_str (const char *s
, bool *res
)
3445 if (!g_ascii_strcasecmp ("true", s
))
3447 else if (!g_ascii_strcasecmp ("false", s
))
3450 // Check if it's a string representing a decimal value
3454 l
= strtol (s
, &endptr
, 10);
3456 if (errno
|| endptr
== s
|| *endptr
|| l
> G_MAXINT32
|| l
< G_MININT32
)
3470 value_from_str_with_parser (XamlParserInfo
*p
, Type::Kind type
, const char *prop_name
, const char *str
, Value
**v
, bool *v_set
)
3475 if (value_is_explicit_null (str
)) {
3481 char *s
= g_strdup (str
);
3483 if (type
== Type::OBJECT
|| type
== Type::STRING
) {
3484 // object and string use the literal string
3487 // everything else depends on the string being stripped
3492 case Type::OBJECT
: {
3493 // not much more can do here, unless we want to try to
3494 // probe str to see if it's actually meant to be a
3495 // specific type. just assume it's a string.
3504 if (!xaml_bool_from_str (s
, &b
))
3511 case Type::DOUBLE
: {
3514 // empty string should not reset default values with 0
3516 // FIXME: this causes a 2.0 unit test to fail (PrimitiveTest.ParseEmptyDouble)
3517 if (IS_NULL_OR_EMPTY(s
)) {
3522 bool is_nan
= false;
3523 if (!g_ascii_strcasecmp (s
, "NAN"))
3527 d
= g_ascii_strtod (s
, &endptr
);
3530 if (is_nan
|| errno
|| endptr
== s
|| *endptr
) {
3532 && (!strcmp (prop_name
, "Width") || !strcmp (prop_name
, "Height"))
3533 && (!g_ascii_strcasecmp (s
, "Auto") || is_nan
))
3547 l
= strtol (s
, &endptr
, 10);
3549 if (errno
|| endptr
== s
)
3552 *v
= new Value (l
, Type::INT64
);
3556 case Type::TIMESPAN
: {
3559 if (!time_span_from_str (s
, &ts
))
3562 *v
= new Value (ts
, Type::TIMESPAN
);
3569 if (IS_NULL_OR_EMPTY(s
))
3571 else if (g_ascii_isalpha (s
[0]) && prop_name
) {
3572 i
= enums_str_to_int (prop_name
, s
);
3574 // g_warning ("'%s' enum is not valid on '%s' property", str, prop_name);
3579 long l
= strtol (s
, &endptr
, 10);
3581 if (errno
|| endptr
== s
)
3592 gunichar unichar
= g_utf8_get_char_validated (str
, -1);
3595 if ((int) unichar
< 0)
3598 if (!(next
= g_utf8_next_char (str
)) || *next
!= '\0')
3601 *v
= new Value (unichar
, Type::CHAR
);
3605 case Type::STRING
: {
3606 *v
= new Value (str
);
3611 Color
*c
= color_from_str (s
);
3614 *v
= new Value (*c
);
3619 case Type::REPEATBEHAVIOR
: {
3620 RepeatBehavior rb
= RepeatBehavior::Forever
;
3622 if (!repeat_behavior_from_str (s
, &rb
))
3625 *v
= new Value (rb
);
3629 case Type::DURATION
: {
3630 Duration d
= Duration::Forever
;
3632 if (!duration_from_str (s
, &d
))
3639 case Type::KEYTIME
: {
3640 KeyTime kt
= KeyTime::Paced
;
3642 if (!keytime_from_str (s
, &kt
))
3645 *v
= new Value (kt
);
3649 case Type::KEYSPLINE
: {
3652 if (!key_spline_from_str (s
, &ks
))
3655 *v
= Value::CreateUnrefPtr (ks
);
3660 case Type::SOLIDCOLORBRUSH
: {
3661 // Only solid color brushes can be specified using attribute syntax
3662 Color
*c
= color_from_str (s
);
3667 SolidColorBrush
*scb
= new SolidColorBrush ();
3672 *v
= Value::CreateUnrefPtr (scb
);
3679 if (!Point::FromStr (s
, &p
))
3689 if (!Size::FromStr (s
, &size
))
3692 *v
= new Value (size
);
3699 if (!Rect::FromStr (s
, &rect
))
3702 *v
= new Value (rect
);
3706 case Type::CACHEMODE
: {
3707 if (!strcmp (s
, "BitmapCache")) {
3708 BitmapCache
*bc
= new BitmapCache ();
3709 *v
= Value::CreateUnrefPtr (bc
);
3717 if (!uri
.Parse (s
)) {
3721 *v
= new Value (uri
);
3725 case Type::DOUBLE_COLLECTION
: {
3726 DoubleCollection
*doubles
= DoubleCollection::FromStr (s
);
3728 *v
= Value::CreateUnrefPtr (new DoubleCollection ());
3733 *v
= Value::CreateUnrefPtr (doubles
);
3737 case Type::POINT_COLLECTION
: {
3738 PointCollection
*points
= PointCollection::FromStr (s
);
3740 *v
= Value::CreateUnrefPtr (new PointCollection ());
3745 *v
= Value::CreateUnrefPtr (points
);
3749 case Type::TRANSFORMGROUP
: {
3750 if (IS_NULL_OR_EMPTY(s
))
3753 Matrix
*mv
= matrix_from_str (s
);
3757 TransformGroup
*tg
= new TransformGroup ();
3758 MatrixTransform
*t
= new MatrixTransform ();
3759 t
->SetValue (MatrixTransform::MatrixProperty
, Value (mv
));
3761 tg
->GetChildren()->Add (t
);
3764 *v
= new Value (tg
);
3770 case Type::TRANSFORM
:
3772 if (!g_ascii_strcasecmp ("Identity", str
)) {
3778 // Intentional fall through, you can create a matrix from a TRANSFORM property, but not using Identity
3779 case Type::MATRIXTRANSFORM
:
3781 if (IS_NULL_OR_EMPTY(s
))
3784 Matrix
*mv
= matrix_from_str (s
);
3788 MatrixTransform
*t
= new MatrixTransform ();
3789 t
->SetValue (MatrixTransform::MatrixProperty
, Value (mv
));
3797 case Type::UNMANAGEDMATRIX
:
3798 case Type::MATRIX
: {
3799 // note: unlike TRANSFORM this creates an empty, identity, matrix for an empty string
3800 Matrix
*matrix
= matrix_from_str (s
);
3804 *v
= new Value (matrix
);
3809 case Type::PROJECTION
:
3811 if (!g_ascii_strcasecmp ("Identity", str
)) {
3817 // Intentional fall through, you can create a matrix from a PROJECTION property, but not using Identity
3818 case Type::MATRIX3DPROJECTION
:
3820 if (IS_NULL_OR_EMPTY(s
))
3823 Matrix3D
*mv
= matrix3d_from_str (s
);
3827 Matrix3DProjection
*p
= new Matrix3DProjection ();
3828 p
->SetValue (Matrix3DProjection::ProjectionMatrixProperty
, Value (mv
));
3836 case Type::UNMANAGEDMATRIX3D
:
3837 case Type::MATRIX3D
: {
3838 Matrix3D
*matrix
= matrix3d_from_str (s
);
3842 *v
= new Value (matrix
);
3847 case Type::PATHGEOMETRY
:
3848 case Type::GEOMETRY
: {
3849 Geometry
*geometry
= geometry_from_str (s
);
3854 *v
= new Value (geometry
);
3859 case Type::THICKNESS
: {
3862 if (!Thickness::FromStr (s
, &t
))
3869 case Type::CORNERRADIUS
: {
3872 if (!CornerRadius::FromStr (s
, &c
))
3879 case Type::GRIDLENGTH
: {
3880 GridLength grid_length
;
3882 if (!grid_length_from_str (s
, &grid_length
))
3885 *v
= new Value (grid_length
);
3889 case Type::IMAGESOURCE
:
3890 case Type::BITMAPIMAGE
: {
3896 BitmapImage
*bi
= new BitmapImage ();
3898 bi
->SetUriSource (&uri
);
3900 *v
= Value::CreateUnrefPtr (bi
);
3905 case Type::MULTISCALETILESOURCE
:
3906 case Type::DEEPZOOMIMAGETILESOURCE
: {
3907 // As far as I know the only thing you can create here is a URI based DeepZoomImageTileSource
3911 *v
= Value::CreateUnrefPtr (new DeepZoomImageTileSource (&uri
));
3916 case Type::FONTFAMILY
: {
3917 *v
= new Value (FontFamily (s
));
3921 case Type::FONTWEIGHT
: {
3922 int fw
= enums_str_to_int ("FontWeight", s
);
3924 *v
= new Value (FontWeight ((FontWeights
)fw
));
3929 case Type::FONTSTYLE
: {
3930 int fs
= enums_str_to_int ("FontStyle", s
);
3932 *v
= new Value (FontStyle ((FontStyles
)fs
));
3937 case Type::FONTSTRETCH
: {
3938 int fs
= enums_str_to_int ("FontStretch", s
);
3940 *v
= new Value (FontStretch ((FontStretches
)fs
));
3945 case Type::PROPERTYPATH
: {
3946 PropertyPath
path (s
);
3947 path
.expanded_path
= expand_property_path (p
, &path
);
3948 *v
= new Value (path
);
3953 // we don't care about NULL or empty values
3954 if (!IS_NULL_OR_EMPTY (s
)) {
3965 XamlElementInstance::TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
)
3967 const char* prop_name
= info
->GetContentProperty (p
);
3972 DependencyProperty
*dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, info
->GetKind ()), prop_name
);
3976 bool is_collection
= Type::IsSubclassOf (p
->deployment
, dep
->GetPropertyType(), Type::DEPENDENCY_OBJECT_COLLECTION
);
3978 if (!is_collection
&& Type::IsSubclassOf (p
->deployment
, value
->info
->GetKind (), dep
->GetPropertyType())) {
3980 if (!item
->SetValueWithError (dep
, value
->GetAsValue (), &err
)) {
3981 parser_error (p
, value
->element_name
, NULL
, err
.code
, err
.message
);
3987 // We only want to enter this if statement if we are NOT dealing with the content property element,
3988 // otherwise, attempting to use explicit property setting, would add the content property element
3989 // to the content property element collection
3990 if (is_collection
&& dep
->GetPropertyType() != value
->info
->GetKind ()) {
3991 Value
*col_v
= item
->GetValue (dep
);
3995 col
= collection_new (dep
->GetPropertyType ());
3996 item
->SetValue (dep
, Value (col
));
3999 col
= (Collection
*) col_v
->AsCollection ();
4003 if (-1 == col
->AddWithError (value
->GetAsValue (), &err
)) {
4004 parser_error (p
, value
->element_name
, NULL
, err
.code
, err
.message
);
4015 XamlElementInstance::TrySetContentProperty (XamlParserInfo
*p
, const char *value
)
4017 const char* prop_name
= info
->GetContentProperty (p
);
4020 if (info
->GetKind () == Type::ICON
) {
4021 prop_name
= "Source";
4026 Type::Kind prop_type
= p
->current_element
->info
->GetKind ();
4027 DependencyProperty
*content
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, prop_type
), prop_name
);
4029 // TODO: There might be other types that can be specified here,
4030 // but string is all i have found so far. If you can specify other
4031 // types, i should pull the property setting out of set_attributes
4032 // and use that code
4034 if (content
&& (content
->GetPropertyType ()) == Type::STRING
&& value
) {
4035 item
->SetValue (content
, Value (g_strstrip (p
->cdata
->str
)));
4037 } else if (content
&& (content
->GetPropertyType ()) == Type::URI
&& value
) {
4040 if (!uri
.Parse (g_strstrip (p
->cdata
->str
)))
4043 item
->SetValue (content
, Value (uri
));
4045 } else if (Type::IsSubclassOf (p
->deployment
, info
->GetKind (), Type::TEXTBLOCK
)) {
4046 TextBlock
*textblock
= (TextBlock
*) item
;
4047 InlineCollection
*inlines
= textblock
->GetInlines ();
4048 Inline
*last
= NULL
;
4050 if (inlines
&& inlines
->GetCount () > 0)
4051 last
= inlines
->GetValueAt (inlines
->GetCount () - 1)->AsInline ();
4053 if (!p
->cdata_content
) {
4054 if (p
->next_element
&& !strcmp (p
->next_element
, "Run") && last
&& last
->GetObjectType () == Type::RUN
&&
4055 !last
->GetAutogenerated ()) {
4056 // LWSP between <Run> elements is to be treated as a single-SPACE <Run> element
4057 // Note: p->cdata is already canonicalized
4059 // This is one of the following cases:
4061 // 1. LWSP before the first <Run> element
4062 // 2. LWSP after the last <Run> element
4063 // 3. LWSP between <Run> and <LineBreak> elements
4067 if (!p
->next_element
|| !strcmp (p
->next_element
, "LineBreak"))
4068 g_strchomp (p
->cdata
->str
);
4070 if (!last
|| last
->GetObjectType () != Type::RUN
|| last
->GetAutogenerated ())
4071 g_strchug (p
->cdata
->str
);
4074 Run
*run
= new Run ();
4075 run
->SetText (p
->cdata
->str
);
4078 inlines
= new InlineCollection ();
4079 textblock
->SetInlines (inlines
);
4092 XamlElementInstance::SetUnknownAttribute (XamlParserInfo
*p
, const char *name
, const char *value
)
4097 Value v
= Value (value
);
4098 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, name
, &v
, NULL
)) {
4105 XamlElementInstance::SetDelayedProperties (XamlParserInfo
*p
)
4107 GSList
*walk
= delayed_properties
;
4110 DelayedProperty
*prop
= (DelayedProperty
*) walk
->data
;
4112 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), prop
->xmlns
, prop
->name
, prop
->value
, NULL
, XamlCallbackData::SETTING_DELAYED_PROPERTY
)) {
4113 parser_error (p
, element_name
, prop
->name
, 2012,
4114 "Unknown property %s on element %s.",
4115 prop
->name
, element_name
);
4125 XamlElementInstance::FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
)
4127 // We didn't find anything so try looking up in managed
4131 Value
*v
= new Value ();
4132 if (p
->loader
->LookupObject (p
, p
->GetTopElementPtr (), GetAsValue (), p
->current_namespace
->GetUri (), el
, false, true, v
)) {
4133 char *type_name
= g_strndup (el
, dot
- el
);
4135 XamlElementInfoManaged
*res
= new XamlElementInfoManaged (g_strdup (p
->current_namespace
->GetUri ()), el
, info
, v
->GetKind (), v
);
4136 XamlElementInfo
*container
= p
->current_namespace
->FindElement (p
, type_name
, NULL
, false);
4137 info
->SetPropertyOwnerKind (container
->GetKind ());
4146 static XamlElementInfo
*
4147 create_element_info_from_imported_managed_type (XamlParserInfo
*p
, const char *name
, const char **attr
, bool create
)
4152 char* type_name
= NULL
;
4153 char* type_xmlns
= NULL
;
4154 const char* use_xmlns
= NULL
;
4157 // We might have an x:Class attribute specified, so we need to use that for the
4158 // type_name that we pass to LookupObject
4159 if (strcmp ("Application", name
)) {
4160 type_name
= x_namespace
->FindTypeName (attr
, &type_xmlns
);
4163 use_xmlns
= type_xmlns
;
4165 if (!p
->hydrating
) {
4166 parser_error (p
, name
, "x:Class", 4005, "Cannot specify x:Class in xaml files outside of a xap.");
4173 Value
*v
= new Value ();
4174 if (!p
->loader
->LookupObject (p
, use_xmlns
? p
->GetTopElementPtr () : NULL
, NULL
, use_xmlns
, name
, create
, false, v
)) {
4179 g_free (type_xmlns
);
4183 XamlElementInfoImportedManaged
*info
= new XamlElementInfoImportedManaged (g_strdup (name
), NULL
, v
);
4186 if (v
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4187 p
->AddCreatedElement (v
->AsDependencyObject());
4195 XamlElementInfoNative::GetContentProperty (XamlParserInfo
*p
)
4197 return type
->GetContentPropertyName ();
4200 XamlElementInstance
*
4201 XamlElementInfoNative::CreateElementInstance (XamlParserInfo
*p
)
4203 if (type
->IsValueType ())
4204 return new XamlElementInstanceValueType (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4205 else if (type
->IsSubclassOf (Type::FRAMEWORKTEMPLATE
))
4206 return new XamlElementInstanceTemplate (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4208 return new XamlElementInstanceNative (this, p
, GetName (), XamlElementInstance::ELEMENT
);
4211 XamlElementInstance
*
4212 XamlElementInfoNative::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4214 XamlElementInstance
*res
= new XamlElementInstanceNative (this, p
, GetName (), XamlElementInstance::ELEMENT
, false);
4215 res
->SetDependencyObject (o
->AsDependencyObject ());
4221 XamlElementInstanceNative::FindPropertyElement (XamlParserInfo
*p
, const char *el
, const char *dot
)
4223 if (IsDependencyObject ()) {
4224 const char *prop_name
= dot
+ 1;
4225 DependencyProperty
*prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, info
->GetKind ()), prop_name
);
4227 XamlElementInfoNative
*info
= new XamlElementInfoNative (Type::Find (p
->deployment
, prop
->GetPropertyType ()));
4228 info
->SetPropertyOwnerKind (prop
->GetOwnerType ());
4233 return XamlElementInstance::FindPropertyElement (p
, el
, dot
);
4236 XamlElementInstance
*
4237 XamlElementInfoNative::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4239 return new XamlElementInstanceNative (this, p
, name
, XamlElementInstance::PROPERTY
, false);
4242 XamlElementInstanceNative::XamlElementInstanceNative (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
, bool create_item
) :
4243 XamlElementInstance (element_info
, name
, type
)
4245 this->element_info
= element_info
;
4246 this->parser_info
= parser_info
;
4248 SetDependencyObject (CreateItem ());
4254 XamlElementInstanceNative::CreateItem ()
4256 XamlElementInstance
*walk
= parser_info
->current_element
;
4257 Type
*type
= element_info
->GetType ();
4259 DependencyObject
*item
= NULL
;
4260 DependencyProperty
*dep
= NULL
;
4262 if (type
->IsSubclassOf (Type::COLLECTION
) || type
->IsSubclassOf (Type::RESOURCE_DICTIONARY
)) {
4263 // If we are creating a collection, try walking up the element tree,
4264 // to find the parent that we belong to and using that instance for
4265 // our collection, instead of creating a new one
4267 // We attempt to advance past the property setter, because we might be dealing with a
4270 if (walk
&& walk
->element_type
== XamlElementInstance::PROPERTY
) {
4271 char **prop_name
= g_strsplit (walk
->element_name
, ".", -1);
4273 walk
= walk
->parent
;
4274 dep
= DependencyProperty::GetDependencyProperty (Type::Find (parser_info
->deployment
, walk
->info
->GetKind ()), prop_name
[1]);
4276 g_strfreev (prop_name
);
4277 } else if (walk
&& walk
->info
->GetContentProperty (parser_info
)) {
4278 dep
= DependencyProperty::GetDependencyProperty (Type::Find (parser_info
->deployment
, walk
->info
->GetKind ()),
4279 (char *) walk
->info
->GetContentProperty (parser_info
));
4282 if (dep
&& Type::IsSubclassOf (parser_info
->deployment
, dep
->GetPropertyType(), type
->GetKind ())) {
4283 Value
*v
= ((DependencyObject
* ) walk
->GetAsDependencyObject ())->GetValue (dep
);
4285 item
= v
->AsDependencyObject ();
4288 // note: if !v then the default collection is NULL (e.g. PathFigureCollection)
4293 item
= element_info
->GetType()->IsCtorVisible() ? element_info
->GetType ()->CreateInstance () : NULL
;
4296 parser_info
->AddCreatedElement (item
);
4298 // in case we must store the collection into the parent
4299 if (dep
&& dep
->GetPropertyType() == type
->GetKind ()) {
4301 Value
item_value (item
);
4302 if (!((DependencyObject
* ) walk
->GetAsDependencyObject ())->SetValueWithError (dep
, &item_value
, &err
))
4303 parser_error (parser_info
, element_name
, NULL
, err
.code
, err
.message
);
4306 parser_error (parser_info
, element_name
, NULL
, 2007, "Unknown element: %s.", element_name
);
4314 XamlElementInstanceNative::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
)
4316 if (property
->info
->RequiresManagedSet () || value
->info
->RequiresManagedSet ())
4317 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, value
->GetAsValue (), NULL
);
4319 return dependency_object_set_property (p
, this, property
, value
, true);
4323 XamlElementInstanceNative::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
)
4325 char **prop_name
= g_strsplit (property
->element_name
, ".", -1);
4326 Type
*owner
= Type::Find (p
->deployment
, prop_name
[0]);
4327 DependencyProperty
*dep
;
4332 dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, owner
->GetKind ()), prop_name
[1]);
4336 return xaml_set_property_from_str (item
, dep
, value
, NULL
/*XXX*/);
4340 XamlElementInstanceNative::AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
)
4342 dependency_object_add_child (p
, this, child
, true);
4346 XamlElementInstanceNative::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4348 dependency_object_set_attributes (p
, this, attr
);
4352 XamlElementInstanceValueType::XamlElementInstanceValueType (XamlElementInfoNative
*element_info
, XamlParserInfo
*parser_info
, const char *name
, ElementType type
) :
4353 XamlElementInstance (element_info
, name
, type
)
4355 this->element_info
= element_info
;
4356 this->parser_info
= parser_info
;
4360 XamlElementInstanceValueType::CreateValueItemFromString (const char* str
)
4363 bool res
= value_from_str (element_info
->GetType ()->GetKind (), NULL
, str
, &value
);
4368 XamlElementInstanceValueType::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4370 value_type_set_attributes (p
, this, attr
);
4373 XamlElementInstanceEnum::XamlElementInstanceEnum (XamlElementInfoEnum
*element_info
, const char *name
, ElementType type
) :
4374 XamlElementInstance (element_info
, name
, type
)
4379 XamlElementInstanceEnum::CreateEnumFromString (const char* str
)
4381 int i
= enums_str_to_int (element_name
, str
);
4385 value
= new Value (i
);
4390 XamlElementInstanceEnum::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4392 value_type_set_attributes (p
, this, attr
);
4395 XamlElementInstance
*
4396 XamlElementInfoEnum::CreateElementInstance (XamlParserInfo
*p
)
4398 return new XamlElementInstanceEnum (this, name
, XamlElementInstance::ELEMENT
);
4401 XamlElementInstance
*
4402 XamlElementInfoEnum::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4404 XamlElementInstance
*res
= new XamlElementInstanceEnum (this, name
, XamlElementInstance::ELEMENT
);
4409 XamlElementInfoManaged::GetContentProperty (XamlParserInfo
*p
)
4414 // TODO: We could cache this, but for now lets keep things as simple as possible.
4415 const char *res
= p
->loader
->GetContentPropertyName (p
, p
->GetTopElementPtr (), obj
);
4418 return XamlElementInfo::GetContentProperty (p
);
4421 XamlElementInstance
*
4422 XamlElementInfoManaged::CreateElementInstance (XamlParserInfo
*p
)
4424 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, GetName (), XamlElementInstance::ELEMENT
, obj
);
4426 if (obj
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4427 p
->AddCreatedElement (inst
->GetAsDependencyObject ());
4432 XamlElementInstance
*
4433 XamlElementInfoManaged::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4435 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, GetName (), XamlElementInstance::ELEMENT
, o
);
4440 XamlElementInstance
*
4441 XamlElementInfoManaged::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4443 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::PROPERTY
, obj
);
4448 XamlElementInstanceManaged::XamlElementInstanceManaged (XamlElementInfo
*info
, const char *name
, ElementType type
, Value
*obj
) :
4449 XamlElementInstance (info
, name
, type
)
4451 // The managed code owns our Value objects
4452 cleanup_value
= false;
4456 if (obj
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
)) {
4457 this->is_dependency_object
= true;
4458 this->SetDependencyObject (obj
->AsDependencyObject ());
4461 this->is_dependency_object
= false;
4465 XamlElementInstanceManaged::GetManagedPointer ()
4467 if (value
->Is (Deployment::GetCurrent (), Type::DEPENDENCY_OBJECT
))
4468 return value
->AsDependencyObject ();
4469 return value
->AsManagedObject ();
4473 XamlElementInstanceManaged::GetParentPointer ()
4475 XamlElementInstance
*walk
= parent
;
4476 while (walk
&& walk
->element_type
!= XamlElementInstance::ELEMENT
)
4477 walk
= walk
->parent
;
4483 return walk
->GetAsValue ();
4487 XamlElementInstanceManaged::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, XamlElementInstance
*value
)
4489 if (GetAsDependencyObject () != NULL
&& dependency_object_set_property (p
, this, property
, value
, false))
4491 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, value
->GetAsValue (), value
);
4495 XamlElementInstanceManaged::SetProperty (XamlParserInfo
*p
, XamlElementInstance
*property
, const char *value
)
4497 Value v
= Value (value
);
4498 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), property
->info
->xmlns
, property
->element_name
, &v
, NULL
);
4502 XamlElementInstanceManaged::AddChild (XamlParserInfo
*p
, XamlElementInstance
*child
)
4504 if (element_type
== XamlElementInstance::PROPERTY
) {
4505 Value
*prop
= new Value (element_name
);
4506 p
->loader
->AddChild (p
, p
->GetTopElementPtr (), GetParentPointer (), true, info
->xmlns
, prop
, this, child
->GetAsValue (), child
);
4511 p
->loader
->AddChild (p
, p
->GetTopElementPtr (), GetParentPointer (), false, info
->xmlns
, GetAsValue (), this, child
->GetAsValue (), child
);
4515 XamlElementInstanceManaged::SetAttributes (XamlParserInfo
*p
, const char **attr
)
4517 dependency_object_set_attributes (p
, this, attr
);
4521 XamlElementInstanceManaged::TrySetContentProperty (XamlParserInfo
*p
, XamlElementInstance
*value
)
4523 Value
*v
= value
->GetAsValue ();
4524 const char* prop_name
= info
->GetContentProperty (p
);
4526 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, prop_name
, v
, value
);
4530 XamlElementInstanceManaged::TrySetContentProperty (XamlParserInfo
*p
, const char *value
)
4532 if (Type::IsSubclassOf (p
->deployment
, info
->GetKind (), Type::CONTENTCONTROL
)) {
4533 // Content controls are not allowed to have their content set as text, they need to have a child element
4534 // if you want to set the content of a contentcontrol to text you need to use attribute syntax
4538 if (!XamlElementInstance::TrySetContentProperty (p
, value
)) {
4539 const char* prop_name
= info
->GetContentProperty (p
);
4540 if (!p
->cdata_content
)
4542 Value v
= Value (value
);
4543 bool res
= p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), info
->xmlns
, GetAsValue (), this, GetParentPointer (), NULL
, prop_name
, &v
, NULL
);
4550 XamlElementInstance
*
4551 XamlElementInfoImportedManaged::CreateElementInstance (XamlParserInfo
*p
)
4553 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::ELEMENT
, obj
);
4559 XamlElementInfoImportedManaged::GetContentProperty (XamlParserInfo
*p
)
4564 // TODO: Test, it's possible that managed objects that aren't DOs are allowed to have content properties.
4565 if (!obj
->Is (p
->deployment
, Type::DEPENDENCY_OBJECT
))
4566 return XamlElementInfo::GetContentProperty (p
);
4569 // TODO: We could cache this, but for now lets keep things as simple as possible.
4570 const char *res
= p
->loader
->GetContentPropertyName (p
, p
->GetTopElementPtr (), obj
);
4574 return XamlElementInfo::GetContentProperty (p
);
4577 XamlElementInstance
*
4578 XamlElementInfoImportedManaged::CreateWrappedElementInstance (XamlParserInfo
*p
, Value
*o
)
4580 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, Type::Find (p
->deployment
, o
->GetKind ())->GetName (), XamlElementInstance::ELEMENT
, o
);
4585 XamlElementInstance
*
4586 XamlElementInfoImportedManaged::CreatePropertyElementInstance (XamlParserInfo
*p
, const char *name
)
4588 XamlElementInstanceManaged
*inst
= new XamlElementInstanceManaged (this, name
, XamlElementInstance::PROPERTY
, obj
);
4599 get_key_from_child (XamlElementInstance
*child
)
4601 const char *key
= child
->GetKey ();
4605 key
= child
->GetName ();
4609 if (child
->IsDependencyObject ()) {
4610 DependencyObject
*c
= child
->GetAsDependencyObject();
4612 if (Type::IsSubclassOf (c
->GetDeployment (), Type::STYLE
, child
->info
->GetKind ())) {
4613 Value
*v
= c
->GetValue (Style::TargetTypeProperty
);
4614 if (v
&& v
->GetKind () == Type::MANAGEDTYPEINFO
)
4615 key
= v
->AsManagedTypeInfo ()->full_name
;
4626 dependency_object_add_child (XamlParserInfo
*p
, XamlElementInstance
*parent
, XamlElementInstance
*child
, bool fail_if_no_prop
)
4628 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4629 if (parent
->element_type
== XamlElementInstance::PROPERTY
) {
4631 if (parent
->info
->RequiresManagedSet ())
4634 char **prop_name
= g_strsplit (parent
->element_name
, ".", -1);
4635 Type
*owner
= types
->Find (prop_name
[0]);
4638 DependencyProperty
*dep
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, owner
->GetKind ()), prop_name
[1]);
4640 g_strfreev (prop_name
);
4643 g_warning ("Unknown element: %s.", parent
->element_name
);
4644 if (fail_if_no_prop
)
4645 parser_error (p
, parent
->element_name
, NULL
, 2007, "Unknown element: %s.", parent
->element_name
);
4649 // XamlElementInfoEnum has Type::INVALID as
4650 // its kind, which is why that first check is
4652 if (child
->info
->GetKind() != Type::MANAGED
&&
4653 !types
->Find (child
->info
->GetKind())->IsCtorVisible()) {
4654 // we can't instantiate this type
4655 return parser_error (p
, child
->element_name
, NULL
, 2007,
4656 "Unknown element: %s.", child
->element_name
);
4659 // Don't add the child element, if it is the entire collection
4660 if (dep
->GetPropertyType() == child
->info
->GetKind ())
4663 Type::Kind prop_type
= dep
->GetPropertyType ();
4664 if (!types
->IsSubclassOf (prop_type
, Type::DEPENDENCY_OBJECT_COLLECTION
)
4665 && !types
->IsSubclassOf (prop_type
, Type::RESOURCE_DICTIONARY
))
4668 // Most common case, we will have a parent that we can snag the collection from
4669 DependencyObject
*obj
= (DependencyObject
*) parent
->parent
->GetAsDependencyObject ();
4673 Value
*col_v
= obj
->GetValue (dep
);
4675 Type
*col_type
= types
->Find (prop_type
);
4676 DependencyObject
*c_obj
= col_type
->CreateInstance ();
4677 obj
->SetValue (dep
, Value::CreateUnrefPtr (c_obj
));
4678 col_v
= obj
->GetValue (dep
);
4681 Collection
*col
= col_v
->AsCollection ();
4684 if (types
->IsSubclassOf (prop_type
, Type::DEPENDENCY_OBJECT_COLLECTION
)) {
4685 Value
child_val (child
->GetAsDependencyObject ());
4686 if (-1 == col
->AddWithError (&child_val
, &err
))
4687 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4689 else if (types
->IsSubclassOf (prop_type
, Type::RESOURCE_DICTIONARY
)) {
4690 ResourceDictionary
*dict
= (ResourceDictionary
*)col
;
4692 const char *key
= get_key_from_child (child
);
4695 // XXX don't know the proper values here...
4696 return parser_error (p
, child
->element_name
, NULL
, 2007,
4697 "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
4700 Value
*child_as_value
= child
->GetAsValue ();
4702 if (!child_as_value
) {
4703 // XXX don't know the proper values here...
4704 return parser_error (p
, child
->element_name
, NULL
, 2007,
4705 "Error adding child to ResourceDictionary");
4708 bool added
= dict
->AddWithError (key
, child_as_value
, &err
);
4710 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4719 if (types
->IsSubclassOf (parent
->info
->GetKind (), Type::DEPENDENCY_OBJECT_COLLECTION
)) {
4720 Collection
*col
= (Collection
*) parent
->GetAsDependencyObject ();
4722 Value
child_val ((DependencyObject
*)child
->GetAsDependencyObject ());
4724 if (-1 == col
->AddWithError (&child_val
, &err
))
4725 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4728 else if (types
->IsSubclassOf (parent
->info
->GetKind (), Type::RESOURCE_DICTIONARY
)) {
4729 ResourceDictionary
*dict
= (ResourceDictionary
*) parent
->GetAsDependencyObject ();
4732 const char *key
= get_key_from_child (child
);
4735 // XXX don't know the proper values here...
4736 return parser_error (p
, child
->element_name
, NULL
, 2007,
4737 "You must specify an x:Key or x:Name for elements in a ResourceDictionary");
4740 Value
*child_as_value
= child
->GetAsValue ();
4741 bool added
= dict
->AddWithError (key
, child_as_value
, &err
);
4743 return parser_error (p
, child
->element_name
, NULL
, err
.code
, err
.message
);
4747 if (parent
->element_type
!= XamlElementInstance::PROPERTY
) {
4748 parent
->TrySetContentProperty (p
, child
);
4751 // Do nothing if we aren't adding to a collection, or a content property collection
4756 /// set property funcs
4759 // these are just a bunch of special cases
4761 dependency_object_missed_property (XamlElementInstance
*item
, XamlElementInstance
*prop
, XamlElementInstance
*value
, char **prop_name
)
4767 set_managed_attached_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*prop
, XamlElementInstance
*value
)
4772 return p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), item
->info
->xmlns
, item
->GetAsValue (), item
, item
->GetParentPointer (), prop
->info
->xmlns
, prop
->element_name
, value
->GetAsValue (), value
);
4776 dependency_object_set_property (XamlParserInfo
*p
, XamlElementInstance
*item
, XamlElementInstance
*property
, XamlElementInstance
*value
, bool raise_errors
)
4778 char **prop_name
= g_strsplit (property
->element_name
, ".", -1);
4779 DependencyObject
*dep
= item
->GetAsDependencyObject ();
4780 DependencyProperty
*prop
= NULL
;
4782 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4784 if (types
->Find (item
->info
->GetKind ())->IsValueType ()) {
4785 if (raise_errors
) parser_error (p
, item
->element_name
, NULL
, -1, "Value types (%s) do not have properties.", property
->element_name
);
4786 g_strfreev (prop_name
);
4790 if (types
->Find (property
->info
->GetPropertyOwnerKind ())->IsCustomType ()) {
4791 g_strfreev (prop_name
);
4792 return set_managed_attached_property (p
, item
, property
, value
);
4796 // FIXME is this really where this check should live
4798 parser_error (p
, item
->element_name
, NULL
, 2030,
4799 "Property element %s cannot be used inside another property element.",
4800 property
->element_name
);
4802 g_strfreev (prop_name
);
4806 prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, item
->info
->GetKind ()), prop_name
[1]);
4809 if (prop
->IsReadOnly ()) {
4811 parser_error (p
, item
->element_name
, NULL
, 2014,
4812 "The attribute %s is read only and cannot be set.", prop
->GetName ());
4814 } else if (types
->IsSubclassOf (value
->info
->GetKind (), prop
->GetPropertyType())) {
4815 // an empty collection can be NULL and valid
4816 if (item
->IsPropertySet (prop
->GetName())) {
4818 parser_error (p
, item
->element_name
, NULL
, 2033,
4819 "Cannot specify the value multiple times for property: %s.",
4820 property
->element_name
);
4825 // HACK - since the Setter is added to the collection *before* its properties are set
4826 // we find ourselves with a sealed Setter - which should not be possible at the parse time
4827 SetterBase
*sb
= NULL
;
4828 if (types
->IsSubclassOf (dep
->GetObjectType (), Type::SETTERBASE
)) {
4829 sb
= (SetterBase
*) dep
;
4830 sb
->SetIsSealed (false);
4833 if (!is_managed_kind (value
->info
->GetKind ()) && !value
->info
->RequiresManagedSet()) {
4834 if (!dep
->SetValueWithError (prop
, value
->GetAsValue (), &err
)) {
4836 parser_error (p
, item
->element_name
, NULL
, err
.code
, err
.message
);
4842 if (!p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, item
->GetAsValue (), item
, item
->GetParentPointer (), NULL
, prop_name
[1], value
->GetAsValue (), NULL
)) {
4844 parser_error (p
, item
->element_name
, NULL
, err
.code
, err
.message
);
4851 // re-seal the Setter (end-HACK)
4853 sb
->SetIsSealed (true);
4855 item
->MarkPropertyAsSet (prop
->GetName());
4858 } else if (types
->IsSubclassOf (prop
->GetPropertyType (), Type::COLLECTION
) || types
->IsSubclassOf (prop
->GetPropertyType (), Type::RESOURCE_DICTIONARY
)) {
4859 // The items were added in add_child
4863 parser_error (p
, item
->element_name
, NULL
, 2010, "does not support %s as content.", value
->element_name
);
4867 dependency_object_missed_property (item
, property
, value
, prop_name
);
4872 g_strfreev (prop_name
);
4877 xaml_set_property_from_str (DependencyObject
*obj
, DependencyProperty
*prop
, const char *value
, MoonError
*error
)
4882 if (!value_from_str (prop
->GetPropertyType(), prop
->GetName(), value
, &v
))
4885 // it's possible for (a valid) value to be NULL (and we must keep the default value)
4887 rv
= obj
->SetValueWithError (prop
, v
, error
);
4895 xaml_is_valid_event_name (Deployment
*deployment
, Type::Kind kind
, const char *name
, bool allow_desktop_events
)
4897 Type
*type
= Type::Find (deployment
, kind
);
4901 int event_id
= type
->LookupEvent (name
);
4905 if (!allow_desktop_events
|| (moonlight_flags
& RUNTIME_INIT_DESKTOP_EXTENSIONS
) == 0) {
4906 // if we're not allowing desktop-only events, or if the user hasn't allowed them,
4907 // return false if the name corresponds to one of them.
4908 if (!strcmp (name
, "MouseRightButtonDown") ||
4909 !strcmp (name
, "MouseRightButtonUp") ||
4910 !strcmp (name
, "MouseWheel"))
4918 value_type_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
)
4920 // the only attributes value on value types seem to be x:Key
4921 // and x:Name, but reuse the generic namespace attribute stuff
4924 for (int i
= 0; attr
[i
]; i
+= 2) {
4926 if (attr
[i
+ 1] == NULL
|| attr
[i
+ 1][0] == '\0')
4929 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4931 if (attr_name
[1]) {
4933 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
4936 return parser_error (p
, item
->element_name
, attr
[i
], 7055, "undeclared prefix");
4938 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
4940 g_strfreev (attr_name
);
4942 // Setting managed attributes can cause errors galore
4949 g_strfreev (attr_name
);
4954 dependency_object_set_attributes (XamlParserInfo
*p
, XamlElementInstance
*item
, const char **attr
)
4956 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
4957 GList
*delay_att
= NULL
;
4959 for (int i
= 0; attr
[i
]; i
+= 2) {
4964 // Setting attributes like x:Class can change item->item, so we
4965 // need to make sure we have an up to date pointer
4966 DependencyObject
*dep
= item
->GetAsDependencyObject ();
4967 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
4969 if (attr_name
[1]) {
4970 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
4972 if (ns
!= x_namespace
) {
4973 delay_att
= g_list_append (delay_att
, GINT_TO_POINTER (i
));
4974 g_strfreev (attr_name
);
4979 g_strfreev (attr_name
);
4980 return parser_error (p
, item
->element_name
, attr
[i
], 5055, "undeclared prefix");
4983 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
4985 g_strfreev (attr_name
);
4987 // Setting managed attributes can cause errors galore
4994 g_strfreev (attr_name
);
4996 const char *pname
= attr
[i
];
4997 char *atchname
= NULL
;
4998 for (int a
= 0; attr
[i
][a
]; a
++) {
4999 if (attr
[i
][a
] != '.')
5001 atchname
= g_strndup (attr
[i
], a
);
5002 pname
= attr
[i
] + a
+ 1;
5006 DependencyProperty
*prop
= NULL
;
5008 Type
*attached_type
= types
->Find (atchname
);
5010 prop
= DependencyProperty::GetDependencyProperty (attached_type
, pname
);
5012 prop
= DependencyProperty::GetDependencyProperty (Type::Find (p
->deployment
, item
->info
->GetKind ()), pname
);
5016 if (prop
->GetId () == DependencyObject::NameProperty
) {
5018 if (item
->GetName ()) {
5019 parser_error (p
, item
->element_name
, NULL
, 2016, "Cannot specify both Name and x:Name attributes.");
5023 // XXX toshok - I don't like doing this here... but it fixes airlines.
5024 item
->SetKey (p
, attr
[i
+1]);
5026 NameScope
*scope
= p
->namescope
;
5027 if (!item
->GetAsDependencyObject ()->SetName (attr
[i
+1], scope
)) {
5028 parser_error (p
, item
->element_name
, NULL
, 2028,
5029 "The name already exists in the tree: %s.", attr
[i
+1]);
5031 g_list_free (delay_att
);
5037 if (prop
->IsReadOnly ()) {
5038 parser_error (p
, item
->element_name
, NULL
, 2014,
5039 "The attribute %s is read only and cannot be set.", prop
->GetName ());
5041 g_list_free (delay_att
);
5045 if (item
->IsPropertySet (prop
->GetName())) {
5046 parser_error (p
, item
->element_name
, attr
[i
], 2033,
5047 "Cannot specify the value multiple times for property: %s.", prop
->GetName ());
5049 g_list_free (delay_att
);
5055 char *attr_value
= g_strdup (attr
[i
+1]);
5057 bool need_managed
= false;
5058 if (attr
[i
+1][0] == '{') {
5059 if (attr
[i
+1][1] == '}') {
5060 // {} is an escape sequence so you can have strings like {StaticResource}
5061 char *nv
= attr_value
;
5062 attr_value
= g_strdup (attr_value
+ 2);
5065 else if (attr
[i
+1][strlen(attr
[i
+1]) - 1] == '}') {
5066 need_managed
= true;
5070 if (!need_managed
) {
5071 if (!value_from_str_with_parser (p
, prop
->GetPropertyType(), prop
->GetName(), attr_value
, &v
, &v_set
)) {
5073 g_free (attr_value
);
5078 Type::Kind propKind
= prop
->GetPropertyType ();
5080 if (need_managed
|| is_managed_kind (propKind
) || types
->Find (prop
->GetOwnerType ())->IsCustomType () || (v
&& is_managed_kind (v
->GetKind ()))) {
5081 bool str_value
= false;
5083 v
= new Value (attr
[i
+ 1]); // Note that we passed the non escaped value, not attr_value
5088 // printf ("setting managed property: %s::%s to %s=%s\n", dep->GetType ()->GetName (), prop->GetName (), attr [i], attr [i + 1]);
5089 if (p
->loader
->SetProperty (p
, p
->GetTopElementPtr (), NULL
, item
->GetAsValue (), item
, item
->GetParentPointer (), NULL
, g_strdup (attr
[i
]), v
, NULL
)) {
5091 g_free (attr_value
);
5098 if (!value_from_str_with_parser (p
, prop
->GetPropertyType(), prop
->GetName(), attr_value
, &v
, &v_set
)) {
5100 g_free (attr_value
);
5107 if (!v_set
&& !value_is_explicit_null (attr
[i
+ 1])) { // Check the non escaped value
5108 parser_error (p
, item
->element_name
, attr
[i
], 2024, "Invalid attribute value %s for property %s.", attr
[i
+1], attr
[i
]);
5110 g_free (attr_value
);
5112 g_list_free (delay_att
);
5117 // 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 ());
5118 if (!dep
->SetValueWithError (prop
, v
, &err
))
5119 parser_error (p
, item
->element_name
, attr
[i
], err
.code
, err
.message
);
5121 item
->MarkPropertyAsSet (prop
->GetName());
5124 g_free (attr_value
);
5126 delay_att
= g_list_append (delay_att
, GINT_TO_POINTER (i
));
5133 GList
*walk
= g_list_first (delay_att
);
5135 int i
= GPOINTER_TO_INT (walk
->data
);
5140 char **attr_name
= g_strsplit (attr
[i
], "|", -1);
5142 if (attr_name
[1]) {
5143 XamlNamespace
*ns
= (XamlNamespace
*) g_hash_table_lookup (p
->namespace_map
, attr_name
[0]);
5145 if (ns
== x_namespace
) {
5146 // Skip these, they are handled earlier
5147 g_strfreev (attr_name
);
5152 g_strfreev (attr_name
);
5153 parser_error (p
, item
->element_name
, attr
[i
], 5055, "undeclared prefix");
5157 ns
->SetAttribute (p
, item
, attr_name
[1], attr
[i
+ 1]);
5159 g_strfreev (attr_name
);
5161 // Setting managed attributes can cause errors galore
5165 if (!item
->SetUnknownAttribute (p
, attr
[i
], attr
[i
+ 1])) {
5166 parser_error (p
, item
->element_name
, attr
[i
], 2012,
5167 "Unknown attribute %s on element %s.",
5168 attr
[i
], item
->element_name
);
5176 g_list_free (delay_att
);
5181 lookup_named_item (XamlElementInstance
*top
, const char *name
)
5183 Types
*types
= Deployment::GetCurrent ()->GetTypes ();
5184 XamlElementInstance
*inst
= top
;
5187 if (inst
->element_type
== XamlElementInstance::ELEMENT
) {
5188 ResourceDictionary
*rd
= NULL
;
5189 Type::Kind kind
= inst
->info
->GetKind ();
5191 if (types
->IsSubclassOf (kind
, Type::FRAMEWORKELEMENT
)) {
5192 rd
= inst
->GetAsDependencyObject ()->GetValue (UIElement::ResourcesProperty
)->AsResourceDictionary ();
5193 } else if (types
->IsSubclassOf (kind
, Type::RESOURCE_DICTIONARY
)) {
5194 rd
= (ResourceDictionary
*) inst
->GetAsDependencyObject ();
5199 Value
*res
= lookup_resource_dictionary (rd
, name
, &exists
);
5205 inst
= inst
->parent
;
5212 lookup_resource_dictionary (ResourceDictionary
*rd
, const char *name
, bool *exists
)
5215 Value
*resource_value
= rd
->Get (name
, exists
);
5216 return *exists
? new Value (*resource_value
) : NULL
;
5220 xaml_lookup_named_item (void *parser
, void *instance
, const char* name
)
5222 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
5223 XamlElementInstance
*inst
= (XamlElementInstance
*) instance
;
5227 res
= lookup_named_item (inst
, name
);
5229 XamlContext
*context
= p
->loader
->GetContext ();
5230 if (!res
&& context
)
5231 context
->internal
->LookupNamedItem (name
, &res
);
5234 Application
*app
= Application::GetCurrent ();
5236 ResourceDictionary
*rd
= app
->GetResources ();
5238 bool exists
= false;
5239 res
= lookup_resource_dictionary (rd
, name
, &exists
);
5241 if (res
&& Type::IsSubclassOf (p
->deployment
, res
->GetKind (), Type::DEPENDENCY_OBJECT
)) {
5242 DependencyObject
*dob
= res
->AsDependencyObject ();
5243 NameScope::SetNameScope (dob
, dob
->FindNameScope ());
5252 xaml_get_template_parent (void *parser
, void *element_instance
)
5254 XamlParserInfo
*p
= (XamlParserInfo
*) parser
;
5255 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5257 return p
->GetTemplateParent (item
);
5261 xaml_get_element_key (void *parser
, void *element_instance
)
5263 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5264 const char *key
= item
->GetKey ();
5266 key
= item
->GetName ();
5267 return g_strdup (key
);
5271 xaml_get_element_name (void *parser
, void *element_instance
)
5273 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5274 return g_strdup (item
->element_name
);
5278 xaml_is_property_set (void *parser
, void *element_instance
, char *name
)
5280 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5281 return item
->IsPropertySet (name
);
5285 xaml_mark_property_as_set (void *parser
, void *element_instance
, char *name
)
5287 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5288 item
->MarkPropertyAsSet (g_strdup (name
));
5292 xaml_delay_set_property (void *parser
, void *element_instance
, const char *xmlns
, const char *name
, const Value
*value
)
5294 XamlElementInstance
*item
= (XamlElementInstance
*) element_instance
;
5295 item
->DelaySetProperty (xmlns
, name
, value
);
5301 default_namespace
= new DefaultNamespace ();
5302 x_namespace
= new XNamespace ();
5303 xml_namespace
= new XmlNamespace ();