/// <summary> /// Adds a tree view item /// </summary> /// <param name="parent">Parent of the item</param> /// <param name="item">The item to be added</param> private void Add(DisplayableTreeViewItem parent, DisplayableTreeViewItem item) { ObservableCollection <DisplayableTreeViewItem> siblings; if (parent == null) { siblings = ItemSource; } else { siblings = parent.Items; parent.IsExpanded = true; } int index = FindIndex(siblings, item); if (index == -1) { index = 0; } if (parent == null) { ItemSource.Insert(index, item); } else { parent.Items.Insert(index, item); } CheckVisibility(); }
private void TreeViewItem_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs args) { TreeViewItem tvi = sender as TreeViewItem; DisplayableTreeViewItem item = tvi.DataContext as DisplayableTreeViewItem; SelectedItem = item; ContextMenu cm; if (!item.IsFolder) { cm = CreateContextMenuMacro(item, item.Header, item.Declaration); } else { cm = CreateContextMenuFolder(item, item.Header, item.Root); } if (cm == null) { System.Diagnostics.Debug.WriteLine("Context menu is null."); return; } tvi.ContextMenu = cm; tvi.ContextMenu.IsOpen = true; }
/// <summary> /// Renames a tree view item /// </summary> /// <param name="parent">The parent of the item</param> /// <param name="item">The item to be renamed</param> private void Rename(DisplayableTreeViewItem parent, DisplayableTreeViewItem item) { Remove(parent, item); Add(parent, item); UpdateRibbon(); }
/// <summary> /// Creates an item from a data source and adds it to its parent /// </summary> /// <param name="parent">The parent of the item</param> /// <param name="data">The data of the macro, for the tree view item</param> /// <returns></returns> private DisplayableTreeViewItem CreateTreeViewItem(DisplayableTreeViewItem parent, DataTreeViewItem data) { DisplayableTreeViewItem item = new DisplayableTreeViewItem(); item.Header = data.name; item.IsFolder = data.folder; item.IsExpanded = false; item.Parent = parent; if (data.children != null) { foreach (DataTreeViewItem child in data.children) { DisplayableTreeViewItem node = CreateTreeViewItem(item, child); if (node != null) { item.Items.Add(node); } } } if (!data.folder) { item.Declaration = data.decl; item.SelectedEvent += delegate(object sender, RoutedEventArgs args) { SelectedItem = item; }; item.DoubleClickEvent += delegate(object sender, MouseButtonEventArgs args) { OpenMacro(data.decl); args.Handled = true; }; } item.Root = data.root; item.RightClickEvent += TreeViewItem_OnPreviewMouseRightButtonDown; return(item); }
/// <summary> /// Imports a macro /// </summary> /// <param name="parent">The parent item to which it'll be added</param> /// <param name="info">The directory in which to import it</param> public async void ImportMacro(DisplayableTreeViewItem parent, DirectoryInfo info) { FileDeclaration d = await MainWindowViewModel.GetInstance().ImportMacro(info); if (d == null) { return; } DisplayableTreeViewItem item = new DisplayableTreeViewItem(); item.Header = d.Name; item.IsFolder = false; item.Declaration = d; item.RightClickEvent = TreeViewItem_OnPreviewMouseRightButtonDown; item.SelectedEvent = delegate(object sender, RoutedEventArgs args) { SelectedItem = item; }; item.DoubleClickEvent = delegate(object sender, MouseButtonEventArgs args) { OpenMacro(d); args.Handled = true; }; if (parent == null) { item.Root = "/"; } else { item.Root = parent.Root + "/" + parent.Header + "/"; } Add(parent, item); OpenMacro(d); }
/// <summary> /// Closes the open document of a macro /// </summary> /// <param name="item">The item which itself and all subsequent children will be closed</param> private void CloseItemMacro(DisplayableTreeViewItem item) { foreach (DisplayableTreeViewItem child in item.Items) { CloseItemMacro(child); } MainWindowViewModel.GetInstance().CloseMacro(item.Declaration); }
private int CompareItems(DisplayableTreeViewItem x, DisplayableTreeViewItem y) { if (x.IsFolder == y.IsFolder) { return(string.Compare(x.Header, y.Header)); } else { return(x.IsFolder ? 1 : 0); } }
/// <summary> /// Remove a tree view item /// </summary> /// <param name="parent">Parent of the item</param> /// <param name="item">The item to be removed</param> private void Remove(DisplayableTreeViewItem parent, DisplayableTreeViewItem item) { if (parent == null) { ItemSource.Remove(item); } else { parent.Items.Remove(item); } CheckVisibility(); }
/// <summary> /// Sort a tree view item's item collection /// </summary> /// <param name="item"></param> /// <returns></returns> private DisplayableTreeViewItem Sort(DisplayableTreeViewItem item) { List <DisplayableTreeViewItem> items = item.Items.ToList <DisplayableTreeViewItem>(); items.Sort((x, y) => CompareItems(x, y)); item.Items.Clear(); for (int i = 0; i < items.Count; i++) { item.Items.Insert(i, Sort(items[i])); } return(item); }
/// <summary> /// Adds RightButtonDown event callbacks to an item for contextmenu opening /// </summary> /// <param name="item"></param> /// <returns></returns> private DisplayableTreeViewItem AddEvent(DisplayableTreeViewItem item) { if (item == null) { return(item); } item.RightClickEvent += TreeViewItem_OnPreviewMouseRightButtonDown; for (int i = 0; i < item.Items.Count; i++) { item.Items[i] = AddEvent(item.Items[i] as DisplayableTreeViewItem); } return(item); }
/// <summary> /// Deletes a macro and its displayable item /// </summary> /// <param name="item">The item to be deleted</param> /// <param name="macro">The macro attached to the item, to be deleted</param> public async void DeleteMacro(DisplayableTreeViewItem item, FileDeclaration macro) { bool result = await macro.Delete(); if (result) { if (item.Parent is DisplayableTreeViewItem) { Remove((item.Parent as DisplayableTreeViewItem), item); } else { Remove(null, item); } CloseItemMacro(item); } }
/// <summary> /// Deletes a folder and removes its displayable item /// </summary> /// <param name="item">The item to be deleted</param> /// <param name="path">The relativepath of the folder</param> /// <param name="name">The name of the folder</param> public async void DeleteFolder(DisplayableTreeViewItem item, string path, string name) { DirectoryInfo info = new DirectoryInfo(Files.FullPath(path, name)); bool result = await MacroUI.GetInstance().DeleteFolder(info); if (result) { if (item.Parent is DisplayableTreeViewItem) { Remove((item.Parent as DisplayableTreeViewItem), item); } else { Remove(null, item); } CloseItemMacro(item); } }
/// <summary> /// Uses recursive function to populate the tree view with macros /// </summary> private void Initialize() { HashSet <DataTreeViewItem> items = CreateTreeViewItemStructure(MacroUI.GetInstance().GetFileDeclarations()); foreach (DataTreeViewItem item in items) { DisplayableTreeViewItem tvi = CreateTreeViewItem(null, item); if (tvi != null) { ItemSource.Add(tvi); } } Sort(); CheckVisibility(); //Events.OnMacroCountChanged += CheckVisibility; Events.SubscribeEvent("OnMacroCountChanged", (Action)CheckVisibility); }
/// <summary> /// Find the index at which an item would exist in an alphabetically ordered list (essentially binary search) /// </summary> /// <param name="items">List of siblings</param> /// <param name="item">The item to searched for</param> /// <returns>Inserting index</returns> private int FindIndex(ObservableCollection <DisplayableTreeViewItem> items, DisplayableTreeViewItem item) { if (items.Count == 0) { return(0); } int count = items.Count - 1; int low = 0; int high = count; int mid = (low + high) / 2; while (low <= high) { mid = (low + high) / 2; int pos = String.Compare(item.Header, items[mid].Header, true); if (pos < 0) { high = mid - 1; } else if (pos > 0) { low = mid + 1; } else { return(mid); } } if (String.Compare(item.Header, items[mid].Header, true) > 0) { mid++; } return(mid); }
/// <summary> /// Creates macro /// </summary> /// <param name="parent">The parent item to which it'll be added</param> /// <param name="root">The root of the item's relative future directory</param> /// <param name="OnReturn">The Action, and resulting file declaration of the created macro, to be fired when the task is completed</param> public void CreateMacro(DisplayableTreeViewItem parent, string root, Action <FileDeclaration> OnReturn) { if (m_IsCreating) { return; } m_IsCreating = true; DisplayableTreeViewItem item = new DisplayableTreeViewItem(); item.KeyUpEvent = delegate(object s, KeyEventArgs a) { if (a.Key == Key.Return) { Focus(); Keyboard.ClearFocus(); } else if (a.Key == Key.Escape) { m_IsCreating = false; item.IsInputting = false; } }; item.FocusLostEvent = delegate(object s, RoutedEventArgs a) { if (String.IsNullOrEmpty(item.Header) || (!item.IsInputting)) { Remove(parent, item); m_IsCreating = false; return; } if (!Path.HasExtension(item.Header)) { item.Header += MacroUI.GetInstance().GetDefaultFileExtension(); } item.Header = Regex.Replace(item.Header, "[^0-9a-zA-Z ._-]", ""); FileInfo info = new FileInfo(Files.FullPathMacro(Files.FullPath(root, item.Header))); FileDeclaration d = MainWindowViewModel.GetInstance().CreateMacro(info); Rename(parent, item); if (d == null) { Remove(parent, item); m_IsCreating = false; return; } item.Header = d.Name; item.Declaration = d; item.Root = root; item.Parent = parent; item.IsFolder = false; item.RightClickEvent = TreeViewItem_OnPreviewMouseRightButtonDown; item.SelectedEvent = delegate(object sender, RoutedEventArgs args) { SelectedItem = item; }; item.DoubleClickEvent = delegate(object sender, MouseButtonEventArgs args) { OpenMacro(d); args.Handled = true; }; item.IsInputting = false; m_IsCreating = false; OnReturn?.Invoke(d); OpenMacro(d); }; Add(parent, item); item.IsInputting = true; }
/// <summary> /// Creates a contextmenu for a tree view item file /// </summary> /// <param name="item">The item for which the context menu is being made</param> /// <param name="name">The name of the macro</param> /// <param name="id">The id of the macro</param> /// <returns>File TreeViewItem ContextMenu</returns> private ContextMenu CreateContextMenuMacro(DisplayableTreeViewItem item, string name, FileDeclaration d) { Style ContextMenuStyle = MainWindow.GetInstance().GetResource("MetroContextMenuStyle") as Style; Style MenuItemStyle = MainWindow.GetInstance().GetResource("MetroMenuItemStyle") as Style; Style SeparatorStyle = MainWindow.GetInstance().GetResource("MertoMenuSeparatorStyle") as Style; ContextMenu cm = new ContextMenu(); cm.Resources.MergedDictionaries.Add(MainWindow.GetInstance().GetResources()); cm.Style = ContextMenuStyle; DisplayableTreeViewItem parentitem = item.Parent; if (d == null) { MacroUI.GetInstance().DisplayOkMessage("Could not get the macro (when attempting to create a context menu): " + name, "Macro Error"); return(null); } MenuItem mi_edit = new MenuItem(); mi_edit.Header = "Edit"; mi_edit.Click += delegate(object sender, RoutedEventArgs args) { OpenMacro(d); args.Handled = true; cm.IsOpen = false; }; mi_edit.Style = MenuItemStyle as Style; cm.Items.Add(mi_edit); MenuItem mi_execute = new MenuItem(); mi_execute.Header = "Synchronous Execute"; mi_execute.ToolTip = "Synchronous executions cannot be terminated."; mi_execute.Click += delegate(object sender, RoutedEventArgs args) { ExecuteMacro(d, false); args.Handled = true; cm.IsOpen = false; }; mi_execute.Style = MenuItemStyle as Style; cm.Items.Add(mi_execute); MenuItem mi_executea = new MenuItem(); mi_executea.Header = "Asynchronous Execute"; mi_executea.ToolTip = "Asynchronous executions can be terminated."; mi_executea.Click += delegate(object sender, RoutedEventArgs args) { ExecuteMacro(d, true); args.Handled = true; cm.IsOpen = false; }; mi_executea.Style = MenuItemStyle as Style; cm.Items.Add(mi_executea); Separator sep1 = new Separator(); sep1.Style = SeparatorStyle as Style; cm.Items.Add(sep1); MenuItem mi_export = new MenuItem(); mi_export.Header = "Export"; mi_export.Click += delegate(object sender, RoutedEventArgs args) { d.Export(); args.Handled = true; cm.IsOpen = false; }; mi_export.Style = MenuItemStyle as Style; cm.Items.Add(mi_export); MenuItem mi_del = new MenuItem(); mi_del.Header = "Delete"; mi_del.Click += delegate(object sender, RoutedEventArgs args) { DeleteMacro(item, d); args.Handled = true; cm.IsOpen = false; }; mi_del.Style = MenuItemStyle as Style; cm.Items.Add(mi_del); MenuItem mi_rename = new MenuItem(); mi_rename.Header = "Rename"; mi_rename.Click += delegate(object sender, RoutedEventArgs args) { args.Handled = true; cm.IsOpen = false; string previousname = item.Header; item.KeyUpEvent = delegate(object s, KeyEventArgs a) { if (a.Key == Key.Return) { Focus(); Keyboard.ClearFocus(); } else if (a.Key == Key.Escape) { item.Header = previousname; Focus(); Keyboard.ClearFocus(); } }; item.FocusLostEvent = delegate(object s, RoutedEventArgs a) { if (item.Header == previousname) { item.IsInputting = false; return; } if (String.IsNullOrEmpty(item.Header)) { MacroUI.GetInstance().DisplayOkMessage("Please enter a valid name.", "Invalid Name"); item.IsInputting = true; return; } if (!Path.HasExtension(item.Header)) { item.Header += MacroUI.GetInstance().GetDefaultFileExtension(); } MainWindowViewModel.GetInstance().RenameMacro(d, item.Header); Rename(parentitem, item); item.IsInputting = false; }; item.IsInputting = true; }; mi_rename.Style = MenuItemStyle as Style; cm.Items.Add(mi_rename); Separator sep2 = new Separator(); sep2.Style = SeparatorStyle; cm.Items.Add(sep2); return(cm); }
/// <summary> /// Create a contextmenu for a tree view item folder /// </summary> /// <param name="item">The item for which the contextmenu is being made</param> /// <param name="name">The name of the folder</param> /// <param name="path">The relativepath of the folder</param> /// <returns>Folder TreeViewItem ContextMenu</returns> private ContextMenu CreateContextMenuFolder(DisplayableTreeViewItem item, string name, string path) { Style ContextMenuStyle = MainWindow.GetInstance().GetResource("MetroContextMenuStyle") as Style; Style MenuItemStyle = MainWindow.GetInstance().GetResource("MetroMenuItemStyle") as Style; Style SeparatorStyle = MainWindow.GetInstance().GetResource("MertoMenuSeparatorStyle") as Style; ContextMenu cm = new ContextMenu(); cm.Resources.MergedDictionaries.Add(MainWindow.GetInstance().GetResources()); cm.Style = ContextMenuStyle; MenuItem mi_create = new MenuItem(); mi_create.Header = "Create Macro"; mi_create.Click += delegate(object sender, RoutedEventArgs args) { item.IsExpanded = true; cm.IsOpen = false; CreateMacro(item, Files.FullPath(path, name), (d) => MacroUI.GetInstance().AddFile(d)); }; mi_create.Style = MenuItemStyle as Style; cm.Items.Add(mi_create); MenuItem mi_folder = new MenuItem(); mi_folder.Header = "Create Folder"; mi_folder.Click += delegate(object sender, RoutedEventArgs args) { item.IsExpanded = true; CreateFolder(item, path + "/" + name + "/"); cm.IsOpen = false; }; mi_folder.Style = MenuItemStyle as Style; cm.Items.Add(mi_folder); MenuItem mi_import = new MenuItem(); mi_import.Header = "Import Macro"; mi_import.Click += delegate(object sender, RoutedEventArgs args) { item.IsExpanded = true; DirectoryInfo info = new DirectoryInfo(Files.FullPath(path, name)); ImportMacro(item, info); cm.IsOpen = false; }; mi_import.Style = MenuItemStyle as Style; cm.Items.Add(mi_import); Separator sep1 = new Separator(); sep1.Style = SeparatorStyle; cm.Items.Add(sep1); MenuItem mi_del = new MenuItem(); mi_del.Header = "Delete"; mi_del.Click += delegate(object sender, RoutedEventArgs args) { DeleteFolder(item, path, name); args.Handled = true; cm.IsOpen = false; }; mi_del.Style = MenuItemStyle as Style; cm.Items.Add(mi_del); MenuItem mi_rename = new MenuItem(); mi_rename.Header = "Rename"; mi_rename.Click += delegate(object sender, RoutedEventArgs args) { args.Handled = true; cm.IsOpen = false; DisplayableTreeViewItem parentitem = item.Parent; string previousname = item.Header; item.KeyUpEvent = delegate(object s, KeyEventArgs a) { if (a.Key == Key.Return) { Focus(); Keyboard.ClearFocus(); } else if (a.Key == Key.Escape) { item.Header = previousname; Focus(); Keyboard.ClearFocus(); } }; item.FocusLostEvent = delegate(object s, RoutedEventArgs a) { if (item.Header == previousname) { item.IsInputting = false; return; } if (String.IsNullOrEmpty(item.Header)) { MacroUI.GetInstance().DisplayOkMessage("Please enter a valid name.", "Invalid Name"); item.IsInputting = true; return; } DirectoryInfo info = new DirectoryInfo(Files.FullPath(path, name)); MainWindowViewModel.GetInstance().RenameFolder(info, path + item.Header); Rename(parentitem, item); item.IsInputting = false; }; item.IsInputting = true; }; mi_rename.Style = MenuItemStyle as Style; cm.Items.Add(mi_rename); return(cm); }
/// <summary> /// Creates a folder /// </summary> /// <param name="parent">The parent item for it to be added to</param> /// <param name="root">The root of the item's relative future directory</param> private void CreateFolder(DisplayableTreeViewItem parent, string root) { if (m_IsCreating) { return; } m_IsCreating = true; DisplayableTreeViewItem item = new DisplayableTreeViewItem(); item.KeyUpEvent = delegate(object s, KeyEventArgs a) { if (a.Key == Key.Return) { Focus(); Keyboard.ClearFocus(); } else if (a.Key == Key.Escape) { m_IsCreating = false; item.IsInputting = false; } }; item.FocusLostEvent = delegate(object s, RoutedEventArgs a) { if (String.IsNullOrEmpty(item.Header) || (!item.IsInputting)) { Remove(parent, item); m_IsCreating = false; return; } item.Header = Regex.Replace(item.Header, @"[^0-9a-zA-Z]+", ""); //FileManager.CreateFolder((root + "/" + item.Header).Replace('\\', '/').Replace("//", "/")) DirectoryInfo info = new DirectoryInfo(Files.CleanPath(root + "/" + item.Header)); bool result = Files.CreateFolder(info); if (!result) { Remove(parent, item); } else { Rename(parent, item); item.RightClickEvent = TreeViewItem_OnPreviewMouseRightButtonDown; item.Root = root; item.IsFolder = true; item.IsExpanded = false; item.Parent = parent; item.IsInputting = false; m_IsCreating = false; } }; //tvi.Items.SortDescriptions.Add(new SortDescription("Header", ListSortDirection.Ascending)); Add(parent, item); item.IsInputting = true; }