From 3f0cebd17f8edc492df984028ba5b19aac3a807c Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 22 Dec 2023 11:44:16 -0700 Subject: [PATCH] Added alt+arrow reorder of bookmarks fixed #1309 --- .../Glue/Controls/MainPanelControl.xaml.cs | 20 +- FRBDK/Glue/Glue/Plugins/PluginBase.cs | 6 + FRBDK/Glue/Glue/Plugins/PluginManager.cs | 23 +- .../TreeViewPlugin/MainTreeViewPlugin.cs | 6 +- .../Views/MainTreeViewControl.xaml | 1 + .../Views/MainTreeViewControl.xaml.cs | 1285 +++++++++-------- 6 files changed, 716 insertions(+), 625 deletions(-) diff --git a/FRBDK/Glue/Glue/Controls/MainPanelControl.xaml.cs b/FRBDK/Glue/Glue/Controls/MainPanelControl.xaml.cs index aa92dec16..79caab1a7 100644 --- a/FRBDK/Glue/Glue/Controls/MainPanelControl.xaml.cs +++ b/FRBDK/Glue/Glue/Controls/MainPanelControl.xaml.cs @@ -276,16 +276,20 @@ private void InitializeThemes() private void UserControl_PreviewKeyDown(object sender, KeyEventArgs e) { - // If this is coming from a text box, don't try to apply hotkeys - // Maybe in the future we want to be selective, like only apply certain - // hotkeys (ctrl+f) but not others (delete)? - var isTextBox = e.OriginalSource is TextBoxBase; + var handledByPlugin = PluginManager.IsHandlingHotkeys(); + if (!handledByPlugin) + { + // If this is coming from a text box, don't try to apply hotkeys + // Maybe in the future we want to be selective, like only apply certain + // hotkeys (ctrl+f) but not others (delete)? + var isTextBox = e.OriginalSource is TextBoxBase; - var isHandled = HotkeyManager.Self.TryHandleKeys(e, isTextBox).Result; + var isHandled = HotkeyManager.Self.TryHandleKeys(e, isTextBox).Result; - if (isHandled) - { - e.Handled = true; + if (isHandled) + { + e.Handled = true; + } } } diff --git a/FRBDK/Glue/Glue/Plugins/PluginBase.cs b/FRBDK/Glue/Glue/Plugins/PluginBase.cs index d48838078..b85d8fde2 100644 --- a/FRBDK/Glue/Glue/Plugins/PluginBase.cs +++ b/FRBDK/Glue/Glue/Plugins/PluginBase.cs @@ -535,6 +535,12 @@ protected async Task ReactToPluginEventWithReturn(string eventName, stri /// public Func ReactToObjectReordered; + /// + /// Raised to determine if a plugin should handle a hotkey. A plugin should return true if it has its own hotkey handling given + /// its current state, such as if a control has focus. + /// + public Func IsHandlingHotkeys; + #endregion public abstract void StartUp(); diff --git a/FRBDK/Glue/Glue/Plugins/PluginManager.cs b/FRBDK/Glue/Glue/Plugins/PluginManager.cs index 990671a95..7e2493774 100644 --- a/FRBDK/Glue/Glue/Plugins/PluginManager.cs +++ b/FRBDK/Glue/Glue/Plugins/PluginManager.cs @@ -1001,6 +1001,23 @@ public static void ReactToNewObject(NamedObjectSave newObject) => plugin => plugin.ReactToNewObjectHandler(newObject), plugin => plugin.ReactToNewObjectHandler != null); + internal static bool IsHandlingHotkeys() + { + var toReturn = false; + + CallMethodOnPlugin( + plugin => + { + if(toReturn == false && plugin.IsHandlingHotkeys()) + { + toReturn = true; + } + }, + plugin => plugin.IsHandlingHotkeys != null); + + return toReturn; + } + public static Task ReactToNewObjectListAsync(List newObjectList) { return CallMethodOnPluginAsync(async (plugin) => @@ -1029,12 +1046,11 @@ public static Task ReactToNewObjectListAsync(List newObjectList plugin => plugin.ReactToNewObjectHandler != null || plugin.ReactToNewObjectList != null || plugin.ReactToNewObjectListAsync != null); } - internal static void ReactToObjectRemoved(IElement element, NamedObjectSave removedObject) - { + internal static void ReactToObjectRemoved(IElement element, NamedObjectSave removedObject) => CallMethodOnPlugin( plugin => plugin.ReactToObjectRemoved(element, removedObject), plugin => plugin.ReactToObjectRemoved != null); - } + public static void TryAssignPreferredDisplayerFromName(CustomVariable customVariable) { @@ -2498,5 +2514,6 @@ static void ResumeRelativeDirectory(string function) } } + } } diff --git a/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/MainTreeViewPlugin.cs b/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/MainTreeViewPlugin.cs index 7d2ab435a..e2985a29c 100644 --- a/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/MainTreeViewPlugin.cs +++ b/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/MainTreeViewPlugin.cs @@ -37,11 +37,6 @@ class MainTreeViewPlugin : PluginBase #endregion - public override bool ShutDown(PluginShutDownReason shutDownReason) - { - return true; - } - public override void StartUp() { var pixelHeight = GlueState.Self.GlueSettingsSave.BookmarkRowHeight > 0 @@ -106,6 +101,7 @@ private void AssignEvents() ReactToCtrlF += HandleCtrlF; ReactToItemsSelected += HandleItemsSelected; TryHandleTreeNodeDoubleClicked += TryHandleTreeNodeDoubleClick; + IsHandlingHotkeys += () => mainView.Bookmarks.IsFocused || mainView.Bookmarks.IsKeyboardFocusWithin; } private bool TryHandleTreeNodeDoubleClick(ITreeNode arg) diff --git a/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/Views/MainTreeViewControl.xaml b/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/Views/MainTreeViewControl.xaml index c8440dd62..f597822aa 100644 --- a/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/Views/MainTreeViewControl.xaml +++ b/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/Views/MainTreeViewControl.xaml @@ -78,6 +78,7 @@ Drop="Bookmarks_Drop" SelectionChanged="Bookmarks_SelectionChanged" KeyDown="Bookmarks_KeyDown" + PreviewKeyDown="Bookmarks_PreviewKeyDown" LostFocus="Bookmarks_LostFocus" MouseDoubleClick="Bookmarks_MouseDoubleClick" ItemsSource="{Binding Bookmarks}" diff --git a/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/Views/MainTreeViewControl.xaml.cs b/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/Views/MainTreeViewControl.xaml.cs index a6a7e1b61..c50db9dae 100644 --- a/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/Views/MainTreeViewControl.xaml.cs +++ b/FRBDK/Glue/OfficialPlugins/TreeViewPlugin/Views/MainTreeViewControl.xaml.cs @@ -9,840 +9,907 @@ using OfficialPlugins.TreeViewPlugin.ViewModels; using System; using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; -namespace OfficialPlugins.TreeViewPlugin.Views -{ +namespace OfficialPlugins.TreeViewPlugin.Views; - /// - /// Interaction logic for MainTreeViewControl.xaml - /// - public partial class MainTreeViewControl : UserControl - { - #region Enums - public enum LeftOrRight - { - Left, - Right - } +/// +/// Interaction logic for MainTreeViewControl.xaml +/// +public partial class MainTreeViewControl : UserControl +{ + #region Enums - #endregion + public enum LeftOrRight + { + Left, + Right + } - #region Fields/Properties + #endregion - LeftOrRight ButtonPressed; + #region Fields/Properties - MainTreeViewViewModel ViewModel => DataContext as MainTreeViewViewModel; + LeftOrRight ButtonPressed; - #endregion + MainTreeViewViewModel ViewModel => DataContext as MainTreeViewViewModel; - public MainTreeViewControl() - { - InitializeComponent(); - } + #endregion - #region Hotkey + public MainTreeViewControl() + { + InitializeComponent(); + } - private async void MainTreeView_KeyDown(object sender, KeyEventArgs e) - { - var ctrlDown = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; - var altDown = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt; - var shiftDown = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift; + #region Hotkey + + private async void MainTreeView_KeyDown(object sender, KeyEventArgs e) + { + var ctrlDown = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; + var altDown = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt; + var shiftDown = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift; - if (e.Key == Key.Enter) + if (e.Key == Key.Enter) + { + var selectedNode = SelectionLogic.CurrentNode; + GlueCommands.Self.TreeNodeCommands.HandleTreeNodeDoubleClicked(selectedNode); + e.Handled = true; + } + else if(e.Key == Key.Delete) + { + HotkeyManager.HandleDeletePressed(); + e.Handled = true; + } + else if(e.Key==Key.N && ctrlDown) + { + e.Handled=true; + ITreeNode currentNode = SelectionLogic.CurrentNode; + if(currentNode.IsFilesContainerNode()) { - var selectedNode = SelectionLogic.CurrentNode; - GlueCommands.Self.TreeNodeCommands.HandleTreeNodeDoubleClicked(selectedNode); - e.Handled = true; + await GlueCommands.Self.DialogCommands.ShowAddNewFileDialogAsync(); } - else if(e.Key == Key.Delete) + else if(currentNode.IsRootNamedObjectNode()) { - HotkeyManager.HandleDeletePressed(); - e.Handled = true; + await GlueCommands.Self.DialogCommands.ShowAddNewObjectDialog(); } - else if(e.Key==Key.N && ctrlDown) + else if(currentNode.IsRootCustomVariablesNode()) { - e.Handled=true; - ITreeNode currentNode = SelectionLogic.CurrentNode; - if(currentNode.IsFilesContainerNode()) - { - await GlueCommands.Self.DialogCommands.ShowAddNewFileDialogAsync(); - } - else if(currentNode.IsRootNamedObjectNode()) - { - await GlueCommands.Self.DialogCommands.ShowAddNewObjectDialog(); - } - else if(currentNode.IsRootCustomVariablesNode()) - { - GlueCommands.Self.DialogCommands.ShowAddNewVariableDialog(); - } - else if(currentNode.IsRootStateNode()) - { - GlueCommands.Self.DialogCommands.ShowAddNewCategoryDialog(); - } - else if(currentNode.IsStateCategoryNode()) - { - // show new state? That doesn't currently exist in the DialogCommands - } - else if(currentNode.IsRootEventsNode()) - { - GlueCommands.Self.DialogCommands.ShowAddNewEventDialog((NamedObjectSave)null); - } - else if(currentNode.IsRootEntityNode()) - { - GlueCommands.Self.DialogCommands.ShowAddNewEntityDialog(); - } - else if(currentNode.IsRootScreenNode()) - { - GlueCommands.Self.DialogCommands.ShowAddNewScreenDialog(); - } + GlueCommands.Self.DialogCommands.ShowAddNewVariableDialog(); } - else if(e.Key == Key.F2) + else if(currentNode.IsRootStateNode()) { - if(SelectionLogic.CurrentNode?.IsEditable == true) - { - SelectionLogic.CurrentNode.IsEditing = true; - } + GlueCommands.Self.DialogCommands.ShowAddNewCategoryDialog(); + } + else if(currentNode.IsStateCategoryNode()) + { + // show new state? That doesn't currently exist in the DialogCommands + } + else if(currentNode.IsRootEventsNode()) + { + GlueCommands.Self.DialogCommands.ShowAddNewEventDialog((NamedObjectSave)null); } - else if(await HotkeyManager.Self.TryHandleKeys(e, isTextBoxFocused:false)) + else if(currentNode.IsRootEntityNode()) { - e.Handled = true; + GlueCommands.Self.DialogCommands.ShowAddNewEntityDialog(); + } + else if(currentNode.IsRootScreenNode()) + { + GlueCommands.Self.DialogCommands.ShowAddNewScreenDialog(); } } - - public void FocusSearchBox() + else if(e.Key == Key.F2) { - SearchBar.FocusTextBox(); + if(SelectionLogic.CurrentNode?.IsEditable == true) + { + SelectionLogic.CurrentNode.IsEditing = true; + } } + else if(await HotkeyManager.Self.TryHandleKeys(e, isTextBoxFocused:false)) + { + e.Handled = true; + } + } + + public void FocusSearchBox() + { + SearchBar.FocusTextBox(); + } - #endregion + #endregion - #region Drag+drop - Point startPoint; - NodeViewModel nodePushed; - NodeViewModel nodeWaitingOnSelection; + #region Drag+drop + Point startPoint; + NodeViewModel nodePushed; + NodeViewModel nodeWaitingOnSelection; - DateTime lastClick; - private void MainTreeView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + DateTime lastClick; + private void MainTreeView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + // Normally tree nodes are selected + // on a push, not click. However, this + // default behavior would unload the current + // editor level and show the new selection. This + // is distracting, and we want to allow the user to + // drag+drop entities into screens to create new instances + // without having to deselect the room. To do this, we suppress + // the default selected behavior by setting e.Handled=true down below. + // Update - by suppressing the click, we also suppress the double-click. + // to solve this, we keep track of how often a click happens and if it's faster + // than .25 seconds, we manually call the DoubleClick event. + if(e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed) { - // Normally tree nodes are selected - // on a push, not click. However, this - // default behavior would unload the current - // editor level and show the new selection. This - // is distracting, and we want to allow the user to - // drag+drop entities into screens to create new instances - // without having to deselect the room. To do this, we suppress - // the default selected behavior by setting e.Handled=true down below. - // Update - by suppressing the click, we also suppress the double-click. - // to solve this, we keep track of how often a click happens and if it's faster - // than .25 seconds, we manually call the DoubleClick event. - if(e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed) + var timeSinceLastClick = DateTime.Now - lastClick; + if(timeSinceLastClick.TotalSeconds < .25) { - var timeSinceLastClick = DateTime.Now - lastClick; - if(timeSinceLastClick.TotalSeconds < .25) - { - MainTreeView_MouseDoubleClick(this, e); - } - lastClick = DateTime.Now; - startPoint = e.GetPosition(null); + MainTreeView_MouseDoubleClick(this, e); } + lastClick = DateTime.Now; + startPoint = e.GetPosition(null); + } - var objectPushed = e.OriginalSource; - var frameworkElementPushed = (objectPushed as FrameworkElement); + var objectPushed = e.OriginalSource; + var frameworkElementPushed = (objectPushed as FrameworkElement); - nodePushed = frameworkElementPushed?.DataContext as NodeViewModel; + nodePushed = frameworkElementPushed?.DataContext as NodeViewModel; - //MainTreeView. - if (e.LeftButton == MouseButtonState.Pressed) - (sender as ListBox).ReleaseMouseCapture(); + //MainTreeView. + if (e.LeftButton == MouseButtonState.Pressed) + (sender as ListBox).ReleaseMouseCapture(); - if(nodePushed != null && ClickedOnGrid(objectPushed as FrameworkElement)) - { - nodeWaitingOnSelection = nodePushed; - // don't select anything (yet) - e.Handled = true; + if(nodePushed != null && ClickedOnGrid(objectPushed as FrameworkElement)) + { + nodeWaitingOnSelection = nodePushed; + // don't select anything (yet) + e.Handled = true; - MainTreeView.Focus(); - } + MainTreeView.Focus(); } + } - private void MainTreeView_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) - { + private void MainTreeView_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) + { - var objectPushed = e.OriginalSource; - var frameworkElementPushed = (objectPushed as FrameworkElement); + var objectPushed = e.OriginalSource; + var frameworkElementPushed = (objectPushed as FrameworkElement); - if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed) + if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed) + { + var timeSinceLastClick = DateTime.Now - lastClick; + if (timeSinceLastClick.TotalSeconds < .25) { - var timeSinceLastClick = DateTime.Now - lastClick; - if (timeSinceLastClick.TotalSeconds < .25) - { - MainTreeView_MouseDoubleClick(this, e); - } - lastClick = DateTime.Now; - startPoint = e.GetPosition(null); + MainTreeView_MouseDoubleClick(this, e); } + lastClick = DateTime.Now; + startPoint = e.GetPosition(null); + } - if(e.RightButton == MouseButtonState.Pressed) - { - nodePushed = frameworkElementPushed?.DataContext as NodeViewModel; - } - // tree nodes may get selected when they are created rather than through a click (which changes the - // view model). Vic isn't sure why so this is a little bit of a hack: - RefreshRightClickMenu(nodePushed); + if(e.RightButton == MouseButtonState.Pressed) + { + nodePushed = frameworkElementPushed?.DataContext as NodeViewModel; } + // tree nodes may get selected when they are created rather than through a click (which changes the + // view model). Vic isn't sure why so this is a little bit of a hack: + RefreshRightClickMenu(nodePushed); + } - public void RefreshRightClickMenu(ITreeNode forcedNode = null) - { - var node = forcedNode ?? SelectionLogic.CurrentNode; + public void RefreshRightClickMenu(ITreeNode forcedNode = null) + { + var node = forcedNode ?? SelectionLogic.CurrentNode; - RightClickContextMenu.Items.Clear(); - if(node != null) + RightClickContextMenu.Items.Clear(); + if(node != null) + { + var items = RightClickHelper.GetRightClickItems(node, MenuShowingAction.RegularRightClick); + foreach (var item in items) { - var items = RightClickHelper.GetRightClickItems(node, MenuShowingAction.RegularRightClick); - foreach (var item in items) - { - var wpfItem = CreateWpfItemFor(item); - RightClickContextMenu.Items.Add(wpfItem); - } + var wpfItem = CreateWpfItemFor(item); + RightClickContextMenu.Items.Add(wpfItem); } } + } - private bool ClickedOnGrid(FrameworkElement frameworkElement) + private bool ClickedOnGrid(FrameworkElement frameworkElement) + { + if(frameworkElement.Name == "ItemGrid") { - if(frameworkElement.Name == "ItemGrid") - { - return true; - } - - if(frameworkElement.Parent is not FrameworkElement parent) - { - return false; - } - - return ClickedOnGrid(parent); + return true; } - private void MainTreeView_PreviewMouseMove(object sender, MouseEventArgs e) + if(frameworkElement.Parent is not FrameworkElement parent) { - // Get the current mouse position - Point mousePos = e.GetPosition(null); - Vector diff = startPoint - mousePos; + return false; + } - var isMouseButtonPressed = - e.LeftButton == MouseButtonState.Pressed || - e.RightButton == MouseButtonState.Pressed; + return ClickedOnGrid(parent); + } - if (isMouseButtonPressed && - - (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || - Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)) - { - ButtonPressed = e.LeftButton == MouseButtonState.Pressed ? - LeftOrRight.Left : LeftOrRight.Right; + private void MainTreeView_PreviewMouseMove(object sender, MouseEventArgs e) + { + // Get the current mouse position + Point mousePos = e.GetPosition(null); + Vector diff = startPoint - mousePos; - GlueState.Self.DraggedTreeNode = nodePushed; - // Get the dragged ListViewItem - var vm = (e.OriginalSource as FrameworkElement).DataContext as NodeViewModel; + var isMouseButtonPressed = + e.LeftButton == MouseButtonState.Pressed || + e.RightButton == MouseButtonState.Pressed; - if(vm != null) - { - // Initialize the drag & drop operation - DataObject dragData = new DataObject("NodeViewModel", vm); - DragDrop.DoDragDrop(e.OriginalSource as DependencyObject, dragData, DragDropEffects.Move); - } - } - if(!isMouseButtonPressed && nodePushed != null) + if (isMouseButtonPressed && + + (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || + Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)) + { + ButtonPressed = e.LeftButton == MouseButtonState.Pressed ? + LeftOrRight.Left : LeftOrRight.Right; + + GlueState.Self.DraggedTreeNode = nodePushed; + // Get the dragged ListViewItem + var vm = (e.OriginalSource as FrameworkElement).DataContext as NodeViewModel; + + if(vm != null) { - nodePushed = null; + // Initialize the drag & drop operation + DataObject dragData = new DataObject("NodeViewModel", vm); + DragDrop.DoDragDrop(e.OriginalSource as DependencyObject, dragData, DragDropEffects.Move); } } + if(!isMouseButtonPressed && nodePushed != null) + { + nodePushed = null; + } + } - private void MainTreeView_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e) + private void MainTreeView_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e) + { + var objectPushed = e.OriginalSource; + var frameworkElementPushed = (objectPushed as FrameworkElement); + if (frameworkElementPushed?.DataContext as NodeViewModel == nodePushed) { - var objectPushed = e.OriginalSource; - var frameworkElementPushed = (objectPushed as FrameworkElement); - if (frameworkElementPushed?.DataContext as NodeViewModel == nodePushed) - { - SelectionLogic.HandleSelected(nodePushed, focus: true, replaceSelection: true); + SelectionLogic.HandleSelected(nodePushed, focus: true, replaceSelection: true); - } - - nodePushed = null; } - private void MainTreeView_DragEnter(object sender, DragEventArgs e) + nodePushed = null; + } + + private void MainTreeView_DragEnter(object sender, DragEventArgs e) + { + if (//!e.Data.GetDataPresent("myFormat") || + sender == e.Source) { - if (//!e.Data.GetDataPresent("myFormat") || - sender == e.Source) - { - e.Effects = DragDropEffects.None; - } + e.Effects = DragDropEffects.None; } + } - private void MainTreeView_Drop(object sender, DragEventArgs e) - { - var isCancelled = Keyboard.IsKeyDown(Key.Escape); + private void MainTreeView_Drop(object sender, DragEventArgs e) + { + var isCancelled = Keyboard.IsKeyDown(Key.Escape); - if(!isCancelled) + if(!isCancelled) + { + if(e.Data.GetDataPresent("FileDrop")) { - if(e.Data.GetDataPresent("FileDrop")) - { - HandleDropFileFromExplorerWindow(e); - } - else - { - HandleDropTreeNodeOnTreeNode(e); - } + HandleDropFileFromExplorerWindow(e); + } + else + { + HandleDropTreeNodeOnTreeNode(e); } } + } - private void HandleDropFileFromExplorerWindow(DragEventArgs e) - { - FilePath[] droppedFiles = ((string[])e.Data.GetData("FileDrop")) - .Select(item => new FilePath(item)) - .ToArray(); - - var targetNode = (e.OriginalSource as FrameworkElement).DataContext as NodeViewModel; + private void HandleDropFileFromExplorerWindow(DragEventArgs e) + { + FilePath[] droppedFiles = ((string[])e.Data.GetData("FileDrop")) + .Select(item => new FilePath(item)) + .ToArray(); - DragDropManager.Self.HandleDropExternalFileOnTreeNode(droppedFiles, targetNode); - } + var targetNode = (e.OriginalSource as FrameworkElement).DataContext as NodeViewModel; - private async void HandleDropTreeNodeOnTreeNode(DragEventArgs e) - { - // There's a bug in the tree view when dragging quickly, which can result in the wrong item dropped. - // To solve this, we're going to use the NodePushed. For more info on the bug, see this: - // https://github.com/vchelaru/FlatRedBall/issues/312 - //var objectDragged = e.Data.GetData("NodeViewModel"); - var targetNode = (e.OriginalSource as FrameworkElement).DataContext as NodeViewModel; + DragDropManager.Self.HandleDropExternalFileOnTreeNode(droppedFiles, targetNode); + } - if (nodePushed != null && targetNode != null) - { - //if (nodePushed.IsSelected == false) - //{ - // This addresses a bug in the tree view which can result in "rolling selection" as you grab - // and drag down the tree view quickly. It won't produce a bug anymore (see above) but this is just for visual confirmation. - // Update, we no longer select on a push anyway - //nodePushed.IsSelected = true; - //} - if (ButtonPressed == LeftOrRight.Left || targetNode == nodePushed) + private async void HandleDropTreeNodeOnTreeNode(DragEventArgs e) + { + // There's a bug in the tree view when dragging quickly, which can result in the wrong item dropped. + // To solve this, we're going to use the NodePushed. For more info on the bug, see this: + // https://github.com/vchelaru/FlatRedBall/issues/312 + //var objectDragged = e.Data.GetData("NodeViewModel"); + var targetNode = (e.OriginalSource as FrameworkElement).DataContext as NodeViewModel; + + if (nodePushed != null && targetNode != null) + { + //if (nodePushed.IsSelected == false) + //{ + // This addresses a bug in the tree view which can result in "rolling selection" as you grab + // and drag down the tree view quickly. It won't produce a bug anymore (see above) but this is just for visual confirmation. + // Update, we no longer select on a push anyway + //nodePushed.IsSelected = true; + //} + if (ButtonPressed == LeftOrRight.Left || targetNode == nodePushed) + { + // do something here... + await DragDropManager.DragDropTreeNode(targetNode, nodePushed); + if (ButtonPressed == LeftOrRight.Right) { - // do something here... - await DragDropManager.DragDropTreeNode(targetNode, nodePushed); - if (ButtonPressed == LeftOrRight.Right) - { - RightClickContextMenu.IsOpen = true;// test this - } + RightClickContextMenu.IsOpen = true;// test this } - else - { - await SelectionLogic.SelectByTag(targetNode.Tag, false); - - var items = RightClickHelper.GetRightClickItems(targetNode, MenuShowingAction.RightButtonDrag, nodePushed); + } + else + { + await SelectionLogic.SelectByTag(targetNode.Tag, false); + var items = RightClickHelper.GetRightClickItems(targetNode, MenuShowingAction.RightButtonDrag, nodePushed); - RightClickContextMenu.Items.Clear(); - foreach (var item in items) - { - var wpfItem = CreateWpfItemFor(item); - RightClickContextMenu.Items.Add(wpfItem); - } - // Do this or it closes immediately - // 100 too fast - await System.Threading.Tasks.Task.Delay(300); - RightClickContextMenu.IsOpen = true;// test this + RightClickContextMenu.Items.Clear(); + foreach (var item in items) + { + var wpfItem = CreateWpfItemFor(item); + RightClickContextMenu.Items.Add(wpfItem); } + // Do this or it closes immediately + // 100 too fast + await System.Threading.Tasks.Task.Delay(300); + RightClickContextMenu.IsOpen = true;// test this + } } + } - public object CreateWpfItemFor(GlueFormsCore.FormHelpers.GeneralToolStripMenuItem item) + public object CreateWpfItemFor(GlueFormsCore.FormHelpers.GeneralToolStripMenuItem item) + { + if (item.Text == "-") { - if (item.Text == "-") - { - var separator = new Separator(); - return separator; - } - else + var separator = new Separator(); + return separator; + } + else + { + var menuItem = new MenuItem(); + menuItem.Icon = item.Image; + menuItem.Header = item.Text; + menuItem.Click += (not, used) => { - var menuItem = new MenuItem(); - menuItem.Icon = item.Image; - menuItem.Header = item.Text; - menuItem.Click += (not, used) => - { - item?.Click?.Invoke(menuItem, null); - }; + item?.Click?.Invoke(menuItem, null); + }; - foreach (var child in item.DropDownItems) - { - var wpfItem = CreateWpfItemFor(child); - menuItem.Items.Add(wpfItem); - } - - return menuItem; + foreach (var child in item.DropDownItems) + { + var wpfItem = CreateWpfItemFor(child); + menuItem.Items.Add(wpfItem); } - } - private void MainTreeView_DragLeave(object sender, DragEventArgs e) - { - // If the user leaves, then set the nodeWaitingOnSelection to null so that a later push doesn't select - // the node that was dragged off - nodeWaitingOnSelection = null; + return menuItem; } + } + private void MainTreeView_DragLeave(object sender, DragEventArgs e) + { + // If the user leaves, then set the nodeWaitingOnSelection to null so that a later push doesn't select + // the node that was dragged off + nodeWaitingOnSelection = null; + } - private void MainTreeView_DragOver(object sender, DragEventArgs e) - { - ListBox li = sender as ListBox; - ScrollViewer sv = FindVisualChild(li); - double tolerance = 24; - double verticalPos = e.GetPosition(li).Y; + private void MainTreeView_DragOver(object sender, DragEventArgs e) + { + ListBox li = sender as ListBox; + ScrollViewer sv = FindVisualChild(li); - double topMargin = tolerance; - var bottomMargin = li.ActualHeight - tolerance; - if(sv.ComputedHorizontalScrollBarVisibility == Visibility.Visible) - { - var horizontalScrollBar = sv.Template.FindName("PART_HorizontalScrollBar", sv) as System.Windows.Controls.Primitives.ScrollBar; + double tolerance = 24; + double verticalPos = e.GetPosition(li).Y; - if(horizontalScrollBar != null) - { - bottomMargin -= horizontalScrollBar.ActualHeight; - } - } + double topMargin = tolerance; + var bottomMargin = li.ActualHeight - tolerance; + if(sv.ComputedHorizontalScrollBarVisibility == Visibility.Visible) + { + var horizontalScrollBar = sv.Template.FindName("PART_HorizontalScrollBar", sv) as System.Windows.Controls.Primitives.ScrollBar; - double distanceToScroll = 3; - if (verticalPos < topMargin) // Top of visible list? - { - sv.ScrollToVerticalOffset(sv.VerticalOffset - distanceToScroll); //Scroll up. - } - else if (verticalPos > bottomMargin) //Bottom of visible list? + if(horizontalScrollBar != null) { - sv.ScrollToVerticalOffset(sv.VerticalOffset + distanceToScroll); //Scroll down. + bottomMargin -= horizontalScrollBar.ActualHeight; } } - public static childItem FindVisualChild(DependencyObject obj) where childItem : DependencyObject + double distanceToScroll = 3; + if (verticalPos < topMargin) // Top of visible list? { - // Search immediate children first (breadth-first) - for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) - { - DependencyObject child = VisualTreeHelper.GetChild(obj, i); + sv.ScrollToVerticalOffset(sv.VerticalOffset - distanceToScroll); //Scroll up. + } + else if (verticalPos > bottomMargin) //Bottom of visible list? + { + sv.ScrollToVerticalOffset(sv.VerticalOffset + distanceToScroll); //Scroll down. + } + } - if (child != null && child is childItem) - return (childItem)child; + public static childItem FindVisualChild(DependencyObject obj) where childItem : DependencyObject + { + // Search immediate children first (breadth-first) + for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) + { + DependencyObject child = VisualTreeHelper.GetChild(obj, i); - else - { - childItem childOfChild = FindVisualChild(child); + if (child != null && child is childItem) + return (childItem)child; - if (childOfChild != null) - return childOfChild; - } - } + else + { + childItem childOfChild = FindVisualChild(child); - return null; + if (childOfChild != null) + return childOfChild; + } } - #endregion + return null; + } + + #endregion - #region Selection + #region Selection - private void MainTreeView_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) + private void MainTreeView_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + if(nodeWaitingOnSelection != null) { - if(nodeWaitingOnSelection != null) - { - // don't push deselection out: - //var wasPushing = SelectionLogic.IsPushingSelectionOutToGlue; - //SelectionLogic.IsPushingSelectionOutToGlue = false; - //ViewModel.DeselectResursively(); - //SelectionLogic.IsPushingSelectionOutToGlue = wasPushing; - //nodeWaitingOnSelection.IsSelected = true; + // don't push deselection out: + //var wasPushing = SelectionLogic.IsPushingSelectionOutToGlue; + //SelectionLogic.IsPushingSelectionOutToGlue = false; + //ViewModel.DeselectResursively(); + //SelectionLogic.IsPushingSelectionOutToGlue = wasPushing; + //nodeWaitingOnSelection.IsSelected = true; - SelectionLogic.HandleSelected(nodeWaitingOnSelection, focus: true, replaceSelection: true); + SelectionLogic.HandleSelected(nodeWaitingOnSelection, focus: true, replaceSelection: true); - nodeWaitingOnSelection = null; - } + nodeWaitingOnSelection = null; } + } - // This makes the selection not happen on push+move as explained here: - // https://stackoverflow.com/questions/2645265/wpf-listbox-click-and-drag-selects-other-items - private void MainTreeView_MouseMove(object sender, MouseEventArgs e) - { - if (e.LeftButton == MouseButtonState.Pressed) - (sender as ListBox).ReleaseMouseCapture(); - } + // This makes the selection not happen on push+move as explained here: + // https://stackoverflow.com/questions/2645265/wpf-listbox-click-and-drag-selects-other-items + private void MainTreeView_MouseMove(object sender, MouseEventArgs e) + { + if (e.LeftButton == MouseButtonState.Pressed) + (sender as ListBox).ReleaseMouseCapture(); + } - #endregion + #endregion - #region Double-click + #region Double-click - private void MainTreeView_MouseDoubleClick(object sender, MouseButtonEventArgs e) + private void MainTreeView_MouseDoubleClick(object sender, MouseButtonEventArgs e) + { + // If we rely on the selected node, then double-clicking the up or down arrows + // on the scroll bar also cause a strong select. Instead, use what was actually clicked: + //var selectedNode = SelectionLogic.CurrentNode; + var objectPushed = e.OriginalSource; + var frameworkElementPushed = (objectPushed as FrameworkElement); + var nodeViewModel = frameworkElementPushed?.DataContext as NodeViewModel; + if(nodeViewModel != null) { - // If we rely on the selected node, then double-clicking the up or down arrows - // on the scroll bar also cause a strong select. Instead, use what was actually clicked: - //var selectedNode = SelectionLogic.CurrentNode; - var objectPushed = e.OriginalSource; - var frameworkElementPushed = (objectPushed as FrameworkElement); - var nodeViewModel = frameworkElementPushed?.DataContext as NodeViewModel; - if(nodeViewModel != null) - { - GlueCommands.Self.TreeNodeCommands.HandleTreeNodeDoubleClicked(nodeViewModel); - } + GlueCommands.Self.TreeNodeCommands.HandleTreeNodeDoubleClicked(nodeViewModel); } + } - private void Bookmarks_MouseDoubleClick(object sender, MouseButtonEventArgs e) + private void Bookmarks_MouseDoubleClick(object sender, MouseButtonEventArgs e) + { + var objectPushed = e.OriginalSource; + var frameworkElementPushed = (objectPushed as FrameworkElement); + var nodeViewModel = frameworkElementPushed?.DataContext as BookmarkViewModel; + if(nodeViewModel != null) { - var objectPushed = e.OriginalSource; - var frameworkElementPushed = (objectPushed as FrameworkElement); - var nodeViewModel = frameworkElementPushed?.DataContext as BookmarkViewModel; - if(nodeViewModel != null) - { - var separated = nodeViewModel.Text.Split('/').ToList(); + var separated = nodeViewModel.Text.Split('/').ToList(); - var node = GetTreeNode(separated); + var node = GetTreeNode(separated); - if(node != null) - { - GlueCommands.Self.TreeNodeCommands.HandleTreeNodeDoubleClicked(node); - } + if(node != null) + { + GlueCommands.Self.TreeNodeCommands.HandleTreeNodeDoubleClicked(node); } } - #endregion + } + #endregion - #region Back/Forward navigation + #region Back/Forward navigation - private void BackButtonClicked(object sender, RoutedEventArgs e) - { - TreeNodeStackManager.Self.GoBack(); - } + private void BackButtonClicked(object sender, RoutedEventArgs e) + { + TreeNodeStackManager.Self.GoBack(); + } - private void NextButtonClicked(object sender, RoutedEventArgs e) - { - TreeNodeStackManager.Self.GoForward(); - } + private void NextButtonClicked(object sender, RoutedEventArgs e) + { + TreeNodeStackManager.Self.GoForward(); + } - #endregion + #endregion - #region Collapse + #region Collapse - private void CollapseAllClicked(object sender, RoutedEventArgs e) - { - ViewModel.SelectedBookmark = null; - ViewModel.CollapseAll(); - } + private void CollapseAllClicked(object sender, RoutedEventArgs e) + { + ViewModel.SelectedBookmark = null; + ViewModel.CollapseAll(); + } - private void CollapseToDefinitionsClicked(object sender, RoutedEventArgs e) - { - ViewModel.SelectedBookmark = null; - ViewModel.CollapseToDefinitions(); - } + private void CollapseToDefinitionsClicked(object sender, RoutedEventArgs e) + { + ViewModel.SelectedBookmark = null; + ViewModel.CollapseToDefinitions(); + } - #endregion + #endregion - #region Searching + #region Searching - private async void SearchBar_ClearSearchButtonClicked() - { - var whatWasSelected = SelectionLogic.CurrentNode?.Tag; + private async void SearchBar_ClearSearchButtonClicked() + { + var whatWasSelected = SelectionLogic.CurrentNode?.Tag; - ViewModel.SearchBoxText = string.Empty; - ViewModel.ScreenRootNode.IsExpanded = false; - ViewModel.EntityRootNode.IsExpanded = false; - ViewModel.GlobalContentRootNode.IsExpanded = false; - if (whatWasSelected != null) - { - await SelectionLogic.SelectByTag(whatWasSelected, false); - SelectionLogic.CurrentNode?.ExpandParentsRecursively(); - } + ViewModel.SearchBoxText = string.Empty; + ViewModel.ScreenRootNode.IsExpanded = false; + ViewModel.EntityRootNode.IsExpanded = false; + ViewModel.GlobalContentRootNode.IsExpanded = false; + if (whatWasSelected != null) + { + await SelectionLogic.SelectByTag(whatWasSelected, false); + SelectionLogic.CurrentNode?.ExpandParentsRecursively(); } + } - private void FlatList_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) - { - var objectPushed = e.OriginalSource; - var frameworkElementPushed = (objectPushed as FrameworkElement); + private void FlatList_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + var objectPushed = e.OriginalSource; + var frameworkElementPushed = (objectPushed as FrameworkElement); - var searchNodePushed = frameworkElementPushed?.DataContext as NodeViewModel; - SelectSearchNode(searchNodePushed); + var searchNodePushed = frameworkElementPushed?.DataContext as NodeViewModel; + SelectSearchNode(searchNodePushed); + } + + private void SelectSearchNode(NodeViewModel searchNodePushed) + { + var foundSomething = true; + switch (searchNodePushed?.Tag) + { + case ScreenSave screenSave: + GlueState.Self.CurrentScreenSave = screenSave; + break; + case EntitySave entitySave: + GlueState.Self.CurrentEntitySave = entitySave; + break; + case ReferencedFileSave rfs: + GlueState.Self.CurrentReferencedFileSave = rfs; + break; + case NamedObjectSave nos: + GlueState.Self.CurrentNamedObjectSave = nos; + break; + case StateSaveCategory stateSaveCategory: + GlueState.Self.CurrentStateSaveCategory = stateSaveCategory; + break; + case StateSave stateSave: + GlueState.Self.CurrentStateSave = stateSave; + break; + case CustomVariable variable: + GlueState.Self.CurrentCustomVariable = variable; + break; + case EventResponseSave eventResponse: + GlueState.Self.CurrentEventResponseSave = eventResponse; + break; + case NodeViewModel nodeViewModel: + GlueState.Self.CurrentTreeNode = nodeViewModel; + break; + default: + foundSomething = false; + break; + } + + if (foundSomething) + { + ViewModel.SearchBoxText = String.Empty; + SelectionLogic.CurrentNode.Focus(this); } + } - private void SelectSearchNode(NodeViewModel searchNodePushed) + private void SearchBar_ArrowKeyPushed(Key key) + { + var selectedIndex = this.FlatList.SelectedIndex; + if(key == Key.Up && selectedIndex > 0) { - var foundSomething = true; - switch (searchNodePushed?.Tag) - { - case ScreenSave screenSave: - GlueState.Self.CurrentScreenSave = screenSave; - break; - case EntitySave entitySave: - GlueState.Self.CurrentEntitySave = entitySave; - break; - case ReferencedFileSave rfs: - GlueState.Self.CurrentReferencedFileSave = rfs; - break; - case NamedObjectSave nos: - GlueState.Self.CurrentNamedObjectSave = nos; - break; - case StateSaveCategory stateSaveCategory: - GlueState.Self.CurrentStateSaveCategory = stateSaveCategory; - break; - case StateSave stateSave: - GlueState.Self.CurrentStateSave = stateSave; - break; - case CustomVariable variable: - GlueState.Self.CurrentCustomVariable = variable; - break; - case EventResponseSave eventResponse: - GlueState.Self.CurrentEventResponseSave = eventResponse; - break; - case NodeViewModel nodeViewModel: - GlueState.Self.CurrentTreeNode = nodeViewModel; - break; - default: - foundSomething = false; - break; - } - - if (foundSomething) - { - ViewModel.SearchBoxText = String.Empty; - SelectionLogic.CurrentNode.Focus(this); - } + this.FlatList.SelectedIndex--; + this.FlatList.ScrollIntoView(this.FlatList.SelectedItem); } - - private void SearchBar_ArrowKeyPushed(Key key) + else if(key == Key.Down && selectedIndex < FlatList.Items.Count-1) { - var selectedIndex = this.FlatList.SelectedIndex; - if(key == Key.Up && selectedIndex > 0) - { - this.FlatList.SelectedIndex--; - this.FlatList.ScrollIntoView(this.FlatList.SelectedItem); - } - else if(key == Key.Down && selectedIndex < FlatList.Items.Count-1) - { - this.FlatList.SelectedIndex++; - this.FlatList.ScrollIntoView(this.FlatList.SelectedItem); - } + this.FlatList.SelectedIndex++; + this.FlatList.ScrollIntoView(this.FlatList.SelectedItem); } + } - private void SearchBar_EnterPressed() + private void SearchBar_EnterPressed() + { + if(FlatList.SelectedItem != null) { - if(FlatList.SelectedItem != null) - { - var node = FlatList.SelectedItem as NodeViewModel; - SelectSearchNode(node); - } + var node = FlatList.SelectedItem as NodeViewModel; + SelectSearchNode(node); } + } - private async void SearchBar_DismissHintTextClicked() + private async void SearchBar_DismissHintTextClicked() + { + ViewModel.HasUserDismissedTips = true; + await TaskManager.Self.AddAsync(() => { - ViewModel.HasUserDismissedTips = true; - await TaskManager.Self.AddAsync(() => + if(GlueState.Self.GlueSettingsSave != null) { - if(GlueState.Self.GlueSettingsSave != null) - { - GlueState.Self.GlueSettingsSave.Properties - .SetValue(nameof(ViewModel.HasUserDismissedTips), true); - GlueCommands.Self.GluxCommands.SaveSettings(); - } - }, Localization.Texts.SavingSettingsAfterDismissing); - } + GlueState.Self.GlueSettingsSave.Properties + .SetValue(nameof(ViewModel.HasUserDismissedTips), true); + GlueCommands.Self.GluxCommands.SaveSettings(); + } + }, Localization.Texts.SavingSettingsAfterDismissing); + } - #endregion + #endregion - #region Bookmarks + #region Bookmarks - private void Bookmarks_MouseMove(object sender, MouseEventArgs e) - { + private void Bookmarks_MouseMove(object sender, MouseEventArgs e) + { - } + } - private void Bookmarks_Drop(object sender, DragEventArgs e) - { - var node = GlueState.Self.DraggedTreeNode; - AddBookmark(node); - } + private void Bookmarks_Drop(object sender, DragEventArgs e) + { + var node = GlueState.Self.DraggedTreeNode; + AddBookmark(node); + } - public void AddBookmark(ITreeNode node) + public void AddBookmark(ITreeNode node) + { + if (node != null) { - if (node != null) - { - var path = node.GetRelativeTreeNodePath(); + var path = node.GetRelativeTreeNodePath(); - var alreadyHas = ViewModel.Bookmarks.Any(item => item.Text == path); - if (!alreadyHas) - { - var bookmark = new GlueBookmark(); - bookmark.Name = path; + var alreadyHas = ViewModel.Bookmarks.Any(item => item.Text == path); + if (!alreadyHas) + { + var bookmark = new GlueBookmark(); + bookmark.Name = path; - var imageSource = (node as NodeViewModel).ImageSource; + var imageSource = (node as NodeViewModel).ImageSource; - if (imageSource == NodeViewModel.ScreenStartupIcon) - { - // don't show the startup: - imageSource = NodeViewModel.ScreenIcon; - } - if (imageSource == NodeViewModel.FileIconWildcard) - { - // Don't show wildcard, since this could change - imageSource = NodeViewModel.FileIcon; - } + if (imageSource == NodeViewModel.ScreenStartupIcon) + { + // don't show the startup: + imageSource = NodeViewModel.ScreenIcon; + } + if (imageSource == NodeViewModel.FileIconWildcard) + { + // Don't show wildcard, since this could change + imageSource = NodeViewModel.FileIcon; + } - bookmark.ImageSource = imageSource.UriSource.OriginalString; + bookmark.ImageSource = imageSource.UriSource.OriginalString; - GlueState.Self.CurrentGlueProject.Bookmarks.Add(bookmark); + GlueState.Self.CurrentGlueProject.Bookmarks.Add(bookmark); - var bookmarkViewModel = new BookmarkViewModel(); - bookmarkViewModel.Text = path; - bookmarkViewModel.ImageSource = imageSource; + var bookmarkViewModel = new BookmarkViewModel(); + bookmarkViewModel.Text = path; + bookmarkViewModel.ImageSource = imageSource; - ViewModel.Bookmarks.Add(bookmarkViewModel); + ViewModel.Bookmarks.Add(bookmarkViewModel); - GlueCommands.Self.GluxCommands.SaveProjectAndElements(); - } + GlueCommands.Self.GluxCommands.SaveProjectAndElements(); } } + } + + private void Bookmarks_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + var selectedItem = Bookmarks.SelectedItem as BookmarkViewModel; - private void Bookmarks_SelectionChanged(object sender, SelectionChangedEventArgs e) + if(selectedItem != null) { - var selectedItem = Bookmarks.SelectedItem as BookmarkViewModel; + var separated = selectedItem.Text.Split('/').ToList(); + + var node = GetTreeNode(separated); - if(selectedItem != null) + if(node != null) { - var separated = selectedItem.Text.Split('/').ToList(); - var node = GetTreeNode(separated); + // don't focus because if we do that, the right-click menu on this disappears + SelectionLogic.SuppressFocus = true; + node.ExpandParentsRecursively(); + node.IsExpanded = true; + GlueState.Self.CurrentTreeNode = node; + SelectionLogic.SuppressFocus = false; - if(node != null) - { + } + } - // don't focus because if we do that, the right-click menu on this disappears - SelectionLogic.SuppressFocus = true; - node.ExpandParentsRecursively(); - node.IsExpanded = true; - GlueState.Self.CurrentTreeNode = node; - SelectionLogic.SuppressFocus = false; + //Bookmarks.SelectedItem = null; + } - } - } + private NodeViewModel GetTreeNode(List separated) + { + var first = separated[0]; + separated.RemoveAt(0); - //Bookmarks.SelectedItem = null; - } + NodeViewModel nodeViewModel = null; - private NodeViewModel GetTreeNode(List separated) + if (first == ViewModel.EntityRootNode.Text) { - var first = separated[0]; - separated.RemoveAt(0); + nodeViewModel = ViewModel.EntityRootNode; + } + else if(first == ViewModel.ScreenRootNode.Text) + { + nodeViewModel = ViewModel.ScreenRootNode; + } + else if(first == ViewModel.GlobalContentRootNode.Text) + { + nodeViewModel = ViewModel.GlobalContentRootNode; + } - NodeViewModel nodeViewModel = null; + return GetTreeNode(separated, nodeViewModel); + - if (first == ViewModel.EntityRootNode.Text) - { - nodeViewModel = ViewModel.EntityRootNode; - } - else if(first == ViewModel.ScreenRootNode.Text) + } + + private NodeViewModel GetTreeNode(List separated, NodeViewModel nodeViewModel) + { + if(separated.Count == 0) + { + return nodeViewModel; + } + else + { + var child = nodeViewModel.Children.FirstOrDefault(item => item.Text == separated[0]); + separated.RemoveAt(0); + if (child != null) { - nodeViewModel = ViewModel.ScreenRootNode; + return GetTreeNode(separated, child); } - else if(first == ViewModel.GlobalContentRootNode.Text) + else { - nodeViewModel = ViewModel.GlobalContentRootNode; + return null; } + } + } - return GetTreeNode(separated, nodeViewModel); - + private void DeleteBookmark_MenuItem_Click(object sender, RoutedEventArgs e) + { + var viewModel = Bookmarks.SelectedItem as BookmarkViewModel; + DeleteBookmark(viewModel); - } + } - private NodeViewModel GetTreeNode(List separated, NodeViewModel nodeViewModel) + private void DeleteBookmark(BookmarkViewModel viewModel) + { + if (ViewModel.Bookmarks.Contains(viewModel)) { - if(separated.Count == 0) + // remove and save: + ViewModel.Bookmarks.Remove(viewModel); + var modelToRemove = GlueState.Self.CurrentGlueProject.Bookmarks.FirstOrDefault(item => item.Name == viewModel.Text); + if (modelToRemove != null) { - return nodeViewModel; - } - else - { - var child = nodeViewModel.Children.FirstOrDefault(item => item.Text == separated[0]); - separated.RemoveAt(0); - if (child != null) - { - return GetTreeNode(separated, child); - } - else - { - return null; - } + GlueState.Self.CurrentGlueProject.Bookmarks.Remove(modelToRemove); + GlueCommands.Self.GluxCommands.SaveGlujFile(); } } + } - private void DeleteBookmark_MenuItem_Click(object sender, RoutedEventArgs e) - { - var viewModel = Bookmarks.SelectedItem as BookmarkViewModel; - DeleteBookmark(viewModel); + private void Bookmarks_KeyDown(object sender, KeyEventArgs e) + { + var selectedBookmark = Bookmarks.SelectedItem as BookmarkViewModel; - } + var altDown = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt; - private void DeleteBookmark(BookmarkViewModel viewModel) + switch (e.Key) { - if (ViewModel.Bookmarks.Contains(viewModel)) - { - // remove and save: - ViewModel.Bookmarks.Remove(viewModel); - var modelToRemove = GlueState.Self.CurrentGlueProject.Bookmarks.FirstOrDefault(item => item.Name == viewModel.Text); - if (modelToRemove != null) + case Key.Delete: + + if(selectedBookmark != null) { - GlueState.Self.CurrentGlueProject.Bookmarks.Remove(modelToRemove); - GlueCommands.Self.GluxCommands.SaveProjectAndElements(); + DeleteBookmark(selectedBookmark); } - } + + break; } + } - private void Bookmarks_KeyDown(object sender, KeyEventArgs e) + private void MoveBookmark(int direction) + { + //////////////////Early Out/////////////////// + if(ViewModel.SelectedBookmark == null) { - var selectedBookmark = Bookmarks.SelectedItem as BookmarkViewModel; - switch (e.Key) - { - case Key.Delete: + return; + } + /////////////////End Early Out/////////////// - if(selectedBookmark != null) - { - DeleteBookmark(selectedBookmark); - } + var selectedIndex = ViewModel.Bookmarks.IndexOf(ViewModel.SelectedBookmark); - break; - } + var didMove = false; + if(direction < 0 && selectedIndex > 0) + { + ViewModel.Bookmarks.Move(selectedIndex, selectedIndex - 1); + MoveBookmark(selectedIndex, selectedIndex - 1); + didMove = true; } - #endregion - - private void Bookmarks_LostFocus(object sender, RoutedEventArgs e) + else if(direction > 0 && selectedIndex < ViewModel.Bookmarks.Count-1) { - Bookmarks.SelectedItem= null; + ViewModel.Bookmarks.Move(selectedIndex, selectedIndex + 1); + MoveBookmark(selectedIndex, selectedIndex + 1); + didMove = true; } - private void UserControl_PreviewKeyDown(object sender, KeyEventArgs e) + if (didMove) { + GlueCommands.Self.GluxCommands.SaveGlujFile(); + } + } + + void MoveBookmark(int oldIndex, int newIndex) + { + var list = GlueState.Self.CurrentGlueProject.Bookmarks; + var removedItem = list[oldIndex]; + + list.RemoveAt(oldIndex); + list.Insert(newIndex, removedItem); + } + + #endregion + + private void Bookmarks_LostFocus(object sender, RoutedEventArgs e) + { + Bookmarks.SelectedItem= null; + } + + private void UserControl_PreviewKeyDown(object sender, KeyEventArgs e) + { + + } + + private void MainTreeView_PreviewKeyDown(object sender, KeyEventArgs e) + { + // this doesn't work: + if(e.Key == Key.Escape) + { + if(GlueState.Self.DraggedTreeNode != null) + { + GlueState.Self.DraggedTreeNode = null; + } } + } - private void MainTreeView_PreviewKeyDown(object sender, KeyEventArgs e) + private void Bookmarks_PreviewKeyDown(object sender, KeyEventArgs e) + { + var altDown = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt; + System.Diagnostics.Debug.WriteLine( + DateTime.Now.ToString() + " " + e.Key.ToString() + " " + e.SystemKey); + if(e.Key == Key.Up || e.SystemKey == Key.Up) { - // this doesn't work: - if(e.Key == Key.Escape) + if(altDown) { - if(GlueState.Self.DraggedTreeNode != null) - { - GlueState.Self.DraggedTreeNode = null; - } + MoveBookmark(-1); + } + + } + if (e.Key == Key.Down || e.SystemKey == Key.Down) + { + if (altDown) + { + MoveBookmark(1); } } }