/*******************************************************************************
* Copyright (c) 2013 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 com.eclipsesource.tabris.widgets.enhancement;
import static com.eclipsesource.tabris.internal.Clauses.whenNull;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
/**
* @since 0.10
*/
@SuppressWarnings("restriction")
public class CompositeDecorator extends WidgetDecorator<CompositeDecorator> {
/**
* <p>
* When using a GroupedEvent this key can be used as a {@link RWT#CUSTOM_VARIANT} to theme the overlayed composite.
* </p>
*
* @since 1.0
*/
public static final String GROUPED_EVENT_COMPOSITE = "groupedEventComposite";
private final Composite composite;
CompositeDecorator( Composite composite ) {
super( composite );
this.composite = composite;
}
/**
* <p>
* Adds a {@link Listener} for the defined eventType. The listener will be notified when the event occurs anywhere
* on the {@link Composite}. It doesn't matter if the {@link Composite} holds controls or not.
* </p>
*
* @since 0.10
*/
public void addGroupedListener( int eventType, Listener listener )
throws IllegalArgumentException, IllegalStateException
{
whenNull( listener ).throwIllegalArgument( "Listener must not be null" );
Composite facade = getFacade();
facade.addListener( eventType, listener );
}
/**
* <p>
* Removes a {@link Listener} for the defined eventType.
* </p>
*
* @since 0.10
*/
public void removeGroupedListener( int eventType, Listener listener )
throws IllegalArgumentException, IllegalStateException
{
whenNull( listener ).throwIllegalArgument( "Listener must not be null" );
Composite facade = findFacade();
if( facade != null ) {
facade.removeListener( eventType, listener );
}
}
private Composite getFacade() {
Composite facade = findFacade();
if( facade == null ) {
facade = createFacade();
}
return facade;
}
private Composite findFacade() {
String compositeId = WidgetUtil.getId( composite );
Control[] children = composite.getChildren();
for( Control child : children ) {
if( compositeId.equals( child.getData( GROUPED_EVENT_COMPOSITE ) ) ) {
return ( Composite )child;
}
}
return null;
}
private Composite createFacade() {
Composite facade = new Composite( composite, SWT.NONE );
facade.setData( GROUPED_EVENT_COMPOSITE, WidgetUtil.getId( composite ) );
facade.setData( RWT.CUSTOM_VARIANT, GROUPED_EVENT_COMPOSITE );
addLayoutDataWithExclude( facade );
layoutFacade( facade );
addResizeListener( facade );
return facade;
}
private void addLayoutDataWithExclude( Composite facade ) {
Layout layout = composite.getLayout();
if( layout instanceof RowLayout ) {
addExcludedRowData( facade );
} else if( layout instanceof GridLayout ) {
addExcludedGridData( facade );
} else {
throw new IllegalStateException( "Composite needs to be layouted using Grid- or RowLayout" );
}
}
private void addExcludedRowData( Composite facade ) {
RowData rowData = new RowData();
rowData.exclude = true;
facade.setLayoutData( rowData );
}
private void addExcludedGridData( Composite facade ) {
GridData gridData = new GridData();
gridData.exclude = true;
facade.setLayoutData( gridData );
}
private void addResizeListener( final Composite facade ) {
composite.addControlListener( new ControlListener() {
@Override
public void controlResized( ControlEvent e ) {
layoutFacade( facade );
}
@Override
public void controlMoved( ControlEvent e ) {
layoutFacade( facade );
}
} );
}
private void layoutFacade( final Composite facade ) {
Rectangle bounds = composite.getBounds();
facade.setBounds( 0, 0, bounds.width, bounds.height );
facade.moveAbove( null );
}
}