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: *******************************************************************************/package org.eclipse.jdt.internal.ui.dialogs;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.util.ArrayList;
014: import java.util.HashSet;
015:
016: import org.eclipse.core.runtime.CoreException;
017: import org.eclipse.core.runtime.IProgressMonitor;
018: import org.eclipse.core.runtime.NullProgressMonitor;
019: import org.eclipse.core.runtime.OperationCanceledException;
020: import org.eclipse.core.runtime.SubProgressMonitor;
021:
022: import org.eclipse.jdt.core.IJavaElement;
023: import org.eclipse.jdt.core.IPackageFragment;
024: import org.eclipse.jdt.core.IPackageFragmentRoot;
025: import org.eclipse.jdt.core.JavaModelException;
026: import org.eclipse.jdt.core.search.IJavaSearchConstants;
027: import org.eclipse.jdt.core.search.IJavaSearchScope;
028: import org.eclipse.jdt.core.search.SearchEngine;
029: import org.eclipse.jdt.core.search.SearchMatch;
030: import org.eclipse.jdt.core.search.SearchPattern;
031: import org.eclipse.jdt.core.search.SearchRequestor;
032:
033: import org.eclipse.swt.graphics.Point;
034: import org.eclipse.swt.graphics.Rectangle;
035: import org.eclipse.swt.widgets.Composite;
036: import org.eclipse.swt.widgets.Control;
037: import org.eclipse.swt.widgets.Shell;
038:
039: import org.eclipse.jface.dialogs.IDialogSettings;
040: import org.eclipse.jface.dialogs.MessageDialog;
041: import org.eclipse.jface.operation.IRunnableContext;
042: import org.eclipse.jface.operation.IRunnableWithProgress;
043: import org.eclipse.jface.viewers.ILabelProvider;
044:
045: import org.eclipse.ui.dialogs.ElementListSelectionDialog;
046: import org.eclipse.ui.PlatformUI;
047:
048: import org.eclipse.jdt.internal.corext.util.SearchUtils;
049:
050: import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
051: import org.eclipse.jdt.internal.ui.JavaPlugin;
052: import org.eclipse.jdt.internal.ui.JavaUIMessages;
053: import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
054:
055: import org.eclipse.jdt.ui.JavaElementLabelProvider;
056:
057: /**
058: * Dialog to browse for package fragments.
059: */
060: public class PackageSelectionDialog extends ElementListSelectionDialog {
061:
062: public static final int F_REMOVE_DUPLICATES = 1;
063: public static final int F_SHOW_PARENTS = 2;
064: public static final int F_HIDE_DEFAULT_PACKAGE = 4;
065: public static final int F_HIDE_EMPTY_INNER = 8;
066:
067: /** The dialog location. */
068: private Point fLocation;
069: /** The dialog size. */
070: private Point fSize;
071:
072: private IRunnableContext fContext;
073: private IJavaSearchScope fScope;
074: private int fFlags;
075:
076: /**
077: * Creates a package selection dialog.
078: * @param parent the parent shell
079: * @param context the runnable context to run the search in
080: * @param flags a combination of <code>F_REMOVE_DUPLICATES</code>, <code>F_SHOW_PARENTS</code>,
081: * <code>F_HIDE_DEFAULT_PACKAGE</code> and <code>F_HIDE_EMPTY_INNER</code>
082: * @param scope the scope defining the available packages.
083: */
084: public PackageSelectionDialog(Shell parent,
085: IRunnableContext context, int flags, IJavaSearchScope scope) {
086: super (parent, createLabelProvider(flags));
087: fFlags = flags;
088: fScope = scope;
089: fContext = context;
090: }
091:
092: private static ILabelProvider createLabelProvider(int dialogFlags) {
093: int flags = JavaElementLabelProvider.SHOW_DEFAULT;
094: if ((dialogFlags & F_REMOVE_DUPLICATES) == 0) {
095: flags = flags | JavaElementLabelProvider.SHOW_ROOT;
096: }
097: return new JavaElementLabelProvider(flags);
098: }
099:
100: /*
101: * @see org.eclipse.jface.window.Window#open()
102: */
103: public int open() {
104: final ArrayList packageList = new ArrayList();
105:
106: IRunnableWithProgress runnable = new IRunnableWithProgress() {
107: public void run(IProgressMonitor monitor)
108: throws InvocationTargetException,
109: InterruptedException {
110: if (monitor == null) {
111: monitor = new NullProgressMonitor();
112: }
113: boolean hideEmpty = (fFlags & F_HIDE_EMPTY_INNER) != 0;
114: monitor
115: .beginTask(
116: JavaUIMessages.PackageSelectionDialog_progress_search,
117: hideEmpty ? 2 : 1);
118: try {
119: SearchRequestor requestor = new SearchRequestor() {
120: private HashSet fSet = new HashSet();
121: private final boolean fAddDefault = (fFlags & F_HIDE_DEFAULT_PACKAGE) == 0;
122: private final boolean fDuplicates = (fFlags & F_REMOVE_DUPLICATES) == 0;
123: private final boolean fIncludeParents = (fFlags & F_SHOW_PARENTS) != 0;
124:
125: public void acceptSearchMatch(SearchMatch match)
126: throws CoreException {
127: IJavaElement enclosingElement = (IJavaElement) match
128: .getElement();
129: String name = enclosingElement
130: .getElementName();
131: if (fAddDefault || name.length() > 0) {
132: if (fDuplicates || fSet.add(name)) {
133: packageList.add(enclosingElement);
134: if (fIncludeParents) {
135: addParentPackages(
136: enclosingElement, name);
137: }
138: }
139: }
140: }
141:
142: private void addParentPackages(
143: IJavaElement enclosingElement,
144: String name) {
145: IPackageFragmentRoot root = (IPackageFragmentRoot) enclosingElement
146: .getParent();
147: int idx = name.lastIndexOf('.');
148: while (idx != -1) {
149: name = name.substring(0, idx);
150: if (fDuplicates || fSet.add(name)) {
151: packageList.add(root
152: .getPackageFragment(name));
153: }
154: idx = name.lastIndexOf('.');
155: }
156: }
157: };
158: SearchPattern pattern = SearchPattern
159: .createPattern(
160: "*", //$NON-NLS-1$
161: IJavaSearchConstants.PACKAGE,
162: IJavaSearchConstants.DECLARATIONS,
163: SearchPattern.R_PATTERN_MATCH
164: | SearchPattern.R_CASE_SENSITIVE);
165: new SearchEngine().search(pattern, SearchUtils
166: .getDefaultSearchParticipants(), fScope,
167: requestor, new SubProgressMonitor(monitor,
168: 1));
169:
170: if (monitor.isCanceled()) {
171: throw new InterruptedException();
172: }
173:
174: if (hideEmpty) {
175: removeEmptyPackages(new SubProgressMonitor(
176: monitor, 1));
177: }
178: } catch (CoreException e) {
179: throw new InvocationTargetException(e);
180: } catch (OperationCanceledException e) {
181: throw new InterruptedException();
182: } finally {
183: monitor.done();
184: }
185: }
186:
187: private void removeEmptyPackages(IProgressMonitor monitor)
188: throws JavaModelException, InterruptedException {
189: monitor
190: .beginTask(
191: JavaUIMessages.PackageSelectionDialog_progress_findEmpty,
192: packageList.size());
193: try {
194: ArrayList res = new ArrayList(packageList.size());
195: for (int i = 0; i < packageList.size(); i++) {
196: IPackageFragment pkg = (IPackageFragment) packageList
197: .get(i);
198: if (pkg.hasChildren() || !pkg.hasSubpackages()) {
199: res.add(pkg);
200: }
201: monitor.worked(1);
202: if (monitor.isCanceled()) {
203: throw new InterruptedException();
204: }
205: }
206: packageList.clear();
207: packageList.addAll(res);
208: } finally {
209: monitor.done();
210: }
211: }
212: };
213:
214: try {
215: fContext.run(true, true, runnable);
216: } catch (InvocationTargetException e) {
217: ExceptionHandler
218: .handle(
219: e,
220: JavaUIMessages.PackageSelectionDialog_error_title,
221: JavaUIMessages.PackageSelectionDialog_error3Message);
222: return CANCEL;
223: } catch (InterruptedException e) {
224: // cancelled by user
225: return CANCEL;
226: }
227:
228: if (packageList.isEmpty()) {
229: String title = JavaUIMessages.PackageSelectionDialog_nopackages_title;
230: String message = JavaUIMessages.PackageSelectionDialog_nopackages_message;
231: MessageDialog.openInformation(getShell(), title, message);
232: return CANCEL;
233: }
234:
235: setElements(packageList.toArray());
236:
237: return super .open();
238: }
239:
240: /*
241: * @see org.eclipse.jface.window.Window#configureShell(Shell)
242: */
243: protected void configureShell(Shell newShell) {
244: super .configureShell(newShell);
245: PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
246: IJavaHelpContextIds.OPEN_PACKAGE_DIALOG);
247: }
248:
249: /*
250: * @see Window#close()
251: */
252: public boolean close() {
253: writeSettings();
254: return super .close();
255: }
256:
257: /*
258: * @see org.eclipse.jface.window.Window#createContents(org.eclipse.swt.widgets.Composite)
259: */
260: protected Control createContents(Composite parent) {
261: Control control = super .createContents(parent);
262: readSettings();
263: return control;
264: }
265:
266: /* (non-Javadoc)
267: * @see org.eclipse.jface.window.Window#getInitialSize()
268: */
269: protected Point getInitialSize() {
270: Point result = super .getInitialSize();
271: if (fSize != null) {
272: result.x = Math.max(result.x, fSize.x);
273: result.y = Math.max(result.y, fSize.y);
274: Rectangle display = getShell().getDisplay().getClientArea();
275: result.x = Math.min(result.x, display.width);
276: result.y = Math.min(result.y, display.height);
277: }
278: return result;
279: }
280:
281: /* (non-Javadoc)
282: * @see org.eclipse.jface.window.Window#getInitialLocation(org.eclipse.swt.graphics.Point)
283: */
284: protected Point getInitialLocation(Point initialSize) {
285: Point result = super .getInitialLocation(initialSize);
286: if (fLocation != null) {
287: result.x = fLocation.x;
288: result.y = fLocation.y;
289: Rectangle display = getShell().getDisplay().getClientArea();
290: int xe = result.x + initialSize.x;
291: if (xe > display.width) {
292: result.x -= xe - display.width;
293: }
294: int ye = result.y + initialSize.y;
295: if (ye > display.height) {
296: result.y -= ye - display.height;
297: }
298: }
299: return result;
300: }
301:
302: /**
303: * Initializes itself from the dialog settings with the same state
304: * as at the previous invocation.
305: */
306: private void readSettings() {
307: IDialogSettings s = getDialogSettings();
308: try {
309: int x = s.getInt("x"); //$NON-NLS-1$
310: int y = s.getInt("y"); //$NON-NLS-1$
311: fLocation = new Point(x, y);
312: int width = s.getInt("width"); //$NON-NLS-1$
313: int height = s.getInt("height"); //$NON-NLS-1$
314: fSize = new Point(width, height);
315:
316: } catch (NumberFormatException e) {
317: fLocation = null;
318: fSize = null;
319: }
320: }
321:
322: /**
323: * Stores it current configuration in the dialog store.
324: */
325: private void writeSettings() {
326: IDialogSettings s = getDialogSettings();
327:
328: Point location = getShell().getLocation();
329: s.put("x", location.x); //$NON-NLS-1$
330: s.put("y", location.y); //$NON-NLS-1$
331:
332: Point size = getShell().getSize();
333: s.put("width", size.x); //$NON-NLS-1$
334: s.put("height", size.y); //$NON-NLS-1$
335: }
336:
337: /**
338: * Returns the dialog settings object used to share state
339: * between several find/replace dialogs.
340: *
341: * @return the dialog settings to be used
342: */
343: private IDialogSettings getDialogSettings() {
344: IDialogSettings settings = JavaPlugin.getDefault()
345: .getDialogSettings();
346: String sectionName = getClass().getName();
347: IDialogSettings subSettings = settings.getSection(sectionName);
348: if (subSettings == null)
349: subSettings = settings.addNewSection(sectionName);
350: return subSettings;
351: }
352:
353: }
|