Package org.eclipse.ui.internal.registry

Source Code of org.eclipse.ui.internal.registry.PerspectiveRegistry

/*******************************************************************************
* Copyright (c) 2000, 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.internal.registry;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.ClosePerspectiveAction;
import org.eclipse.ui.internal.IPreferenceConstants;
import org.eclipse.ui.internal.Workbench;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.WorkbenchPage;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.misc.StatusUtil;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.statushandlers.StatusManager;

/**
* Perspective registry.
*/
public class PerspectiveRegistry implements IPerspectiveRegistry,
    IExtensionChangeHandler {
  private String defaultPerspID;

  private static final String EXT = "_persp.xml"; //$NON-NLS-1$

  private static final String ID_DEF_PERSP = "PerspectiveRegistry.DEFAULT_PERSP"; //$NON-NLS-1$

  private static final String PERSP = "_persp"; //$NON-NLS-1$

  private static final char SPACE_DELIMITER = ' ';

  private List perspectives = new ArrayList(10);

  // keep track of the perspectives the user has selected to remove or revert
  private ArrayList perspToRemove = new ArrayList(5);

  private IPropertyChangeListener preferenceListener;

  /**
   * Construct a new registry.
   */
  public PerspectiveRegistry() {
    IExtensionTracker tracker = PlatformUI.getWorkbench()
        .getExtensionTracker();
    tracker.registerHandler(this, null);

    initializePreferenceChangeListener();
    WorkbenchPlugin.getDefault().getPreferenceStore()
        .addPropertyChangeListener(preferenceListener);

  }

  /**
   * Initialize the preference change listener.
   */
  private void initializePreferenceChangeListener() {
    preferenceListener = new IPropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent event) {
        /*
         * To ensure the that no custom perspective definitions are
         * deleted when preferences are imported, merge old and new
         * values
         */
        if (event.getProperty().endsWith(PERSP)) {
          /* A Perspective is being changed, merge */
          mergePerspectives(event);
        } else if (event.getProperty().equals(
            IPreferenceConstants.PERSPECTIVES)) {
          /* The list of perpsectives is being changed, merge */
          updatePreferenceList((IPreferenceStore) event.getSource());
        }
      }

      private void mergePerspectives(PropertyChangeEvent event) {
        IPreferenceStore store = (IPreferenceStore) event.getSource();
        if (event.getNewValue() == null
            || event.getNewValue().equals("")) { //$NON-NLS-1$
          /*
           * Perpsective is being removed; if the user has deleted or
           * reverted a custom perspective, let the change pass
           * through. Otherwise, restore the custom perspective entry
           */

          // Find the matching descriptor in the registry
          IPerspectiveDescriptor[] perspectiveList = getPerspectives();
          for (int i = 0; i < perspectiveList.length; i++) {
            String id = perspectiveList[i].getId();
            if (event.getProperty().equals(id + PERSP)) { // found
              // descriptor
              // see if the perspective has been flagged for
              // reverting or deleting
              if (!perspToRemove.contains(id)) { // restore
                store.setValue(id + PERSP, (String) event
                    .getOldValue());
              } else { // remove element from the list
                perspToRemove.remove(id);
              }
            }
          }
        } else if ((event.getOldValue() == null || event.getOldValue()
            .equals(""))) { //$NON-NLS-1$

          /*
           * New perspective is being added, update the
           * perspectiveRegistry to contain the new custom perspective
           */

          String id = event.getProperty().substring(0,
              event.getProperty().lastIndexOf(PERSP));
          if (findPerspectiveWithId(id) == null) {
            // perspective does not already exist in registry, add
            // it
            PerspectiveDescriptor desc = new PerspectiveDescriptor(
                null, null, null);
            StringReader reader = new StringReader((String) event
                .getNewValue());
            try {
              XMLMemento memento = XMLMemento
                  .createReadRoot(reader);
              desc.restoreState(memento);
              addPerspective(desc);
            } catch (WorkbenchException e) {
              unableToLoadPerspective(e.getStatus());
            }
          }
        }
        /* If necessary, add to the list of perspectives */
        updatePreferenceList(store);
      }

      /*
       * Update the list of perspectives from the registry. This will be
       * called for each perspective during an import preferences, but is
       * necessary to ensure the perspectives list stays consistent with
       * the registry
       */
      private void updatePreferenceList(IPreferenceStore store) {
        IPerspectiveDescriptor[] perspectiveList = getPerspectives();
        StringBuffer perspBuffer = new StringBuffer();
        for (int i = 0; i < perspectiveList.length; i++) {
          PerspectiveDescriptor desc = (PerspectiveDescriptor) perspectiveList[i];
          if (hasCustomDefinition(desc)) {
            perspBuffer.append(desc.getId())
                .append(SPACE_DELIMITER);
          }
        }
        String newList = perspBuffer.toString().trim();
        store.setValue(IPreferenceConstants.PERSPECTIVES, newList);
      }
    };
  }

  /**
   * Adds a perspective. This is typically used by the reader.
   *
   * @param desc
   */
  public void addPerspective(PerspectiveDescriptor desc) {
    if (desc == null) {
      return;
    }
    add(desc);
  }

  /**
   * @param desc
   */
  private void add(PerspectiveDescriptor desc) {
    perspectives.add(desc);
    IConfigurationElement element = desc.getConfigElement();
    if (element != null) {
      PlatformUI.getWorkbench().getExtensionTracker().registerObject(
          element.getDeclaringExtension(), desc,
          IExtensionTracker.REF_WEAK);
    }
  }

  /**
   * Create a new perspective.
   *
   * @param label
   *            the name of the new descriptor
   * @param originalDescriptor
   *            the descriptor on which to base the new descriptor
   * @return a new perspective descriptor or <code>null</code> if the
   *         creation failed.
   */
  public PerspectiveDescriptor createPerspective(String label,
      PerspectiveDescriptor originalDescriptor) {
    // Sanity check to avoid invalid or duplicate labels.
    if (!validateLabel(label)) {
      return null;
    }
    if (findPerspectiveWithLabel(label) != null) {
      return null;
    }

    // Calculate ID.
    String id = label.replace(' ', '_');
    id = id.trim();

    // Create descriptor.
    PerspectiveDescriptor desc = new PerspectiveDescriptor(id, label,
        originalDescriptor);
    add(desc);
    return desc;
  }

  /**
   * Reverts a list of perspectives back to the plugin definition
   *
   * @param perspToRevert
   */
  public void revertPerspectives(ArrayList perspToRevert) {
    // indicate that the user is removing these perspectives
    for (int i = 0; i < perspToRevert.size(); i++) {
      PerspectiveDescriptor desc = (PerspectiveDescriptor) perspToRevert
          .get(i);
      perspToRemove.add(desc.getId());
      desc.revertToPredefined();
    }
  }

  /**
   * Deletes a list of perspectives
   *
   * @param perspToDelete
   */
  public void deletePerspectives(ArrayList perspToDelete) {
    for (int i = 0; i < perspToDelete.size(); i++) {
      deletePerspective((IPerspectiveDescriptor) perspToDelete.get(i));
    }
  }

  /**
   * Delete a perspective. Has no effect if the perspective is defined in an
   * extension.
   *
   * @param in
   */
  public void deletePerspective(IPerspectiveDescriptor in) {
    PerspectiveDescriptor desc = (PerspectiveDescriptor) in;
    // Don't delete predefined perspectives
    if (!desc.isPredefined()) {
      perspToRemove.add(desc.getId());
      perspectives.remove(desc);
      desc.deleteCustomDefinition();
      verifyDefaultPerspective();
    }
  }

  /**
   * Delete a perspective. This will remove perspectives defined in
   * extensions.
   *
   * @param desc
   *            the perspective to delete
   * @since 3.1
   */
  private void internalDeletePerspective(PerspectiveDescriptor desc) {
    perspToRemove.add(desc.getId());
    perspectives.remove(desc);
    desc.deleteCustomDefinition();
    verifyDefaultPerspective();
  }

  /**
   * Removes the custom definition of a perspective from the preference store
   *
   * @param desc
   */
  /* package */
  void deleteCustomDefinition(PerspectiveDescriptor desc) {
    // remove the entry from the preference store.
    IPreferenceStore store = WorkbenchPlugin.getDefault()
        .getPreferenceStore();

    /*
     * To delete the perspective definition from the preference store, use
     * the setToDefault method. Since no default is defined, this will
     * remove the entry
     */
    store.setToDefault(desc.getId() + PERSP);

  }

  /**
   * Method hasCustomDefinition.
   *
   * @param desc
   */
  /* package */
  boolean hasCustomDefinition(PerspectiveDescriptor desc) {
    IPreferenceStore store = WorkbenchPlugin.getDefault()
        .getPreferenceStore();
    return store.contains(desc.getId() + PERSP);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.IPerspectiveRegistry#findPerspectiveWithId(java.lang.String)
   */
  public IPerspectiveDescriptor findPerspectiveWithId(String id) {
    for (Iterator i = perspectives.iterator(); i.hasNext();) {
      PerspectiveDescriptor desc = (PerspectiveDescriptor) i.next();
      if (desc.getId().equals(id)) {
        return desc;
      }
    }

    return null;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.IPerspectiveRegistry#findPerspectiveWithLabel(java.lang.String)
   */
  public IPerspectiveDescriptor findPerspectiveWithLabel(String label) {
    for (Iterator i = perspectives.iterator(); i.hasNext();) {
      PerspectiveDescriptor desc = (PerspectiveDescriptor) i.next();
      if (desc.getLabel().equals(label)) {
        return desc;
      }
    }
    return null;
  }

  /**
   * @see IPerspectiveRegistry#getDefaultPerspective()
   */
  public String getDefaultPerspective() {
    return defaultPerspID;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.IPerspectiveRegistry#getPerspectives()
   */
  public IPerspectiveDescriptor[] getPerspectives() {
    return (IPerspectiveDescriptor[]) perspectives
        .toArray(new IPerspectiveDescriptor[perspectives.size()]);
  }

  /**
   * Loads the registry.
   */
  public void load() {
    // Load the registries.
    loadPredefined();
    loadCustom();

    // Get default perspective.
    // Get it from the R1.0 dialog settings first. Fixes bug 17039
    IDialogSettings dialogSettings = WorkbenchPlugin.getDefault()
        .getDialogSettings();
    String str = dialogSettings.get(ID_DEF_PERSP);
    if (str != null && str.length() > 0) {
      setDefaultPerspective(str);
      dialogSettings.put(ID_DEF_PERSP, ""); //$NON-NLS-1$
    }
    verifyDefaultPerspective();
  }

  /**
   * Read children from the file system.
   */
  private void loadCustom() {
    Reader reader = null;

    /* Get the entries from the Preference store */
    IPreferenceStore store = WorkbenchPlugin.getDefault()
        .getPreferenceStore();

    /* Get the space-delimited list of custom perspective ids */
    String customPerspectives = store
        .getString(IPreferenceConstants.PERSPECTIVES);
    String[] perspectivesList = StringConverter.asArray(customPerspectives);

    for (int i = 0; i < perspectivesList.length; i++) {
      try {
        String xmlString = store.getString(perspectivesList[i] + PERSP);
        if (xmlString != null && xmlString.length() != 0) {
          reader = new StringReader(xmlString);
        }

        // Restore the layout state.
        XMLMemento memento = XMLMemento.createReadRoot(reader);
        PerspectiveDescriptor newPersp = new PerspectiveDescriptor(
            null, null, null);
        newPersp.restoreState(memento);
        String id = newPersp.getId();
        IPerspectiveDescriptor oldPersp = findPerspectiveWithId(id);
        if (oldPersp == null) {
          add(newPersp);
        }
        reader.close();
      } catch (IOException e) {
        unableToLoadPerspective(null);
      } catch (WorkbenchException e) {
        unableToLoadPerspective(e.getStatus());
      }
    }

    // Get the entries from files, if any
    // if -data @noDefault specified the state location may not be
    // initialized
    IPath path = WorkbenchPlugin.getDefault().getDataLocation();
    if (path == null) {
      return;
    }

    File folder = path.toFile();

    if (folder.isDirectory()) {
      File[] fileList = folder.listFiles();
      int nSize = fileList.length;
      for (int nX = 0; nX < nSize; nX++) {
        File file = fileList[nX];
        if (file.getName().endsWith(EXT)) {
          // get the memento
          InputStream stream = null;
          try {
            stream = new FileInputStream(file);
            reader = new BufferedReader(new InputStreamReader(
                stream, "utf-8")); //$NON-NLS-1$

            // Restore the layout state.
            XMLMemento memento = XMLMemento.createReadRoot(reader);
            PerspectiveDescriptor newPersp = new PerspectiveDescriptor(
                null, null, null);
            newPersp.restoreState(memento);
            IPerspectiveDescriptor oldPersp = findPerspectiveWithId(newPersp
                .getId());
            if (oldPersp == null) {
              add(newPersp);
            }

            // save to the preference store
            saveCustomPersp(newPersp, memento);

            // delete the file
            file.delete();

            reader.close();
            stream.close();
          } catch (IOException e) {
            unableToLoadPerspective(null);
          } catch (WorkbenchException e) {
            unableToLoadPerspective(e.getStatus());
          }
        }
      }
    }
  }

  /**
   * @param status
   */
  private void unableToLoadPerspective(IStatus status) {
    String msg = WorkbenchMessages.Perspective_errorLoadingState;
    if (status == null) {
      IStatus errStatus = new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH, msg);
        StatusManager.getManager().handle(errStatus, StatusManager.SHOW);
    } else {
      IStatus errStatus = StatusUtil.newStatus(status, msg);
        StatusManager.getManager().handle(errStatus, StatusManager.SHOW);
    }
  }

  /**
   * Saves a custom perspective definition to the preference store.
   *
   * @param desc
   *            the perspective
   * @param memento
   *            the memento to save to
   * @throws IOException
   */
  public void saveCustomPersp(PerspectiveDescriptor desc, XMLMemento memento)
      throws IOException {

    IPreferenceStore store = WorkbenchPlugin.getDefault()
        .getPreferenceStore();

    // Save it to the preference store.
    Writer writer = new StringWriter();

    memento.save(writer);
    writer.close();
    store.setValue(desc.getId() + PERSP, writer.toString());

  }

  /**
   * Gets the Custom perspective definition from the preference store.
   *
   * @param id
   *            the id of the perspective to find
   * @return IMemento a memento containing the perspective description
   *
   * @throws WorkbenchException
   * @throws IOException
   */
  public IMemento getCustomPersp(String id) throws WorkbenchException,
      IOException {
    Reader reader = null;

    IPreferenceStore store = WorkbenchPlugin.getDefault()
        .getPreferenceStore();
    String xmlString = store.getString(id + PERSP);
    if (xmlString != null && xmlString.length() != 0) { // defined in store
      reader = new StringReader(xmlString);
    }
    XMLMemento memento = XMLMemento.createReadRoot(reader);
    reader.close();
    return memento;
  }

  /**
   * Read children from the plugin registry.
   */
  private void loadPredefined() {
    PerspectiveRegistryReader reader = new PerspectiveRegistryReader(this);
    reader.readPerspectives(Platform.getExtensionRegistry());
  }

  /**
   * @see IPerspectiveRegistry#setDefaultPerspective(String)
   */
  public void setDefaultPerspective(String id) {
    IPerspectiveDescriptor desc = findPerspectiveWithId(id);
    if (desc != null) {
      defaultPerspID = id;
      PrefUtil.getAPIPreferenceStore().setValue(
          IWorkbenchPreferenceConstants.DEFAULT_PERSPECTIVE_ID, id);
    }
  }

  /**
   * Return <code>true</code> if a label is valid. This checks only the
   * given label in isolation. It does not check whether the given label is
   * used by any existing perspectives.
   *
   * @param label
   *            the label to test
   * @return whether the label is valid
   */
  public boolean validateLabel(String label) {
    label = label.trim();
    if (label.length() <= 0) {
      return false;
    }
    return true;
  }

  /**
   * Verifies the id of the default perspective. If the default perspective is
   * invalid use the workbench default.
   */
  private void verifyDefaultPerspective() {
    // Step 1: Try current defPerspId value.
    IPerspectiveDescriptor desc = null;
    if (defaultPerspID != null) {
      desc = findPerspectiveWithId(defaultPerspID);
    }
    if (desc != null) {
      return;
    }

    // Step 2. Read default value.
    String str = PrefUtil.getAPIPreferenceStore().getString(
        IWorkbenchPreferenceConstants.DEFAULT_PERSPECTIVE_ID);
    if (str != null && str.length() > 0) {
      desc = findPerspectiveWithId(str);
    }
    if (desc != null) {
      defaultPerspID = str;
      return;
    }

    // Step 3. Use application-specific default
    defaultPerspID = Workbench.getInstance().getDefaultPerspectiveId();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.IPerspectiveRegistry#clonePerspective(java.lang.String,
   *      java.lang.String, org.eclipse.ui.IPerspectiveDescriptor)
   */
  public IPerspectiveDescriptor clonePerspective(String id, String label,
      IPerspectiveDescriptor originalDescriptor) {

    // Check for invalid labels
    if (label == null || !(label.trim().length() > 0)) {
      throw new IllegalArgumentException();
    }

    // Check for duplicates
    IPerspectiveDescriptor desc = findPerspectiveWithId(id);
    if (desc != null) {
      throw new IllegalArgumentException();
    }

    // Create descriptor.
    desc = new PerspectiveDescriptor(id, label,
        (PerspectiveDescriptor) originalDescriptor);
    add((PerspectiveDescriptor) desc);
    return desc;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ui.IPerspectiveRegistry#revertPerspective(org.eclipse.ui.IPerspectiveDescriptor)
   */
  public void revertPerspective(IPerspectiveDescriptor perspToRevert) {
    PerspectiveDescriptor desc = (PerspectiveDescriptor) perspToRevert;
    perspToRemove.add(desc.getId());
    desc.revertToPredefined();
  }

  /**
   * Dispose the receiver.
   */
  public void dispose() {
    PlatformUI.getWorkbench().getExtensionTracker().unregisterHandler(this);
    WorkbenchPlugin.getDefault().getPreferenceStore()
        .removePropertyChangeListener(preferenceListener);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension,
   *      java.lang.Object[])
   */
  public void removeExtension(IExtension source, Object[] objects) {
    for (int i = 0; i < objects.length; i++) {
      if (objects[i] instanceof PerspectiveDescriptor) {
        // close the perspective in all windows
        IWorkbenchWindow[] windows = PlatformUI.getWorkbench()
            .getWorkbenchWindows();
        PerspectiveDescriptor desc = (PerspectiveDescriptor) objects[i];
        for (int w = 0; w < windows.length; ++w) {
          IWorkbenchWindow window = windows[w];
          IWorkbenchPage[] pages = window.getPages();
          for (int p = 0; p < pages.length; ++p) {
            WorkbenchPage page = (WorkbenchPage) pages[p];
            ClosePerspectiveAction.closePerspective(page, page
                .findPerspective(desc));
          }
        }

        // ((Workbench)PlatformUI.getWorkbench()).getPerspectiveHistory().removeItem(desc);

        internalDeletePerspective(desc);
      }

    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker,
   *      org.eclipse.core.runtime.IExtension)
   */
  public void addExtension(IExtensionTracker tracker,
      IExtension addedExtension) {
    IConfigurationElement[] addedElements = addedExtension
        .getConfigurationElements();
    for (int i = 0; i < addedElements.length; i++) {
      PerspectiveRegistryReader reader = new PerspectiveRegistryReader(
          this);
      reader.readElement(addedElements[i]);
    }
  }
}
TOP

Related Classes of org.eclipse.ui.internal.registry.PerspectiveRegistry

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.