/**
* 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.createShellWithoutLayout;
import static com.codeaffine.eclipse.swt.widget.scrollable.AdaptionContextHelper.BORDER_WIDTH;
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.FlatScrollBarTree.MAX_EXPANSION;
import static com.codeaffine.eclipse.swt.widget.scrollable.OverlayLayouter.CORNER_COVERAGE;
import static com.codeaffine.eclipse.swt.widget.scrollable.OverlayLayouter.calculateCornerOverlayBounds;
import static com.codeaffine.eclipse.swt.widget.scrollbar.FlatScrollBarAssert.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import java.util.Collection;
import java.util.LinkedList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import com.codeaffine.eclipse.swt.test.util.DisplayHelper;
import com.codeaffine.eclipse.swt.widget.scrollable.context.AdaptionContext;
import com.codeaffine.eclipse.swt.widget.scrollbar.FlatScrollBar;
@RunWith( Parameterized.class )
public class OverlayLayouterTest {
private static final int OFFSET = 2;
@Rule
public final DisplayHelper displayHelper = new DisplayHelper();
private FlatScrollBar horizontal;
private OverlayLayouter layouter;
private FlatScrollBar vertical;
private Label cornerOverlay;
private Shell shell;
@Parameter
public Demeanor demeanor;
@Parameters
public static Collection<Object[]> data() {
Collection<Object[]> result = new LinkedList<>();
for( Demeanor element : Demeanor.values() ) {
result.add( new Object[] { element } );
}
return result;
}
@Before
public void setUp() {
shell = createShellWithoutLayout( displayHelper, SWT.RESIZE );
horizontal = new FlatScrollBar( shell, SWT.HORIZONTAL );
vertical = new FlatScrollBar( shell, SWT.VERTICAL );
cornerOverlay = new Label( shell, SWT.NONE );
layouter = new OverlayLayouter( horizontal, vertical, cornerOverlay );
}
@Test
public void layout() {
AdaptionContext<?> context = stubContext( V_VISIBLE, H_VISIBLE, exceedVisibleArea(), getVisibleArea(), demeanor );
layouter.layout( context );
assertThat( horizontal )
.isVisible()
.hasBounds( 0, expectedHorizontalY( context ), getVisibleArea().width - MAX_EXPANSION, barBreadth( context ) );
assertThat( vertical )
.isVisible()
.hasBounds( expectedVerticalX( context ), 0, barBreadth( context ), getVisibleArea().height - MAX_EXPANSION );
assertThat( cornerOverlay.getBounds() )
.isEqualTo( expectedCornerOverlayBounds() );
}
@Test
public void layoutWithoutHorizontalBar() {
AdaptionContext<?> context = stubContext( V_VISIBLE, H_INVISIBLE, exceedVisibleArea(), getVisibleArea(), demeanor );
layouter.layout( context );
assertThat( horizontal )
.isNotVisible()
.hasBounds( 0, 0, 0, 0 );
assertThat( vertical )
.isVisible()
.hasBounds( expectedVerticalX( context ), 0, barBreadth( context ), getVisibleArea().height );
assertThat( cornerOverlay.getBounds() )
.isEqualTo( expectedCornerOverlayBounds() );
}
@Test
public void layoutWithoutVerticalBar() {
AdaptionContext<?> context = stubContext( V_INVISIBLE, H_VISIBLE, exceedVisibleArea(), getVisibleArea(), demeanor );
layouter.layout( context );
assertThat( horizontal )
.isVisible()
.hasBounds( 0, expectedHorizontalY( context ), getVisibleArea().width, barBreadth( context ) );
assertThat( vertical )
.isNotVisible()
.hasBounds( 0, 0, 0, 0 );
assertThat( cornerOverlay.getBounds() )
.isEqualTo( expectedCornerOverlayBounds() );
}
@Test
public void layoutWithoutScrollBars() {
AdaptionContext<?> context = stubContext( V_INVISIBLE, H_INVISIBLE, fitVisibleArea(), getVisibleArea(), demeanor );
layouter.layout( context );
assertThat( horizontal )
.isNotVisible()
.hasBounds( 0, 0, 0, 0 );
assertThat( vertical )
.isNotVisible()
.hasBounds( 0, 0, 0, 0 );
assertThat( cornerOverlay.getBounds() )
.isEqualTo( expectedCornerOverlayBounds() );
}
@Test
public void cornerOverlayBoundsCalculation() {
AdaptionContext<?> context = stubContextWithOffset( OFFSET );
horizontal.setSize( 10, 20 );
vertical.setSize( 30, 40 );
Rectangle actual = OverlayLayouter.calculateCornerOverlayBounds( horizontal, vertical, context );
int width = 30 + OFFSET + BORDER_WIDTH + CORNER_COVERAGE;
int height = 20 + BORDER_WIDTH + CORNER_COVERAGE;
assertThat( actual ).isEqualTo( new Rectangle( 10, 40, width, height) );
}
private AdaptionContext<?> stubContextWithOffset( int offset ) {
AdaptionContext<?> result = stubContext( V_VISIBLE, H_VISIBLE, exceedVisibleArea(), getVisibleArea(), demeanor );
when( result.getOffset() ).thenReturn( offset );
return result;
}
private Rectangle expectedCornerOverlayBounds() {
AdaptionContext<?> context = stubContext( V_VISIBLE, H_VISIBLE, exceedVisibleArea(), getVisibleArea(), demeanor );
return calculateCornerOverlayBounds( horizontal, vertical , context);
}
private int expectedHorizontalY( AdaptionContext<?> context ) {
return getVisibleArea().height - barBreadth( context );
}
private int expectedVerticalX( AdaptionContext<?> context ) {
return getVisibleArea().width - barBreadth( context );
}
private Rectangle getVisibleArea() {
return shell.getClientArea();
}
private Point exceedVisibleArea() {
return new Point( shell.getSize().x * 2, shell.getSize().y * 2 );
}
private static Point fitVisibleArea() {
return new Point( 0, 0 );
}
private static int barBreadth( AdaptionContext<?> context ) {
return context.get( Demeanor.class ).getBarBreadth();
}
}