Pārlūkot izejas kodu

Added EditableAttribute and added property to interface of ILookupEditorControl to better allow for the type system.

Kenric Nugteren 1 gadu atpakaļ
vecāks
revīzija
1549b67277

+ 13 - 0
InABox.Core/DatabaseSchema/DatabaseSchema.cs

@@ -169,6 +169,19 @@ namespace InABox.Core
                                 Property = prop
                             };
 
+                            var parentWithEditable = newProperty.GetOuterParent(x =>
+                                x is StandardProperty st
+                                && st.Property.GetCustomAttribute<EditableAttribute>() != null);
+                            if(parentWithEditable != null)
+                            {
+                                var attr = (parentWithEditable as StandardProperty)!.Property.GetCustomAttribute<EditableAttribute>()!;
+                                newProperty.Editor.Editable = newProperty.Editor.Editable.Combine(attr.Editable);
+                            }
+                            else if(prop.GetCustomAttribute<EditableAttribute>() is EditableAttribute attr)
+                            {
+                                newProperty.Editor.Editable = newProperty.Editor.Editable.Combine(attr.Editable);
+                            }
+
                             var isLink = prop.PropertyType.GetInterfaces().Contains(typeof(IEntityLink));
                             var isEnclosedEntity = prop.PropertyType.GetInterfaces().Contains(typeof(IEnclosedEntity));
                             var isBaseEditor = prop.PropertyType.Equals(typeof(BaseEditor)) ||

+ 33 - 0
InABox.Core/DatabaseSchema/IProperty.cs

@@ -69,6 +69,11 @@ namespace InABox.Core
         public static bool HasAttribute<TAttribute>(this IProperty property) where TAttribute : Attribute
             => property.GetAttribute<TAttribute>() != null;
 
+        /// <summary>
+        /// Get the outermost parent property which has an editor.
+        /// </summary>
+        /// <param name="property"></param>
+        /// <returns></returns>
         public static IProperty? GetParentWithEditor(this IProperty property)
         {
             if (property.Parent == null) return null;
@@ -82,6 +87,34 @@ namespace InABox.Core
             return null;
         }
 
+        /// <summary>
+        /// Gets the outermost parent property which matches the predicate.
+        /// </summary>
+        /// <param name="property"></param>
+        /// <param name="predicate"></param>
+        /// <returns></returns>
+        public static IProperty? GetOuterParent(this IProperty property, Func<IProperty, bool> predicate)
+        {
+            if (property.Parent == null) return null;
+
+            return property.Parent.GetOuterParent(predicate)
+                ?? (predicate(property.Parent) ? property.Parent : null);
+        }
+
+        /// <summary>
+        /// Gets the innermost parent property which matches the predicate.
+        /// </summary>
+        /// <param name="property"></param>
+        /// <param name="predicate"></param>
+        /// <returns></returns>
+        public static IProperty? GetParent(this IProperty property, Func<IProperty, bool> predicate)
+        {
+            if (property.Parent == null) return null;
+
+            if(predicate(property.Parent)) return property.Parent;
+            return property.Parent.GetParent(predicate);
+        }
+
         public static bool HasParentEditor(this IProperty property)
         {
             return property.Parent != null && (property.Parent.HasEditor || property.Parent.HasParentEditor());

+ 47 - 1
InABox.Core/Editors/Utils/Editable.cs

@@ -1,4 +1,6 @@
-namespace InABox.Core
+using System;
+
+namespace InABox.Core
 {
     public enum Editable
     {
@@ -11,6 +13,24 @@
         DisabledOnDirectEdit
     }
 
+    /// <summary>
+    /// Set whether or not this property is editable, overriding any <see cref="BaseEditor"/> on this property or any sub-properties.
+    /// </summary>
+    /// <remarks>
+    /// What this actually does is that when <see cref="DatabaseSchema"/> is loading a property, it checks to find the outer-most parent property
+    /// of that property with an <see cref="EditableAttribute"/>, or if the property has one of its own. If so, it overrides the <see cref="Editable"/>
+    /// property of that property's <see cref="IProperty.Editor"/>, combining using the <see cref="EditableUtils.Combine(Editable, Editable)"/> function.
+    /// </remarks>
+    public class EditableAttribute: Attribute
+    {
+        public Editable Editable { get; set; }
+
+        public EditableAttribute(Editable editable)
+        {
+            Editable = editable;
+        }
+    }
+
     public static class EditableUtils
     {
         public static bool IsEditable(this Editable editable)
@@ -31,5 +51,31 @@
         {
             return editable != Editable.Hidden;
         }
+
+        /// <summary>
+        /// Combine (restrictively) two editable enums.
+        /// </summary>
+        /// <param name="editable"></param>
+        /// <param name="other"></param>
+        /// <returns></returns>
+        public static Editable Combine(this Editable editable, Editable other)
+        {
+            switch (editable)
+            {
+                case Editable.Enabled:
+                    return other;
+                case Editable.DisabledOnDirectEdit:
+                    if (other == Editable.Disabled || other == Editable.Hidden)
+                        return other;
+                    return editable;
+                case Editable.Disabled:
+                    if (other == Editable.Hidden)
+                        return other;
+                    return editable;
+                case Editable.Hidden:
+                default:
+                    return editable;
+            }
+        }
     }
 }

+ 2 - 8
inabox.wpf/DynamicGrid/DynamicEditorGrid.xaml.cs

@@ -616,14 +616,7 @@ namespace InABox.DynamicGrid
                     {
                         if (!Security.IsAllowed(security.SecurityDescriptor))
                         {
-                            if(security.Editable == Editable.Hidden)
-                            {
-                                editor.Editable = Editable.Hidden;
-                            }
-                            else if(security.Editable == Editable.Disabled && editor.Editable == Editable.Enabled)
-                            {
-                                editor.Editable = Editable.Disabled;
-                            }
+                            editor.Editable = editor.Editable.Combine(security.Editable);
                             if (editor.Editable == Editable.Hidden)
                             {
                                 break;
@@ -646,6 +639,7 @@ namespace InABox.DynamicGrid
                 }
                 else if (iProp?.HasParentEditor() == true)
                 {
+                    // Add the parent editor if it hasn't been added already.
                     var parent = iProp.GetParentWithEditor();
                     if(parent is not null)
                     {

+ 2 - 0
inabox.wpf/DynamicGrid/Editors/CheckListEditor/CheckListEditorControl.cs

@@ -27,6 +27,8 @@ namespace InABox.DynamicGrid
 
         private CheckListBox Editor;
 
+        public ILookupEditor LookupEditorDefinition => EditorDefinition;
+
         public Dictionary<string, string> OtherColumns { get; set; }
 
         public override void Configure()

+ 2 - 0
inabox.wpf/DynamicGrid/Editors/ILookupEditorControl.cs

@@ -5,6 +5,8 @@ namespace InABox.DynamicGrid
 {
     public interface ILookupEditorControl : IDynamicEditorControl
     {
+        ILookupEditor LookupEditorDefinition { get; }
+
         Dictionary<string, string> OtherColumns { get; }
 
         void LoadLookups(CoreTable values);

+ 2 - 0
inabox.wpf/DynamicGrid/Editors/LookupEditor/LookupEditorControl.cs

@@ -21,6 +21,8 @@ namespace InABox.DynamicGrid
 
         private CoreTable LookupTable;
 
+        public ILookupEditor LookupEditorDefinition => EditorDefinition;
+
         public LookupEditorControl()
         {
             OtherColumns = new Dictionary<string, string>();

+ 2 - 0
inabox.wpf/DynamicGrid/Editors/MultiLookupEditor/MultiLookupEditorControl.cs

@@ -38,6 +38,8 @@ namespace InABox.DynamicGrid
 
         private List<Tuple<object?, string>> Items;
 
+        public ILookupEditor LookupEditorDefinition => EditorDefinition;
+
         public override void Configure()
         {
             Editor.HorizontalAlignment = Width.Equals(int.MaxValue) ? HorizontalAlignment.Stretch : HorizontalAlignment.Left;