/*******************************************************************************
* Copyright (c) 2002, 2010 Innoopract Informationssysteme GmbH.
* 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:
* Innoopract Informationssysteme GmbH - initial API and implementation
* EclipseSource - ongoing development
******************************************************************************/
package org.eclipse.swt.widgets;
import java.util.ArrayList;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.eclipse.rwt.Fixture;
import org.eclipse.rwt.internal.lifecycle.DisposedWidgets;
import org.eclipse.rwt.lifecycle.IWidgetAdapter;
import org.eclipse.rwt.lifecycle.PhaseId;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.*;
public class Widget_Test extends TestCase {
protected void setUp() throws Exception {
Fixture.setUp();
}
protected void tearDown() throws Exception {
Fixture.tearDown();
}
public void testGetAdapter() {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
Display display = new Display();
Widget shell = new Shell( display );
// ensure that Widget#getAdapter can be called after widget was disposed of
shell.dispose();
assertNotNull( shell.getAdapter( IWidgetAdapter.class ) );
}
public void testCheckWidget() throws InterruptedException {
Display display = new Display();
Shell shell = new Shell( display, SWT.NONE );
final Widget widget = new Text( shell, SWT.NONE );
final Throwable[] throwable = new Throwable[ 1 ];
final String[] message = new String[ 1 ];
Thread thread = new Thread( new Runnable() {
public void run() {
try {
widget.checkWidget();
fail( "Illegal thread access expected." );
} catch( final SWTException swte ) {
message[ 0 ] = swte.getMessage();
} catch( final Throwable thr ) {
throwable[ 0 ] = thr;
}
}
});
thread.start();
thread.join();
assertEquals( message[ 0 ], "Invalid thread access" );
assertNull( throwable[ 0 ] );
}
public void testData() {
Display display = new Display();
Shell shell = new Shell( display );
Widget widget = new Text( shell, SWT.NONE );
// Test initial state
assertEquals( null, widget.getData() );
Object singleData = new Object();
// Set/get some single data
widget.setData( singleData );
assertSame( singleData, widget.getData() );
// Set/get some keyed data, ensure that single data remains unchanged
Object keyedData = new Object();
widget.setData( "key", keyedData );
widget.setData( "null-key", null );
assertSame( singleData, widget.getData() );
assertSame( keyedData, widget.getData( "key" ) );
assertSame( null, widget.getData( "null-key" ) );
// Test 'deleting' a key
widget.setData( "key", null );
assertNull( widget.getData( "key" ) );
// Test keyed data with non-existing key
assertNull( widget.getData( "non-existing-key" ) );
// Test keyed data with illegal arguments
try {
widget.setData( null, new Object() );
fail( "Must not allow to set data with null key" );
} catch( IllegalArgumentException e ) {
// expected
}
try {
widget.getData( null );
fail( "Must not allow to get data for null key" );
} catch( IllegalArgumentException e ) {
// expected
}
}
public void testDisposeParentWhileInDispose() {
// This test leads to a stack overflow or, if line "item[ 0 ].dispose();"
// is activated to a NPE
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
Display display = new Display();
Shell shell = new Shell( display, SWT.NONE );
final Composite composite = new Composite( shell, SWT.NONE );
ToolBar toolbar = new ToolBar( composite, SWT.NONE );
final ToolItem[] item = { null };
toolbar.addDisposeListener( new DisposeListener() {
public void widgetDisposed( final DisposeEvent event ) {
item[ 0 ].dispose();
}
} );
toolbar.addDisposeListener( new DisposeListener() {
public void widgetDisposed( final DisposeEvent event ) {
composite.dispose();
}
} );
item[ 0 ] = new ToolItem( toolbar, SWT.PUSH );
shell.dispose();
// no assert: this test ensures that no StackOverflowError occurs
}
public void testDisposeSelfWhileInDispose() {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
Display display = new Display();
final Shell widget = new Shell( display, SWT.NONE );
widget.addDisposeListener( new DisposeListener() {
public void widgetDisposed( final DisposeEvent event ) {
widget.dispose();
}
} );
widget.dispose();
// no assert: this test ensures that no exception occurs
}
public void testCheckBits() {
int style = SWT.VERTICAL | SWT.HORIZONTAL;
int result = Widget.checkBits( style,
SWT.VERTICAL,
SWT.HORIZONTAL,
0,
0,
0,
0 );
assertTrue( ( result & SWT.VERTICAL ) != 0 );
assertFalse( ( result & SWT.HORIZONTAL ) != 0 );
}
public void testDispose() {
Display display = new Display();
Shell shell = new Shell( display );
Widget widget = new Button( shell, SWT.NONE );
// Ensure initial state
assertEquals( false, widget.isDisposed() );
// Test dispose the first time
widget.dispose();
assertEquals( true, widget.isDisposed() );
// Disposing of an already disposed of widget does nothing
widget.dispose();
assertEquals( true, widget.isDisposed() );
}
public void testDisposeFromIllegalThread() throws InterruptedException {
Display display = new Display();
Shell shell = new Shell( display );
final Widget widget = new Button( shell, SWT.NONE );
final AssertionFailedError[] failure = new AssertionFailedError[ 1 ];
Thread thread = new Thread( new Runnable() {
public void run() {
try {
widget.dispose();
fail( "Must not allow to dispose of a widget from a non-UI-thread" );
} catch( SWTException e ) {
// expected
} catch( final AssertionFailedError afa ) {
failure[ 0 ] = afa;
}
}
} );
thread.start();
thread.join();
if( failure[ 0 ] != null ) {
throw failure[ 0 ];
}
}
public void testDisposeWithException() throws Exception {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
Display display = new Display();
Widget widget = new Shell( display );
widget.addDisposeListener( new DisposeListener() {
public void widgetDisposed( final DisposeEvent event ) {
throw new RuntimeException();
}
} );
try {
widget.dispose();
fail( "Wrong test setup: dispose listener must throw exception" );
} catch( Exception e ) {
// expected
}
assertFalse( widget.isDisposed() );
assertEquals( 0, DisposedWidgets.getAll().length );
}
public void testRemoveListener() {
// Ensure that removing a listener that was never added is ignored
// silently see https://bugs.eclipse.org/251816
Display display = new Display();
Widget widget = new Shell( display );
widget.removeListener( SWT.Activate, new Listener() {
public void handleEvent( final Event event ) {
}
} );
}
public void testNotifyListeners() throws Exception {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
Display display = new Display();
Widget widget = new Shell( display );
final StringBuffer log = new StringBuffer();
widget.addListener( SWT.Resize, new Listener() {
public void handleEvent( final Event event ) {
log.append( "untyped" );
}
} );
widget.notifyListeners( SWT.Resize, new Event() );
assertEquals( "untyped", log.toString() );
}
public void testNotifyListenersTyped() throws Exception {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
Display display = new Display();
Shell shell = new Shell( display );
final StringBuffer log = new StringBuffer();
shell.addControlListener( new ControlAdapter() {
public void controlResized( final ControlEvent e ) {
log.append( "typed" );
}
} );
shell.notifyListeners( SWT.Resize, new Event() );
assertEquals( "typed", log.toString() );
}
public void testNotifyListenersDisplayFilter() throws Exception {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
Display display = new Display();
Shell shell = new Shell( display );
final StringBuffer log = new StringBuffer();
display.addFilter( SWT.Resize, new Listener() {
public void handleEvent( final Event event ) {
log.append( "filter" );
}
});
shell.notifyListeners( SWT.Resize, new Event() );
assertEquals( "filter", log.toString() );
}
// SWT always overrides e.type, e.display and e.widget
public void testNotifyListenersEventFields() throws Exception {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
final Display display = new Display();
final Shell shell = new Shell( display );
final StringBuffer log = new StringBuffer();
display.addFilter( SWT.Resize, new Listener() {
public void handleEvent( final Event event ) {
assertEquals( SWT.Resize, event.type );
assertEquals( shell, event.widget );
log.append( "filter" );
}
});
Event event = new Event();
event.button = 2;
event.character = 'a';
event.count = 4;
event.data = new Object();
event.detail = 6;
event.display = null;
event.doit = false;
event.end = 8;
event.height = 10;
event.index = 12;
event.item = shell;
event.keyCode = 14;
event.start = 16;
event.stateMask = 18;
event.text = "foo";
event.type = SWT.MouseDoubleClick;
event.widget = shell;
event.width = 20;
event.x = 22;
event.y = 24;
shell.notifyListeners( SWT.Resize, event );
assertEquals( "filter", log.toString() );
}
public void testNotifyListenersSetData() throws Exception {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
final Display display = new Display();
final Widget widget = new Shell( display );
final StringBuffer log = new StringBuffer();
widget.addListener( SWT.SetData, new Listener(){
public void handleEvent( final Event event ) {
assertSame( widget, event.widget );
assertSame( widget, event.item );
assertEquals( 3, event.index );
assertSame( display, event.display );
log.append( "setdata" );
}
});
Event event = new Event();
event.item = widget;
event.index = 3;
widget.notifyListeners( SWT.SetData, event );
assertEquals( "setdata", log.toString() );
}
public void testNotifyListenersNullEvent() throws Exception {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
final Display display = new Display();
final Control control = new Shell( display );
final StringBuffer log = new StringBuffer();
control.addControlListener( new ControlAdapter() {
public void controlResized( final ControlEvent event ) {
assertSame( control, event.widget );
assertSame( display, event.display );
log.append( "typed" );
}
} );
control.notifyListeners( SWT.Resize, null );
assertEquals( "typed", log.toString() );
}
public void testNotifyListenersInvalidEvent() {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
final Display display = new Display();
final Widget widget = new Shell( display );
widget.notifyListeners( 4711, new Event() );
// no assertion: this test ensures that invalid event types are silently
// ignored
}
public void testGetListeners() throws Exception {
final Display display = new Display();
final Widget widget = new Shell( display );
Listener[] listeners = widget.getListeners( 0 );
assertNotNull( listeners );
assertEquals( 0, listeners.length );
Listener dummyListener = new Listener() {
public void handleEvent( final Event event ) {
}
};
Listener dummyListener2 = new Listener() {
public void handleEvent( final Event event ) {
}
};
widget.addListener( SWT.Resize, dummyListener );
assertEquals( 0, widget.getListeners( SWT.Move ).length );
assertEquals( 1, widget.getListeners( SWT.Resize ).length );
assertSame( dummyListener, widget.getListeners( SWT.Resize )[0] );
widget.addListener( SWT.Resize, dummyListener2 );
assertEquals( 2, widget.getListeners( SWT.Resize ).length );
}
public void testIsListening() throws Exception {
final Display display = new Display();
final Widget widget = new Shell( display );
final Listener dummyListener = new Listener() {
public void handleEvent( final Event event ) {
}
};
assertFalse( widget.isListening( SWT.Resize ) );
widget.addListener( SWT.Resize, dummyListener );
assertTrue( widget.isListening( SWT.Resize ) );
widget.removeListener( SWT.Resize, dummyListener );
assertFalse( widget.isListening( SWT.Resize ) );
}
public void testIsListeningForTypedEvent() {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
Display display = new Display();
Control control = new Shell( display );
control.addHelpListener( new HelpListener() {
public void helpRequested( final HelpEvent event ) {
}
} );
assertTrue( control.isListening( SWT.Help ) );
}
public void testReskin() {
Fixture.fakePhase( PhaseId.PROCESS_ACTION );
final java.util.List log = new ArrayList();
Display display = new Display();
Listener listener = new Listener() {
public void handleEvent( final Event event ) {
if( event.type == SWT.Skin ) {
log.add( event.widget );
}
}
};
display.addListener( SWT.Skin, listener );
Shell shell = new Shell( display );
Composite child1 = new Composite( shell, SWT.NONE );
Label subchild1 = new Label( child1, SWT.NONE );
Composite child2 = new Composite( shell, SWT.NONE );
Label subchild2 = new Label( child2, SWT.NONE );
Composite child3 = new Composite( shell, SWT.NONE );
Label subchild3 = new Label( child3, SWT.NONE );
shell.reskin( SWT.ALL );
display.readAndDispatch();
assertEquals( 7, log.size() );
assertSame( shell, log.get( 0 ) );
assertSame( child1, log.get( 1 ) );
assertSame( subchild1, log.get( 2 ) );
assertSame( child2, log.get( 3 ) );
assertSame( subchild2, log.get( 4 ) );
assertSame( child3, log.get( 5 ) );
assertSame( subchild3, log.get( 6 ) );
log.clear();
shell.setData( SWT.SKIN_CLASS, "skin" );
display.readAndDispatch();
assertEquals( 7, log.size() );
assertSame( shell, log.get( 0 ) );
assertSame( child1, log.get( 1 ) );
assertSame( subchild1, log.get( 2 ) );
assertSame( child2, log.get( 3 ) );
assertSame( subchild2, log.get( 4 ) );
assertSame( child3, log.get( 5 ) );
assertSame( subchild3, log.get( 6 ) );
log.clear();
shell.setData( SWT.SKIN_ID, "skin" );
display.readAndDispatch();
assertEquals( 7, log.size() );
assertSame( shell, log.get( 0 ) );
assertSame( child1, log.get( 1 ) );
assertSame( subchild1, log.get( 2 ) );
assertSame( child2, log.get( 3 ) );
assertSame( subchild2, log.get( 4 ) );
assertSame( child3, log.get( 5 ) );
assertSame( subchild3, log.get( 6 ) );
log.clear();
child3.reskin( SWT.ALL );
display.readAndDispatch();
assertEquals( 2, log.size() );
assertSame( child3, log.get( 0 ) );
assertSame( subchild3, log.get( 1 ) );
log.clear();
child2.reskin( SWT.NONE );
display.readAndDispatch();
assertEquals( 1, log.size() );
assertSame( child2, log.get( 0 ) );
log.clear();
display.removeListener( SWT.Skin, listener );
shell.reskin( SWT.ALL );
display.readAndDispatch();
assertEquals( 0, log.size() );
}
}