diff options
author | Jeff Johnston | 2016-11-07 23:02:42 +0000 |
---|---|---|
committer | Jeff Johnston | 2016-11-07 23:44:17 +0000 |
commit | 23f393f9c1b2c422dea1f76b3359a8a80f8fd54d (patch) | |
tree | 846b978448b88f1fdf9a8fdbe6784ceaa42f30b6 | |
parent | 378935f628a275a30dac9dd9bc3f38b0273e2b00 (diff) | |
download | org.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>
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: |