/**
* Copyright (c) 2014 - 2017 Frank Appel
* 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:
* Frank Appel - initial API and implementation
*/
package com.codeaffine.eclipse.swt.widget.scrollable;
import static com.codeaffine.eclipse.swt.widget.scrollable.ScrollableAdapterFactory.createLayoutFactory;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.ScrollBar;
import com.codeaffine.eclipse.swt.util.ControlReflectionUtil;
import com.codeaffine.eclipse.swt.util.Platform;
import com.codeaffine.eclipse.swt.util.PlatformSupport;
import com.codeaffine.eclipse.swt.widget.scrollable.ScrollableAdapterFactory.Adapter;
import com.codeaffine.eclipse.swt.widget.scrollable.context.AdaptionContext;
import com.codeaffine.eclipse.swt.widget.scrollable.context.Reconciliation;
import com.codeaffine.eclipse.swt.widget.scrollable.context.ScrollableControl;
public class ScrolledCompositeAdapter extends ScrolledComposite implements Adapter<ScrolledComposite>, ScrollbarStyle {
private LayoutFactory<ScrolledComposite> layoutFactory;
private AdaptionContext<ScrolledComposite> context;
private Reconciliation reconciliation;
private ScrolledComposite scrolledComposite;
ScrolledCompositeAdapter() {
super( null, -1 );
}
@Override
public ScrolledComposite getScrollable() {
return scrolledComposite;
}
@Override
@SuppressWarnings("unchecked")
public void adapt( ScrolledComposite scrolledComposite, PlatformSupport platformSupport ) {
this.layoutFactory = createLayoutFactory( new Platform(), createLayoutMapping( platformSupport ) );
this.scrolledComposite = scrolledComposite;
if( platformSupport.isGranted() ) {
initialize();
}
}
///////////////////////////////
// ScrolledComposite overrides
@Override
public void setLayout( Layout layout ) {
throw new UnsupportedOperationException( "TreeAdapter does not allow to change its layout" );
}
@Override
public ScrollBar getVerticalBar() {
return layoutFactory.getVerticalBarAdapter();
}
@Override
public ScrollBar getHorizontalBar() {
return layoutFactory.getHorizontalBarAdapter();
}
@Override
public void setSize( int width, int height ) {
reconciliation.runWithSuspendedBoundsReconciliation( () -> super.setSize( width, height ) );
}
@Override
public void setBounds( int x, int y, int width, int height ) {
reconciliation.runWithSuspendedBoundsReconciliation( () -> super.setBounds( x, y, width, height ) );
if( mustWorkaroundPageCreationProblemOfPreferenceDialog( x, y, width, height ) ) {
reconciliation.runWithSuspendedBoundsReconciliation( () -> super.setBounds( x, y, width, height ) );
}
}
@Override
public void setLocation( int x, int y ) {
reconciliation.runWithSuspendedBoundsReconciliation( () -> super.setLocation( x, y ) );
}
@Override
public void setVisible( boolean visible ) {
super.setVisible( reconciliation.setVisible( visible ) );
}
@Override
public void setEnabled( boolean enabled ) {
super.setEnabled( reconciliation.setEnabled( enabled ) );
}
@Override
public Control getContent() {
return scrolledComposite.getContent();
}
////////////////////////////////////////////////////
// scroll bar style attributes
@Override
public void setIncrementButtonLength( int length ) {
layoutFactory.setIncrementButtonLength( length );
}
@Override
public int getIncrementButtonLength() {
return layoutFactory.getIncrementButtonLength();
}
@Override
public void setIncrementColor( Color color ) {
layoutFactory.setIncrementColor( color );
}
@Override
public Color getIncrementColor() {
return layoutFactory.getIncrementColor();
}
@Override
public void setPageIncrementColor( Color color ) {
layoutFactory.setPageIncrementColor( color );
}
@Override
public Color getPageIncrementColor() {
return layoutFactory.getPageIncrementColor();
}
@Override
public void setThumbColor( Color color ) {
layoutFactory.setThumbColor( color );
}
@Override
public Color getThumbColor() {
return layoutFactory.getThumbColor();
}
@Override
public void setBackgroundColor( Color color ) {
layoutFactory.setBackgroundColor( color );
}
@Override
public Color getBackgroundColor() {
return layoutFactory.getBackgroundColor();
}
@Override
public void setDemeanor( Demeanor demeanor ) {
layoutFactory.setDemeanor( demeanor );
}
@Override
public Demeanor getDemeanor() {
return layoutFactory.getDemeanor();
}
//////////////////////////////////////////////////////
// delegating adapter methods
@Override
public Point computeSize( int wHint, int hHint, boolean changed ) {
return scrolledComposite.computeSize( wHint, hHint, changed );
}
@Override
public Object getLayoutData() {
return scrolledComposite.getLayoutData();
}
@Override
public void setLayoutData( Object layoutData ) {
scrolledComposite.setLayoutData( layoutData );
}
@Override
public Object getData() {
return scrolledComposite.getData();
}
@Override
public Object getData( String key ) {
return scrolledComposite.getData( key );
}
@Override
public void setBackgroundMode( int mode ) {
scrolledComposite.setBackgroundMode( mode );
}
@Override
public boolean setFocus() {
return scrolledComposite.setFocus();
}
@Override
public boolean forceFocus() {
return scrolledComposite.forceFocus();
}
@Override
public Color getBackground() {
return scrolledComposite.getBackground();
}
@Override
public void setData( Object data ) {
scrolledComposite.setData( data );
}
@Override
public Image getBackgroundImage() {
return scrolledComposite.getBackgroundImage();
}
@Override
public void setData( String key, Object value ) {
scrolledComposite.setData( key, value );
}
@Override
public void setTabList( Control[] tabList ) {
scrolledComposite.setTabList( tabList );
}
@Override
public boolean getEnabled() {
return scrolledComposite.getEnabled();
}
@Override
public Font getFont() {
return scrolledComposite.getFont();
}
@Override
public Color getForeground() {
return scrolledComposite.getForeground();
}
@Override
public String toString() {
if( scrolledComposite != null ) {
return scrolledComposite.toString();
}
return scrolledComposite.toString();
}
@Override
public Control[] getTabList() {
return scrolledComposite.getTabList();
}
@Override
public boolean getVisible() {
return scrolledComposite.getVisible();
}
@Override
public boolean isFocusControl() {
return scrolledComposite.isFocusControl();
}
@Override
public void setBackground( Color color ) {
scrolledComposite.setBackground( color );
}
@Override
public void setBackgroundImage( Image image ) {
scrolledComposite.setBackgroundImage( image );
}
@Override
public void setForeground( Color color ) {
scrolledComposite.setForeground( color );
}
@Override
public boolean traverse( int traversal ) {
return scrolledComposite.traverse( traversal );
}
@Override
public boolean traverse( int traversal, Event event ) {
return scrolledComposite.traverse( traversal, event );
}
@Override
public boolean traverse( int traversal, KeyEvent event ) {
return scrolledComposite.traverse( traversal, event );
}
@Override
public void setFont( Font font ) {
scrolledComposite.setFont( font );
}
@Override
public void setMinHeight( int height ) {
scrolledComposite.setMinHeight( height );
}
@Override
public int getMinHeight() {
return scrolledComposite.getMinHeight();
}
@Override
public void setMinWidth( int width ) {
scrolledComposite.setMinWidth( width );
}
@Override
public int getMinWidth() {
return scrolledComposite.getMinWidth();
}
@Override
public void setMinSize( Point size ) {
scrolledComposite.setMinSize( size );
}
@Override
public void setExpandHorizontal( boolean expand ) {
scrolledComposite.setExpandHorizontal( expand );
}
@Override
public boolean getExpandHorizontal() {
return scrolledComposite.getExpandHorizontal();
}
@Override
public void setExpandVertical( boolean expand ) {
scrolledComposite.setExpandVertical( expand );
}
@Override
public boolean getExpandVertical() {
return scrolledComposite.getExpandVertical();
}
///////////////////////////////
// private helper methods
private void initialize() {
scrolledComposite.setParent( this );
ScrollableControl<ScrolledComposite> scrollableControl = new ScrollableControl<>( scrolledComposite );
context = new AdaptionContext<>( this, scrollableControl );
reconciliation = context.getReconciliation();
new ControlReflectionUtil().setField( this, "layout", layoutFactory.create( context ) );
new DisposalRouting().register( this, scrolledComposite );
}
private boolean mustWorkaroundPageCreationProblemOfPreferenceDialog( int x, int y, int width, int height ) {
// Note [fappel]: This passage isn't covered with unit tests, since I wasn't able to reproduce the layout
// issue in a test scenario. However, since this workaround avoids the size setting problem when
// opening the workbench's preference dialog (adapter was rendered too small) I leave it at that
// for now.
return !new Rectangle( x, y, width, height ).equals( getBounds() );
}
private static LayoutMapping<ScrolledComposite> createLayoutMapping( PlatformSupport platformSupport ) {
return new LayoutMapping<ScrolledComposite>( new ScrolledCompositeLayoutFactory(),
platformSupport.getSupportedTypes() );
}
}