/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG 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: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.navigation.ui.swt.views; import java.util.ArrayList; import java.util.List; import org.osgi.service.log.LogService; import org.eclipse.core.runtime.Assert; import org.eclipse.equinox.log.Logger; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IContributionManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.window.ApplicationWindow; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.CoolBar; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IPerspectiveRegistry; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.WorkbenchException; import org.eclipse.ui.application.ActionBarAdvisor; import org.eclipse.ui.application.IActionBarConfigurer; import org.eclipse.ui.application.IWorkbenchWindowConfigurer; import org.eclipse.ui.application.WorkbenchWindowAdvisor; import org.eclipse.ui.internal.WorkbenchWindow; import org.eclipse.riena.core.Log4r; import org.eclipse.riena.core.wire.InjectExtension; import org.eclipse.riena.internal.navigation.ui.swt.Activator; import org.eclipse.riena.internal.navigation.ui.swt.CoolbarUtils; import org.eclipse.riena.internal.navigation.ui.swt.IAdvisorHelper; import org.eclipse.riena.internal.navigation.ui.swt.RestoreFocusOnEscListener; import org.eclipse.riena.navigation.IApplicationNode; import org.eclipse.riena.navigation.IModuleGroupNode; import org.eclipse.riena.navigation.IModuleNode; import org.eclipse.riena.navigation.INavigationNode; import org.eclipse.riena.navigation.ISubApplicationNode; import org.eclipse.riena.navigation.ISubModuleNode; import org.eclipse.riena.navigation.listener.ApplicationNodeListener; import org.eclipse.riena.navigation.listener.ModuleGroupNodeListener; import org.eclipse.riena.navigation.listener.ModuleNodeListener; import org.eclipse.riena.navigation.listener.NavigationTreeObserver; import org.eclipse.riena.navigation.listener.SubApplicationNodeListener; import org.eclipse.riena.navigation.listener.SubModuleNodeListener; import org.eclipse.riena.navigation.model.ApplicationNode; import org.eclipse.riena.navigation.ui.controllers.ApplicationController; import org.eclipse.riena.navigation.ui.swt.binding.InjectSwtViewBindingDelegate; import org.eclipse.riena.navigation.ui.swt.component.IEntriesProvider; import org.eclipse.riena.navigation.ui.swt.component.MenuCoolBarComposite; import org.eclipse.riena.navigation.ui.swt.component.TitleComposite; import org.eclipse.riena.navigation.ui.swt.lnf.renderer.ShellBorderRenderer; import org.eclipse.riena.navigation.ui.swt.lnf.renderer.ShellRenderer; import org.eclipse.riena.navigation.ui.swt.presentation.SwtViewProvider; import org.eclipse.riena.navigation.ui.swt.presentation.stack.TitlelessStackPresentation; import org.eclipse.riena.navigation.ui.swt.presentation.stack.common.TitlelessStackPresentation3xRAP; import org.eclipse.riena.navigation.ui.swt.statusline.IStatuslineContentFactoryExtension; import org.eclipse.riena.ui.core.resource.IconSize; import org.eclipse.riena.ui.filter.IUIFilter; import org.eclipse.riena.ui.ridgets.swt.uibinding.AbstractViewBindingDelegate; import org.eclipse.riena.ui.swt.DefaultStatuslineContentFactory; import org.eclipse.riena.ui.swt.IStatusLineContentFactory; import org.eclipse.riena.ui.swt.InfoFlyout; import org.eclipse.riena.ui.swt.Statusline; import org.eclipse.riena.ui.swt.StatuslineSpacer; import org.eclipse.riena.ui.swt.facades.SWTFacade; import org.eclipse.riena.ui.swt.lnf.LnFUpdater; import org.eclipse.riena.ui.swt.lnf.LnfKeyConstants; import org.eclipse.riena.ui.swt.lnf.LnfManager; import org.eclipse.riena.ui.swt.lnf.rienadefault.RienaDefaultLnf; import org.eclipse.riena.ui.swt.utils.ImageStore; import org.eclipse.riena.ui.swt.utils.ShellHelper; import org.eclipse.riena.ui.swt.utils.SwtUtilities; import org.eclipse.riena.ui.swt.utils.TestingSupport; import org.eclipse.riena.ui.swt.utils.UIControlsFactory; import org.eclipse.riena.ui.swt.utils.WidgetIdentificationSupport; import org.eclipse.riena.ui.workarea.IWorkareaDefinition; import org.eclipse.riena.ui.workarea.WorkareaManager; public class ApplicationViewAdvisor3xRAP extends WorkbenchWindowAdvisor { private static final Logger LOGGER = Log4r.getLogger(Activator.getDefault(), ApplicationViewAdvisor3xRAP.class); /** * Binding ID */ private static final String INFO_FLYOUT_BINDING_ID = "infoFlyout"; //$NON-NLS-1$ /** * System property defining the initial width of the application window. */ private static final String PROPERTY_RIENA_APPLICATION_WIDTH = "riena.application.width"; //$NON-NLS-1$ /** * System property defining the initial height of the application window. */ private static final String PROPERTY_RIENA_APPLICATION_HEIGHT = "riena.application.height"; //$NON-NLS-1$ /** * System property defining the minimum width of the application window. */ private static final String PROPERTY_RIENA_APPLICATION_MINIMUM_WIDTH = "riena.application.minimum.width"; //$NON-NLS-1$ /** * System property defining the minimum height of the application window. */ private static final String PROPERTY_RIENA_APPLICATION_MINIMUM_HEIGHT = "riena.application.minimum.height"; //$NON-NLS-1$ private static final int DEFAULT_COOLBAR_TOP_MARGIN = 2; enum BtnState { NONE, HOVER, HOVER_SELECTED; } private final ApplicationController controller; private final AbstractViewBindingDelegate binding; private final IAdvisorHelper advisorHelper; private TitleComposite titleComposite; // content factory for delegation of content creation from the statusline private IStatusLineContentFactory statuslineContentFactory; private IWindowNavigator windowNavigator; /** * The application window size minimum. */ private Point applicationSizeMinimum; /** * @noreference This constructor is not intended to be referenced by clients. */ public ApplicationViewAdvisor3xRAP(final IWorkbenchWindowConfigurer configurer, final ApplicationController pController, final IAdvisorHelper helper) { super(configurer); controller = pController; binding = createBinding(); advisorHelper = helper; initializeListener(); } public void addUIControl(final Composite control, final String propertyName) { binding.addUIControl(control, propertyName); } /** * @since 4.0 */ @InjectExtension(min = 0, max = 1) public void updateStatuslineContentFactory(final IStatuslineContentFactoryExtension statuslineContentFactoryExtension) { this.statuslineContentFactory = statuslineContentFactoryExtension == null ? new DefaultStatuslineContentFactory() : statuslineContentFactoryExtension .createFactory(); } public IStatusLineContentFactory getStatuslineContentFactory() { return statuslineContentFactory; } /** * @since 4.0 */ @InjectExtension(min = 0, max = 1) public void updateWindowNavigator(final IWindowNavigatorExtension windowNavigatorExtension) { this.windowNavigator = windowNavigatorExtension == null ? new DefaultWindowNavigator() : windowNavigatorExtension.createWindowNavigator(); } private IWindowNavigator getWindowNavigator() { return windowNavigator; } @Override public final ActionBarAdvisor createActionBarAdvisor(final IActionBarConfigurer configurer) { return advisorHelper.createActionBarAdvisor(configurer); } @Override public void createWindowContents(final Shell shell) { initShell(shell); // create and layouts the composite of switcher, menu, tool bar etc. shell.setLayout(new FormLayout()); final Composite grabCorner = createGrabCorner(shell); createStatusLine(shell, grabCorner); titleComposite = createTitleComposite(shell); final Composite menuBarComposite = createMenuBarComposite(shell, titleComposite); final Composite coolBarComposite = createCoolBarComposite(shell, menuBarComposite); final Composite mainComposite = createMainComposite(shell, coolBarComposite); createInfoFlyout(mainComposite); final RestoreFocusOnEscListener focusListener = new RestoreFocusOnEscListener(shell); focusListener.addControl(RestoreFocusOnEscListener.findCoolBar(menuBarComposite)); focusListener.addControl(RestoreFocusOnEscListener.findCoolBar(coolBarComposite)); } private void createInfoFlyout(final Composite mainComposite) { final InfoFlyout flyout = UIControlsFactory.createInfoFlyout(mainComposite); binding.addUIControl(flyout, INFO_FLYOUT_BINDING_ID); } @Override public void dispose() { super.dispose(); if (titleComposite != null) { titleComposite.dispose(); titleComposite = null; } } @Override public void preWindowOpen() { configureWindow(); } @Override public void postWindowCreate() { super.postWindowCreate(); final Shell shell = getWindowConfigurer().getWindow().getShell(); if (SWTFacade.isRAP()) { shell.setMaximized(true); } else { getWindowNavigator().beforeOpen(shell); } } @Override public void postWindowOpen() { super.postWindowOpen(); doInitialBinding(); final IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); updateApplicationSize(configurer); if (titleComposite != null) { // Redraw so that the active tab is displayed correct titleComposite.setRedraw(false); titleComposite.setRedraw(true); } } @Override public boolean preWindowShellClose() { getWindowNavigator().beforeClose(getWindowConfigurer().getWindow().getShell()); return super.preWindowShellClose(); } /** * Updates the size of the application window (if necessary) according to the dimension of the display. * * @param configurer */ private void updateApplicationSize(final IWorkbenchWindowConfigurer configurer) { final Shell shell = configurer.getWindow().getShell(); final Rectangle maxBounds = ShellHelper.calcMaxBounds(shell); boolean update = false; int x = shell.getLocation().x; int width = shell.getBounds().width; if (width > maxBounds.width) { x = maxBounds.x; width = maxBounds.width; LOGGER.log(LogService.LOG_WARNING, "The width of the application is greater than the maximum width which is " //$NON-NLS-1$ + width); update = true; } int y = shell.getLocation().y; int height = shell.getBounds().height; if (height > maxBounds.height) { y = maxBounds.y; height = maxBounds.height; LOGGER.log(LogService.LOG_WARNING, "The height of the application is greater than the maximum height which is " //$NON-NLS-1$ + height); update = true; } final Point minSize = shell.getMinimumSize(); if (minSize.x > maxBounds.width) { minSize.x = maxBounds.width; update = true; } if (minSize.y > maxBounds.height) { minSize.y = maxBounds.height; update = true; } if (update) { shell.setLocation(x, y); shell.setMinimumSize(minSize); shell.setSize(width, height); } } /** * Creates a delegate for the binding of view and controller. * * @return delegate for binding */ protected AbstractViewBindingDelegate createBinding() { return new InjectSwtViewBindingDelegate(); } // helping methods ////////////////// private void initializeListener() { final NavigationTreeObserver navigationTreeObserver = new NavigationTreeObserver(); navigationTreeObserver.addListener(new MyApplicationNodeListener()); navigationTreeObserver.addListener(new MySubApplicationNodeListener()); navigationTreeObserver.addListener(new MyModuleGroupNodeListener()); navigationTreeObserver.addListener(new MyModuleNodeListener()); navigationTreeObserver.addListener(new MySubModuleNodeListener()); navigationTreeObserver.addListenerTo(controller.getNavigationNode()); } /** * Configures the window of the application. */ private void configureWindow() { final IWorkbenchWindowConfigurer configurer = getWindowConfigurer(); final String label = controller.getNavigationNode().getLabel(); if (label != null) { configurer.setTitle(label); } initApplicationSize(configurer); if (LnfManager.getLnf().getBooleanSetting(LnfKeyConstants.SHELL_HIDE_OS_BORDER) && !TestingSupport.isTestingEnabled()) { // some testing UI tools might not work with windows w/o real decorations(menu, border, etc){ // don't show the shell border (with the minimize, maximize and // close buttons) of the operation system configurer.setShellStyle(SWT.NO_TRIM | SWT.DOUBLE_BUFFERED); } } /** * Reads the two properties for the initial width and the initial height of the application. * * @param configurer */ private void initApplicationSize(final IWorkbenchWindowConfigurer configurer) { int width = Integer.getInteger(PROPERTY_RIENA_APPLICATION_WIDTH, getApplicationSizeMinimum().x); if (width < getApplicationSizeMinimum().x) { width = getApplicationSizeMinimum().x; LOGGER.log(LogService.LOG_WARNING, "The initial width of the application is less than the minimum width which is " //$NON-NLS-1$ + getApplicationSizeMinimum().x); } int height = Integer.getInteger(PROPERTY_RIENA_APPLICATION_HEIGHT, getApplicationSizeMinimum().y); if (height < getApplicationSizeMinimum().y) { height = getApplicationSizeMinimum().y; LOGGER.log(LogService.LOG_WARNING, "The initial height of the application is less than the minimum height which is " //$NON-NLS-1$ + getApplicationSizeMinimum().y); } width = SwtUtilities.convertXToDpi(width); height = SwtUtilities.convertYToDpi(height); configurer.setInitialSize(new Point(width, height)); } private void initApplicationSizeMinimum() { final int widthMinimum = Integer.getInteger(PROPERTY_RIENA_APPLICATION_MINIMUM_WIDTH, getApplicationDefaultSizeMinimum().x); final int heightMinimum = Integer.getInteger(PROPERTY_RIENA_APPLICATION_MINIMUM_HEIGHT, getApplicationDefaultSizeMinimum().y); applicationSizeMinimum = new Point(widthMinimum, heightMinimum); } private Point getApplicationSizeMinimum() { if (applicationSizeMinimum == null) { initApplicationSizeMinimum(); } return applicationSizeMinimum; } private Point getApplicationDefaultSizeMinimum() { return (Point) LnfManager.getLnf().getSetting(LnfKeyConstants.APPLICATION_MIN_SIZE); } private void doInitialBinding() { binding.injectAndBind(controller); controller.afterBind(); } private void createStatusLine(final Composite shell, final Composite grabCorner) { final IStatusLineContentFactory statusLineFactory = getStatuslineContentFactory(); final Statusline statusLine = new Statusline(shell, SWT.None, StatuslineSpacer.class, statusLineFactory); final FormData fd = new FormData(); fd.height = SwtUtilities.convertYToDpi(LnfManager.getLnf().getIntegerSetting(LnfKeyConstants.STATUSLINE_HEIGHT)); final Rectangle navigationBounds = TitlelessStackPresentation3xRAP.calcNavigationBounds(shell); fd.left = new FormAttachment(0, navigationBounds.x); if (grabCorner != null) { fd.right = new FormAttachment(grabCorner, 0); } else { final int padding = getShellPadding(); fd.right = new FormAttachment(100, -padding); } fd.bottom = new FormAttachment(100, SwtUtilities.convertYToDpiTruncate(-5)); statusLine.setLayoutData(fd); addUIControl(statusLine, "statusline"); //$NON-NLS-1$ LnFUpdater.getInstance().updateUIControls(statusLine, true); } /** * Initializes the given shell. * * @param shell * shell to initialize */ private void initShell(final Shell shell) { shell.setBackground(LnfManager.getLnf().getColor(LnfKeyConstants.TITLELESS_SHELL_BACKGROUND)); shell.addPaintListener(new ShellPaintListener()); final String iconName = controller.getNavigationNode().getIcon(); shell.setImage(ImageStore.getInstance().getImage(iconName)); Point minimum = getApplicationSizeMinimum(); minimum = new Point(SwtUtilities.convertXToDpi(minimum.x), SwtUtilities.convertXToDpi(minimum.y)); shell.setMinimumSize(minimum); // prepare shell for binding addUIControl(shell, ApplicationViewAdvisor.SHELL_RIDGET_PROPERTY); if (getShellRenderer() != null) { getShellRenderer().setShell(shell); } // TODO check if this is the main window. maybe support more then one workbench window. WidgetIdentificationSupport.setIdentification(shell); } /** * Create the composite that contains the: * <ul> * <li>shell title and title buttons</li> * <li>the logo</li> * <li>the sub application switcher</li> * </ul> * * @param parentShell * the parent shell (non null) * @return the title composite (never null) */ private TitleComposite createTitleComposite(final Shell parentShell) { final ApplicationNode node = (ApplicationNode) controller.getNavigationNode(); return new TitleComposite(parentShell, node); } /** * Creates and positions the corner to grab. * * @param shell */ private org.eclipse.riena.ui.swt.GrabCorner createGrabCorner(final Shell shell) { if (org.eclipse.riena.ui.swt.GrabCorner.isResizeable() && LnfManager.getLnf().getBooleanSetting(LnfKeyConstants.SHELL_HIDE_OS_BORDER)) { return new org.eclipse.riena.ui.swt.GrabCorner(shell, SWT.DOUBLE_BUFFERED); } return null; } /** * Creates and positions the composite for the menu bar. * * @param parent * parent of composite * @param previous * previous composite in the layout * @return composite */ private Composite createMenuBarComposite(final Composite parent, final Composite previous) { Assert.isTrue(parent.getLayout() instanceof FormLayout); final int padding = getShellPadding(); // menu bar final IWorkbenchWindow window = getWindowConfigurer().getWindow(); final IEntriesProvider entriesProvider = new IEntriesProvider() { /** * Returns the top-level menu entries. */ @SuppressWarnings("restriction") public IContributionItem[] getTopLevelEntries() { if (window instanceof WorkbenchWindow) { final MenuManager menuManager = ((WorkbenchWindow) window).getMenuManager(); ImageReplacer.getInstance().replaceImagesOfManager(menuManager,((IconSize)LnfManager.getLnf().getSetting(LnfKeyConstants.MENUBAR_ICON_SIZE))); return menuManager.getItems(); } return new IContributionItem[0]; } }; final MenuCoolBarComposite composite = new MenuCoolBarComposite(parent, SWT.NONE, entriesProvider); final FormData formData = new FormData(); formData.top = new FormAttachment(previous, getMenuBarTopMargin()); formData.left = new FormAttachment(0, padding); formData.right = new FormAttachment(100, -padding); composite.setLayoutData(formData); return composite; } /** * Creates and positions the composite for the cool bar. * * @param parent * parent of composite * @param previous * previous composite in the layout * @return composite */ private Composite createCoolBarComposite(final Composite parent, Composite previous) { Assert.isTrue(parent.getLayout() instanceof FormLayout); final Composite separator = UIControlsFactory.createSeparator(parent, SWT.HORIZONTAL); FormData formData = new FormData(); formData.top = new FormAttachment(previous); formData.left = new FormAttachment(0, getBorderWidth()); formData.right = new FormAttachment(100, -getBorderWidth()); formData.height = SwtUtilities.convertYToDpi(2); separator.setLayoutData(formData); previous = separator; final int padding = getShellPadding(); final Composite result = new Composite(parent, SWT.NONE); result.setLayout(new FillLayout()); formData = new FormData(); formData.top = new FormAttachment(previous, getToolBarTopMargin()); formData.left = new FormAttachment(0, padding); formData.right = new FormAttachment(100, -padding); result.setLayoutData(formData); replaceImagesOfCoolBar(); final Control control = getWindowConfigurer().createCoolBarControl(result); if (control instanceof CoolBar) { final CoolBar coolbar = (CoolBar) control; CoolbarUtils.initCoolBar(coolbar, getToolbarFont()); } return result; } /** * Replaces all not scaled images of the cool bar items, if necessary. */ private void replaceImagesOfCoolBar() { final IWorkbenchWindow window = getWindowConfigurer().getWindow(); if (window instanceof ApplicationWindow) { final IContributionManager coolBarManager = ((ApplicationWindow) window).getCoolBarManager(); ImageReplacer.getInstance().replaceImagesOfManager(coolBarManager,((IconSize)LnfManager.getLnf().getSetting(LnfKeyConstants.TOOLBAR_ICON_SIZE))); } } private int getBorderWidth() { int width = 2; final ShellBorderRenderer shellBorderRenderer = (ShellBorderRenderer) LnfManager.getLnf().getRenderer(LnfKeyConstants.TITLELESS_SHELL_BORDER_RENDERER); if (shellBorderRenderer != null) { width = shellBorderRenderer.getBorderWidth(); // don't scale! } return width; } private static Font getToolbarFont() { return LnfManager.getLnf().getFont(LnfKeyConstants.TOOLBAR_FONT); } /** * Creates the main composite. * * @param parent * parent of composite * @param previous * previous composite in the layout * @return composite */ private Composite createMainComposite(final Composite parent, final Composite previous) { Assert.isTrue(parent.getLayout() instanceof FormLayout); final int padding = getShellPadding(); final Composite composite = new Composite(parent, SWT.DOUBLE_BUFFERED); composite.setLayout(new FillLayout()); final FormData formData = new FormData(); formData.top = new FormAttachment(previous, LnfManager.getLnf().getIntegerSetting(LnfKeyConstants.TOOLBAR_WORK_AREA_VERTICAL_GAP), 0); formData.bottom = new FormAttachment(100, -padding); formData.left = new FormAttachment(0, padding); formData.right = new FormAttachment(100, -padding); composite.setLayoutData(formData); getWindowConfigurer().createPageComposite(composite); return composite; } /** * Returns the padding between shell border and content. * * @return padding */ private int getShellPadding() { final ShellBorderRenderer borderRenderer = (ShellBorderRenderer) LnfManager.getLnf().getRenderer(LnfKeyConstants.TITLELESS_SHELL_BORDER_RENDERER); return borderRenderer.getCompleteBorderWidth(); } /** * Returns the renderer of the shell. * * @return renderer */ private ShellRenderer getShellRenderer() { final ShellRenderer shellRenderer = (ShellRenderer) LnfManager.getLnf().getRenderer(LnfKeyConstants.TITLELESS_SHELL_RENDERER); return shellRenderer; } /** * Returns the margin above the menu bar. * * @return top margin */ private int getMenuBarTopMargin() { final RienaDefaultLnf lnf = LnfManager.getLnf(); return lnf.getIntegerSetting(LnfKeyConstants.MENUBAR_TOP_MARGIN, DEFAULT_COOLBAR_TOP_MARGIN); } /** * Returns the margin above the tool bar. * * @return top margin */ private int getToolBarTopMargin() { final RienaDefaultLnf lnf = LnfManager.getLnf(); return lnf.getIntegerSetting(LnfKeyConstants.TOOLBAR_TOP_MARGIN, DEFAULT_COOLBAR_TOP_MARGIN); } private IWorkbenchPage getActivePage() { return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); } // helping classes ////////////////// private class MyApplicationNodeListener extends ApplicationNodeListener { @Override public void filterAdded(final IApplicationNode source, final IUIFilter filter) { show(); } @Override public void filterRemoved(final IApplicationNode source, final IUIFilter filter) { show(); } private void show() { if (controller == null || controller.getNavigationNode() == null || controller.getNavigationNode().isDisposed()) { return; } try { final IViewPart vp = getNavigationViewPart(); if (vp == null) { final NavigationViewPart navi = (NavigationViewPart) getActivePage().showView(NavigationViewPart.ID); navi.updateNavigationSize(); } } catch (final PartInitException e) { throw new UIViewFailure(e.getMessage(), e); } } /** * Returns the view part of the navigation. * * @return view part of the navigation or */ private IViewPart getNavigationViewPart() { final IViewReference[] references = getActivePage().getViewReferences(); for (final IViewReference viewReference : references) { if (viewReference.getId().equals(NavigationViewPart.ID)) { return viewReference.getView(true); } } return null; } } private class MySubApplicationNodeListener extends SubApplicationNodeListener { /** * {@inheritDoc} * <p> * Shows the specified perspective (sub-application). */ @Override public void activated(final ISubApplicationNode source) { if (source != null) { showPerspective(source); if (titleComposite != null) { // Redraw so that the active tab is displayed correct titleComposite.setRedraw(false); titleComposite.setRedraw(true); } prepare(source); } super.activated(source); } private void showPerspective(final ISubApplicationNode source) { try { final IWorkbench workbench = PlatformUI.getWorkbench(); workbench.showPerspective(SwtViewProvider.getInstance().getSwtViewId(source).getId(), workbench.getActiveWorkbenchWindow()); } catch (final WorkbenchException e) { throw new UIViewFailure(e.getMessage(), e); } } @Override public void disposed(final ISubApplicationNode source) { final SwtViewProvider viewProvider = SwtViewProvider.getInstance(); final String id = viewProvider.getSwtViewId(source).getId(); final IWorkbench workbench = PlatformUI.getWorkbench(); final IPerspectiveRegistry registry = workbench.getPerspectiveRegistry(); final IPerspectiveDescriptor perspDesc = registry.findPerspectiveWithId(id); getActivePage().closePerspective(perspDesc, false, false); viewProvider.unregisterSwtViewId(source); } } /** * This listener of a module group ensures the preparation of nodes (if necessary). */ private class MyModuleGroupNodeListener extends ModuleGroupNodeListener { /** * {@inheritDoc} * <p> * After activation of a module group prepare - if necessary - every child (sub module) node. */ @Override public void activated(final IModuleGroupNode source) { prepare(source); super.activated(source); } /** * {@inheritDoc} * <p> * After the parent of a module group changed prepare - if necessary - every child node. */ @Override public void parentChanged(final IModuleGroupNode source) { super.parentChanged(source); prepare(source); } } /** * This listener of a module ensures the preparation of nodes (if necessary). */ private class MyModuleNodeListener extends ModuleNodeListener { /** * {@inheritDoc} * <p> * After activation of a module prepare - if necessary - every child (sub module) node. */ @Override public void activated(final IModuleNode source) { prepare(source); super.activated(source); } /** * {@inheritDoc} * <p> * After the parent of a module changed prepare - if necessary - every child node. */ @Override public void parentChanged(final IModuleNode source) { super.parentChanged(source); prepare(source); } } /** * This listener of a sub module ensures the preparation of nodes (if necessary). */ private class MySubModuleNodeListener extends SubModuleNodeListener { /** * {@inheritDoc} * <p> * After activation of a sub module prepare - if necessary - every child node. */ @Override public void activated(final ISubModuleNode source) { prepare(source); super.activated(source); } /** * {@inheritDoc} * <p> * After the parent of a sub module changed prepare - if necessary - every child node. */ @Override public void parentChanged(final ISubModuleNode source) { super.parentChanged(source); prepare(source); } } /** * Prepares every sub-module whose definition requires preparation. * * @param node * navigation node */ private void prepare(final INavigationNode<?> node) { if ((node == null) || (node.getParent() == null)) { return; } if (node instanceof ISubModuleNode) { final ISubModuleNode subModuleNode = (ISubModuleNode) node; final IWorkareaDefinition definition = WorkareaManager.getInstance().getDefinition(subModuleNode); if ((definition != null) && definition.isRequiredPreparation() && subModuleNode.isCreated()) { subModuleNode.prepare(); } } /* * The number of children can change while iterating. Only observe the node children !before! the iteration begins. Any child added while iterating will * be handled automatically if preparation is required. Just ensure that there will be no concurrent modification of the children list while iterating * over it. Conclusion is a copy.. */ final List<INavigationNode<?>> children = new ArrayList<INavigationNode<?>>(node.getChildren()); for (final INavigationNode<?> child : children) { prepare(child); } } }