001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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: *******************************************************************************/package org.eclipse.jdt.ui.wizards;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.net.URI;
014:
015: import org.eclipse.core.filesystem.EFS;
016: import org.eclipse.core.filesystem.IFileStore;
017:
018: import org.eclipse.core.runtime.CoreException;
019: import org.eclipse.core.runtime.IPath;
020: import org.eclipse.core.runtime.IProgressMonitor;
021: import org.eclipse.core.runtime.IStatus;
022: import org.eclipse.core.runtime.NullProgressMonitor;
023:
024: import org.eclipse.core.resources.IResource;
025:
026: import org.eclipse.swt.SWT;
027: import org.eclipse.swt.layout.GridData;
028: import org.eclipse.swt.layout.GridLayout;
029: import org.eclipse.swt.widgets.Composite;
030: import org.eclipse.swt.widgets.Label;
031: import org.eclipse.swt.widgets.Text;
032:
033: import org.eclipse.jface.dialogs.Dialog;
034: import org.eclipse.jface.operation.IRunnableWithProgress;
035: import org.eclipse.jface.viewers.IStructuredSelection;
036:
037: import org.eclipse.ui.PlatformUI;
038:
039: import org.eclipse.jdt.core.IJavaElement;
040: import org.eclipse.jdt.core.IJavaProject;
041: import org.eclipse.jdt.core.IPackageFragment;
042: import org.eclipse.jdt.core.IPackageFragmentRoot;
043: import org.eclipse.jdt.core.JavaConventions;
044: import org.eclipse.jdt.core.JavaCore;
045:
046: import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil;
047: import org.eclipse.jdt.internal.corext.util.Messages;
048:
049: import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
050: import org.eclipse.jdt.internal.ui.JavaPlugin;
051: import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
052: import org.eclipse.jdt.internal.ui.dialogs.TextFieldNavigationHandler;
053: import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
054: import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
055: import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
056: import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
057: import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
058:
059: /**
060: * Wizard page to create a new package.
061: *
062: * <p>
063: * Note: This class is not intended to be subclassed, but clients can instantiate.
064: * To implement a different kind of a new package wizard page, extend <code>NewContainerWizardPage</code>.
065: * </p>
066: *
067: * @since 2.0
068: */
069: public class NewPackageWizardPage extends NewContainerWizardPage {
070:
071: private static final String PAGE_NAME = "NewPackageWizardPage"; //$NON-NLS-1$
072:
073: private static final String PACKAGE = "NewPackageWizardPage.package"; //$NON-NLS-1$
074:
075: private StringDialogField fPackageDialogField;
076:
077: /*
078: * Status of last validation of the package field
079: */
080: private IStatus fPackageStatus;
081:
082: private IPackageFragment fCreatedPackageFragment;
083:
084: /**
085: * Creates a new <code>NewPackageWizardPage</code>
086: */
087: public NewPackageWizardPage() {
088: super (PAGE_NAME);
089:
090: setTitle(NewWizardMessages.NewPackageWizardPage_title);
091: setDescription(NewWizardMessages.NewPackageWizardPage_description);
092:
093: fCreatedPackageFragment = null;
094:
095: PackageFieldAdapter adapter = new PackageFieldAdapter();
096:
097: fPackageDialogField = new StringDialogField();
098: fPackageDialogField.setDialogFieldListener(adapter);
099: fPackageDialogField
100: .setLabelText(NewWizardMessages.NewPackageWizardPage_package_label);
101:
102: fPackageStatus = new StatusInfo();
103: }
104:
105: // -------- Initialization ---------
106:
107: /**
108: * The wizard owning this page is responsible for calling this method with the
109: * current selection. The selection is used to initialize the fields of the wizard
110: * page.
111: *
112: * @param selection used to initialize the fields
113: */
114: public void init(IStructuredSelection selection) {
115: IJavaElement jelem = getInitialJavaElement(selection);
116:
117: initContainerPage(jelem);
118: String pName = ""; //$NON-NLS-1$
119: if (jelem != null) {
120: IPackageFragment pf = (IPackageFragment) jelem
121: .getAncestor(IJavaElement.PACKAGE_FRAGMENT);
122: if (pf != null && !pf.isDefaultPackage())
123: pName = pf.getElementName();
124: }
125: setPackageText(pName, true);
126: updateStatus(new IStatus[] { fContainerStatus, fPackageStatus });
127: }
128:
129: // -------- UI Creation ---------
130:
131: /*
132: * @see WizardPage#createControl
133: */
134: public void createControl(Composite parent) {
135: initializeDialogUnits(parent);
136:
137: Composite composite = new Composite(parent, SWT.NONE);
138: composite.setFont(parent.getFont());
139: int nColumns = 3;
140:
141: GridLayout layout = new GridLayout();
142: layout.numColumns = 3;
143: composite.setLayout(layout);
144:
145: Label label = new Label(composite, SWT.WRAP);
146: label.setText(NewWizardMessages.NewPackageWizardPage_info);
147: GridData gd = new GridData();
148: gd.widthHint = convertWidthInCharsToPixels(60);
149: gd.horizontalSpan = 3;
150: label.setLayoutData(gd);
151:
152: createContainerControls(composite, nColumns);
153: createPackageControls(composite, nColumns);
154:
155: setControl(composite);
156: Dialog.applyDialogFont(composite);
157: PlatformUI.getWorkbench().getHelpSystem().setHelp(composite,
158: IJavaHelpContextIds.NEW_PACKAGE_WIZARD_PAGE);
159: }
160:
161: /**
162: * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
163: */
164: public void setVisible(boolean visible) {
165: super .setVisible(visible);
166: if (visible) {
167: setFocus();
168: }
169: }
170:
171: /**
172: * Sets the focus to the package name input field.
173: */
174: protected void setFocus() {
175: fPackageDialogField.setFocus();
176: }
177:
178: private void createPackageControls(Composite composite, int nColumns) {
179: fPackageDialogField.doFillIntoGrid(composite, nColumns - 1);
180: Text text = fPackageDialogField.getTextControl(null);
181: LayoutUtil.setWidthHint(text, getMaxFieldWidth());
182: LayoutUtil.setHorizontalGrabbing(text);
183: DialogField.createEmptySpace(composite);
184:
185: TextFieldNavigationHandler.install(text);
186: }
187:
188: // -------- PackageFieldAdapter --------
189:
190: private class PackageFieldAdapter implements IDialogFieldListener {
191:
192: // --------- IDialogFieldListener
193:
194: public void dialogFieldChanged(DialogField field) {
195: fPackageStatus = packageChanged();
196: // tell all others
197: handleFieldChanged(PACKAGE);
198: }
199: }
200:
201: // -------- update message ----------------
202:
203: /*
204: * @see org.eclipse.jdt.ui.wizards.NewContainerWizardPage#handleFieldChanged(String)
205: */
206: protected void handleFieldChanged(String fieldName) {
207: super .handleFieldChanged(fieldName);
208: if (fieldName == CONTAINER) {
209: fPackageStatus = packageChanged();
210: }
211: // do status line update
212: updateStatus(new IStatus[] { fContainerStatus, fPackageStatus });
213: }
214:
215: // ----------- validation ----------
216:
217: private IStatus validatePackageName(String text) {
218: IJavaProject project = getJavaProject();
219: if (project == null || !project.exists()) {
220: return JavaConventions.validatePackageName(text,
221: JavaCore.VERSION_1_3, JavaCore.VERSION_1_3);
222: }
223: return JavaConventionsUtil.validatePackageName(text, project);
224: }
225:
226: /*
227: * Verifies the input for the package field.
228: */
229: private IStatus packageChanged() {
230: StatusInfo status = new StatusInfo();
231: String packName = getPackageText();
232: if (packName.length() > 0) {
233: IStatus val = validatePackageName(packName);
234: if (val.getSeverity() == IStatus.ERROR) {
235: status
236: .setError(Messages
237: .format(
238: NewWizardMessages.NewPackageWizardPage_error_InvalidPackageName,
239: val.getMessage()));
240: return status;
241: } else if (val.getSeverity() == IStatus.WARNING) {
242: status
243: .setWarning(Messages
244: .format(
245: NewWizardMessages.NewPackageWizardPage_warning_DiscouragedPackageName,
246: val.getMessage()));
247: }
248: } else {
249: status
250: .setError(NewWizardMessages.NewPackageWizardPage_error_EnterName);
251: return status;
252: }
253:
254: IPackageFragmentRoot root = getPackageFragmentRoot();
255: if (root != null && root.getJavaProject().exists()) {
256: IPackageFragment pack = root.getPackageFragment(packName);
257: try {
258: IPath rootPath = root.getPath();
259: IPath outputPath = root.getJavaProject()
260: .getOutputLocation();
261: if (rootPath.isPrefixOf(outputPath)
262: && !rootPath.equals(outputPath)) {
263: // if the bin folder is inside of our root, don't allow to name a package
264: // like the bin folder
265: IPath packagePath = pack.getPath();
266: if (outputPath.isPrefixOf(packagePath)) {
267: status
268: .setError(NewWizardMessages.NewPackageWizardPage_error_IsOutputFolder);
269: return status;
270: }
271: }
272: if (pack.exists()) {
273: if (pack.containsJavaResources()
274: || !pack.hasSubpackages()) {
275: status
276: .setError(NewWizardMessages.NewPackageWizardPage_error_PackageExists);
277: } else {
278: status
279: .setError(NewWizardMessages.NewPackageWizardPage_error_PackageNotShown);
280: }
281: } else {
282: URI location = pack.getResource().getLocationURI();
283: if (location != null) {
284: IFileStore store = EFS.getStore(location);
285: if (store.fetchInfo().exists()) {
286: status
287: .setError(NewWizardMessages.NewPackageWizardPage_error_PackageExistsDifferentCase);
288: }
289: }
290: }
291: } catch (CoreException e) {
292: JavaPlugin.log(e);
293: }
294: }
295: return status;
296: }
297:
298: /**
299: * Returns the content of the package input field.
300: *
301: * @return the content of the package input field
302: */
303: public String getPackageText() {
304: return fPackageDialogField.getText();
305: }
306:
307: /**
308: * Sets the content of the package input field to the given value.
309: *
310: * @param str the new package input field text
311: * @param canBeModified if <code>true</code> the package input
312: * field can be modified; otherwise it is read-only.
313: */
314: public void setPackageText(String str, boolean canBeModified) {
315: fPackageDialogField.setText(str);
316:
317: fPackageDialogField.setEnabled(canBeModified);
318: }
319:
320: /**
321: * Returns the resource handle that corresponds to the element to was created or
322: * will be created.
323: * @return A resource or null if the page contains illegal values.
324: * @since 3.0
325: */
326: public IResource getModifiedResource() {
327: IPackageFragmentRoot root = getPackageFragmentRoot();
328: if (root != null) {
329: return root.getPackageFragment(getPackageText())
330: .getResource();
331: }
332: return null;
333: }
334:
335: // ---- creation ----------------
336:
337: /**
338: * Returns a runnable that creates a package using the current settings.
339: *
340: * @return the runnable that creates the new package
341: */
342: public IRunnableWithProgress getRunnable() {
343: return new IRunnableWithProgress() {
344: public void run(IProgressMonitor monitor)
345: throws InvocationTargetException,
346: InterruptedException {
347: try {
348: createPackage(monitor);
349: } catch (CoreException e) {
350: throw new InvocationTargetException(e);
351: }
352: }
353: };
354: }
355:
356: /**
357: * Returns the created package fragment. This method only returns a valid value
358: * after <code>getRunnable</code> or <code>createPackage</code> have been
359: * executed.
360: *
361: * @return the created package fragment
362: */
363: public IPackageFragment getNewPackageFragment() {
364: return fCreatedPackageFragment;
365: }
366:
367: /**
368: * Creates the new package using the entered field values.
369: *
370: * @param monitor a progress monitor to report progress. The progress
371: * monitor must not be <code>null</code>
372: * @throws CoreException Thrown if creating the package failed.
373: * @throws InterruptedException Thrown when the operation has been canceled.
374: * @since 2.1
375: */
376: public void createPackage(IProgressMonitor monitor)
377: throws CoreException, InterruptedException {
378: if (monitor == null) {
379: monitor = new NullProgressMonitor();
380: }
381:
382: IPackageFragmentRoot root = getPackageFragmentRoot();
383: String packName = getPackageText();
384: fCreatedPackageFragment = root.createPackageFragment(packName,
385: true, monitor);
386:
387: if (monitor.isCanceled()) {
388: throw new InterruptedException();
389: }
390: }
391: }
|