001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Igor Fedorenko <igorfie@yahoo.com> -
011: * Fix for Bug 136921 [IDE] New File dialog locks for 20 seconds
012: *******************************************************************************/package org.eclipse.ui.internal.ide.misc;
013:
014: import java.util.ArrayList;
015: import java.util.List;
016:
017: import org.eclipse.core.resources.IContainer;
018: import org.eclipse.core.resources.ResourcesPlugin;
019: import org.eclipse.core.runtime.IPath;
020: import org.eclipse.core.runtime.Path;
021: import org.eclipse.jface.dialogs.Dialog;
022: import org.eclipse.jface.viewers.DoubleClickEvent;
023: import org.eclipse.jface.viewers.IDoubleClickListener;
024: import org.eclipse.jface.viewers.ISelection;
025: import org.eclipse.jface.viewers.ISelectionChangedListener;
026: import org.eclipse.jface.viewers.IStructuredSelection;
027: import org.eclipse.jface.viewers.SelectionChangedEvent;
028: import org.eclipse.jface.viewers.StructuredSelection;
029: import org.eclipse.jface.viewers.TreeViewer;
030: import org.eclipse.jface.viewers.ViewerComparator;
031: import org.eclipse.swt.SWT;
032: import org.eclipse.swt.layout.GridData;
033: import org.eclipse.swt.layout.GridLayout;
034: import org.eclipse.swt.widgets.Composite;
035: import org.eclipse.swt.widgets.Event;
036: import org.eclipse.swt.widgets.Label;
037: import org.eclipse.swt.widgets.Listener;
038: import org.eclipse.swt.widgets.Text;
039: import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
040: import org.eclipse.ui.model.WorkbenchLabelProvider;
041: import org.eclipse.ui.part.DrillDownComposite;
042:
043: /**
044: * Workbench-level composite for choosing a container.
045: */
046: public class ContainerSelectionGroup extends Composite {
047: // The listener to notify of events
048: private Listener listener;
049:
050: // Enable user to type in new container name
051: private boolean allowNewContainerName = true;
052:
053: // show all projects by default
054: private boolean showClosedProjects = true;
055:
056: // Last selection made by user
057: private IContainer selectedContainer;
058:
059: // handle on parts
060: private Text containerNameField;
061:
062: TreeViewer treeViewer;
063:
064: // the message to display at the top of this dialog
065: private static final String DEFAULT_MSG_NEW_ALLOWED = IDEWorkbenchMessages.ContainerGroup_message;
066:
067: private static final String DEFAULT_MSG_SELECT_ONLY = IDEWorkbenchMessages.ContainerGroup_selectFolder;
068:
069: // sizing constants
070: private static final int SIZING_SELECTION_PANE_WIDTH = 320;
071:
072: private static final int SIZING_SELECTION_PANE_HEIGHT = 300;
073:
074: /**
075: * Creates a new instance of the widget.
076: *
077: * @param parent
078: * The parent widget of the group.
079: * @param listener
080: * A listener to forward events to. Can be null if no listener is
081: * required.
082: * @param allowNewContainerName
083: * Enable the user to type in a new container name instead of
084: * just selecting from the existing ones.
085: */
086: public ContainerSelectionGroup(Composite parent, Listener listener,
087: boolean allowNewContainerName) {
088: this (parent, listener, allowNewContainerName, null);
089: }
090:
091: /**
092: * Creates a new instance of the widget.
093: *
094: * @param parent
095: * The parent widget of the group.
096: * @param listener
097: * A listener to forward events to. Can be null if no listener is
098: * required.
099: * @param allowNewContainerName
100: * Enable the user to type in a new container name instead of
101: * just selecting from the existing ones.
102: * @param message
103: * The text to present to the user.
104: */
105: public ContainerSelectionGroup(Composite parent, Listener listener,
106: boolean allowNewContainerName, String message) {
107: this (parent, listener, allowNewContainerName, message, true);
108: }
109:
110: /**
111: * Creates a new instance of the widget.
112: *
113: * @param parent
114: * The parent widget of the group.
115: * @param listener
116: * A listener to forward events to. Can be null if no listener is
117: * required.
118: * @param allowNewContainerName
119: * Enable the user to type in a new container name instead of
120: * just selecting from the existing ones.
121: * @param message
122: * The text to present to the user.
123: * @param showClosedProjects
124: * Whether or not to show closed projects.
125: */
126: public ContainerSelectionGroup(Composite parent, Listener listener,
127: boolean allowNewContainerName, String message,
128: boolean showClosedProjects) {
129: this (parent, listener, allowNewContainerName, message,
130: showClosedProjects, SIZING_SELECTION_PANE_HEIGHT,
131: SIZING_SELECTION_PANE_WIDTH);
132: }
133:
134: /**
135: * Creates a new instance of the widget.
136: *
137: * @param parent
138: * The parent widget of the group.
139: * @param listener
140: * A listener to forward events to. Can be null if no listener is
141: * required.
142: * @param allowNewContainerName
143: * Enable the user to type in a new container name instead of
144: * just selecting from the existing ones.
145: * @param message
146: * The text to present to the user.
147: * @param showClosedProjects
148: * Whether or not to show closed projects.
149: * @param heightHint
150: * height hint for the drill down composite
151: * @param widthHint
152: * width hint for the drill down composite
153: */
154: public ContainerSelectionGroup(Composite parent, Listener listener,
155: boolean allowNewContainerName, String message,
156: boolean showClosedProjects, int heightHint, int widthHint) {
157: super (parent, SWT.NONE);
158: this .listener = listener;
159: this .allowNewContainerName = allowNewContainerName;
160: this .showClosedProjects = showClosedProjects;
161: if (message != null) {
162: createContents(message, heightHint, widthHint);
163: } else if (allowNewContainerName) {
164: createContents(DEFAULT_MSG_NEW_ALLOWED, heightHint,
165: widthHint);
166: } else {
167: createContents(DEFAULT_MSG_SELECT_ONLY, heightHint,
168: widthHint);
169: }
170: }
171:
172: /**
173: * The container selection has changed in the tree view. Update the
174: * container name field value and notify all listeners.
175: *
176: * @param container
177: * The container that changed
178: */
179: public void containerSelectionChanged(IContainer container) {
180: selectedContainer = container;
181:
182: if (allowNewContainerName) {
183: if (container == null) {
184: containerNameField.setText("");//$NON-NLS-1$
185: } else {
186: String text = container.getFullPath().makeRelative()
187: .toString();
188: containerNameField.setText(text);
189: containerNameField.setToolTipText(text);
190: }
191: }
192:
193: // fire an event so the parent can update its controls
194: if (listener != null) {
195: Event changeEvent = new Event();
196: changeEvent.type = SWT.Selection;
197: changeEvent.widget = this ;
198: listener.handleEvent(changeEvent);
199: }
200: }
201:
202: /**
203: * Creates the contents of the composite.
204: *
205: * @param message
206: */
207: public void createContents(String message) {
208: createContents(message, SIZING_SELECTION_PANE_HEIGHT,
209: SIZING_SELECTION_PANE_WIDTH);
210: }
211:
212: /**
213: * Creates the contents of the composite.
214: *
215: * @param message
216: * @param heightHint
217: * @param widthHint
218: */
219: public void createContents(String message, int heightHint,
220: int widthHint) {
221: GridLayout layout = new GridLayout();
222: layout.marginWidth = 0;
223: setLayout(layout);
224: setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
225:
226: Label label = new Label(this , SWT.WRAP);
227: label.setText(message);
228: label.setFont(this .getFont());
229:
230: if (allowNewContainerName) {
231: containerNameField = new Text(this , SWT.SINGLE | SWT.BORDER);
232: GridData gd = new GridData(GridData.FILL_HORIZONTAL);
233: gd.widthHint = widthHint;
234: containerNameField.setLayoutData(gd);
235: containerNameField.addListener(SWT.Modify, listener);
236: containerNameField.setFont(this .getFont());
237: } else {
238: // filler...
239: new Label(this , SWT.NONE);
240: }
241:
242: createTreeViewer(heightHint);
243: Dialog.applyDialogFont(this );
244: }
245:
246: /**
247: * Returns a new drill down viewer for this dialog.
248: *
249: * @param heightHint
250: * height hint for the drill down composite
251: */
252: protected void createTreeViewer(int heightHint) {
253: // Create drill down.
254: DrillDownComposite drillDown = new DrillDownComposite(this ,
255: SWT.BORDER);
256: GridData spec = new GridData(SWT.FILL, SWT.FILL, true, true);
257: spec.widthHint = SIZING_SELECTION_PANE_WIDTH;
258: spec.heightHint = heightHint;
259: drillDown.setLayoutData(spec);
260:
261: // Create tree viewer inside drill down.
262: treeViewer = new TreeViewer(drillDown, SWT.NONE);
263: drillDown.setChildTree(treeViewer);
264: ContainerContentProvider cp = new ContainerContentProvider();
265: cp.showClosedProjects(showClosedProjects);
266: treeViewer.setContentProvider(cp);
267: treeViewer.setLabelProvider(WorkbenchLabelProvider
268: .getDecoratingWorkbenchLabelProvider());
269: treeViewer.setComparator(new ViewerComparator());
270: treeViewer.setUseHashlookup(true);
271: treeViewer
272: .addSelectionChangedListener(new ISelectionChangedListener() {
273: public void selectionChanged(
274: SelectionChangedEvent event) {
275: IStructuredSelection selection = (IStructuredSelection) event
276: .getSelection();
277: containerSelectionChanged((IContainer) selection
278: .getFirstElement()); // allow null
279: }
280: });
281: treeViewer.addDoubleClickListener(new IDoubleClickListener() {
282: public void doubleClick(DoubleClickEvent event) {
283: ISelection selection = event.getSelection();
284: if (selection instanceof IStructuredSelection) {
285: Object item = ((IStructuredSelection) selection)
286: .getFirstElement();
287: if (item == null) {
288: return;
289: }
290: if (treeViewer.getExpandedState(item)) {
291: treeViewer.collapseToLevel(item, 1);
292: } else {
293: treeViewer.expandToLevel(item, 1);
294: }
295: }
296: }
297: });
298:
299: // This has to be done after the viewer has been laid out
300: treeViewer.setInput(ResourcesPlugin.getWorkspace());
301: }
302:
303: /**
304: * Returns the currently entered container name. Null if the field is empty.
305: * Note that the container may not exist yet if the user entered a new
306: * container name in the field.
307: * @return IPath
308: */
309: public IPath getContainerFullPath() {
310: if (allowNewContainerName) {
311: String pathName = containerNameField.getText();
312: if (pathName == null || pathName.length() < 1) {
313: return null;
314: }
315: // The user may not have made this absolute so do it for them
316: return (new Path(pathName)).makeAbsolute();
317:
318: }
319: if (selectedContainer == null)
320: return null;
321: return selectedContainer.getFullPath();
322:
323: }
324:
325: /**
326: * Gives focus to one of the widgets in the group, as determined by the
327: * group.
328: */
329: public void setInitialFocus() {
330: if (allowNewContainerName) {
331: containerNameField.setFocus();
332: } else {
333: treeViewer.getTree().setFocus();
334: }
335: }
336:
337: /**
338: * Sets the selected existing container.
339: * @param container
340: */
341: public void setSelectedContainer(IContainer container) {
342: selectedContainer = container;
343:
344: // expand to and select the specified container
345: List itemsToExpand = new ArrayList();
346: IContainer parent = container.getParent();
347: while (parent != null) {
348: itemsToExpand.add(0, parent);
349: parent = parent.getParent();
350: }
351: treeViewer.setExpandedElements(itemsToExpand.toArray());
352: treeViewer.setSelection(new StructuredSelection(container),
353: true);
354: }
355: }
|