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: * Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
011: * font should be activated and used by other components.
012: *******************************************************************************/package org.eclipse.ui.dialogs;
013:
014: import java.lang.reflect.InvocationTargetException;
015: import java.net.URI;
016: import org.eclipse.core.resources.IContainer;
017: import org.eclipse.core.resources.IFolder;
018: import org.eclipse.core.resources.IProject;
019: import org.eclipse.core.resources.IProjectNatureDescriptor;
020: import org.eclipse.core.resources.IResource;
021: import org.eclipse.core.resources.IWorkspace;
022: import org.eclipse.core.resources.IWorkspaceRoot;
023: import org.eclipse.core.resources.ResourcesPlugin;
024: import org.eclipse.core.runtime.CoreException;
025: import org.eclipse.core.runtime.IPath;
026: import org.eclipse.core.runtime.IProgressMonitor;
027: import org.eclipse.core.runtime.IStatus;
028: import org.eclipse.core.runtime.OperationCanceledException;
029: import org.eclipse.core.runtime.Path;
030: import org.eclipse.core.runtime.Preferences;
031: import org.eclipse.core.runtime.Status;
032: import org.eclipse.jface.dialogs.ErrorDialog;
033: import org.eclipse.jface.dialogs.IDialogConstants;
034: import org.eclipse.jface.dialogs.MessageDialog;
035: import org.eclipse.osgi.util.NLS;
036: import org.eclipse.swt.SWT;
037: import org.eclipse.swt.events.SelectionAdapter;
038: import org.eclipse.swt.events.SelectionEvent;
039: import org.eclipse.swt.graphics.Font;
040: import org.eclipse.swt.graphics.Point;
041: import org.eclipse.swt.layout.GridData;
042: import org.eclipse.swt.layout.GridLayout;
043: import org.eclipse.swt.widgets.Button;
044: import org.eclipse.swt.widgets.Composite;
045: import org.eclipse.swt.widgets.Control;
046: import org.eclipse.swt.widgets.Event;
047: import org.eclipse.swt.widgets.Label;
048: import org.eclipse.swt.widgets.Listener;
049: import org.eclipse.swt.widgets.Shell;
050: import org.eclipse.swt.widgets.Text;
051: import org.eclipse.ui.PlatformUI;
052: import org.eclipse.ui.actions.WorkspaceModifyOperation;
053: import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
054: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
055: import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
056: import org.eclipse.ui.internal.ide.dialogs.CreateLinkedResourceGroup;
057:
058: /**
059: * The NewFolderDialog is used to create a new folder.
060: * The folder can optionally be linked to a file system folder.
061: * <p>
062: * This class may be instantiated; it is not intended to be subclassed.
063: * </p>
064: */
065: public class NewFolderDialog extends SelectionStatusDialog {
066: // widgets
067: private Text folderNameField;
068:
069: private Button advancedButton;
070:
071: private CreateLinkedResourceGroup linkedResourceGroup;
072:
073: private IContainer container;
074:
075: private boolean firstLinkCheck = true;
076:
077: /**
078: * Parent composite of the advanced widget group for creating
079: * linked resources.
080: */
081: private Composite linkedResourceParent;
082:
083: /**
084: * Linked resources widget group. Null if advanced section is not visible.
085: */
086: private Composite linkedResourceComposite;
087:
088: /**
089: * Height of the dialog without the "advanced" linked resource group.
090: * Set when the advanced group is first made visible.
091: */
092: private int basicShellHeight = -1;
093:
094: /**
095: * Creates a NewFolderDialog
096: *
097: * @param parentShell parent of the new dialog
098: * @param container parent of the new folder
099: */
100: public NewFolderDialog(Shell parentShell, IContainer container) {
101: super (parentShell);
102: this .container = container;
103: setTitle(IDEWorkbenchMessages.NewFolderDialog_title);
104: setStatusLineAboveButtons(true);
105: }
106:
107: /**
108: * Creates the folder using the name and link target entered
109: * by the user.
110: * Sets the dialog result to the created folder.
111: */
112: protected void computeResult() {
113: //Do nothing here as we
114: //need to know the result
115: }
116:
117: /* (non-Javadoc)
118: * Method declared in Window.
119: */
120: protected void configureShell(Shell shell) {
121: super .configureShell(shell);
122: PlatformUI.getWorkbench().getHelpSystem().setHelp(shell,
123: IIDEHelpContextIds.NEW_FOLDER_DIALOG);
124: }
125:
126: /**
127: * @see org.eclipse.jface.window.Window#create()
128: */
129: public void create() {
130: super .create();
131: // initially disable the ok button since we don't preset the
132: // folder name field
133: getButton(IDialogConstants.OK_ID).setEnabled(false);
134: }
135:
136: /**
137: * Creates the widget for advanced options.
138: *
139: * @param parent the parent composite
140: */
141: protected void createAdvancedControls(Composite parent) {
142: Preferences preferences = ResourcesPlugin.getPlugin()
143: .getPluginPreferences();
144:
145: if (preferences
146: .getBoolean(ResourcesPlugin.PREF_DISABLE_LINKING) == false
147: && isValidContainer()) {
148: linkedResourceParent = new Composite(parent, SWT.NONE);
149: linkedResourceParent.setFont(parent.getFont());
150: linkedResourceParent.setLayoutData(new GridData(
151: GridData.FILL_HORIZONTAL));
152: GridLayout layout = new GridLayout();
153: layout.marginHeight = 0;
154: layout.marginWidth = 0;
155: linkedResourceParent.setLayout(layout);
156:
157: advancedButton = new Button(linkedResourceParent, SWT.PUSH);
158: advancedButton.setFont(linkedResourceParent.getFont());
159: advancedButton.setText(IDEWorkbenchMessages.showAdvanced);
160: setButtonLayoutData(advancedButton);
161: GridData data = (GridData) advancedButton.getLayoutData();
162: data.horizontalAlignment = GridData.BEGINNING;
163: advancedButton.setLayoutData(data);
164: advancedButton.addSelectionListener(new SelectionAdapter() {
165: public void widgetSelected(SelectionEvent e) {
166: handleAdvancedButtonSelect();
167: }
168: });
169: }
170: linkedResourceGroup = new CreateLinkedResourceGroup(
171: IResource.FOLDER, new Listener() {
172: public void handleEvent(Event e) {
173: validateLinkedResource();
174: firstLinkCheck = false;
175: }
176: }, new CreateLinkedResourceGroup.IStringValue() {
177: public void setValue(String string) {
178: folderNameField.setText(string);
179: }
180:
181: public String getValue() {
182: return folderNameField.getText();
183: }
184: });
185: }
186:
187: /* (non-Javadoc)
188: * Method declared on Dialog.
189: */
190: protected Control createDialogArea(Composite parent) {
191: Composite composite = (Composite) super
192: .createDialogArea(parent);
193: composite.setLayout(new GridLayout());
194: composite.setLayoutData(new GridData(GridData.FILL_BOTH));
195:
196: createFolderNameGroup(composite);
197: createAdvancedControls(composite);
198: return composite;
199: }
200:
201: /**
202: * Creates the folder name specification controls.
203: *
204: * @param parent the parent composite
205: */
206: private void createFolderNameGroup(Composite parent) {
207: Font font = parent.getFont();
208: // project specification group
209: Composite folderGroup = new Composite(parent, SWT.NONE);
210: GridLayout layout = new GridLayout();
211: layout.numColumns = 2;
212: folderGroup.setLayout(layout);
213: folderGroup
214: .setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
215:
216: // new folder label
217: Label folderLabel = new Label(folderGroup, SWT.NONE);
218: folderLabel.setFont(font);
219: folderLabel
220: .setText(IDEWorkbenchMessages.NewFolderDialog_nameLabel);
221:
222: // new folder name entry field
223: folderNameField = new Text(folderGroup, SWT.BORDER);
224: GridData data = new GridData(GridData.FILL_HORIZONTAL);
225: data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
226: folderNameField.setLayoutData(data);
227: folderNameField.setFont(font);
228: folderNameField.addListener(SWT.Modify, new Listener() {
229: public void handleEvent(Event event) {
230: validateLinkedResource();
231: }
232: });
233: }
234:
235: /**
236: * Creates a folder resource handle for the folder with the given name.
237: * The folder handle is created relative to the container specified during
238: * object creation.
239: *
240: * @param folderName the name of the folder resource to create a handle for
241: * @return the new folder resource handle
242: */
243: private IFolder createFolderHandle(String folderName) {
244: IWorkspaceRoot workspaceRoot = container.getWorkspace()
245: .getRoot();
246: IPath folderPath = container.getFullPath().append(folderName);
247: IFolder folderHandle = workspaceRoot.getFolder(folderPath);
248:
249: return folderHandle;
250: }
251:
252: /**
253: * Creates a new folder with the given name and optionally linking to
254: * the specified link target.
255: *
256: * @param folderName name of the new folder
257: * @param linkTarget name of the link target folder. may be null.
258: * @return IFolder the new folder
259: */
260: private IFolder createNewFolder(String folderName,
261: final URI linkTarget) {
262: final IFolder folderHandle = createFolderHandle(folderName);
263:
264: WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
265: public void execute(IProgressMonitor monitor)
266: throws CoreException {
267: try {
268: monitor
269: .beginTask(
270: IDEWorkbenchMessages.NewFolderDialog_progress,
271: 2000);
272: if (monitor.isCanceled()) {
273: throw new OperationCanceledException();
274: }
275: if (linkTarget == null) {
276: folderHandle.create(false, true, monitor);
277: } else {
278: folderHandle.createLink(linkTarget,
279: IResource.ALLOW_MISSING_LOCAL, monitor);
280: }
281: if (monitor.isCanceled()) {
282: throw new OperationCanceledException();
283: }
284: } finally {
285: monitor.done();
286: }
287: }
288: };
289: try {
290: PlatformUI.getWorkbench().getProgressService()
291: .busyCursorWhile(operation);
292: } catch (InterruptedException exception) {
293: return null;
294: } catch (InvocationTargetException exception) {
295: if (exception.getTargetException() instanceof CoreException) {
296: ErrorDialog
297: .openError(
298: getShell(),
299: IDEWorkbenchMessages.NewFolderDialog_errorTitle,
300: null, // no special message
301: ((CoreException) exception
302: .getTargetException())
303: .getStatus());
304: } else {
305: // CoreExceptions are handled above, but unexpected runtime exceptions and errors may still occur.
306: IDEWorkbenchPlugin
307: .log(
308: getClass(),
309: "createNewFolder", exception.getTargetException()); //$NON-NLS-1$
310: MessageDialog
311: .openError(
312: getShell(),
313: IDEWorkbenchMessages.NewFolderDialog_errorTitle,
314: NLS
315: .bind(
316: IDEWorkbenchMessages.NewFolderDialog_internalError,
317: exception
318: .getTargetException()
319: .getMessage()));
320: }
321: return null;
322: }
323: return folderHandle;
324: }
325:
326: /**
327: * Shows/hides the advanced option widgets.
328: */
329: protected void handleAdvancedButtonSelect() {
330: Shell shell = getShell();
331: Point shellSize = shell.getSize();
332: Composite composite = (Composite) getDialogArea();
333:
334: if (linkedResourceComposite != null) {
335: linkedResourceComposite.dispose();
336: linkedResourceComposite = null;
337: composite.layout();
338: shell.setSize(shellSize.x, basicShellHeight);
339: advancedButton.setText(IDEWorkbenchMessages.showAdvanced);
340: } else {
341: if (basicShellHeight == -1) {
342: basicShellHeight = shell.computeSize(SWT.DEFAULT,
343: SWT.DEFAULT, true).y;
344: }
345: linkedResourceComposite = linkedResourceGroup
346: .createContents(linkedResourceParent);
347: shellSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT,
348: true);
349: shell.setSize(shellSize);
350: composite.layout();
351: advancedButton.setText(IDEWorkbenchMessages.hideAdvanced);
352: }
353: }
354:
355: /**
356: * Returns whether the container specified in the constructor is
357: * a valid parent for creating linked resources.
358: *
359: * @return boolean <code>true</code> if the container specified in
360: * the constructor is a valid parent for creating linked resources.
361: * <code>false</code> if no linked resources may be created with the
362: * specified container as a parent.
363: */
364: private boolean isValidContainer() {
365: if (container.getType() != IResource.PROJECT
366: && container.getType() != IResource.FOLDER) {
367: return false;
368: }
369:
370: try {
371: IWorkspace workspace = IDEWorkbenchPlugin
372: .getPluginWorkspace();
373: IProject project = container.getProject();
374: String[] natureIds = project.getDescription()
375: .getNatureIds();
376:
377: for (int i = 0; i < natureIds.length; i++) {
378: IProjectNatureDescriptor descriptor = workspace
379: .getNatureDescriptor(natureIds[i]);
380: if (descriptor != null
381: && descriptor.isLinkingAllowed() == false) {
382: return false;
383: }
384: }
385: } catch (CoreException exception) {
386: // project does not exist or is closed
387: return false;
388: }
389: return true;
390: }
391:
392: /**
393: * Update the dialog's status line to reflect the given status. It is safe to call
394: * this method before the dialog has been opened.
395: */
396: protected void updateStatus(IStatus status) {
397: if (firstLinkCheck && status != null) {
398: // don't show the first validation result as an error.
399: // fixes bug 29659
400: Status newStatus = new Status(IStatus.OK, status
401: .getPlugin(), status.getCode(),
402: status.getMessage(), status.getException());
403: super .updateStatus(newStatus);
404: } else {
405: super .updateStatus(status);
406: }
407: }
408:
409: /**
410: * Update the dialog's status line to reflect the given status. It is safe to call
411: * this method before the dialog has been opened.
412: * @param severity
413: * @param message
414: */
415: private void updateStatus(int severity, String message) {
416: updateStatus(new Status(severity,
417: IDEWorkbenchPlugin.IDE_WORKBENCH, severity, message,
418: null));
419: }
420:
421: /**
422: * Checks whether the folder name and link location are valid.
423: * Disable the OK button if the folder name and link location are valid.
424: * a message that indicates the problem otherwise.
425: */
426: private void validateLinkedResource() {
427: boolean valid = validateFolderName();
428:
429: if (valid) {
430: IFolder linkHandle = createFolderHandle(folderNameField
431: .getText());
432: IStatus status = linkedResourceGroup
433: .validateLinkLocation(linkHandle);
434:
435: if (status.getSeverity() != IStatus.ERROR) {
436: getOkButton().setEnabled(true);
437: } else {
438: getOkButton().setEnabled(false);
439: }
440:
441: if (status.isOK() == false) {
442: updateStatus(status);
443: }
444: } else {
445: getOkButton().setEnabled(false);
446: }
447: }
448:
449: /**
450: * Checks if the folder name is valid.
451: *
452: * @return null if the new folder name is valid.
453: * a message that indicates the problem otherwise.
454: */
455: private boolean validateFolderName() {
456: String name = folderNameField.getText();
457: IWorkspace workspace = container.getWorkspace();
458: IStatus nameStatus = workspace.validateName(name,
459: IResource.FOLDER);
460:
461: if ("".equals(name)) { //$NON-NLS-1$
462: updateStatus(
463: IStatus.ERROR,
464: IDEWorkbenchMessages.NewFolderDialog_folderNameEmpty);
465: return false;
466: }
467: if (nameStatus.isOK() == false) {
468: updateStatus(nameStatus);
469: return false;
470: }
471: IPath path = new Path(name);
472: if (container.getFolder(path).exists()
473: || container.getFile(path).exists()) {
474: updateStatus(IStatus.ERROR, NLS.bind(
475: IDEWorkbenchMessages.NewFolderDialog_alreadyExists,
476: name));
477: return false;
478: }
479: updateStatus(IStatus.OK, ""); //$NON-NLS-1$
480: return true;
481: }
482:
483: /* (non-Javadoc)
484: * @see org.eclipse.ui.dialogs.SelectionStatusDialog#okPressed()
485: */
486: protected void okPressed() {
487: URI linkTarget = linkedResourceGroup.getLinkTargetURI();
488: IFolder folder = createNewFolder(folderNameField.getText(),
489: linkTarget);
490: if (folder == null) {
491: return;
492: }
493:
494: setSelectionResult(new IFolder[] { folder });
495:
496: super.okPressed();
497: }
498: }
|