/// <summary> /// Called when a cell is double-clicked in the datagrid. Raises an event to the main UI based on which item was clicked. /// </summary> /// <param name="sender">DataGrid that raised event</param> /// <param name="e">Info about event</param> private void cellClicked(object sender, RoutedEventArgs e) { //it has to be a row DataGrid grid = (DataGrid)sender; if (grid.SelectedCells.Count < 1) { return; } //get the name cell dataEntry de = (dataEntry)(grid.SelectedCells[0].Item); //get the name only string nName = de.Name.Substring(3); //call out to update the UI (using a raised notification) try { //is it a folder? FolderData fd = folderData.sfDict[nName]; try { GridClicked(this, new FolderDisplayEvent() { folderData = fd }); } catch (NullReferenceException) { //silently catch } } catch (System.Collections.Generic.KeyNotFoundException) { //it's a file, signal to show properties try { //make sure that it's in there FileInfo fi = folderData.fDict[nName]; GridClicked(this, new FolderDisplayEvent() { fileInfo = fi }); } catch (Exception) { //it's a folder that hasn't been loaded yet } } }
/// <summary> /// Constructor for FolderDisplay objects /// </summary> /// <param name="fd">FolderData object to display</param> /// <param name="l">UI Level (0 is root, 1 is first subfolder level, etc)</param> public FolderDisplay(FolderData fd, int l) { //setup grid folderData = fd; level = l; //set maxlevel if (level > maxLevel) { maxLevel = level; } //setup datagrid dg = new DataGrid() { IsReadOnly = true, GridLinesVisibility = DataGridGridLinesVisibility.Vertical, VerticalGridLinesBrush = new SolidColorBrush(Color.FromArgb(255, 230, 230, 230)) /*AutoGenerateColumns = false*/ }; dg.DataContext = new Binding() { RelativeSource = RelativeSource.Self }; //click handlers dg.MouseDoubleClick += cellClicked; dg.MouseLeftButtonUp += cellSingleClick; dg.KeyUp += keyPressed; updateTableListing(); /*//fix the width to prevent columns from being too wide * foreach (DataGridColumn c in dg.Columns) * { * if (c.ActualWidth > maxWidth) * { * c.MaxWidth = maxWidth; * } * }*/ /* //Name column * DataGridTextColumn header = new DataGridTextColumn() { Header = "Name" }; * header.Binding = new Binding("Name"); * dg.Columns.Add(header); * * //percentage column * DataGridTemplateColumn percentage = new DataGridTemplateColumn() { Header="Percentage"}; * //percentage.CellTemplate = Application.Current.Resources["ProgressTemplate"] as DataTemplate; * dg.Columns.Add(percentage); * * //Size column * DataGridTextColumn size = new DataGridTextColumn() { Header = "Size" }; * header.Binding = new Binding("Size"); * dg.Columns.Add(size);*/ }
/// <summary> /// Sizes the folder tree with the given root folder on a background thread /// </summary> /// <param name="path">String representing the fully qualified path to the root folder</param> private void sizeFolder(string path) { FolderData fd = new FolderData(path, true); displayList = new List <FolderDisplay>(); bgWorker = new System.Threading.Thread(() => fd.size(UpdateUIOnCallback)); sidebarPath = path; revealButton.IsEnabled = true; RevealToolbar.IsEnabled = true; copyPath.IsEnabled = true; bgWorker.Start(); //hide instructions label ContentGrid.Children.Remove(LInstructions); }
/// <summary> /// Called when a row in the grid is single clicked (for updating the sidebar) /// </summary> /// <param name="sender">FolderDisplay object that raised the event</param> /// <param name="e">Event arguments for the event</param> protected void onSingleClick(object sender, EventArgs e) { FolderDisplayEvent fde = (FolderDisplayEvent)e; //update the sidebarPath (folder or file?) if (fde.fileInfo != null) { sidebarPath = fde.fileInfo.FullName; } else { sidebarPath = fde.folderData.path.FullName; sidebarFolder = fde.folderData; } //redraw the sidebar updateSidebar(); }
/// <summary> /// Determines if a folder is in this folder, including subfolders /// </summary> /// <param name="path">Fully qualified path to search for</param> /// <returns>the FolderData object, or null if it does not exist</returns> public FolderData find(string path) { FolderData root = this; string[] components = path.Split(Path.DirectorySeparatorChar); for (int i = 1; i < components.Length; i++) { string component = components[i]; try { root = root.sfDict[component]; } catch (Exception) { return(null); } } return(root); }
/// <summary> /// Recursively determines the total size of the folder, including subfolders /// </summary> /// <param name="callback">Bool returning function that takes a double 0-1. Pass this if you want progress updates (i.e. doing the size asyncronously)</param> public void size(Func <FolderData, double, bool> callback = null) { sfDict = new Dictionary <string, FolderData>(); subFolders = new List <FolderData>(); if (sfdi == null) { return; } total_size = 0; files_size = 0; num_items = 0; size_files(); //build the list of subfolders by sizing each one double prog = 0; foreach (DirectoryInfo d in sfdi) { FolderData t = new FolderData(d.FullName); t.size(); total_size += t.total_size; num_items += t.num_items; subFolders.Add(t); sfDict.Add(t.path.Name, t); //call the callback if (callback != null) { prog++; callback(this, prog / sfdi.Count()); } } //if the target folder has no subfolders if (prog == 0 && callback != null) { callback(this, 1); } }
/// <summary> /// Updates the UI on progress updates from the background thread /// </summary> /// <param name="fd">The FolderData object passed on the callback</param> /// <param name="prog">Double from 0-1 representing the current progress</param> /// <returns>true</returns> private bool UpdateUIOnCallback(FolderData fd, double prog) { //if first update show UI if (fd.subFolders.Count() == 1) { System.Windows.Application.Current.Dispatcher.Invoke((Action) delegate { FolderDisplay fd1 = new FolderDisplay(fd, 0); addToTable(fd1); //sign up the object's click event fd1.GridClicked += OnGridClicked; fd1.GridSingleClick += onSingleClick; fd1.GridKeys += onGridKey; }); } //update progress bar System.Windows.Application.Current.Dispatcher.Invoke((Action) delegate { MainProg.Value = prog; StatusL.Content = "Sizing " + fd.ToString() + " (" + Math.Round(prog * 100) + "%)"; //loop through displaylist to get the correct folderdisplays FolderData root = fd; //if displaylist is empty (e.g. no subfolders), create one if (displayList.Count == 0) { FolderDisplay fdisp = new FolderDisplay(root, 0); fdisp.GridClicked += OnGridClicked; fdisp.GridSingleClick += onSingleClick; fdisp.GridKeys += onGridKey; displayList.Add(fdisp); } displayList[0].folderData = root; displayList[0].updateTableListing(); for (int i = 1; i < displayList.Count(); i++) { //get the current one FolderData fdt = displayList[i].folderData; //find the correspondant in root FolderData updated = root.sfDict[fdt.path.Name]; //update the list displayList[i].folderData = updated; displayList[i].updateTableListing(); //update root root = updated; } //update the UI ContentGrid.Children.Clear(); ContentGrid.ColumnDefinitions.Clear(); foreach (FolderDisplay fdisp in displayList) { addToTable(fdisp, false); } if (prog == 1) { ChooseFolderBtn.IsEnabled = true; ResizeFolder.IsEnabled = true; StopBtn.IsEnabled = false; sidebarFolder = fd; updateSidebar(); } }); return(true); }