Esempio n. 1
0
        /// <summary>
        /// Sets view values parsed from XUML.
        /// </summary>
        private static void SetViewValues(View view, XElement xumlElement, View parent, ValueConverterContext context)
        {
            if (view == null)
            {
                return;
            }

            var viewTypeData = GetViewTypeData(view.ViewTypeName);

            foreach (var attribute in xumlElement.Attributes())
            {
                string viewFieldPath  = attribute.Name.LocalName;
                string viewFieldValue = attribute.Value;

                // ignore namespace specification
                if (String.Equals(viewFieldPath, "xmlns", StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                // check if the field value is allowed to be be set from xuml
                bool notAllowed = viewTypeData.FieldsNotSetFromXuml.Contains(viewFieldPath);
                if (notAllowed)
                {
                    Utils.LogError("[MarkLight] {0}: Unable to assign value \"{1}\" to view field \"{2}.{3}\". Field not allowed to be set from XUML.", view.GameObjectName, viewFieldValue, view.ViewTypeName, viewFieldPath);
                    continue;
                }

                // check if value contains a binding
                if (ViewFieldBinding.ValueHasBindings(viewFieldValue))
                {
                    view.AddBinding(viewFieldPath, viewFieldValue);
                    continue;
                }

                // check if we are setting a state-value
                int stateIndex = viewFieldPath.IndexOf('-', 0);
                if (stateIndex > 0)
                {
                    // check if we are setting a sub-state, i.e. the state of the target view
                    var stateViewField = viewFieldPath.Substring(stateIndex + 1);
                    var state          = viewFieldPath.Substring(0, stateIndex);

                    bool isSubState = stateViewField.StartsWith("-");
                    if (isSubState)
                    {
                        stateViewField = stateViewField.Substring(1);
                    }

                    // setting the state of the source view
                    view.AddStateValue(state, stateViewField, attribute.Value, context, isSubState);
                    continue;
                }

                // get view field data
                var viewFieldData = view.GetViewFieldData(viewFieldPath);
                if (viewFieldData == null)
                {
                    Utils.LogError("[MarkLight] {0}: Unable to assign value \"{1}\" to view field \"{2}\". View field not found.", view.GameObjectName, viewFieldValue, viewFieldPath);
                    continue;
                }

                // check if we are setting a view action handler
                if (viewFieldData.ViewFieldTypeName == "ViewAction")
                {
                    viewFieldData.SourceView.AddViewActionEntry(viewFieldData.ViewFieldPath, viewFieldValue, parent);
                    continue;
                }

                // we are setting a normal view field
                view.SetValue(attribute.Name.LocalName, attribute.Value, true, null, context, true);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Creates view of specified type.
        /// </summary>
        public static View CreateView(string viewName, View layoutParent, View parent, ValueConverterContext context = null, string theme = "", string id = "", string style = "", IEnumerable <XElement> contentXuml = null)
        {
            // Creates the views in the following order:
            // CreateView(view)
            //   Foreach child
            //     CreateView(child)
            //     SetViewValues(child)
            //   Foreach contentView
            //      CreateView(contentView)
            //      SetViewValues(contentView)
            //   SetViewValues(view)
            //   SetThemeValues(view)

            // TODO store away and re-use view templates

            // use default theme if no theme is specified
            if (String.IsNullOrEmpty(theme))
            {
                theme = ViewPresenter.Instance.DefaultTheme;
            }

            // initialize value converter context
            if (context == null)
            {
                context = ValueConverterContext.Default;
            }

            // create view from XUML
            var viewTypeData = GetViewTypeData(viewName);

            if (viewTypeData == null)
            {
                return(null);
            }

            // get view type
            var viewType = GetViewType(viewName);

            if (viewType == null)
            {
                viewType = typeof(View);
            }

            // create view game object with required components
            var go = new GameObject(viewTypeData.ViewName);

            if (typeof(UIView).IsAssignableFrom(viewType))
            {
                go.AddComponent <RectTransform>();
            }
            go.transform.SetParent(layoutParent.transform, false);

            // create view behavior and initialize it
            var view = go.AddComponent(viewType) as View;

            view.LayoutParent          = layoutParent;
            view.Parent                = parent;
            view.Id                    = id;
            view.Style                 = style;
            view.Theme                 = theme;
            view.Content               = view;
            view.ViewXumlName          = viewName;
            view.ValueConverterContext = context;

            // set component fields
            foreach (var componentField in viewTypeData.ComponentFields)
            {
                if (viewTypeData.ExcludedComponentFields.Contains(componentField))
                {
                    continue; // exclude component
                }
                var       componentFieldInfo = viewType.GetField(componentField);
                Component component          = null;
                if (componentField == "Transform")
                {
                    component = go.transform;
                }
                else if (componentField == "RectTransform")
                {
                    component = go.transform as RectTransform;
                }
                else
                {
                    component = go.AddComponent(componentFieldInfo.FieldType);
                }
                componentFieldInfo.SetValue(view, component);
            }

            // set view action fields
            foreach (var viewActionField in viewTypeData.ViewActionFields)
            {
                var viewActionFieldInfo = viewTypeData.GetViewField(viewActionField);
                viewActionFieldInfo.SetValue(view, new ViewAction(viewActionField));
            }

            // set dependency fields
            foreach (var dependencyField in viewTypeData.DependencyFields)
            {
                var dependencyFieldInfo     = viewTypeData.GetViewField(dependencyField);
                var dependencyFieldInstance = TypeHelper.CreateViewField(dependencyFieldInfo.FieldType);
                dependencyFieldInfo.SetValue(view, dependencyFieldInstance);
                dependencyFieldInstance.ParentView    = view;
                dependencyFieldInstance.ViewFieldPath = dependencyField;
                dependencyFieldInstance.IsMapped      = !String.Equals(viewTypeData.GetMappedViewField(dependencyField), dependencyField);
            }

            // parse child XUML and for each child create views and set their values
            foreach (var childElement in viewTypeData.XumlElement.Elements())
            {
                var childViewIdAttr    = childElement.Attribute("Id");
                var childViewStyleAttr = childElement.Attribute("Style");
                var childThemeAttr     = childElement.Attribute("Theme");
                var childContext       = GetValueConverterContext(context, childElement, view.GameObjectName);

                var childView = CreateView(childElement.Name.LocalName, view, view, childContext,
                                           childThemeAttr != null ? childThemeAttr.Value : theme,
                                           childViewIdAttr != null ? childViewIdAttr.Value : String.Empty,
                                           GetChildViewStyle(view.Style, childViewStyleAttr),
                                           childElement.Elements());
                SetViewValues(childView, childElement, view, childContext);
            }

            // search for a content placeholder
            ContentPlaceholder contentContainer = view.Find <ContentPlaceholder>(true, view);
            var contentLayoutParent             = view;

            if (contentContainer != null)
            {
                contentLayoutParent = contentContainer.LayoutParent;
                view.Content        = contentLayoutParent;

                // remove placeholder
                GameObject.DestroyImmediate(contentContainer.gameObject);
            }

            // parse content XUML and for each content child create views and set their values
            if (contentXuml != null)
            {
                // create content views
                foreach (var contentElement in contentXuml)
                {
                    var contentElementIdAttr    = contentElement.Attribute("Id");
                    var contentElementStyleAttr = contentElement.Attribute("Style");
                    var contentThemeAttr        = contentElement.Attribute("Theme");
                    var contentContext          = GetValueConverterContext(context, contentElement, view.GameObjectName);

                    var contentView = CreateView(contentElement.Name.LocalName, contentLayoutParent, parent, contentContext,
                                                 contentThemeAttr != null ? contentThemeAttr.Value : theme,
                                                 contentElementIdAttr != null ? contentElementIdAttr.Value : String.Empty,
                                                 GetChildViewStyle(view.Style, contentElementStyleAttr),
                                                 contentElement.Elements());
                    SetViewValues(contentView, contentElement, parent, contentContext);
                }
            }

            // set view references
            foreach (var referenceField in viewTypeData.ReferenceFields)
            {
                // is this a reference to a view?
                var referencedView = view.Find <View>(x => String.Equals(x.Id, referenceField, StringComparison.OrdinalIgnoreCase),
                                                      true, view);
                if (referencedView != null)
                {
                    var referenceFieldInfo = viewType.GetField(referenceField);
                    referenceFieldInfo.SetValue(view, referencedView);
                }
            }

            // set view default values
            view.SetDefaultValues();

            // set internal view values that appear inside the root element of the XUML file
            SetViewValues(view, viewTypeData.XumlElement, view, context);

            // set theme values
            var themeData = GetThemeData(theme);

            if (themeData != null)
            {
                foreach (var themeElement in themeData.GetThemeElementData(view.ViewTypeName, view.Id, view.Style))
                {
                    var themeValueContext = new ValueConverterContext(context);
                    if (themeData.BaseDirectorySet)
                    {
                        themeValueContext.BaseDirectory = themeData.BaseDirectory;
                    }
                    if (themeData.UnitSizeSet)
                    {
                        themeValueContext.UnitSize = themeData.UnitSize;
                    }

                    SetViewValues(view, themeElement.XumlElement, view, themeValueContext);
                }
            }

            return(view);
        }
        /// <summary>
        /// Sets value of field.
        /// </summary>
        public object SetValue(object inValue, HashSet <ViewFieldData> callstack, bool updateDefaultState = true,
                               ValueConverterContext context = null, bool notifyObservers = true)
        {
            if (callstack.Contains(this))
            {
                return(null);
            }

            callstack.Add(this);

            if (!IsOwner)
            {
                var targetView = GetTargetView();
                if (targetView == null)
                {
                    Debug.LogError(String.Format("[MarkLight] {0}: Unable to assign value \"{1}\" to view field \"{2}\". View along path is null.", SourceView.GameObjectName, inValue, ViewFieldPath));
                    return(null);
                }

                return(targetView.SetValue(TargetViewFieldPath, inValue, updateDefaultState, callstack, null, notifyObservers));
            }

            // check if path has been parsed
            if (!IsPathParsed)
            {
                // attempt to parse path
                if (!ParseViewFieldPath())
                {
                    // path can't be resolved at this point
                    if (SevereParseError)
                    {
                        // severe parse error means the path is incorrect
                        Debug.LogError(String.Format("[MarkLight] {0}: Unable to assign value \"{1}\". {2}", SourceView.GameObjectName, inValue, Utils.ErrorMessage));
                    }

                    // unsevere parse errors can be expected, e.g. value along path is null
                    return(null);
                }
            }

            object value = inValue;

            if (context == null)
            {
                if (SourceView.ValueConverterContext != null)
                {
                    context = SourceView.ValueConverterContext;
                }
                else
                {
                    context = ValueConverterContext.Default;
                }
            }

            // get converted value
            if (ValueConverter != null)
            {
                var conversionResult = ValueConverter.Convert(value, context);
                if (!conversionResult.Success)
                {
                    Debug.LogError(String.Format("[MarkLight] {0}: Unable to assign value \"{1}\" to view field \"{2}\". Value converion failed. {3}", SourceView.GameObjectName, value, ViewFieldPath, conversionResult.ErrorMessage));
                    return(null);
                }
                value = conversionResult.ConvertedValue;
            }

            // set value
            object oldValue = ViewFieldPathInfo.SetValue(SourceView, value);

            // notify observers if the value has changed
            if (notifyObservers)
            {
                // set isSet-indicator
                SetIsSet();

                bool valueChanged = value != null ? !value.Equals(oldValue) : oldValue != null;
                if (valueChanged)
                {
                    NotifyValueObservers(callstack);

                    // find dependent view fields and notify their value observers
                    SourceView.NotifyDependentValueObservers(ViewFieldPath);
                }
            }

            return(value);
        }
Esempio n. 4
0
        /// <summary>
        /// Creates view of specified type.
        /// </summary>
        public static T CreateView <T>(View layoutParent, View parent, ValueConverterContext context = null, string themeName = "", string id = "", string style = "", IEnumerable <XElement> contentXuml = null) where T : View
        {
            Type viewType = typeof(T);

            return(CreateView(viewType.Name, layoutParent, parent, context, themeName, id, style, contentXuml) as T);
        }
 /// <summary>
 /// Converts XUML attribute to a view value.
 /// </summary>
 public virtual ConversionResult Convert(object value, ValueConverterContext context)
 {
     return(new ConversionResult(value));
 }