de.walware.rj.eclient.graphics.PageBookRGraphicView.java Source code

Java tutorial

Introduction

Here is the source code for de.walware.rj.eclient.graphics.PageBookRGraphicView.java

Source

/*=============================================================================#
 # Copyright (c) 2009-2015 Stephan Wahlbrink (WalWare.de) 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:
 #     Stephan Wahlbrink - initial API and implementation
 #=============================================================================*/

package de.walware.rj.eclient.graphics;

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

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler2;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.StatusLineContributionItem;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.part.IPageBookViewPage;
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.views.IViewDescriptor;

import de.walware.ecommons.ts.ITool;
import de.walware.ecommons.ui.SharedUIResources;
import de.walware.ecommons.ui.actions.HandlerCollection;
import de.walware.ecommons.ui.actions.HandlerContributionItem;
import de.walware.ecommons.ui.actions.SimpleContributionItem;
import de.walware.ecommons.ui.mpbv.ISession;
import de.walware.ecommons.ui.mpbv.ManagedPageBookView;
import de.walware.ecommons.ui.util.UIAccess;

import de.walware.rj.eclient.AbstractRToolRunnable;
import de.walware.rj.eclient.IRToolService;

/**
 * Multi page view for R graphics.
 * <p>
 * No view is registered by this plug-in.</p>
 */
public abstract class PageBookRGraphicView extends ManagedPageBookView<PageBookRGraphicView.RGraphicSession> {

    public class RGraphicSession implements ISession {

        private final IERGraphic fGraphic;

        public RGraphicSession(final IERGraphic graphic) {
            fGraphic = graphic;
        }

        @Override
        public ImageDescriptor getImageDescriptor() {
            return ImageDescriptor.createFromImage(PageBookRGraphicView.this.getTitleImage());
        }

        @Override
        public String getLabel() {
            return fGraphic.getLabel();
        }

        public IERGraphic getGraphic() {
            return fGraphic;
        }

    }

    public static class ShowRequiredViewListener implements IERGraphicsManager.ListenerShowExtension {

        private final String fViewId;

        public ShowRequiredViewListener(final String viewId) {
            fViewId = viewId;
        }

        @Override
        public int canShowGraphic(final IERGraphic graphic) {
            return 0;
        }

        private static String getId(final IViewReference ref) {
            // E-Bug #405563
            final String id = ref.getId();
            final int idx = id.indexOf(':');
            return (idx >= 0) ? id.substring(0, idx) : id;
        }

        @Override
        public void showGraphic(final IERGraphic graphic) {
            try {
                final IWorkbenchPage page = getBestPage(graphic);
                String secondaryId = ""; //$NON-NLS-1$
                final IViewReference[] refs = page.getViewReferences();
                for (int i = 0; i < refs.length; i++) { // search views not yet instanced
                    if (fViewId.equals(getId(refs[i])) && refs[i].getView(false) == null) {
                        if (refs[i].getSecondaryId() == null) {
                            secondaryId = null;
                            break;
                        }
                        if (secondaryId == "") { //$NON-NLS-1$
                            secondaryId = refs[i].getSecondaryId();
                        }
                    }
                }
                if (secondaryId == "") { //$NON-NLS-1$
                    secondaryId = "t" + System.currentTimeMillis(); //$NON-NLS-1$
                }
                gNewViewGraphic = graphic;
                page.showView(fViewId, secondaryId, IWorkbenchPage.VIEW_VISIBLE);
            } catch (final PartInitException e) {
                StatusManager.getManager().handle(new Status(IStatus.ERROR, RGraphics.PLUGIN_ID,
                        "An error occurred when opening a new R Graphics view.", e));
            } finally {
                gNewViewGraphic = null;
            }
        }

        protected IWorkbenchPage getBestPage(final IERGraphic graphic) {
            return UIAccess.getActiveWorkbenchPage(true);
        }

        @Override
        public void graphicAdded(final IERGraphic graphic) {
        }

        @Override
        public void graphicRemoved(final IERGraphic graphic) {
        }

    }

    protected static abstract class NewDevHandler extends AbstractHandler {

        public NewDevHandler() {
        }

        protected abstract ITool getTool() throws CoreException;

        @Override
        public Object execute(final ExecutionEvent event) throws ExecutionException {
            try {
                final ITool tool = getTool();
                if (tool != null) {
                    tool.getQueue().add(new AbstractRToolRunnable("r/rj/gd/new", "New R Graphic") { //$NON-NLS-1$

                        @Override
                        public void run(final IRToolService r, final IProgressMonitor monitor)
                                throws CoreException {
                            r.evalVoid("rj.gd::rj.GD()", monitor); //$NON-NLS-1$
                        }

                    });
                }
            } catch (final CoreException e) {
                if (e.getStatus().getSeverity() != IStatus.CANCEL) {
                    StatusManager.getManager()
                            .handle(new Status(IStatus.ERROR, RGraphics.PLUGIN_ID, -1,
                                    "An error occurrend when creating a new graphic device.", e),
                                    StatusManager.LOG | StatusManager.SHOW);
                }
            }
            return null;
        }

    }

    private static class RGraphicComparator implements Comparator<RGraphicSession> {

        public RGraphicComparator() {
        }

        @Override
        public int compare(final RGraphicSession o1, final RGraphicSession o2) {
            final ITool handle1 = o1.fGraphic.getRHandle();
            final ITool handle2 = o2.fGraphic.getRHandle();
            if (handle1 == null) {
                if (handle2 == null) {
                    return 0;
                }
                return Integer.MIN_VALUE;
            } else if (handle2 == null) {
                return Integer.MAX_VALUE;
            }
            if (handle1 != handle2) {
                final int diff = handle1.getLabel(ITool.LONG_LABEL).compareTo(handle2.getLabel(ITool.LONG_LABEL));
                if (diff != 0) {
                    return diff;
                }
            }
            return o1.fGraphic.getDevId() - o2.fGraphic.getDevId();
        }

    }

    private static class OpenAdditionalViewHandler extends AbstractHandler {

        private final IViewSite fViewSite;

        public OpenAdditionalViewHandler(final IViewSite viewSite) {
            fViewSite = viewSite;
        }

        @Override
        public Object execute(final ExecutionEvent event) throws ExecutionException {
            try {
                final String secondaryId = "t" + System.currentTimeMillis(); //$NON-NLS-1$
                fViewSite.getWorkbenchWindow().getActivePage().showView(fViewSite.getId(), secondaryId,
                        IWorkbenchPage.VIEW_ACTIVATE);
            } catch (final PartInitException e) {
                StatusManager.getManager().handle(new Status(IStatus.ERROR, RGraphics.PLUGIN_ID, -1,
                        "An error occurred when opening an additional R graphics view.", e));
            }
            return null;
        }

    }

    private class PinPageAction extends SimpleContributionItem {

        public PinPageAction() {
            super(SharedUIResources.getImages().getDescriptor(SharedUIResources.LOCTOOL_PIN_PAGE_IMAGE_ID),
                    SharedUIResources.getImages().getDescriptor(SharedUIResources.LOCTOOLD_PIN_PAGE_IMAGE_ID),
                    "Pin Graphic Page", "P", SimpleContributionItem.STYLE_CHECK);
            setChecked(fPinPage);
        }

        @Override
        protected void execute() throws ExecutionException {
            fPinPage = !fPinPage;
            setChecked(fPinPage);
        }

    }

    private static IERGraphic gNewViewGraphic;

    private IERGraphicsManager fManager;
    private final IERGraphicsManager.ListenerShowExtension fManagerListener = new IERGraphicsManager.ListenerShowExtension() {
        private IERGraphic toShow;

        @Override
        public int canShowGraphic(final IERGraphic graphic) {
            return PageBookRGraphicView.this.canShowGraphic(graphic);
        }

        @Override
        public void showGraphic(final IERGraphic graphic) {
            toShow = graphic;
            final IViewSite site = getViewSite();
            try {
                site.getPage().showView(site.getId(), site.getSecondaryId(), IWorkbenchPage.VIEW_VISIBLE);
            } catch (final PartInitException e) {
            }
        }

        @Override
        public void graphicAdded(final IERGraphic graphic) {
            add(graphic, graphic == toShow || (graphic.isActive() && (!fPinPage || getCurrentSession() == null)));
            toShow = null;
        }

        @Override
        public void graphicRemoved(final IERGraphic graphic) {
            final RGraphicSession session = getSession(graphic);
            if (session != null) {
                PageBookRGraphicView.super.closePage(session);
            }
        }
    };

    private boolean fPinPage;

    private final IERGraphic.Listener fGraphicListener = new IERGraphic.ListenerLocatorExtension() {
        @Override
        public void activated() {
            updateTitle();
        }

        @Override
        public void deactivated() {
            updateTitle();
        }

        @Override
        public void drawingStarted() {
        }

        @Override
        public void drawingStopped() {
        }

        @Override
        public void locatorStarted() {
            updateTitle();
        }

        @Override
        public void locatorStopped() {
            updateTitle();
        }
    };

    private StatusLineContributionItem fPositionStatusLineItem;

    public PageBookRGraphicView() {
    }

    @Override
    public void init(final IViewSite site, final IMemento memento) throws PartInitException {
        setSessionComparator(new RGraphicComparator());
        super.init(site, memento);
        fManager = loadManager();
    }

    protected abstract IERGraphicsManager loadManager();

    @Override
    public void createPartControl(final Composite parent) {
        super.createPartControl(parent);
        if (fManager != null) {
            fManager.addListener(fManagerListener);
            IERGraphic active = gNewViewGraphic;
            if (active != null) {
                final List<? extends IERGraphic> graphics = fManager.getAllGraphics();
                for (final IERGraphic graphic : graphics) {
                    add(graphic, false);
                }
            } else {
                final List<? extends IERGraphic> graphics = fManager.getAllGraphics();
                for (final IERGraphic graphic : graphics) {
                    add(graphic, false);
                    if (graphic.isActive()) {
                        active = graphic;
                    }
                }
                if (active == null && !graphics.isEmpty()) {
                    active = graphics.get(graphics.size() - 1);
                }
            }
            if (active != null) {
                final RGraphicSession session = getSession(active);
                if (session != null) {
                    showPage(session);
                }
            }
        }
    }

    public RGraphicSession getSession(final IERGraphic graphic) {
        final List<RGraphicSession> sessions = getSessions();
        for (final RGraphicSession session : sessions) {
            if (session.getGraphic() == graphic) {
                return session;
            }
        }
        return null;
    }

    protected int canShowGraphic(final IERGraphic graphic) {
        final RGraphicSession session = getCurrentSession();
        int canShow;
        if (session != null && session.getGraphic() == graphic) {
            canShow = (fPinPage) ? 20 : 10;
        } else if (fPinPage && session != null) {
            return -1;
        } else {
            canShow = 1;
        }
        if (getViewSite().getPage().isPartVisible(this)) {
            canShow += 2;
        }
        return canShow;
    }

    protected void add(final IERGraphic graphic, final boolean show) {
        super.newPage(new RGraphicSession(graphic), show);
    }

    @Override
    protected String getNoPageTitle() {
        return "No graphics at this time.";
    }

    @Override
    protected IHandler2 createNewPageHandler() {
        return null;
    }

    @Override
    protected void initActions(final IServiceLocator serviceLocator, final HandlerCollection handlers) {
        super.initActions(serviceLocator, handlers);

        final OpenAdditionalViewHandler openViewHandler = new OpenAdditionalViewHandler(getViewSite());
        handlers.add(".OpenView", openViewHandler);
    }

    @Override
    protected void contributeToActionBars(final IServiceLocator serviceLocator, final IActionBars actionBars,
            final HandlerCollection handlers) {
        super.contributeToActionBars(serviceLocator, actionBars, handlers);

        final IMenuManager menuManager = actionBars.getMenuManager();
        menuManager.add(new Separator("view"));
        final IViewDescriptor viewDescriptor = PlatformUI.getWorkbench().getViewRegistry()
                .find(getViewSite().getId());
        menuManager.add(new HandlerContributionItem(new CommandContributionItemParameter(serviceLocator, null,
                HandlerContributionItem.NO_COMMAND_ID, null, viewDescriptor.getImageDescriptor(), null, null,
                NLS.bind("Open Additional {0} View", viewDescriptor.getLabel()), "O", null,
                HandlerContributionItem.STYLE_PUSH, null, false), handlers.get(".OpenView")));
        menuManager.add(new Separator("save"));
        menuManager.add(new Separator(SharedUIResources.ADDITIONS_MENU_ID));

        menuManager.add(new Separator("settings")); //$NON-NLS-1$
        menuManager.add(new SimpleContributionItem("Preferences...", "P") {
            @Override
            protected void execute() throws ExecutionException {
                final Shell shell = getViewSite().getShell();
                final String[] preferencePages = collectContextMenuPreferencePages();
                if (preferencePages.length > 0 && (shell == null || !shell.isDisposed())) {
                    org.eclipse.ui.dialogs.PreferencesUtil
                            .createPreferenceDialogOn(shell, preferencePages[0], preferencePages, null).open();
                }
            }
        });

        final IToolBarManager toolBarManager = actionBars.getToolBarManager();
        toolBarManager.insertAfter("page_control.change_page", new PinPageAction()); //$NON-NLS-1$

        final IStatusLineManager lineManager = actionBars.getStatusLineManager();
        fPositionStatusLineItem = new StatusLineContributionItem(
                RGraphicCompositeActionSet.POSITION_STATUSLINE_ITEM_ID, 20);
        lineManager.add(fPositionStatusLineItem);
    }

    private String[] collectContextMenuPreferencePages() {
        final List<String> pageIds = new ArrayList<String>();
        collectContextMenuPreferencePages(pageIds);
        return pageIds.toArray(new String[pageIds.size()]);
    }

    protected void collectContextMenuPreferencePages(final List<String> pageIds) {
    }

    @Override
    protected RGraphicPage doCreatePage(final RGraphicSession session) {
        return new RGraphicPage(session.getGraphic());
    }

    @Override
    protected void initPage(final IPageBookViewPage page) {
        super.initPage(page);
        if (page instanceof RGraphicPage) {
            ((RGraphicPage) page).init(fPositionStatusLineItem);
        }
    }

    @Override
    public void closePage(final RGraphicSession session) {
        final IStatus status = session.getGraphic().close();
        if (status != null && status.getSeverity() < IStatus.ERROR) {
            return;
        }
        super.closePage(session);
    }

    @Override
    protected void onPageShowing(final IPageBookViewPage page, final RGraphicSession session) {
        if (session != null) {
            session.getGraphic().addListener(fGraphicListener);
        }
        super.onPageShowing(page, session);
    }

    @Override
    protected void onPageHiding(final IPageBookViewPage page, final RGraphicSession session) {
        if (session != null) {
            session.getGraphic().removeListener(fGraphicListener);
        }
        if (fPositionStatusLineItem != null) {
            fPositionStatusLineItem.setText(""); //$NON-NLS-1$
        }
        super.onPageHiding(page, session);
    }

    @Override
    public void dispose() {
        if (fManager != null) {
            fManager.removeListener(fManagerListener);
        }
        final RGraphicSession session = getCurrentSession();
        if (session != null) {
            session.getGraphic().removeListener(fGraphicListener);
        }
        super.dispose();
    }

}