/* * Copyright (c) 2011, M. Woelker, H. Westphal * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of jo-widgets.org nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL jo-widgets.org BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.jowidgets.workbench.impl.rcp.internal.part; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.core.internal.registry.ExtensionRegistry; import org.eclipse.core.runtime.ContributorFactoryOSGi; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IContributor; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IPerspectiveRegistry; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.registry.ViewDescriptor; import org.eclipse.ui.internal.registry.ViewRegistry; import org.eclipse.ui.views.IViewDescriptor; import org.jowidgets.workbench.api.IFolderContext; import org.jowidgets.workbench.api.IFolderLayout; import org.jowidgets.workbench.api.ILayout; import org.jowidgets.workbench.api.ILayoutContainer; import org.jowidgets.workbench.api.ISplitLayout; import org.jowidgets.workbench.api.IView; import org.jowidgets.workbench.api.IViewLayout; import org.jowidgets.workbench.api.LayoutScope; import org.jowidgets.workbench.api.ViewScope; import org.jowidgets.workbench.impl.rcp.RcpView; import org.jowidgets.workbench.impl.rcp.internal.Activator; import org.jowidgets.workbench.impl.rcp.internal.ComponentContext; import org.jowidgets.workbench.impl.rcp.internal.ComponentNodeContext; import org.jowidgets.workbench.impl.rcp.internal.FolderContext; import org.jowidgets.workbench.impl.rcp.internal.ViewContext; import org.jowidgets.workbench.impl.rcp.internal.WorkbenchApplicationContext; @SuppressWarnings("restriction") public final class PartSupport { private static final PartSupport INSTANCE = new PartSupport(); private final Map<String, IViewContainerContext> viewContainerContextMap = new HashMap<String, IViewContainerContext>(); private final Map<String, ViewLayoutContext> viewLayoutContextMap = new HashMap<String, ViewLayoutContext>(); private final Map<String, ViewContext> viewContextMap = new HashMap<String, ViewContext>(); private final Map<String, IView> viewMap = new HashMap<String, IView>(); private final Set<String> closingViewSet = new HashSet<String>(); private final Set<String> hidingViewSet = new HashSet<String>(); private PartSupport() {} public static PartSupport getInstance() { return INSTANCE; } public IViewContainerContext getViewContainerContext(final String perspectiveId) { return viewContainerContextMap.get(perspectiveId); } public ViewLayoutContext getViewLayoutContext(final String viewId) { return viewLayoutContextMap.get(viewId); } public IView getView(final String viewId) { return viewMap.get(viewId); } public void setViewAndContext(final String viewId, final IView view, final ViewContext viewContext) { viewMap.put(viewId, view); viewContextMap.put(viewId, viewContext); } public ViewContext getViewContext(final String viewId) { return viewContextMap.get(viewId); } public void removeViewAndContext(final String viewId) { viewMap.remove(viewId); viewContextMap.remove(viewId); closingViewSet.remove(viewId); } public void showEmptyPerspective() { final IPerspectiveRegistry perspectiveRegistry = PlatformUI.getWorkbench().getPerspectiveRegistry(); final IPerspectiveDescriptor perspectiveDescriptor = perspectiveRegistry.findPerspectiveWithId(DynamicPerspective.ID); final IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); activePage.setPerspective(perspectiveDescriptor); perspectiveRegistry.setDefaultPerspective(DynamicPerspective.ID); } public void showPerspective( final ComponentNodeContext componentTreeNodeContext, final ComponentContext componentContext, final ILayout perspective) { if (perspective == null) { showEmptyPerspective(); return; } final String perspectiveId = getPerspectiveId(perspective, componentTreeNodeContext); final IPerspectiveRegistry perspectiveRegistry = PlatformUI.getWorkbench().getPerspectiveRegistry(); IPerspectiveDescriptor newPerspective = perspectiveRegistry.findPerspectiveWithId(perspectiveId); if (newPerspective == null) { final IPerspectiveDescriptor perspectiveDescriptor = perspectiveRegistry.findPerspectiveWithId(DynamicPerspective.ID); newPerspective = perspectiveRegistry.clonePerspective( perspectiveId, String.valueOf(perspective.getLabel()), perspectiveDescriptor); final IViewContainerContext context = registerViews(perspectiveId, perspective.getLayoutContainer(), componentContext); viewContainerContextMap.put(perspectiveId, context); } final IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); activePage.setPerspective(newPerspective); // initialize views to update view titles from view model initializeViews(); } private String getPerspectiveId(final ILayout layout, final ComponentNodeContext componentTreeNodeContext) { final LayoutScope scope = layout.getScope(); if (scope == LayoutScope.WORKBENCH) { return layout.getId(); } final String appId = ((WorkbenchApplicationContext) componentTreeNodeContext.getWorkbenchApplicationContext()).getId(); if (scope == LayoutScope.WORKBENCH_APPLICATION) { return appId + "." + layout.getId(); } return appId + "." + getComponentNodeId(componentTreeNodeContext) + "." + layout.getId(); } private String getComponentNodeId(ComponentNodeContext componentTreeNodeContext) { final StringBuilder id = new StringBuilder(); while (componentTreeNodeContext != null) { id.insert(0, "." + componentTreeNodeContext.getId()); componentTreeNodeContext = (ComponentNodeContext) componentTreeNodeContext.getParent(); } return id.substring(1); } private void initializeViews() { final IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); final IViewReference[] viewReferences = activePage.getViewReferences(); for (final IViewReference viewReference : viewReferences) { viewReference.getView(true); } } private IViewContainerContext registerViews( final String perspectiveId, final ILayoutContainer viewContainer, final ComponentContext componentContext) { if (viewContainer instanceof ISplitLayout) { final ISplitLayout splitViewContainer = (ISplitLayout) viewContainer; return new SplitViewContainerContext(splitViewContainer, registerViews( perspectiveId, splitViewContainer.getFirstContainer(), componentContext), registerViews(perspectiveId, splitViewContainer.getSecondContainer(), componentContext)); } if (viewContainer instanceof IFolderLayout) { final IFolderLayout viewListContainer = (IFolderLayout) viewContainer; final TabViewContainerContext context = new TabViewContainerContext(perspectiveId + "." + viewListContainer.getId()); final IFolderContext folderContext = new FolderContext(viewListContainer.getId(), componentContext); componentContext.getComponent().onFolderCreated(folderContext); for (final IViewLayout singleViewContainer : viewListContainer.getViews()) { context.add(registerView(viewListContainer, singleViewContainer, componentContext, folderContext)); } return context; } throw new IllegalArgumentException("unknown view container type"); } private SingleViewContainerContext registerView( final IFolderLayout folderLayout, final IViewLayout view, final ComponentContext componentContext, final IFolderContext folderContext) { final String viewId; if (isRCPView(view)) { viewId = filterId(view.getId()); } else { if (view.getScope() == ViewScope.WORKBENCH) { viewId = view.getId(); } else { final String appId = ((WorkbenchApplicationContext) componentContext.getWorkbenchApplicationContext()).getId(); if (view.getScope() == ViewScope.WORKBENCH_APPLICATION) { viewId = appId + "." + view.getId(); } else if (view.getScope() == ViewScope.COMPONENT) { final String componentNodeId = getComponentNodeId((ComponentNodeContext) componentContext.getComponentNodeContext()); viewId = appId + "." + componentNodeId + "." + view.getId(); } else { throw new IllegalArgumentException("unsupported view layout scope: " + view.getScope()); } } viewLayoutContextMap.put(viewId, new ViewLayoutContext(view, componentContext, folderContext)); } return new SingleViewContainerContext(viewId, folderLayout.getViewsCloseable(), view.isDetachable(), isRCPView(view)); } public void showView(final IViewLayout viewLayout, final ComponentContext componentContext, final IFolderContext folderContext) { final String viewId = viewLayout.getId(); try { if (isRCPView(viewLayout)) { showRcpView(viewId); return; } // TODO HW do we have to deal with IViewLayout#getScope? final String primaryViewId = DynamicView.ID + "." + folderContext.getFolderId(); registerFolderView(primaryViewId); viewLayoutContextMap.put(viewId, new ViewLayoutContext(viewLayout, componentContext, folderContext)); PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView( primaryViewId, viewId, IWorkbenchPage.VIEW_CREATE); } catch (final PartInitException e) { throw new RuntimeException(e); } } private boolean isRCPView(final IViewLayout view) { boolean result = false; if (view instanceof RcpView) { result = true; } // TODO: Quickhack --> better check view registry for containedness of viewId else if (view.getId().contains("rcp://")) { result = true; } return result; } private String filterId(final String id) { return id.replace("rcp://", ""); } private void showRcpView(final String viewId) throws PartInitException { final String[] ids = viewId.split(":", 2); String secondaryId = null; if (ids.length == 2) { secondaryId = ids[1]; } PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView( ids[0], secondaryId, IWorkbenchPage.VIEW_CREATE); } public void closeView(final ViewContext viewContext) { for (final Entry<String, ViewContext> viewContextEntry : viewContextMap.entrySet()) { // find viewId if (viewContextEntry.getValue() == viewContext) { final String viewId = viewContextEntry.getKey(); final String primaryViewId = viewContext.getPrimaryViewId(); for (final IWorkbenchPage page : PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPages()) { final IViewReference viewRef = page.findViewReference(primaryViewId, viewId); if (viewRef != null) { closingViewSet.add(viewId); page.hideView(viewRef); break; } } break; } } } public boolean isViewClosing(final String viewId) { return closingViewSet.contains(viewId); } public void activateView(final ViewContext viewContext) { for (final Entry<String, ViewContext> viewContextEntry : viewContextMap.entrySet()) { // find viewId if (viewContextEntry.getValue() == viewContext) { final String viewId = viewContextEntry.getKey(); final String primaryViewId = viewContext.getPrimaryViewId(); for (final IWorkbenchPage page : PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPages()) { final IViewReference viewRef = page.findViewReference(primaryViewId, viewId); if (viewRef != null) { try { page.showView(primaryViewId, viewId, IWorkbenchPage.VIEW_ACTIVATE); } catch (final PartInitException e) { throw new RuntimeException(e); } break; } } break; } } } public void hideView(final ViewContext viewContext) { for (final Entry<String, ViewContext> viewContextEntry : viewContextMap.entrySet()) { // find viewId if (viewContextEntry.getValue() == viewContext) { final String viewId = viewContextEntry.getKey(); final String primaryViewId = viewContext.getPrimaryViewId(); for (final IWorkbenchPage page : PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPages()) { final IViewReference viewRef = page.findViewReference(primaryViewId, viewId); if (viewRef != null) { hidingViewSet.add(viewId); page.hideView(viewRef); break; } } break; } } } public boolean isViewHiding(final String viewId) { return hidingViewSet.contains(viewId); } public void clearViewHiding(final String viewId) { hidingViewSet.remove(viewId); } public void unhideView(final ViewContext viewContext) { for (final Entry<String, ViewContext> viewContextEntry : viewContextMap.entrySet()) { // find viewId if (viewContextEntry.getValue() == viewContext) { final String viewId = viewContextEntry.getKey(); final String primaryViewId = viewContext.getPrimaryViewId(); try { PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView( primaryViewId, viewId, IWorkbenchPage.VIEW_ACTIVATE); } catch (final PartInitException e) { throw new RuntimeException(e); } break; } } } public void registerFolderView(final String primaryViewId) { final ViewRegistry viewRegistry = (ViewRegistry) PlatformUI.getWorkbench().getViewRegistry(); final IViewDescriptor viewDescriptor = viewRegistry.find(primaryViewId); if (viewDescriptor == null) { // register a new dynamic view for this folder final String xml = String.format( "<plugin><extension point='org.eclipse.ui.views' id='%s'><view allowMultiple='true' class='%s' id='%s' name='Dynamic View' restorable='false'></view></extension></plugin>", primaryViewId, DynamicView.class.getName(), primaryViewId); try { final IContributor contributor = ContributorFactoryOSGi.createContributor(Activator.getBundle()); final IExtensionRegistry registry = Platform.getExtensionRegistry(); final Object key = ((ExtensionRegistry) registry).getTemporaryUserToken(); registry.addContribution(new ByteArrayInputStream(xml.getBytes("UTF-8")), contributor, false, null, null, key); final IExtension extension = registry.getExtension("org.eclipse.ui.views", contributor.getName() + "." + primaryViewId); viewRegistry.add(new ViewDescriptor(extension.getConfigurationElements()[0])); } catch (final UnsupportedEncodingException e) { throw new Error(e); } catch (final CoreException e) { throw new RuntimeException(e); } } } public void resetPerspective( final ComponentNodeContext componentTreeNodeContext, final ComponentContext componentContext, final ILayout layout) { final IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); final IPerspectiveDescriptor currentPerspective = activePage.getPerspective(); showPerspective(componentTreeNodeContext, componentContext, layout); activePage.resetPerspective(); activePage.setPerspective(currentPerspective); // initialize views to update view titles from view model initializeViews(); } }