/**
* 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.TableHelper.HEADER_TITLES;
import static com.codeaffine.eclipse.swt.widget.scrollable.TableHelper.createTable;
import static com.codeaffine.eclipse.swt.widget.scrollable.TableHelper.createTableInSingleCellGridLayout;
import static com.codeaffine.test.util.lang.ThrowableCaptor.thrownBy;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Optional;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
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.test.util.SWTIgnoreConditions.NonWindowsPlatform;
import com.codeaffine.eclipse.swt.util.ReadAndDispatch;
import com.codeaffine.test.util.junit.ConditionalIgnoreRule;
import com.codeaffine.test.util.junit.ConditionalIgnoreRule.ConditionalIgnore;
import com.codeaffine.test.util.lang.ThrowableCaptor;
public class TableAdapterTest {
private static final int SELECTION = 50;
@Rule public final ConditionalIgnoreRule ignoreRule = new ConditionalIgnoreRule();
@Rule public final DisplayHelper displayHelper = new DisplayHelper();
private ScrollableAdapterFactory adapterFactory;
private TableAdapter adapter;
private Object layoutData;
private Shell shell;
private Table table;
@Before
public void setUp() {
adapterFactory = new ScrollableAdapterFactory();
shell = createShell( displayHelper );
table = createTable( shell, 10 );
layoutData = new Object();
table.setLayoutData( layoutData );
adapter = adapterFactory.create( table, TableAdapter.class ).get();
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void adapt() {
assertThat( adapter.getChildren() ).contains( table );
assertThat( adapter.getLayout() ).isInstanceOf( ScrollableLayout.class );
assertThat( adapter.getBounds() ).isEqualTo( shell.getClientArea() );
assertThat( adapter.getLayoutData() ).isSameAs( layoutData );
assertThat( adapter.getScrollable() ).isSameAs( table );
}
@Test
public void setLayout() {
Throwable actual = ThrowableCaptor.thrownBy( () -> adapter.setLayout( new FillLayout() ) );
assertThat( actual ).isInstanceOf( UnsupportedOperationException.class );
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void disposalOfAdapter() {
adapter.dispose();
assertThat( table.isDisposed() ).isTrue();
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void disposalOfTable() {
table.dispose();
assertThat( adapter.isDisposed() ).isTrue();
assertThat( shell.getChildren() ).isEmpty();
}
@Test
public void disposalWithDragSourceOnTable() {
Table table = new TestTableFactory().create( shell );
ScrollableAdapterFactoryHelper.adapt( table, TableAdapter.class );
DragSource dragSource = new DragSource( table, DND.DROP_MOVE | DND.DROP_COPY );
shell.dispose();
assertThat( dragSource.isDisposed() ).isTrue();
}
@Test
public void constructor() {
Throwable actual = thrownBy( () -> new TableAdapter() );
assertThat( actual )
.hasMessageContaining( "Subclassing not allowed" )
.isInstanceOf( SWTException.class );
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void changeTableBounds() {
openShellWithoutLayout();
table = new Table( shell, SWT.NONE );
adapter = adapterFactory.create( table, TableAdapter.class ).get();
waitForReconciliation();
table.setBounds( expectedBounds() );
waitForReconciliation();
assertThat( adapter.getBounds() ).isEqualTo( expectedBounds() );
assertThat( table.getBounds() ).isEqualTo( expectedBounds() );
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void changeTableBoundsWithVisibleScrollBars() {
openShellWithoutLayout();
waitForReconciliation();
table.setBounds( expectedBounds() );
waitForReconciliation();
assertThat( adapter.getBounds() ).isEqualTo( expectedBounds() );
assertThat( table.getBounds() ).isNotEqualTo( expectedBounds() );
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void changeTableBoundsWithHorizontalScroll() {
openShellWithoutLayout();
table.setBounds( expectedBounds() );
waitForReconciliation();
scrollHorizontal( adapter, SELECTION );
assertThat( adapter.getBounds() ).isEqualTo( expectedBounds() );
assertThat( table.getBounds() ).isNotEqualTo( expectedBounds() );
assertThat( adapter.getHorizontalBar().getSelection() ).isEqualTo( SELECTION );
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void changeTableVisibility() {
waitForReconciliation();
table.setVisible( false );
waitForReconciliation();
assertThat( adapter.getVisible() ).isFalse();
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void changeTableEnablement() {
waitForReconciliation();
table.setEnabled( false );
waitForReconciliation();
assertThat( adapter.getEnabled() ).isFalse();
}
@Test
public void getLayoutData() {
RowData expected = new RowData();
table.setLayoutData( expected );
Object actual = adapter.getLayoutData();
assertThat( actual ).isSameAs( expected );
}
@Test
public void setLayoutData() {
Object expected = new Object();
adapter.setLayoutData( expected );
Object actual = table.getLayoutData();
assertThat( actual ).isSameAs( expected );
}
@Test
public void computeSize() {
Point expected = table.computeSize( SWT.DEFAULT, SWT.DEFAULT, true );
Point actual = adapter.computeSize( SWT.DEFAULT, SWT.DEFAULT, true );
assertThat( actual ).isEqualTo( expected );
}
@Test
public void tableColumnDelegation() {
assertThat( adapter.getColumn( 0 ) ).isNotNull();
assertThat( adapter.getColumnCount() ).isEqualTo( HEADER_TITLES.length );
assertThat( adapter.getColumnOrder() ).isEqualTo( table.getColumnOrder() );
assertThat( adapter.getColumns() ).hasSize( HEADER_TITLES.length );
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void changeTableItemHeight() {
int expectedHeight = configureTableItemHeightAdjuster();
shell.open();
waitForReconciliation();
assertThat( table.getItemHeight() ).isEqualTo( expectedHeight );
}
@Test
@ConditionalIgnore( condition = NonWindowsPlatform.class )
public void packPopupShell() {
shell.open();
Shell popup = new Shell( shell, SWT.ON_TOP );
popup.setLocation( shell.getLocation() );
createTableInSingleCellGridLayout( popup,
table -> ScrollableAdapterFactoryHelper.adapt( table, TableAdapter.class )
);
popup.pack();
popup.setVisible( true );
waitForReconciliation();
TableAdapter actual = ( TableAdapter )popup.getChildren()[ 0 ];
assertThat( actual.getVerticalBar().isVisible() ).isFalse();
}
@Test
public void adaptWithoutScrollBarStyle() {
openShellWithoutLayout();
table = new Table( shell, SWT.NO_SCROLL );
Optional<TableAdapter> adapter = adapterFactory.create( table, TableAdapter.class );
assertThat( adapter.isPresent() ).isFalse();
}
private int configureTableItemHeightAdjuster() {
int result = 24;
table.addListener( SWT.MeasureItem, evt -> evt.height = result );
return result;
}
private void scrollHorizontal( TableAdapter adapter, int selection ) {
int duration = 100;
displayHelper.getDisplay().timerExec( duration, () -> adapter.getHorizontalBar().setSelection( selection ) );
new ReadAndDispatch().spinLoop( shell, duration * 2 );
}
private void openShellWithoutLayout() {
shell.setLayout( null );
shell.open();
}
private void waitForReconciliation() {
new ReadAndDispatch().spinLoop( shell, WatchDog.DELAY * 6 );
}
private Rectangle expectedBounds() {
Rectangle clientArea = shell.getClientArea();
return new Rectangle( 5, 10, clientArea.width - 10, clientArea.height - 20 );
}
}