// When selected item changes we update its content/appendix in text view // Don't use SelectedItemChanged to retrieve items directly when using Data Binding: http://www.wpf-tutorial.com/treeview-control/handling-selection-expansion-state/, http://stackoverflow.com/questions/12856522/how-to-access-data-of-an-treeviewitem-object private void ChangesList_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { // Display Content in right panel // JFile file = (TreeViewItem)e.NewValue as JFile; if (ChangesList.SelectedItem != null) { CopyContentButton.IsEnabled = true; JFile file = ChangesList.SelectedItem as JFile; if (file != null) { // If it's file, then show its content or appendix ReviweText.Text = file.TextContent != null? file.TextContent : (file.Appendix != null? file.Appendix : "No modification is available on this file, and this must be a bug since the file should be cleaned during Cleanup stage!"); } else { // It it's not a file, then clear content ReviweText.Text = ""; } // Another way to implement all these would be to add event handling mechanism inside children classes of TreeViewItemBase, i.e. JFile and JFolder } else { CopyContentButton.IsEnabled = false; } }
private void ReplaceFileButton_Click(object sender, RoutedEventArgs e) { // Extract Item from metadata JFile item = (sender as Button).Tag as JFile; // Get file path string filePath = GetFilePath(item); if (filePath != null) { // Write content to original file if (File.Exists(filePath)) { // Write to file File.WriteAllText(filePath, item.TextContent); // Display Result OriginalText.Text = File.ReadAllText(filePath); } else { // Display Error StatusLabel.Content = "File doesn't exist on local drive!"; } } }
private void FileImage_MouseDown(object sender, MouseButtonEventArgs e) { // Extract Item from metadata JFile item = (sender as Image).Tag as JFile; OpenFileForEditing(item); }
private void AppendFileButton_Click(object sender, RoutedEventArgs e) { // Extract Item from metadata JFile item = (sender as Button).Tag as JFile; // Get file path string filePath = GetFilePath(item); if (filePath != null) { // Append content to original file if (File.Exists(filePath)) { // Append to file using (StreamWriter sw = File.AppendText(filePath)) // Notice in this case the encoding being used is: UTF-8, meaning if appendix is ASCII then just fine since ANSI and UTF-8 both love ASCII but when source is ANSI while here is UTF-8 then two encodings will be mixed together in a single file; We suggest converting everything into UTF-8 BOM before we upload { sw.WriteLine(item.Appendix); } // Display Result OriginalText.Text = File.ReadAllText(filePath); } else { // Display Error StatusLabel.Content = "File doesn't exist on local drive!"; } } }
private void UpdateItemContent(JFile file) { if (file.bInclude == true) { // Get Filepath string filePath = App.GetParentFolderPath(file.Parent) + file.FileName; // Convert it to UTF8, then add content to JSON var checker = new Unicode.Utf8Checker(); // If UTF8 BOM if (checker.Check(filePath) == true) { // In this case we don't care whether user said it's ANSI file.TextContent = File.ReadAllText(filePath); } else { // If asserted ANSI by user if (file.bANSI) { file.TextContent = File.ReadAllText(filePath, Encoding.Default); } // Then UTF8 else { file.TextContent = File.ReadAllText(filePath); } } } else { file.TextContent = null; } }
private void MenuItem_FileProperty_Click(object sender, RoutedEventArgs e) { // Get file path JFile file = (sender as MenuItem).DataContext as JFile; string filePath = App.GetParentFolderPath(file.Parent) + file.FileName; SystemInterpService.ShowFileProperties(filePath); }
private void MenuItem_ShowWhere_Click(object sender, RoutedEventArgs e) { JFile file = (sender as MenuItem).DataContext as JFile; // Get file pathh string filePath = App.GetParentFolderPath(file.Parent) + file.FileName; UpdateStatus(filePath); }
private void OnTreeViewItemPreviewKeyDown(object sender, KeyEventArgs e) { Key key = (e.Key == Key.System ? e.SystemKey : e.Key); // Enter key for quick search if (key == Key.Enter) { // If SHIFT is pressed, then open file location if file, otherwise ignore if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) { // Make sure some node is selected and that represents a file JFile file = DirectoryView.SelectedItem as JFile; if (file != null) { OpenFolderForInspection(file.Parent); e.Handled = true; } } // If ALT is pressed, then open property window else if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt) { // Open as a file JFile file = DirectoryView.SelectedItem as JFile; if (file != null) { SystemInterpService.ShowFileProperties(App.GetParentFolderPath(file.Parent) + file.FileName); e.Handled = true; } // Open as a folder JFolder folder = DirectoryView.SelectedItem as JFolder; if (folder != null) { SystemInterpService.ShowFileProperties(App.GetParentFolderPath(folder)); e.Handled = true; } } // Open as is else { // Open as a file JFile file = DirectoryView.SelectedItem as JFile; if (file != null) { OpenFileForEditing(file); e.Handled = true; } // Open as a folder JFolder folder = DirectoryView.SelectedItem as JFolder; if (folder != null) { OpenFolderForInspection(folder); e.Handled = true; } } } }
private void FileContentCheckBox_bInclude_Checked(object sender, RoutedEventArgs e) { // Append content to JFile object JFile item = (sender as CheckBox).Tag as JFile; item.bInclude = true; // Update Item Content UpdateItemContent(item); }
private void FileContentCheckBox_bInclude_Unchecked(object sender, RoutedEventArgs e) { // Clear content from JFIle Object JFile item = (sender as CheckBox).Tag as JFile; item.bInclude = false; // Update Item Content UpdateItemContent(item); }
private void FileEncodingCheckBox_bANSI_Unchecked(object sender, RoutedEventArgs e) { // Append content to JFile object JFile item = (sender as CheckBox).Tag as JFile; item.bANSI = false; // Add Content to Item UpdateItemContent(item); }
private void CopyContentButton_Click(object sender, RoutedEventArgs e) { JFile file = ChangesList.SelectedItem as JFile; if (file != null) { // Clipboard.SetText(ReviweText.Text); // http://stackoverflow.com/questions/12769264/openclipboard-failed-when-copy-pasting-data-from-wpf-datagrid Clipboard.SetDataObject(ReviweText.Text); } }
private void MenuItem_CopyFilePath_Click(object sender, RoutedEventArgs e) { JFile file = (sender as MenuItem).DataContext as JFile; // Get file pathh string filePath = App.GetParentFolderPath(file.Parent) + file.FileName; Clipboard.SetText(filePath); UpdateStatus("Path copied to clipboard"); }
private void OpenFileButton_Click(object sender, RoutedEventArgs e) { // Extract Item from metadata JFile item = (sender as Button).Tag as JFile; // Open file in system editor string filePath = GetFilePath(item); if (filePath != null) { System.Diagnostics.Process.Start(filePath); } }
private void OpenFileButton_Click(object sender, RoutedEventArgs e) { // Extract Item from metadata JFile item = (sender as Button).Tag as JFile; // Get file pathh string filePath = App.GetParentFolderPath(item.Parent) + item.FileName; // Open file in system editor try { System.Diagnostics.Process.Start(filePath); } catch (System.ComponentModel.Win32Exception) {} }
private List <CancellationTokenSource> searchingTaskTokenSourceList = new List <CancellationTokenSource>(); // Current Deployed Tokens: The first being oldest, the last being newest // private List<string> historyKeywordsList = new List<string>(); // Not neeeded and might cause IndexOutofRange if not used properly private void OpenFileForEditing(JFile file) { // Get file pathh string filePath = App.GetParentFolderPath(file.Parent) + file.FileName; // If file exist on local machine if (File.Exists(filePath)) { try { // Open file in system editor System.Diagnostics.Process.Start(filePath); // Update Status StatusLabel.Content = "File opened."; } catch (System.ComponentModel.Win32Exception) { } } // Other wise we use a Reference file else { // Update Status StatusLabel.Content = "Original file cannot be found, use a reference file instead."; string referenceFilePath = AppDomain.CurrentDomain.BaseDirectory + "\\" + App.ReferenceDirectoryName + "\\" + file.FileName; // If not already exists then create one if (File.Exists(referenceFilePath) == false) { File.WriteAllText(referenceFilePath, string.Format( "You are writing in a reference file! Original file cannot be found on this computer, we created a reference file for editing purpose.\n<Original file location>{0}\n<Current file location>{1}", filePath, referenceFilePath)); } // Then open it try { // Open file in system editor System.Diagnostics.Process.Start(referenceFilePath); } catch (System.ComponentModel.Win32Exception) { } } // Auto Hide this.WindowState = WindowState.Minimized; }
// http://stackoverflow.com/questions/2280049/why-is-the-treeviewitems-mousedoubleclick-event-being-raised-multiple-times-per private void OnTreeViewItemMouseDoubleClick(object sender, RoutedEventArgs e) { TreeViewItem item = sender as TreeViewItem; if (item.IsSelected) { // Open folder or file depending on item type JFolder folder = item.DataContext as JFolder; if (folder != null) { // Don't do this since by default this should be expanding folder action // OpenFolderForInspection(folder); // e.Handled = true; } else { JFile file = item.DataContext as JFile; OpenFileForEditing(file); e.Handled = true; } } }
// Extract and build a new JFolder from one JFile private static JFolder JBuildRootFromFile(JFile file) { // This is a bit complicated: We first constrct a string of all folder paths List <string> folderNames = new List <string>(); JFolder parent = file.Parent; while (parent != null) { folderNames.Add(parent.FolderName); parent = parent.Parent; } folderNames.Reverse(); // Revese order so things are logical // Then we add all those paths to our newly created JFolder JFolder representativeFolder = new JFolder(folderNames[0]); JFolder currentFolder = representativeFolder; // Expand Root Folder currentFolder.bExpanded = true; for (int i = 1; i < folderNames.Count; i++) // Skipped the root folder name, i.e. when i = 0 { // Add Children and Iterate currentFolder.Folders.Add(new JFolder(folderNames[i])); currentFolder = currentFolder.Folders[0]; // Go to the only child folder of current folder // Expand Folder currentFolder.bExpanded = true; } // Finally we add our JFile JFile newFile = new JFile(file.FileName); newFile.TextContent = file.TextContent; newFile.Appendix = file.Appendix; currentFolder.Files.Add(newFile); // Notice we are NOT just referencing the old - we are creating a complete replicate // Establish New ParentalShip App.EstablishParents(representativeFolder); // Return the JSON obejct return(representativeFolder); }
// Used to expand current folder by one layer: load all items under this folder private void FolderGenerator(JFolder currentFolder) { // First get folder path string FolderPath = App.GetParentFolderPath(currentFolder); // Then add items to folder try { foreach (string elementPath in Directory.EnumerateDirectories(FolderPath)) // It seems DirectorInfo can provide directory name directly using ToString() { string FolderName = elementPath.Substring(elementPath.LastIndexOf("\\") + 1); // Generate JFolders JFolder elementFolder = new JFolder(FolderName); elementFolder.Parent = currentFolder; elementFolder.bSelected = currentFolder.bSelected; // Let Children share the same status of selection as parent elementFolder.Folders.Add(new JFolder(TempLoadingFolderString)); currentFolder.Folders.Add(elementFolder); } } catch (UnauthorizedAccessException) { } catch (PathTooLongException) { } try { foreach (string elementPath in Directory.EnumerateFiles(FolderPath)) { string FileName = System.IO.Path.GetFileName(elementPath); // Generate JFiles JFile elementFile = new JFile(FileName); elementFile.Parent = currentFolder; currentFolder.Files.Add(elementFile); } } catch (UnauthorizedAccessException) { } catch (System.IO.PathTooLongException) { } }
// Get file path for specifci JFile in tree, considering QuickMatch private string GetFilePath(JFile file) { // QuickMatch® (4/4): Use QuickMatch® for QuickMatched files if (file.Parent.FolderName == App.QuickMatchFolderName) { JFolder matches = QuickMatch.QuickMatchFile(file.FileName, JRootFolderExclusive); // If no match found if (matches == null) { StatusLabel.Content = "No match found."; return(null); } // If more than one match if found if (matches.Files.Count > 1) { StatusLabel.Content = "More than one match is found, please do matching manually using magic explorer."; // Better with a shortcut to it return(null); } // Otherwise there can be only one match else { // Get JFile first List <JFolder> subFolders = matches.Folders; while (subFolders[0].Folders.Count != 0) { subFolders = subFolders[0].Folders; } JFile foundFile = subFolders[0].Files[0]; // Then get the file's path return(App.GetParentFolderPath(foundFile.Parent) + foundFile.FileName); } } else { return(App.GetParentFolderPath(file.Parent) + file.FileName); } }
private void MenuItem_OpenFileLocation_Click(object sender, RoutedEventArgs e) { JFile file = (sender as MenuItem).DataContext as JFile; OpenFolderForInspection(file.Parent); }
// Return the file matched in original folder(well the actual return value is explained on the forth line of this comment), we will match only one file: YES, only one file, no choices can be made, this is the key for making this whole thing useful (and be strict to ourselves) // Rationale: I have only one file in mind, despite how ambiguous we are identifying it // So to be flexible, there really should be two modes: one is to return one file, the other is to return a bunch of files // We will return a "partially new" JFolder for representation purpose only: DO NOT TEMPER WITH THE FOLDER because it is not deep copied - sometimes it is e.g. in case we return only one file; other cases not, see "Notice Hacking" below public static JFolder QuickMatchFile(string keywordsString, JFolder rootFolder, bool bMultiReturn = false) { // Delimit keywords /* Remove last element in case an extra blank * http://stackoverflow.com/questions/26946196/c-sharp-deleting-last-item-from-array-of-string * http://stackoverflow.com/questions/6823253/c-sharp-string-split-remove-last-item * https://msdn.microsoft.com/en-us/library/kxbw3kwc(v=vs.110).aspx */ char[] delimiters = new Char[] { ' ' }; string[] keywordsArray = keywordsString.TrimEnd(delimiters).Split(delimiters); // If no keywords at all if (keywordsArray.Length == 0) { return(null); } // First we get an array of all JFiles that matches the last keyword List <JFile> potentialEndPoints = new List <JFile>(); KeywordIterator(rootFolder, potentialEndPoints, keywordsArray.First()); // If we have found only one element, then all good to go; if none was found, then also we end our job; if multiple files are found, we do a second level comparison if (potentialEndPoints.Count == 0) { return(null); } else if (potentialEndPoints.Count == 1) { // Extract a new JSON and return return(JBuildRootFromFile(potentialEndPoints[0])); } else { // Depending on the number of keywords left, we take next step decision if (keywordsArray.Length == 1) // No extra keywords left, we return all we have found { // If no keywords left for comparison, then the user is just looking for all potential matches /// ****** Notice Hacking ****** To save effort and resource we use a trick: Since The user will only display the folder structure, and when user clicks the file image to open the file it will iterate from file to parents to find its path, so we will generate a phatom folder to hold temporary files, without showing detailed structure of each one /// But notice that in this case the folder itself cannot be clicked to open any specific folder JFolder newFolder = new JFolder("Search Results"); // Expand Folder newFolder.bExpanded = true; foreach (JFile file in potentialEndPoints) { newFolder.Files.Add(file); } return(newFolder); } else { // First do a similarity check for each file foreach (JFile file in potentialEndPoints) { // Form a path string string filePath = App.GetParentFolderPath(file.Parent) + file.FileName; // Evaluate similarity between path string and remaining keywords, add a point for each match // Remember that we are not trying to provide an exact match, but ambiguous in a sense expecially when dealing with CHN characters because no space seperation for (int i = 1; i < keywordsArray.Length; i++) { if (filePath.ToUpper().Contains(keywordsArray[i].ToUpper())) { file.keywordOccurences++; } else { file.keywordMisses++; } } } // Then sort out the file with most points for the last test /* The below creates a new EnumerableItem. * http://stackoverflow.com/questions/16620135/sort-a-list-of-objects-by-the-value-of-a-property * https://msdn.microsoft.com/en-us/library/bb534966.aspx * http://stackoverflow.com/questions/3309188/how-to-sort-a-listt-by-a-property-in-the-object */ List <JFile> orderedList = (potentialEndPoints.OrderByDescending(x => (x.keywordOccurences - x.keywordMisses)).ToList()); // Clean keyword occurences for next search foreach (JFile file in potentialEndPoints) { file.keywordOccurences = 0; file.keywordMisses = 0; } // Return only one file or return multiple ones depending on option if (bMultiReturn) { JFolder newFolder = new JFolder("Search Results"); // Expand Folder newFolder.bExpanded = true; foreach (JFile file in orderedList) { newFolder.Folders.Add(JBuildRootFromFile(file)); } return(newFolder); } else { JFile bestMatch = orderedList[0]; // Return the only best match we have return(JBuildRootFromFile(bestMatch)); } } } }
private void SearchKeywordBox_KeyDown(object sender, KeyEventArgs e) { // http://stackoverflow.com/questions/3099472/previewkeydown-is-not-seeing-alt-modifiers Key key = (e.Key == Key.System ? e.SystemKey : e.Key); // Enter key for quick search if (key == Key.Enter) { // Application short cut if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control) { // Theoratically we can search in index list and open any file with .exe extension (pending implementation) but applications in app home has priority (and doesn't need a suffix) // Pending ignoring upper/lower case // Check file exit string AppPath = AppDomain.CurrentDomain.BaseDirectory + "\\" + App.AppHome + "\\" + SearchKeywordBox.Text; if (!File.Exists(AppPath)) { AppPath += ".exe"; if (!File.Exists(AppPath)) { AppPath = null; } } if (AppPath != null) { System.Diagnostics.Process.Start(AppPath); } else { // update status for information StatusLabel.Content = "Executable doesn't exist."; } } JFolder CurrentDisplay = (DirectoryView.ItemsSource as List <JFolder>).First(); // If no match found if (CurrentDisplay == null) { StatusLabel.Content = "No file to open."; } // If more than one match if found if (CurrentDisplay.Files.Count > 1) { StatusLabel.Content = "More than one match is found, please open using tree view."; } // Otherwise there can be only one match else { if (FolderCheckBox.IsChecked == true) // We are displaying folder serach results { // Get JFolder first List <JFolder> subFolders = CurrentDisplay.Folders; while (subFolders[0].Folders.Count != 0) { subFolders = subFolders[0].Folders; } JFolder foundFolder = subFolders[0]; // If used Alt to open properties if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt) { SystemInterpService.ShowFileProperties(App.GetParentFolderPath(foundFolder)); } // Otherwise open folder else { OpenFolderForInspection(foundFolder); } } else // We are displaying file search results { // Get JFile first List <JFolder> subFolders = CurrentDisplay.Folders; while (subFolders[0].Folders.Count != 0) { subFolders = subFolders[0].Folders; } JFile foundFile = subFolders[0].Files[0]; // If used SHIFT then open file location if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift) { OpenFolderForInspection(foundFile.Parent); } // If used Alt to open properties else if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt) { SystemInterpService.ShowFileProperties(App.GetParentFolderPath(foundFile.Parent) + foundFile.FileName); } // Otherwise just open file else { OpenFileForEditing(foundFile); PreviousOpenFile = foundFile; // For later quick access } } } } }