From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. Signed-off-by: Daniel Baumann --- .../qa/complex/toolkit/AccessibleStatusBar.java | 315 ++++++ .../complex/toolkit/AccessibleStatusBarItem.java | 359 +++++++ toolkit/qa/complex/toolkit/Assert.java | 185 ++++ toolkit/qa/complex/toolkit/GridControl.java | 746 +++++++++++++++ .../accessibility/_XAccessibleComponent.java | 463 +++++++++ .../toolkit/accessibility/_XAccessibleContext.java | 246 +++++ .../_XAccessibleEventBroadcaster.java | 177 ++++ .../_XAccessibleExtendedComponent.java | 75 ++ .../toolkit/accessibility/_XAccessibleText.java | 1001 ++++++++++++++++++++ .../qa/complex/toolkit/awtgrid/DummyColumn.java | 167 ++++ .../complex/toolkit/awtgrid/GridDataListener.java | 107 +++ .../toolkit/awtgrid/TMutableGridDataModel.java | 449 +++++++++ 12 files changed, 4290 insertions(+) create mode 100644 toolkit/qa/complex/toolkit/AccessibleStatusBar.java create mode 100644 toolkit/qa/complex/toolkit/AccessibleStatusBarItem.java create mode 100644 toolkit/qa/complex/toolkit/Assert.java create mode 100644 toolkit/qa/complex/toolkit/GridControl.java create mode 100644 toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent.java create mode 100644 toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext.java create mode 100644 toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster.java create mode 100644 toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent.java create mode 100644 toolkit/qa/complex/toolkit/accessibility/_XAccessibleText.java create mode 100644 toolkit/qa/complex/toolkit/awtgrid/DummyColumn.java create mode 100644 toolkit/qa/complex/toolkit/awtgrid/GridDataListener.java create mode 100644 toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel.java (limited to 'toolkit/qa/complex') diff --git a/toolkit/qa/complex/toolkit/AccessibleStatusBar.java b/toolkit/qa/complex/toolkit/AccessibleStatusBar.java new file mode 100644 index 000000000..abed29c56 --- /dev/null +++ b/toolkit/qa/complex/toolkit/AccessibleStatusBar.java @@ -0,0 +1,315 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit; + +import complex.toolkit.accessibility._XAccessibleEventBroadcaster; +import complex.toolkit.accessibility._XAccessibleExtendedComponent; +import complex.toolkit.accessibility._XAccessibleComponent; +import complex.toolkit.accessibility._XAccessibleContext; +import java.util.logging.Logger; +import java.util.logging.Level; +import util.SOfficeFactory; +import util.AccessibilityTools; +import com.sun.star.awt.XWindow; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.sheet.XSpreadsheetDocument; +import com.sun.star.text.XTextDocument; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.XCloseable; +import com.sun.star.accessibility.AccessibleRole; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.awt.XExtendedToolkit; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openoffice.test.OfficeConnection; +import static org.junit.Assert.*; + +/** + * + */ +public class AccessibleStatusBar { + + XInterface testObject = null; + XMultiServiceFactory xMSF = null; + XWindow xWindow = null; + + private XMultiServiceFactory getMSF() + { + return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager()); + } + + /** + * Check document types + */ + @Test + public void checkDocs() { + checkWriterDoc(); + checkMathDoc(); + checkDrawDoc(); + checkImpressDoc(); + checkCalcDoc(); + } + + /** + * Test the interfaces on a writer document + */ + public void checkWriterDoc() { + xMSF = getMSF(); + SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF); + XTextDocument xTextDoc = null; + try { + System.out.println("****** Open a new writer document"); + xTextDoc = xSOF.createTextDoc("_blank"); + getTestObject(); + } + catch(com.sun.star.uno.Exception e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + runAllInterfaceTests(); + + if (xTextDoc != null) { + XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xTextDoc); + try { + xClose.close(false); + } + catch(com.sun.star.util.CloseVetoException e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + } + } + + /** + * Test the interfaces on a math document + */ + public void checkMathDoc() { + xMSF = getMSF(); + SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF); + XComponent xMathDoc = null; + try { + System.out.println("****** Open a new math document"); + xMathDoc = xSOF.createMathDoc("_blank"); + getTestObject(); + } + catch(com.sun.star.uno.Exception e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + runAllInterfaceTests(); + + if (xMathDoc != null) { + XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xMathDoc); + try { + xClose.close(false); + } + catch(com.sun.star.util.CloseVetoException e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + } + } + + /** + * Test the interfaces on a draw document + */ + public void checkDrawDoc() { + xMSF = getMSF(); + SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF); + XComponent xDrawDoc = null; + try { + System.out.println("****** Open a new draw document"); + xDrawDoc = xSOF.createDrawDoc("_blank"); + getTestObject(); + } + catch(com.sun.star.uno.Exception e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + runAllInterfaceTests(); + + if (xDrawDoc != null) { + XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xDrawDoc); + try { + xClose.close(false); + } + catch(com.sun.star.util.CloseVetoException e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + } + } + + /** + * Test the interfaces on an impress document + */ + public void checkImpressDoc() { + xMSF = getMSF(); + SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF); + XComponent xImpressDoc = null; + try { + System.out.println("****** Open a new impress document"); + xImpressDoc = xSOF.createImpressDoc("_blank"); + getTestObject(); + } + catch(com.sun.star.uno.Exception e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + runAllInterfaceTests(); + + if (xImpressDoc != null) { + XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xImpressDoc); + try { + xClose.close(false); + } + catch(com.sun.star.util.CloseVetoException e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + } + } + /** + * Test the interfaces on a calc document + */ + public void checkCalcDoc() { + xMSF = getMSF(); + SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF); + XSpreadsheetDocument xSpreadsheetDoc = null; + try { + System.out.println("****** Open a new calc document"); + xSpreadsheetDoc = xSOF.createCalcDoc("_blank"); + util.utils.waitForEventIdle(xMSF); + getTestObject(); + } + catch(com.sun.star.uno.Exception e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + runAllInterfaceTests(); + + if (xSpreadsheetDoc != null) { + XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xSpreadsheetDoc); + try { + xClose.close(false); + } + catch(com.sun.star.util.CloseVetoException e) { + Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e ); + } + } + } + + public void getTestObject() { + try { + XInterface xIfc = (XInterface) xMSF.createInstance( + "com.sun.star.awt.Toolkit") ; + XExtendedToolkit tk = UnoRuntime.queryInterface(XExtendedToolkit.class, xIfc); + + util.utils.waitForEventIdle(xMSF); + xWindow = UnoRuntime.queryInterface(XWindow.class, tk.getActiveTopWindow()); + + util.utils.waitForEventIdle(xMSF); + XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow); + XAccessibleContext parentContext = null; + + System.out.println("Get the accessible status bar."); + parentContext = AccessibilityTools.getAccessibleObjectForRole( + xRoot, AccessibleRole.STATUS_BAR, ""); + util.utils.waitForEventIdle(xMSF); + System.out.println("...OK."); + + XServiceInfo xSI = UnoRuntime.queryInterface(XServiceInfo.class, parentContext); + String[] services = xSI.getSupportedServiceNames(); + System.out.println("*****"); + System.out.println("* Implementation Name: " + xSI.getImplementationName()); + for (int i=0; ino exception must be throw by invoking the method. + */ + public static void assertException( final String i_message, final Object i_object, final String i_methodName, + final Class[] i_argClasses, final Object[] i_methodArgs, final Class i_expectedExceptionClass ) + { + Class objectClass = i_object.getClass(); + + boolean noExceptionAllowed = ( i_expectedExceptionClass == null ); + + boolean caughtExpected = noExceptionAllowed; + try + { + Method method = impl_getMethod( objectClass, i_methodName, i_argClasses ); + method.invoke(i_object, i_methodArgs ); + } + catch ( NoSuchMethodException e ) + { + StringBuilder message = new StringBuilder(); + message.append( "no such method: " ).append( objectClass.getName() ).append( '.' ).append( i_methodName ).append( "( " ); + for ( int i=0; ifoo( int ), {@link Class#getMethod} would not return this + * method when you pass Integer.class. impl_getMethod will recognize this, and + * properly retrieve the method. + * + * Note: impl_getMethod is limited in that it will not try all possible combinations of primitive + * and non-primitive types. That is, a method like foo( int, Integer, int ) is likely to not be + * found. + * + * @param i_objectClass + * @param i_methodName + * @param i_argClasses + * @return + */ + private static Method impl_getMethod( final Class i_objectClass, final String i_methodName, final Class[] i_argClasses ) throws NoSuchMethodException + { + try + { + return i_objectClass.getMethod( i_methodName, i_argClasses ); + } + catch ( NoSuchMethodException ex ) + { + } + + int substitutedTypes = 0; + int substitutedTypesLastRound = 0; + final Class[][] substitutionTable = new Class[][] { + new Class[] { Long.class, long.class }, + new Class[] { Integer.class, int.class }, + new Class[] { Short.class, short.class }, + new Class[] { Byte.class, byte.class }, + new Class[] { Double.class, double.class }, + new Class[] { Float.class, float.class }, + new Class[] { Character.class, char.class } + }; + do + { + substitutedTypes = 0; + final Class[] argClasses = new Class[ i_argClasses.length ]; + for ( int i=0; i < argClasses.length; ++i ) + { + argClasses[i] = i_argClasses[i]; + if ( substitutedTypes > substitutedTypesLastRound ) + continue; + + for ( int c=0; c 0 ); + throw new NoSuchMethodException(); + } + + /** invokes a given method on a given object, and assures a certain exception is caught + * @param i_message is the message to print when the check fails + * @param i_object is the object to invoke the method on + * @param i_methodName is the name of the method to invoke + * @param i_methodArgs are the arguments to pass to the method. Those implicitly define + * the classes of the arguments of the method which is called. + * @param i_expectedExceptionClass is the class of the exception to be caught. If this is null, + * it means that no exception must be throw by invoking the method. + */ + public static void assertException( final String i_message, final Object i_object, final String i_methodName, + final Object[] i_methodArgs, final Class i_expectedExceptionClass ) + { + Class[] argClasses = new Class[ i_methodArgs.length ]; + for ( int i=0; iXMutableGridDataModel interface + */ + @Test + public void testMutableGridDataModel() throws Exception + { + impl_recreateGridModel(); + + TMutableGridDataModel test = new TMutableGridDataModel( m_dataModel ); + test.testAddRow(); + test.testAddRows(); + test.testInsertRow(); + test.testInsertRows(); + test.testRemoveRow(); + test.testRemoveAllRows(); + test.testUpdateCellData(); + test.testUpdateRowData(); + test.testUpdateRowHeading(); + test.cleanup(); + + // a somewhat less straight-forward test: the data model is expected to implicitly increase its column count + // when you add a row which has more columns than currently known + final XMutableGridDataModel dataModel = DefaultGridDataModel.create( m_context ); + dataModel.addRow( 0, new Object[] { 1 } ); + assertEquals( "unexpected column count after adding the most simple row", 1, dataModel.getColumnCount() ); + dataModel.addRow( 1, new Object[] { 1, 2 } ); + assertEquals( "implicit extension of the column count doesn't work", 2, dataModel.getColumnCount() ); + } + + + @Test + public void testGridColumnModel() throws Exception + { + impl_recreateGridModel(); + + ColumnModelListener listener = new ColumnModelListener(); + m_columnModel.addContainerListener( listener ); + + // insert default columns into the previously empty model, ensure we get the right notifications + final int defaultColumnsCount = 3; + m_columnModel.setDefaultColumns( defaultColumnsCount ); + impl_assertColumnModelConsistency(); + List< ContainerEvent > events = listener.assertExclusiveInsertionEvents(); + listener.reset(); + assertEquals( "wrong number of events fired by setDefaultColumns", defaultColumnsCount, events.size() ); + for ( int i=0; i removalEvents = listener.getRemovalEvents(); + final List< ContainerEvent > insertionEvents = listener.getInsertionEvents(); + listener.reset(); + + // for the removal events, check the indexes + assertEquals( "wrong number of columns removed (or notified) upon setting default columns", + defaultColumnsCount, removalEvents.size() ); + for ( int i=0; i currentSortOrder = m_dataModel.getCurrentSortOrder(); + assertEquals( "invalid current sort column (column " + colIndex + ")", currentSortOrder.First.intValue(), colIndex ); + assertEquals( "invalid current sort direction", currentSortOrder.Second.booleanValue(), ascending ); + + /*for ( int i=0; i= nextIntValue ); + + // ensure the data in the other columns, and the row headings, are sorted as well + final Object rowHeading = m_dataModel.getRowHeading( rowIndex ); + final int unsortedRowIndex = impl_assertInteger( rowHeading ); + for ( int innerColIndex = 0; innerColIndex < colCount; ++innerColIndex ) + { + assertEquals( "sorted row " + rowIndex + ", unsorted row " + unsortedRowIndex + ", col " + innerColIndex + + ": wrong data", + data[unsortedRowIndex][innerColIndex], m_dataModel.getCellData( innerColIndex, rowIndex ) ); + } + } + } + } + } + + + @Test + public void testView() throws Exception + { + final XControl control = impl_createDialogWithGridControl(); + final XPropertySet gridModelProps = + UnoRuntime.queryInterface( XPropertySet.class, control.getModel() ); + + // in the current implementation (not sure this is a good idea at all), the control (more precise: the peer) + // ensures that if there are no columns in the column model, but in the data model, then the column model + // will implicitly have the needed columns added. + // To ensure that clients which rely on this do not break in the future, check this here. + final XMutableGridDataModel dataModel = UnoRuntime.queryInterface( XMutableGridDataModel.class, + gridModelProps.getPropertyValue( "GridDataModel" ) ); + assertNotNull( dataModel ); + assertEquals( 0, dataModel.getColumnCount() ); + + final XGridColumnModel columnModel = UnoRuntime.queryInterface( XGridColumnModel.class, + gridModelProps.getPropertyValue( "ColumnModel" ) ); + assertNotNull( columnModel ); + assertEquals( 0, columnModel.getColumnCount() ); + + final int columnCount = 3; + final int rowCount = 2; + dataModel.addRow( null, new Object[] { 1, 2, 3 } ); + dataModel.addRow( null, new Object[] { 6, 5, 4 } ); + + assertEquals( columnCount, dataModel.getColumnCount() ); + assertEquals( columnCount, columnModel.getColumnCount() ); + + // some cursor traveling + final XGridControl gridControl = UnoRuntime.queryInterface( XGridControl.class, control ); + gridControl.goToCell( 0, 0 ); + assertEquals( "wrong 'current column' (1)", 0, gridControl.getCurrentColumn() ); + assertEquals( "wrong 'current row' (1)", 0, gridControl.getCurrentRow() ); + gridControl.goToCell( columnCount - 1, rowCount - 1 ); + assertEquals( "wrong 'current column' (2)", dataModel.getColumnCount() - 1, gridControl.getCurrentColumn() ); + assertEquals( "wrong 'current row' (2)", dataModel.getRowCount() - 1, gridControl.getCurrentRow() ); + + // removing the last column, while the active cell is in this very last column, is expected to adjust + // the active cell + columnModel.removeColumn( columnCount - 1 ); + assertEquals( "removed the last and active column, active column was not adjusted!", + columnCount - 2, gridControl.getCurrentColumn() ); + // same holds for rows + dataModel.removeRow( rowCount - 1 ); + assertEquals( "removed the last and active row, active row was not adjusted!", + rowCount - 2, gridControl.getCurrentRow() ); + } + + + private XControl impl_createDialogWithGridControl() throws Exception + { + // create a simple dialog model/control/peer trinity + final XControlModel dialogModel = createInstance( XControlModel.class, "com.sun.star.awt.UnoControlDialogModel" ); + m_disposables.add( dialogModel ); + final XPropertySet dialogProps = UnoRuntime.queryInterface( XPropertySet.class, dialogModel ); + dialogProps.setPropertyValue( "Width", 200 ); + dialogProps.setPropertyValue( "Height", 100 ); + dialogProps.setPropertyValue( "Title", "Grid Control Unit Test" ); + final XControl dialogControl = createInstance( XControl.class, "com.sun.star.awt.UnoControlDialog" ); + m_disposables.add( dialogControl ); + dialogControl.setModel( dialogModel ); + dialogControl.createPeer( createInstance( XToolkit.class, "com.sun.star.awt.Toolkit" ), null ); + + // insert a grid control model + final XMultiServiceFactory controlModelFactory = UnoRuntime.queryInterface( XMultiServiceFactory.class, + dialogModel ); + final XPropertySet gridModelProps = UnoRuntime.queryInterface( XPropertySet.class, + controlModelFactory.createInstance( "com.sun.star.awt.grid.UnoControlGridModel" ) ); + m_disposables.add( gridModelProps ); + gridModelProps.setPropertyValue( "PositionX", 6 ); + gridModelProps.setPropertyValue( "PositionY", 6 ); + gridModelProps.setPropertyValue( "Width", 188 ); + gridModelProps.setPropertyValue( "Height", 88 ); + final XNameContainer modelContainer = UnoRuntime.queryInterface( XNameContainer.class, dialogModel ); + modelContainer.insertByName( "grid", gridModelProps ); + + // check the respective control has been created + final XControlContainer controlContainer = UnoRuntime.queryInterface( XControlContainer.class, dialogControl ); + final XControl gridControl = controlContainer.getControl( "grid" ); + assertNotNull( "no grid control created in the dialog", gridControl ); + + return gridControl; + } + + + private int impl_assertInteger( final Object i_object ) + { + assertTrue( i_object instanceof Integer ); + return ((Integer)i_object).intValue(); + } + + + private void impl_assertColumnModelConsistency() throws IndexOutOfBoundsException + { + for ( int col = 0; col < m_columnModel.getColumnCount(); ++col ) + { + final XGridColumn column = m_columnModel.getColumn( col ); + assertNotNull( column ); + assertEquals( "column/model inconsistency: column " + col + " has a wrong index!", col, column.getIndex() ); + } + + final XGridColumn[] allColumns = m_columnModel.getColumns(); + assertEquals( "getColumns returns the wrong number of column objects", + m_columnModel.getColumnCount(), allColumns.length ); + for ( int col = 0; col < m_columnModel.getColumnCount(); ++col ) + { + assertTrue( "getColumns inconsistency", impl_areSameInterface( allColumns[col], m_columnModel.getColumn(col) ) ); + } + } + + + private void impl_assertEquality( final XGridDataModel i_reference, final XGridDataModel i_compare ) throws IndexOutOfBoundsException + { + assertNotNull( i_reference ); + assertNotNull( i_compare ); + + assertEquals( "data model comparison: wrong column counts", i_reference.getColumnCount(), i_compare.getColumnCount() ); + assertEquals( "data model comparison: wrong row counts", i_reference.getRowCount(), i_compare.getRowCount() ); + + for ( int row = 0; row < i_reference.getRowCount(); ++row ) + { + assertEquals( "data model comparison: wrong row heading content in row " + row, + i_reference.getRowHeading( row ) ); + for ( int col = 0; col < i_reference.getRowCount(); ++col ) + { + assertEquals( "data model comparison: wrong cell content in cell (" + col + ", " + row + ")", + i_reference.getCellData( col, row ) ); + assertEquals( "data model comparison: wrong tooltip content in cell (" + col + ", " + row + ")", + i_reference.getCellToolTip( col, row ) ); + } + } + } + + + private void impl_assertEquality( final XGridColumnModel i_reference, final XGridColumnModel i_compare ) throws IndexOutOfBoundsException + { + assertEquals( "column model comparison: wrong column counts", i_reference.getColumnCount(), i_compare.getColumnCount() ); + for ( int col = 0; col < i_reference.getColumnCount(); ++col ) + { + final XGridColumn referenceColumn = i_reference.getColumn( col ); + final XGridColumn compareColumn = i_compare.getColumn( col ); + impl_assertEquality( referenceColumn, compareColumn ); + } + } + + + private void impl_assertEquality( final XGridColumn i_reference, final XGridColumn i_compare ) + { + final Method[] methods = XGridColumn.class.getMethods(); + for ( int m=0; m T createInstance( Class i_interfaceClass, final String i_serviceIndentifer ) throws Exception + { + return UnoRuntime.queryInterface( i_interfaceClass, createInstance( i_serviceIndentifer ) ); + } + + + private Object createInstance( final String i_serviceName ) throws Exception + { + Object instance = m_context.getServiceManager().createInstanceWithContext( i_serviceName, m_context ); + assertNotNull( "could not create an instance of '" + i_serviceName + "'", instance ); + return instance; + } + + private static final class DisposeListener implements XEventListener + { + DisposeListener( final Object i_component ) + { + m_component = UnoRuntime.queryInterface( XComponent.class, i_component ); + assertNotNull( m_component ); + m_component.addEventListener( this ); + } + + public void disposing( EventObject i_event ) + { + assertTrue( UnoRuntime.areSame( i_event.Source, m_component ) ); + m_isDisposed = true; + } + + final boolean isDisposed() { return m_isDisposed; } + + private final XComponent m_component; + private boolean m_isDisposed; + } + + + private static final class ColumnModelListener implements XContainerListener + { + ColumnModelListener() + { + } + + public void elementInserted( ContainerEvent i_event ) + { + m_insertionEvents.add( i_event ); + } + + public void elementRemoved( ContainerEvent i_event ) + { + m_removalEvents.add( i_event ); + } + + public void elementReplaced( ContainerEvent i_event ) + { + m_replacementEvents.add( i_event ); + } + + public void disposing( EventObject eo ) + { + } + + private List< ContainerEvent > assertExclusiveInsertionEvents() + { + assertFalse( m_insertionEvents.isEmpty() ); + assertTrue( m_removalEvents.isEmpty() ); + assertTrue( m_replacementEvents.isEmpty() ); + return m_insertionEvents; + } + + private List< ContainerEvent > assertExclusiveRemovalEvents() + { + assertTrue( m_insertionEvents.isEmpty() ); + assertFalse( m_removalEvents.isEmpty() ); + assertTrue( m_replacementEvents.isEmpty() ); + return m_removalEvents; + } + + private void reset() + { + m_insertionEvents = new ArrayList< ContainerEvent >(); + m_removalEvents = new ArrayList< ContainerEvent >(); + m_replacementEvents = new ArrayList< ContainerEvent >(); + } + + private List< ContainerEvent > getInsertionEvents() { return m_insertionEvents; } + private List< ContainerEvent > getRemovalEvents() { return m_removalEvents; } + + private List< ContainerEvent > m_insertionEvents = new ArrayList< ContainerEvent >(); + private List< ContainerEvent > m_removalEvents = new ArrayList< ContainerEvent >(); + private List< ContainerEvent > m_replacementEvents = new ArrayList< ContainerEvent >(); + } + + + private static final OfficeConnection m_connection = new OfficeConnection(); + private static Random m_randomGenerator = new Random(); + private final XComponentContext m_context; + + private XPropertySet m_gridControlModel; + private XGridColumnModel m_columnModel; + private XSortableMutableGridDataModel m_dataModel; + private final List< Object > m_disposables = new ArrayList< Object >(); +} diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent.java new file mode 100644 index 000000000..3d4df2c5f --- /dev/null +++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent.java @@ -0,0 +1,463 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit.accessibility; + +import java.util.ArrayList; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleComponent; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.awt.Point; +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.Size; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; + +/** + * Testing com.sun.star.accessibility.XAccessibleComponent + * interface methods : + *
    + *
  • containsPoint()
  • + *
  • getAccessibleAtPoint()
  • + *
  • getBounds()
  • + *
  • getLocation()
  • + *
  • getLocationOnScreen()
  • + *
  • getSize()
  • + *
  • grabFocus()
  • + *

+ * + * @see com.sun.star.accessibility.XAccessibleComponent + */ +public class _XAccessibleComponent { + + private final XAccessibleComponent oObj; + + private Rectangle bounds = null ; + + /** + * Constructor + */ + public _XAccessibleComponent(XInterface object/*, LogWriter log*/) { + oObj = UnoRuntime.queryInterface( + XAccessibleComponent.class, object); + } + + /** + * First checks 4 inner bounds (upper, lower, left and right) + * of component bounding box to contain + * at least one point of the component. Second 4 outer bounds + * are checked to not contain any component points.

+ * + * Has OK status if inner bounds contain component points + * and outer bounds don't contain any component points.

+ * + * The following method tests are to be completed successfully before : + *

    + *
  • getBounds() : to have size of a component.
  • + *
+ */ + public boolean _containsPoint() { + + boolean result = true ; + + int curX = 0; + while (!oObj.containsPoint(new Point(curX, 0)) && curX < bounds.Width) { + curX++; + } + if (curX < bounds.Width) { + System.out.println("Upper bound of box contains point (" + + curX + ",0) - OK"); + } else { + System.out.println + ("Upper bound of box contains no component points - FAILED"); + result = false; + } + + curX = 0; + while (!oObj.containsPoint(new Point(curX, bounds.Height - 1)) + && curX < bounds.Width) { + + System.out.println("Contains returns false for ("+curX+","+bounds.Height+")"); + curX++; + } + if (curX < bounds.Width) { + System.out.println("Lower bound of box contains point (" + + curX + "," + (bounds.Height - 1) + ") - OK"); + } else { + System.out.println + ("Lower bound of box contains no component points - FAILED"); + result = false; + } + + int curY = 0; + while (!oObj.containsPoint(new Point(0, curY)) && curY < bounds.Height) { + curY++; + } + if (curY < bounds.Height) { + System.out.println("Left bound of box contains point (0," + + curY + ") - OK"); + } else { + System.out.println + ("Left bound of box contains no component points - FAILED"); + result = false; + } + + curY = 0; + while (!oObj.containsPoint(new Point(bounds.Width - 1, curY)) && curY < bounds.Height) { + curY++; + } + if (curY < bounds.Height) { + System.out.println("Right bound of box contains point (" + + (bounds.Width - 1) + "," + curY + ") - OK"); + } else { + System.out.println + ("Right bound of box contains no component points - FAILED"); + result = false; + } + + boolean locRes = true; + for (int x = -1; x <= bounds.Width; x++) { + locRes &= !oObj.containsPoint(new Point(x, -1)); + locRes &= !oObj.containsPoint(new Point(x, bounds.Height+bounds.Y)); + } + if (locRes) { + System.out.println("Outer upper and lower bounds contain no component " + + "points - OK"); + } else { + System.out.println("Outer upper and lower bounds CONTAIN some component " + + "points - FAILED"); + result = false; + } + + locRes = true; + for (int y = -1; y <= bounds.Height; y++) { + locRes &= !oObj.containsPoint(new Point(-1, y)); + locRes &= !oObj.containsPoint(new Point(bounds.X+bounds.Width, y)); + } + if (locRes) { + System.out.println("Outer left and right bounds contain no component " + + "points - OK"); + } else { + System.out.println("Outer left and right bounds CONTAIN some component " + + "points - FAILED"); + result = false; + } + + return result; + } + + /** + * Iterates through all children which implement + * XAccessibleComponent (if they exist) determines their + * boundaries and tries to get each child by getAccessibleAtPoint + * passing point which belongs to the child. + * Also the point is checked which doesn't belong to child boundary + * box.

+ * + * Has OK status if in the first cases the right children + * are returned, and in the second null or + * another child is returned. + */ + public boolean _getAccessibleAtPoint() { + + boolean result = true ; + XAccessibleComponent[] children = getChildrenComponents(); + + if (children.length > 0) { + for (int i = 0; i < children.length; i++) { + Rectangle chBnd = children[i].getBounds(); + if (chBnd.X == -1) + { + continue; + } + System.out.println("Checking child with bounds " + + "(" + chBnd.X + "," + chBnd.Y + "),(" + + chBnd.Width + "," + chBnd.Height + "): " + + util.AccessibilityTools.accessibleToString(children[i])); + + System.out.println("finding the point which lies on the component"); + int curX = 0; + int curY = 0; + while (!children[i].containsPoint(new Point(curX, curY)) + && curX < chBnd.Width) { + curX++; + curY++; + } + + if (curX==chBnd.Width) { + System.out.println("Couldn't find a point with contains"); + continue; + } + + // trying the point laying on child + XAccessible xAcc = oObj.getAccessibleAtPoint + (new Point(chBnd.X , chBnd.Y)); + if (xAcc == null) { + System.out.println("The child not found at point (" + + (chBnd.X ) + "," + chBnd.Y + ") - FAILED"); + result = false; + } else { + XAccessible xAccCh = UnoRuntime.queryInterface + (XAccessible.class, children[i]); + System.out.println("Child found at point (" + + (chBnd.X ) + "," + chBnd.Y + ") - OK"); + boolean res = util.AccessibilityTools.equals(xAccCh, xAcc); + if (!res) { + int expIndex = xAccCh.getAccessibleContext().getAccessibleIndexInParent(); + int gotIndex = xAcc.getAccessibleContext().getAccessibleIndexInParent(); + if (expIndex < gotIndex) { + System.out.println("The children found is not the same"); + System.out.println("The expected child " + + xAccCh.getAccessibleContext().getAccessibleName()); + System.out.println("is hidden behind the found Child "); + System.out.println(xAcc.getAccessibleContext().getAccessibleName()+" - OK"); + } else { + System.out.println("The children found is not the same - FAILED"); + System.out.println("Expected: " + +xAccCh.getAccessibleContext().getAccessibleName()); + System.out.println("Found: " + +xAcc.getAccessibleContext().getAccessibleName()); + result = false ; + } + } + } + + // trying the point NOT laying on child + xAcc = oObj.getAccessibleAtPoint + (new Point(chBnd.X - 1, chBnd.Y - 1)); + if (xAcc == null) { + System.out.println("No children found at point (" + + (chBnd.X - 1) + "," + (chBnd.Y - 1) + ") - OK"); + result &= true; + } else { + XAccessible xAccCh = UnoRuntime.queryInterface(XAccessible.class, children[i]); + boolean res = util.AccessibilityTools.equals(xAccCh, xAcc); + if (res) { + System.out.println("The same child found outside " + + "its bounds - FAILED"); + result = false ; + } + } + } + } else { + System.out.println("There are no children supporting " + + "XAccessibleComponent"); + } + + return result; + } + + /** + * Retrieves the component bounds and stores it.

+ * + * Has OK status if boundary position (x,y) is not negative + * and size (Width, Height) is greater than 0. + */ + public boolean _getBounds() { + boolean result = true ; + + bounds = oObj.getBounds() ; + result &= bounds != null + && bounds.X >=0 && bounds.Y >=0 + && bounds.Width >0 && bounds.Height >0; + + System.out.println("Bounds = " + (bounds != null + ? "(" + bounds.X + "," + bounds.Y + "),(" + + bounds.Width + "," + bounds.Height + ")" : "null")); + + return result; + } + + /** + * Gets the location.

+ * + * Has OK status if the location is the same as location + * of boundary obtained by getBounds() method. + * + * The following method tests are to be completed successfully before : + *

    + *
  • getBounds() : to have bounds
  • + *
+ */ + public boolean _getLocation() { + + boolean result = true ; + Point loc = oObj.getLocation() ; + + result &= loc.X == bounds.X && loc.Y == bounds.Y ; + + return result; + } + + /** + * Get the screen location of the component and its parent + * (if it exists and supports XAccessibleComponent).

+ * + * Has OK status if component screen location equals + * to screen location of its parent plus location of the component + * relative to the parent.

+ * + * The following method tests are to be completed successfully before : + *

    + *
  • getBounds() : to have location of the component + * relative to its parent
  • + *
+ */ + public boolean _getLocationOnScreen() { + + XAccessibleComponent parent = getParentComponent(); + + boolean result = true ; + Point loc = oObj.getLocationOnScreen(); + System.out.println("Location is (" + loc.X + "," + loc.Y + ")"); + + if (parent != null) { + Point parLoc = parent.getLocationOnScreen(); + System.out.println("Parent location is (" + + parLoc.X + "," + parLoc.Y + ")"); + + result &= parLoc.X + bounds.X == loc.X; + result &= parLoc.Y + bounds.Y == loc.Y; + } + + return result; + } + + /** + * Obtains the size of the component.

+ * + * Has OK status if the size is the same as in bounds.

+ * + * The following method tests are to be completed successfully before : + *

    + *
  • getBounds()
  • + *
+ */ + public boolean _getSize() { + + boolean result = true ; + Size size = oObj.getSize() ; + + result &= size.Width == bounds.Width; + result &= size.Height == bounds.Height; + + return result; + } + + /** + * Just calls the method.

+ * + * Has OK status if no runtime exceptions occurred. + */ + public boolean _grabFocus() { + + boolean result = true ; + oObj.grabFocus() ; + + return result ; + } + + /** + * Retrieves all children (not more than 50) of the current + * component which support XAccessibleComponent. + * + * @return The array of children. Empty array returned if + * such children were not found or some error occurred. + */ + private XAccessibleComponent[] getChildrenComponents() { + XAccessible xAcc = UnoRuntime.queryInterface(XAccessible.class, oObj) ; + if (xAcc == null) { + System.out.println("Component doesn't support XAccessible."); + return new XAccessibleComponent[0]; + } + XAccessibleContext xAccCon = xAcc.getAccessibleContext(); + int cnt = xAccCon.getAccessibleChildCount(); + + // for cases when too many children exist checking only first 50 + if (cnt > 50) + { + cnt = 50; + } + + ArrayList childComp = new ArrayList(); + for (int i = 0; i < cnt; i++) { + try { + XAccessible child = xAccCon.getAccessibleChild(i); + XAccessibleContext xAccConCh = child.getAccessibleContext(); + XAccessibleComponent xChAccComp = UnoRuntime.queryInterface(XAccessibleComponent.class, xAccConCh); + if (xChAccComp != null) { + childComp.add(xChAccComp) ; + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) {} + } + + return childComp.toArray(new XAccessibleComponent[childComp.size()]); + } + + /** + * Gets the parent of the current component which support + * XAccessibleComponent. + * + * @return The parent or null if the component + * has no parent or some errors occurred. + */ + private XAccessibleComponent getParentComponent() { + XAccessible xAcc = UnoRuntime.queryInterface(XAccessible.class, oObj) ; + if (xAcc == null) { + System.out.println("Component doesn't support XAccessible."); + return null; + } + + XAccessibleContext xAccCon = xAcc.getAccessibleContext(); + XAccessible xAccPar = xAccCon.getAccessibleParent(); + + if (xAccPar == null) { + System.out.println("Component has no accessible parent."); + return null; + } + XAccessibleContext xAccConPar = xAccPar.getAccessibleContext(); + XAccessibleComponent parent = UnoRuntime.queryInterface(XAccessibleComponent.class, xAccConPar); + if (parent == null) { + System.out.println + ("Accessible parent doesn't support XAccessibleComponent"); + return null; + } + + return parent; + } + + /** + * Just calls the method. + */ + public boolean _getForeground() { + int forColor = oObj.getForeground(); + System.out.println("getForeground(): " + forColor); + return true; + } + + /** + * Just calls the method. + */ + public boolean _getBackground() { + int backColor = oObj.getBackground(); + System.out.println("getBackground(): " + backColor); + return true; + } + +} diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext.java new file mode 100644 index 000000000..df7ef76ab --- /dev/null +++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext.java @@ -0,0 +1,246 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit.accessibility; + +import com.sun.star.lang.Locale; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.accessibility.IllegalAccessibleComponentStateException; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleRelationSet; +import com.sun.star.accessibility.XAccessibleStateSet; +import util.AccessibilityTools; + +/** + * Testing com.sun.star.accessibility.XAccessibleContext + * interface methods : + *

    + *
  • getAccessibleChildCount()
  • + *
  • getAccessibleChild()
  • + *
  • getAccessibleParent()
  • + *
  • getAccessibleIndexInParent()
  • + *
  • getAccessibleRole()
  • + *
  • getAccessibleDescription()
  • + *
  • getAccessibleName()
  • + *
  • getAccessibleRelationSet()
  • + *
  • getAccessibleStateSet()
  • + *
  • getLocale()
  • + *

+ * + * @see com.sun.star.accessibility.XAccessibleContext + */ +public class _XAccessibleContext { + + private final XAccessibleContext oObj; + + private int childCount = 0; + private XAccessible parent = null ; + + public _XAccessibleContext(XInterface object) { + oObj = UnoRuntime.queryInterface(XAccessibleContext.class, object); + } + + /** + * Calls the method and stores the number of children.

+ * Has OK status if non-negative number rutrned. + */ + public boolean _getAccessibleChildCount() { + childCount = oObj.getAccessibleChildCount(); + System.out.println(childCount + " children found."); + return childCount > -1; + } + + /** + * Tries to get every child and checks its parent.

+ * + * Has OK status if parent of every child + * and the tested component are the same objects. + * + * The following method tests are to be completed successfully before : + *

    + *
  • getAccessibleChildCount() : to have a number of + * children
  • + *
+ */ + public boolean _getAccessibleChild() { + boolean bOK = true; + int counter = childCount; + if (childCount > 500) + { + counter = 500; + } + for (int i = 0; i < counter; i++) { + try { + XAccessible ch = oObj.getAccessibleChild(i) ; + XAccessibleContext chAC = ch.getAccessibleContext(); + + System.out.println(" Child " + i + ": " + + chAC.getAccessibleDescription()) ; + + if (!AccessibilityTools.equals + (chAC.getAccessibleParent().getAccessibleContext(), oObj)){ + + System.out.println("Role:"); + System.out.println("Getting: "+chAC.getAccessibleParent().getAccessibleContext().getAccessibleRole()); + System.out.println("Expected: "+oObj.getAccessibleRole()); + + System.out.println("ImplementationName:"); + System.out.println("Getting: "+util.utils.getImplName(chAC.getAccessibleParent().getAccessibleContext())); + System.out.println("Expected: "+util.utils.getImplName(oObj)); + + System.out.println("The parent of child and component "+ + "itself differ."); + System.out.println("Getting(Description): " + +chAC.getAccessibleParent().getAccessibleContext().getAccessibleDescription()); + System.out.println("Expected(Description): " + +oObj.getAccessibleDescription()); + + bOK = false; + } else { + System.out.println("Getting the expected Child -- OK"); + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + e.printStackTrace(); + bOK = false; + } + } + + return bOK; + } + + /** + * Just gets the parent.

+ * + * Has OK status if parent is not null. + */ + public boolean _getAccessibleParent() { + // assume that the component is not ROOT + parent = oObj.getAccessibleParent(); + return parent != null; + } + + /** + * Retrieves the index of tested component in its parent. + * Then gets the parent's child by this index and compares + * it with tested component.

+ * + * Has OK status if the parent's child and the tested + * component are the same objects. + * + * The following method tests are to be completed successfully before : + *

    + *
  • getAccessibleParent() : to have a parent
  • + *
+ */ + public boolean _getAccessibleIndexInParent() { + + boolean bOK = true; + int idx = oObj.getAccessibleIndexInParent(); + + XAccessibleContext parentAC = parent.getAccessibleContext() ; + try { + bOK &= AccessibilityTools.equals( + parentAC.getAccessibleChild(idx).getAccessibleContext(),oObj); + if (!bOK) { + System.out.println("Expected: "+util.utils.getImplName(oObj)); + System.out.println("Getting: "+util.utils.getImplName( + parentAC.getAccessibleChild(idx).getAccessibleContext())); + } + } catch (com.sun.star.lang.IndexOutOfBoundsException e) { + e.printStackTrace(); + bOK = false; + } + return bOK; + } + + /** + * Get the accessible role of component.

+ * + * Has OK status if non-negative number rutrned. + */ + public boolean _getAccessibleRole() { + short role = oObj.getAccessibleRole(); + System.out.println("The role is " + role); + return role > -1; + } + + /** + * Get the accessible name of the component.

+ * + * Has OK status if the name has non-zero length. + */ + public boolean _getAccessibleName() { + String name = oObj.getAccessibleName(); + System.out.println("The name is '" + name + "'"); + return name != null; + } + + /** + * Get the accessible description of the component.

+ * + * Has OK status if the description has non-zero length. + */ + public boolean _getAccessibleDescription() { + String descr = oObj.getAccessibleDescription(); + System.out.println("The description is '" + descr + "'"); + return descr != null; + } + + /** + * Just gets the set.

+ * + * Has OK status if the set is not null. + */ + public boolean _getAccessibleRelationSet() { + XAccessibleRelationSet set = oObj.getAccessibleRelationSet(); + return set != null; + } + + /** + * Just gets the set.

+ * + * Has OK status if the set is not null. + */ + public boolean _getAccessibleStateSet() { + XAccessibleStateSet set = oObj.getAccessibleStateSet(); + return set != null; + } + + /** + * Gets the locale.

+ * + * Has OK status if Country and + * Language fields of locale structure + * are not empty. + */ + public boolean _getLocale() { + Locale loc = null ; + try { + loc = oObj.getLocale(); + System.out.println("The locale is " + loc.Language + "," + loc.Country); + } catch (IllegalAccessibleComponentStateException e) { + e.printStackTrace(); + } + + return loc != null && loc.Language.length() > 0 && + loc.Country.length() > 0; + } +} + diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster.java new file mode 100644 index 000000000..fe48a6cb8 --- /dev/null +++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster.java @@ -0,0 +1,177 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit.accessibility; + +import com.sun.star.accessibility.AccessibleEventObject; +import com.sun.star.accessibility.AccessibleStateType; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleEventBroadcaster; +import com.sun.star.accessibility.XAccessibleEventListener; +import com.sun.star.awt.PosSize; +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.XWindow; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; + +/** + * Testing + * com.sun.star.accessibility.XAccessibleEventBroadcaster + * interface methods : + *

    + *
  • addAccessibleEventListener()
  • + *
  • removeAccessibleEventListener()
  • + *
+ * + *

This test needs the following object relations :

+ *
    + *
  • 'EventProducer' (of type + * ifc.accessibility._XAccessibleEventBroadcaster.EventProducer): + * this must be an implementation of the interface which could perform + * some actions for generating any kind of AccessibleEvent
  • + *
+ * + * @see com.sun.star.accessibility.XAccessibleEventBroadcaster + */ +public class _XAccessibleEventBroadcaster { + + private final XAccessibleEventBroadcaster oObj; + private final EventProducer prod; + private final EvListener list = new EvListener(); + + /** + * An event producer + */ + private static class EventProducer { + private final XWindow xWindow; + private EventProducer(XWindow window) { + xWindow = window; + } + + private void fireEvent() { + Rectangle newPosSize = xWindow.getPosSize(); + newPosSize.Width = newPosSize.Width - 20; + newPosSize.Height = newPosSize.Height - 20; + newPosSize.X = newPosSize.X + 20; + newPosSize.Y = newPosSize.Y + 20; + xWindow.setPosSize(newPosSize.X, newPosSize.Y, newPosSize.Width, + newPosSize.Height, PosSize.POSSIZE); + } + } + + /** + * Listener implementation which registers listener calls. + */ + private class EvListener implements XAccessibleEventListener { + public AccessibleEventObject notifiedEvent = null ; + public void notifyEvent(AccessibleEventObject ev) { + System.out.println("Listener, Event : " + ev.EventId); + System.out.println("EventID: " + ev.EventId); + Object old=ev.OldValue; + if (old instanceof com.sun.star.accessibility.XAccessible) { + System.out.println("Old: "+((XAccessible)old).getAccessibleContext().getAccessibleName()); + } + + Object nev=ev.NewValue; + if (nev instanceof com.sun.star.accessibility.XAccessible) { + System.out.println("New: "+((XAccessible)nev).getAccessibleContext().getAccessibleName()); + } + notifiedEvent = ev; + } + + public void disposing(EventObject ev) {} + } + + public _XAccessibleEventBroadcaster(XInterface object, XWindow window) { + oObj = UnoRuntime.queryInterface(XAccessibleEventBroadcaster.class, object); + prod = new EventProducer(window); + } + + /** + * Adds two listeners and fires event by mean of object relation.

+ * Has OK status if both listeners were called + */ + public boolean _addEventListener(XMultiServiceFactory xMSF) { + System.out.println("adding two listeners"); + oObj.addAccessibleEventListener(list); + boolean isTransient = chkTransient(oObj); + System.out.println("fire event"); + prod.fireEvent() ; + + util.utils.waitForEventIdle(xMSF); + + boolean works = true; + + if (list.notifiedEvent == null) { + if (!isTransient) { + System.out.println("listener wasn't called"); + works = false; + } else { + System.out.println("Object is Transient, listener isn't expected to be called"); + } + oObj.removeAccessibleEventListener(list); + } + + return works; + } + + /** + * Removes one of two listeners added before and fires event + * by mean of object relation.

+ * + * Has OK status if the removed listener wasn't called.

+ * + * The following method tests are to be completed successfully before : + *

    + *
  • addEventListener() : to have added listeners
  • + *
+ */ + public boolean _removeEventListener(XMultiServiceFactory xMSF) { + + list.notifiedEvent = null; + + System.out.println("remove first listener"); + oObj.removeAccessibleEventListener(list); + + System.out.println("fire event"); + prod.fireEvent() ; + + util.utils.waitForEventIdle(xMSF); + + if (list.notifiedEvent == null) { + System.out.println("listener wasn't called -- OK"); + } + + return list.notifiedEvent == null; + + } + + private static boolean chkTransient(Object Testcase) { + XAccessibleContext accCon = UnoRuntime.queryInterface(XAccessibleContext.class, Testcase); + return accCon.getAccessibleStateSet().contains( + AccessibleStateType.TRANSIENT) + && accCon.getAccessibleParent().getAccessibleContext() + .getAccessibleStateSet().contains( + AccessibleStateType.MANAGES_DESCENDANTS); + } + +} + diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent.java new file mode 100644 index 000000000..64dd66fcb --- /dev/null +++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent.java @@ -0,0 +1,75 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit.accessibility; + +import com.sun.star.accessibility.XAccessibleExtendedComponent; +import com.sun.star.awt.XFont; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; + +/** + * Testing com.sun.star.accessibility.XAccessibleExtendedComponent + * interface methods : + *
    + *
  • getForeground()
  • + *
  • getBackground()
  • + *
  • getFont()
  • + *
  • isEnabled()
  • + *
  • getTitledBorderText()
  • + *
  • getToolTipText()
  • + *

+ * @see com.sun.star.accessibility.XAccessibleExtendedComponent + */ +public class _XAccessibleExtendedComponent { + + private final XAccessibleExtendedComponent oObj; + + public _XAccessibleExtendedComponent(XInterface object/*, LogWriter log*/) { + oObj = UnoRuntime.queryInterface(XAccessibleExtendedComponent.class, object); + } + + /** + * Just calls the method. + */ + public boolean _getFont() { + XFont font = oObj.getFont(); + System.out.println("getFont(): " + font); + return true; + } + + /** + * Calls the method and checks returned value. + * Has OK status if returned value isn't null. + */ + public boolean _getTitledBorderText() { + String titleBorderText = oObj.getTitledBorderText(); + System.out.println("getTitledBorderText(): '" + titleBorderText + "'"); + return titleBorderText != null; + } + + /** + * Calls the method and checks returned value. + * Has OK status if returned value isn't null. + */ + public boolean _getToolTipText() { + String toolTipText = oObj.getToolTipText(); + System.out.println("getToolTipText(): '" + toolTipText + "'"); + return toolTipText != null; + } +} diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleText.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleText.java new file mode 100644 index 000000000..1cd97d63a --- /dev/null +++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleText.java @@ -0,0 +1,1001 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit.accessibility; + +import com.sun.star.accessibility.XAccessibleText; +import com.sun.star.beans.PropertyValue; +import com.sun.star.awt.Rectangle; +import com.sun.star.awt.Point; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.accessibility.AccessibleTextType; +import com.sun.star.accessibility.TextSegment; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; + +/** + * Testing com.sun.star.accessibility.XAccessibleText + * interface methods : + *

    + *
  • getCaretPosition()
  • + *
  • setCaretPosition()
  • + *
  • getCharacter()
  • + *
  • getCharacterAttributes()
  • + *
  • getCharacterBounds()
  • + *
  • getCharacterCount()
  • + *
  • getIndexAtPoint()
  • + *
  • getSelectedText()
  • + *
  • getSelectionStart()
  • + *
  • getSelectionEnd()
  • + *
  • setSelection()
  • + *
  • getText()
  • + *
  • getTextRange()
  • + *
  • getTextAtIndex()
  • + *
  • getTextBeforeIndex()
  • + *
  • getTextBehindIndex()
  • + *
  • copyText()
  • + *
+ *

This test needs the following object relations :

+ *
    + *
  • 'XAccessibleText.Text' (of type String) + * optional : + * the string presentation of component's text. If the relation + * is not specified, then text from method getText() + * is used. + *
  • + *
+ * @see com.sun.star.accessibility.XAccessibleText + */ +public class _XAccessibleText { + + private final XAccessibleText oObj; + private final XMultiServiceFactory xMSF; + + private Rectangle chBounds = null; + private int chCount = 0; + + private String text = null; + private final String editOnly; + + + public _XAccessibleText(XInterface object, XMultiServiceFactory xMSF, String editOnly) { + this.oObj = UnoRuntime.queryInterface(XAccessibleText.class, object); + this.xMSF = xMSF; + this.editOnly = editOnly; + } + + + /** + * Calls the method and checks returned value. + * Has OK status if returned value is equal to chCount - 1. + * The following method tests are to be executed before: + *
    + *
  • setCaretPosition()
  • + *
+ */ + public boolean _getCaretPosition() { + + if (editOnly != null) { + System.out.println(editOnly); + return true; + } + + boolean res = true; + if ( chCount > 0 ) { + try { + oObj.setCaretPosition(chCount - 1); + } catch (com.sun.star.lang.IndexOutOfBoundsException ie) { + + } + int carPos = oObj.getCaretPosition(); + System.out.println("getCaretPosition: " + carPos); + res = carPos == (chCount - 1); + } + return res; + } + + /** + * Calls the method with the wrong index and with the correct index + * chCount - 1. + * Has OK status if exception was thrown for wrong index and + * if exception wasn't thrown for the correct index. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _setCaretPosition() { + boolean res = true; + + try { + System.out.println("setCaretPosition(-1):"); + oObj.setCaretPosition(-1); + res &= false; + System.out.println("exception was expected"); + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("expected exception"); + res &= true; + } + + try { + System.out.println("setCaretPosition(chCount+1):"); + oObj.setCaretPosition(chCount+1); + res &= false; + System.out.println("exception was expected"); + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("expected exception"); + res &= true; + } + if ( chCount > 0 ) { + try { + System.out.println("setCaretPosition(chCount - 1)"); + oObj.setCaretPosition(chCount - 1); + res &= true; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("unexpected exception"); + e.printStackTrace(); + res &= false; + } + } + + return res; + } + + /** + * Calls the method with the wrong index and with the correct indexes. + * Checks every character in the text. + * Has OK status if exception was thrown for wrong index, + * if exception wasn't thrown for the correct index and + * if every character is equal to corresponding character in the text. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _getCharacter() { + boolean res = true; + + try { + System.out.println("getCharacter(-1)"); + oObj.getCharacter(-1); + System.out.println("Exception was expected"); + res = false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res = true; + } + + try { + System.out.println("getCharacter(chCount)"); + oObj.getCharacter(chCount); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + System.out.println("Checking of every character in the text..."); + boolean isEqCh = true; + for(int i = 0; i < chCount; i++) { + char ch = oObj.getCharacter(i); + isEqCh = ch == text.charAt(i); + res &= isEqCh; + if (!isEqCh) { + System.out.println("At the position " + i + + "was expected character: " + text.charAt(i)); + System.out.println("but was returned: " + ch); + break; + } + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } + + return res; + } + + /** + * Calls the method with the wrong indexes and with the correct index, + * checks a returned value. + * Has OK status if exception was thrown for the wrong indexes, + * if exception wasn't thrown for the correct index and + * if returned value isn't null. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _getCharacterAttributes() { + boolean res = true; + + try { + System.out.println("getCharacterAttributes(-1)"); + oObj.getCharacterAttributes(-1, new String[0]); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } catch(UnknownPropertyException e) { + System.out.println("unexpected exception => FAILED"); + res &= false; + } + + try { + System.out.println("getCharacterAttributes(chCount)"); + oObj.getCharacterAttributes(chCount, new String[0]); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } catch(UnknownPropertyException e) { + System.out.println("unexpected exception => FAILED"); + res &= false; + } + + try { + if ( chCount > 0 ) { + System.out.println("getCharacterAttributes(chCount-1)"); + PropertyValue[] props = oObj.getCharacterAttributes(chCount - 1, new String[0]); + res &= props != null; + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } catch(UnknownPropertyException e) { + System.out.println("unexpected exception => FAILED"); + res &= false; + } + + return res; + } + + + /** + * Calls the method with the wrong indexes and with the correct index. + * checks and stores a returned value. + * Has OK status if exception was thrown for the wrong indexes, + * if exception wasn't thrown for the correct index and + * if returned value isn't null. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _getCharacterBounds() { + boolean res = true; + + try { + System.out.println("getCharacterBounds(-1)"); + oObj.getCharacterBounds(-1); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + System.out.println("getCharacterBounds(chCount)"); + oObj.getCharacterBounds(chCount); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + if (chCount > 0) { + System.out.println("getCharacterBounds(chCount-1)"); + chBounds = oObj.getCharacterBounds(chCount-1); + res &= chBounds != null; + System.out.println("rect: " + chBounds.X + ", " + chBounds.Y + ", " + + chBounds.Width + ", " + chBounds.Height); + } + + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } + + return res; + } + + + /** + * Calls the method and stores a returned value to the variable + * chCount. + * Has OK status if a returned value is equal to the text length. + */ + public boolean _getCharacterCount() { + chCount = oObj.getCharacterCount(); + System.out.println("Character count:" + chCount); + boolean res = chCount == text.length(); + return res; + } + + /** + * Calls the method for an invalid point and for the point of rectangle + * returned by the method getCharacterBounds(). + * Has OK status if returned value is equal to -1 for an + * invalid point and if returned value is equal to chCount-1 + * for a valid point. + * The following method tests are to be executed before: + *
    + *
  • getCharacterBounds()
  • + *
+ */ + public boolean _getIndexAtPoint() { + + boolean res = true; + System.out.println("getIndexAtPoint(-1, -1):"); + Point pt = new Point(-1, -1); + int index = oObj.getIndexAtPoint(pt); + System.out.println(Integer.toString(index)); + res &= index == -1; + + if (chBounds != null) { + pt = new Point(chBounds.X , chBounds.Y ); + System.out.println("getIndexAtPoint(" + pt.X + ", " + pt.Y + "):"); + index = oObj.getIndexAtPoint(pt); + System.out.println(Integer.toString(index)); + res &= index == (chCount - 1); + } + + return res; + } + + /** + * Checks a returned values after different calls of the method + * setSelection(). + * The following method tests are to be executed before: + *
    + *
  • setSelection()
  • + *
+ */ + public boolean _getSelectedText() { + if (editOnly != null) { + System.out.println(editOnly); + return true; + } + + boolean res = true; + + try { + System.out.println("setSelection(0, 0)"); + oObj.setSelection(0, 0); + System.out.println("getSelectedText():"); + String txt = oObj.getSelectedText(); + System.out.println("'" + txt + "'"); + res &= txt.length() == 0; + + System.out.println("setSelection(0, chCount)"); + oObj.setSelection(0, chCount); + System.out.println("getSelectedText():"); + txt = oObj.getSelectedText(); + System.out.println("'" + txt + "'"); + res &= txt.equals(text); + + if (chCount > 2) { + System.out.println("setSelection(1, chCount-1)"); + oObj.setSelection(1, chCount - 1); + System.out.println("getSelectedText():"); + txt = oObj.getSelectedText(); + System.out.println("'" + txt + "'"); + res &= txt.equals(text.substring(1, chCount - 1)); + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } + + return res; + } + + /** + * Checks a returned values after different calls of the method + * setSelection(). + * The following method tests are to be executed before: + *
    + *
  • setSelection()
  • + *
+ */ + public boolean _getSelectionStart() { + if (editOnly != null) { + System.out.println(editOnly); + return true; + } + + boolean res = true; + + try { + System.out.println("setSelection(0, chCount)"); + oObj.setSelection(0, chCount); + int start = oObj.getSelectionStart(); + System.out.println("getSelectionStart():" + start); + res &= start == 0; + + if (chCount > 2) { + System.out.println("setSelection(1, chCount-1)"); + oObj.setSelection(1, chCount - 1); + start = oObj.getSelectionStart(); + System.out.println("getSelectionStart():" + start); + res &= start == 1; + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } + + return res; + } + + /** + * Checks a returned values after different calls of the method + * setSelection(). + * The following method tests are to be executed before: + *
    + *
  • setSelection()
  • + *
+ */ + public boolean _getSelectionEnd() { + if (editOnly != null) { + System.out.println(editOnly); + return true; + } + + boolean res = true; + + try { + System.out.println("setSelection(0, chCount)"); + oObj.setSelection(0, chCount); + int end = oObj.getSelectionEnd(); + System.out.println("getSelectionEnd():" + end); + res &= end == chCount; + + if (chCount > 2) { + System.out.println("setSelection(1, chCount-1)"); + oObj.setSelection(1, chCount - 1); + end = oObj.getSelectionEnd(); + System.out.println("getSelectionEnd():" + end); + res &= end == chCount - 1; + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } + + return res; + } + + /** + * Calls the method with invalid parameters and with valid parameters. + * Has OK status if exception was thrown for invalid parameters, + * if exception wasn't thrown for valid parameters. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _setSelection() { + boolean res = true; + boolean locRes = true; + + if (editOnly != null) { + System.out.println(editOnly); + return true; + } + + try { + System.out.println("setSelection(-1, chCount-1):"); + locRes = oObj.setSelection(-1, chCount - 1); + System.out.println(locRes + " exception was expected"); + res &= !locRes; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + System.out.println("setSelection(0, chCount+1):"); + locRes = oObj.setSelection(0, chCount + 1); + System.out.println(locRes + " exception was expected"); + res &= !locRes; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + if (chCount > 2) { + System.out.println("setSelection(1, chCount-1):"); + locRes = oObj.setSelection(1, chCount - 1); + System.out.println(Boolean.toString(locRes)); + res &= locRes; + + System.out.println("setSelection(chCount-1, 1):"); + locRes = oObj.setSelection(chCount - 1, 1); + System.out.println(Boolean.toString(locRes)); + res &= locRes; + } + + if (chCount > 1) { + System.out.println("setSelection(0, chCount-1):"); + locRes = oObj.setSelection(0, chCount-1); + System.out.println(Boolean.toString(locRes)); + res &= locRes; + + System.out.println("setSelection(chCount-1, 0):"); + locRes = oObj.setSelection(chCount-1, 0); + System.out.println(Boolean.toString(locRes)); + res &= locRes; + } + + System.out.println("setSelection(0, 0):"); + locRes = oObj.setSelection(0, 0); + System.out.println(Boolean.toString(locRes)); + res &= locRes; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } + + return res; + } + + /** + * Calls the method and checks returned value. + * Has OK status if returned string is not null + * received from relation. + */ + public boolean _getText() { + text = oObj.getText(); + System.out.println("getText: '" + text + "'"); + return (text != null); + } + + /** + * Calls the method with invalid parameters and with valid parameters, + * checks returned values. + * Has OK status if exception was thrown for invalid parameters, + * if exception wasn't thrown for valid parameters and if returned values + * are equal to corresponding substrings of the text received by relation. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _getTextRange() { + boolean res = true; + boolean locRes = true; + + try { + if (chCount > 3) { + System.out.println("getTextRange(1, chCount - 2): "); + String txtRange = oObj.getTextRange(1, chCount - 2); + System.out.println(txtRange); + locRes = txtRange.equals(text.substring(1, chCount - 2)); + res &= locRes; + if (!locRes) { + System.out.println("Was expected: " + + text.substring(1, chCount - 2)); + } + } + + if (chCount > 0) { + System.out.println("getTextRange(0, chCount-1): "); + String txtRange = oObj.getTextRange(0, chCount-1); + System.out.println(txtRange); + locRes = txtRange.equals(text.substring(0, chCount - 1)); + res &= locRes; + if (!locRes) { + System.out.println("Was expected: " + + text.substring(0, chCount - 1)); + } + + System.out.println("getTextRange(chCount, 0): "); + txtRange = oObj.getTextRange(chCount, 0); + System.out.println(txtRange); + res &= txtRange.equals(text); + + System.out.println("getTextRange(0, 0): "); + txtRange = oObj.getTextRange(0, 0); + System.out.println(txtRange); + locRes = txtRange.length() == 0; + res &= locRes; + if (!locRes) { + System.out.println("Empty string was expected"); + } + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } + + try { + System.out.println("getTextRange(-1, chCount - 1): "); + oObj.getTextRange(-1, chCount - 1); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + System.out.println("getTextRange(0, chCount + 1): "); + oObj.getTextRange(0, chCount + 1); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + System.out.println("getTextRange(chCount+1, -1): "); + oObj.getTextRange(chCount+1, -1); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + return res; + } + + /** + * Calls the method with invalid parameters and with valid parameters, + * checks returned values. + * Has OK status if exception was thrown for invalid parameters, + * if exception wasn't thrown for valid parameters and if returned values + * are equal to corresponding substrings of the text received by relation. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _getTextAtIndex() { + boolean res = true; + + try { + System.out.println("getTextAtIndex(-1, AccessibleTextType.PARAGRAPH):"); + oObj.getTextAtIndex(-1, AccessibleTextType.PARAGRAPH); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + System.out.println("getTextAtIndex(chCount+1," + + " AccessibleTextType.PARAGRAPH):"); + oObj.getTextAtIndex(chCount + 1, AccessibleTextType.PARAGRAPH); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Expected exception"); + res &= true; + } + + + try { + if ( chCount > 0 ) { + System.out.println("getTextAtIndex(chCount," + + " AccessibleTextType.PARAGRAPH):"); + TextSegment txt = oObj.getTextAtIndex(chCount, + AccessibleTextType.PARAGRAPH); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.length() == 0; + + System.out.println("getTextAtIndex(1," + + " AccessibleTextType.PARAGRAPH):"); + txt = oObj.getTextAtIndex(1, + AccessibleTextType.PARAGRAPH); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.equals(text); + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Unexpected exception"); + res &= false; + } + + + return res; + } + + /** + * Calls the method with invalid parameters and with valid parameters, + * checks returned values. + * Has OK status if exception was thrown for invalid parameters, + * if exception wasn't thrown for valid parameters and if returned values + * are equal to corresponding substrings of the text received by relation. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _getTextBeforeIndex() { + boolean res = true; + + try { + System.out.println("getTextBeforeIndex(-1, AccessibleTextType.PARAGRAPH):"); + oObj.getTextBeforeIndex(-1, AccessibleTextType.PARAGRAPH); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Expected exception"); + res &= true; + } + + + try { + System.out.println("getTextBeforeIndex(chCount+1, " + + "AccessibleTextType.PARAGRAPH):"); + oObj.getTextBeforeIndex(chCount + 1, AccessibleTextType.PARAGRAPH); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Expected exception"); + res &= true; + } + + TextSegment txt = null; + try { + if (chCount > 0) { + System.out.println("getTextBeforeIndex(chCount," + + " AccessibleTextType.PARAGRAPH):"); + txt = oObj.getTextBeforeIndex(chCount, + AccessibleTextType.PARAGRAPH); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.length() == chCount ; + + System.out.println("getTextBeforeIndex(1," + + " AccessibleTextType.PARAGRAPH):"); + txt = oObj.getTextBeforeIndex(1, + AccessibleTextType.PARAGRAPH); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.length() == 0; + } + + if (chCount > 2) { + System.out.println("getTextBeforeIndex(chCount-1," + + " AccessibleTextType.CHARACTER):"); + txt = oObj.getTextBeforeIndex(chCount - 1, + AccessibleTextType.CHARACTER); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.equals(text.substring(chCount - 2, chCount - 1)); + System.out.println("getTextBeforeIndex(2," + + " AccessibleTextType.CHARACTER):"); + txt = oObj.getTextBeforeIndex(2, + AccessibleTextType.CHARACTER); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.equals(text.substring(1, 2)); + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Unexpected exception"); + res &= false; + } + + + return res; + } + + /** + * Calls the method with invalid parameters and with valid parameters, + * checks returned values. + * Has OK status if exception was thrown for invalid parameters, + * if exception wasn't thrown for valid parameters and if returned values + * are equal to corresponding substrings of the text received by relation. + * The following method tests are to be executed before: + *
    + *
  • getCharacterCount()
  • + *
+ */ + public boolean _getTextBehindIndex() { + boolean res = true; + + try { + System.out.println("getTextBehindIndex(-1, AccessibleTextType.PARAGRAPH):"); + oObj.getTextBehindIndex(-1, AccessibleTextType.PARAGRAPH); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Expected exception"); + res &= true; + } + + + try { + System.out.println("getTextBehindIndex(chCount+1, " + + "AccessibleTextType.PARAGRAPH):"); + oObj.getTextBehindIndex(chCount + 1, AccessibleTextType.PARAGRAPH); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Expected exception"); + res &= true; + } + + + try { + if ( chCount > 0 ) { + System.out.println("getTextBehindIndex(chCount," + + " AccessibleTextType.PARAGRAPH):"); + TextSegment txt = oObj.getTextBehindIndex(chCount, + AccessibleTextType.PARAGRAPH); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.length() == 0; + + System.out.println("getTextBehindIndex(chCount-1," + + " AccessibleTextType.PARAGRAPH):"); + txt = oObj.getTextBehindIndex(chCount - 1, + AccessibleTextType.PARAGRAPH); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.length() == 0; + } + if ( chCount > 1 ) { + System.out.println("getTextBehindIndex(1," + + " AccessibleTextType.CHARACTER):"); + TextSegment txt = oObj.getTextBehindIndex(1, + AccessibleTextType.CHARACTER); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.equals(text.substring(2, 3)); + } + if (chCount > 2) { + System.out.println("getTextBehindIndex(chCount-2," + + " AccessibleTextType.CHARACTER):"); + TextSegment txt = oObj.getTextBehindIndex(chCount - 2, + AccessibleTextType.CHARACTER); + System.out.println("'" + txt.SegmentText + "'"); + res &= txt.SegmentText.equals(text.substring(chCount - 1, chCount)); + } + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } catch(com.sun.star.lang.IllegalArgumentException e) { + System.out.println("Unexpected exception"); + res &= false; + } + + + return res; + } + + /** + * Calls the method with invalid parameters and with valid parameter, + * checks returned values. + * Has OK status if exception was thrown for invalid parameters, + * if exception wasn't thrown for valid parameter and if returned value for + * valid parameter is equal to true. + */ + public boolean _copyText() { + boolean res = true; + boolean locRes = true; + + if (editOnly != null) { + System.out.println(editOnly); + return true; + } + + try { + System.out.println("copyText(-1,chCount):"); + oObj.copyText(-1, chCount); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + System.out.println("copyText(0,chCount+1):"); + oObj.copyText(0, chCount + 1); + System.out.println("Exception was expected"); + res &= false; + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Expected exception"); + res &= true; + } + + try { + System.out.println("copyText(0,chCount):"); + locRes = oObj.copyText(0, chCount); + System.out.println(locRes); + res &= locRes; + + String cbText = null; + try { + cbText = + util.SysUtils.getSysClipboardText(xMSF); + } catch (com.sun.star.uno.Exception e) { + System.out.println("Couldn't access system clipboard :"); + e.printStackTrace(); + } + System.out.println("Clipboard: '" + cbText + "'"); + res &= text.equals(cbText); + + if (chCount > 2) { + System.out.println("copyText(1,chCount-1):"); + locRes = oObj.copyText(1, chCount - 1); + System.out.println(locRes); + res &= locRes; + + try { + cbText = util.SysUtils.getSysClipboardText(xMSF); + } catch (com.sun.star.uno.Exception e) { + System.out.println("Couldn't access system clipboard :"); + e.printStackTrace(); + } + + System.out.println("Clipboard: '" + cbText + "'"); + res &= text.substring(1, chCount - 1).equals(cbText); + } + + } catch(com.sun.star.lang.IndexOutOfBoundsException e) { + System.out.println("Unexpected exception"); + e.printStackTrace(); + res &= false; + } + + return res; + } +} diff --git a/toolkit/qa/complex/toolkit/awtgrid/DummyColumn.java b/toolkit/qa/complex/toolkit/awtgrid/DummyColumn.java new file mode 100644 index 000000000..d86df3f1c --- /dev/null +++ b/toolkit/qa/complex/toolkit/awtgrid/DummyColumn.java @@ -0,0 +1,167 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit.awtgrid; + +import com.sun.star.awt.grid.XGridColumn; +import com.sun.star.awt.grid.XGridColumnListener; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.XEventListener; +import com.sun.star.style.HorizontalAlignment; +import com.sun.star.util.XCloneable; + +/** + * a dummy implementation of css.awt.grid.XGridColumn + */ +public class DummyColumn implements XGridColumn +{ + public Object getIdentifier() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setIdentifier( Object o ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public int getColumnWidth() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setColumnWidth( int i ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public int getMinWidth() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setMinWidth( int i ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public int getMaxWidth() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setMaxWidth( int i ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public boolean getResizeable() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setResizeable( boolean bln ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public int getFlexibility() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setFlexibility( int i ) throws IllegalArgumentException + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public HorizontalAlignment getHorizontalAlign() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setHorizontalAlign( HorizontalAlignment ha ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public String getTitle() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setTitle( String string ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public String getHelpText() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setHelpText( String string ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public int getIndex() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public int getDataColumnIndex() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setDataColumnIndex( int i ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void addGridColumnListener( XGridColumnListener xl ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void removeGridColumnListener( XGridColumnListener xl ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void dispose() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void addEventListener( XEventListener xl ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void removeEventListener( XEventListener xl ) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public XCloneable createClone() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } +} diff --git a/toolkit/qa/complex/toolkit/awtgrid/GridDataListener.java b/toolkit/qa/complex/toolkit/awtgrid/GridDataListener.java new file mode 100644 index 000000000..800727bb3 --- /dev/null +++ b/toolkit/qa/complex/toolkit/awtgrid/GridDataListener.java @@ -0,0 +1,107 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit.awtgrid; + +import com.sun.star.awt.grid.GridDataEvent; +import com.sun.star.awt.grid.XGridDataListener; +import com.sun.star.lang.EventObject; +import static org.junit.Assert.*; + +final public class GridDataListener implements XGridDataListener +{ + public void rowsInserted( GridDataEvent i_event ) + { + assertNull( m_rowInsertionEvent ); + m_rowInsertionEvent = i_event; + } + + public void rowsRemoved( GridDataEvent i_event ) + { + assertNull( m_rowRemovalEvent ); + m_rowRemovalEvent = i_event; + } + + public void dataChanged( GridDataEvent i_event ) + { + assertNull( m_dataChangeEvent ); + m_dataChangeEvent = i_event; + } + + public void rowHeadingChanged( GridDataEvent i_event ) + { + assertNull( m_rowHeadingChangeEvent ); + m_rowHeadingChangeEvent = i_event; + } + + public void disposing( EventObject eo ) + { + m_disposed = true; + } + + public final GridDataEvent assertSingleRowInsertionEvent() + { + assertNotNull( m_rowInsertionEvent ); + assertNull( m_rowRemovalEvent ); + assertNull( m_dataChangeEvent ); + assertNull( m_rowHeadingChangeEvent ); + assertFalse( m_disposed ); + return m_rowInsertionEvent; + } + + public final GridDataEvent assertSingleRowRemovalEvent() + { + assertNull( m_rowInsertionEvent ); + assertNotNull( m_rowRemovalEvent ); + assertNull( m_dataChangeEvent ); + assertNull( m_rowHeadingChangeEvent ); + assertFalse( m_disposed ); + return m_rowRemovalEvent; + } + + public final GridDataEvent assertSingleDataChangeEvent() + { + assertNull( m_rowInsertionEvent ); + assertNull( m_rowRemovalEvent ); + assertNotNull( m_dataChangeEvent ); + assertNull( m_rowHeadingChangeEvent ); + assertFalse( m_disposed ); + return m_dataChangeEvent; + } + + public final GridDataEvent assertSingleRowHeadingChangeEvent() + { + assertNull( m_rowInsertionEvent ); + assertNull( m_rowRemovalEvent ); + assertNull( m_dataChangeEvent ); + assertNotNull( m_rowHeadingChangeEvent ); + assertFalse( m_disposed ); + return m_rowHeadingChangeEvent; + } + + public final void reset() + { + m_rowInsertionEvent = m_rowRemovalEvent = m_dataChangeEvent = m_rowHeadingChangeEvent = null; + // m_disposed is not reset intentionally + } + private GridDataEvent m_rowInsertionEvent = null; + private GridDataEvent m_rowRemovalEvent = null; + private GridDataEvent m_dataChangeEvent = null; + private GridDataEvent m_rowHeadingChangeEvent = null; + private boolean m_disposed = false; +} diff --git a/toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel.java b/toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel.java new file mode 100644 index 000000000..1623af8b6 --- /dev/null +++ b/toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel.java @@ -0,0 +1,449 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package complex.toolkit.awtgrid; + +import com.sun.star.awt.grid.GridDataEvent; +import com.sun.star.awt.grid.XMutableGridDataModel; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.IndexOutOfBoundsException; +import static org.junit.Assert.*; +import static complex.toolkit.Assert.*; + +/** test for the css.awt.grid.XMutableGridData interface + * + */ +public class TMutableGridDataModel +{ + public TMutableGridDataModel( final XMutableGridDataModel i_dataModel ) + { + m_dataModel = i_dataModel; + + m_listener = new GridDataListener(); + m_dataModel.addGridDataListener( m_listener ); + } + + /* + * tests the XMutableGridDataModel.addRow method + */ + public void testAddRow() throws IndexOutOfBoundsException + { + m_dataModel.addRow( m_rowHeadings[0], m_rowValues[0] ); + GridDataEvent event = m_listener.assertSingleRowInsertionEvent(); + m_listener.reset(); + assertEquals( "row insertion: wrong FirstRow (1)", 0, event.FirstRow ); + assertEquals( "row insertion: wrong LastRow (1)", 0, event.LastRow ); + impl_assertRowData( 0 ); + + m_dataModel.addRow( m_rowHeadings[1], m_rowValues[1] ); + event = m_listener.assertSingleRowInsertionEvent(); + m_listener.reset(); + assertEquals( "row insertion: wrong FirstRow (2)", 1, event.FirstRow ); + assertEquals( "row insertion: wrong LastRow (2)", 1, event.LastRow ); + impl_assertRowData( 1 ); + } + + /** + * tests the XMutableGridDataModel.addRows method + */ + public void testAddRows() throws IndexOutOfBoundsException, IllegalArgumentException + { + assertEquals( "precondition not met: call this directly after testAddRow, please!", 2, m_dataModel.getRowCount() ); + + m_dataModel.addRows( + new Object[] { m_rowHeadings[2], m_rowHeadings[3], m_rowHeadings[4] }, + new Object[][] { m_rowValues[2], m_rowValues[3], m_rowValues[4] } ); + GridDataEvent event = m_listener.assertSingleRowInsertionEvent(); + assertEquals( "row insertion: wrong FirstRow (1)", 2, event.FirstRow ); + assertEquals( "row insertion: wrong LastRow (1)", 4, event.LastRow ); + m_listener.reset(); + + assertEquals( "data model's row count is not adjusted when adding rows", m_rowValues.length, m_dataModel.getRowCount() ); + assertEquals( "data model's column count is not adjusted when adding rows", m_rowValues[0].length, m_dataModel.getColumnCount() ); + for ( int row=0; row rowCount is expected to throw", + m_dataModel, "insertRow", + new Class[] { Integer.class, Object.class, Object[].class }, + new Object[] { expectedRowCount + 1, "", new Object[] { "1", 2, 3 } }, + IndexOutOfBoundsException.class ); + assertException( "inserting a row at a position < 0 is expected to throw", + m_dataModel, "insertRow", + new Class[] { Integer.class, Object.class, Object[].class }, + new Object[] { -1, "", new Object[] { "1", 2, 3 } }, + IndexOutOfBoundsException.class ); + + // remove the row, to create the situation expected by the next test + m_dataModel.removeRow( insertionPos ); + m_listener.reset(); + } + + /** + * tests the XMutableGridDataModel.insertRows method + */ + public void testInsertRows() throws IndexOutOfBoundsException, IllegalArgumentException + { + int expectedRowCount = m_rowValues.length; + assertEquals( "precondition not met: call this directly after testInsertRow, please!", expectedRowCount, m_dataModel.getRowCount() ); + + // inserting some rows somewhere between the other rows + final int insertionPos = 3; + final Object[] rowHeadings = new Object[] { "A", "B", "C" }; + final Object[][] rowData = new Object[][] { + new Object[] { "A", "B", "C", "D", "E" }, + new Object[] { "J", "I", "H", "G", "F" }, + new Object[] { "K", "L", "M", "N", "O" } + }; + final int insertedRowCount = rowData.length; + assertEquals( "invalid test data", rowHeadings.length, insertedRowCount ); + + m_dataModel.insertRows( insertionPos, rowHeadings, rowData ); + expectedRowCount += insertedRowCount; + + final GridDataEvent event = m_listener.assertSingleRowInsertionEvent(); + assertEquals( "inserting multiple rows results in wrong FirstRow being notified", + insertionPos, event.FirstRow ); + assertEquals( "inserting multiple rows results in wrong LastRow being notified", + insertionPos + insertedRowCount - 1, event.LastRow ); + m_listener.reset(); + + for ( int row=0; row= insertionPos ) && ( row < insertionPos + insertedRowCount ) + ? rowData[ row - insertionPos ] + : m_rowValues[ row - insertedRowCount ]; + assertArrayEquals( "row number " + row + " has wrong content after inserting multiple rows", + expectedRowData, actualRowData ); + + final Object actualHeading = m_dataModel.getRowHeading(row); + final Object expectedHeading = + ( row < insertionPos ) + ? m_rowHeadings[ row ] + : ( row >= insertionPos ) && ( row < insertionPos + insertedRowCount ) + ? rowHeadings[ row - insertionPos ] + : m_rowHeadings[ row - insertedRowCount ]; + assertEquals( "row " + row + " has a wrong heading after invoking insertRows", + expectedHeading, actualHeading ); + } + + // exceptions + assertException( "inserting multiple rows at a position > rowCount is expected to throw an IndexOutOfBoundsException", + m_dataModel, "insertRows", + new Class[] { Integer.class, Object[].class, Object[][].class }, + new Object[] { expectedRowCount + 1, new Object[0], new Object[][] { } }, + IndexOutOfBoundsException.class ); + assertException( "inserting multiple rows at a position < 0 is expected to throw an IndexOutOfBoundsException", + m_dataModel, "insertRows", + new Class[] { Integer.class, Object[].class, Object[][].class }, + new Object[] { -1, new Object[0], new Object[][] { } }, + IndexOutOfBoundsException.class ); + assertException( "inserting multiple rows with inconsistent array lengths is expected to throw an IllegalArgumentException", + m_dataModel, "insertRows", + new Class[] { Integer.class, Object[].class, Object[][].class }, + new Object[] { 0, new Object[0], new Object[][] { new Object[0] } }, + IllegalArgumentException.class ); + + // remove the row, to create the situation expected by the next test + for ( int i=0; i