IDE.java :  » IDE-Eclipse » ui-ide » org » eclipse » ui » ide » Java Open Source

Java Open Source » IDE Eclipse » ui ide 
ui ide » org » eclipse » ui » ide » IDE.java
/*******************************************************************************
 * Copyright (c) 2003, 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.ide;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.osgi.util.NLS;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeMatcher;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.mapping.IModelProviderDescriptor;
import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
import org.eclipse.core.resources.mapping.ModelProvider;
import org.eclipse.core.resources.mapping.ModelStatus;
import org.eclipse.core.resources.mapping.ResourceChangeValidator;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.resources.mapping.ResourceTraversal;

import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.IStructuredSelection;

import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IMarkerHelpRegistry;
import org.eclipse.ui.ISaveableFilter;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.Saveable;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.registry.MarkerHelpRegistry;
import org.eclipse.ui.internal.ide.registry.MarkerHelpRegistryReader;
import org.eclipse.ui.internal.misc.UIStats;
import org.eclipse.ui.part.FileEditorInput;

/**
 * Collection of IDE-specific APIs factored out of existing workbench. This
 * class cannot be instantiated; all functionality is provided by static methods
 * and fields.
 * 
 * @since 3.0
 */
public final class IDE {
  /**
   * The persistent property key used on IFile resources to contain the
   * preferred editor ID to use.
   * <p>
   * Example of retrieving the persisted editor id:
   * 
   * <pre><code>
   *  IFile file = ...
   *  IEditorDescriptor editorDesc = null;
   *  try {
   *    String editorID = file.getPersistentProperty(EDITOR_KEY);
   *    if (editorID != null) {
   *      editorDesc = editorReg.findEditor(editorID);
   *    }
   *  } catch (CoreException e) {
   *    // handle problem accessing persistent property here
   *  }
   * </code></pre>
   * 
   * </p>
   * <p>
   * Example of persisting the editor id:
   * 
   * <pre><code>
   *  IFile file = ...
   *  try {
   *    file.setPersistentProperty(EDITOR_KEY, editorDesc.getId());
   *  } catch (CoreException e) {
   *    // handle problem setting persistent property here
   *  }
   * </code></pre>
   * 
   * </p>
   */
  public static final QualifiedName EDITOR_KEY = new QualifiedName(
      "org.eclipse.ui.internal.registry.ResourceEditorRegistry", "EditorProperty");//$NON-NLS-2$//$NON-NLS-1$

  /**
   * An optional attribute within a workspace marker (<code>IMarker</code>)
   * which identifies the preferred editor type to be opened.
   */
  public static final String EDITOR_ID_ATTR = "org.eclipse.ui.editorID"; //$NON-NLS-1$

  /**
   * The resource based perspective identifier.
   */
  public static final String RESOURCE_PERSPECTIVE_ID = "org.eclipse.ui.resourcePerspective"; //$NON-NLS-1$

  /**
   * Marker help registry mapping markers to help context ids and resolutions;
   * lazily initialized on fist access.
   */
  private static MarkerHelpRegistry markerHelpRegistry = null;

  /**
   * Standard shared images defined by the IDE. These are over and above the
   * standard workbench images declared in {@link org.eclipse.ui.ISharedImages
   * ISharedImages}.
   * <p>
   * This interface is not intended to be implemented by clients.
   * </p>
   * 
   * @see org.eclipse.ui.ISharedImages
   */
  public interface SharedImages {
    /**
     * Identifies a project image.
     */
    public final static String IMG_OBJ_PROJECT = "IMG_OBJ_PROJECT"; //$NON-NLS-1$

    /**
     * Identifies a closed project image.
     */
    public final static String IMG_OBJ_PROJECT_CLOSED = "IMG_OBJ_PROJECT_CLOSED"; //$NON-NLS-1$

    /**
     * Identifies the image used for "open marker".
     */
    public final static String IMG_OPEN_MARKER = "IMG_OPEN_MARKER"; //$NON-NLS-1$

    /**
     * Identifies the default image used to indicate a task.
     */
    public final static String IMG_OBJS_TASK_TSK = "IMG_OBJS_TASK_TSK"; //$NON-NLS-1$

    /**
     * Identifies the default image used to indicate a bookmark.
     */
    public final static String IMG_OBJS_BKMRK_TSK = "IMG_OBJS_BKMRK_TSK"; //$NON-NLS-1$
  }

  /**
   * Preferences defined by the IDE workbench.
   * <p>
   * This interface is not intended to be implemented by clients.
   * </p>
   */
  public interface Preferences {

    /**
     * A named preference for how a new perspective should be opened when a
     * new project is created.
     * <p>
     * Value is of type <code>String</code>. The possible values are
     * defined by the constants
     * <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE, 
     * OPEN_PERSPECTIVE_REPLACE, and NO_NEW_PERSPECTIVE</code>.
     * </p>
     * 
     * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_WINDOW
     * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_PAGE
     * @see org.eclipse.ui.IWorkbenchPreferenceConstants#OPEN_PERSPECTIVE_REPLACE
     * @see org.eclipse.ui.IWorkbenchPreferenceConstants#NO_NEW_PERSPECTIVE
     */
    public static final String PROJECT_OPEN_NEW_PERSPECTIVE = "PROJECT_OPEN_NEW_PERSPECTIVE"; //$NON-NLS-1$

    /**
     * <p>
     * Specifies whether or not the workspace selection dialog should be
     * shown on startup.
     * </p>
     * <p>
     * The default value for this preference is <code>true</code>.
     * </p>
     * 
     * @since 3.1
     */
    public static final String SHOW_WORKSPACE_SELECTION_DIALOG = "SHOW_WORKSPACE_SELECTION_DIALOG"; //$NON-NLS-1$

    /**
     * <p>
     * Stores the maximum number of workspaces that should be displayed in
     * the ChooseWorkspaceDialog.
     * </p>
     * 
     * @since 3.1
     */
    public static final String MAX_RECENT_WORKSPACES = "MAX_RECENT_WORKSPACES"; //$NON-NLS-1$

    /**
     * <p>
     * Stores a comma separated list of the recently used workspace paths.
     * </p>
     * 
     * @since 3.1
     */
    public static final String RECENT_WORKSPACES = "RECENT_WORKSPACES"; //$NON-NLS-1$

    /**
     * <p>
     * Stores the version of the protocol used to decode/encode the list of
     * recent workspaces.
     * </p>
     * 
     * @since 3.1
     */
    public static final String RECENT_WORKSPACES_PROTOCOL = "RECENT_WORKSPACES_PROTOCOL"; //$NON-NLS-1$

  }

  /**
   * A saveable filter that selects savables that contain resources that
   * are descendants of the roots of the filter.
   * @since 3.3
   *
   */
  private static class SaveFilter implements ISaveableFilter {
    private final IResource[] roots;

    /**
     * Create the filter
     * @param roots the save roots
     */
    public SaveFilter(IResource[] roots) {
      this.roots = roots;
    }
    
    /* (non-Javadoc)
     * @see org.eclipse.ui.ISaveableFilter#select(org.eclipse.ui.Saveable, org.eclipse.ui.IWorkbenchPart[])
     */
    public boolean select(Saveable saveable,
        IWorkbenchPart[] containingParts) {
      if (isDescendantOfRoots(saveable)) {
        return true;
      }
      // For backwards compatibility, we need to check the parts
      for (int i = 0; i < containingParts.length; i++) {
        IWorkbenchPart workbenchPart = containingParts[i];
        if (workbenchPart instanceof IEditorPart) {
          IEditorPart editorPart = (IEditorPart) workbenchPart;
          if (isEditingDescendantOf(editorPart)) {
            return true;
          }
        }
      }
      return false;
    }
    
    /**
     * Return whether the given saveable contains any resources that
     * are descendants of the root resources.
     * @param saveable the saveable
     * @return whether the given saveable contains any resources that
     * are descendants of the root resources
     */
    private boolean isDescendantOfRoots(Saveable saveable) {
      // First, try and adapt the saveable to a resource mapping.
      ResourceMapping mapping = ResourceUtil.getResourceMapping(saveable);
      if (mapping != null) {
        try {
          ResourceTraversal[] traversals = mapping.getTraversals(
              ResourceMappingContext.LOCAL_CONTEXT, null);
          for (int i = 0; i < traversals.length; i++) {
            ResourceTraversal traversal = traversals[i];
            IResource[] resources = traversal.getResources();
            for (int j = 0; j < resources.length; j++) {
              IResource resource = resources[j];
              if (isDescendantOfRoots(resource)) {
                return true;
              }
            }
          }
        } catch (CoreException e) {
          IDEWorkbenchPlugin
              .log(
                  NLS
                      .bind(
                          "An internal error occurred while determining the resources for {0}", saveable.getName()), e); //$NON-NLS-1$
        }
      } else {
        // If there is no mapping, try to adapt to a resource or file directly
        IFile file = ResourceUtil.getFile(saveable);
        if (file != null) {
          return isDescendantOfRoots(file);
        }
      }
      return false;
    }

    /**
     * Return whether the given resource is either equal to or a descendant of
     * one of the given roots.
     * 
     * @param roots the root resources
     * @param resource the resource to be tested
     * @return whether the given resource is either equal to or a descendant of
     *         one of the given roots
     */
    private boolean isDescendantOfRoots(IResource resource) {
      for (int l = 0; l < roots.length; l++) {
        IResource root = roots[l];
        if (root.getFullPath().isPrefixOf(resource.getFullPath())) {
          return true;
        }
      }
      return false;
    }
    
    /**
     * Return whether the given dirty editor part is editing resources that are
     * descendants of the given roots.
     * 
     * @param roots the root resources
     * @param part the dirty editor part
     * @return whether the given dirty editor part is editing resources that are
     *         descendants of the given roots
     */
    private boolean isEditingDescendantOf(IEditorPart part) {
      IFile file = ResourceUtil.getFile(part.getEditorInput());
      if (file != null) {
        return isDescendantOfRoots(file);
      }
      return false;
    }
    
  }
  
  /**
   * Block instantiation.
   */
  private IDE() {
    // do nothing
  }

  /**
   * Returns the marker help registry for the workbench.
   * 
   * @return the marker help registry
   */
  public static IMarkerHelpRegistry getMarkerHelpRegistry() {
    if (markerHelpRegistry == null) {
      markerHelpRegistry = new MarkerHelpRegistry();
      new MarkerHelpRegistryReader().addHelp(markerHelpRegistry);
    }
    return markerHelpRegistry;
  }

  /**
   * Sets the cursor and selection state for the given editor to reveal the
   * position of the given marker. This is done on a best effort basis. If the
   * editor does not provide an <code>IGotoMarker</code> interface (either
   * directly or via <code>IAdaptable.getAdapter</code>), this has no
   * effect.
   * 
   * @param editor
   *            the editor
   * @param marker
   *            the marker
   */
  public static void gotoMarker(IEditorPart editor, IMarker marker) {
    IGotoMarker gotoMarker = null;
    if (editor instanceof IGotoMarker) {
      gotoMarker = (IGotoMarker) editor;
    } else {
      gotoMarker = (IGotoMarker) editor.getAdapter(IGotoMarker.class);
    }
    if (gotoMarker != null) {
      gotoMarker.gotoMarker(marker);
    }
  }

  /**
   * Opens an editor on the given object.
   * <p>
   * If the page already has an editor open on the target object then that
   * editor is brought to front; otherwise, a new editor is opened.
   * <p>
   * 
   * @param page
   *            the page in which the editor will be opened
   * @param input
   *            the editor input
   * @param editorId
   *            the id of the editor extension to use
   * @return an open editor or <code>null</code> if an external editor was
   *         opened
   * @exception PartInitException
   *                if the editor could not be initialized
   * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
   */
  public static IEditorPart openEditor(IWorkbenchPage page,
      IEditorInput input, String editorId) throws PartInitException {
    // sanity checks
    if (page == null) {
      throw new IllegalArgumentException();
    }

    // open the editor on the file
    return page.openEditor(input, editorId);
  }

  /**
   * Opens an editor on the given IFileStore object.
   * <p>
   * Unlike the other <code>openEditor</code> methods, this one can be used
   * to open files that reside outside the workspace resource set.
   * </p>
   * <p>
   * If the page already has an editor open on the target object then that
   * editor is brought to front; otherwise, a new editor is opened.
   * </p>
   * 
   * @param page
   *            the page in which the editor will be opened
   * @param uri
   *            the URI of the file store representing the file to open
   * @param editorId
   *            the id of the editor extension to use
   * @param activate
   *            if <code>true</code> the editor will be activated opened
   * @return an open editor or <code>null</code> if an external editor was
   * @exception PartInitException
   *                if the editor could not be initialized
   * 
   * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
   * @see EFS#getStore(URI)
   * 
   * @since 3.3
   */
  public static IEditorPart openEditor(IWorkbenchPage page, URI uri,
      String editorId, boolean activate) throws PartInitException {
    // sanity checks
    if (page == null) {
      throw new IllegalArgumentException();
    }

    IFileStore fileStore;
    try {
      fileStore = EFS.getStore(uri);
    } catch (CoreException e) {
      throw new PartInitException(
          IDEWorkbenchMessages.IDE_coreExceptionFileStore, e);
    }

    IEditorInput input = getEditorInput(fileStore);

    // open the editor on the file
    return page.openEditor(input, editorId, activate);
  }

  /**
   * Create the Editor Input appropriate for the given <code>IFileStore</code>.
   * The result is a normal file editor input if the file exists in the
   * workspace and, if not, we create a wrapper capable of managing an
   * 'external' file using its <code>IFileStore</code>.
   * 
   * @param fileStore
   *            The file store to provide the editor input for
   * @return The editor input associated with the given file store
   */
  private static IEditorInput getEditorInput(IFileStore fileStore) {
    IFile workspaceFile = getWorkspaceFile(fileStore);
    if (workspaceFile != null)
      return new FileEditorInput(workspaceFile);
    return new FileStoreEditorInput(fileStore);
  }

  /**
   * Determine whether or not the <code>IFileStore</code> represents a file
   * currently in the workspace.
   * 
   * @param fileStore
   *            The <code>IFileStore</code> to test
   * @return The workspace's <code>IFile</code> if it exists or
   *         <code>null</code> if not
   */
  private static IFile getWorkspaceFile(IFileStore fileStore) {
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    IFile[] files = root.findFilesForLocationURI(fileStore.toURI());
    files = filterNonExistentFiles(files);
    if (files == null || files.length == 0)
      return null;

    // for now only return the first file
    return files[0];
  }

  /**
   * Filter the incoming array of <code>IFile</code> elements by removing
   * any that do not currently exist in the workspace.
   * 
   * @param files
   *            The array of <code>IFile</code> elements
   * @return The filtered array
   */
  private static IFile[] filterNonExistentFiles(IFile[] files) {
    if (files == null)
      return null;

    int length = files.length;
    ArrayList existentFiles = new ArrayList(length);
    for (int i = 0; i < length; i++) {
      if (files[i].exists())
        existentFiles.add(files[i]);
    }
    return (IFile[]) existentFiles.toArray(new IFile[existentFiles.size()]);
  }

  /**
   * Opens an editor on the given object.
   * <p>
   * If the page already has an editor open on the target object then that
   * editor is brought to front; otherwise, a new editor is opened. If
   * <code>activate == true</code> the editor will be activated.
   * <p>
   * 
   * @param page
   *            the page in which the editor will be opened
   * @param input
   *            the editor input
   * @param editorId
   *            the id of the editor extension to use
   * @param activate
   *            if <code>true</code> the editor will be activated
   * @return an open editor or <code>null</code> if an external editor was
   *         opened
   * @exception PartInitException
   *                if the editor could not be initialized
   * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String,
   *      boolean)
   */
  public static IEditorPart openEditor(IWorkbenchPage page,
      IEditorInput input, String editorId, boolean activate)
      throws PartInitException {
    // sanity checks
    if (page == null) {
      throw new IllegalArgumentException();
    }

    // open the editor on the file
    return page.openEditor(input, editorId, activate);
  }

  /**
   * Opens an editor on the given file resource. This method will attempt to
   * resolve the editor based on content-type bindings as well as traditional
   * name/extension bindings.
   * <p>
   * If the page already has an editor open on the target object then that
   * editor is brought to front; otherwise, a new editor is opened. If
   * <code>activate == true</code> the editor will be activated.
   * <p>
   * 
   * @param page
   *            the page in which the editor will be opened
   * @param input
   *            the editor input
   * @param activate
   *            if <code>true</code> the editor will be activated
   * @return an open editor or <code>null</code> if an external editor was
   *         opened
   * @exception PartInitException
   *                if the editor could not be initialized
   * @see org.eclipse.ui.IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput,
   *      String, boolean)
   */
  public static IEditorPart openEditor(IWorkbenchPage page, IFile input,
      boolean activate) throws PartInitException {
    return openEditor(page, input, activate, true);
  }

  /**
   * Opens an editor on the given file resource. This method will attempt to
   * resolve the editor based on content-type bindings as well as traditional
   * name/extension bindings if <code>determineContentType</code> is
   * <code>true</code>.
   * <p>
   * If the page already has an editor open on the target object then that
   * editor is brought to front; otherwise, a new editor is opened. If
   * <code>activate == true</code> the editor will be activated.
   * <p>
   * 
   * @param page
   *            the page in which the editor will be opened
   * @param input
   *            the editor input
   * @param activate
   *            if <code>true</code> the editor will be activated
   * @param determineContentType
   *            attempt to resolve the content type for this file
   * @return an open editor or <code>null</code> if an external editor was
   *         opened
   * @exception PartInitException
   *                if the editor could not be initialized
   * @see org.eclipse.ui.IWorkbenchPage#openEditor(org.eclipse.ui.IEditorInput,
   *      String, boolean)
   * @since 3.1
   */
  public static IEditorPart openEditor(IWorkbenchPage page, IFile input,
      boolean activate, boolean determineContentType)
      throws PartInitException {
    // sanity checks
    if (page == null) {
      throw new IllegalArgumentException();
    }

    // open the editor on the file
    IEditorDescriptor editorDesc = getEditorDescriptor(input,
        determineContentType);
    return page.openEditor(new FileEditorInput(input), editorDesc.getId(),
        activate);
  }

  /**
   * Opens an editor on the given file resource. This method will attempt to
   * resolve the editor based on content-type bindings as well as traditional
   * name/extension bindings.
   * <p>
   * If the page already has an editor open on the target object then that
   * editor is brought to front; otherwise, a new editor is opened.
   * <p>
   * 
   * @param page
   *            the page in which the editor will be opened
   * @param input
   *            the editor input
   * @return an open editor or <code>null</code> if an external editor was
   *         opened
   * @exception PartInitException
   *                if the editor could not be initialized
   * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
   */
  public static IEditorPart openEditor(IWorkbenchPage page, IFile input)
      throws PartInitException {
    // sanity checks
    if (page == null) {
      throw new IllegalArgumentException();
    }

    // open the editor on the file
    IEditorDescriptor editorDesc = getEditorDescriptor(input);
    return page.openEditor(new FileEditorInput(input), editorDesc.getId());
  }

  /**
   * Opens an editor on the given file resource.
   * <p>
   * If the page already has an editor open on the target object then that
   * editor is brought to front; otherwise, a new editor is opened.
   * <p>
   * 
   * @param page
   *            the page in which the editor will be opened
   * @param input
   *            the editor input
   * @param editorId
   *            the id of the editor extension to use
   * @return an open editor or <code>null</code> if an external editor was
   *         opened
   * @exception PartInitException
   *                if the editor could not be initialized
   * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
   */
  public static IEditorPart openEditor(IWorkbenchPage page, IFile input,
      String editorId) throws PartInitException {
    // sanity checks
    if (page == null) {
      throw new IllegalArgumentException();
    }

    // open the editor on the file
    return page.openEditor(new FileEditorInput(input), editorId);
  }

  /**
   * Opens an editor on the given file resource.
   * <p>
   * If the page already has an editor open on the target object then that
   * editor is brought to front; otherwise, a new editor is opened. If
   * <code>activate == true</code> the editor will be activated.
   * <p>
   * 
   * @param page
   *            the page in which the editor will be opened
   * @param input
   *            the editor input
   * @param editorId
   *            the id of the editor extension to use
   * @param activate
   *            if <code>true</code> the editor will be activated
   * @return an open editor or <code>null</code> if an external editor was
   *         opened
   * @exception PartInitException
   *                if the editor could not be initialized
   * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String,
   *      boolean)
   */
  public static IEditorPart openEditor(IWorkbenchPage page, IFile input,
      String editorId, boolean activate) throws PartInitException {
    // sanity checks
    if (page == null) {
      throw new IllegalArgumentException();
    }

    // open the editor on the file
    return page.openEditor(new FileEditorInput(input), editorId, activate);
  }

  /**
   * Returns an editor descriptor appropriate for opening the given file
   * resource.
   * <p>
   * The editor descriptor is determined using a multi-step process. This
   * method will attempt to resolve the editor based on content-type bindings
   * as well as traditional name/extension bindings.
   * </p>
   * <ol>
   * <li>The file is consulted for a persistent property named
   * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be
   * used.</li>
   * <li>The workbench editor registry is consulted to determine if an editor
   * extension has been registered for the file type. If so, an instance of
   * the editor extension is opened on the file. See
   * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li>
   * <li>The operating system is consulted to determine if an in-place
   * component editor is available (e.g. OLE editor on Win32 platforms).</li>
   * <li>The operating system is consulted to determine if an external editor
   * is available.</li>
   * </ol>
   * </p>
   * 
   * @param file
   *            the file
   * @return an editor descriptor, appropriate for opening the file
   * @throws PartInitException
   *             if no editor can be found
   */
  public static IEditorDescriptor getEditorDescriptor(IFile file)
      throws PartInitException {
    return getEditorDescriptor(file, true);
  }

  /**
   * Returns an editor descriptor appropriate for opening the given file
   * resource.
   * <p>
   * The editor descriptor is determined using a multi-step process. This
   * method will attempt to resolve the editor based on content-type bindings
   * as well as traditional name/extension bindings if
   * <code>determineContentType</code>is <code>true</code>.
   * </p>
   * <ol>
   * <li>The file is consulted for a persistent property named
   * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be
   * used.</li>
   * <li>The workbench editor registry is consulted to determine if an editor
   * extension has been registered for the file type. If so, an instance of
   * the editor extension is opened on the file. See
   * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li>
   * <li>The operating system is consulted to determine if an in-place
   * component editor is available (e.g. OLE editor on Win32 platforms).</li>
   * <li>The operating system is consulted to determine if an external editor
   * is available.</li>
   * </ol>
   * </p>
   * 
   * @param file
   *            the file
   * @param determineContentType
   *            query the content type system for the content type of the file
   * @return an editor descriptor, appropriate for opening the file
   * @throws PartInitException
   *             if no editor can be found
   * @since 3.1
   */
  public static IEditorDescriptor getEditorDescriptor(IFile file,
      boolean determineContentType) throws PartInitException {

    if (file == null) {
      throw new IllegalArgumentException();
    }

    return getEditorDescriptor(file.getName(), PlatformUI.getWorkbench()
        .getEditorRegistry(), getDefaultEditor(file,
        determineContentType));
  }

  /**
   * Returns an editor descriptor appropriate for opening a file resource with
   * the given name.
   * <p>
   * The editor descriptor is determined using a multi-step process. This
   * method will attempt to infer content type from the file name.
   * </p>
   * <ol>
   * <li>The file is consulted for a persistent property named
   * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be
   * used.</li>
   * <li>The workbench editor registry is consulted to determine if an editor
   * extension has been registered for the file type. If so, an instance of
   * the editor extension is opened on the file. See
   * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li>
   * <li>The operating system is consulted to determine if an in-place
   * component editor is available (e.g. OLE editor on Win32 platforms).</li>
   * <li>The operating system is consulted to determine if an external editor
   * is available.</li>
   * </ol>
   * </p>
   * 
   * @param name
   *            the file name
   * @return an editor descriptor, appropriate for opening the file
   * @throws PartInitException
   *             if no editor can be found
   * @since 3.1
   */
  public static IEditorDescriptor getEditorDescriptor(String name)
      throws PartInitException {
    return getEditorDescriptor(name, true);
  }

  /**
   * Returns an editor descriptor appropriate for opening a file resource with
   * the given name.
   * <p>
   * The editor descriptor is determined using a multi-step process. This
   * method will attempt to infer the content type of the file if
   * <code>inferContentType</code> is <code>true</code>.
   * </p>
   * <ol>
   * <li>The file is consulted for a persistent property named
   * <code>IDE.EDITOR_KEY</code> containing the preferred editor id to be
   * used.</li>
   * <li>The workbench editor registry is consulted to determine if an editor
   * extension has been registered for the file type. If so, an instance of
   * the editor extension is opened on the file. See
   * <code>IEditorRegistry.getDefaultEditor(String)</code>.</li>
   * <li>The operating system is consulted to determine if an in-place
   * component editor is available (e.g. OLE editor on Win32 platforms).</li>
   * <li>The operating system is consulted to determine if an external editor
   * is available.</li>
   * </ol>
   * </p>
   * 
   * @param name
   *            the file name
   * @param inferContentType
   *            attempt to infer the content type from the file name if this
   *            is <code>true</code>
   * @return an editor descriptor, appropriate for opening the file
   * @throws PartInitException
   *             if no editor can be found
   * @since 3.1
   */
  public static IEditorDescriptor getEditorDescriptor(String name,
      boolean inferContentType) throws PartInitException {

    if (name == null) {
      throw new IllegalArgumentException();
    }

    IContentType contentType = inferContentType ? Platform
        .getContentTypeManager().findContentTypeFor(name) : null;
    IEditorRegistry editorReg = PlatformUI.getWorkbench()
        .getEditorRegistry();

    return getEditorDescriptor(name, editorReg, editorReg.getDefaultEditor(
        name, contentType));
  }

  /**
   * Get the editor descriptor for a given name using the editorDescriptor
   * passed in as a default as a starting point.
   * 
   * @param name
   *            The name of the element to open.
   * @param editorReg
   *            The editor registry to do the lookups from.
   * @param defaultDescriptor
   *            IEditorDescriptor or <code>null</code>
   * @return IEditorDescriptor
   * @throws PartInitException
   *             if no valid editor can be found
   * 
   * @since 3.1
   */
  private static IEditorDescriptor getEditorDescriptor(String name,
      IEditorRegistry editorReg, IEditorDescriptor defaultDescriptor)
      throws PartInitException {

    if (defaultDescriptor != null) {
      return defaultDescriptor;
    }

    IEditorDescriptor editorDesc = defaultDescriptor;

    // next check the OS for in-place editor (OLE on Win32)
    if (editorReg.isSystemInPlaceEditorAvailable(name)) {
      editorDesc = editorReg
          .findEditor(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID);
    }

    // next check with the OS for an external editor
    if (editorDesc == null
        && editorReg.isSystemExternalEditorAvailable(name)) {
      editorDesc = editorReg
          .findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
    }

    // next lookup the default text editor
    if (editorDesc == null) {
      editorDesc = editorReg
          .findEditor(IDEWorkbenchPlugin.DEFAULT_TEXT_EDITOR_ID);
    }

    // if no valid editor found, bail out
    if (editorDesc == null) {
      throw new PartInitException(
          IDEWorkbenchMessages.IDE_noFileEditorFound);
    }

    return editorDesc;
  }

  /**
   * Opens an editor on the file resource of the given marker.
   * <p>
   * If this page already has an editor open on the marker resource file that
   * editor is brought to front; otherwise, a new editor is opened.The cursor
   * and selection state of the editor are then updated from information
   * recorded in the marker.
   * </p>
   * <p>
   * If the marker contains an <code>EDITOR_ID_ATTR</code> attribute the
   * attribute value will be used to determine the editor type to be opened.
   * If not, the registered editor for the marker resource file will be used.
   * </p>
   * 
   * @param page
   *            the workbench page to open the editor in
   * @param marker
   *            the marker to open
   * @return an open editor or <code>null</code> not possible
   * @exception PartInitException
   *                if the editor could not be initialized
   * @see #openEditor(org.eclipse.ui.IWorkbenchPage,
   *      org.eclipse.core.resources.IMarker, boolean)
   */
  public static IEditorPart openEditor(IWorkbenchPage page, IMarker marker)
      throws PartInitException {
    return openEditor(page, marker, true);
  }

  /**
   * Opens an editor on the file resource of the given marker.
   * <p>
   * If this page already has an editor open on the marker resource file that
   * editor is brought to front; otherwise, a new editor is opened. If
   * <code>activate == true</code> the editor will be activated. The cursor
   * and selection state of the editor are then updated from information
   * recorded in the marker.
   * </p>
   * <p>
   * If the marker contains an <code>EDITOR_ID_ATTR</code> attribute the
   * attribute value will be used to determine the editor type to be opened.
   * If not, the registered editor for the marker resource file will be used.
   * </p>
   * 
   * @param page
   *            the workbench page to open the editor in
   * @param marker
   *            the marker to open
   * @param activate
   *            if <code>true</code> the editor will be activated
   * @return an open editor or <code>null</code> not possible
   * @exception PartInitException
   *                if the editor could not be initialized
   */
  public static IEditorPart openEditor(IWorkbenchPage page, IMarker marker,
      boolean activate) throws PartInitException {
    // sanity checks
    if (page == null || marker == null) {
      throw new IllegalArgumentException();
    }

    // get the marker resource file
    if (!(marker.getResource() instanceof IFile)) {
      IDEWorkbenchPlugin
          .log("Open editor on marker failed; marker resource not an IFile"); //$NON-NLS-1$
      return null;
    }
    IFile file = (IFile) marker.getResource();

    // get the preferred editor id from the marker
    IEditorRegistry editorReg = PlatformUI.getWorkbench()
        .getEditorRegistry();
    IEditorDescriptor editorDesc = null;
    try {
      String editorID = (String) marker.getAttribute(EDITOR_ID_ATTR);
      if (editorID != null) {
        editorDesc = editorReg.findEditor(editorID);
      }
    } catch (CoreException e) {
      // ignore this
    }

    // open the editor on the marker resource file
    IEditorPart editor = null;
    if (editorDesc == null) {
      editor = openEditor(page, file, activate);
    } else {
      editor = page.openEditor(new FileEditorInput(file), editorDesc
          .getId(), activate);
    }

    // get the editor to update its position based on the marker
    if (editor != null) {
      gotoMarker(editor, marker);
    }

    return editor;
  }

    /**
     * Opens an editor on the given IFileStore object.
     * <p>
     * Unlike the other <code>openEditor</code> methods, this one
     * can be used to open files that reside outside the workspace
     * resource set.
     * </p>
     * <p>
     * If the page already has an editor open on the target object then that
     * editor is brought to front; otherwise, a new editor is opened.
     * </p>
     * 
     * @param page
     *            the page in which the editor will be opened
     * @param fileStore 
     *            the IFileStore representing the file to open
     * @return an open editor or <code>null</code> if an external editor was opened
     * @exception PartInitException
     *                if the editor could not be initialized
     * @see org.eclipse.ui.IWorkbenchPage#openEditor(IEditorInput, String)
     * @since 3.3
     */
  public static IEditorPart openEditorOnFileStore(IWorkbenchPage page, IFileStore fileStore) throws PartInitException {
        //sanity checks
        if (page == null) {
      throw new IllegalArgumentException();
    }

        IEditorInput input = getEditorInput(fileStore);
        String editorId = getEditorId(fileStore);
        
        // open the editor on the file
        return page.openEditor(input, editorId);
    }

    /**
     * Get the id of the editor associated with the given <code>IFileStore</code>.
     * 
   * @param workbench
   *            the Workbench to use to determine the appropriate editor's id 
     * @param fileStore
     *           the <code>IFileStore</code> representing the file for which the editor id is desired
   * @return the id of the appropriate editor
   * @since 3.3
   */
  private static String getEditorId(IFileStore fileStore) {
    IEditorDescriptor descriptor;
    try {
      descriptor = IDE.getEditorDescriptor(fileStore.getName());
    } catch (PartInitException e) {
      return null;
    }
    if (descriptor != null)
      return descriptor.getId();
    return null;
  }

  /**
   * Save all dirty editors in the workbench whose editor input is a child
   * resource of one of the <code>IResource</code>'s provided. Opens a
   * dialog to prompt the user if <code>confirm</code> is true. Return true
   * if successful. Return false if the user has canceled the command.
   * 
   * @since 3.0
   * 
   * @param resourceRoots the resource roots under which editor input should
   *            be saved, other will be left dirty
   * @param confirm <code>true</code> to ask the user before saving unsaved
   *            changes (recommended), and <code>false</code> to save
   *            unsaved changes without asking
   * @return <code>true</code> if the command succeeded, and
   *         <code>false</code> if the operation was canceled by the user or
   *         an error occurred while saving
   */
  public static boolean saveAllEditors(final IResource[] resourceRoots,
      final boolean confirm) {

    if (resourceRoots.length == 0) {
      return true;
    }

    final boolean[] result = new boolean[] { true };
    SafeRunner.run(new SafeRunnable(IDEWorkbenchMessages.ErrorOnSaveAll) {
      public void run() {
        IWorkbenchWindow w = PlatformUI.getWorkbench()
            .getActiveWorkbenchWindow();
        if (w == null) {
          IWorkbenchWindow[] windows = PlatformUI.getWorkbench()
              .getWorkbenchWindows();
          if (windows.length > 0)
            w = windows[0];
        }
        if (w != null) {
          result[0] = PlatformUI.getWorkbench().saveAll(w, w,
              new SaveFilter(resourceRoots), confirm);
        }
      }
    });
    return result[0];
  }

  /**
   * Sets the default editor id for a given file. This value will be used to
   * determine the default editor descriptor for the file in future calls to
   * <code>getDefaultEditor(IFile)</code>.
   * 
   * @param file
   *            the file
   * @param editorID
   *            the editor id
   */
  public static void setDefaultEditor(IFile file, String editorID) {
    try {
      file.setPersistentProperty(EDITOR_KEY, editorID);
    } catch (CoreException e) {
      // do nothing
    }
  }

  /**
   * Returns the default editor for a given file. This method will attempt to
   * resolve the editor based on content-type bindings as well as traditional
   * name/extension bindings.
   * <p>
   * A default editor id may be registered for a specific file using
   * <code>setDefaultEditor</code>. If the given file has a registered
   * default editor id the default editor will derived from it. If not, the
   * default editor is determined by taking the file name for the file and
   * obtaining the default editor for that name.
   * </p>
   * 
   * @param file
   *            the file
   * @return the descriptor of the default editor, or <code>null</code> if
   *         not found
   */
  public static IEditorDescriptor getDefaultEditor(IFile file) {
    return getDefaultEditor(file, true);
  }

  /**
   * Returns the default editor for a given file. This method will attempt to
   * resolve the editor based on content-type bindings as well as traditional
   * name/extension bindings if <code>determineContentType</code> is
   * <code>true</code>.
   * <p>
   * A default editor id may be registered for a specific file using
   * <code>setDefaultEditor</code>. If the given file has a registered
   * default editor id the default editor will derived from it. If not, the
   * default editor is determined by taking the file name for the file and
   * obtaining the default editor for that name.
   * </p>
   * 
   * @param file
   *            the file
   * @param determineContentType
   *            determine the content type for the given file
   * @return the descriptor of the default editor, or <code>null</code> if
   *         not found
   * @since 3.1
   */
  public static IEditorDescriptor getDefaultEditor(IFile file,
      boolean determineContentType) {
    // Try file specific editor.
    IEditorRegistry editorReg = PlatformUI.getWorkbench()
        .getEditorRegistry();
    try {
      String editorID = file.getPersistentProperty(EDITOR_KEY);
      if (editorID != null) {
        IEditorDescriptor desc = editorReg.findEditor(editorID);
        if (desc != null) {
          return desc;
        }
      }
    } catch (CoreException e) {
      // do nothing
    }

    IContentType contentType = null;
    if (determineContentType) {
      contentType = getContentType(file);
    }
    // Try lookup with filename
    return editorReg.getDefaultEditor(file.getName(), contentType);
  }

  /**
   * Extracts and returns the <code>IResource</code>s in the given
   * selection or the resource objects they adapts to.
   * 
   * @param originalSelection
   *            the original selection, possibly empty
   * @return list of resources (element type: <code>IResource</code>),
   *         possibly empty
   */
  public static List computeSelectedResources(
      IStructuredSelection originalSelection) {
    List resources = null;
    for (Iterator e = originalSelection.iterator(); e.hasNext();) {
      Object next = e.next();
      Object resource = null;
      if (next instanceof IResource) {
        resource = next;
      } else if (next instanceof IAdaptable) {
        resource = ((IAdaptable) next).getAdapter(IResource.class);
      }
      if (resource != null) {
        if (resources == null) {
          // lazy init to avoid creating empty lists
          // assume selection contains mostly resources most times
          resources = new ArrayList(originalSelection.size());
        }
        resources.add(resource);
      }
    }
    if (resources == null) {
      return Collections.EMPTY_LIST;
    }
    return resources;

  }

  /**
   * Return the content type for the given file.
   * 
   * @param file
   *            the file to test
   * @return the content type, or <code>null</code> if it cannot be
   *         determined.
   * @since 3.1
   */
  public static IContentType getContentType(IFile file) {
    try {
      UIStats.start(UIStats.CONTENT_TYPE_LOOKUP, file.getName());
      IContentDescription contentDescription = file
          .getContentDescription();
      if (contentDescription == null) {
        return null;
      }
      return contentDescription.getContentType();
    } catch (CoreException e) {
      return null;
    } finally {
      UIStats.end(UIStats.CONTENT_TYPE_LOOKUP, file, file.getName());
    }
  }

  /**
   * Guess at the content type of the given file based on the filename.
   * 
   * @param file
   *            the file to test
   * @return the content type, or <code>null</code> if it cannot be
   *         determined.
   * @since 3.2
   */
  public static IContentType guessContentType(IFile file) {
    String fileName = file.getName();
    try {
      UIStats.start(UIStats.CONTENT_TYPE_LOOKUP, fileName);
      IContentTypeMatcher matcher = file.getProject()
          .getContentTypeMatcher();
      return matcher.findContentTypeFor(fileName);
    } catch (CoreException e) {
      return null;
    } finally {
      UIStats.end(UIStats.CONTENT_TYPE_LOOKUP, file, fileName);
    }
  }

  /**
   * Prompt the user to inform them of the possible side effects of an
   * operation on resources. Do not prompt for side effects from ignored model
   * providers. A model provider can be ignored if it is the client calling
   * this API. Any message from the provided model provider id or any model
   * providers it extends will be ignored.
   * 
   * @param shell
   *            the shell to parent the prompt dialog
   * @param title
   *            the title of the dialog
   * @param message
   *            the message for the dialog
   * @param delta
   *            a delta built using an
   *            {@link IResourceChangeDescriptionFactory}
   * @param ignoreModelProviderIds
   *            model providers to be ignored
   * @param syncExec
   *            prompt in a sync exec (required when called from a non-UI
   *            thread)
   * @return whether the user chose to continue
   * @since 3.2
   */
  public static boolean promptToConfirm(final Shell shell,
      final String title, String message, IResourceDelta delta,
      String[] ignoreModelProviderIds, boolean syncExec) {
    IStatus status = ResourceChangeValidator.getValidator().validateChange(
        delta, null);
    if (status.isOK()) {
      return true;
    }
    final IStatus displayStatus;
    if (status.isMultiStatus()) {
      List result = new ArrayList();
      IStatus[] children = status.getChildren();
      for (int i = 0; i < children.length; i++) {
        IStatus child = children[i];
        if (!isIgnoredStatus(child, ignoreModelProviderIds)) {
          result.add(child);
        }
      }
      if (result.isEmpty()) {
        return true;
      }
      if (result.size() == 1) {
        displayStatus = (IStatus) result.get(0);
      } else {
        displayStatus = new MultiStatus(status.getPlugin(), status
            .getCode(), (IStatus[]) result
            .toArray(new IStatus[result.size()]), status
            .getMessage(), status.getException());
      }
    } else {
      if (isIgnoredStatus(status, ignoreModelProviderIds)) {
        return true;
      }
      displayStatus = status;
    }

    if (message == null) {
      message = IDEWorkbenchMessages.IDE_sideEffectWarning;
    }
    final String dialogMessage = NLS.bind(
        IDEWorkbenchMessages.IDE_areYouSure, message);

    final boolean[] result = new boolean[] { false };
    Runnable runnable = new Runnable() {
      public void run() {
        ErrorDialog dialog = new ErrorDialog(shell, title,
            dialogMessage, displayStatus, IStatus.ERROR
                | IStatus.WARNING | IStatus.INFO) {
          protected void createButtonsForButtonBar(Composite parent) {
            createButton(parent, IDialogConstants.YES_ID,
                IDialogConstants.YES_LABEL, false);
            createButton(parent, IDialogConstants.NO_ID,
                IDialogConstants.NO_LABEL, true);
            createDetailsButton(parent);
          }

          /*
           * (non-Javadoc)
           * 
           * @see org.eclipse.jface.dialogs.ErrorDialog#buttonPressed(int)
           */
          protected void buttonPressed(int id) {
            if (id == IDialogConstants.YES_ID) {
              super.buttonPressed(IDialogConstants.OK_ID);
            } else if (id == IDialogConstants.NO_ID) {
              super.buttonPressed(IDialogConstants.CANCEL_ID);
            }
            super.buttonPressed(id);
          }
        };
        int code = dialog.open();
        result[0] = code == 0;
      }
    };
    if (syncExec) {
      shell.getDisplay().syncExec(runnable);
    } else {
      runnable.run();
    }
    return result[0];
  }

  private static boolean isIgnoredStatus(IStatus status,
      String[] ignoreModelProviderIds) {
    if (ignoreModelProviderIds == null) {
      return false;
    }
    if (status instanceof ModelStatus) {
      ModelStatus ms = (ModelStatus) status;
      for (int i = 0; i < ignoreModelProviderIds.length; i++) {
        String id = ignoreModelProviderIds[i];
        if (ms.getModelProviderId().equals(id)) {
          return true;
        }
        IModelProviderDescriptor desc = ModelProvider
            .getModelProviderDescriptor(id);
        String[] extended = desc.getExtendedModels();
        if (isIgnoredStatus(status, extended)) {
          return true;
        }
      }
    }
    return false;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.