Exemplo n.º 1
0
        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));
                    }
                };
            };
        }
Exemplo n.º 2
0
        public static String ResolveShellPathAsFileSystemPath(this String shellPath, ShellBrowser shellBrowser)
        {
            try
            {
                String resolved;
                if (Path.IsPathRooted(shellPath))
                {
                    resolved = shellPath;
                }
                else
                {
                    var parent = shellBrowser.CurrentDirectory;
                    parent.AssertNotNull();

                    Func<ShellItem, String> reallyRealPath = si =>
                    {
                        var realPath = ShellItem.GetRealPath(si);
                        Func<Func<String>, String> neverFail = f => { try { return f(); } catch { return null; } };
                        realPath = neverFail(() => Path.GetFullPath(realPath));

                        if (realPath == null)
                        {
                            var desktop = shellBrowser.ShellBrowserComponent.DesktopItem;
                            if (si == desktop)
                            {
                                realPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
                            }
                            else if (si.Text == shellBrowser.ShellBrowserComponent.MyComputerName)
                            {
                                realPath = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
                            }
                            else
                            {
                                // todo. possibly map other bizarre folders
                                AssertionHelper.Fail();
                            }
                        }

                        realPath.AssertNotNull();
                        return realPath;
                    };

                    // strategy 1. match children of current parent with the fpath
                    var match = parent.Cast<ShellItem>().SingleOrDefaultDontCrash(si => si.Text == shellPath);
                    if (match != null)
                    {
                        match.IsFileSystem.AssertTrue();
                        match.IsLink.AssertFalse();
                        resolved = reallyRealPath(match);
                    }
                    // strategy 2. resolve fpath as [parent's real path] + fpath
                    else
                    {
                        var parentResolved = reallyRealPath(parent);
                        resolved = Path.Combine(parentResolved, shellPath);
                    }
                }

                resolved.AssertNotNull();
                Path.IsPathRooted(resolved).AssertTrue();

                // canonicalize the path
                resolved = Path.GetFullPath(resolved);
                return resolved;
            }
            catch (Exception)
            {
                // i know this is bad, but in this case user experience >> robustness
                return null;
            }
        }