Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Johnston2016-11-07 23:02:42 +0000
committerJeff Johnston2016-11-07 23:44:17 +0000
commit23f393f9c1b2c422dea1f76b3359a8a80f8fd54d (patch)
tree846b978448b88f1fdf9a8fdbe6784ceaa42f30b6
parent378935f628a275a30dac9dd9bc3f38b0273e2b00 (diff)
downloadorg.eclipse.linuxtools-23f393f9c1b2c422dea1f76b3359a8a80f8fd54d.tar.gz
org.eclipse.linuxtools-23f393f9c1b2c422dea1f76b3359a8a80f8fd54d.tar.xz
org.eclipse.linuxtools-23f393f9c1b2c422dea1f76b3359a8a80f8fd54d.zip
Bug 507192 - Add a Container directory dialog
- add DynamicTreeViewer which is similar to DynamicCheckboxTreeViewer but without checkboxes - add ContainerTreeGroup class which uses a DynamicTreeViewer - add ContainerDirectorySelectionDialog class which uses the ContainerTreeGroup to show the directory tree for an active Container Change-Id: I4f615c9018d323ecda0fc83ffa1b041c5107bfdd Reviewed-on: https://git.eclipse.org/r/84631 Tested-by: Hudson CI Reviewed-by: Jeff Johnston <jjohnstn@redhat.com>
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/.settings/.api_filters8
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ContainerDirectorySelectionDialog.java239
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ContainerTreeGroup.java289
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/DynamicTreeViewer.java49
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/Messages.properties2
5 files changed, 587 insertions, 0 deletions
diff --git a/containers/org.eclipse.linuxtools.docker.ui/.settings/.api_filters b/containers/org.eclipse.linuxtools.docker.ui/.settings/.api_filters
index 639132ef55..22c6629ceb 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/.settings/.api_filters
+++ b/containers/org.eclipse.linuxtools.docker.ui/.settings/.api_filters
@@ -8,4 +8,12 @@
</message_arguments>
</filter>
</resource>
+ <resource path="src/org/eclipse/linuxtools/internal/docker/ui/DynamicTreeViewer.java" type="org.eclipse.linuxtools.internal.docker.ui.DynamicTreeViewer">
+ <filter id="571473929">
+ <message_arguments>
+ <message_argument value="TreeViewer"/>
+ <message_argument value="DynamicTreeViewer"/>
+ </message_arguments>
+ </filter>
+ </resource>
</component>
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ContainerDirectorySelectionDialog.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ContainerDirectorySelectionDialog.java
new file mode 100644
index 0000000000..f856169dc6
--- /dev/null
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ContainerDirectorySelectionDialog.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat - Initial Contribution
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.docker.ui;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.linuxtools.internal.docker.core.ContainerFileProxy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.FileSystemElement;
+import org.eclipse.ui.dialogs.SelectionDialog;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.model.WorkbenchViewerComparator;
+import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
+
+/**
+ * A standard directory selection dialog which solicits a choice of directory
+ * from the user. The <code>getResult</code> method returns the selected
+ * directory in a list.
+ * <p>
+ * This class may be instantiated; it is not intended to be subclassed.
+ * </p>
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * ProgressMonitorDialog pd = new ProgressMonitorDialog(
+ * Activator.getActiveWorkbenchShell());
+ * ContainerFileSystemProvider provider = new ContainerFileSystemProvider(
+ * connection, container.id());
+ * PopulateContainerFilesOperation sfo = new PopulateContainerFilesOperation(
+ * new ContainerFileProxy("", "", true), //$NON-NLS-1$ //$NON-NLS-2$
+ * null, provider);
+ * try {
+ * pd.run(true, true, sfo); m
+ * } catch (InvocationTargetException | InterruptedException e) {
+ * e.printStackTrace();
+ * }
+ * ContainerDirectorySelectionDialog d = new ContainerDirectorySelectionDialog(
+ * Activator.getActiveWorkbenchShell(), sfo.getResult(), provider,
+ * null);
+ * if (d.open() == IStatus.OK) {
+ * return d.getResult();
+ * }
+ * </pre>
+ * </p>
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class ContainerDirectorySelectionDialog extends SelectionDialog {
+ // the root file representative to populate the viewer with
+ private FileSystemElement root;
+
+ private IImportStructureProvider structureProvider;
+ // static final String FILE_SELECTION_DIALOG =
+ // "org.eclipse.ui.ide.file_selection_dialog_context"; //$NON-NLS-1$
+
+ // the visual selection widget group
+ ContainerTreeGroup selectionGroup;
+
+ // expand all items in the tree view on dialog open
+ private boolean expandAllOnOpen = false;
+
+ // sizing constants
+ private static final int SIZING_SELECTION_WIDGET_WIDTH = 500;
+
+ private static final int SIZING_SELECTION_WIDGET_HEIGHT = 250;
+
+ static final String SELECT_ALL_TITLE = "SelectionDialog_selectLabel"; //$NON-NLS-1$
+ static final String DESELECT_ALL_TITLE = "SelectionDialog_deselectLabel"; //$NON-NLS-1$
+
+ /**
+ * Creates a file selection dialog rooted at the given file system element.
+ *
+ * @param parentShell the parent shell
+ * @param fileSystemElement the root element to populate this dialog with
+ * @param message the message to be displayed at the top of this dialog, or
+ * <code>null</code> to display a default message
+ */
+ public ContainerDirectorySelectionDialog(Shell parentShell,
+ FileSystemElement fileSystemElement,
+ IImportStructureProvider structureProvider, String message) {
+ super(parentShell);
+ setTitle(Messages.getString("DirectorySelectionDialog_title")); //$NON-NLS-1$
+ root = fileSystemElement;
+ this.structureProvider = structureProvider;
+ if (message != null) {
+ setMessage(message);
+ } else {
+ setMessage(Messages.getString("DirectorySelectionDialog_message")); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ // TODO: replace with correct help context
+ // PlatformUI.getWorkbench().getHelpSystem().setHelp(shell,
+ // FILE_SELECTION_DIALOG);
+ }
+
+ @Override
+ public void create() {
+ super.create();
+ initializeDialog();
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ // page group
+ Composite composite = (Composite) super.createDialogArea(parent);
+
+ createMessageArea(composite);
+
+ // Create a fake parent of the root to be the dialog input element.
+ // Use an empty label so that display of the element's full name
+ // doesn't include a confusing label
+ FileSystemElement input = new FileSystemElement("", null, true);//$NON-NLS-1$
+ input.addChild(root);
+ root.setParent(input);
+
+ selectionGroup = new ContainerTreeGroup(composite, input,
+ getFolderProvider(), getDynamicFolderProvider(),
+ new WorkbenchLabelProvider(),
+ SWT.NONE,
+ SIZING_SELECTION_WIDGET_WIDTH, // since this page has no other significantly-sized
+ SIZING_SELECTION_WIDGET_HEIGHT); // widgets we need to hardcode the combined widget's
+ // size, otherwise it will open too small
+
+ ISelectionChangedListener listener = event -> getOkButton()
+ .setEnabled(event.getSelection() != null
+ && !event.getSelection().isEmpty());
+
+ WorkbenchViewerComparator comparator = new WorkbenchViewerComparator();
+ selectionGroup.setTreeComparator(comparator);
+ selectionGroup.addSelectionChangedListener(listener);
+ return composite;
+ }
+
+ /**
+ * Returns whether the tree view of the file system element
+ * will be fully expanded when the dialog is opened.
+ *
+ * @return true to expand all on dialog open, false otherwise.
+ */
+ public boolean getExpandAllOnOpen() {
+ return expandAllOnOpen;
+ }
+
+ /**
+ * Returns a content provider for <code>FileSystemElement</code>s that returns
+ * only folders as children.
+ */
+ private ITreeContentProvider getFolderProvider() {
+ return new WorkbenchContentProvider() {
+ @Override
+ public Object[] getChildren(Object o) {
+ if (o instanceof FileSystemElement) {
+ return ((FileSystemElement) o).getFolders().getChildren(o);
+ }
+
+ return new Object[0];
+ }
+ };
+ }
+
+ /**
+ * Returns a content provider for <code>FileSystemElement</code>s that
+ * returns only folders as children.
+ */
+ private ITreeContentProvider getDynamicFolderProvider() {
+ return new WorkbenchContentProvider() {
+ @Override
+ public Object[] getChildren(Object o) {
+ if (o instanceof MinimizedFileSystemElement) {
+ return ((MinimizedFileSystemElement) o)
+ .getFolders(structureProvider)
+ .getChildren(o);
+ } else if (o instanceof FileSystemElement) {
+ return ((FileSystemElement) o).getFolders().getChildren(o);
+ }
+
+ return new Object[0];
+ }
+ };
+ }
+
+ /**
+ * Initializes this dialog's controls.
+ */
+ private void initializeDialog() {
+ // initialize page
+ if (getInitialElementSelections().isEmpty()) {
+ getOkButton().setEnabled(false);
+ }
+ selectionGroup.aboutToOpen();
+ }
+
+ /**
+ * The <code>FileSelectionDialog</code> implementation of this
+ * <code>Dialog</code> method builds a list of the selected files for later
+ * retrieval by the client and closes this dialog.
+ */
+ @SuppressWarnings({})
+ @Override
+ protected void okPressed() {
+ Object result = selectionGroup.getCurrentSelection();
+ if (result != null) {
+ MinimizedFileSystemElement selected = (MinimizedFileSystemElement) result;
+ List<ContainerFileProxy> list = new ArrayList<>();
+ list.add((ContainerFileProxy) selected.getFileSystemObject());
+ setResult(list);
+ }
+ super.okPressed();
+ }
+
+ /**
+ * Set whether the tree view of the file system element
+ * will be fully expanded when the dialog is opened.
+ *
+ * @param expandAll true to expand all on dialog open, false otherwise.
+ */
+ public void setExpandAllOnOpen(boolean expandAll) {
+ expandAllOnOpen = expandAll;
+ }
+}
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ContainerTreeGroup.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ContainerTreeGroup.java
new file mode 100644
index 0000000000..dde4dd5e09
--- /dev/null
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/ContainerTreeGroup.java
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.docker.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.commands.common.EventManager;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.jface.util.SafeRunnable;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ITreeViewerListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeExpansionEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+
+/**
+ * Workbench-level composite that shows a dynamic tree. All viewer
+ * selection-driven interactions are handled within this object
+ */
+@SuppressWarnings("rawtypes")
+public class ContainerTreeGroup extends EventManager implements
+ ISelectionChangedListener, ITreeViewerListener {
+ private Object root;
+
+ private Object currentTreeSelection;
+
+ private List expandedTreeNodes = new ArrayList();
+
+ private ITreeContentProvider treeContentProvider;
+
+ private ITreeContentProvider dynamicTreeContentProvider;
+
+ private ILabelProvider treeLabelProvider;
+
+ // widgets
+ private TreeViewer treeViewer;
+
+ /**
+ * Create an instance of this class. Use this constructor if you wish to
+ * specify the width and/or height of the combined widget (to only hardcode
+ * one of the sizing dimensions, specify the other dimension's value as -1)
+ *
+ * @param parent
+ * @param rootObject
+ * @param treeContentProvider
+ * @param treeLabelProvider
+ * @param listContentProvider
+ * @param listLabelProvider
+ * @param style
+ * @param width
+ * @param height
+ */
+ public ContainerTreeGroup(Composite parent, Object rootObject,
+ ITreeContentProvider treeContentProvider,
+ ITreeContentProvider dynamicTreeContentProvider,
+ ILabelProvider treeLabelProvider,
+ int style, int width,
+ int height) {
+
+ root = rootObject;
+ this.treeContentProvider = treeContentProvider;
+ this.dynamicTreeContentProvider = dynamicTreeContentProvider;
+ this.treeLabelProvider = treeLabelProvider;
+ createContents(parent, width, height, style);
+ }
+
+ /**
+ * This method must be called just before this window becomes visible.
+ */
+ public void aboutToOpen() {
+ currentTreeSelection = null;
+
+ // select the first element in the list
+ Object[] elements = treeContentProvider.getElements(root);
+ Object primary = elements.length > 0 ? elements[0] : null;
+ if (primary != null) {
+ treeViewer.setSelection(new StructuredSelection(primary));
+ }
+ treeViewer.getControl().setFocus();
+ }
+
+ /**
+ * Lay out and initialize self's visual components.
+ *
+ * @param parent
+ * org.eclipse.swt.widgets.Composite
+ * @param width
+ * int
+ * @param height
+ * int
+ */
+ protected void createContents(Composite parent, int width, int height,
+ int style) {
+ // group pane
+ Composite composite = new Composite(parent, style);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ layout.makeColumnsEqualWidth = true;
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ composite.setFont(parent.getFont());
+
+ createTreeViewer(composite, width, height);
+ initialize();
+ }
+
+ /**
+ * Create this group's tree viewer.
+ */
+ protected void createTreeViewer(Composite parent, int width, int height) {
+ Tree tree = new Tree(parent, SWT.BORDER | SWT.SINGLE);
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.widthHint = width;
+ data.heightHint = height;
+ tree.setLayoutData(data);
+ tree.setFont(parent.getFont());
+
+ treeViewer = new DynamicTreeViewer(tree,
+ dynamicTreeContentProvider);
+ treeViewer.setContentProvider(treeContentProvider);
+ treeViewer.setLabelProvider(treeLabelProvider);
+ treeViewer.addTreeListener(this);
+ treeViewer.addSelectionChangedListener(this);
+ }
+
+ /**
+ * Cause the tree viewer to expand all its items
+ */
+ public void expandAll() {
+ treeViewer.expandAll();
+ }
+
+ /**
+ * Initialize this group's viewers after they have been laid out.
+ */
+ protected void initialize() {
+ treeViewer.setInput(root);
+ }
+
+
+ /**
+ * Notify all selection state listeners that a selection has been made
+ */
+ protected void notifySelectionChangeListeners(
+ final SelectionChangedEvent event) {
+ Object[] array = getListeners();
+ for (int i = 0; i < array.length; i++) {
+ final ISelectionChangedListener l = (ISelectionChangedListener) array[i];
+ SafeRunner.run(new SafeRunnable() {
+ @Override
+ public void run() {
+ l.selectionChanged(event);
+ }
+ });
+ }
+ }
+
+ /**
+ * Add the passed listener to self's collection of clients that listen for
+ * changes to selection
+ *
+ * @param listener
+ * ISelectionChangedListener
+ */
+ public void addSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ addListenerObject(listener);
+ }
+
+ /**
+ * Remove the passed listener from self's collection of clients that listen
+ * for changes to selection
+ *
+ * @param listener
+ * ISelectionChangedListener
+ */
+ public void removeSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ removeListenerObject(listener);
+ }
+
+ /**
+ * Handle the selection of an item in the tree viewer
+ *
+ * @param event
+ * SelectionChangedEvent
+ */
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection selection = (IStructuredSelection) event
+ .getSelection();
+ Object selectedElement = selection.getFirstElement();
+ currentTreeSelection = selectedElement;
+ notifySelectionChangeListeners(event);
+ }
+
+ public Object getCurrentSelection() {
+ return currentTreeSelection;
+ }
+
+ /**
+ * Set the root of the widget to be new Root. Regenerate all of the tables
+ * and lists from this value.
+ *
+ * @param newRoot
+ */
+ public void setRoot(Object newRoot) {
+ this.root = newRoot;
+ initialize();
+ }
+
+ /**
+ * Set the tree viewer's providers to those passed
+ *
+ * @param contentProvider
+ * ITreeContentProvider
+ * @param labelProvider
+ * ILabelProvider
+ */
+ public void setTreeProviders(ITreeContentProvider contentProvider,
+ ILabelProvider labelProvider) {
+ treeViewer.setContentProvider(contentProvider);
+ treeViewer.setLabelProvider(labelProvider);
+ }
+
+ /**
+ * Set the comparator that is to be applied to self's tree viewer
+ *
+ * @param comparator
+ * the comparator for the tree
+ */
+ public void setTreeComparator(ViewerComparator comparator) {
+ treeViewer.setComparator(comparator);
+ }
+
+
+ /**
+ * Handle the collapsing of an element in a tree viewer
+ */
+ @Override
+ public void treeCollapsed(TreeExpansionEvent event) {
+ // We don't need to do anything with this
+ }
+
+ /**
+ * Handle the expansionsion of an element in a tree viewer
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void treeExpanded(TreeExpansionEvent event) {
+
+ Object item = event.getElement();
+
+ // First see if the children need to be given their checked state at
+ // all. If they've
+ // already been realized then this won't be necessary
+ if (!expandedTreeNodes.contains(item)) {
+ expandedTreeNodes.add(item);
+ dynamicTreeContentProvider.getChildren(item);
+ Object[] children = treeContentProvider.getElements(item);
+ for (int i = 0; i < children.length; ++i) {
+ dynamicTreeContentProvider.getElements(children[i]);
+ }
+ }
+ }
+
+}
+
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/DynamicTreeViewer.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/DynamicTreeViewer.java
new file mode 100644
index 0000000000..9caa6b378e
--- /dev/null
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/DynamicTreeViewer.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat - Initial Contribution
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.docker.ui;
+
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.events.TreeEvent;
+import org.eclipse.swt.widgets.Tree;
+
+public class DynamicTreeViewer extends TreeViewer {
+
+ private final ITreeContentProvider dynamicProvider;
+ private boolean useDynamic;
+
+ public DynamicTreeViewer(Tree tree,
+ ITreeContentProvider dynamicProvider) {
+ super(tree);
+ this.dynamicProvider = dynamicProvider;
+ }
+
+ public void useDynamic(boolean value) {
+ this.useDynamic = value;
+ }
+
+ @Override
+ public IContentProvider getContentProvider() {
+ if (useDynamic) {
+ return dynamicProvider;
+ }
+ return super.getContentProvider();
+ }
+
+ @Override
+ protected void handleTreeExpand(TreeEvent event) {
+ useDynamic(true);
+ super.handleTreeExpand(event);
+ useDynamic(false);
+ }
+
+}
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/Messages.properties b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/Messages.properties
index 9cf863adb9..a6539008e2 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/Messages.properties
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/Messages.properties
@@ -4,3 +4,5 @@ FileSelectionDialog_title = File Selection
FileSelectionDialog_message = Select the files:
SelectionDialog_selectLabel = &Select All
SelectionDialog_deselectLabel = &Deselect All
+DirectorySelectionDialog_title = Directory Selection
+DirectorySelectionDialog_message = Select a directory:

Back to the top