private void SetupReorder(DictionaryAttribute dictionaryAttribute, DictionaryField field, SerializedProperty property, Type declaringType)
 {
     if (field.AllowReorder)
     {
         if (!string.IsNullOrEmpty(dictionaryAttribute.ReorderCallback))
         {
             var reorderCallback = ReflectionHelper.CreateActionCallback(dictionaryAttribute.ReorderCallback, declaringType, property);
             if (reorderCallback != null)
             {
                 field.RegisterCallback <DictionaryField.ItemReorderedEvent>(evt => reorderCallback.Invoke());
             }
             else
             {
                 var reorderCallbackFromTo = ReflectionHelper.CreateActionCallback <int, int>(dictionaryAttribute.ReorderCallback, declaringType, property);
                 if (reorderCallbackFromTo != null)
                 {
                     field.RegisterCallback <DictionaryField.ItemReorderedEvent>(evt => reorderCallbackFromTo.Invoke(evt.FromIndex, evt.ToIndex));
                 }
                 else
                 {
                     Debug.LogWarningFormat(_invalidReorderCallbackWarning, property.propertyPath);
                 }
             }
         }
     }
 }
        public override VisualElement CreatePropertyGUI(SerializedProperty property)
        {
            var keys   = property.FindPropertyRelative(SerializedDictionary <string, int> .KeyProperty);
            var values = property.FindPropertyRelative(SerializedDictionary <string, int> .ValueProperty);

            if (keys != null && keys.isArray && values != null && values.isArray && keys.arrayElementType == "string")
            {
                var dictionaryAttribute = attribute as DictionaryAttribute;
                var parent = property.GetOwner <object>();
                var path   = property.propertyPath;
                var proxy  = CreateProxy(property, keys, values, dictionaryAttribute);

                if (TryGetMethod(dictionaryAttribute.AllowAdd, _missingAllowAddMethodWarning, path, out var allowAddMethod))
                {
                    AddConditional(proxy.CanAddCallback, parent, allowAddMethod, _invalidAllowAddMethodWarning, path);
                }

                if (TryGetMethod(dictionaryAttribute.AllowRemove, _missingAllowRemoveMethodWarning, path, out var allowRemoveMethod))
                {
                    AddConditional(proxy.CanRemoveCallback, parent, allowRemoveMethod, _invalidAllowRemoveMethodWarning, path);
                }

                if (TryGetMethod(dictionaryAttribute.AllowReorder, _missingAllowReorderMethodWarning, path, out var allowReorderMethod))
                {
                    AddConditional(proxy.CanReorderCallback, parent, allowReorderMethod, _invalidAllowReorderMethodWarning, path);
                }

                if (TryGetMethod(dictionaryAttribute.AddCallback, _missingAddMethodWarning, path, out var addMethod))
                {
                    AddCallback(proxy.AddCallback, parent, addMethod, _invalidAddMethodWarning, path);
                }

                if (TryGetMethod(dictionaryAttribute.RemoveCallback, _missingRemoveMethodWarning, path, out var removeMethod))
                {
                    AddCallback(proxy.RemoveCallback, parent, removeMethod, _invalidRemoveMethodWarning, path);
                }

                if (TryGetMethod(dictionaryAttribute.ReorderCallback, _missingReorderMethodWarning, path, out var reorderMethod))
                {
                    AddCallback(proxy.ReorderCallback, parent, reorderMethod, _invalidReorderMethodWarning, path);
                }

                var field = new DictionaryField();
                field.Setup(keys, proxy);

                return(field);
            }
            else
            {
                Debug.LogWarningFormat(_invalidTypeWarning, property.propertyPath);
                return(new FieldContainer(property.displayName));
            }
        }
        public override VisualElement CreatePropertyGUI(SerializedProperty property)
        {
            var keys   = property.FindPropertyRelative(SerializedDictionary <string, int> .KeyProperty);
            var values = property.FindPropertyRelative(SerializedDictionary <string, int> .ValueProperty);

            if (keys != null && keys.isArray && values != null && values.isArray && keys.arrayElementType == "string")
            {
                var isReference         = fieldInfo.FieldType.BaseType.GetGenericTypeDefinition() == typeof(ReferenceDictionary <,>);
                var referenceType       = isReference ? fieldInfo.GetFieldType() : null;
                var declaringType       = fieldInfo.DeclaringType;
                var dictionaryAttribute = attribute as DictionaryAttribute;
                var drawer = this.GetNextDrawer();
                var proxy  = new PropertyDictionaryProxy(property, keys, values, drawer);

                var field = new DictionaryField
                {
                    IsCollapsable = dictionaryAttribute.IsCollapsable,
                    bindingPath   = keys.propertyPath,
                    Label         = property.displayName
                };

                // TODO: other stuff from ConfigureField

                if (!string.IsNullOrEmpty(dictionaryAttribute.AddPlaceholder))
                {
                    field.AddPlaceholder = dictionaryAttribute.AddPlaceholder;
                }

                if (!string.IsNullOrEmpty(dictionaryAttribute.EmptyLabel))
                {
                    field.EmptyLabel = dictionaryAttribute.EmptyLabel;
                }

                field.AllowAdd     = dictionaryAttribute.AllowAdd != DictionaryAttribute.Never;
                field.AllowRemove  = dictionaryAttribute.AllowRemove != DictionaryAttribute.Never;
                field.AllowReorder = dictionaryAttribute.AllowReorder;

                SetupAdd(dictionaryAttribute, proxy, field, property, declaringType, isReference);
                SetupRemove(dictionaryAttribute, proxy, field, property, declaringType);
                SetupReorder(dictionaryAttribute, field, property, declaringType);
                SetupChange(dictionaryAttribute, field, property, declaringType);

                field.SetProxy(proxy, referenceType, true);

                return(field);
            }
            else
            {
                Debug.LogWarningFormat(_invalidTypeWarning, property.propertyPath);
                return(new FieldContainer(property.displayName));
            }
        }
 private void SetupChange(DictionaryAttribute dictionaryAttribute, DictionaryField field, SerializedProperty property, Type declaringType)
 {
     if (!string.IsNullOrEmpty(dictionaryAttribute.ChangeCallback))
     {
         var changeCallback = ReflectionHelper.CreateActionCallback(dictionaryAttribute.ChangeCallback, declaringType, property);
         if (changeCallback != null)
         {
             field.RegisterCallback <DictionaryField.ItemsChangedEvent>(evt => changeCallback.Invoke());
         }
         else
         {
             Debug.LogWarningFormat(_invalidChangeCallbackWarning, property.propertyPath);
         }
     }
 }
        private void SetupAdd(DictionaryAttribute dictionaryAttribute, PropertyDictionaryProxy proxy, DictionaryField field, SerializedProperty property, Type declaringType, bool isReference)
        {
            if (field.AllowAdd)
            {
                if (!string.IsNullOrEmpty(dictionaryAttribute.AllowAdd))
                {
                    proxy.CanAddKeyCallback = ReflectionHelper.CreateFunctionCallback <string, bool>(dictionaryAttribute.AllowAdd, declaringType, property);
                    if (proxy.CanAddKeyCallback == null)
                    {
                        var canAdd = ReflectionHelper.CreateValueSourceFunction(dictionaryAttribute.AllowAdd, property, field, declaringType, true);
                        proxy.CanAddKeyCallback = index => canAdd();
                    }
                }

                if (!string.IsNullOrEmpty(dictionaryAttribute.AddCallback))
                {
                    if (!isReference)
                    {
                        var addCallback = ReflectionHelper.CreateActionCallback(dictionaryAttribute.AddCallback, declaringType, property);
                        if (addCallback != null)
                        {
                            field.RegisterCallback <DictionaryField.ItemAddedEvent>(evt => addCallback.Invoke());
                        }
                        else
                        {
                            var addCallbackKey = ReflectionHelper.CreateActionCallback <string>(dictionaryAttribute.AddCallback, declaringType, property);
                            if (addCallbackKey != null)
                            {
                                field.RegisterCallback <DictionaryField.ItemAddedEvent>(evt => addCallbackKey.Invoke(evt.Key));
                            }
                            else
                            {
                                Debug.LogWarningFormat(_invalidAddCallbackWarning, property.propertyPath);
                            }
                        }
                    }
                    else
                    {
                        var addCallback = ReflectionHelper.CreateActionCallback(dictionaryAttribute.AddCallback, declaringType, property);
                        if (addCallback != null)
                        {
                            field.RegisterCallback <DictionaryField.ItemAddedEvent>(evt => addCallback.Invoke());
                        }
                        else
                        {
                            var addCallbackKey = ReflectionHelper.CreateActionCallback <string>(dictionaryAttribute.AddCallback, declaringType, property);
                            if (addCallbackKey != null)
                            {
                                field.RegisterCallback <DictionaryField.ItemAddedEvent>(evt => addCallbackKey.Invoke(evt.Key));
                            }
                            else
                            {
                                Debug.LogWarningFormat(_invalidAddReferenceCallbackWarning, property.propertyPath);
                            }
                        }
                    }
                }
            }
        }