/**
* 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.test.util.ShellHelper.createShell;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.BORDER_ADJUSTMENT;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.BORDER_WIDTH;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.STUB_VERTICAL_BAR_OFFSET;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.stubContext;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.Horizontal.H_INVISIBLE;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.Horizontal.H_VISIBLE;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.Vertical.V_INVISIBLE;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.Vertical.V_VISIBLE;
import static com.codeaffine.eclipse.swt.widget.scrollable.Demeanor.FIXED_SCROLL_BAR_BREADTH;
import static com.codeaffine.eclipse.swt.widget.scrollable.TreeHelper.createTree;
import static com.codeaffine.eclipse.swt.widget.scrollable.TreeHelper.expandTopBranch;
import static com.codeaffine.eclipse.swt.widget.scrollbar.FlatScrollBar.BAR_BREADTH;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Scrollable;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import com.codeaffine.eclipse.swt.test.util.DisplayHelper;
import com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.Horizontal;
import com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.Vertical;
import com.codeaffine.eclipse.swt.widget.scrollable.context.AdaptionContext;
import com.codeaffine.eclipse.swt.widget.scrollable.context.ScrollableControl;
public class StructuredScrollableLayouterTest {
private static final int SELECTION = 10;
@Rule
public final DisplayHelper displayHelper = new DisplayHelper();
private StructuredScrollableLayouter layouter;
private Composite adapter;
private Tree scrollable;
private Shell shell;
@Before
public void setUp() {
shell = createShell( displayHelper );
adapter = createAdapter( shell );
scrollable = createTree( adapter, 6, 4 );
layouter = new StructuredScrollableLayouter( new ScrollableControl<>( scrollable ) );
shell.open();
}
@Test
public void withoutScrollBarsAndScrollableFitsInVisibleArea() {
layouter.layout( stubAdaptionContext( V_INVISIBLE, H_INVISIBLE, fitVisibleArea(), getVisibleArea() ) );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH,
-BORDER_WIDTH,
getVisibleArea().width + BORDER_ADJUSTMENT,
getVisibleArea().height + BORDER_ADJUSTMENT ) );
}
@Test
public void withoutScrollBarsAndScrollableDoesNotFitInVisibleArea() {
layouter.layout( stubAdaptionContext( V_INVISIBLE, H_INVISIBLE, exceedVisibleArea(), getVisibleArea() ) );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH,
-BORDER_WIDTH,
exceedVisibleArea().x,
getVisibleArea().height + BORDER_ADJUSTMENT ) );
}
@Test
public void withVerticalBarAndScrollableFitsInVisibleArea() {
layouter.layout( stubAdaptionContext( V_VISIBLE, H_INVISIBLE, fitVisibleArea(), getVisibleArea() ) );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH,
-BORDER_WIDTH,
verticalHeightIfTreeFits() + BORDER_ADJUSTMENT,
getVisibleArea().height + BORDER_ADJUSTMENT ) );
}
@Test
public void withVerticalBarAndScrollableDoesNotFitInVisibleArea() {
layouter.layout( stubAdaptionContext( V_VISIBLE, H_INVISIBLE, exceedVisibleArea(), getVisibleArea() ) );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH,
-BORDER_WIDTH,
verticalHeightIfTreeDoesNotFit(),
getVisibleArea().height + BORDER_ADJUSTMENT ) );
}
@Test
public void withHorizontalBarAndScrollableFitsVisibleArea() {
layouter.layout( stubAdaptionContext( V_INVISIBLE, H_VISIBLE, fitVisibleArea(), getVisibleArea() ) );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH,
-BORDER_WIDTH,
getVisibleArea().width + BORDER_ADJUSTMENT,
expectedVerticalHeightIfHorizontalIsVisible() + BORDER_ADJUSTMENT ) );
}
@Test
public void withHorizontalBarAndScrollableDoesNotFitVisibleArea() {
layouter.layout( stubAdaptionContext( V_INVISIBLE, H_VISIBLE, exceedVisibleArea(), getVisibleArea() ) );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH,
-BORDER_WIDTH,
exceedVisibleArea().y,
expectedVerticalHeightIfHorizontalIsVisible() + BORDER_ADJUSTMENT ) );
}
@Test
public void withScrollBarsAndScrollableDoesNotFitVisibleArea() {
layouter.layout( stubAdaptionContext( V_VISIBLE, H_VISIBLE, exceedVisibleArea(), getVisibleArea() ) );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH,
-BORDER_WIDTH,
verticalHeightIfTreeDoesNotFit(),
expectedVerticalHeightIfHorizontalIsVisible() + BORDER_ADJUSTMENT) );
}
@Test
public void horizontalBarSelectionIfScrollableIsChildOfAdapter() {
adapter.getHorizontalBar().setSelection( SELECTION );
layouter.layout( stubAdaptionContext( V_VISIBLE, H_VISIBLE, exceedVisibleArea(), getVisibleArea() ) );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH,
-BORDER_WIDTH,
verticalHeightIfTreeDoesNotFit(),
expectedVerticalHeightIfHorizontalIsVisible() + BORDER_ADJUSTMENT ) );
}
@Test
public void horizontalBarSelectionIfScrollableIsReplacedByAdapter() {
expandTopBranch( scrollable );
adapter.getHorizontalBar().setSelection( SELECTION );
AdaptionContext<?> context = stubAdaptionContext( V_VISIBLE, H_VISIBLE, exceedVisibleArea(), getVisibleArea() );
stubChildByAdapterReplacement( context );
layouter.layout( context );
assertThat( scrollable.getBounds() )
.isEqualTo( $( -BORDER_WIDTH -SELECTION,
-BORDER_WIDTH,
verticalHeightIfTreeDoesNotFit(),
expectedVerticalHeightIfHorizontalIsVisible() + BORDER_ADJUSTMENT ) );
}
private AdaptionContext<Scrollable> stubAdaptionContext(
Vertical verticalBarVisible, Horizontal horizontalBarVisible, Point preferredSize, Rectangle visibleArea )
{
AdaptionContext<Scrollable> result
= stubContext( verticalBarVisible, horizontalBarVisible, preferredSize, visibleArea, FIXED_SCROLL_BAR_BREADTH );
when( result.getScrollable() ).thenReturn( new ScrollableControl<>( scrollable ) );
when( result.getAdapter() ).thenReturn( adapter );
return result;
}
private static void stubChildByAdapterReplacement( AdaptionContext<?> context ) {
when( context.isScrollableReplacedByAdapter() ).thenReturn( true );
when( context.getHorizontalAdapterSelection() ).thenCallRealMethod();
}
private static Composite createAdapter( Composite parent ) {
Composite result = new Composite( parent, SWT.H_SCROLL | SWT.V_SCROLL );
result.setLayout( new FillLayout() );
return result;
}
private int expectedVerticalHeightIfHorizontalIsVisible() {
return adapter.getClientArea().height - BAR_BREADTH;
}
private int verticalHeightIfTreeFits() {
return getVisibleArea().width + AdaptionContextHelper.STUB_VERTICAL_BAR_OFFSET;
}
private int verticalHeightIfTreeDoesNotFit() {
return exceedVisibleArea().x + STUB_VERTICAL_BAR_OFFSET;
}
private Rectangle getVisibleArea() {
return adapter.getClientArea();
}
private static Point fitVisibleArea() {
return new Point( 0, 0 );
}
private Point exceedVisibleArea() {
return new Point( adapter.getSize().x * 4, adapter.getSize().y * 4 );
}
private static Rectangle $( int x, int y, int width, int height ) {
return new Rectangle( x, y, width, height );
}
}