public override void BuildDialogControls(IVaultDialog dialog, IVaultDialogTab tab) { // File dialog emulation var shellBrowser = new ShellBrowser(); shellBrowser.Dock = DockStyle.Fill; shellBrowser.ListViewMode = View.List; shellBrowser.Multiselect = false; shellBrowser.ShowFolders = false; shellBrowser.ShowFoldersButton = true; var lbFileName = new Label { Text = Resources.Dialogs_BrowseForFile_FileNameLabel, Padding = new Padding(2, 7, 5, 3) }; var tbFileName = new TextBox() { Dock = DockStyle.Fill }; var pn1 = new Panel() { Dock = DockStyle.Left }; pn1.Controls.Add(lbFileName); pn1.Width = 70; var pn2 = new Panel() { Dock = DockStyle.Fill, Padding = new Padding(5, 5, 2, 5) }; pn2.Controls.Add(tbFileName); var pnFileName = new Panel() { Dock = DockStyle.Bottom }; pnFileName.Controls.Add(pn2); pnFileName.Controls.Add(pn1); pnFileName.Height = tbFileName.Height + 10; var pnShellBrowser = new Panel() { Dock = DockStyle.Fill }; pnShellBrowser.Controls.Add(shellBrowser); tab.TabPage.Controls.Add(pnShellBrowser); tab.TabPage.Controls.Add(pnFileName); Action refreshTextBox = () => { var shellItem = shellBrowser.SelectedItem; tbFileName.Text = shellItem == null ? String.Empty : shellItem.Text; }; shellBrowser.FileView.SelectedIndexChanged += (o, e) => refreshTextBox(); shellBrowser.FolderView.AfterSelect += (o, e) => refreshTextBox(); // Ensuring consistent OK button availability Action refreshOkAvailability = () => { var shellItem = shellBrowser.SelectedItem; var fileName = tbFileName.Text; if (fileName == (shellItem == null ? String.Empty : shellItem.Text) || fileName == (shellItem == null ? String.Empty : shellItem.Path)) { // filename in the text box corresponds to selected file/dir dialog.OkButton.Enabled = shellItem != null && shellItem.IsFileSystem && !shellItem.IsFolder && !shellItem.IsLink; } else { dialog.OkButton.Enabled = fileName.IsNeitherNullNorEmpty(); } }; dialog.TabActivated += (o, e) => refreshOkAvailability(); tbFileName.TextChanged += (o, e) => refreshOkAvailability(); // Processing file selection: via OK, via ENTER, or via double-click on a file Action <String> processSelectFile = fpath => { var resolved = fpath.ResolveShellPathAsFileSystemPath(shellBrowser); if (resolved == null) { MessageBox.Show( Resources.Dialogs_BrowseForFile_NotAFileSystemLocation_Message, Resources.Dialogs_BrowseForFile_NotAFileSystemLocation_Title, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // the logic below only accepts full paths Path.IsPathRooted(resolved).AssertTrue(); if (Directory.Exists(resolved)) { MessageBox.Show( Resources.Dialogs_BrowseForFile_FolderIsNotValidHere_Message, Resources.Dialogs_BrowseForFile_FolderIsNotValidHere_Title, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // remember directory-container of the selected file AppDomain.CurrentDomain.SetData(this.GetType().FullName, resolved); if (dialog.Action == VaultAction.Create || dialog.Action == VaultAction.Export) { if (File.Exists(resolved)) { if (MessageBox.Show( Resources.VaultFormat_ExistingFileBasedVault_Message, Resources.VaultFormat_ExistingFileBasedVault_Title, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) { File.Delete(resolved); } else { return; } } else { var parentDir = Path.GetDirectoryName(resolved); parentDir.EnsureDirectoryExists(); // the file itself will be created by vault logic } IVault vault; var dialogForm = tab.TabPage.Parent.Parent.Parent; var oldCursor = dialogForm.Cursor; dialogForm.Cursor = Cursors.WaitCursor; try { vault = OpenCore(resolved); } finally { dialogForm.Cursor = oldCursor; } if (vault != null) { dialog.EndDialog(vault); } } else if (dialog.Action == VaultAction.Open || dialog.Action == VaultAction.Import) { if (!File.Exists(resolved)) { MessageBox.Show( Resources.Dialogs_BrowseForFile_FileDoesNotExist_Message, Resources.Dialogs_BrowseForFile_FileDoesNotExist_Title, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { IVault vault; var dialogForm = tab.TabPage.Parent.Parent.Parent; var oldCursor = dialogForm.Cursor; dialogForm.Cursor = Cursors.WaitCursor; try { vault = OpenCore(resolved); } finally { dialogForm.Cursor = oldCursor; } if (vault != null) { dialog.EndDialog(vault); } } } else { AssertionHelper.Fail(); } } } }; // ENTER over the filename textbox tbFileName.KeyDown += (o, e) => { if (e.KeyCode == Keys.Enter && !e.Alt && !e.Shift && !e.Control) { processSelectFile(tbFileName.Text); } }; // OK click dialog.OkButton.Click += (o, e) => { if (dialog.ActiveTab == tab) { processSelectFile(tbFileName.Text); } }; // double-click or ENTER over the files list Action onValidItemActivated = () => { var shellItem = shellBrowser.SelectedItem; shellItem.AssertNotNull(); shellItem.IsFileSystem.AssertTrue(); shellItem.IsFolder.AssertFalse(); shellItem.IsLink.AssertFalse(); processSelectFile(shellItem.Text); }; // Stuff that needs to be run on after the handle is created shellBrowser.HandleCreated += (o, e) => { // loads startup dir from appdomain-wide history var prevFile = (String)AppDomain.CurrentDomain.GetData(this.GetType().FullName); var startupDir = Path.GetDirectoryName(prevFile); if (!Directory.Exists(startupDir)) { startupDir = null; } startupDir = startupDir ?? shellBrowser.ShellBrowserComponent.MyDocumentsPath; shellBrowser.SelectPath(startupDir, false); // selects previously selected file in the file view... var match = shellBrowser.FileView.Items.Cast <ListViewItem>().SingleOrDefaultDontCrash(lvi => { var si = lvi.Tag.AssertCast <ShellItem>(); return(si.Text.ResolveShellPathAsFileSystemPath(shellBrowser) == prevFile); }); // ...if it still exists if (match != null) { match.Selected = true; } // remember all changes of current directory Action storeCurrentDirInAppDomain = () => { var currentDir = ".".ResolveShellPathAsFileSystemPath(shellBrowser); AppDomain.CurrentDomain.SetData(this.GetType().FullName, Path.Combine(currentDir, "aux")); }; shellBrowser.FileView.SelectedIndexChanged += (o1, e1) => storeCurrentDirInAppDomain(); shellBrowser.FolderView.AfterSelect += (o1, e1) => storeCurrentDirInAppDomain(); // make sure that double-clicking on a file doesn't open associated application // but just selects that file instead var fv = shellBrowser.fileView; var itemActivate = typeof(ListView).GetEvent("ItemActivate"); var invocationList = itemActivate.GetInvocationList(fv); itemActivate.ClearInvocationList(fv); fv.ItemActivate += (o1, e1) => { refreshOkAvailability(); if (dialog.OkButton.Enabled) { onValidItemActivated(); } else { invocationList.ForEach(d => d.DynamicInvoke(o1, e1)); } }; }; }
public override void BuildDialogControls(IVaultDialog dialog, IVaultDialogTab tab) { // File dialog emulation var shellBrowser = new ShellBrowser(); shellBrowser.Dock = DockStyle.Fill; shellBrowser.ListViewMode = View.List; shellBrowser.Multiselect = false; shellBrowser.ShowFolders = true; shellBrowser.ShowFoldersButton = false; shellBrowser.browseSplitter.Panel2Collapsed = true; // hack! var lbFolderName = new Label { Text = Resources.Dialogs_BrowseForFolder_FolderNameLabel, Padding = new Padding(2, 7, 5, 3) }; var tbFolderName = new TextBox() { Dock = DockStyle.Fill }; var pn1 = new Panel() { Dock = DockStyle.Left }; pn1.Controls.Add(lbFolderName); pn1.Width = 70; var pn2 = new Panel() { Dock = DockStyle.Fill, Padding = new Padding(5, 5, 2, 5) }; pn2.Controls.Add(tbFolderName); var pnFolderName = new Panel() { Dock = DockStyle.Bottom }; pnFolderName.Controls.Add(pn2); pnFolderName.Controls.Add(pn1); pnFolderName.Height = tbFolderName.Height + 10; var pnShellBrowser = new Panel() { Dock = DockStyle.Fill }; pnShellBrowser.Controls.Add(shellBrowser); tab.TabPage.Controls.Add(pnShellBrowser); tab.TabPage.Controls.Add(pnFolderName); shellBrowser.HandleCreated += (o, e) => { // loads startup dir from appdomain-wide history var startupDir = (String)AppDomain.CurrentDomain.GetData(this.GetType().FullName); if (!Directory.Exists(startupDir)) { startupDir = null; } startupDir = startupDir ?? shellBrowser.ShellBrowserComponent.MyDocumentsPath; shellBrowser.SelectPath(startupDir, false); // remember all changes of current directory Action storeCurrentDirInAppDomain = () => { var currentDir = ".".ResolveShellPathAsFileSystemPath(shellBrowser); AppDomain.CurrentDomain.SetData(this.GetType().FullName, currentDir); }; shellBrowser.FileView.SelectedIndexChanged += (o1, e1) => storeCurrentDirInAppDomain(); shellBrowser.FolderView.AfterSelect += (o1, e1) => storeCurrentDirInAppDomain(); }; Action refreshTextBox = () => { var shellItem = shellBrowser.CurrentDirectory; tbFolderName.Text = shellItem == null ? String.Empty : "."; }; shellBrowser.FileView.SelectedIndexChanged += (o, e) => refreshTextBox(); shellBrowser.FolderView.AfterSelect += (o, e) => refreshTextBox(); // Ensuring consistent OK button availability Action refreshOkAvailability = () => { var shellItem = shellBrowser.CurrentDirectory; // hack var folderName = tbFolderName.Text; if (folderName == (shellItem == null ? String.Empty : shellItem.Text) || folderName == (shellItem == null ? String.Empty : shellItem.Path)) { // foldername in the text box corresponds to selected file/dir dialog.OkButton.Enabled = shellItem != null && shellItem.IsFileSystem && shellItem.IsFolder && !shellItem.IsLink; } else { dialog.OkButton.Enabled = folderName.IsNeitherNullNorEmpty(); } }; dialog.TabActivated += (o, e) => refreshOkAvailability(); tbFolderName.TextChanged += (o, e) => refreshOkAvailability(); // Processing folder selection: via OK, via ENTER, or via double-click on a folder in the tree Action <String> processSelectFolder = path => { var resolved = path.ResolveShellPathAsFileSystemPath(shellBrowser); if (resolved == null) { MessageBox.Show( Resources.Dialogs_BrowseForFolder_NotAFileSystemLocation_Message, Resources.Dialogs_BrowseForFolder_NotAFileSystemLocation_Title, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // the logic below only accepts full paths Path.IsPathRooted(resolved).AssertTrue(); if (File.Exists(resolved)) { MessageBox.Show( Resources.Dialogs_BrowseForFolder_FileIsNotValidHere_Message, Resources.Dialogs_BrowseForFolder_FileIsNotValidHere_Title, MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // remember the selection AppDomain.CurrentDomain.SetData(this.GetType().FullName, resolved); if (dialog.Action == VaultAction.Create || dialog.Action == VaultAction.Export) { if (ApproveSavingToUri(resolved)) { resolved.EnsureDirectoryExists(); var vault = OpenCore(resolved, true); if (vault != null) { dialog.EndDialog(vault); } } } else if (dialog.Action == VaultAction.Open || dialog.Action == VaultAction.Import) { if (ApproveOpeningFromUri(resolved)) { var vault = OpenCore(resolved, false); if (vault != null) { dialog.EndDialog(vault); } } } else { AssertionHelper.Fail(); } } } }; // disabled on purpose: // general guideline is having expand/collapse on double click // and even Windows' system browse for folder dialog respects this behaviour // shellBrowser.folderView.NodeMouseDoubleClick += (o, e) => // { // refreshOkAvailability(); // if (dialog.OkButton.Enabled) // { // processSelectShellItem(); // } // }; dialog.OkButton.Click += (o, e) => { if (dialog.ActiveTab == tab) { processSelectFolder(tbFolderName.Text); } }; tbFolderName.KeyDown += (o, e) => { if (e.KeyCode == Keys.Enter && !e.Alt && !e.Shift && !e.Control) { processSelectFolder(tbFolderName.Text); } }; }