/******************************************************************************* * Copyright (c) 2012, 2014 EclipseSource and others. * 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: * EclipseSource - initial API and implementation ******************************************************************************/ package org.eclipse.swt.internal.events; import static org.eclipse.rap.rwt.internal.lifecycle.DisplayUtil.getId; import static org.eclipse.rap.rwt.internal.protocol.RemoteObjectFactory.getRemoteObject; import static org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil.getId; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import java.util.ArrayList; import org.eclipse.rap.rwt.internal.lifecycle.PhaseId; import org.eclipse.rap.rwt.internal.protocol.ClientMessageConst; import org.eclipse.rap.rwt.internal.service.ContextProvider; import org.eclipse.rap.rwt.testfixture.internal.Fixture; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.events.ShellListener; import org.eclipse.swt.events.TypedEvent; import org.eclipse.swt.internal.widgets.buttonkit.ButtonOperationHandler; import org.eclipse.swt.internal.widgets.textkit.TextOperationHandler; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Widget; import org.junit.After; import org.junit.Before; import org.junit.Test; public class EventUtil_Test { private Display display; private Shell shell; @Before public void setUp() { Fixture.setUp(); display = new Display(); shell = new Shell( display ); shell.setLayout( new FillLayout() ); Fixture.fakeNewRequest(); } @After public void tearDown() { if( !ContextProvider.hasContext() ) { Fixture.createServiceContext(); } Fixture.tearDown(); } @Test public void testGetLastEventTimeInSameRequest() { Fixture.fakePhase( PhaseId.READ_DATA ); int eventTime1 = EventUtil.getLastEventTime(); int eventTime2 = EventUtil.getLastEventTime(); assertEquals( eventTime1, eventTime2 - 1 ); } @Test public void testGetLastEventTimeInSubsequentRequests() throws InterruptedException { Fixture.fakePhase( PhaseId.READ_DATA ); int eventTime1 = EventUtil.getLastEventTime(); simulateNewRequest(); Thread.sleep( 5 ); int eventTime2 = EventUtil.getLastEventTime(); assertTrue( eventTime1 < eventTime2 ); } @Test public void testGetLastEventTimeWithoutCurrentPhase() { Fixture.fakePhase( null ); int eventTime = EventUtil.getLastEventTime(); assertTrue( eventTime > 0 ); } @Test public void testGetLastEventTimeOutsideRequest() { ContextProvider.releaseContextHolder(); int eventTime = EventUtil.getLastEventTime(); assertTrue( eventTime > 0 ); } @Test public void testAllowProcessingForActivateEventOnInvisibleControl() { Control control = new Button( shell, SWT.PUSH ); control.setEnabled( false ); Event event = createEvent( control, SWT.Activate ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testAllowProcessingForDeactivateEventOnInvisibleControl() { Control control = new Button( shell, SWT.PUSH ); control.setEnabled( false ); Event event = createEvent( control, SWT.Deactivate ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testAllowProcessingForProgressEventOnInvisibleBrowser() { Browser browser = new Browser( shell, SWT.NONE ); Event event = createEvent( browser, EventTypes.PROGRESS_CHANGED ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testAllowProcessingForResizeEventOnDisabledControl() { Control control = new Button( shell, SWT.PUSH ); control.setEnabled( false ); Event event = createEvent( control, SWT.Resize ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testAllowProcessingForMoveEventOnDisabledControl() { Control control = new Button( shell, SWT.PUSH ); control.setEnabled( false ); Event event = createEvent( control, SWT.Move ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testAllowProcessingForModifyEventOnDisabledText() { Text text = new Text( shell, SWT.PUSH ); text.setEnabled( false ); Event event = createEvent( text, SWT.Modify ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testAllowProcessingForVerifyEventOnDisabledText() { Text text = new Text( shell, SWT.PUSH ); text.setEnabled( false ); Event event = createEvent( text, SWT.Verify ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testAllowProcessingForPaintEventOnDisabledControl() { Control control = new Canvas( shell, SWT.PUSH ); control.setEnabled( false ); Event event = createEvent( control, SWT.Paint ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testAllowProcessingForSetDataEventOnDisabledControl() { Control text = new Canvas( shell, SWT.PUSH ); text.setEnabled( false ); Event event = createEvent( text, SWT.SetData ); boolean accessible = EventUtil.allowProcessing( event ); assertTrue( accessible ); } @Test public void testЕventNotFiredOnDisabledButton() { Button button = new Button( shell, SWT.PUSH ); getRemoteObject( button ).setHandler( new ButtonOperationHandler( button ) ); button.setEnabled( false ); SelectionListener listener = mock( SelectionListener.class ); button.addSelectionListener( listener ); shell.open(); Fixture.fakeNotifyOperation( getId( button ), ClientMessageConst.EVENT_SELECTION, null ); Fixture.readDataAndProcessAction( button ); verify( listener, never() ).widgetSelected( any( SelectionEvent.class ) ); } @Test public void testЕventNotFiredOnInvisibleButton() { Button button = new Button( shell, SWT.PUSH ); getRemoteObject( button ).setHandler( new ButtonOperationHandler( button ) ); button.setVisible( false ); SelectionListener listener = mock( SelectionListener.class ); button.addSelectionListener( listener ); shell.open(); Fixture.fakeNotifyOperation( getId( button ), ClientMessageConst.EVENT_SELECTION, null ); Fixture.readDataAndProcessAction( button ); verify( listener, never() ).widgetSelected( any( SelectionEvent.class ) ); } @Test public void testЕventNotFiredOnDisposedButton() { // LCAs not called for disposed widgets Button button = new Button( shell, SWT.PUSH ); SelectionListener listener = mock( SelectionListener.class ); button.addSelectionListener( listener ); button.dispose(); shell.open(); Fixture.fakeNotifyOperation( getId( button ), ClientMessageConst.EVENT_SELECTION, null ); Fixture.executeLifeCycleFromServerThread(); verify( listener, never() ).widgetSelected( any( SelectionEvent.class ) ); } @Test public void testEventNotFiredOnBlockedParentShell() { Button button = new Button( shell, SWT.PUSH ); getRemoteObject( button ).setHandler( new ButtonOperationHandler( button ) ); SelectionListener listener = mock( SelectionListener.class ); button.addSelectionListener( listener ); shell.open(); Shell dialog = new Shell( shell, SWT.APPLICATION_MODAL ); dialog.setSize( 100, 100 ); dialog.open(); Fixture.fakeNotifyOperation( getId( button ), ClientMessageConst.EVENT_SELECTION, null ); Fixture.readDataAndProcessAction( display ); verify( listener, never() ).widgetSelected( any( SelectionEvent.class ) ); } @Test public void testFocusOutOpensModalShell() { final java.util.List<TypedEvent> events = new ArrayList<TypedEvent>(); Text text = new Text( shell, SWT.NONE ); getRemoteObject( text ).setHandler( new TextOperationHandler( text ) ); text.addFocusListener( new FocusAdapter() { @Override public void focusLost( FocusEvent event ) { events.add( event ); Shell dialog = new Shell( shell, SWT.APPLICATION_MODAL ); dialog.setSize( 100, 100 ); dialog.open(); } } ); Button button = new Button( shell, SWT.PUSH ); getRemoteObject( button ).setHandler( new ButtonOperationHandler( button ) ); SelectionListener selectionListener = mock( SelectionListener.class ); button.addSelectionListener( selectionListener ); shell.open(); // Within this request a focusLost and widgetSelected (for the button) // is sent. The focusList listener opens a modal shell, thus the event on // button must not be executed Fixture.fakeSetProperty( getId( display ), "focusControl", getId( button ) ); Fixture.fakeNotifyOperation( getId( text ), ClientMessageConst.EVENT_FOCUS_OUT, null ); Fixture.fakeNotifyOperation( getId( button ), ClientMessageConst.EVENT_SELECTION, null ); Fixture.readDataAndProcessAction( display ); assertEquals( 1, events.size() ); assertEquals( FocusEvent.class, events.get( 0 ).getClass() ); FocusEvent event = ( FocusEvent )events.get( 0 ); assertSame( text, event.widget ); verify( selectionListener, never() ).widgetSelected( any( SelectionEvent.class ) ); } @Test public void testCloseEventNotFiredOnDisposedShell() { // LCAs not called for disposed widgets shell.setSize( 100, 100 ); ShellListener listener = mock( ShellListener.class ); shell.addShellListener( listener ); shell.open(); shell.dispose(); Fixture.fakeNotifyOperation( getId( shell ), ClientMessageConst.EVENT_CLOSE, null ); Fixture.executeLifeCycleFromServerThread( ); verify( listener, never() ).shellClosed( any( ShellEvent.class ) ); } @Test public void testNestedModalShell() { Shell parentShell = new Shell( shell, SWT.APPLICATION_MODAL ); parentShell.setSize( 100, 100 ); parentShell.open(); Shell childShell = new Shell( parentShell, SWT.APPLICATION_MODAL ); childShell.setSize( 100, 100 ); Button button = new Button( childShell, SWT.PUSH ); getRemoteObject( button ).setHandler( new ButtonOperationHandler( button ) ); SelectionListener selectionListener = mock( SelectionListener.class ); button.addSelectionListener( selectionListener ); childShell.open(); Fixture.fakeNotifyOperation( getId( button ), ClientMessageConst.EVENT_SELECTION, null ); Fixture.readDataAndProcessAction( display ); verify( selectionListener ).widgetSelected( any( SelectionEvent.class ) ); } private static Event createEvent( Widget widget, int eventType ) { Event result = new Event(); result.widget = widget; result.type = eventType; return result; } private void simulateNewRequest() { ContextProvider.releaseContextHolder(); Fixture.createServiceContext(); Fixture.fakePhase( PhaseId.READ_DATA ); } }