/*******************************************************************************
* 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;
}
}