org.eclipse.rap.ui.interactiondesign.ConfigurableStack.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.rap.ui.interactiondesign.ConfigurableStack.java

Source

/*******************************************************************************
* Copyright (c) 2009 EclipseSource 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:
*   EclipseSource - initial API and implementation
*******************************************************************************/
package org.eclipse.rap.ui.interactiondesign;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.internal.provisional.action.IToolBarManager2;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.rap.ui.interactiondesign.internal.ConfigurableStackProxy;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.DefaultStackPresentationSite;
import org.eclipse.ui.internal.LayoutPart;
import org.eclipse.ui.internal.PartPane;
import org.eclipse.ui.internal.ViewPane;
import org.eclipse.ui.internal.presentations.PresentablePart;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.eclipse.ui.presentations.IPartMenu;
import org.eclipse.ui.presentations.IPresentablePart;
import org.eclipse.ui.presentations.IStackPresentationSite;
import org.eclipse.ui.presentations.StackPresentation;

/**
 * This represents an object, which extends the original <code>
 * {@link StackPresentation}</code>.
 * <p>
 * You can do everything with this as you can do with the original one. It
 * just provides more methods for making a StackPresentation configurable.
 * </p>
 *
 * @see StackPresentation
 * @since 1.2
 */
public abstract class ConfigurableStack extends StackPresentation {

    private static final String CONFIG_ACTION_NAME = "actionClass";

    private static IStackPresentationSite siteDummy = new IStackPresentationSite() {

        public void addSystemActions(final IMenuManager menuManager) {

        }

        public void close(final IPresentablePart[] toClose) {

        }

        public void dragStart(final IPresentablePart beingDragged, final Point initialPosition,
                final boolean keyboard) {

        }

        public void dragStart(final Point initialPosition, final boolean keyboard) {

        }

        public void flushLayout() {

        }

        public IPresentablePart[] getPartList() {
            return null;
        }

        public String getProperty(final String id) {
            return null;
        }

        public IPresentablePart getSelectedPart() {
            return null;
        }

        public int getState() {
            return 0;
        }

        public boolean isCloseable(final IPresentablePart toClose) {
            return false;
        }

        public boolean isPartMoveable(final IPresentablePart toMove) {
            return false;
        }

        public boolean isStackMoveable() {
            return false;
        }

        public void selectPart(final IPresentablePart toSelect) {

        }

        public void setState(final int newState) {

        }

        public boolean supportsState(final int state) {
            return false;
        }

    };

    /**
     * Extension Point ID of the StackPresentation Extension point.
     */
    public static final String STACK_PRESENTATION_EXT_ID = "org.eclipse.rap.ui.stackPresentations";

    /**
     * This method is used for getting the <code>{@link LayoutPart}</code> ID for
     * a specific <code>IStackPresentationSite</code>. Their is no other
     * oppertunity to get this id.
     *
     * @param site an instance of <code>IStackPreentationSite</code>.
     *
     * @return the unique <code>LayoutPart</code> ID defined in a Perspective or
     * <code>null</code> if their is no id.
     *
     * @see LayoutPart
     * @see IStackPresentationSite
     */
    public static final String getLayoutPartId(final IStackPresentationSite site) {
        String result = null;
        if (site != null && site instanceof DefaultStackPresentationSite) {
            DefaultStackPresentationSite defaultSite = (DefaultStackPresentationSite) site;
            result = defaultSite.getProperty("id");
        }
        return result;
    }

    /**
     * Loads the saved <code>ConfigurableStack</code> id from the preferences
     * store using a specific <code>IStackPresentationSite</code>. This id is
     * needed to instantiate the <code>ConfigurableStack</code> for a specific
     * LayoutPart.
     *
     * @param site an instance of <code>IStackPreentationSite</code>.
     *
     * @return the saved <code>ConfigurableStack</code> id for the part
     * represented by the <code>IStackPresentationSite</code> or <code>null</code>
     * if no id is saved.
     *
     * @see LayoutPart
     * @see IStackPresentationSite
     */
    public static String getSavedStackId(final IStackPresentationSite site) {
        String layoutPartId = null;
        String result = IPreferenceStore.STRING_DEFAULT_DEFAULT;

        layoutPartId = getLayoutPartId(site);

        if (layoutPartId != null) {
            ScopedPreferenceStore prefStore = (ScopedPreferenceStore) PrefUtil.getAPIPreferenceStore();
            String stackPresentationId = ConfigurableStackProxy.STACK_PRESENTATION_ID;
            String stackPresentationKey = stackPresentationId + "/" + layoutPartId;
            result = prefStore.getString(stackPresentationKey);
        }

        return result;
    }

    private ConfigurationAction configAction;
    private ImageDescriptor menuIcon;

    private Composite parent;

    private ConfigurableStackProxy proxy;
    private IStackPresentationSite site;

    private String stackPresentationId;

    private List managersWhoHasListeners;

    /**
     * Instantiate an object of this class by calling the super constructor with
     * a dummy <code>{@link IStackPresentationSite}</code>.
     *
     * @see IStackPresentationSite
     */
    public ConfigurableStack() {
        super(siteDummy);
    }

    public Control createPartToolBar() {
        Control result = null;
        IToolBarManager manager = getPartToolBarManager();
        ConfigurationAction action = getConfigAction();
        IStackPresentationSite site = getSite();
        int actionCount = 0;
        if (action != null && manager != null) {
            addPropertyChangeListenerToToolBar(manager);
            IContributionItem[] items = manager.getItems();
            String paneId = getPaneId(site);

            // get the toolbar
            if (manager instanceof IToolBarManager2) {
                result = ((IToolBarManager2) manager).getControl2();
            }
            // set the correct visibility
            for (int i = 0; i < items.length; i++) {
                IContributionItem item = items[i];
                boolean isVisible = action.isViewActionVisibile(paneId, item.getId());
                if ((!item.isVisible() && isVisible) || (item.isVisible() && !isVisible)) {
                    item.setVisible(isVisible);
                }
                if (isVisible) {
                    actionCount++;
                }
            }

            // update the toolbar manager with the new visibility
            if (manager != null && result != null) {
                manager.update(true);
            }

            // if no item is visible the toolbar should be null
            if (actionCount <= 0) {
                result = null;
            }
            if (result != null) {
                result.pack();
                result.setVisible(true);
            }
        }
        return result;
    }

    private void addPropertyChangeListenerToToolBar(final IToolBarManager manager) {
        if (manager instanceof IToolBarManager2 && !hasListener(manager)) {
            final IToolBarManager2 manager2 = (IToolBarManager2) manager;
            final IPropertyChangeListener listener = new IPropertyChangeListener() {
                public void propertyChange(final PropertyChangeEvent event) {
                    if (event.getProperty().equals(IToolBarManager2.PROP_LAYOUT)) {
                        if (configAction != null) {
                            configAction.fireToolBarChange();
                        }
                    }
                }
            };
            manager2.addPropertyChangeListener(listener);
            final Control toolBar = manager2.getControl2();
            if (toolBar != null) {
                // Remove all listeners from the manager and the manager from the list
                // to prevent memory leaks
                toolBar.addDisposeListener(new DisposeListener() {
                    public void widgetDisposed(final DisposeEvent event) {
                        toolBar.removeDisposeListener(this);
                        manager2.removePropertyChangeListener(listener);
                        if (managersWhoHasListeners != null) {
                            managersWhoHasListeners.remove(manager);
                        }
                    }
                });
            }
        }

    }

    private boolean hasListener(final IToolBarManager manager) {
        boolean result = false;
        if (managersWhoHasListeners == null) {
            managersWhoHasListeners = new ArrayList();
        }
        if (managersWhoHasListeners.contains(manager)) {
            result = true;
        } else {
            managersWhoHasListeners.add(manager);
        }
        return result;
    }

    public IPartMenu createViewMenu() {
        IPartMenu result = null;
        if (isPartMenuVisisble()) {
            result = new IPartMenu() {
                public void showMenu(final Point location) {
                    IPresentablePart selectedPart = site.getSelectedPart();
                    if (selectedPart instanceof PresentablePart) {
                        PresentablePart part = (PresentablePart) selectedPart;
                        part.getPane().showViewMenu(location);
                    }
                }
            };
        }
        return result;
    }

    /**
     * Returns an instance of <code>{@link ConfigurationAction}</code> for this
     * <code>ConfigurableStack</code> object, which is declared over the same
     * extension.
     *
     * @return the <code>ConfigurationAction</code> or <code>null</code> if no
     * action is declared for the id holding by this object.
     *
     * @see ConfigurationAction
     */
    public ConfigurationAction getConfigAction() {
        ConfigurationAction result = null;
        if (configAction == null) {
            if (stackPresentationId != null && !stackPresentationId.equals("")) {
                IExtensionRegistry registry = Platform.getExtensionRegistry();
                String stackId = STACK_PRESENTATION_EXT_ID;
                IExtensionPoint point = registry.getExtensionPoint(stackId);

                if (point != null) {
                    IConfigurationElement[] elements = point.getConfigurationElements();
                    String defaultValue = IPreferenceStore.STRING_DEFAULT_DEFAULT;
                    String actionClass = defaultValue;

                    boolean breakValue = true;
                    IConfigurationElement element = null;
                    ImageDescriptor imageDesc = null;
                    for (int i = 0; breakValue && i < elements.length; i++) {
                        String id = elements[i].getAttribute("id");
                        if (id.equals(stackPresentationId)) {
                            actionClass = elements[i].getAttribute(CONFIG_ACTION_NAME);
                            if (actionClass != null && !actionClass.equals(defaultValue)) {
                                breakValue = false;
                                element = elements[i];
                                String actionImage = element.getAttribute("actionIcon");
                                String menuImage = element.getAttribute("menuIcon");
                                String contributerId = element.getContributor().getName();
                                if (actionImage != null) {
                                    imageDesc = AbstractUIPlugin.imageDescriptorFromPlugin(contributerId,
                                            actionImage);
                                }
                                if (menuImage != null) {
                                    menuIcon = AbstractUIPlugin.imageDescriptorFromPlugin(contributerId, menuImage);
                                }
                            }
                        }
                    }

                    String defaultStore = defaultValue;
                    if (actionClass != null && !actionClass.equals(defaultStore) && element != null) {
                        try {
                            Object obj = element.createExecutableExtension(CONFIG_ACTION_NAME);
                            if (obj instanceof ConfigurationAction) {
                                configAction = (ConfigurationAction) obj;
                                configAction.init(getSite(), this);
                                if (imageDesc != null) {
                                    configAction.setImageDescriptor(imageDesc);
                                }
                            }
                        } catch (CoreException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        result = configAction;
        return result;
    }

    /**
     * Represents the menuIcon which is declared in the extension for the
     * extension point org.eclipse.rap.ui.stackPresentations. Return the
     * ImageDescriptor for this image.
     */
    protected ImageDescriptor getMenuIcon() {
        return menuIcon;
    }

    /**
     * This method returns the <code>{@link PartPane}</code> id defined in the
     * selected <code>{@link PresentablePart}</code> of a
     * <code>IStackPresentationSite</code> instance.
     *
     * @param site an instance of <code>IStackPresentationSite</code>
     *
     * @return the id of the <code>PartPane</code> from the selected
     * <code>PresentablePart</code> or an empty String if no part is selected.
     *
     * @see PartPane
     * @see PresentablePart
     * @see IStackPresentationSite
     */
    public final String getPaneId(final IStackPresentationSite site) {
        String result = "";
        IPresentablePart selectedPart = site.getSelectedPart();
        if (selectedPart instanceof PresentablePart) {
            PresentablePart part = (PresentablePart) selectedPart;
            result = part.getPane().getID();
        }
        return result;
    }

    private String getSecondaryPaneId(final IStackPresentationSite site) {
        String result = null;
        IPresentablePart selectedPart = site.getSelectedPart();
        if (selectedPart instanceof PresentablePart) {
            PresentablePart part = (PresentablePart) selectedPart;
            PartPane pane = part.getPane();
            if (pane instanceof ViewPane) {
                ViewPane viewPane = (ViewPane) pane;
                result = viewPane.getViewReference().getSecondaryId();
            }
        }
        return result;
    }

    /**
     * Returns the parent composite for this kind of <code>StackPresentation
     * </code>.
     * @return the parent composite
     */
    public Composite getParent() {
        return parent;
    }

    /**
     * This method returns the <code>{@link IToolBarManager}</code> for the
     * selected <code>{@link ViewPart}</code>.
     *
     * @return the <code>IToolBarManager</code> or <code>null</code> if their is
     * no <code>ViewPart</code> selected.
     *
     * @see IToolBarManager
     * @see ViewPart
     */
    public IToolBarManager getPartToolBarManager() {
        IToolBarManager result = null;
        IStackPresentationSite site = getSite();
        String paneId = getPaneId(site);
        IWorkbench workbench = PlatformUI.getWorkbench();
        IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
        IWorkbenchPage activePage = window.getActivePage();
        if (activePage != null) {
            String secId = getSecondaryPaneId(site);
            IViewPart viewPart = null;
            if (secId != null) {
                IViewReference ref = activePage.findViewReference(paneId, secId);
                if (ref != null) {
                    viewPart = (ViewPart) ref.getPart(false);
                }
            } else {
                viewPart = activePage.findView(paneId);
            }

            IActionBars bars = null;
            if (viewPart != null) {
                IViewSite viewSite = (IViewSite) viewPart.getSite();
                bars = viewSite.getActionBars();
                result = bars.getToolBarManager();
            }
        }
        return result;
    }

    /**
     * If this Stack is from the type standaloneview, than it will have an
     * attribute called showTitle. This is a parameter of the crate method in the
     * original <code>AbstractPresentationFactory</code>. This is just a separate
     * method, because the creation is now automated and using proxy objects.
     * To match the old behaviour, this method was introduced.
     * @return the showTitle flag for the standalone view. If the view is not
     * standalone, it will return allways <code>false</code>.
     */
    public boolean getShowTitle() {
        return proxy.getShowTitle();
    }

    /**
     * Returns the <code>{@link IStackPresentationSite}</code> holding by this
     * instance.
     *
     * @return the site used for communication between the presentation and
     * the workbench.
     *
     * @see IStackPresentationSite
     */
    public IStackPresentationSite getSite() {
        return site;
    }

    public String getStackPresentationId() {
        return stackPresentationId;
    }

    /**
     * Returns the type of the Stack.
     * @return the type. See <code>PresentationFactory</code> constants.
     */
    protected String getType() {
        return proxy.getType();
    }

    /**
     * This is called right after all necessary fields are initialized e.g. site,
     * stackPresentationId, parent and proxy. Subclasses can implement any
     * initializaion behaviour using this mehtod.
     */
    public abstract void init();

    /**
     * This method is called right after the constructor is called. It's
     * necessary for creating a <code>ConfigurableStack</code> object over an
     * extension because the standard <code>StackPresentation</code> has no
     * parameterless constructor.
     * <p>
     * This method just set the mandatory fields.
     * </p>
     *
     * @param site the site used for communication between the presentation and
     * the workbench.
     * @param stackId the StackPresentation ID, which is declared in the
     * Extension.
     * @param parent the parent composite to use for the presentation's controls.
     * @param proxy the <code>{@link ConfigurableStackProxy}</code> that holds
     * this instance.
     *
     * @see ConfigurableStackProxy
     * @see StackPresentation
     */
    public void init(final IStackPresentationSite site, final String stackId, final Composite parent,
            final ConfigurableStackProxy proxy) {
        this.site = site;
        this.stackPresentationId = stackId;
        this.parent = parent;
        this.proxy = proxy;
        init();
    }

    private boolean isPartMenuVisisble() {
        boolean result = false;
        if (configAction != null) {
            result = configAction.isPartMenuVisible();
        }
        return result;
    }

    /**
     * Method to change the current StackPresentation of a part. This method just
     * calls the
     * <code>{@link ConfigurableStackProxy#setCurrentStackPresentation(String)}
     * </code> method.
     *
     * @param newStackId the id of the stack to change.
     *
     * @see ConfigurableStackProxy
     */
    public void setCurrentStackPresentation(final String newStackId) {
        if (proxy != null) {
            proxy.setCurrentStackPresentation(newStackId);
        }
    }

}