/** * 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.ScrolledCompositeHelper.createScrolledComposite; 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.custom.ScrolledComposite; 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.Control; import org.eclipse.swt.widgets.Shell; 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; public class ScrolledCompositeAdapterTest { private static final int SELECTION = 50; @Rule public final ConditionalIgnoreRule ignoreRule = new ConditionalIgnoreRule(); @Rule public final DisplayHelper displayHelper = new DisplayHelper(); private ScrollableAdapterFactory adapterFactory; private ScrolledComposite scrolledComposite; private ScrolledCompositeAdapter adapter; private Shell shell; private Object layoutData; @Before public void setUp() { adapterFactory = new ScrollableAdapterFactory(); shell = createShell( displayHelper ); scrolledComposite = createScrolledComposite( shell ); layoutData = new Object(); scrolledComposite.setLayoutData( layoutData ); adapter = adapterFactory.create( scrolledComposite, ScrolledCompositeAdapter.class ).get(); } @Test @ConditionalIgnore( condition = NonWindowsPlatform.class ) public void adapt() { assertThat( adapter.getChildren() ).contains( scrolledComposite ); assertThat( adapter.getLayout() ).isInstanceOf( ScrollableLayout.class ); assertThat( adapter.getLayoutData() ).isSameAs( layoutData ); assertThat( adapter.getBounds() ).isEqualTo( shell.getClientArea() ); assertThat( adapter.getScrollable() ).isSameAs( scrolledComposite ); } @Test public void setLayout() { Throwable actual = thrownBy( () -> adapter.setLayout( new FillLayout() ) ); assertThat( actual ).isInstanceOf( UnsupportedOperationException.class ); } @Test public void getContent() { Control actual = adapter.getContent(); assertThat( actual ) .isNotNull() .isSameAs( scrolledComposite.getContent() ); } @Test @ConditionalIgnore( condition = NonWindowsPlatform.class ) public void disposalOfAdapter() { adapter.dispose(); assertThat( scrolledComposite.isDisposed() ).isTrue(); } @Test @ConditionalIgnore( condition = NonWindowsPlatform.class ) public void disposalOfScrolledComposite() { scrolledComposite.dispose(); assertThat( adapter.isDisposed() ).isTrue(); assertThat( shell.getChildren() ).isEmpty(); } @Test public void disposalWithDragSourceOnScrolledComposite() { ScrolledComposite scrolledComposite = new TestScrolledCompositeFactory().create( shell ); ScrollableAdapterFactoryHelper.adapt( scrolledComposite, ScrolledCompositeAdapter.class ); DragSource dragSource = new DragSource( scrolledComposite, DND.DROP_MOVE | DND.DROP_COPY ); shell.dispose(); assertThat( dragSource.isDisposed() ).isTrue(); } @Test public void constructor() { Throwable actual = thrownBy( () -> new ScrolledCompositeAdapter() ); assertThat( actual ) .hasMessageContaining( "Argument cannot be null" ) .isInstanceOf( IllegalArgumentException.class ); } @Test @ConditionalIgnore( condition = NonWindowsPlatform.class ) public void changeScrolledCompositeBounds() { openShellWithoutLayout(); scrolledComposite = createScrolledComposite( shell, SWT.H_SCROLL | SWT.V_SCROLL, "" ); adapter = adapterFactory.create( scrolledComposite, ScrolledCompositeAdapter.class ).get(); waitForReconciliation(); scrolledComposite.setBounds( expectedBounds() ); waitForReconciliation(); assertThat( adapter.getBounds() ).isEqualTo( expectedBounds() ); assertThat( scrolledComposite.getBounds() ).isEqualTo( expectedBounds() ); } @Test @ConditionalIgnore( condition = NonWindowsPlatform.class ) public void changeScrolledCompositeBoundsWithVisibleScrollBars() { openShellWithoutLayout(); scrolledComposite = createScrolledComposite( shell ); adapter = adapterFactory.create( scrolledComposite, ScrolledCompositeAdapter.class ).get(); scrolledComposite.setBounds( expectedBounds() ); waitForReconciliation(); assertThat( adapter.getBounds() ).isEqualTo( expectedBounds() ); assertThat( scrolledComposite.getBounds() ).isNotEqualTo( expectedBounds() ); } @Test @ConditionalIgnore( condition = NonWindowsPlatform.class ) public void changeScrolledCompositeBoundsWithHorizontalScroll() { openShellWithoutLayout(); scrolledComposite.setBounds( expectedBounds() ); waitForReconciliation(); scrollHorizontal( adapter, SELECTION ); assertThat( adapter.getBounds() ).isEqualTo( expectedBounds() ); assertThat( scrolledComposite.getBounds() ).isNotEqualTo( expectedBounds() ); assertThat( adapter.getHorizontalBar().getSelection() ).isEqualTo( SELECTION ); } @Test @ConditionalIgnore( condition = NonWindowsPlatform.class ) public void changeScrolledCompositeVisibility() { scrolledComposite.setVisible( false ); waitForReconciliation(); assertThat( adapter.getVisible() ).isFalse(); } @Test @ConditionalIgnore( condition = NonWindowsPlatform.class ) public void changeScrolledCompositeEnablement() { scrolledComposite.setEnabled( false ); waitForReconciliation(); assertThat( adapter.getEnabled() ).isFalse(); } @Test public void getLayoutData() { RowData expected = new RowData(); scrolledComposite.setLayoutData( expected ); Object actual = adapter.getLayoutData(); assertThat( actual ).isSameAs( expected ); } @Test public void setLayoutData() { Object expected = new Object(); adapter.setLayoutData( expected ); Object actual = scrolledComposite.getLayoutData(); assertThat( actual ).isSameAs( expected ); } @Test public void computeSize() { Point expected = scrolledComposite.computeSize( SWT.DEFAULT, SWT.DEFAULT, true ); Point actual = adapter.computeSize( SWT.DEFAULT, SWT.DEFAULT, true ); assertThat( actual ).isEqualTo( expected ); } @Test public void adaptWithoutScrollBarStyle() { openShellWithoutLayout(); scrolledComposite = new ScrolledComposite( shell, SWT.NO_SCROLL ); Class<ScrolledCompositeAdapter> adapterType = ScrolledCompositeAdapter.class; Optional<ScrolledCompositeAdapter> adapter = adapterFactory.create( scrolledComposite, adapterType ); assertThat( adapter.isPresent() ).isFalse(); } private void scrollHorizontal( ScrolledCompositeAdapter 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 ); } }