/******************************************************************************* * 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.internal.design.example.stacks; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.rap.internal.design.example.ILayoutSetConstants; import org.eclipse.rap.internal.design.example.builder.StackPresentationBuider; import org.eclipse.rap.ui.interactiondesign.ConfigurableStack; import org.eclipse.rap.ui.interactiondesign.ConfigurationAction; import org.eclipse.rap.ui.interactiondesign.IConfigurationChangeListener; import org.eclipse.rap.ui.interactiondesign.PresentationFactory; import org.eclipse.rap.ui.interactiondesign.layout.ElementBuilder; import org.eclipse.rwt.lifecycle.WidgetUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IPropertyListener; import org.eclipse.ui.ISaveablePart; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.PartPane; import org.eclipse.ui.internal.presentations.PresentablePart; import org.eclipse.ui.presentations.IPartMenu; import org.eclipse.ui.presentations.IPresentablePart; import org.eclipse.ui.presentations.IStackPresentationSite; import org.eclipse.ui.presentations.StackDropResult; public class ViewStackPresentation extends ConfigurableStack { private static final String VARIANT_PART_INACTIVE = "partInactive"; private static final String VARIANT_PART_ACTIVE = "partActive"; private static final String VARIANT_PART_INACTIVE_ACTIVE = "partInActiveActive"; private static final int BUTTON_SPACING = 6; private static final String ID_CLOSE = "close"; private static final String BUTTON_ID = "buttonId"; private static final int WIDTH_SPACING = 65; private static final int HEIGHT_SPACING = 15; private Control presentationControl; private IPresentablePart currentPart; private ElementBuilder stackBuilder; private Composite tabBg; private Composite confArea; private Button confButton; private Label confCorner; private Map partButtonMap = new HashMap(); private List partList = new ArrayList(); private List buttonList = new ArrayList(); private Composite toolbarBg; private Shell toolBarLayer; private int activeState; private int state; protected boolean deactivated; private Button viewMenuButton; private Map dirtyListenerMap = new HashMap(); private Button overflowButton; private List overflowButtons = new ArrayList(); private Map buttonPartMap = new HashMap(); private IPresentablePart oldPart; private boolean allActionsVisible; private class DirtyListener implements IPropertyListener { private IPresentablePart part; public DirtyListener( final IPresentablePart part ) { this.part = part; } public void propertyChanged( Object source, int propId ) { if( propId == ISaveablePart.PROP_DIRTY ) { Button partButton = getPartButton( part ); if( partButton != null ) { String text = partButton.getText(); char lastCharacter = getLastCharacter( text ); if( part.isDirty() ) { // mark the part as dirty if( lastCharacter != '*') { text = text + "*"; } } else { // mark the part as clean if( lastCharacter == '*' ) { text = text.substring( 0, text.length() - 1 ); } } partButton.setText( text ); } } } private Button getPartButton( final IPresentablePart part ) { Button result = null; Object object = partButtonMap.get( part ); if( object instanceof Composite ) { Control[] children = ( ( Composite ) object ).getChildren(); if( children.length > 0 && children[ 0 ] instanceof Button ) { result = ( Button ) children[ 0 ]; } } return result; } private char getLastCharacter( final String text ) { char[] starArray = new char[ 1 ]; text.getChars( text.length()-1, text.length(), starArray, 0); return starArray[ 0 ]; } }; public ViewStackPresentation() { activeState = AS_INACTIVE; deactivated = false; allActionsVisible = ConfigAction.allActionsVisible(); } public void init() { ConfigurationAction action = getConfigAction(); if( action != null ) { action.addConfigurationChangeListener( new IConfigurationChangeListener(){ public void toolBarChanged() { ViewToolBarRegistry registry = ViewToolBarRegistry.getInstance(); registry.fireToolBarChanged( ); } public void presentationChanged( final String newStackPresentationId ) { // do nothing atm } } ); } presentationControl = createStyledControl(); ViewToolBarRegistry registry = ViewToolBarRegistry.getInstance(); registry.addViewPartPresentation( this ); } void catchToolbarChange() { layoutToolBar(); setBounds( presentationControl.getBounds() ); } private void createToolBarBg() { Composite tabBar = getTabBar(); toolbarBg = new Composite( tabBar.getParent(), SWT.NONE ); toolbarBg.setLayout( new FormLayout() ); Image bg = stackBuilder.getImage( ILayoutSetConstants.STACK_VIEW_TOOLBAR_BG ); toolbarBg.setBackgroundImage( bg ); FormData fdToolBar = new FormData(); toolbarBg.setLayoutData( fdToolBar ); fdToolBar.left = new FormAttachment( 0 ); fdToolBar.right = new FormAttachment( 100 ); fdToolBar.top = new FormAttachment( tabBar ); fdToolBar.height = bg.getBounds().height; toolbarBg.moveAbove( tabBar ); } private Control createStyledControl() { getParent().setData( WidgetUtil.CUSTOM_VARIANT, "compGray" ); final Composite parent = new Composite( getParent(), SWT.NONE ); parent.addControlListener( new ControlAdapter() { public void controlResized( ControlEvent e ) { setBounds( parent.getBounds() ); }; } ); parent.setData( WidgetUtil.CUSTOM_VARIANT, "compGray" ); String setID = ILayoutSetConstants.SET_ID_STACKPRESENTATION; stackBuilder = new StackPresentationBuider( parent, setID ); stackBuilder.build(); return parent; } private boolean isStandalone() { return getType().equals( PresentationFactory.KEY_STANDALONE_VIEW ); } public void addPart( final IPresentablePart newPart, final Object cookie ) { checkTabBg(); if( !isStandalone() ) { createPartButton( newPart ); partList.add( newPart ); Control partControl = newPart.getControl(); if( partControl != null ) { partControl.getParent().setBackgroundMode( SWT.INHERIT_NONE ); partControl.setData( WidgetUtil.CUSTOM_VARIANT, "partBorder" ); } tabBg.layout( true ); } else { decorateStandaloneView( newPart ); } // add the listener for the dirty activeState IPropertyListener listener = new DirtyListener( newPart ); dirtyListenerMap.put( newPart, listener ); newPart.addPropertyListener( listener ); } private void decorateStandaloneView( final IPresentablePart newPart ) { checkTabBg(); if( getShowTitle() ) { getTabBar().setVisible( true ); tabBg.setVisible( true ); Label title = new Label( tabBg, SWT.NONE ); title.setData( WidgetUtil.CUSTOM_VARIANT, "standaloneView" ); title.setText( newPart.getName() ); hideFrameLabel( StackPresentationBuider.TOP_BORDER ); } else { getTabBar().setVisible( false ); hideFrameLabel( StackPresentationBuider.LEFT ); hideFrameLabel( StackPresentationBuider.RIGHT ); } } private void hideFrameLabel( final String id ) { Object labelMap = stackBuilder.getAdapter( Map.class ); if( labelMap != null && ( labelMap instanceof Map ) ) { Map map = ( Map ) labelMap; Object object = map.get( id ); if( object != null ) { Label frameLabel = ( Label)object; frameLabel.setVisible( false ); } } } private void layoutToolBar() { if( toolbarBg == null && tabBg != null ) { createToolBarBg(); } if( currentPart != null && getPartPane( currentPart ) != null ) { Control toolBar = currentPart.getToolBar(); final IPartMenu viewMenu = currentPart.getMenu(); // viewmenu if( viewMenu != null ) { if( viewMenuButton == null ) { viewMenuButton = new Button( toolbarBg, SWT.PUSH ); viewMenuButton.setData( WidgetUtil.CUSTOM_VARIANT, "clearButton" ); Image icon = stackBuilder.getImage( ILayoutSetConstants.STACK_VIEW_MENU_ICON ); viewMenuButton.setImage( icon ); FormData fdViewMenuButton = new FormData(); viewMenuButton.setLayoutData( fdViewMenuButton ); fdViewMenuButton.right = new FormAttachment( 100, -4 ); fdViewMenuButton.top = new FormAttachment( 0, 8 ); viewMenuButton.addSelectionListener( new SelectionAdapter() { public void widgetSelected( final SelectionEvent e ) { Display display = viewMenuButton.getDisplay(); int height = viewMenuButton.getSize().y; Point newLoc = display.map( viewMenuButton, null, 0, height ); viewMenu.showMenu( newLoc ); }; } ); } } else if( viewMenuButton != null ) { viewMenuButton.setVisible( false ); viewMenuButton.dispose(); viewMenuButton = null; } // toolbar Point size = toolbarBg.getSize(); if( toolBar != null ) { Point point = currentPart.getControl().getLocation(); point.y -= ( size.y + 2 ); point.x += ( size.x - toolBar.getSize().x ); if( viewMenu != null ) { point.x -= 20; } toolBar.setLocation( point ); toolbarBg.moveBelow( toolBar ); presentationControl.moveBelow( toolBar ); currentPart.getControl().moveBelow( toolBar ); } // toolbarbg and layer if( toolBar != null || viewMenu != null ) { toolbarBg.setVisible( true ); // Toolbar Layer if( !deactivated ) { getToolBarLayer(); if( toolBarLayer != null ) { toolBarLayer.setVisible( false ); if( activeState != AS_ACTIVE_FOCUS ) { Display display = toolBarLayer.getDisplay(); Point newLocation = display.map( toolbarBg, null, 0, 0 ); toolBarLayer.setBounds( newLocation.x, newLocation.y, size.x, size.y - 1 ); toolBarLayer.moveAbove( toolBar ); toolBarLayer.setVisible( true ); } } } } else { toolbarBg.setVisible( false ); } toolbarBg.layout( true ); } handleConfigurationButton(); } /* * Deactivates the configuration button if the current part has nothing to * configure. */ private void handleConfigurationButton() { boolean hasViewMenu = false; if( currentPart != null && currentPart instanceof PresentablePart ) { PresentablePart part = ( PresentablePart ) currentPart; if( part.getPane() != null ) { hasViewMenu = part.getPane().hasViewMenu(); IToolBarManager manager = getPartToolBarManager(); boolean hasViewActions = manager != null && manager.getItems().length > 0; if( ( hasViewActions || hasViewMenu ) && !allActionsVisible ) { if( confButton != null ) { // enable conf button confButton.setEnabled( true ); String toolTip = "Configure the actions and viewmenu from " + currentPart.getName(); confButton.setToolTipText( toolTip ); } } else { if( confButton != null ) { // disable conf button confButton.setEnabled( false ); String toolTip = currentPart.getName() + " has no actions or viewmenu to configure"; confButton.setToolTipText( toolTip ); } } } } } private void createPartButton( final IPresentablePart part ) { Composite buttonArea = new Composite( tabBg, SWT.NONE ); buttonArea.setData( WidgetUtil.CUSTOM_VARIANT, "inactiveButton" ); buttonArea.setLayout( new FormLayout() ); final Button partButton = new Button( buttonArea, SWT.PUSH ); partButton.setData( WidgetUtil.CUSTOM_VARIANT, VARIANT_PART_INACTIVE ); partButton.setText( part.getName() ); partButton.setToolTipText( part.getTitleToolTip() ); final IPropertyListener nameListener = new IPropertyListener() { public void propertyChanged( final Object source, final int propId ) { if( propId == IPresentablePart.PROP_PART_NAME ) { partButton.setText( part.getName() ); tabBg.layout(); } else if( propId == IPresentablePart.PROP_TITLE ) { partButton.setToolTipText( part.getTitleToolTip() ); } } }; part.addPropertyListener( nameListener ); partButton.addDisposeListener( new DisposeListener() { public void widgetDisposed( final DisposeEvent event ) { partButton.removeDisposeListener( this ); part.removePropertyListener( nameListener ); } } ); FormData fdPartButton = new FormData(); partButton.setLayoutData( fdPartButton ); fdPartButton.left = new FormAttachment( 0 ); fdPartButton.top = new FormAttachment( 0, 4 ); fdPartButton.bottom = new FormAttachment( 100 ); partButton.addSelectionListener( new SelectionAdapter() { public void widgetSelected( final SelectionEvent e ) { if( !currentPart.equals( part ) ) { selectPart( part ); } activatePart( part ); if( toolBarLayer != null ) { toolBarLayer.setVisible( false ); } // move the toolbar on top currentPart.getControl().moveAbove( null ); Control toolBar = currentPart.getToolBar(); if( toolBar != null ) { toolBar.moveAbove( null ); } }; } ); partButton.addListener( SWT.MouseDoubleClick, new Listener() { public void handleEvent( final Event event ) { handleToggleZoom( part ); } } ); Composite corner = new Composite( buttonArea, SWT.NONE ); corner.setData( WidgetUtil.CUSTOM_VARIANT, "compTrans" ); corner.setLayout( new FormLayout() ); String separatorActive = ILayoutSetConstants.STACK_TAB_INACTIVE_SEPARATOR_ACTIVE; Image cornerImage = stackBuilder.getImage( separatorActive ); FormData fdCorner = new FormData(); corner.setLayoutData( fdCorner ); fdCorner.right = new FormAttachment( 100 ); fdCorner.bottom = new FormAttachment( 100 ); fdCorner.width = cornerImage.getBounds().width; fdCorner.height = cornerImage.getBounds().height; fdPartButton.height = cornerImage.getBounds().height; fdPartButton.right = new FormAttachment( corner, -8 ); partButtonMap.put( part, buttonArea ); buttonPartMap.put( buttonArea, part ); buttonList.add( buttonArea ); } private void handleToggleZoom( final IPresentablePart part ) { IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); IWorkbenchPage page = window.getActivePage(); page.toggleZoom( getReference( part ) ); handleToolbarsOnToggleZoom(); } private void handleToolbarsOnToggleZoom() { ViewToolBarRegistry registry = ViewToolBarRegistry.getInstance(); if( state == IStackPresentationSite.STATE_MAXIMIZED ) { registry.moveAllToolbarsBellow( null ); } else if( state == IStackPresentationSite.STATE_RESTORED ) { registry.fireToolBarChanged(); } if( toolBarLayer != null ) { toolBarLayer.setVisible( false ); } if( currentPart != null ) { currentPart.getControl().moveAbove( null ); Control toolBar = currentPart.getToolBar(); if( toolBar != null ) { toolBar.moveAbove( null ); } } } public void hideAllToolBars( final Control control ) { for( int i = 0; i < partList.size(); i++ ) { IPresentablePart part = ( IPresentablePart )partList.get( i ); Control toolBar = part.getToolBar(); if( toolBar != null ) { toolBar.moveBelow( control ); } } } protected void activatePart( final IPresentablePart part ) { IWorkbench workbench = PlatformUI.getWorkbench(); IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); IWorkbenchPage activePage = window.getActivePage(); IWorkbenchPart workbenchPart = getReference( part ).getPart( true ); if( workbenchPart != null ) { if( oldPart != null ) { Control toolBar = oldPart.getToolBar(); if( toolBar != null ) { toolBar.setVisible( false ); } } activePage.activate( workbenchPart ); } } private IWorkbenchPartReference getReference( final IPresentablePart part) { IWorkbenchPartReference result = null; if( part instanceof PresentablePart ) { PresentablePart presentablePart = ( PresentablePart ) part; PartPane pane = presentablePart.getPane(); result = pane.getPartReference(); } return result; } private void makePartButtonActive( final IPresentablePart part ) { Object object = partButtonMap.get( part ); if( object instanceof Composite ) { Composite buttonArea = ( Composite ) object; buttonArea.setData( WidgetUtil.CUSTOM_VARIANT, "tabInactive" ); checkHideSeparator( buttonArea ); Color bg = stackBuilder.getColor( ILayoutSetConstants.STACK_BUTTON_INACTIVE ); buttonArea.setBackground( bg ); Control[] children = buttonArea.getChildren(); buttonArea.setLayout( new FormLayout() ); for( int i = 0; i < children.length; i++ ) { Control child = children[ i ]; if( child instanceof Button ) { // Partbutton Button partButton = ( Button ) child; partButton.setData( WidgetUtil.CUSTOM_VARIANT, VARIANT_PART_ACTIVE ); FormData fdButton = ( FormData ) partButton.getLayoutData(); FormData pos = stackBuilder.getPosition( ILayoutSetConstants.STACK_BUTTON_TOP ); fdButton.top = pos.top; } else if( child instanceof Composite ) { // Corner Composite corner = ( Composite ) child; corner.setVisible( true ); String cornerDesc = ILayoutSetConstants.STACK_TAB_INACTIVE_CORNER_ACTIVE; Image cornerImage = stackBuilder.getImage( cornerDesc ); corner.setBackgroundImage( null ); FormData fdCorner = ( FormData ) corner.getLayoutData(); fdCorner.top = new FormAttachment( 0 ); fdCorner.width = cornerImage.getBounds().width; fdCorner.height = cornerImage.getBounds().height; if( part.isCloseable() ) { Button close = new Button( buttonArea, SWT.PUSH ); close.setData( BUTTON_ID, ID_CLOSE ); close.setData( WidgetUtil.CUSTOM_VARIANT, "viewCloseInactive" ); close.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { IStackPresentationSite site = getSite(); if( site.isCloseable( part ) ) { site.close( new IPresentablePart[] { part } ); showPartButton( currentPart ); } }; } ); FormData fdClose = new FormData(); close.setLayoutData( fdClose ); fdClose.right = new FormAttachment( 100, -5 ); fdClose.top = new FormAttachment( 0, 6 ); fdClose.width = 7; fdClose.height = 8; close.setLayoutData( fdClose ); close.moveAbove( corner ); } } } buttonArea.getParent().layout(); preventButtonOfOverflow(); } } private void preventButtonOfOverflow() { if( isOverflowNecessary() ) { showPartButton( currentPart ); } } private void checkHideSeparator( final Composite buttonArea ) { int indexOf = buttonList.indexOf( buttonArea ); for( int i = 0; i < buttonList.size(); i++ ) { Composite area = ( Composite ) buttonList.get( i ); Control[] children = area.getChildren(); for( int j = 0; j < children.length; j++ ) { if( children[ j ] instanceof Composite ) { if( i == indexOf || ( i == indexOf - 1 ) ) { ( ( Composite ) children[ j ] ).setVisible( false ); } else { ( ( Composite ) children[ j ] ).setVisible( true ); } } } } } private void makePartButtonInactive( final IPresentablePart part ) { Object object = partButtonMap.get( part ); if( object instanceof Composite ) { Composite buttonArea = ( Composite ) object; buttonArea.setData( WidgetUtil.CUSTOM_VARIANT, "inactiveButton" ); buttonArea.setBackground( null ); Control[] children = buttonArea.getChildren(); for( int i = 0; i < children.length; i++ ) { Control child = children[ i ]; if( child instanceof Button ) { Button button = ( Button ) child; // Partbutton if( button.getData( BUTTON_ID ) != null ) { // close button button.setVisible( false ); button.dispose(); } else { // Part button button.setData( WidgetUtil.CUSTOM_VARIANT, VARIANT_PART_INACTIVE ); FormData fdButton = ( FormData ) button.getLayoutData(); fdButton.top = new FormAttachment( 0, 0 ); } } else if( child instanceof Composite ) { // Corner Composite corner = ( Composite ) child; corner.setVisible( true ); String sepConst = ILayoutSetConstants.STACK_TAB_INACTIVE_SEPARATOR_ACTIVE; Image cornerImage = stackBuilder.getImage( sepConst ); corner.setBackgroundImage( cornerImage ); FormData fdCorner = ( FormData ) corner.getLayoutData(); fdCorner.width = cornerImage.getBounds().width; fdCorner.height = cornerImage.getBounds().height; fdCorner.top = new FormAttachment( 0, 6 ); } } buttonArea.getParent().layout(); } } /* * check if the tabBg exists. If not it will create it. */ private void checkTabBg() { Composite tabBar = getTabBar(); if( tabBg == null && tabBar != null ) { tabBg = new Composite( tabBar, SWT.NONE ); tabBg.setData( WidgetUtil.CUSTOM_VARIANT, "compTrans" ); FormData fdTabBg = new FormData(); tabBg.setLayoutData( fdTabBg ); fdTabBg.left = new FormAttachment( 0 ); fdTabBg.top = new FormAttachment( 0 ); fdTabBg.bottom = new FormAttachment( 100 ); createConfArea( fdTabBg ); FormData fdLayout = stackBuilder.getPosition( ILayoutSetConstants.STACK_TABBG_POS ); RowLayout layout = new RowLayout( SWT.HORIZONTAL ); layout.spacing = 0; layout.marginBottom = 0; if( !isStandalone() ) { layout.marginHeight = 0; layout.marginLeft = fdLayout.width; } else { layout.marginHeight = 4; layout.marginLeft = BUTTON_SPACING; } layout.marginRight = 16; layout.marginTop = fdLayout.height; layout.marginWidth = 0; layout.wrap = false; tabBg.setLayout( layout ); // calculate overflow presentationControl.addControlListener( new ControlAdapter() { public void controlResized( final ControlEvent e ) { manageOverflow(); }; } ); } } private void manageOverflow() { if( isOverflowNecessary() ) { hideLastVisibleButton(); manageOverflow(); } else { showLastChildIfNecessary( 0 ); } handleOverflowButton(); } private boolean isOverflowNecessary() { int tabChildrenSize = getTabChildrenSize(); boolean childrenBiggerThanParent = tabChildrenSize > tabBg.getBounds().width; return childrenBiggerThanParent && moreThanOneChildVisible(); } private boolean moreThanOneChildVisible() { boolean result = false; Control[] children = tabBg.getChildren(); int visibleChilds = 0; for( int i = 0; i < children.length && !result; i++ ) { if( children[ i ].isVisible() ) { visibleChilds++; if( visibleChilds > 1 ) { result = true; } } } return result; } private void handleOverflowButton() { if( overflowButton == null ) { overflowButton = new Button( tabBg.getParent(), SWT.PUSH ); String stackOverflowPosition = ILayoutSetConstants.STACK_OVERFLOW_POSITION; FormData fdOverflowButton = stackBuilder.getPosition( stackOverflowPosition ); overflowButton.setLayoutData( fdOverflowButton ); String stackTabOverflowActive = ILayoutSetConstants.STACK_TAB_OVERFLOW_ACTIVE; Image icon = stackBuilder.getImage( stackTabOverflowActive ); fdOverflowButton.height = icon.getBounds().height; fdOverflowButton.width = icon.getBounds().width; String variant = "tabOverflowInactive"; if( activeState == AS_ACTIVE_FOCUS ) { variant = "tabOverflowActive"; } overflowButton.setData( WidgetUtil.CUSTOM_VARIANT, variant ); overflowButton.moveAbove( tabBg ); overflowButton.addSelectionListener( new SelectionAdapter() { public void widgetSelected( final SelectionEvent e ) { performOverflow(); }; } ); } if( tabBgHasInvisibleButtons() ) { overflowButton.setVisible( true ); } else { overflowButton.setVisible( false ); } } private void performOverflow() { activatePart( currentPart ); Menu overflowMenu = new Menu( overflowButton ); for( int i = 0; i < overflowButtons.size(); i++ ) { Object obj = buttonPartMap.get( overflowButtons.get( i ) ); final IPresentablePart part = ( IPresentablePart ) obj; MenuItem item = new MenuItem( overflowMenu, SWT.PUSH ); if( part != null ) { item.setText( part.getName() ); item.addSelectionListener( new SelectionAdapter() { public void widgetSelected( final SelectionEvent e ) { activatePart( part ); showPartButton( part ); }; } ); } } // show popup overflowButton.setMenu( overflowMenu ); overflowMenu.setVisible( true ); Display display = overflowButton.getDisplay(); Point newLocation = display.map( overflowButton, null, 0, 10 ); overflowMenu.setLocation( newLocation ); } private void showPartButton( final IPresentablePart part ) { Control button = ( Control ) partButtonMap.get( part ); Control hiddenButton = hideLastVisibleButton(); if( button != null && !button.isDisposed() ) { button.setVisible( true ); overflowButtons.remove( button ); button.moveAbove( hiddenButton ); tabBg.layout( true, true ); manageOverflow(); } } private void showLastChildIfNecessary( final int recursionCount ) { Control childToShow = getLastInvisibleButton(); if( childToShow != null && futureTabChildrenSize( childToShow ) < tabBg.getBounds().width && tabBgHasInvisibleButtons() ) { childToShow.setVisible( true ); IPresentablePart part = ( IPresentablePart ) buttonPartMap.get( childToShow ); makePartButtonInactive( part ); overflowButtons.remove( childToShow ); tabBg.layout( true, true ); if( recursionCount <= tabBg.getChildren().length ) { int newCount = recursionCount + 1; showLastChildIfNecessary( newCount ); } } } private boolean tabBgHasInvisibleButtons() { boolean result = false; Control[] children = tabBg.getChildren(); for( int i = 0; i < children.length && !result; i++ ) { if( !children[ i ].isVisible() ) { result = true; } } return result; } private int futureTabChildrenSize( final Control childToShow ) { int result = 0; result = getTabChildrenSize(); result += childToShow.getBounds().width; return result; } private Control getLastInvisibleButton() { Control result = null; Control[] children = tabBg.getChildren(); boolean childShowedUp = false; for( int i = children.length - 1; i >= 0 && !childShowedUp; i-- ) { if( children[ i ].isVisible() ) { if( children.length >= ( i + 2 ) ) { result = children[ i + 1 ]; } else { result = children[ i ]; } childShowedUp = true; } } return result; } /* * Returns the control which was hide. */ private Control hideLastVisibleButton() { Control result = null; if( tabBg != null && !tabBg.isDisposed() ) { Control[] children = tabBg.getChildren(); boolean lastChildHidden = false; for( int i = children.length - 1; i >= 0 && !lastChildHidden; i-- ) { if( children[ i ].isVisible() ) { if( isButtonActive( children[ i ] ) ) { if( i > 0 ) { children[ i - 1 ].setVisible( false ); result = children[ i - 1 ]; if( !overflowButtons.contains( children[ i - 1 ] ) ) { overflowButtons.add( children[ i - 1 ] ); } children[ i ].moveAbove( children[ i - 1 ] ); } } else { children[ i ].setVisible( false ); result = children[ i ]; overflowButtons.add( children[ i ] ); } lastChildHidden = true; tabBg.layout( true, true ); } } } return result; } private boolean isButtonActive( final Control control ) { boolean result = false; // check against the button variant if( control instanceof Composite ) { Composite buttonArea = ( Composite ) control; Control[] children = buttonArea.getChildren(); for( int i = 0; i < children.length && !result; i++ ) { if( children[ i ] instanceof Button ) { Object data = children[ i ].getData( WidgetUtil.CUSTOM_VARIANT ); if( data.equals( VARIANT_PART_INACTIVE_ACTIVE ) || data.equals( VARIANT_PART_ACTIVE ) ) { result = true; } } } } return result; } private int getTabChildrenSize() { int result = 0; Control[] children = tabBg.getChildren(); for( int i = 0; i < children.length; i++ ) { if( children[ i ].isVisible() && !children[ i ].isDisposed() ) { result += ( children[ i ].getSize().x + BUTTON_SPACING ); } } return result; } private void createConfArea( final FormData fdTabBg ) { final ConfigurationAction configAction = getConfigAction(); if( configAction != null ) { confArea = new Composite( getTabBar(), SWT.NONE ); Image confBg = stackBuilder.getImage( ILayoutSetConstants.STACK_CONF_BG_INACTIVE ); confArea.setBackgroundImage( confBg ); confArea.setLayout( new FormLayout() ); confArea.setBackgroundMode( SWT.INHERIT_FORCE ); FormData fdConfArea = new FormData(); confArea.setLayoutData( fdConfArea ); fdConfArea.top = new FormAttachment( 0 ); fdConfArea.bottom = new FormAttachment( 100 ); fdConfArea.right = new FormAttachment( 100 ); fdConfArea.width = 28; fdTabBg.right = new FormAttachment( confArea ); confCorner = new Label( confArea, SWT.NONE ); Image cornerImage = stackBuilder.getImage( ILayoutSetConstants.STACK_INACTIVE_CORNER ); confCorner.setImage( cornerImage ); FormData fdCorner = new FormData(); confCorner.setLayoutData( fdCorner ); fdCorner.left = new FormAttachment( 0 ); fdCorner.top = new FormAttachment( 0 ); fdCorner.bottom = new FormAttachment( 100 ); confButton = new Button( confArea, SWT.PUSH ); Image confImage = stackBuilder.getImage( ILayoutSetConstants.STACK_CONF_INACTIVE ); confButton.setImage( confImage ); confButton.setData( WidgetUtil.CUSTOM_VARIANT, "clearButton" ); FormData fdConfButton = stackBuilder.getPosition( ILayoutSetConstants.STACK_CONF_POSITION ); confButton.setLayoutData( fdConfButton ); FormData fdConfPos = stackBuilder.getPosition( ILayoutSetConstants.STACK_CONF_POS ); fdConfButton.right = fdConfPos.right; confButton.addSelectionListener( new SelectionAdapter(){ public void widgetSelected( SelectionEvent e ) { activatePart( getSite().getSelectedPart() ); configAction.run(); }; } ); } else { // make tabarea full width if no confarea exist. fdTabBg.right = new FormAttachment( 100 ); } } public void dispose() { ViewToolBarRegistry registry = ViewToolBarRegistry.getInstance(); registry.removeViewPartPresentation( this ); if( toolBarLayer != null ) { toolBarLayer.dispose(); } presentationControl.dispose(); } public Control getControl() { return presentationControl; } public Control[] getTabList( final IPresentablePart part ) { ArrayList list = new ArrayList(); if( getControl() != null ) { list.add( getControl() ); } if( part.getToolBar() != null ) { list.add( part.getToolBar() ); } if( part.getControl() != null ) { list.add( part.getControl() ); } return ( Control[] )list.toArray( new Control[ list.size() ] ); } public void removePart( final IPresentablePart oldPart ) { Object object = partButtonMap.get( oldPart ); buttonPartMap.remove( object ); if( toolBarLayer != null ) { toolBarLayer.setVisible( false ); } // remove the dirtyListener Object listener = dirtyListenerMap.get( oldPart ); if( listener != null && listener instanceof IPropertyListener ) { oldPart.removePropertyListener( ( IPropertyListener ) listener ); } partButtonMap.remove( oldPart ); buttonList.remove( object ); handleButtonDispose( object ); partList.remove( oldPart ); oldPart.setVisible( false ); tabBg.layout(); } private void handleButtonDispose( final Object buttonArea ) { if( buttonArea != null && !isStandalone() ) { ( ( Composite ) buttonArea ).dispose(); } } public void selectPart( final IPresentablePart toSelect ) { if( toSelect != null ) { toSelect.setVisible( true ); } if( currentPart != null ) { oldPart = currentPart; if( currentPart instanceof PresentablePart && ( (PresentablePart) currentPart ).getPane() != null ) { currentPart.setVisible( false ); } } makePartButtonInactive( currentPart ); currentPart = toSelect; currentPart.getControl().moveAbove( null ); makePartButtonActive( currentPart ); setBounds( presentationControl.getBounds() ); if( toolBarLayer != null ) { toolBarLayer.setVisible( false ); } } public StackDropResult dragOver( final Control currentControl, final Point location ) { return null; } public void setActive( final int newState ) { activeState = newState; Image confBg = null; Image cornerImage = null; Image confImage = null; Image tabBgImage = null; String tabOverflow = "tabOverflowInactive"; // create the necessary images if( newState == AS_ACTIVE_FOCUS ) { if( !isStandalone() ) { changeSelectedActiveButton( true ); } confBg = stackBuilder.getImage( ILayoutSetConstants.STACK_CONF_BG_ACTIVE ); String rightActive = ILayoutSetConstants.STACK_TAB_INACTIVE_RIGHT_ACTIVE; cornerImage = stackBuilder.getImage( rightActive ); confImage = stackBuilder.getImage( ILayoutSetConstants.STACK_CONF_ACTIVE ); tabOverflow = "tabOverflowActive"; tabBgImage = stackBuilder.getImage( ILayoutSetConstants.STACK_TAB_BG_ACTIVE ); changeStack( true ); } else { if( !isStandalone() ) { changeSelectedActiveButton( false ); } confBg = stackBuilder.getImage( ILayoutSetConstants.STACK_CONF_BG_INACTIVE ); cornerImage = stackBuilder.getImage( ILayoutSetConstants.STACK_INACTIVE_CORNER ); confImage = stackBuilder.getImage( ILayoutSetConstants.STACK_CONF_INACTIVE ); String stackTabInactiveBgActive = ILayoutSetConstants.STACK_TAB_INACTIVE_BG_ACTIVE; tabBgImage = stackBuilder.getImage( stackTabInactiveBgActive ); changeStack( false ); } // set the images if( tabBg != null ) { tabBg.getParent().setBackgroundImage( tabBgImage ); } if( confArea != null ) { confArea.setBackgroundImage( confBg ); if( confCorner != null ) { confCorner.setImage( cornerImage ); } if( confButton != null ) { confButton.setImage( confImage ); } confArea.getParent().layout( true ); if( currentPart != null && getPartPane( currentPart ) != null ) { currentPart.setVisible( true ); } confArea.layout( true ); } if( overflowButton != null ) { overflowButton.setData( WidgetUtil.CUSTOM_VARIANT, tabOverflow ); } setBounds( presentationControl.getBounds() ); } private void changeStack( boolean active ) { Object adapter = stackBuilder.getAdapter( Map.class ); if( adapter != null && adapter instanceof Map ) { Map labelMap = ( Map ) adapter; Label leftLabel = ( Label ) labelMap.get( StackPresentationBuider.LEFT ); Label rightLabel = ( Label ) labelMap.get( StackPresentationBuider.RIGHT ); Label leftBorder = ( Label ) labelMap.get( StackPresentationBuider.LEFT_BORDER ); Label rightBorder = ( Label ) labelMap.get( StackPresentationBuider.RIGHT_BORDER ); Label bottomBorder = ( Label ) labelMap.get( StackPresentationBuider.BOTTOM_BORDER ); Label topBorder = ( Label ) labelMap.get( StackPresentationBuider.TOP_BORDER ); Image left; Image right; Image leftBorderImg; Image rightBorderImg; Image bottomBorderImg; Image topBorderImg; if( active ) { String leftActive = ILayoutSetConstants.STACK_TABBAR_LEFT_ACTIVE; left = stackBuilder.getImage( leftActive ); String rightActive = ILayoutSetConstants.STACK_TABBAR_RIGHT_ACTIVE; right = stackBuilder.getImage( rightActive ); String bottomActive = ILayoutSetConstants.STACK_BORDER_BOTTOM_ACTIVE; bottomBorderImg = stackBuilder.getImage( bottomActive ); String leftBorderActive = ILayoutSetConstants.STACK_BORDER_LEFT_ACTIVE; leftBorderImg = stackBuilder.getImage( leftBorderActive ); String rightBorderActive = ILayoutSetConstants.STACK_BORDER_RIGHT_AVTIVE; rightBorderImg = stackBuilder.getImage( rightBorderActive ); String stackTopStandaloneActive = ILayoutSetConstants.STACK_TOP_STANDALONE_ACTIVE; topBorderImg = stackBuilder.getImage( stackTopStandaloneActive ); } else { String leftInactive = ILayoutSetConstants.STACK_TABBAR_LEFT_INACTIVE; left = stackBuilder.getImage( leftInactive ); String rightInactive = ILayoutSetConstants.STACK_TABBAR_RIGHT_INACTIVE; right = stackBuilder.getImage( rightInactive ); bottomBorderImg = stackBuilder.getImage( ILayoutSetConstants.STACK_BORDER_BOTTOM ); leftBorderImg = stackBuilder.getImage( ILayoutSetConstants.STACK_BORDER_LEFT ); rightBorderImg = stackBuilder.getImage( ILayoutSetConstants.STACK_BORDER_RIGHT ); String stackTopStandaloneInactive = ILayoutSetConstants.STACK_TOP_STANDALONE_INACTIVE; topBorderImg = stackBuilder.getImage( stackTopStandaloneInactive ); } leftLabel.setImage( left ); rightLabel.setImage( right ); leftBorder.setBackgroundImage( leftBorderImg ); rightBorder.setBackgroundImage( rightBorderImg ); bottomBorder.setBackgroundImage( bottomBorderImg ); // top image for standalone view if( isStandalone() && topBorderImg != null ) { topBorder.setBackgroundImage( topBorderImg ); int height = topBorderImg.getBounds().height; FormData fdTopBorder = ( FormData ) topBorder.getLayoutData(); fdTopBorder.height = height; fdTopBorder.top = new FormAttachment( 0, 7 ); FormData fdLeftBorder = ( FormData ) leftBorder.getLayoutData(); FormData fdRightBorder = ( FormData ) rightBorder.getLayoutData(); fdLeftBorder.top = new FormAttachment( 0, height + 6 ); fdRightBorder.top = new FormAttachment( 0, height + 6 ); topBorder.getParent().layout( true ); topBorder.moveAbove( null ); } } } private PartPane getPartPane( IPresentablePart part ) { PartPane result = null; if( part instanceof PresentablePart ) { result = ( ( PresentablePart ) part ).getPane(); } return result; } private void changeSelectedActiveButton( final boolean selected ) { String close = ""; Color buttonAreaBg; String font = ""; String tab = ""; if( selected ) { buttonAreaBg = stackBuilder.getColor( ILayoutSetConstants.STACK_BUTTON_ACTIVE ); close = "viewClose"; font = "partInActiveActive"; tab = "tabActive"; } else { buttonAreaBg = stackBuilder.getColor( ILayoutSetConstants.STACK_BUTTON_INACTIVE ); close = "viewCloseInactive"; font ="partActive"; tab = "tabInactive"; } Object object = partButtonMap.get( currentPart ); if( object != null && object instanceof Composite ) { Composite buttonArea = ( Composite ) object; buttonArea.setData( WidgetUtil.CUSTOM_VARIANT, tab ); buttonArea.setBackground( buttonAreaBg ); Control[] children = buttonArea.getChildren(); for( int i = 0; i < children.length; i++ ) { Control child = children[ i ]; if( child instanceof Button ) { Button button = ( Button ) child; if( button.getData( BUTTON_ID ) != null ) { button.setData( WidgetUtil.CUSTOM_VARIANT, close ); } else { button.setData( WidgetUtil.CUSTOM_VARIANT, font ); } } } } } public void setBounds( final Rectangle bounds ) { presentationControl.setBounds( bounds ); Composite tabBar = getTabBar(); if( currentPart != null && tabBar != null && getPartPane( currentPart ) != null ) { int newHeight = bounds.height - 16; int partBoundsY = bounds.y + 8; if( getTabBar().isVisible() ) { newHeight -= ( tabBar.getBounds().height ); partBoundsY += tabBar.getBounds().height; } Control toolBar = currentPart.getToolBar(); if( toolbarBg != null && ( toolbarBg.isVisible() || toolBar != null ) ) { int toolbarHeight = toolbarBg.getBounds().height; newHeight -= toolbarHeight; partBoundsY += toolbarHeight; } String stackTopStandaloneActive = ILayoutSetConstants.STACK_TOP_STANDALONE_ACTIVE; Image stackTop = stackBuilder.getImage( stackTopStandaloneActive ); if( stackTop != null ) { partBoundsY += 1; newHeight -= 1; } Rectangle partBounds = new Rectangle( bounds.x + 8, partBoundsY, bounds.width - 16, newHeight ); currentPart.setBounds( partBounds ); } layoutToolBar(); } private Shell getToolBarLayer() { if( toolBarLayer == null && toolbarBg != null ) { toolBarLayer = new Shell( toolbarBg.getShell(), SWT.NO_TRIM ); toolBarLayer.setData( WidgetUtil.CUSTOM_VARIANT, "toolbarLayer" ); toolBarLayer.setAlpha( 200 ); toolBarLayer.addListener( SWT.MouseDown, new Listener() { public void handleEvent( final Event event ) { activatePart( currentPart ); } } ); } return toolBarLayer; } private Composite getTabBar() { Composite result = null; Object adapter = stackBuilder.getAdapter( this.getClass() ); if( adapter != null && adapter instanceof Composite ) { result = ( Composite ) adapter; } return result; } public void setState( final int state ) { this.state = state; } public void setVisible( final boolean isVisible ) { if( currentPart != null && getPartPane( currentPart ) != null ) { currentPart.setVisible( isVisible ); // Toolbar Layer deactivated = !isVisible; layoutToolBar(); if( toolBarLayer != null ) { if( !isVisible ) { toolBarLayer.setVisible( false ); } } setBounds( presentationControl.getBounds() ); } } public void showPaneMenu() { } public void showSystemMenu() { } public int computePreferredSize( final boolean width, final int availableParallel, final int availablePerpendicular, final int preferredResult ) { int result = preferredResult; if( width ) { // preferred width int minWidth = calculateMinimumWidth(); if( getSite().getState() == IStackPresentationSite.STATE_MINIMIZED || preferredResult < minWidth ) { result = minWidth; } } else { // preferred height result = calculateMinimumHeight(); } return result; } /* * Returns the height of the tabbar plus a spacing */ private int calculateMinimumHeight() { int result = 0; if( tabBg != null ) { tabBg.pack(); result = tabBg.getSize().y; } return result + HEIGHT_SPACING; } /* * Calculates the width of the biggest child */ private int calculateMinimumWidth() { int result = 0; if( tabBg != null ) { Control[] children = tabBg.getChildren(); for( int i = 0; i < children.length; i++ ) { if( children[ i ].getSize().x >= result ) { result = children[ i ].getSize().x; } } } return result + WIDTH_SPACING; } }