public void ReflectObject(object obj)
        {
            OrderedDictionary new_details = new OrderedDictionary();

            if (obj == null)
            {
                Categories = new_details;
                return;
            }

            HideCategoriesAttribute hidden_categories = (HideCategoriesAttribute)obj.GetType().GetCustomAttribute(typeof(HideCategoriesAttribute));

            PropertyInfo[] obj_properties = obj.GetType().GetProperties();

            foreach (PropertyInfo p in obj_properties)
            {
                // We want to ignore all properties that are not marked with the WProperty attribute.
                CustomAttributeData[] custom_attributes = p.CustomAttributes.ToArray();
                if (custom_attributes.Length == 0 || custom_attributes[0].AttributeType.Name != "WProperty")
                {
                    continue;
                }

                // Grab our custom attribute data for use
                string category_name = (string)custom_attributes[0].ConstructorArguments[0].Value;
                string property_name = (string)custom_attributes[0].ConstructorArguments[1].Value;
                bool   is_editable   = (bool)custom_attributes[0].ConstructorArguments[2].Value;
                string tool_tip      = (string)custom_attributes[0].ConstructorArguments[3].Value;

                // Get the base type for possible use later
                Type base_type = p.PropertyType;
                while (base_type.BaseType != typeof(object))
                {
                    base_type = base_type.BaseType;
                }

                // Only add the category to the view if it's not blacklisted by the HideCategories attribute.
                if (!new_details.Contains(category_name) && hidden_categories != null && !hidden_categories.CategoryHidden(category_name))
                {
                    // Also, we want to force the Transform category to the top of the list.
                    if (category_name == "Transform")
                    {
                        new_details.Insert(0, category_name, new WDetailsCategoryRowViewModel(category_name));
                    }
                    else
                    {
                        new_details.Add(category_name, new WDetailsCategoryRowViewModel(category_name));
                    }
                }

                WDetailsCategoryRowViewModel current_category = null;

                if (new_details.Contains(category_name))
                {
                    current_category = (WDetailsCategoryRowViewModel)new_details[category_name];
                }
                else
                {
                    continue;
                }

                /* This is where we generate the control for the details view. */

                List <WDetailSingleRowViewModel> property_rows = new List <WDetailSingleRowViewModel>();

                // We first check if the type of the property has a customization registered.
                // If it is, we just grab the customization and generate a control with it.
                if (m_TypeCustomizations.ContainsKey(p.PropertyType.Name))
                {
                    property_rows = m_TypeCustomizations[p.PropertyType.Name].CustomizeHeader(p, property_name, is_editable, obj);
                }
                // If there is no customization registered, and the type is an enum, we
                // use EnumTypeCustomization to generate a control.
                else if (p.PropertyType.IsEnum)
                {
                    EnumTypeCustomization enu = new EnumTypeCustomization();
                    property_rows = enu.CustomizeHeader(p, property_name, is_editable, obj);
                }
                // Failing the prior checks, we see if the base type of the property is WDOMNode,
                // in which case we just use the WDOMNode customization to generate a control.
                else if (base_type.Name == typeof(WDOMNode).Name)
                {
                    property_rows = m_TypeCustomizations[typeof(WDOMNode).Name].CustomizeHeader(p, property_name, is_editable, obj);
                }
                // If the property type is completely unknown or unsupported, we create an empty row with
                // just the property's name.
                else
                {
                    property_rows.Add(new WDetailSingleRowViewModel(property_name));
                }

                // Saw online that adding multiple things to a binding list can be slow,
                // so I'll do what that guy suggested. Disable raising changed events, then re-enable when we're done.
                current_category.PropertyRows.RaiseListChangedEvents = false;

                foreach (var row in property_rows)
                {
                    current_category.PropertyRows.Add(row);
                    row.PropertyToolTip = tool_tip;
                }

                current_category.PropertyRows.RaiseListChangedEvents = true;
                current_category.PropertyRows.ResetBindings();
            }

            Categories = new_details;
        }
예제 #2
0
        public void ReflectObject(object obj)
        {
            OrderedDictionary new_details = new OrderedDictionary();

            if (obj == null)
            {
                Categories = new_details;
                return;
            }

            HideCategoriesAttribute hidden_categories = (HideCategoriesAttribute)obj.GetType().GetCustomAttribute(typeof(HideCategoriesAttribute));

            PropertyInfo[] obj_properties = obj.GetType().GetProperties();

            foreach (PropertyInfo p in obj_properties)
            {
                // We want to ignore all properties that are not marked with the WProperty attribute.
                CustomAttributeData[] custom_attributes   = p.CustomAttributes.ToArray();
                CustomAttributeData   wproperty_attribute = custom_attributes.FirstOrDefault(x => x.AttributeType.Name == "WProperty");
                if (wproperty_attribute == null)
                {
                    continue;
                }

                // Grab our custom attribute data for use
                string      category_name = (string)wproperty_attribute.ConstructorArguments[0].Value;
                string      property_name = (string)wproperty_attribute.ConstructorArguments[1].Value;
                bool        is_editable   = (bool)wproperty_attribute.ConstructorArguments[2].Value;
                string      tool_tip      = (string)wproperty_attribute.ConstructorArguments[3].Value;
                SourceScene source_scene  = (SourceScene)wproperty_attribute.ConstructorArguments[4].Value;

                // Get the base type for possible use later
                Type base_type = p.PropertyType;
                while (base_type.BaseType != typeof(object))
                {
                    base_type = base_type.BaseType;
                }

                // Only add the category to the view if it's not blacklisted by the HideCategories attribute.
                if (!new_details.Contains(category_name) && (hidden_categories == null || !hidden_categories.CategoryHidden(category_name)))
                {
                    new_details.Add(category_name, new WDetailsCategoryRowViewModel(category_name));
                }

                WDetailsCategoryRowViewModel current_category = null;

                if (new_details.Contains(category_name))
                {
                    current_category = (WDetailsCategoryRowViewModel)new_details[category_name];
                }
                else
                {
                    continue;
                }

                /* This is where we generate the control for the details view. */

                List <WDetailSingleRowViewModel> property_rows = new List <WDetailSingleRowViewModel>();

                // We first check if the type of the property has a customization registered.
                // If it is, we just grab the customization and generate a control with it.
                if (m_TypeCustomizations.ContainsKey(p.PropertyType.Name))
                {
                    property_rows = m_TypeCustomizations[p.PropertyType.Name].CustomizeHeader(p, property_name, is_editable, obj);
                }
                // If there is no customization registered, and the type is an enum, we
                // use EnumTypeCustomization to generate a control.
                else if (p.PropertyType.IsEnum)
                {
                    EnumTypeCustomization enu = new EnumTypeCustomization();
                    property_rows = enu.CustomizeHeader(p, property_name, is_editable, obj);
                }
                // Check if the type is an AndvancedBindingList.
                else if (p.PropertyType.Name == typeof(AdvancedBindingList <object>).Name)
                {
                    Type underlying_type   = p.PropertyType.GetGenericArguments().Single();
                    Type type_from_generic = typeof(AdvancedBindingListTypeCustomization <>).MakeGenericType(underlying_type);

                    IPropertyTypeCustomization adv_cus = Activator.CreateInstance(type_from_generic) as IPropertyTypeCustomization;
                    property_rows = adv_cus.CustomizeHeader(p, property_name, is_editable, obj);

                    WAdvancedBindingListControl base_ctrl = property_rows[0].PropertyControl as WAdvancedBindingListControl;
                    base_ctrl.entry_combo.SelectedIndex = 0;
                    property_rows.AddRange(base_ctrl.GenerateBoundFields());
                    base_ctrl.OnEntryComboSelectionChanged();
                }
                // Failing the prior checks, we see if the base type of the property is WDOMNode,
                // in which case we just use the WDOMNode customization to generate a control.
                else if (base_type.Name == typeof(WDOMNode).Name)
                {
                    property_rows = m_TypeCustomizations[typeof(WDOMNode).Name].CustomizeHeader(p, property_name, is_editable, obj);

                    WActorReferenceControl c = (WActorReferenceControl)property_rows[0].PropertyControl;
                    c.Source = source_scene;
                    c.FillComboBox();
                }
                // If the property type is completely unknown or unsupported, we create an empty row with
                // just the property's name.
                else
                {
                    property_rows.Add(new WDetailSingleRowViewModel(property_name));
                }

                // Saw online that adding multiple things to a binding list can be slow,
                // so I'll do what that guy suggested. Disable raising changed events, then re-enable when we're done.
                current_category.PropertyRows.RaiseListChangedEvents = false;

                foreach (var row in property_rows)
                {
                    current_category.PropertyRows.Add(row);

                    if (tool_tip != "")
                    {
                        row.PropertyToolTip = tool_tip;
                    }
                }

                current_category.PropertyRows.RaiseListChangedEvents = true;
                current_category.PropertyRows.ResetBindings();
            }

            // We want to force certain categories to the top of the list, so reorder it at the end.
            foreach (var cat_name in new string[] { "Actor", "Transform", "Entity" })
            {
                if (new_details.Contains(cat_name))
                {
                    var row = new_details[cat_name];
                    new_details.Remove(cat_name);
                    new_details.Insert(0, cat_name, row);
                }
            }

            Categories = new_details;
        }