Package org.eclipse.jst.pagedesigner.ui.common.sash

Source Code of org.eclipse.jst.pagedesigner.ui.common.sash.SashEditorPart

/*******************************************************************************
* Copyright (c) 2006 Sybase, Inc. 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:
*     Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.pagedesigner.ui.common.sash;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jst.jsf.common.ui.internal.guiutils.SWTUtils;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.INestableKeyBindingService;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
import org.eclipse.ui.part.MultiPageEditorSite;

/**
* This class emulates the MultiPageEditorPart. But instead of using multipage,
* it use SashForm to separate the editors.
*
* @author mengbo
*/
public abstract class SashEditorPart extends EditorPart {
  private int _orientation = SWT.VERTICAL;

  private SashForm _sashForm;

  /**
   * List of nested editors. Element type: IEditorPart. Need to hang onto them
   * here, in addition to using get/setData on the items, because dispose()
   * needs to access them, but widgetry has already been disposed at that
   * point.
   */
  private ArrayList _nestedEditors = new ArrayList(3);

  private Map _editorToComposite = new HashMap();

  private IEditorPart _activeEditor = null;

  /**
   * Creates and adds a new page containing the given editor to this
   * multi-page editor. The page is added at the given index. This also hooks
   * a property change listener on the nested editor.
   *
   * @param editor
   *            the nested editor
   * @param input
   *            the input for the nested editor
   * @exception PartInitException
   *                if a new page could not be created
   * @see org.eclipse.ui.part.MultiPageEditorPart#handlePropertyChange(int) the handler for
   *      property change events from the nested editor
   */
  public void addPage(final IEditorPart editor, IEditorInput input)
      throws PartInitException {
    IEditorSite site = createSite(editor);
    // call init first so that if an exception is thrown, we have created no
    // new widgets
    editor.init(site, input);
    final Composite parent1 = new Composite(getContainer(), SWT.NONE);
    FillLayout fillLayout = new FillLayout();
    fillLayout.marginWidth = fillLayout.marginHeight = 1;
    parent1.setLayout(fillLayout);

    parent1.addListener(SWT.Activate, new Listener() {
      public void handleEvent(Event event) {
        if (event.type == SWT.Activate) {
          activeEditorChanged(editor);
          parent1.setBackground(ColorConstants.green);
        }
      }
    });
    parent1.addListener(SWT.Deactivate, new Listener() {
      public void handleEvent(Event event) {
        parent1.setBackground(ColorConstants.titleInactiveBackground);
      }
    });
    SWTUtils.workaroundResize(parent1);
    editor.createPartControl(parent1);
    editor.addPropertyListener(new IPropertyListener() {
      public void propertyChanged(Object source, int propertyId) {
        SashEditorPart.this.handlePropertyChange(propertyId);
      }
    });

    _nestedEditors.add(editor);
    _editorToComposite.put(editor, parent1);

    connectPage(editor);
  }

  /**
   * @param editor
   */
  protected void connectPage(IEditorPart editor) {
    ISelectionProvider editSelectionProvider = editor.getSite()
        .getSelectionProvider();
    if (editSelectionProvider instanceof IPostSelectionProvider) {
      ((IPostSelectionProvider) editSelectionProvider)
          .addPostSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
              ((SashEditorSelectionProvider) getSite()
                  .getSelectionProvider())
                  .firePostSelectionChanged(event);
            }
          });
    } else {
      editSelectionProvider
          .addSelectionChangedListener(new ISelectionChangedListener() {

            public void selectionChanged(SelectionChangedEvent event) {
              ((SashEditorSelectionProvider) getSite()
                  .getSelectionProvider())
                  .fireSelectionChanged(event);
            }
          });
    }
  }

  /**
   * Creates an empty container. Creates a CTabFolder with no style bits set,
   * and hooks a selection listener which calls <code>pageChange()</code>
   * whenever the selected tab changes.
   *
   * @param parent
   *            The composite in which the container tab folder should be
   *            created; must not be <code>null</code>.
   * @return a new container
   */
  private SashForm createContainer(Composite parent) {
    // use SWT.FLAT style so that an extra 1 pixel border is not reserved
    // inside the folder
    SashForm newContainer = new SashForm(parent, SWT.NONE);
    SWTUtils.workaroundResize(newContainer);
    newContainer.setOrientation(_orientation);
    return newContainer;
  }

  /**
   * @throws PartInitException
   */
  abstract protected void createPages() throws PartInitException;

  /**
   * The <code>MultiPageEditor</code> implementation of this
   * <code>IWorkbenchPart</code> method creates the control for the
   * multi-page editor by calling <code>createContainer</code>, then
   * <code>createPages</code>. Subclasses should implement
   * <code>createPages</code> rather than overriding this method.
   *
   * @param parent
   *            The parent in which the editor should be created; must not be
   *            <code>null</code>.
   */
  public final void createPartControl(Composite parent) {
    this._sashForm = createContainer(parent);

    try {
      createPages();
    } catch (PartInitException ex) {
      ex.printStackTrace();
    }
    // set the active page (page 0 by default), unless it has already been
    // done
    if (getActiveEditor() == null) {
      if (!_nestedEditors.isEmpty()) {
        setActiveEditor((IEditorPart) _nestedEditors.get(0));
      }
    }
  }

  /**
   * Creates the site for the given nested editor. The
   * <code>MultiPageEditorPart</code> implementation of this method creates
   * an instance of <code>MultiPageEditorSite</code>. Subclasses may
   * reimplement to create more specialized sites.
   *
   * @param editor
   *            the nested editor
   * @return the editor site
   */
  protected IEditorSite createSite(IEditorPart editor) {
    return new SashEditorSite(this, editor);
  }

  /**
   * The <code>MultiPageEditorPart</code> implementation of this
   * <code>IWorkbenchPart</code> method disposes all nested editors.
   * Subclasses may extend.
   */
  public void dispose() {
    _activeEditor = null;
    for (int i = 0; i < _nestedEditors.size(); ++i) {
      IEditorPart editor = (IEditorPart) _nestedEditors.get(i);
      disposePart(editor);
    }
    _nestedEditors.clear();
    _editorToComposite.clear();
  }

  /**
   * Returns the active nested editor if there is one.
   * <p>
   * Subclasses should not override this method
   * </p>
   *
   * @return the active nested editor, or <code>null</code> if none
   */
  public IEditorPart getActiveEditor() {
    return _activeEditor;
  }

  /**
   * Returns the composite control containing this multi-page editor's pages.
   * This should be used as the parent when creating controls for the
   * individual pages. That is, when calling <code>addPage(Control)</code>,
   * the passed control should be a child of this container.
   * <p>
   * Warning: Clients should not assume that the container is any particular
   * subclass of Composite. The actual class used may change in order to
   * improve the look and feel of multi-page editors. Any code making
   * assumptions on the particular subclass would thus be broken.
   * </p>
   * <p>
   * Subclasses should not override this method
   * </p>
   *
   * @return the composite, or <code>null</code> if
   *         <code>createPartControl</code> has not been called yet
   */
  protected Composite getContainer() {
    return _sashForm;
  }

  /**
   * Returns the editor for the given page index. The page index must be
   * valid.
   *
   * @param pageIndex
   *            the index of the page
   * @return the editor for the specified page, or <code>null</code> if the
   *         specified page was not created with
   *         <code>addPage(IEditorPart,IEditorInput)</code>
   */
  protected IEditorPart getEditor(int pageIndex) {
    return (IEditorPart) _nestedEditors.get(pageIndex);
  }

  /**
   * Handles a property change notification from a nested editor. The default
   * implementation simply forwards the change to listeners on this multi-page
   * editor by calling <code>firePropertyChange</code> with the same
   * property id. For example, if the dirty state of a nested editor changes
   * (property id <code>IEditorPart.PROP_DIRTY</code>), this method handles
   * it by firing a property change event for
   * <code>IEditorPart.PROP_DIRTY</code> to property listeners on this
   * multi-page editor.
   * <p>
   * Subclasses may extend or reimplement this method.
   * </p>
   *
   * @param propertyId
   *            the id of the property that changed
   */
  protected void handlePropertyChange(int propertyId) {
    firePropertyChange(propertyId);
  }

  /**
   * The <code>MultiPageEditorPart</code> implementation of this
   * <code>IEditorPart</code> method sets its site to the given site, its
   * input to the given input, and the site's selection provider to a
   * <code>MultiPageSelectionProvider</code>. Subclasses may extend this
   * method.
   *
   * @param site
   *            The site for which this part is being created; must not be
   *            <code>null</code>.
   * @param input
   *            The input on which this editor should be created; must not be
   *            <code>null</code>.
   * @throws PartInitException
   *             If the initialization of the part fails -- currently never.
   */
  public void init(IEditorSite site, IEditorInput input)
      throws PartInitException {
    setSite(site);
    setInput(input);
    site.setSelectionProvider(new SashEditorSelectionProvider(this));
  }

  /**
   * The <code>MultiPageEditorPart</code> implementation of this
   * <code>IEditorPart</code> method returns whether the contents of any of
   * this multi-page editor's nested editors have changed since the last save.
   * Pages created with <code>addPage(Control)</code> are ignored.
   * <p>
   * Subclasses may extend or reimplement this method.
   * </p>
   *
   * @return <code>true</code> if any of the nested editors are dirty;
   *         <code>false</code> otherwise.
   */
  public boolean isDirty() {
    // use nestedEditors to avoid SWT requests; see bug 12996
    for (Iterator i = _nestedEditors.iterator(); i.hasNext();) {
      IEditorPart editor = (IEditorPart) i.next();
      if (editor.isDirty()) {
        return true;
      }
    }
    return false;
  }

  /**
   * Notifies this multi-page editor that the page with the given id has been
   * activated. This method is called when the user selects a different tab.
   * <p>
   * The <code>MultiPageEditorPart</code> implementation of this method sets
   * focus to the new page, and notifies the action bar contributor (if there
   * is one). This checks whether the action bar contributor is an instance of
   * <code>MultiPageEditorActionBarContributor</code>, and, if so, calls
   * <code>setActivePage</code> with the active nested editor. This also
   * fires a selection change event if required.
   * </p>
   * <p>
   * Subclasses may extend this method.
   * </p>
   * @param activeEditor
   *
   */
  protected void activeEditorChanged(IEditorPart activeEditor) {
    setActiveEditor(activeEditor);
    setFocus();

    IEditorSite site = getEditorSite();
    while (site != null) {
      IEditorActionBarContributor contributor = site
          .getActionBarContributor();
      if (contributor instanceof MultiPageEditorActionBarContributor) {
        ((MultiPageEditorActionBarContributor) contributor)
            .setActivePage(activeEditor);
      }
      if (site instanceof MultiPageEditorSite) {
        site = (IEditorSite) ((MultiPageEditorSite) site)
            .getMultiPageEditor().getSite();
      } else if (site instanceof SashEditorSite) {
        site = (IEditorSite) ((SashEditorSite) site).getSashEditor()
            .getSite();
      } else {
        site = null;
      }
    }

    if (activeEditor != null) {
      // Workaround for 1GAUS7C: ITPUI:ALL - Editor not activated when
      // restored from previous session
      // do not need second if once fixed
      ISelectionProvider selectionProvider = activeEditor.getSite()
          .getSelectionProvider();
      if (selectionProvider != null) {
        SelectionChangedEvent event = new SelectionChangedEvent(
            selectionProvider, selectionProvider.getSelection());
        ((SashEditorSelectionProvider) getSite().getSelectionProvider())
            .fireSelectionChanged(event);
      }
    }
  }

  /**
   * Disposes the given part and its site.
   *
   * @param part
   *            The part to dispose; must not be <code>null</code>.
   */
  private void disposePart(final IWorkbenchPart part) {
        SafeRunner.run(new SafeRunnable() {
      public void run() {
        if (part.getSite() instanceof SashEditorSite) {
          SashEditorSite partSite = (SashEditorSite) part.getSite();
          partSite.dispose();
        }
        part.dispose();
      }

      public void handleException(Throwable e) {
        // Exception has already being logged by Core. Do nothing.
      }
    });
  }

  /**
   * Sets the currently active page.
   * @param part
   *
   */
  protected void setActiveEditor(IEditorPart part) {
    _activeEditor = part;
  }

  /**
   * The <code>MultiPageEditor</code> implementation of this
   * <code>IWorkbenchPart</code> method sets focus on the active nested
   * editor, if there is one.
   * <p>
   * Subclasses may extend or reimplement.
   * </p>
   */
  public void setFocus() {
    setFocus(getActiveEditor());
  }

  /**
   * Sets focus to the control for the given page. If the page has an editor,
   * this calls its <code>setFocus()</code> method. Otherwise, this calls
   * <code>setFocus</code> on the control for the page.
   *
   * @param pageIndex
   *            the index of the page
   */
  private void setFocus(IEditorPart editor) {
    final IKeyBindingService service = getSite().getKeyBindingService();

    if (editor == null) {
      // There is no selected page, so deactivate the active service.
      if (service instanceof INestableKeyBindingService) {
        final INestableKeyBindingService nestableService = (INestableKeyBindingService) service;
        nestableService.activateKeyBindingService(null);
      } else {
        //WorkbenchPlugin
        PDPlugin
            .getLogger(getClass()).error("MultiPageEditorPart.setFocus()   Parent key binding service was not an instance of INestableKeyBindingService.  It was an instance of " + service.getClass().getName() + " instead."); //$NON-NLS-1$ //$NON-NLS-2$
      }
      return;
    }
        editor.setFocus();
        // There is no selected page, so deactivate the active service.
        if (service instanceof INestableKeyBindingService) {
          final INestableKeyBindingService nestableService = (INestableKeyBindingService) service;
          if (editor != null) {
            nestableService.activateKeyBindingService(editor
                .getEditorSite());
          } else {
            nestableService.activateKeyBindingService(null);
          }
        } else {
            PDPlugin
                .getLogger(getClass()).error("MultiPageEditorPart.setFocus()   Parent key binding service was not an instance of INestableKeyBindingService.  It was an instance of " + service.getClass().getName() + " instead."); //$NON-NLS-1$ //$NON-NLS-2$
        }
  }

  public void doSave(IProgressMonitor monitor) {
    if (_activeEditor != null) {
      _activeEditor.doSave(monitor);
    }
  }

  public void doSaveAs() {
    if (_activeEditor != null) {
      _activeEditor.doSaveAs();
    }

  }

  public boolean isSaveAsAllowed() {
    if (_activeEditor != null)
        {
      return _activeEditor.isSaveAsAllowed();
        }
    return false;
  }

  /**
   * @param orientation
   */
  public void setOrientation(int orientation) {
    this._orientation = orientation;
    if (_sashForm != null && !_sashForm.isDisposed()) {
      _sashForm.setMaximizedControl(null);
      _sashForm.setOrientation(_orientation);
    }
  }

  /**
   * @param part
   */
  public void setMaximizedEditor(IEditorPart part) {
    if (part != null) {
      Composite c = (Composite) _editorToComposite.get(part);
      if (c != null && _sashForm != null && !_sashForm.isDisposed()) {
        _sashForm.setMaximizedControl(c);
        part.setFocus();
      }
    } else {
      if (_sashForm != null && !_sashForm.isDisposed()) {
        _sashForm.setMaximizedControl(null);
      }
    }
  }
}
TOP

Related Classes of org.eclipse.jst.pagedesigner.ui.common.sash.SashEditorPart

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.