| /*=============================================================================# |
| # Copyright (c) 2009, 2018 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.rj.eclient.graphics; |
| |
| import static org.eclipse.statet.ecommons.ui.actions.UIActions.ADDITIONS_GROUP_ID; |
| |
| 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 org.eclipse.statet.ecommons.ts.core.Tool; |
| import org.eclipse.statet.ecommons.ui.SharedUIResources; |
| import org.eclipse.statet.ecommons.ui.actions.HandlerCollection; |
| import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem; |
| import org.eclipse.statet.ecommons.ui.actions.SimpleContributionItem; |
| import org.eclipse.statet.ecommons.ui.mpbv.ISession; |
| import org.eclipse.statet.ecommons.ui.mpbv.ManagedPageBookView; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| import org.eclipse.statet.ecommons.ui.workbench.ContextHandlers; |
| |
| import org.eclipse.statet.rj.eclient.core.AbstractRToolRunnable; |
| import org.eclipse.statet.rj.eclient.core.RToolService; |
| |
| |
| /** |
| * 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 ERGraphic graphic; |
| |
| |
| public RGraphicSession(final ERGraphic graphic) { |
| this.graphic= graphic; |
| } |
| |
| |
| @Override |
| public String getLabel() { |
| return this.graphic.getLabel(); |
| } |
| |
| @Override |
| public ImageDescriptor getImageDescriptor() { |
| return ImageDescriptor.createFromImage(getTitleImage()); |
| } |
| |
| public ERGraphic getGraphic() { |
| return this.graphic; |
| } |
| |
| } |
| |
| public static class ShowRequiredViewListener implements ERGraphicsManager.ListenerShowExtension { |
| |
| |
| private final String viewId; |
| |
| |
| public ShowRequiredViewListener(final String viewId) { |
| this.viewId= viewId; |
| } |
| |
| |
| @Override |
| public int canShowGraphic(final ERGraphic 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 ERGraphic 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 (this.viewId.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$ |
| } |
| newViewGraphic= graphic; |
| page.showView(this.viewId, secondaryId, IWorkbenchPage.VIEW_VISIBLE ); |
| } |
| catch (final PartInitException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, RGraphics.BUNDLE_ID, |
| "An error occurred when opening a new R Graphics view.", e )); |
| } |
| finally { |
| newViewGraphic= null; |
| } |
| } |
| |
| protected IWorkbenchPage getBestPage(final ERGraphic graphic) { |
| return UIAccess.getActiveWorkbenchPage(true); |
| } |
| |
| @Override |
| public void graphicAdded(final ERGraphic graphic) { |
| } |
| |
| @Override |
| public void graphicRemoved(final ERGraphic graphic) { |
| } |
| |
| } |
| |
| |
| protected static abstract class NewDevHandler extends AbstractHandler { |
| |
| |
| public NewDevHandler() { |
| } |
| |
| |
| protected abstract Tool getTool() throws CoreException; |
| |
| @Override |
| public Object execute(final ExecutionEvent event) throws ExecutionException { |
| try { |
| final Tool 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 RToolService 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.BUNDLE_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 Tool handle1= o1.graphic.getRHandle(); |
| final Tool handle2= o2.graphic.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(Tool.LONG_LABEL).compareTo(handle2.getLabel(Tool.LONG_LABEL)); |
| if (diff != 0) { |
| return diff; |
| } |
| } |
| return o1.graphic.getDevId() - o2.graphic.getDevId(); |
| } |
| |
| } |
| |
| |
| private static class OpenAdditionalViewHandler extends AbstractHandler { |
| |
| private final IViewSite viewSite; |
| |
| public OpenAdditionalViewHandler(final IViewSite viewSite) { |
| this.viewSite= viewSite; |
| } |
| |
| @Override |
| public Object execute(final ExecutionEvent event) throws ExecutionException { |
| try { |
| final String secondaryId= "t" + System.currentTimeMillis(); //$NON-NLS-1$ |
| this.viewSite.getWorkbenchWindow().getActivePage().showView(this.viewSite.getId(), |
| secondaryId, IWorkbenchPage.VIEW_ACTIVATE ); |
| } |
| catch (final PartInitException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, RGraphics.BUNDLE_ID, -1, |
| "An error occurred when opening an additional R graphics view.", e)); |
| } |
| return null; |
| } |
| |
| } |
| |
| private class PinPageAction extends SimpleContributionItem { |
| |
| public PinPageAction() { |
| super("Pin Graphic Page", "P", |
| SharedUIResources.getImages().getDescriptor(SharedUIResources.LOCTOOL_PIN_PAGE_IMAGE_ID), |
| SharedUIResources.getImages().getDescriptor(SharedUIResources.LOCTOOLD_PIN_PAGE_IMAGE_ID), |
| SimpleContributionItem.STYLE_CHECK ); |
| setChecked(PageBookRGraphicView.this.pinPage); |
| } |
| |
| @Override |
| protected void execute() throws ExecutionException { |
| PageBookRGraphicView.this.pinPage= !PageBookRGraphicView.this.pinPage; |
| setChecked(PageBookRGraphicView.this.pinPage); |
| } |
| |
| } |
| |
| |
| private static ERGraphic newViewGraphic; |
| |
| private ERGraphicsManager manager; |
| private final ERGraphicsManager.ListenerShowExtension managerListener= new ERGraphicsManager.ListenerShowExtension() { |
| private ERGraphic toShow; |
| @Override |
| public int canShowGraphic(final ERGraphic graphic) { |
| return PageBookRGraphicView.this.canShowGraphic(graphic); |
| } |
| @Override |
| public void showGraphic(final ERGraphic graphic) { |
| this.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 ERGraphic graphic) { |
| add(graphic, graphic == this.toShow |
| || (graphic.isActive() && (!PageBookRGraphicView.this.pinPage || getCurrentSession() == null)) ); |
| this.toShow= null; |
| } |
| @Override |
| public void graphicRemoved(final ERGraphic graphic) { |
| final RGraphicSession session= getSession(graphic); |
| if (session != null) { |
| PageBookRGraphicView.super.closePage(session); |
| } |
| } |
| }; |
| |
| private boolean pinPage; |
| |
| private final ERGraphic.Listener graphicListener= new ERGraphic.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 positionStatusLineItem; |
| |
| |
| public PageBookRGraphicView() { |
| } |
| |
| |
| @Override |
| public void init(final IViewSite site, final IMemento memento) throws PartInitException { |
| setSessionComparator(new RGraphicComparator()); |
| super.init(site, memento); |
| this.manager= loadManager(); |
| } |
| |
| protected abstract ERGraphicsManager loadManager(); |
| |
| @Override |
| public void createPartControl(final Composite parent) { |
| super.createPartControl(parent); |
| if (this.manager != null) { |
| this.manager.addListener(this.managerListener); |
| ERGraphic active= newViewGraphic; |
| if (active != null) { |
| final List<? extends ERGraphic> graphics= this.manager.getAllGraphics(); |
| for (final ERGraphic graphic : graphics) { |
| add(graphic, false); |
| } |
| } |
| else { |
| final List<? extends ERGraphic> graphics= this.manager.getAllGraphics(); |
| for (final ERGraphic 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 ERGraphic graphic) { |
| final List<RGraphicSession> sessions= getSessions(); |
| for (final RGraphicSession session : sessions) { |
| if (session.getGraphic() == graphic) { |
| return session; |
| } |
| } |
| return null; |
| } |
| |
| protected int canShowGraphic(final ERGraphic graphic) { |
| final RGraphicSession session= getCurrentSession(); |
| int canShow; |
| if (session != null && session.getGraphic() == graphic) { |
| canShow= (this.pinPage) ? 20 : 10; |
| } |
| else if (this.pinPage && session != null) { |
| return -1; |
| } |
| else { |
| canShow= 1; |
| } |
| if (getViewSite().getPage().isPartVisible(this)) { |
| canShow+=2; |
| } |
| return canShow; |
| } |
| |
| protected void add(final ERGraphic 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 ContextHandlers 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(ADDITIONS_GROUP_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(); |
| this.positionStatusLineItem= new StatusLineContributionItem(RGraphicCompositeActionSet.POSITION_STATUSLINE_ITEM_ID, 20); |
| lineManager.add(this.positionStatusLineItem); |
| } |
| |
| private String[] collectContextMenuPreferencePages() { |
| final List<String> pageIds= new ArrayList<>(); |
| 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(this.positionStatusLineItem); |
| } |
| } |
| |
| @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(this.graphicListener); |
| } |
| super.onPageShowing(page, session); |
| } |
| |
| @Override |
| protected void onPageHiding(final IPageBookViewPage page, final RGraphicSession session) { |
| if (session != null) { |
| session.getGraphic().removeListener(this.graphicListener); |
| } |
| if (this.positionStatusLineItem != null) { |
| this.positionStatusLineItem.setText(""); //$NON-NLS-1$ |
| } |
| super.onPageHiding(page, session); |
| } |
| |
| @Override |
| public void dispose() { |
| if (this.manager != null) { |
| this.manager.removeListener(this.managerListener); |
| } |
| final RGraphicSession session= getCurrentSession(); |
| if (session != null) { |
| session.getGraphic().removeListener(this.graphicListener); |
| } |
| super.dispose(); |
| } |
| |
| } |