![JAR search and dependency download from the Maven repository](/logo.png)
org.eclipse.swt.custom.SashForm Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* EclipseSource - ongoing development
*******************************************************************************/
package org.eclipse.swt.custom;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Sash;
/**
* The SashForm is a composite control that lays out its children in a row or column arrangement (as
* specified by the orientation) and places a Sash between each child. One child may be maximized to
* occupy the entire size of the SashForm. The relative sizes of the children may be specified using
* weights.
*
*
* - Styles:
* - HORIZONTAL, VERTICAL, SMOOTH
*
*
*
* @since 1.0
*/
public class SashForm extends Composite {
public int SASH_WIDTH = 3;
private static final int DRAG_MINIMUM = 20;
int sashStyle;
Sash[] sashes = new Sash[ 0 ];
// Remember background and foreground
// colors to determine whether to set
// sashes to the default color (null) or
// a specific color
Color background = null;
Color foreground = null;
Control[] controls = new Control[ 0 ];
Control maxControl = null;
Listener sashListener;
/**
* Constructs a new instance of this class given its parent
* and a style value describing its behavior and appearance.
*
* The style value is either one of the style constants defined in
* class SWT
which is applicable to instances of this
* class, or must be built by bitwise OR'ing together
* (that is, using the int
"|" operator) two or more
* of those SWT
style constants. The class description
* lists the style constants that are applicable to the class.
* Style bits are also inherited from superclasses.
*
*
* @param parent a widget which will be the parent of the new instance (cannot be null)
* @param style the style of widget to construct
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if the parent is null
*
* @exception SWTException
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
*
*
* @see SWT#HORIZONTAL
* @see SWT#VERTICAL
* @see #getStyle()
*/
public SashForm( Composite parent, int style ) {
super( parent, checkStyle( style ) );
super.setLayout( new SashFormLayout() );
sashStyle = ( ( style & SWT.VERTICAL ) != 0 ) ? SWT.HORIZONTAL : SWT.VERTICAL;
if( ( style & SWT.BORDER ) != 0 ) {
sashStyle |= SWT.BORDER;
}
if( ( style & SWT.SMOOTH ) != 0 ) {
sashStyle |= SWT.SMOOTH;
}
sashListener = new Listener() {
@Override
public void handleEvent( Event e ) {
onDragSash( e );
}
};
}
static int checkStyle( int style ) {
int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
return style & mask;
}
/**
* Returns SWT.HORIZONTAL if the controls in the SashForm are laid out side by side
* or SWT.VERTICAL if the controls in the SashForm are laid out top to bottom.
*
*
* To retrieve the bidi orientation of the SashForm use {@link #getStyle()}
* and test if the SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT bits are set.
*
*
* @return SWT.HORIZONTAL or SWT.VERTICAL
*/
@Override
public int getOrientation() {
// checkWidget();
return ( sashStyle & SWT.VERTICAL ) != 0 ? SWT.HORIZONTAL : SWT.VERTICAL;
}
/**
* Returns the width of the sashes when the controls in the SashForm are
* laid out.
*
* @return the width of the sashes
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 1.2
*/
public int getSashWidth() {
checkWidget();
return SASH_WIDTH;
}
@Override
public int getStyle() {
int style = super.getStyle();
style |= getOrientation() == SWT.VERTICAL ? SWT.VERTICAL : SWT.HORIZONTAL;
if( ( sashStyle & SWT.SMOOTH ) != 0 ) {
style |= SWT.SMOOTH;
}
return style;
}
/**
* Answer the control that currently is maximized in the SashForm.
* This value may be null.
*
* @return the control that currently is maximized or null
*/
public Control getMaximizedControl() {
// checkWidget();
return maxControl;
}
/**
* Answer the relative weight of each child in the SashForm. The weight represents the
* percent of the total width (if SashForm has Horizontal orientation) or
* total height (if SashForm has Vertical orientation) each control occupies.
* The weights are returned in order of the creation of the widgets (weight[0]
* corresponds to the weight of the first child created).
*
* @return the relative weight of each child
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
public int[] getWeights() {
checkWidget();
Control[] cArray = getControls( false );
int[] ratios = new int[ cArray.length ];
for( int i = 0; i < cArray.length; i++ ) {
Object data = cArray[ i ].getLayoutData();
if( data != null && data instanceof SashFormData ) {
ratios[ i ] = ( int )( ( ( SashFormData )data ).weight * 1000 >> 16 );
} else {
ratios[ i ] = 200;
}
}
return ratios;
}
Control[] getControls( boolean onlyVisible ) {
Control[] children = getChildren();
Control[] result = new Control[ 0 ];
for( int i = 0; i < children.length; i++ ) {
if( children[ i ] instanceof Sash ) {
continue;
}
if( onlyVisible && !children[ i ].getVisible() ) {
continue;
}
Control[] newResult = new Control[ result.length + 1 ];
System.arraycopy( result, 0, newResult, 0, result.length );
newResult[ result.length ] = children[ i ];
result = newResult;
}
return result;
}
void onDragSash( Event event ) {
Sash sash = ( Sash )event.widget;
int sashIndex = -1;
for( int i = 0; i < sashes.length; i++ ) {
if( sashes[ i ] == sash ) {
sashIndex = i;
break;
}
}
if( sashIndex == -1 ) {
return;
}
Control c1 = controls[ sashIndex ];
Control c2 = controls[ sashIndex + 1 ];
Rectangle b1 = c1.getBounds();
Rectangle b2 = c2.getBounds();
Rectangle sashBounds = sash.getBounds();
Rectangle area = getClientArea();
boolean correction = false;
if( getOrientation() == SWT.HORIZONTAL ) {
correction = b1.width < DRAG_MINIMUM || b2.width < DRAG_MINIMUM;
int totalWidth = b2.x + b2.width - b1.x;
int shift = event.x - sashBounds.x;
b1.width += shift;
b2.x += shift;
b2.width -= shift;
if( b1.width < DRAG_MINIMUM ) {
b1.width = DRAG_MINIMUM;
b2.x = b1.x + b1.width + sashBounds.width;
b2.width = totalWidth - b2.x;
event.x = b1.x + b1.width;
event.doit = false;
}
if( b2.width < DRAG_MINIMUM ) {
b1.width = totalWidth - DRAG_MINIMUM - sashBounds.width;
b2.x = b1.x + b1.width + sashBounds.width;
b2.width = DRAG_MINIMUM;
event.x = b1.x + b1.width;
event.doit = false;
}
Object data1 = c1.getLayoutData();
if( data1 == null || !( data1 instanceof SashFormData ) ) {
data1 = new SashFormData();
c1.setLayoutData( data1 );
}
Object data2 = c2.getLayoutData();
if( data2 == null || !( data2 instanceof SashFormData ) ) {
data2 = new SashFormData();
c2.setLayoutData( data2 );
}
( ( SashFormData )data1 ).weight = ( ( ( long )b1.width << 16 ) + area.width - 1 )
/ area.width;
( ( SashFormData )data2 ).weight = ( ( ( long )b2.width << 16 ) + area.width - 1 )
/ area.width;
} else {
correction = b1.height < DRAG_MINIMUM || b2.height < DRAG_MINIMUM;
int totalHeight = b2.y + b2.height - b1.y;
int shift = event.y - sashBounds.y;
b1.height += shift;
b2.y += shift;
b2.height -= shift;
if( b1.height < DRAG_MINIMUM ) {
b1.height = DRAG_MINIMUM;
b2.y = b1.y + b1.height + sashBounds.height;
b2.height = totalHeight - b2.y;
event.y = b1.y + b1.height;
event.doit = false;
}
if( b2.height < DRAG_MINIMUM ) {
b1.height = totalHeight - DRAG_MINIMUM - sashBounds.height;
b2.y = b1.y + b1.height + sashBounds.height;
b2.height = DRAG_MINIMUM;
event.y = b1.y + b1.height;
event.doit = false;
}
Object data1 = c1.getLayoutData();
if( data1 == null || !( data1 instanceof SashFormData ) ) {
data1 = new SashFormData();
c1.setLayoutData( data1 );
}
Object data2 = c2.getLayoutData();
if( data2 == null || !( data2 instanceof SashFormData ) ) {
data2 = new SashFormData();
c2.setLayoutData( data2 );
}
( ( SashFormData )data1 ).weight = ( ( ( long )b1.height << 16 ) + area.height - 1 )
/ area.height;
( ( SashFormData )data2 ).weight = ( ( ( long )b2.height << 16 ) + area.height - 1 )
/ area.height;
}
if( correction || ( event.doit && event.detail != SWT.DRAG ) ) {
c1.setBounds( b1 );
sash.setBounds( event.x, event.y, event.width, event.height );
c2.setBounds( b2 );
}
}
/**
* If orientation is SWT.HORIZONTAL, lay the controls in the SashForm
* out side by side. If orientation is SWT.VERTICAL, lay the
* controls in the SashForm out top to bottom.
*
*
* Since 3.1, this method can also be called with SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
* to change the bidi orientation of the SashForm.
*
*
* @param orientation SWT.HORIZONTAL or SWT.VERTICAL, SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
*
* @see Control#setOrientation(int)
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
* - ERROR_INVALID_ARGUMENT - if the value of orientation is not SWT.HORIZONTAL or SWT.VERTICAL, SWT.RIGHT_TO_LEFT or SWT.LEFT_TO_RIGHT
*
*/
@Override
public void setOrientation( int orientation ) {
checkWidget();
if( orientation == SWT.RIGHT_TO_LEFT || orientation == SWT.LEFT_TO_RIGHT ) {
super.setOrientation( orientation );
return;
}
if( getOrientation() == orientation ) {
return;
}
if( orientation != SWT.HORIZONTAL && orientation != SWT.VERTICAL ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
sashStyle &= ~( SWT.HORIZONTAL | SWT.VERTICAL );
sashStyle |= orientation == SWT.VERTICAL ? SWT.HORIZONTAL : SWT.VERTICAL;
for( int i = 0; i < sashes.length; i++ ) {
sashes[ i ].dispose();
sashes[ i ] = new Sash( this, sashStyle );
sashes[ i ].setBackground( background );
sashes[ i ].setForeground( foreground );
sashes[ i ].addListener( SWT.Selection, sashListener );
}
layout( false );
}
@Override
public void setBackground( Color color ) {
super.setBackground( color );
background = color;
for( int i = 0; i < sashes.length; i++ ) {
sashes[ i ].setBackground( background );
}
}
@Override
public void setForeground( Color color ) {
super.setForeground( color );
foreground = color;
for( int i = 0; i < sashes.length; i++ ) {
sashes[ i ].setForeground( foreground );
}
}
/**
* Sets the layout which is associated with the receiver to be
* the argument which may be null.
*
* Note: No Layout can be set on this Control because it already
* manages the size and position of its children.
*
*
* @param layout the receiver's new layout or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
@Override
public void setLayout( Layout layout ) {
checkWidget();
return;
}
/**
* Specify the control that should take up the entire client area of the SashForm.
* If one control has been maximized, and this method is called with a different control,
* the previous control will be minimized and the new control will be maximized.
* If the value of control is null, the SashForm will minimize all controls and return to
* the default layout where all controls are laid out separated by sashes.
*
* @param control the control to be maximized or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 1.2
*/
public void setMaximizedControl( Control control ) {
checkWidget();
if( control == null ) {
if( maxControl != null ) {
this.maxControl = null;
layout( false );
for( int i = 0; i < sashes.length; i++ ) {
sashes[ i ].setVisible( true );
}
}
return;
}
for( int i = 0; i < sashes.length; i++ ) {
sashes[ i ].setVisible( false );
}
maxControl = control;
layout( false );
}
/**
* Specify the width of the sashes when the controls in the SashForm are
* laid out.
*
* @param width the width of the sashes
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 1.2
*/
public void setSashWidth( int width ) {
checkWidget();
if( SASH_WIDTH == width ) {
return;
}
SASH_WIDTH = width;
layout( false );
}
/**
* Specify the relative weight of each child in the SashForm. This will determine
* what percent of the total width (if SashForm has Horizontal orientation) or
* total height (if SashForm has Vertical orientation) each control will occupy.
* The weights must be positive values and there must be an entry for each
* non-sash child of the SashForm.
*
* @param weights the relative weight of each child
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
* - ERROR_INVALID_ARGUMENT - if the weights value is null or of incorrect length (must match the number of children)
*
*/
public void setWeights( int[] weights ) {
checkWidget();
Control[] cArray = getControls( false );
if( weights == null || weights.length != cArray.length ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
int total = 0;
for( int i = 0; i < weights.length; i++ ) {
if( weights[ i ] < 0 ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
total += weights[ i ];
}
if( total == 0 ) {
SWT.error( SWT.ERROR_INVALID_ARGUMENT );
}
for( int i = 0; i < cArray.length; i++ ) {
Object data = cArray[ i ].getLayoutData();
if( data == null || !( data instanceof SashFormData ) ) {
data = new SashFormData();
cArray[ i ].setLayoutData( data );
}
( ( SashFormData )data ).weight = ( ( ( long )weights[ i ] << 16 ) + total - 1 ) / total;
}
layout( false );
}
}