0001: /*******************************************************************************
0002: * Copyright (c) 2003, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.ide;
0011:
0012: import java.net.URI;
0013: import java.util.ArrayList;
0014: import java.util.Collections;
0015: import java.util.Iterator;
0016: import java.util.List;
0017:
0018: import org.eclipse.osgi.util.NLS;
0019:
0020: import org.eclipse.swt.widgets.Composite;
0021: import org.eclipse.swt.widgets.Shell;
0022:
0023: import org.eclipse.core.filesystem.EFS;
0024: import org.eclipse.core.filesystem.IFileStore;
0025:
0026: import org.eclipse.core.runtime.CoreException;
0027: import org.eclipse.core.runtime.IAdaptable;
0028: import org.eclipse.core.runtime.IStatus;
0029: import org.eclipse.core.runtime.MultiStatus;
0030: import org.eclipse.core.runtime.Platform;
0031: import org.eclipse.core.runtime.QualifiedName;
0032: import org.eclipse.core.runtime.SafeRunner;
0033: import org.eclipse.core.runtime.content.IContentDescription;
0034: import org.eclipse.core.runtime.content.IContentType;
0035: import org.eclipse.core.runtime.content.IContentTypeMatcher;
0036:
0037: import org.eclipse.core.resources.IFile;
0038: import org.eclipse.core.resources.IMarker;
0039: import org.eclipse.core.resources.IResource;
0040: import org.eclipse.core.resources.IResourceDelta;
0041: import org.eclipse.core.resources.IWorkspaceRoot;
0042: import org.eclipse.core.resources.ResourcesPlugin;
0043: import org.eclipse.core.resources.mapping.IModelProviderDescriptor;
0044: import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
0045: import org.eclipse.core.resources.mapping.ModelProvider;
0046: import org.eclipse.core.resources.mapping.ModelStatus;
0047: import org.eclipse.core.resources.mapping.ResourceChangeValidator;
0048: import org.eclipse.core.resources.mapping.ResourceMapping;
0049: import org.eclipse.core.resources.mapping.ResourceMappingContext;
0050: import org.eclipse.core.resources.mapping.ResourceTraversal;
0051:
0052: import org.eclipse.jface.dialogs.ErrorDialog;
0053: import org.eclipse.jface.dialogs.IDialogConstants;
0054: import org.eclipse.jface.util.SafeRunnable;
0055: import org.eclipse.jface.viewers.IStructuredSelection;
0056:
0057: import org.eclipse.ui.IEditorDescriptor;
0058: import org.eclipse.ui.IEditorInput;
0059: import org.eclipse.ui.IEditorPart;
0060: import org.eclipse.ui.IEditorRegistry;
0061: import org.eclipse.ui.IMarkerHelpRegistry;
0062: import org.eclipse.ui.ISaveableFilter;
0063: import org.eclipse.ui.IWorkbenchPage;
0064: import org.eclipse.ui.IWorkbenchPart;
0065: import org.eclipse.ui.IWorkbenchWindow;
0066: import org.eclipse.ui.PartInitException;
0067: import org.eclipse.ui.PlatformUI;
0068: import org.eclipse.ui.Saveable;
0069: import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
0070: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
0071: import org.eclipse.ui.internal.ide.registry.MarkerHelpRegistry;
0072: import org.eclipse.ui.internal.ide.registry.MarkerHelpRegistryReader;
0073: import org.eclipse.ui.internal.misc.UIStats;
0074: import org.eclipse.ui.part.FileEditorInput;
0075:
0076: /**
0077: * Collection of IDE-specific APIs factored out of existing workbench. This
0078: * class cannot be instantiated; all functionality is provided by static methods
0079: * and fields.
0080: *
0081: * @since 3.0
0082: */
0083: public final class IDE {
0084: /**
0085: * The persistent property key used on IFile resources to contain the
0086: * preferred editor ID to use.
0087: * <p>
0088: * Example of retrieving the persisted editor id:
0089: *
0090: * <pre><code>
0091: * IFile file = ...
0092: * IEditorDescriptor editorDesc = null;
0093: * try {
0094: * String editorID = file.getPersistentProperty(EDITOR_KEY);
0095: * if (editorID != null) {
0096: * editorDesc = editorReg.findEditor(editorID);
0097: * }
0098: * } catch (CoreException e) {
0099: * // handle problem accessing persistent property here
0100: * }
0101: * </code></pre>
0102: *
0103: * </p>
0104: * <p>
0105: * Example of persisting the editor id:
0106: *
0107: * <pre><code>
0108: * IFile file = ...
0109: * try {
0110: * file.setPersistentProperty(EDITOR_KEY, editorDesc.getId());
0111: * } catch (CoreException e) {
0112: * // handle problem setting persistent property here
0113: * }
0114: * </code></pre>
0115: *
0116: * </p>
0117: */
0118: public static final QualifiedName EDITOR_KEY = new QualifiedName(
0119: "org.eclipse.ui.internal.registry.ResourceEditorRegistry", "EditorProperty");//$NON-NLS-2$//$NON-NLS-1$
0120:
0121: /**
0122: * An optional attribute within a workspace marker (<code>IMarker</code>)
0123: * which identifies the preferred editor type to be opened.
0124: */
0125: public static final String EDITOR_ID_ATTR = "org.eclipse.ui.editorID"; //$NON-NLS-1$
0126:
0127: /**
0128: * The resource based perspective identifier.
0129: */
0130: public static final String RESOURCE_PERSPECTIVE_ID = "org.eclipse.ui.resourcePerspective"; //$NON-NLS-1$
0131:
0132: /**
0133: * Marker help registry mapping markers to help context ids and resolutions;
0134: * lazily initialized on fist access.
0135: */
0136: private static MarkerHelpRegistry markerHelpRegistry = null;
0137:
0138: /**
0139: * Standard shared images defined by the IDE. These are over and above the
0140: * standard workbench images declared in {@link org.eclipse.ui.ISharedImages
0141: * ISharedImages}.
0142: * <p>
0143: * This interface is not intended to be implemented by clients.
0144: * </p>
0145: *
0146: * @see org.eclipse.ui.ISharedImages
0147: */
0148: public interface SharedImages {
0149: /**
0150: * Identifies a project image.
0151: */
0152: public final static String IMG_OBJ_PROJECT = "IMG_OBJ_PROJECT"; //$NON-NLS-1$
0153:
0154: /**
0155: * Identifies a closed project image.
0156: */
0157: public final static String IMG_OBJ_PROJECT_CLOSED = "IMG_OBJ_PROJECT_CLOSED"; //$NON-NLS-1$
0158:
0159: /**
0160: * Identifies the image used for "open marker".
0161: */
0162: public final static String IMG_OPEN_MARKER = "IMG_OPEN_MARKER"; //$NON-NLS-1$
0163:
0164: /**
0165: * Identifies the default image used to indicate a task.
0166: */
0167: public final static String IMG_OBJS_TASK_TSK = "IMG_OBJS_TASK_TSK"; //$NON-NLS-1$
0168:
0169: /**
0170: * Identifies the default image used to indicate a bookmark.
0171: */
0172: public final static String IMG_OBJS_BKMRK_TSK = "IMG_OBJS_BKMRK_TSK"; //$NON-NLS-1$
0173: }
0174:
0175: /**
0176: * Preferences defined by the IDE workbench.
0177: * <p>
0178: * This interface is not intended to be implemented by clients.
0179: * </p>
0180: */
0181: public interface Preferences {
0182:
0183: /**
0184: * A named preference for how a new perspective should be opened when a
0185: * new project is created.
0186: * <p>
0187: * Value is of type <code>String</code>. The possible values are
0188: * defined by the constants
0189: * <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE,
0190: * OPEN_PERSPECTIVE_REPLACE, and NO_NEW_PERSPECTIVE</code>.
0191: * </p>
0192: *
0193: * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_WINDOW
0194: * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_PAGE
0195: * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_REPLACE
0196: * @see org.eclipse.ui.IWorkbenchPreferenceConstants#NO_NEW_PERSPECTIVE
0197: */
0198: public static final String PROJECT_OPEN_NEW_PERSPECTIVE = "PROJECT_OPEN_NEW_PERSPECTIVE"; //$NON-NLS-1$
0199:
0200: /**
0201: * <p>
0202: * Specifies whether or not the workspace selection dialog should be
0203: * shown on startup.
0204: * </p>
0205: * <p>
0206: * The default value for this preference is <code>true</code>.
0207: * </p>
0208: *
0209: * @since 3.1
0210: */
0211: public static final String SHOW_WORKSPACE_SELECTION_DIALOG = "SHOW_WORKSPACE_SELECTION_DIALOG"; //$NON-NLS-1$
0212:
0213: /**
0214: * <p>
0215: * Stores the maximum number of workspaces that should be displayed in
0216: * the ChooseWorkspaceDialog.
0217: * </p>
0218: *
0219: * @since 3.1
0220: */
0221: public static final String MAX_RECENT_WORKSPACES = "MAX_RECENT_WORKSPACES"; //$NON-NLS-1$
0222:
0223: /**
0224: * <p>
0225: * Stores a comma separated list of the recently used workspace paths.
0226: * </p>
0227: *
0228: * @since 3.1
0229: */
0230: public static final String RECENT_WORKSPACES = "RECENT_WORKSPACES"; //$NON-NLS-1$
0231:
0232: /**
0233: * <p>
0234: * Stores the version of the protocol used to decode/encode the list of
0235: * recent workspaces.
0236: * </p>
0237: *
0238: * @since 3.1
0239: */
0240: public static final String RECENT_WORKSPACES_PROTOCOL = "RECENT_WORKSPACES_PROTOCOL"; //$NON-NLS-1$
0241:
0242: }
0243:
0244: /**
0245: * A saveable filter that selects savables that contain resources that
0246: * are descendants of the roots of the filter.
0247: * @since 3.3
0248: *
0249: */
0250: private static class SaveFilter implements ISaveableFilter {
0251: private final IResource[] roots;
0252:
0253: /**
0254: * Create the filter
0255: * @param roots the save roots
0256: */
0257: public SaveFilter(IResource[] roots) {
0258: this .roots = roots;
0259: }
0260:
0261: /* (non-Javadoc)
0262: * @see org.eclipse.ui.ISaveableFilter#select(org.eclipse.ui.Saveable, org.eclipse.ui.IWorkbenchPart[])
0263: */
0264: public boolean select(Saveable saveable,
0265: IWorkbenchPart[] containingParts) {
0266: if (isDescendantOfRoots(saveable)) {
0267: return true;
0268: }
0269: // For backwards compatibility, we need to check the parts
0270: for (int i = 0; i < containingParts.length; i++) {
0271: IWorkbenchPart workbenchPart = containingParts[i];
0272: if (workbenchPart instanceof IEditorPart) {
0273: IEditorPart editorPart = (IEditorPart) workbenchPart;
0274: if (isEditingDescendantOf(editorPart)) {
0275: return true;
0276: }
0277: }
0278: }
0279: return false;
0280: }
0281:
0282: /**
0283: * Return whether the given saveable contains any resources that
0284: * are descendants of the root resources.
0285: * @param saveable the saveable
0286: * @return whether the given saveable contains any resources that
0287: * are descendants of the root resources
0288: */
0289: private boolean isDescendantOfRoots(Saveable saveable) {
0290: // First, try and adapt the saveable to a resource mapping.
0291: ResourceMapping mapping = ResourceUtil
0292: .getResourceMapping(saveable);
0293: if (mapping != null) {
0294: try {
0295: ResourceTraversal[] traversals = mapping
0296: .getTraversals(
0297: ResourceMappingContext.LOCAL_CONTEXT,
0298: null);
0299: for (int i = 0; i < traversals.length; i++) {
0300: ResourceTraversal traversal = traversals[i];
0301: IResource[] resources = traversal
0302: .getResources();
0303: for (int j = 0; j < resources.length; j++) {
0304: IResource resource = resources[j];
0305: if (isDescendantOfRoots(resource)) {
0306: return true;
0307: }
0308: }
0309: }
0310: } catch (CoreException e) {
0311: IDEWorkbenchPlugin
0312: .log(
0313: NLS
0314: .bind(
0315: "An internal error occurred while determining the resources for {0}", saveable.getName()), e); //$NON-NLS-1$
0316: }
0317: } else {
0318: // If there is no mapping, try to adapt to a resource or file directly
0319: IFile file = ResourceUtil.getFile(saveable);
0320: if (file != null) {
0321: return isDescendantOfRoots(file);
0322: }
0323: }
0324: return false;
0325: }
0326:
0327: /**
0328: * Return whether the given resource is either equal to or a descendant of
0329: * one of the given roots.
0330: *
0331: * @param roots the root resources
0332: * @param resource the resource to be tested
0333: * @return whether the given resource is either equal to or a descendant of
0334: * one of the given roots
0335: */
0336: private boolean isDescendantOfRoots(IResource resource) {
0337: for (int l = 0; l < roots.length; l++) {
0338: IResource root = roots[l];
0339: if (root.getFullPath().isPrefixOf(
0340: resource.getFullPath())) {
0341: return true;
0342: }
0343: }
0344: return false;
0345: }
0346:
0347: /**
0348: * Return whether the given dirty editor part is editing resources that are
0349: * descendants of the given roots.
0350: *
0351: * @param roots the root resources
0352: * @param part the dirty editor part
0353: * @return whether the given dirty editor part is editing resources that are
0354: * descendants of the given roots
0355: */
0356: private boolean isEditingDescendantOf(IEditorPart part) {
0357: IFile file = ResourceUtil.getFile(part.getEditorInput());
0358: if (file != null) {
0359: return isDescendantOfRoots(file);
0360: }
0361: return false;
0362: }
0363:
0364: }
0365:
0366: /**
0367: * Block instantiation.
0368: */
0369: private IDE() {
0370: // do nothing
0371: }
0372:
0373: /**
0374: * Returns the marker help registry for the workbench.
0375: *
0376: * @return the marker help registry
0377: */
0378: public static IMarkerHelpRegistry getMarkerHelpRegistry() {
0379: if (markerHelpRegistry == null) {
0380: markerHelpRegistry = new MarkerHelpRegistry();
0381: new MarkerHelpRegistryReader().addHelp(markerHelpRegistry);
0382: }
0383: return markerHelpRegistry;
0384: }
0385:
0386: /**
0387: * Sets the cursor and selection state for the given editor to reveal the
0388: * position of the given marker. This is done on a best effort basis. If the
0389: * editor does not provide an <code>IGotoMarker</code> interface (either
0390: * directly or via <code>IAdaptable.getAdapter</code>), this has no
0391: * effect.
0392: *
0393: * @param editor
0394: * the editor
0395: * @param marker
0396: * the marker
0397: */
0398: public static void gotoMarker(IEditorPart editor, IMarker marker) {
0399: IGotoMarker gotoMarker = null;
0400: if (editor instanceof IGotoMarker) {
0401: gotoMarker = (IGotoMarker) editor;
0402: } else {
0403: gotoMarker = (IGotoMarker) editor
0404: .getAdapter(IGotoMarker.class);
0405: }
0406: if (gotoMarker != null) {
0407: gotoMarker.gotoMarker(marker);
0408: }
0409: }
0410:
0411: /**
0412: * Opens an editor on the given object.
0413: * <p>
0414: * If the page already has an editor open on the target object then that
0415: * editor is brought to front; otherwise, a new editor is opened.
0416: * <p>
0417: *
0418: * @param page
0419: * the page in which the editor will be opened
0420: * @param input
0421: * the editor input
0422: * @param editorId
0423: * the id of the editor extension to use
0424: * @return an open editor or <code>null</code> if an external editor was
0425: * opened
0426: * @exception PartInitException
0427: * if the editor could not be initialized
0428: * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
0429: */
0430: public static IEditorPart openEditor(IWorkbenchPage page,
0431: IEditorInput input, String editorId)
0432: throws PartInitException {
0433: // sanity checks
0434: if (page == null) {
0435: throw new IllegalArgumentException();
0436: }
0437:
0438: // open the editor on the file
0439: return page.openEditor(input, editorId);
0440: }
0441:
0442: /**
0443: * Opens an editor on the given IFileStore object.
0444: * <p>
0445: * Unlike the other <code>openEditor</code> methods, this one can be used
0446: * to open files that reside outside the workspace resource set.
0447: * </p>
0448: * <p>
0449: * If the page already has an editor open on the target object then that
0450: * editor is brought to front; otherwise, a new editor is opened.
0451: * </p>
0452: *
0453: * @param page
0454: * the page in which the editor will be opened
0455: * @param uri
0456: * the URI of the file store representing the file to open
0457: * @param editorId
0458: * the id of the editor extension to use
0459: * @param activate
0460: * if <code>true</code> the editor will be activated opened
0461: * @return an open editor or <code>null</code> if an external editor was
0462: * @exception PartInitException
0463: * if the editor could not be initialized
0464: *
0465: * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
0466: * @see EFS#getStore(URI)
0467: *
0468: * @since 3.3
0469: */
0470: public static IEditorPart openEditor(IWorkbenchPage page, URI uri,
0471: String editorId, boolean activate) throws PartInitException {
0472: // sanity checks
0473: if (page == null) {
0474: throw new IllegalArgumentException();
0475: }
0476:
0477: IFileStore fileStore;
0478: try {
0479: fileStore = EFS.getStore(uri);
0480: } catch (CoreException e) {
0481: throw new PartInitException(
0482: IDEWorkbenchMessages.IDE_coreExceptionFileStore, e);
0483: }
0484:
0485: IEditorInput input = getEditorInput(fileStore);
0486:
0487: // open the editor on the file
0488: return page.openEditor(input, editorId, activate);
0489: }
0490:
0491: /**
0492: * Create the Editor Input appropriate for the given <code>IFileStore</code>.
0493: * The result is a normal file editor input if the file exists in the
0494: * workspace and, if not, we create a wrapper capable of managing an
0495: * 'external' file using its <code>IFileStore</code>.
0496: *
0497: * @param fileStore
0498: * The file store to provide the editor input for
0499: * @return The editor input associated with the given file store
0500: */
0501: private static IEditorInput getEditorInput(IFileStore fileStore) {
0502: IFile workspaceFile = getWorkspaceFile(fileStore);
0503: if (workspaceFile != null)
0504: return new FileEditorInput(workspaceFile);
0505: return new FileStoreEditorInput(fileStore);
0506: }
0507:
0508: /**
0509: * Determine whether or not the <code>IFileStore</code> represents a file
0510: * currently in the workspace.
0511: *
0512: * @param fileStore
0513: * The <code>IFileStore</code> to test
0514: * @return The workspace's <code>IFile</code> if it exists or
0515: * <code>null</code> if not
0516: */
0517: private static IFile getWorkspaceFile(IFileStore fileStore) {
0518: IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
0519: IFile[] files = root.findFilesForLocationURI(fileStore.toURI());
0520: files = filterNonExistentFiles(files);
0521: if (files == null || files.length == 0)
0522: return null;
0523:
0524: // for now only return the first file
0525: return files[0];
0526: }
0527:
0528: /**
0529: * Filter the incoming array of <code>IFile</code> elements by removing
0530: * any that do not currently exist in the workspace.
0531: *
0532: * @param files
0533: * The array of <code>IFile</code> elements
0534: * @return The filtered array
0535: */
0536: private static IFile[] filterNonExistentFiles(IFile[] files) {
0537: if (files == null)
0538: return null;
0539:
0540: int length = files.length;
0541: ArrayList existentFiles = new ArrayList(length);
0542: for (int i = 0; i < length; i++) {
0543: if (files[i].exists())
0544: existentFiles.add(files[i]);
0545: }
0546: return (IFile[]) existentFiles.toArray(new IFile[existentFiles
0547: .size()]);
0548: }
0549:
0550: /**
0551: * Opens an editor on the given object.
0552: * <p>
0553: * If the page already has an editor open on the target object then that
0554: * editor is brought to front; otherwise, a new editor is opened. If
0555: * <code>activate == true</code> the editor will be activated.
0556: * <p>
0557: *
0558: * @param page
0559: * the page in which the editor will be opened
0560: * @param input
0561: * the editor input
0562: * @param editorId
0563: * the id of the editor extension to use
0564: * @param activate
0565: * if <code>true</code> the editor will be activated
0566: * @return an open editor or <code>null</code> if an external editor was
0567: * opened
0568: * @exception PartInitException
0569: * if the editor could not be initialized
0570: * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String,
0571: * boolean)
0572: */
0573: public static IEditorPart openEditor(IWorkbenchPage page,
0574: IEditorInput input, String editorId, boolean activate)
0575: throws PartInitException {
0576: // sanity checks
0577: if (page == null) {
0578: throw new IllegalArgumentException();
0579: }
0580:
0581: // open the editor on the file
0582: return page.openEditor(input, editorId, activate);
0583: }
0584:
0585: /**
0586: * Opens an editor on the given file resource. This method will attempt to
0587: * resolve the editor based on content-type bindings as well as traditional
0588: * name/extension bindings.
0589: * <p>
0590: * If the page already has an editor open on the target object then that
0591: * editor is brought to front; otherwise, a new editor is opened. If
0592: * <code>activate == true</code> the editor will be activated.
0593: * <p>
0594: *
0595: * @param page
0596: * the page in which the editor will be opened
0597: * @param input
0598: * the editor input
0599: * @param activate
0600: * if <code>true</code> the editor will be activated
0601: * @return an open editor or <code>null</code> if an external editor was
0602: * opened
0603: * @exception PartInitException
0604: * if the editor could not be initialized
0605: * @see org.eclipse.ui.IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput,
0606: * String, boolean)
0607: */
0608: public static IEditorPart openEditor(IWorkbenchPage page,
0609: IFile input, boolean activate) throws PartInitException {
0610: return openEditor(page, input, activate, true);
0611: }
0612:
0613: /**
0614: * Opens an editor on the given file resource. This method will attempt to
0615: * resolve the editor based on content-type bindings as well as traditional
0616: * name/extension bindings if <code>determineContentType</code> is
0617: * <code>true</code>.
0618: * <p>
0619: * If the page already has an editor open on the target object then that
0620: * editor is brought to front; otherwise, a new editor is opened. If
0621: * <code>activate == true</code> the editor will be activated.
0622: * <p>
0623: *
0624: * @param page
0625: * the page in which the editor will be opened
0626: * @param input
0627: * the editor input
0628: * @param activate
0629: * if <code>true</code> the editor will be activated
0630: * @param determineContentType
0631: * attempt to resolve the content type for this file
0632: * @return an open editor or <code>null</code> if an external editor was
0633: * opened
0634: * @exception PartInitException
0635: * if the editor could not be initialized
0636: * @see org.eclipse.ui.IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput,
0637: * String, boolean)
0638: * @since 3.1
0639: */
0640: public static IEditorPart openEditor(IWorkbenchPage page,
0641: IFile input, boolean activate, boolean determineContentType)
0642: throws PartInitException {
0643: // sanity checks
0644: if (page == null) {
0645: throw new IllegalArgumentException();
0646: }
0647:
0648: // open the editor on the file
0649: IEditorDescriptor editorDesc = getEditorDescriptor(input,
0650: determineContentType);
0651: return page.openEditor(new FileEditorInput(input), editorDesc
0652: .getId(), activate);
0653: }
0654:
0655: /**
0656: * Opens an editor on the given file resource. This method will attempt to
0657: * resolve the editor based on content-type bindings as well as traditional
0658: * name/extension bindings.
0659: * <p>
0660: * If the page already has an editor open on the target object then that
0661: * editor is brought to front; otherwise, a new editor is opened.
0662: * <p>
0663: *
0664: * @param page
0665: * the page in which the editor will be opened
0666: * @param input
0667: * the editor input
0668: * @return an open editor or <code>null</code> if an external editor was
0669: * opened
0670: * @exception PartInitException
0671: * if the editor could not be initialized
0672: * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
0673: */
0674: public static IEditorPart openEditor(IWorkbenchPage page,
0675: IFile input) throws PartInitException {
0676: // sanity checks
0677: if (page == null) {
0678: throw new IllegalArgumentException();
0679: }
0680:
0681: // open the editor on the file
0682: IEditorDescriptor editorDesc = getEditorDescriptor(input);
0683: return page.openEditor(new FileEditorInput(input), editorDesc
0684: .getId());
0685: }
0686:
0687: /**
0688: * Opens an editor on the given file resource.
0689: * <p>
0690: * If the page already has an editor open on the target object then that
0691: * editor is brought to front; otherwise, a new editor is opened.
0692: * <p>
0693: *
0694: * @param page
0695: * the page in which the editor will be opened
0696: * @param input
0697: * the editor input
0698: * @param editorId
0699: * the id of the editor extension to use
0700: * @return an open editor or <code>null</code> if an external editor was
0701: * opened
0702: * @exception PartInitException
0703: * if the editor could not be initialized
0704: * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
0705: */
0706: public static IEditorPart openEditor(IWorkbenchPage page,
0707: IFile input, String editorId) throws PartInitException {
0708: // sanity checks
0709: if (page == null) {
0710: throw new IllegalArgumentException();
0711: }
0712:
0713: // open the editor on the file
0714: return page.openEditor(new FileEditorInput(input), editorId);
0715: }
0716:
0717: /**
0718: * Opens an editor on the given file resource.
0719: * <p>
0720: * If the page already has an editor open on the target object then that
0721: * editor is brought to front; otherwise, a new editor is opened. If
0722: * <code>activate == true</code> the editor will be activated.
0723: * <p>
0724: *
0725: * @param page
0726: * the page in which the editor will be opened
0727: * @param input
0728: * the editor input
0729: * @param editorId
0730: * the id of the editor extension to use
0731: * @param activate
0732: * if <code>true</code> the editor will be activated
0733: * @return an open editor or <code>null</code> if an external editor was
0734: * opened
0735: * @exception PartInitException
0736: * if the editor could not be initialized
0737: * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String,
0738: * boolean)
0739: */
0740: public static IEditorPart openEditor(IWorkbenchPage page,
0741: IFile input, String editorId, boolean activate)
0742: throws PartInitException {
0743: // sanity checks
0744: if (page == null) {
0745: throw new IllegalArgumentException();
0746: }
0747:
0748: // open the editor on the file
0749: return page.openEditor(new FileEditorInput(input), editorId,
0750: activate);
0751: }
0752:
0753: /**
0754: * Returns an editor descriptor appropriate for opening the given file
0755: * resource.
0756: * <p>
0757: * The editor descriptor is determined using a multi-step process. This
0758: * method will attempt to resolve the editor based on content-type bindings
0759: * as well as traditional name/extension bindings.
0760: * </p>
0761: * <ol>
0762: * <li>The file is consulted for a persistent property named
0763: * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be
0764: * used.</li>
0765: * <li>The workbench editor registry is consulted to determine if an editor
0766: * extension has been registered for the file type. If so, an instance of
0767: * the editor extension is opened on the file. See
0768: * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li>
0769: * <li>The operating system is consulted to determine if an in-place
0770: * component editor is available (e.g. OLE editor on Win32 platforms).</li>
0771: * <li>The operating system is consulted to determine if an external editor
0772: * is available.</li>
0773: * </ol>
0774: * </p>
0775: *
0776: * @param file
0777: * the file
0778: * @return an editor descriptor, appropriate for opening the file
0779: * @throws PartInitException
0780: * if no editor can be found
0781: */
0782: public static IEditorDescriptor getEditorDescriptor(IFile file)
0783: throws PartInitException {
0784: return getEditorDescriptor(file, true);
0785: }
0786:
0787: /**
0788: * Returns an editor descriptor appropriate for opening the given file
0789: * resource.
0790: * <p>
0791: * The editor descriptor is determined using a multi-step process. This
0792: * method will attempt to resolve the editor based on content-type bindings
0793: * as well as traditional name/extension bindings if
0794: * <code>determineContentType</code>is <code>true</code>.
0795: * </p>
0796: * <ol>
0797: * <li>The file is consulted for a persistent property named
0798: * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be
0799: * used.</li>
0800: * <li>The workbench editor registry is consulted to determine if an editor
0801: * extension has been registered for the file type. If so, an instance of
0802: * the editor extension is opened on the file. See
0803: * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li>
0804: * <li>The operating system is consulted to determine if an in-place
0805: * component editor is available (e.g. OLE editor on Win32 platforms).</li>
0806: * <li>The operating system is consulted to determine if an external editor
0807: * is available.</li>
0808: * </ol>
0809: * </p>
0810: *
0811: * @param file
0812: * the file
0813: * @param determineContentType
0814: * query the content type system for the content type of the file
0815: * @return an editor descriptor, appropriate for opening the file
0816: * @throws PartInitException
0817: * if no editor can be found
0818: * @since 3.1
0819: */
0820: public static IEditorDescriptor getEditorDescriptor(IFile file,
0821: boolean determineContentType) throws PartInitException {
0822:
0823: if (file == null) {
0824: throw new IllegalArgumentException();
0825: }
0826:
0827: return getEditorDescriptor(file.getName(), PlatformUI
0828: .getWorkbench().getEditorRegistry(), getDefaultEditor(
0829: file, determineContentType));
0830: }
0831:
0832: /**
0833: * Returns an editor descriptor appropriate for opening a file resource with
0834: * the given name.
0835: * <p>
0836: * The editor descriptor is determined using a multi-step process. This
0837: * method will attempt to infer content type from the file name.
0838: * </p>
0839: * <ol>
0840: * <li>The file is consulted for a persistent property named
0841: * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be
0842: * used.</li>
0843: * <li>The workbench editor registry is consulted to determine if an editor
0844: * extension has been registered for the file type. If so, an instance of
0845: * the editor extension is opened on the file. See
0846: * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li>
0847: * <li>The operating system is consulted to determine if an in-place
0848: * component editor is available (e.g. OLE editor on Win32 platforms).</li>
0849: * <li>The operating system is consulted to determine if an external editor
0850: * is available.</li>
0851: * </ol>
0852: * </p>
0853: *
0854: * @param name
0855: * the file name
0856: * @return an editor descriptor, appropriate for opening the file
0857: * @throws PartInitException
0858: * if no editor can be found
0859: * @since 3.1
0860: */
0861: public static IEditorDescriptor getEditorDescriptor(String name)
0862: throws PartInitException {
0863: return getEditorDescriptor(name, true);
0864: }
0865:
0866: /**
0867: * Returns an editor descriptor appropriate for opening a file resource with
0868: * the given name.
0869: * <p>
0870: * The editor descriptor is determined using a multi-step process. This
0871: * method will attempt to infer the content type of the file if
0872: * <code>inferContentType</code> is <code>true</code>.
0873: * </p>
0874: * <ol>
0875: * <li>The file is consulted for a persistent property named
0876: * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be
0877: * used.</li>
0878: * <li>The workbench editor registry is consulted to determine if an editor
0879: * extension has been registered for the file type. If so, an instance of
0880: * the editor extension is opened on the file. See
0881: * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li>
0882: * <li>The operating system is consulted to determine if an in-place
0883: * component editor is available (e.g. OLE editor on Win32 platforms).</li>
0884: * <li>The operating system is consulted to determine if an external editor
0885: * is available.</li>
0886: * </ol>
0887: * </p>
0888: *
0889: * @param name
0890: * the file name
0891: * @param inferContentType
0892: * attempt to infer the content type from the file name if this
0893: * is <code>true</code>
0894: * @return an editor descriptor, appropriate for opening the file
0895: * @throws PartInitException
0896: * if no editor can be found
0897: * @since 3.1
0898: */
0899: public static IEditorDescriptor getEditorDescriptor(String name,
0900: boolean inferContentType) throws PartInitException {
0901:
0902: if (name == null) {
0903: throw new IllegalArgumentException();
0904: }
0905:
0906: IContentType contentType = inferContentType ? Platform
0907: .getContentTypeManager().findContentTypeFor(name)
0908: : null;
0909: IEditorRegistry editorReg = PlatformUI.getWorkbench()
0910: .getEditorRegistry();
0911:
0912: return getEditorDescriptor(name, editorReg, editorReg
0913: .getDefaultEditor(name, contentType));
0914: }
0915:
0916: /**
0917: * Get the editor descriptor for a given name using the editorDescriptor
0918: * passed in as a default as a starting point.
0919: *
0920: * @param name
0921: * The name of the element to open.
0922: * @param editorReg
0923: * The editor registry to do the lookups from.
0924: * @param defaultDescriptor
0925: * IEditorDescriptor or <code>null</code>
0926: * @return IEditorDescriptor
0927: * @throws PartInitException
0928: * if no valid editor can be found
0929: *
0930: * @since 3.1
0931: */
0932: private static IEditorDescriptor getEditorDescriptor(String name,
0933: IEditorRegistry editorReg,
0934: IEditorDescriptor defaultDescriptor)
0935: throws PartInitException {
0936:
0937: if (defaultDescriptor != null) {
0938: return defaultDescriptor;
0939: }
0940:
0941: IEditorDescriptor editorDesc = defaultDescriptor;
0942:
0943: // next check the OS for in-place editor (OLE on Win32)
0944: if (editorReg.isSystemInPlaceEditorAvailable(name)) {
0945: editorDesc = editorReg
0946: .findEditor(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID);
0947: }
0948:
0949: // next check with the OS for an external editor
0950: if (editorDesc == null
0951: && editorReg.isSystemExternalEditorAvailable(name)) {
0952: editorDesc = editorReg
0953: .findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
0954: }
0955:
0956: // next lookup the default text editor
0957: if (editorDesc == null) {
0958: editorDesc = editorReg
0959: .findEditor(IDEWorkbenchPlugin.DEFAULT_TEXT_EDITOR_ID);
0960: }
0961:
0962: // if no valid editor found, bail out
0963: if (editorDesc == null) {
0964: throw new PartInitException(
0965: IDEWorkbenchMessages.IDE_noFileEditorFound);
0966: }
0967:
0968: return editorDesc;
0969: }
0970:
0971: /**
0972: * Opens an editor on the file resource of the given marker.
0973: * <p>
0974: * If this page already has an editor open on the marker resource file that
0975: * editor is brought to front; otherwise, a new editor is opened.The cursor
0976: * and selection state of the editor are then updated from information
0977: * recorded in the marker.
0978: * </p>
0979: * <p>
0980: * If the marker contains an <code>EDITOR_ID_ATTR</code> attribute the
0981: * attribute value will be used to determine the editor type to be opened.
0982: * If not, the registered editor for the marker resource file will be used.
0983: * </p>
0984: *
0985: * @param page
0986: * the workbench page to open the editor in
0987: * @param marker
0988: * the marker to open
0989: * @return an open editor or <code>null</code> not possible
0990: * @exception PartInitException
0991: * if the editor could not be initialized
0992: * @see #openEditor(org.eclipse.ui.IWorkbenchPage,
0993: * org.eclipse.core.resources.IMarker, boolean)
0994: */
0995: public static IEditorPart openEditor(IWorkbenchPage page,
0996: IMarker marker) throws PartInitException {
0997: return openEditor(page, marker, true);
0998: }
0999:
1000: /**
1001: * Opens an editor on the file resource of the given marker.
1002: * <p>
1003: * If this page already has an editor open on the marker resource file that
1004: * editor is brought to front; otherwise, a new editor is opened. If
1005: * <code>activate == true</code> the editor will be activated. The cursor
1006: * and selection state of the editor are then updated from information
1007: * recorded in the marker.
1008: * </p>
1009: * <p>
1010: * If the marker contains an <code>EDITOR_ID_ATTR</code> attribute the
1011: * attribute value will be used to determine the editor type to be opened.
1012: * If not, the registered editor for the marker resource file will be used.
1013: * </p>
1014: *
1015: * @param page
1016: * the workbench page to open the editor in
1017: * @param marker
1018: * the marker to open
1019: * @param activate
1020: * if <code>true</code> the editor will be activated
1021: * @return an open editor or <code>null</code> not possible
1022: * @exception PartInitException
1023: * if the editor could not be initialized
1024: */
1025: public static IEditorPart openEditor(IWorkbenchPage page,
1026: IMarker marker, boolean activate) throws PartInitException {
1027: // sanity checks
1028: if (page == null || marker == null) {
1029: throw new IllegalArgumentException();
1030: }
1031:
1032: // get the marker resource file
1033: if (!(marker.getResource() instanceof IFile)) {
1034: IDEWorkbenchPlugin
1035: .log("Open editor on marker failed; marker resource not an IFile"); //$NON-NLS-1$
1036: return null;
1037: }
1038: IFile file = (IFile) marker.getResource();
1039:
1040: // get the preferred editor id from the marker
1041: IEditorRegistry editorReg = PlatformUI.getWorkbench()
1042: .getEditorRegistry();
1043: IEditorDescriptor editorDesc = null;
1044: try {
1045: String editorID = (String) marker
1046: .getAttribute(EDITOR_ID_ATTR);
1047: if (editorID != null) {
1048: editorDesc = editorReg.findEditor(editorID);
1049: }
1050: } catch (CoreException e) {
1051: // ignore this
1052: }
1053:
1054: // open the editor on the marker resource file
1055: IEditorPart editor = null;
1056: if (editorDesc == null) {
1057: editor = openEditor(page, file, activate);
1058: } else {
1059: editor = page.openEditor(new FileEditorInput(file),
1060: editorDesc.getId(), activate);
1061: }
1062:
1063: // get the editor to update its position based on the marker
1064: if (editor != null) {
1065: gotoMarker(editor, marker);
1066: }
1067:
1068: return editor;
1069: }
1070:
1071: /**
1072: * Opens an editor on the given IFileStore object.
1073: * <p>
1074: * Unlike the other <code>openEditor</code> methods, this one
1075: * can be used to open files that reside outside the workspace
1076: * resource set.
1077: * </p>
1078: * <p>
1079: * If the page already has an editor open on the target object then that
1080: * editor is brought to front; otherwise, a new editor is opened.
1081: * </p>
1082: *
1083: * @param page
1084: * the page in which the editor will be opened
1085: * @param fileStore
1086: * the IFileStore representing the file to open
1087: * @return an open editor or <code>null</code> if an external editor was opened
1088: * @exception PartInitException
1089: * if the editor could not be initialized
1090: * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
1091: * @since 3.3
1092: */
1093: public static IEditorPart openEditorOnFileStore(
1094: IWorkbenchPage page, IFileStore fileStore)
1095: throws PartInitException {
1096: //sanity checks
1097: if (page == null) {
1098: throw new IllegalArgumentException();
1099: }
1100:
1101: IEditorInput input = getEditorInput(fileStore);
1102: String editorId = getEditorId(fileStore);
1103:
1104: // open the editor on the file
1105: return page.openEditor(input, editorId);
1106: }
1107:
1108: /**
1109: * Get the id of the editor associated with the given <code>IFileStore</code>.
1110: *
1111: * @param workbench
1112: * the Workbench to use to determine the appropriate editor's id
1113: * @param fileStore
1114: * the <code>IFileStore</code> representing the file for which the editor id is desired
1115: * @return the id of the appropriate editor
1116: * @since 3.3
1117: */
1118: private static String getEditorId(IFileStore fileStore) {
1119: IEditorDescriptor descriptor;
1120: try {
1121: descriptor = IDE.getEditorDescriptor(fileStore.getName());
1122: } catch (PartInitException e) {
1123: return null;
1124: }
1125: if (descriptor != null)
1126: return descriptor.getId();
1127: return null;
1128: }
1129:
1130: /**
1131: * Save all dirty editors in the workbench whose editor input is a child
1132: * resource of one of the <code>IResource</code>'s provided. Opens a
1133: * dialog to prompt the user if <code>confirm</code> is true. Return true
1134: * if successful. Return false if the user has canceled the command.
1135: *
1136: * @since 3.0
1137: *
1138: * @param resourceRoots the resource roots under which editor input should
1139: * be saved, other will be left dirty
1140: * @param confirm <code>true</code> to ask the user before saving unsaved
1141: * changes (recommended), and <code>false</code> to save
1142: * unsaved changes without asking
1143: * @return <code>true</code> if the command succeeded, and
1144: * <code>false</code> if the operation was canceled by the user or
1145: * an error occurred while saving
1146: */
1147: public static boolean saveAllEditors(
1148: final IResource[] resourceRoots, final boolean confirm) {
1149:
1150: if (resourceRoots.length == 0) {
1151: return true;
1152: }
1153:
1154: final boolean[] result = new boolean[] { true };
1155: SafeRunner.run(new SafeRunnable(
1156: IDEWorkbenchMessages.ErrorOnSaveAll) {
1157: public void run() {
1158: IWorkbenchWindow w = PlatformUI.getWorkbench()
1159: .getActiveWorkbenchWindow();
1160: if (w == null) {
1161: IWorkbenchWindow[] windows = PlatformUI
1162: .getWorkbench().getWorkbenchWindows();
1163: if (windows.length > 0)
1164: w = windows[0];
1165: }
1166: if (w != null) {
1167: result[0] = PlatformUI.getWorkbench().saveAll(w, w,
1168: new SaveFilter(resourceRoots), confirm);
1169: }
1170: }
1171: });
1172: return result[0];
1173: }
1174:
1175: /**
1176: * Sets the default editor id for a given file. This value will be used to
1177: * determine the default editor descriptor for the file in future calls to
1178: * <code>getDefaultEditor(IFile)</code>.
1179: *
1180: * @param file
1181: * the file
1182: * @param editorID
1183: * the editor id
1184: */
1185: public static void setDefaultEditor(IFile file, String editorID) {
1186: try {
1187: file.setPersistentProperty(EDITOR_KEY, editorID);
1188: } catch (CoreException e) {
1189: // do nothing
1190: }
1191: }
1192:
1193: /**
1194: * Returns the default editor for a given file. This method will attempt to
1195: * resolve the editor based on content-type bindings as well as traditional
1196: * name/extension bindings.
1197: * <p>
1198: * A default editor id may be registered for a specific file using
1199: * <code>setDefaultEditor</code>. If the given file has a registered
1200: * default editor id the default editor will derived from it. If not, the
1201: * default editor is determined by taking the file name for the file and
1202: * obtaining the default editor for that name.
1203: * </p>
1204: *
1205: * @param file
1206: * the file
1207: * @return the descriptor of the default editor, or <code>null</code> if
1208: * not found
1209: */
1210: public static IEditorDescriptor getDefaultEditor(IFile file) {
1211: return getDefaultEditor(file, true);
1212: }
1213:
1214: /**
1215: * Returns the default editor for a given file. This method will attempt to
1216: * resolve the editor based on content-type bindings as well as traditional
1217: * name/extension bindings if <code>determineContentType</code> is
1218: * <code>true</code>.
1219: * <p>
1220: * A default editor id may be registered for a specific file using
1221: * <code>setDefaultEditor</code>. If the given file has a registered
1222: * default editor id the default editor will derived from it. If not, the
1223: * default editor is determined by taking the file name for the file and
1224: * obtaining the default editor for that name.
1225: * </p>
1226: *
1227: * @param file
1228: * the file
1229: * @param determineContentType
1230: * determine the content type for the given file
1231: * @return the descriptor of the default editor, or <code>null</code> if
1232: * not found
1233: * @since 3.1
1234: */
1235: public static IEditorDescriptor getDefaultEditor(IFile file,
1236: boolean determineContentType) {
1237: // Try file specific editor.
1238: IEditorRegistry editorReg = PlatformUI.getWorkbench()
1239: .getEditorRegistry();
1240: try {
1241: String editorID = file.getPersistentProperty(EDITOR_KEY);
1242: if (editorID != null) {
1243: IEditorDescriptor desc = editorReg.findEditor(editorID);
1244: if (desc != null) {
1245: return desc;
1246: }
1247: }
1248: } catch (CoreException e) {
1249: // do nothing
1250: }
1251:
1252: IContentType contentType = null;
1253: if (determineContentType) {
1254: contentType = getContentType(file);
1255: }
1256: // Try lookup with filename
1257: return editorReg.getDefaultEditor(file.getName(), contentType);
1258: }
1259:
1260: /**
1261: * Extracts and returns the <code>IResource</code>s in the given
1262: * selection or the resource objects they adapts to.
1263: *
1264: * @param originalSelection
1265: * the original selection, possibly empty
1266: * @return list of resources (element type: <code>IResource</code>),
1267: * possibly empty
1268: */
1269: public static List computeSelectedResources(
1270: IStructuredSelection originalSelection) {
1271: List resources = null;
1272: for (Iterator e = originalSelection.iterator(); e.hasNext();) {
1273: Object next = e.next();
1274: Object resource = null;
1275: if (next instanceof IResource) {
1276: resource = next;
1277: } else if (next instanceof IAdaptable) {
1278: resource = ((IAdaptable) next)
1279: .getAdapter(IResource.class);
1280: }
1281: if (resource != null) {
1282: if (resources == null) {
1283: // lazy init to avoid creating empty lists
1284: // assume selection contains mostly resources most times
1285: resources = new ArrayList(originalSelection.size());
1286: }
1287: resources.add(resource);
1288: }
1289: }
1290: if (resources == null) {
1291: return Collections.EMPTY_LIST;
1292: }
1293: return resources;
1294:
1295: }
1296:
1297: /**
1298: * Return the content type for the given file.
1299: *
1300: * @param file
1301: * the file to test
1302: * @return the content type, or <code>null</code> if it cannot be
1303: * determined.
1304: * @since 3.1
1305: */
1306: public static IContentType getContentType(IFile file) {
1307: try {
1308: UIStats.start(UIStats.CONTENT_TYPE_LOOKUP, file.getName());
1309: IContentDescription contentDescription = file
1310: .getContentDescription();
1311: if (contentDescription == null) {
1312: return null;
1313: }
1314: return contentDescription.getContentType();
1315: } catch (CoreException e) {
1316: return null;
1317: } finally {
1318: UIStats.end(UIStats.CONTENT_TYPE_LOOKUP, file, file
1319: .getName());
1320: }
1321: }
1322:
1323: /**
1324: * Guess at the content type of the given file based on the filename.
1325: *
1326: * @param file
1327: * the file to test
1328: * @return the content type, or <code>null</code> if it cannot be
1329: * determined.
1330: * @since 3.2
1331: */
1332: public static IContentType guessContentType(IFile file) {
1333: String fileName = file.getName();
1334: try {
1335: UIStats.start(UIStats.CONTENT_TYPE_LOOKUP, fileName);
1336: IContentTypeMatcher matcher = file.getProject()
1337: .getContentTypeMatcher();
1338: return matcher.findContentTypeFor(fileName);
1339: } catch (CoreException e) {
1340: return null;
1341: } finally {
1342: UIStats.end(UIStats.CONTENT_TYPE_LOOKUP, file, fileName);
1343: }
1344: }
1345:
1346: /**
1347: * Prompt the user to inform them of the possible side effects of an
1348: * operation on resources. Do not prompt for side effects from ignored model
1349: * providers. A model provider can be ignored if it is the client calling
1350: * this API. Any message from the provided model provider id or any model
1351: * providers it extends will be ignored.
1352: *
1353: * @param shell
1354: * the shell to parent the prompt dialog
1355: * @param title
1356: * the title of the dialog
1357: * @param message
1358: * the message for the dialog
1359: * @param delta
1360: * a delta built using an
1361: * {@link IResourceChangeDescriptionFactory}
1362: * @param ignoreModelProviderIds
1363: * model providers to be ignored
1364: * @param syncExec
1365: * prompt in a sync exec (required when called from a non-UI
1366: * thread)
1367: * @return whether the user chose to continue
1368: * @since 3.2
1369: */
1370: public static boolean promptToConfirm(final Shell shell,
1371: final String title, String message, IResourceDelta delta,
1372: String[] ignoreModelProviderIds, boolean syncExec) {
1373: IStatus status = ResourceChangeValidator.getValidator()
1374: .validateChange(delta, null);
1375: if (status.isOK()) {
1376: return true;
1377: }
1378: final IStatus displayStatus;
1379: if (status.isMultiStatus()) {
1380: List result = new ArrayList();
1381: IStatus[] children = status.getChildren();
1382: for (int i = 0; i < children.length; i++) {
1383: IStatus child = children[i];
1384: if (!isIgnoredStatus(child, ignoreModelProviderIds)) {
1385: result.add(child);
1386: }
1387: }
1388: if (result.isEmpty()) {
1389: return true;
1390: }
1391: if (result.size() == 1) {
1392: displayStatus = (IStatus) result.get(0);
1393: } else {
1394: displayStatus = new MultiStatus(status.getPlugin(),
1395: status.getCode(), (IStatus[]) result
1396: .toArray(new IStatus[result.size()]),
1397: status.getMessage(), status.getException());
1398: }
1399: } else {
1400: if (isIgnoredStatus(status, ignoreModelProviderIds)) {
1401: return true;
1402: }
1403: displayStatus = status;
1404: }
1405:
1406: if (message == null) {
1407: message = IDEWorkbenchMessages.IDE_sideEffectWarning;
1408: }
1409: final String dialogMessage = NLS.bind(
1410: IDEWorkbenchMessages.IDE_areYouSure, message);
1411:
1412: final boolean[] result = new boolean[] { false };
1413: Runnable runnable = new Runnable() {
1414: public void run() {
1415: ErrorDialog dialog = new ErrorDialog(shell, title,
1416: dialogMessage, displayStatus, IStatus.ERROR
1417: | IStatus.WARNING | IStatus.INFO) {
1418: protected void createButtonsForButtonBar(
1419: Composite parent) {
1420: createButton(parent, IDialogConstants.YES_ID,
1421: IDialogConstants.YES_LABEL, false);
1422: createButton(parent, IDialogConstants.NO_ID,
1423: IDialogConstants.NO_LABEL, true);
1424: createDetailsButton(parent);
1425: }
1426:
1427: /*
1428: * (non-Javadoc)
1429: *
1430: * @see org.eclipse.jface.dialogs.ErrorDialog#buttonPressed(int)
1431: */
1432: protected void buttonPressed(int id) {
1433: if (id == IDialogConstants.YES_ID) {
1434: super .buttonPressed(IDialogConstants.OK_ID);
1435: } else if (id == IDialogConstants.NO_ID) {
1436: super
1437: .buttonPressed(IDialogConstants.CANCEL_ID);
1438: }
1439: super .buttonPressed(id);
1440: }
1441: };
1442: int code = dialog.open();
1443: result[0] = code == 0;
1444: }
1445: };
1446: if (syncExec) {
1447: shell.getDisplay().syncExec(runnable);
1448: } else {
1449: runnable.run();
1450: }
1451: return result[0];
1452: }
1453:
1454: private static boolean isIgnoredStatus(IStatus status,
1455: String[] ignoreModelProviderIds) {
1456: if (ignoreModelProviderIds == null) {
1457: return false;
1458: }
1459: if (status instanceof ModelStatus) {
1460: ModelStatus ms = (ModelStatus) status;
1461: for (int i = 0; i < ignoreModelProviderIds.length; i++) {
1462: String id = ignoreModelProviderIds[i];
1463: if (ms.getModelProviderId().equals(id)) {
1464: return true;
1465: }
1466: IModelProviderDescriptor desc = ModelProvider
1467: .getModelProviderDescriptor(id);
1468: String[] extended = desc.getExtendedModels();
1469: if (isIgnoredStatus(status, extended)) {
1470: return true;
1471: }
1472: }
1473: }
1474: return false;
1475: }
1476: }
|