Browse Source

WIP ProjectWindow rename & delete

Marko Pintera 10 years ago
parent
commit
fbb6f3980f

+ 1 - 1
MBansheeEditor/Inspector/Inspector.cs

@@ -24,7 +24,7 @@ namespace BansheeEditor
 
         internal void SetVisible(bool visible)
         {
-            GUI.SetVisible(visible);
+            GUI.Visible = visible;
         }
 
         internal void Destroy()

+ 183 - 37
MBansheeEditor/ProjectWindow.cs

@@ -97,6 +97,7 @@ namespace BansheeEditor
             private GUITexture underlay;
             private ContentInfo info;
             private UnderlayState underlayState;
+            private GUITextBox renameTextBox;
 
             public ElementEntry(ContentInfo info, GUILayout parent, LibraryEntry entry, int index)
             {
@@ -219,6 +220,37 @@ namespace BansheeEditor
                 underlayState = UnderlayState.Hovered;
             }
 
+            public void StartRename()
+            {
+                if (renameTextBox != null)
+                    return;
+
+                renameTextBox = new GUITextBox(false);
+                renameTextBox.Bounds = label.Bounds;
+                info.overlay.AddElement(renameTextBox);
+
+                label.Visible = false;
+            }
+
+            public void StopRename()
+            {
+                if (renameTextBox != null)
+                {
+                    renameTextBox.Destroy();
+                    renameTextBox = null;
+                }
+
+                label.Visible = true;
+            }
+
+            public string GetRenamedName()
+            {
+                if (renameTextBox != null)
+                    return renameTextBox.Text;
+
+                return "";
+            }
+
             private void ClearUnderlay()
             {
                 if (underlay != null)
@@ -330,6 +362,8 @@ namespace BansheeEditor
         private Vector2I dragSelectionStart;
         private Vector2I dragSelectionEnd;
 
+        private ElementEntry inProgressRenameElement;
+
         // Cut/Copy/Paste
         private List<string> copyPaths = new List<string>();
         private List<string> cutPaths = new List<string>();
@@ -381,10 +415,14 @@ namespace BansheeEditor
             contentLayout.AddFlexibleSpace();
 
             entryContextMenu = new ContextMenu();
+            entryContextMenu.AddItem("Rename", RenameSelection, new ShortcutKey(ButtonModifier.None, ButtonCode.F2));
+            entryContextMenu.AddSeparator("");
             entryContextMenu.AddItem("Cut", CutSelection, new ShortcutKey(ButtonModifier.Ctrl, ButtonCode.X));
             entryContextMenu.AddItem("Copy", CopySelection, new ShortcutKey(ButtonModifier.Ctrl, ButtonCode.C));
             entryContextMenu.AddItem("Duplicate", DuplicateSelection, new ShortcutKey(ButtonModifier.Ctrl, ButtonCode.D));
             entryContextMenu.AddItem("Paste", PasteToSelection, new ShortcutKey(ButtonModifier.Ctrl, ButtonCode.V));
+            entryContextMenu.AddSeparator("");
+            entryContextMenu.AddItem("Delete", DeleteSelection, new ShortcutKey(ButtonModifier.None, ButtonCode.Delete));
 
             Reset();
 
@@ -741,6 +779,7 @@ namespace BansheeEditor
             }
 
             Ping(null);
+            StopRename();
 
             if (selectionPaths != null)
                 Selection.resourcePaths = selectionPaths.ToArray();
@@ -859,63 +898,118 @@ namespace BansheeEditor
 
         private void EditorUpdate()
         {
+            bool isRenameInProgress = inProgressRenameElement != null;
+
             if (HasContentFocus)
             {
-                if (Input.IsButtonHeld(ButtonCode.LeftControl) || Input.IsButtonHeld(ButtonCode.RightControl))
+                if (!isRenameInProgress)
                 {
-                    if (Input.IsButtonUp(ButtonCode.C))
+                    if (Input.IsButtonHeld(ButtonCode.LeftControl) || Input.IsButtonHeld(ButtonCode.RightControl))
                     {
-                        CopySelection();
+                        if (Input.IsButtonUp(ButtonCode.C))
+                        {
+                            CopySelection();
+                        }
+                        else if (Input.IsButtonUp(ButtonCode.X))
+                        {
+                            CutSelection();
+                        }
+                        else if (Input.IsButtonUp(ButtonCode.D))
+                        {
+                            DuplicateSelection();
+                        }
+                        else if (Input.IsButtonUp(ButtonCode.V))
+                        {
+                            PasteToSelection();
+                        }
+                    }
+
+                    if (Input.IsButtonDown(ButtonCode.Return))
+                    {
+                        if (selectionPaths.Count == 1)
+                        {
+                            LibraryEntry entry = ProjectLibrary.GetEntry(selectionPaths[0]);
+                            if (entry != null && entry.Type == LibraryEntryType.Directory)
+                            {
+                                EnterDirectory(entry.Path);
+                            }
+                        }
+                    }
+                    else if (Input.IsButtonDown(ButtonCode.Back))
+                    {
+                        LibraryEntry entry = ProjectLibrary.GetEntry(currentDirectory);
+                        if (entry != null && entry.Parent != null)
+                        {
+                            EnterDirectory(entry.Parent.Path);
+                        }
                     }
-                    else if (Input.IsButtonUp(ButtonCode.X))
+                    else if (Input.IsButtonDown(ButtonCode.Up))
                     {
-                        CutSelection();
+                        MoveSelection(MoveDirection.Up);
                     }
-                    else if (Input.IsButtonUp(ButtonCode.D))
+                    else if (Input.IsButtonDown(ButtonCode.Down))
                     {
-                        DuplicateSelection();
+                        MoveSelection(MoveDirection.Down);
                     }
-                    else if (Input.IsButtonUp(ButtonCode.V))
+                    else if (Input.IsButtonDown(ButtonCode.Left))
                     {
-                        PasteToSelection();
+                        MoveSelection(MoveDirection.Left);
+                    }
+                    else if (Input.IsButtonDown(ButtonCode.Right))
+                    {
+                        MoveSelection(MoveDirection.Right);
+                    }
+                    else if (Input.IsButtonDown(ButtonCode.F2))
+                    {
+                        RenameSelection();
+                    }
+                    else if (Input.IsButtonDown(ButtonCode.Delete))
+                    {
+                        DeleteSelection();
                     }
                 }
-
-                if (Input.IsButtonDown(ButtonCode.Return))
+                else
                 {
-                    if (selectionPaths.Count == 1)
+                    if (Input.IsButtonDown(ButtonCode.Return))
                     {
-                        LibraryEntry entry = ProjectLibrary.GetEntry(selectionPaths[0]);
-                        if (entry != null && entry.Type == LibraryEntryType.Directory)
+                        string newName = inProgressRenameElement.GetRenamedName();
+
+                        string originalPath = inProgressRenameElement.path;
+                            string newPath = Path.GetDirectoryName(originalPath);
+                            newPath = Path.Combine(newPath, newName + Path.GetExtension(originalPath));
+
+                        bool renameOK = true;
+                        if (!PathEx.IsValidFileName(newName))
                         {
-                            EnterDirectory(entry.Path);
+                            DialogBox.Open("Error", "The name you specified is not a valid file name. Try another.", DialogBox.Type.OK);
+                            renameOK = false;
+                        }
+
+                        if (renameOK)
+                        {
+                            if (ProjectLibrary.Exists(newPath))
+                            {
+                                DialogBox.Open("Error", "File/folder with that name already exists in this folder.", DialogBox.Type.OK);
+                                renameOK = false;
+                            }
+                        }
+
+                        if (renameOK)
+                        {
+                            ProjectLibrary.Rename(originalPath, newPath);
+                            StopRename();
                         }
                     }
-                }
-                else if (Input.IsButtonDown(ButtonCode.Back))
-                {
-                    LibraryEntry entry = ProjectLibrary.GetEntry(currentDirectory);
-                    if (entry != null && entry.Parent != null)
+                    else if (Input.IsButtonDown(ButtonCode.Escape))
                     {
-                        EnterDirectory(entry.Parent.Path);
+                        StopRename();
                     }
                 }
-                else if (Input.IsButtonDown(ButtonCode.Up))
-                {
-                    MoveSelection(MoveDirection.Up);
-                }
-                else if (Input.IsButtonDown(ButtonCode.Down))
-                {
-                    MoveSelection(MoveDirection.Down);
-                }
-                else if (Input.IsButtonDown(ButtonCode.Left))
-                {
-                    MoveSelection(MoveDirection.Left);
-                }
-                else if (Input.IsButtonDown(ButtonCode.Right))
-                {
-                    MoveSelection(MoveDirection.Right);
-                }
+            }
+            else
+            {
+                if(isRenameInProgress)
+                    StopRename();
             }
 
             if (autoScrollAmount != 0)
@@ -991,6 +1085,8 @@ namespace BansheeEditor
 
             entries.Clear();
             entryLookup.Clear();
+            inProgressRenameElement = null;
+
             scrollAreaPanel = contentScrollArea.Layout.AddPanel();
 
             RefreshDirectoryBar();
@@ -1376,6 +1472,56 @@ namespace BansheeEditor
                 Paste(currentDirectory);
         }
 
+        private void RenameSelection()
+        {
+            if (selectionPaths.Count == 0)
+                return;
+
+            if (selectionPaths.Count > 1)
+            {
+                DeselectAll();
+                Select(selectionPaths[0]);
+            }
+
+            ElementEntry entry;
+            if (entryLookup.TryGetValue(pingPath, out entry))
+            {
+                entry.StartRename();
+                inProgressRenameElement = entry;
+            }
+        }
+
+        private void StopRename()
+        {
+            if (inProgressRenameElement != null)
+            {
+                inProgressRenameElement.StopRename();
+                inProgressRenameElement = null;
+            }
+        }
+
+        private void DeleteSelection()
+        {
+            if (selectionPaths.Count == 0)
+                return;
+
+            DialogBox.Open("Confirm deletion", "Are you sure you want to delete the selected object(s)?",
+                DialogBox.Type.YesNo,
+                type =>
+                {
+                    if (type == DialogBox.ResultType.Yes)
+                    {
+                        foreach (var path in selectionPaths)
+                        {
+                            ProjectLibrary.Delete(path);
+                        }
+
+                        DeselectAll();
+                        Refresh();
+                    }
+                });
+        }
+
         private void OnSearchChanged(string newValue)
         {
             searchQuery = newValue;

+ 5 - 5
MBansheeEngine/GUI/GUIElement.cs

@@ -19,6 +19,11 @@ namespace BansheeEngine
             get { return Internal_GetVisualBounds(mCachedPtr); }
         }
 
+        public bool Visible
+        {
+            set { Internal_SetVisible(mCachedPtr, value); }
+        }
+
         private void InternalOnFocusChanged(bool focus)
         {
             if (OnFocusChanged != null)
@@ -30,11 +35,6 @@ namespace BansheeEngine
             Internal_Destroy(mCachedPtr);
         }
 
-        public void SetVisible(bool visible)
-        {
-            Internal_SetVisible(mCachedPtr, visible);
-        }
-
         public void SetPosition(int x, int y)
         {
             Internal_SetPosition(mCachedPtr, x, y);

+ 10 - 0
MBansheeEngine/GUI/GUITextBox.cs

@@ -5,6 +5,10 @@ namespace BansheeEngine
 {
     public sealed class GUITextBox : GUIElement
     {
+        public delegate void OnChangedDelegate(string newValue);
+
+        public event OnChangedDelegate OnChanged;
+
         public GUITextBox(bool multiline, string style, params GUIOption[] options)
         {
             Internal_CreateInstance(this, multiline, style, options);
@@ -36,6 +40,12 @@ namespace BansheeEngine
             Internal_SetTint(mCachedPtr, color);
         }
 
+        private void DoOnChanged(string newValue)
+        {
+            if (OnChanged != null)
+                OnChanged(newValue);
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_CreateInstance(GUITextBox instance, bool multiline, string style, GUIOption[] options);
 

+ 6 - 0
MBansheeEngine/PathEx.cs

@@ -34,5 +34,11 @@ namespace BansheeEngine
 
             return path.Remove(path.Length - tail.Length);
         }
+
+        public static bool IsValidFileName(string name)
+        {
+            return !string.IsNullOrWhiteSpace(name) &&
+                   name.IndexOfAny(Path.GetInvalidFileNameChars()) < 0;
+        }
     }
 }

+ 5 - 0
SBansheeEngine/Include/BsScriptGUIInputBox.h

@@ -18,6 +18,11 @@ namespace BansheeEngine
 		static void internal_getText(ScriptGUIInputBox* nativeInstance, MonoString** text);
 		static void internal_setTint(ScriptGUIInputBox* nativeInstance, Color color);
 
+		static void onChanged(MonoObject* instance, const WString& newValue);
+
+		typedef void(__stdcall *OnChangedThunkDef) (MonoObject*, MonoString*, MonoException**);
+		static OnChangedThunkDef onChangedThunk;
+
 		ScriptGUIInputBox(MonoObject* instance, GUIInputBox* inputBox);
 	};
 }

+ 19 - 8
SBansheeEngine/Source/BsScriptGUIInputBox.cpp

@@ -1,21 +1,18 @@
 #include "BsScriptGUIInputBox.h"
 #include "BsScriptMeta.h"
-#include "BsMonoField.h"
+#include "BsMonoMethod.h"
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
-#include "BsSpriteTexture.h"
 #include "BsMonoUtil.h"
-#include "BsGUILayout.h"
 #include "BsGUIInputBox.h"
 #include "BsGUIOptions.h"
-#include "BsScriptSpriteTexture.h"
-#include "BsScriptGUIElementStyle.h"
-#include "BsScriptGUILayout.h"
-#include "BsScriptHString.h"
-#include "BsScriptGUIContent.h"
+
+using namespace std::placeholders;
 
 namespace BansheeEngine
 {
+	ScriptGUIInputBox::OnChangedThunkDef ScriptGUIInputBox::onChangedThunk;
+
 	ScriptGUIInputBox::ScriptGUIInputBox(MonoObject* instance, GUIInputBox* inputBox)
 		:TScriptGUIElement(instance, inputBox)
 	{
@@ -28,6 +25,8 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_GetText", &ScriptGUIInputBox::internal_getText);
 		metaData.scriptClass->addInternalCall("Internal_SetText", &ScriptGUIInputBox::internal_setText);
 		metaData.scriptClass->addInternalCall("Internal_SetTint", &ScriptGUIInputBox::internal_setTint);
+
+		onChangedThunk = (OnChangedThunkDef)metaData.scriptClass->getMethod("DoOnChanged", 1)->getThunk();
 	}
 
 	void ScriptGUIInputBox::internal_createInstance(MonoObject* instance, bool multiline, MonoString* style, MonoArray* guiOptions)
@@ -39,6 +38,8 @@ namespace BansheeEngine
 			options.addOption(mono_array_get(guiOptions, GUIOption, i));
 
 		GUIInputBox* guiInputBox = GUIInputBox::create(multiline, options, toString(MonoUtil::monoToWString(style)));
+		guiInputBox->onValueChanged.connect(std::bind(&ScriptGUIInputBox::onChanged, instance, _1));
+
 
 		ScriptGUIInputBox* nativeInstance = new (bs_alloc<ScriptGUIInputBox>()) ScriptGUIInputBox(instance, guiInputBox);
 	}
@@ -60,4 +61,14 @@ namespace BansheeEngine
 		GUIInputBox* inputBox = (GUIInputBox*)nativeInstance->getGUIElement();
 		inputBox->setTint(color);
 	}
+
+	void ScriptGUIInputBox::onChanged(MonoObject* instance, const WString& newValue)
+	{
+		MonoString* monoValue = MonoUtil::wstringToMono(MonoManager::instance().getDomain(), newValue);
+
+		MonoException* exception = nullptr;
+		onChangedThunk(instance, monoValue, &exception);
+
+		MonoUtil::throwIfException(exception);
+	}
 }

+ 0 - 2
TODO.txt

@@ -25,8 +25,6 @@ return them in checkForModifications?
 ----------------------------------------------------------------------
 Project window
 
-Dropping doesn't work. endDrag in DragAndDropManager gets called before cursorReleased()
-
 Later:
  - Hook up ping effect so it triggers when I select a resource or sceneobject
   - Add ping to SceneTreeView