diff options
Diffstat (limited to 'forms/qa')
43 files changed, 7267 insertions, 0 deletions
diff --git a/forms/qa/complex/forms/CheckOGroupBoxModel.java b/forms/qa/complex/forms/CheckOGroupBoxModel.java new file mode 100755 index 000000000000..26005585827e --- /dev/null +++ b/forms/qa/complex/forms/CheckOGroupBoxModel.java @@ -0,0 +1,150 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: CheckOGroupBoxModel.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package complex.forms; + +import com.sun.star.beans.Property; +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.PropertyChangeEvent; +import com.sun.star.beans.XMultiPropertySet; +import com.sun.star.beans.XPropertiesChangeListener; +import com.sun.star.lang.EventObject; +import com.sun.star.drawing.XControlShape; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import complexlib.ComplexTestCase; +import java.io.PrintWriter; +import java.util.Vector; +import util.FormTools; +import util.SOfficeFactory; +import util.ValueChanger; + +/** + */ +public class CheckOGroupBoxModel extends ComplexTestCase { + + private XMultiPropertySet xPropSet = null; + + public String[] getTestMethodNames() { + return new String[] {"setPropertyValues"}; + } + + public void before() { + XComponent xDrawDoc = null; + SOfficeFactory SOF = SOfficeFactory.getFactory(((XMultiServiceFactory) param.getMSF())); + + try { + log.println("creating a draw document"); + xDrawDoc = SOF.createDrawDoc(null); + } catch (com.sun.star.uno.Exception e) { + e.printStackTrace((PrintWriter)log); + failed("Couldn't create document."); + } + + String objName = "GroupBox"; + XControlShape shape = FormTools.insertControlShape(xDrawDoc, 5000, 7000, 2000, 2000, objName); + xPropSet = (XMultiPropertySet)UnoRuntime.queryInterface(XMultiPropertySet.class, shape.getControl()); + } + + + public void setPropertyValues() { + String[] boundPropsToTest = getBoundPropsToTest(); + + MyChangeListener ml = new MyChangeListener(); + xPropSet.addPropertiesChangeListener(boundPropsToTest, ml); + + Object[] gValues = xPropSet.getPropertyValues(boundPropsToTest); + Object[] newValue = new Object[gValues.length]; + log.println("Trying to change all properties."); + for (int i=0; i<boundPropsToTest.length; i++) { + newValue[i] = ValueChanger.changePValue(gValues[i]); + } + try { + xPropSet.setPropertyValues(boundPropsToTest, newValue); + } catch (com.sun.star.beans.PropertyVetoException e) { + e.printStackTrace((PrintWriter)log); + failed("Exception occured while trying to change the properties."); + } catch (com.sun.star.lang.IllegalArgumentException e) { + e.printStackTrace((PrintWriter)log); + failed("Exception occured while trying to change the properties."); + } catch (com.sun.star.lang.WrappedTargetException e) { + e.printStackTrace((PrintWriter)log); + failed("Exception occured while trying to change the properties."); + } // end of try-catch + + assure("Listener was not called.", ml.wasListenerCalled()); + xPropSet.removePropertiesChangeListener(ml); + } + + private String[] getBoundPropsToTest() { + Property[] properties = xPropSet.getPropertySetInfo().getProperties(); + String[] testPropsNames = null; + + Vector tNames = new Vector(); + + for (int i = 0; i < properties.length; i++) { + + Property property = properties[i]; + String name = property.Name; + boolean isWritable = ((property.Attributes & + PropertyAttribute.READONLY) == 0); + boolean isNotNull = ((property.Attributes & + PropertyAttribute.MAYBEVOID) == 0); + boolean isBound = ((property.Attributes & + PropertyAttribute.BOUND) != 0); + + if ( isWritable && isNotNull && isBound) { + tNames.add(name); + } + + } // endfor + + //get a array of bound properties + testPropsNames = new String[tNames.size()]; + testPropsNames = (String[])tNames.toArray(testPropsNames); + return testPropsNames; + } + + /** + * Listener implementation which sets a flag when + * listener was called. + */ + public class MyChangeListener implements XPropertiesChangeListener { + boolean propertiesChanged = false; + public void propertiesChange(PropertyChangeEvent[] e) { + propertiesChanged = true; + } + public void disposing (EventObject obj) {} + public boolean wasListenerCalled() { return propertiesChanged; } + public void reset() { propertiesChanged = false; } + }; + +} diff --git a/forms/qa/complex/forms/makefile.mk b/forms/qa/complex/forms/makefile.mk new file mode 100755 index 000000000000..7333c58e2381 --- /dev/null +++ b/forms/qa/complex/forms/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.4.56.1 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = ..$/..$/.. +TARGET = CheckOGroupBoxModel +PRJNAME = $(TARGET) +PACKAGE = complex$/forms + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +#----- compile .java files ----------------------------------------- + +JARFILES = sandbox.jar ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar mysql.jar +JAVAFILES = CheckOGroupBoxModel.java +JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + +#----- make a jar from compiled files ------------------------------ + +MAXLINELENGTH = 100000 + +JARCLASSDIRS = $(PACKAGE) + +# --- Parameters for the test -------------------------------------- + +# start an office if the parameter is set for the makefile +.IF "$(OFFICE)" == "" +CT_APPEXECCOMMAND = +.ELSE +CT_APPEXECCOMMAND = -AppExecutionCommand "$(OFFICE)$/soffice -accept=socket,host=localhost,port=8100;urp;" +.ENDIF + +# test base is java complex +CT_TESTBASE = -TestBase java_complex + +# build up package name with "." instead of $/ +CT_PACKAGE = -o $(PACKAGE:s\$/\.\) + +# start the runner application +CT_APP = org.openoffice.Runner + +# --- Targets ------------------------------------------------------ + +.IF "$(depend)" == "" +run : ALLTAR +.ELSE +run : ALLDEP +.ENDIF + +.INCLUDE : target.mk + +run: + +java -cp $(CLASSPATH) $(CT_APP) $(CT_APPEXECCOMMAND) $(CT_TESTBASE) $(CT_PACKAGE).$(JAVAFILES:b) diff --git a/forms/qa/forms_all.sce b/forms/qa/forms_all.sce new file mode 100644 index 000000000000..6b5344f60f6a --- /dev/null +++ b/forms/qa/forms_all.sce @@ -0,0 +1,7 @@ +-o integration.forms.RadioButtons +-o integration.forms.FormControlTest +-o integration.forms.FormPropertyBags +-o integration.forms.CellBinding +-o integration.forms.ListSelection +-o integration.forms.MasterDetailForms +-o integration.forms.XMLFormSettings diff --git a/forms/qa/integration/forms/BooleanValidator.java b/forms/qa/integration/forms/BooleanValidator.java new file mode 100644 index 000000000000..3cba1273d63f --- /dev/null +++ b/forms/qa/integration/forms/BooleanValidator.java @@ -0,0 +1,59 @@ +/* + * BooleanValidator.java + * + * Created on 10. Maerz 2004, 16:27 + */ + +package integration.forms; + +/** + * + * @author fs93730 + */ +public class BooleanValidator extends integration.forms.ControlValidator +{ + private boolean m_preventChecked; + private com.sun.star.uno.AnyConverter m_converter; + + /** Creates a new instance of BooleanValidator */ + public BooleanValidator( boolean preventChecked ) + { + m_preventChecked = preventChecked; + m_converter = new com.sun.star.uno.AnyConverter(); + } + + public String explainInvalid( Object Value ) + { + try + { + if ( m_converter.isVoid( Value ) ) + return "'indetermined' is not an allowed state"; + boolean value = ((Boolean)Value).booleanValue(); + if ( m_preventChecked && ( value == true ) ) + return "no no no. Don't check it."; + } + catch( java.lang.Exception e ) + { + return "ooops. Unknown error"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + if ( m_converter.isVoid( Value ) ) + return false; + + boolean value = ((Boolean)Value).booleanValue(); + if ( m_preventChecked && ( value == true ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + } + return false; + } +} diff --git a/forms/qa/integration/forms/CellBinding.java b/forms/qa/integration/forms/CellBinding.java new file mode 100644 index 000000000000..3bf171d82465 --- /dev/null +++ b/forms/qa/integration/forms/CellBinding.java @@ -0,0 +1,560 @@ +/* + * CellBinding.java + * + * Created on 12. Mai 2004, 15:15 + */ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.util.*; +import com.sun.star.lang.*; +import com.sun.star.beans.*; +import com.sun.star.form.binding.*; +import com.sun.star.accessibility.*; +import com.sun.star.awt.XListBox; +import com.sun.star.table.CellAddress; +import com.sun.star.table.XCell; +import com.sun.star.sheet.XCellRangeData; +import com.sun.star.sheet.XCellRangeFormula; +import com.sun.star.table.CellRangeAddress; +import com.sun.star.text.XTextRange; + +/** + * + * @author fs93730 + */ +public class CellBinding extends complexlib.ComplexTestCase +{ + /** the test document our form layer lives in */ + private SpreadsheetDocument m_document; + /** our form layer */ + private FormLayer m_formLayer; + /** our service factory */ + private XMultiServiceFactory m_orb; + + /** Creates a new instance of CellBinding */ + public CellBinding() + { + } + + public String[] getTestMethodNames() + { + return new String[] { + "checkTextFieldBinding", + "checkBooleanRadioBinding", + "checkStringRadioBinding", + "checkBooleanCheckBoxBinding", + "checkStringCheckBoxBinding", + "checkListBoxBinding", + "checkListBoxIndexBinding" + }; + } + + public String getTestObjectName() + { + return "Form Control Spreadsheet Cell Binding Test"; + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one + */ + private void closeDocument() + { + try + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + catch ( com.sun.star.uno.Exception e ) + { + } + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + m_document = new SpreadsheetDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + closeDocument(); + } + + /* ------------------------------------------------------------------ */ + public void checkTextFieldBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + final short col = 0; + final short row = 2; + final String text = new String( "content" ); + final String otherText = new String( "something else" ); + final String yetAnotherText = new String( "yet another text" ); + + // cretae a normal text control + XPropertySet controlModel = m_formLayer.createControlAndShape( "DatabaseTextField", 30, 9, 30, 6 ); + + // bind it to cell A1 + bindToCell( controlModel, col, row ); + + // switch to alive mode + m_document.getCurrentView().toggleFormDesignMode(); + + // test the data transfer control -> cell + simulateUserTextInput( controlModel, text ); + verifyStringCellContent( col, row, text, "A text field does not forward its user input to the cell." ); + + // the same, but this time changing the control value programmatically + controlModel.setPropertyValue( "Text", otherText ); + verifyStringCellContent( col, row, otherText, "A text field does not forward programmatic changes to the cell." ); + + // the other way round: cell->control + setCellText( col, row, yetAnotherText ); + String controlText = (String)controlModel.getPropertyValue( "Text" ); + if ( !controlText.equals( yetAnotherText ) ) + failed( "Changes in the cell are not forwarded to the text field." ); + } + /* ------------------------------------------------------------------ */ + public void checkBooleanRadioBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + // two radio buttons + XPropertySet primaryRadio = createRadio( 28, "radio button no. 1", "radio group", "primary" ); + XPropertySet secondaryRadio = createRadio( 33, "radio button no. 2", "radio group", "secodary" ); + + // bind them + short col = (short)0; + short row1 = (short)6; + short row2 = (short)7; + bindToCell( primaryRadio, col, row1 ); + bindToCell( secondaryRadio, col, row2 ); + + // check the first button + simulateUserRadioCheck( primaryRadio ); + // check the cell content + verifyNumericCellContent( col, row1, 1, "Radio buttons do not forward their (boolean) values to cells (1)." ); + verifyNumericCellContent( col, row2, 0, "Radio buttons do not forward their (boolean) values to cells (2)." ); + // check the second button + simulateUserRadioCheck( secondaryRadio ); + // check the cell content + verifyNumericCellContent( col, row1, 0, "Radio buttons do not forward their (boolean) values to cells (3)." ); + verifyNumericCellContent( col, row2, 1, "Radio buttons do not forward their (boolean) values to cells (4)." ); + + // the other way round: writing values into the cell + setCellValue( col, row1, 1.0 ); + // setting this should have checked the primary radio, which should have unchecked the secondary radio, + // which should have been propagated to the second cell + verifyNumericCellContent( col, row2, 0, "Changing primary cell is not propagated to the secondary cell (via the radio buttons)." ); + + // setting an empty cell should result in the radio being unchecked + setCellEmpty( col, row1 ); + if ( ((Short)primaryRadio.getPropertyValue( "State" )).shortValue() != 0 ) + failed( "Setting a cell to 'empty' does not reset the bound radio button." ); + } + + /* ------------------------------------------------------------------ */ + public void checkStringRadioBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + // two radio buttons + XPropertySet primaryRadio = createRadio( 46, "radio button A", "radio ref group", "primary" ); + XPropertySet secondaryRadio = createRadio( 51, "radio button B", "radio ref group", "secodary" ); + + // give the ref values + String refValueA = new String( "ref value A" ); + String refValueB = new String( "ref value B" ); + primaryRadio.setPropertyValue( "RefValue", refValueA ); + secondaryRadio.setPropertyValue( "RefValue", refValueB ); + + // bind them to the same cell + short col = (short)0; + short row = (short)10; + bindToCell( primaryRadio, col, row ); + bindToCell( secondaryRadio, col, row ); + + // checking a radio should set the respective ref value at the cell + simulateUserRadioCheck( primaryRadio ); + verifyStringCellContent( col, row, refValueA, "A bound radio button with a reference value does not pass this value to the cell upon checking (1)." ); + simulateUserRadioCheck( secondaryRadio ); + verifyStringCellContent( col, row, refValueB, "A bound radio button with a reference value does not pass this value to the cell upon checking (2)." ); + + // changing the cell should check the buttons if the cell text equals the ref value + setCellText( col, row, "no ref value" ); + verifyRadioStates( primaryRadio, secondaryRadio, (short)0, (short)0, "Radio button not unchecked, though the bound cell value does not equal ref value." ); + + setCellText( col, row, refValueA ); + verifyRadioStates( primaryRadio, secondaryRadio, (short)1, (short)0, "Radio button not properly un/checked according to the cell and ref value (1)." ); + + setCellText( col, row, refValueB ); + verifyRadioStates( primaryRadio, secondaryRadio, (short)0, (short)1, "Radio button not properly un/checked according to the cell and ref value (2)." ); + } + + /* ------------------------------------------------------------------ */ + public void checkBooleanCheckBoxBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet checkBox = m_formLayer.createControlAndShape( "DatabaseCheckBox", 30, 59, 40, 4 ); + checkBox.setPropertyValue( "Label", "check box" ); + checkBox.setPropertyValue( "TriState", new Boolean( true ) ); + + short col = (short)0; + short row = (short)13; + bindToCell( checkBox, col, row ); + + // initialize with "not checked" + checkBox.setPropertyValue( "State", new Short( (short)0 ) ); + verifyNumericCellContent( col, row, 0, "programmatically unchecking the check box is not propagated to the cell." ); + + // first click: "not checked" -> "checked" + simulateUserCheckBoxCheck( checkBox, (short)1 ); + verifyNumericCellContent( col, row, 1, "moving the check box state to 'checked' is not propagated to the cell." ); + + // second click: "checked" -> "indetermined" + simulateUserCheckBoxCheck( checkBox, (short)2 ); + verifyVoidCell( col, row, "propagating the 'indetermined' state to the cell does not work." ); + + // third click: "indetermined" -> "not checked" + simulateUserCheckBoxCheck( checkBox, (short)0 ); + verifyNumericCellContent( col, row, 0, "unchecking a check box via UI is not propagated to the cell." ); + } + + /* ------------------------------------------------------------------ */ + public void checkStringCheckBoxBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + String refValue = new String( "checked " ); + + XPropertySet checkBox = m_formLayer.createControlAndShape( "DatabaseCheckBox", 30, 68, 40, 4 ); + checkBox.setPropertyValue( "Label", "check box with ref value" ); + checkBox.setPropertyValue( "TriState", new Boolean( true ) ); + checkBox.setPropertyValue( "RefValue", refValue ); + + short col = (short)0; + short row = (short)15; + bindToCell( checkBox, col, row ); + + // initialize with "not checked" + checkBox.setPropertyValue( "State", new Short( (short)0 ) ); + verifyNumericCellContent( col, row, 0, "programmatically unchecking the check box is not propagated to the cell." ); + + // first click: "not checked" -> "checked" + simulateUserCheckBoxCheck( checkBox, (short)1 ); + verifyStringCellContent( col, row, refValue, "moving the check box state to 'checked' does not propagated the ref value to the cell." ); + + // second click: "checked" -> "indetermined" + simulateUserCheckBoxCheck( checkBox, (short)2 ); + verifyVoidCell( col, row, "propagating the 'indetermined' state to the cell does not work, when exchanging ref values." ); + + // third click: "indetermined" -> "not checked" + simulateUserCheckBoxCheck( checkBox, (short)0 ); + verifyStringCellContent( col, row, "", "unchecking a check box via UI does not propagated the ref value to the cell." ); + } + + /* ------------------------------------------------------------------ */ + /** verifies that a list box, which is bound via an ordinary value binding, + * works as expected + */ + public void checkListBoxBinding( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet listBox = m_formLayer.createControlAndShape( "DatabaseListBox", 30, 80, 40, 6 ); + listBox.setPropertyValue( "Dropdown", new Boolean( true ) ); + listBox.setPropertyValue( "StringItemList", new String[] { "Apples", "Oranges", "Peaches" } ); + + short col = (short)0; + short row = (short)18; + + // ............................................................... + // add a list entry source which fills the list boxes list from cells in the + // spreadsheet + short sourceCol = (short)4; + setCellText( sourceCol, (short)( row - 1 ), "Apples" ); + setCellText( sourceCol, (short)( row + 0 ), "Oranges" ); + setCellText( sourceCol, (short)( row + 1 ), "Peaches" ); + + //setListSource( listBox, sourceCol, row, (short)( row + 2 ) ); + // TODO: this is currently prone to deadlocks + + // ............................................................... + // bind to a cell + bindToCell( listBox, col, row ); + + // ............................................................... + // do the tests + listBox.setPropertyValue( "SelectedItems", new short[] { (short)0 } ); + verifyStringCellContent( col, row, "Apples", "programmatically selecting a list entry is not propagated to the cell." ); + + simulateUserListBoxSelection( listBox, "Oranges" ); + verifyStringCellContent( col, row, "Oranges", "UI-selecting a list entry is not propagated to the cell." ); + + setCellText( col, row, "Peaches" ); + short[] selectedItems = (short[])listBox.getPropertyValue( "SelectedItems" ); + assureEquals( "changes in the cell bound to a list box are not propagated to the list box selection", + 2, selectedItems[0] ); + } + + /* ------------------------------------------------------------------ */ + /** verifies that a list box, which is bound via a value binding exchanging the <b>index</b> + * of the selected entry, works as expected + */ + public void checkListBoxIndexBinding() throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet listBox = m_formLayer.createControlAndShape( "DatabaseListBox", 30, 94, 40, 6 ); + listBox.setPropertyValue( "Dropdown", new Boolean( true ) ); + listBox.setPropertyValue( "StringItemList", new String[] { "Pears", "Bananas", "Strawberries" } ); + + short col = (short)0; + short row = (short)21; + + // ............................................................... + // add a list entry source which fills the list boxes list from cells in the + // spreadsheet + short sourceCol = (short)4; + setCellText( sourceCol, (short)( row - 1 ), "Pears" ); + setCellText( sourceCol, (short)( row + 0 ), "Bananas" ); + setCellText( sourceCol, (short)( row + 1 ), "Strawberries" ); + + //setListSource( listBox, sourceCol, row, (short)( row + 2 ) ); + // TODO: this is currently prone to deadlocks + + // ............................................................... + // bind to a cell + bindToCell( listBox, col, row, "com.sun.star.table.ListPositionCellBinding" ); + + // ............................................................... + // do the tests + listBox.setPropertyValue( "SelectedItems", new short[] { (short)0 } ); + verifyNumericCellContent( col, row, 1, "programmatically selecting a list entry is not propagated (as index) to the cell." ); + + simulateUserListBoxSelection( listBox, "Bananas" ); + verifyNumericCellContent( col, row, 2, "UI-selecting a list entry is not propagated (as index) to the cell." ); + + setCellValue( col, row, 3 ); + short[] selectedItems = (short[])listBox.getPropertyValue( "SelectedItems" ); + assureEquals( "changes in the cell bound to a list box via list index are not propagated to the list box selection", + 2, selectedItems[0] ); + } + + /* ------------------------------------------------------------------ */ + /** verifies that the content of a given cell equals a given string + */ + private XPropertySet createRadio( int yPos, String label, String name, String tag ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet radio = m_formLayer.createControlAndShape( "DatabaseRadioButton", 30, yPos, 40, 4 ); + radio.setPropertyValue( "Label", label ); + radio.setPropertyValue( "Name", name ); + radio.setPropertyValue( "Tag", tag ); + return radio; + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of two radio button + */ + private boolean verifyRadioStates( XPropertySet radio1, XPropertySet radio2, short value1, short value2, + String errorMessage ) throws com.sun.star.uno.Exception, java.lang.Exception + { + if ( ( ((Short)radio1.getPropertyValue( "State" )).shortValue() != value1 ) + || ( ((Short)radio2.getPropertyValue( "State" )).shortValue() != value2 ) + ) + { + failed( errorMessage ); + return false; + } + return true; + } + + /* ------------------------------------------------------------------ */ + /** verifies that the content of a given cell equals a given string + */ + private boolean verifyVoidCell( short col, short row, String failErrorMessage ) throws com.sun.star.uno.Exception + { + XCellRangeData cell = (XCellRangeData)UnoRuntime.queryInterface( XCellRangeData.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + Object cellContent = cell.getDataArray()[0][0]; + if ( ((com.sun.star.uno.Any)cellContent).getType().getTypeClass() != com.sun.star.uno.TypeClass.VOID ) + { + failed( failErrorMessage ); + return false; + } + return true; + } + + /* ------------------------------------------------------------------ */ + /** verifies that the content of a given cell equals a given string + */ + private boolean verifyNumericCellContent( short col, short row, double value, String failErrorMessage ) throws com.sun.star.uno.Exception + { + XCell cell = (XCell)UnoRuntime.queryInterface( XCell.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + if ( cell.getValue() != value ) + { + failed( failErrorMessage ); + return false; + } + return true; + } + + /* ------------------------------------------------------------------ */ + /** verifies that the content of a given cell equals a given string + */ + private boolean verifyStringCellContent( short col, short row, String text, String failErrorMessage ) throws com.sun.star.uno.Exception + { + XTextRange cell = (XTextRange)UnoRuntime.queryInterface( XTextRange.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + if ( !cell.getString().equals( text ) ) + { + failed( failErrorMessage ); + return false; + } + return true; + } + + /* ------------------------------------------------------------------ */ + /** sets the text of a given cell to a given string + */ + private void setCellText( short col, short row, String text ) throws com.sun.star.uno.Exception + { + XTextRange cell = (XTextRange)UnoRuntime.queryInterface( XTextRange.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + cell.setString( text ); + } + + /* ------------------------------------------------------------------ */ + /** sets a numeric value in a given cell + */ + private void setCellValue( short col, short row, double value ) throws com.sun.star.uno.Exception + { + XCell cell = (XCell)UnoRuntime.queryInterface( XCell.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + cell.setValue( value ); + } + + /* ------------------------------------------------------------------ */ + /** sets a numeric value in a given cell + */ + private void setCellEmpty( short col, short row ) throws com.sun.star.uno.Exception + { + // as long as #i29130# is not fixed, we do not set the cell to "empty", but to + // an invalid formular, which serves well for our purpose + XCellRangeFormula cell = (XCellRangeFormula)UnoRuntime.queryInterface( XCellRangeFormula.class, + m_document.getSheet( 0 ).getCellByPosition( col, row ) + ); + String[][] args = new String[][] { new String[] { "=INVALID_FUNCTION()" } }; + cell.setFormulaArray( args ); + } + + /* ------------------------------------------------------------------ */ + /** binds the given control model to the given cell in the first sheet, + * using the given service name for the binding + */ + private void bindToCell( XPropertySet controlModel, short column, short row, String _bindingServiceName ) throws com.sun.star.uno.Exception + { + XBindableValue bindableModel = (XBindableValue)UnoRuntime.queryInterface( XBindableValue.class, + controlModel + ); + + CellAddress address = new CellAddress(); + address.Column = column; + address.Row = row; + address.Sheet = 0; + + NamedValue[] parameters = new NamedValue[] { new NamedValue() }; + parameters[0].Name = "BoundCell"; + parameters[0].Value = address; + + XValueBinding cellBinding = (XValueBinding)UnoRuntime.queryInterface( XValueBinding.class, + m_document.createInstanceWithArguments( _bindingServiceName, parameters ) + ); + + bindableModel.setValueBinding( cellBinding ); + } + + /* ------------------------------------------------------------------ */ + /** binds the given control model to the given cell in the first sheet + */ + private void bindToCell( XPropertySet _controlModel, short _column, short _row ) throws com.sun.star.uno.Exception + { + bindToCell( _controlModel, _column, _row, "com.sun.star.table.CellValueBinding" ); + } + + /* ------------------------------------------------------------------ */ + /** sets the given cell range as list entry source for the given control + */ + private void setListSource( XPropertySet _listSink, short _sourceCol, short _rowStart, short _rowEnd ) throws com.sun.star.uno.Exception + { + CellRangeAddress listSourceAddress = new CellRangeAddress( (short)0, (int)_sourceCol, (int)_rowStart, (int)_sourceCol, (int)_rowEnd ); + NamedValue addressParameter = new NamedValue( "CellRange", listSourceAddress ); + + XListEntrySource listSource = (XListEntrySource)UnoRuntime.queryInterface( XListEntrySource.class, + m_document.createInstanceWithArguments( "com.sun.star.table.CellRangeListSource", new NamedValue[]{ addressParameter } ) + ); + XListEntrySink listSink = (XListEntrySink)UnoRuntime.queryInterface( XListEntrySink.class, + _listSink ); + listSink.setListEntrySource( listSource ); + } + + /* ------------------------------------------------------------------ */ + /** simulates a user action to check a radio button + */ + private void simulateUserRadioCheck( XPropertySet radioModel ) throws com.sun.star.uno.Exception + { + XAccessible accessible = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, m_document.getCurrentView().getControl( radioModel ) ); + + XAccessibleValue xValue = (XAccessibleValue)UnoRuntime.queryInterface( + XAccessibleValue.class, accessible.getAccessibleContext() ); + + Integer newValue = new Integer( 1 ); + xValue.setCurrentValue( newValue ); + } + + /* ------------------------------------------------------------------ */ + /** simulates a user action to check a radio button + */ + private void simulateUserCheckBoxCheck( XPropertySet checkBox, short state ) throws com.sun.star.uno.Exception + { + XAccessible accessible = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, m_document.getCurrentView().getControl( checkBox ) ); + + XAccessibleValue xValue = (XAccessibleValue)UnoRuntime.queryInterface( + XAccessibleValue.class, accessible.getAccessibleContext() ); + + xValue.setCurrentValue( new Short( state ) ); + } + + /* ------------------------------------------------------------------ */ + /** simulates a user selecting an entry in a list box + */ + private void simulateUserListBoxSelection( XPropertySet _listBox, String _selectEntry ) throws com.sun.star.uno.Exception + { + XListBox listBoxControl = (XListBox)UnoRuntime.queryInterface( + XListBox.class, m_document.getCurrentView().getControl( _listBox ) ); + listBoxControl.selectItem( _selectEntry, true ); + } + + /* ------------------------------------------------------------------ */ + /** simulates text input into the control belonging to the given model + */ + private void simulateUserTextInput( XPropertySet controlModel, String text ) throws com.sun.star.uno.Exception + { + XAccessible accessible = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, m_document.getCurrentView().getControl( controlModel ) ); + + XAccessibleContext context = accessible.getAccessibleContext(); + XServiceInfo si = (XServiceInfo)UnoRuntime.queryInterface( XServiceInfo.class, + accessible.getAccessibleContext() ); + + XAccessibleEditableText textAccess = (XAccessibleEditableText)UnoRuntime.queryInterface( + XAccessibleEditableText.class, accessible.getAccessibleContext() ); + + textAccess.setText( text ); + } +} diff --git a/forms/qa/integration/forms/ControlValidation.java b/forms/qa/integration/forms/ControlValidation.java new file mode 100644 index 000000000000..a055e1fb80d4 --- /dev/null +++ b/forms/qa/integration/forms/ControlValidation.java @@ -0,0 +1,205 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ControlValidation.java,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.util.*; +import com.sun.star.lang.*; +import com.sun.star.accessibility.*; +import com.sun.star.container.*; +import com.sun.star.beans.*; +import com.sun.star.form.binding.*; + +import integration.forms.DocumentHelper; +import integration.forms.NumericValidator; +import integration.forms.TextValidator; +import integration.forms.BooleanValidator; +import integration.forms.ListSelectionValidator; +import integration.forms.SingleControlValidation; + +/** + * + * @author fs@openoffice.org + */ +public class ControlValidation extends complexlib.ComplexTestCase implements com.sun.star.lang.XEventListener +{ + private DocumentHelper m_document; /// our current test document + private XMultiServiceFactory m_orb; /// our service factory + + /** Creates a new instance of ControlValidation */ + public ControlValidation() + { + } + + public String[] getTestMethodNames() + { + return new String[] { + "interactiveValidation" + }; + } + + public String getTestObjectName() + { + return "Form Control Validation Test"; + } + + public static boolean isInteractiveTest() + { + return true; + } + + /* ------------------------------------------------------------------ */ + /* test framework */ + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + } + + /* ------------------------------------------------------------------ */ + private void prepareTestStep( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + m_document = DocumentHelper.blankTextDocument( m_orb ); + m_document.getDocument( ).addEventListener( this ); + } + + /* ------------------------------------------------------------------ */ + public void after() + { + closeDocument(); + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one + */ + private void closeDocument() + { + try + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + catch ( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.out ); + } + } + + /* ------------------------------------------------------------------ */ + /* public test methods */ + /* ------------------------------------------------------------------ */ + public void interactiveValidation() throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep(); + + SingleControlValidation validation; + XPropertySet focusField; + + validation = new SingleControlValidation( m_document, 5, 5, "DatabaseFormattedField", new NumericValidator() ); + focusField = validation.getInputField(); + validation.setExplanatoryText( "Please enter a number between 0 and 100, with at most 1 decimal digit" ); + + validation = new SingleControlValidation( m_document, 90, 5, "DatabaseTextField", new TextValidator() ); + validation.setExplanatoryText( "Please enter a text whose length is a multiple of 3, and which does not contain the letter 'Z'" ); + + validation = new SingleControlValidation( m_document, 5, 55, "DatabaseDateField", new DateValidator() ); + validation.setExplanatoryText( "Please enter a date in the current month" ); + validation.getInputField().setPropertyValue( "Dropdown", new Boolean( true ) ); + + validation = new SingleControlValidation( m_document, 90, 55, "DatabaseTimeField", new TimeValidator() ); + validation.setExplanatoryText( "Please enter a time. Valid values are all full hours." ); + + validation = new SingleControlValidation( m_document, 5, 110, "DatabaseCheckBox", new BooleanValidator( false ) ); + validation.setExplanatoryText( "Please check (well, or uncheck) the box. Don't leave it in indetermined state." ); + validation.getInputField().setPropertyValue( "TriState", new Boolean( true ) ); + + validation = new SingleControlValidation( m_document, 90, 110, "DatabaseRadioButton", new BooleanValidator( true ), 3, 0 ); + validation.setExplanatoryText( "Please check any but the first button" ); + + validation = new SingleControlValidation( m_document, 5, 165, "DatabaseListBox", new ListSelectionValidator( ), 1, 24 ); + validation.setExplanatoryText( "Please select not more than two entries." ); + validation.getInputField().setPropertyValue( "MultiSelection", new Boolean( true ) ); + validation.getInputField().setPropertyValue( "StringItemList", new String[] { "first", "second", "third", "forth", "fivth" } ); + + // switch to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + m_document.getCurrentView( ).grabControlFocus( focusField ); + + // wait for the user telling us to exit + waitForUserInput(); + } + + /* ------------------------------------------------------------------ */ + /* internal methods */ + /* ------------------------------------------------------------------ */ + /** waits for the user to press a key (on the console where she started the java program) + or the document to be closed by the user. + @return + <TRUE/> if the user pressed a key on the console, <FALSE/> if she closed the document + */ + protected boolean waitForUserInput() throws java.lang.Exception + { + synchronized (this) + { + integration.forms.WaitForInput aWait = new integration.forms.WaitForInput( this ); + aWait.start(); + wait(); + + // if the waiter thread is done, the user pressed enter + boolean bKeyPressed = aWait.isDone(); + if ( !bKeyPressed ) + aWait.interrupt(); + + return bKeyPressed; + } + } + + /* ------------------------------------------------------------------ */ + /* XEventListener overridables */ + /* ------------------------------------------------------------------ */ + public void disposing( com.sun.star.lang.EventObject eventObject ) + { + if ( m_document.getDocument().equals( eventObject.Source ) ) + { + // notify ourself that we can stop waiting for user input + synchronized (this) + { + notify(); + } + } + } + +} diff --git a/forms/qa/integration/forms/ControlValidator.java b/forms/qa/integration/forms/ControlValidator.java new file mode 100644 index 000000000000..cf192162f801 --- /dev/null +++ b/forms/qa/integration/forms/ControlValidator.java @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ControlValidator.java,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +/** base class for components validating the content of form controls + * + * @author fs@openoffice.org + */ +public abstract class ControlValidator implements com.sun.star.form.validation.XValidator +{ + + /** Creates a new instance of ControlValidator */ + public ControlValidator() + { + } + + public void addValidityConstraintListener(com.sun.star.form.validation.XValidityConstraintListener xValidityConstraintListener) + { + } + + public void removeValidityConstraintListener(com.sun.star.form.validation.XValidityConstraintListener xValidityConstraintListener) + { + } + + protected boolean isVoid( Object Value ) + { + try + { + return ( com.sun.star.uno.AnyConverter.getType(Value).getTypeClass() + == com.sun.star.uno.TypeClass.VOID ); + } + catch( java.lang.ClassCastException e ) + { + } + return false; + } +} diff --git a/forms/qa/integration/forms/DateValidator.java b/forms/qa/integration/forms/DateValidator.java new file mode 100644 index 000000000000..799c503218d0 --- /dev/null +++ b/forms/qa/integration/forms/DateValidator.java @@ -0,0 +1,106 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DateValidator.java,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.form.binding.*; + +/** + * + * @author fs@openoffice.org + */ +public class DateValidator extends integration.forms.ControlValidator +{ + + /** Creates a new instance of NumericValidator */ + public DateValidator( ) + { + } + + public String explainInvalid( Object Value ) + { + try + { + if ( isVoid( Value ) ) + return "empty input"; + + com.sun.star.util.Date dateValue = (com.sun.star.util.Date)Value; + if ( isDedicatedInvalidDate( dateValue ) ) + return "this is no valid date"; + + if ( !isNextMonthsDate( dateValue ) ) + return "date must denote a day in the current month"; + } + catch( java.lang.Exception e ) + { + return "oops. What did you enter for this to happen?"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + if ( isVoid( Value ) ) + return false; + + com.sun.star.util.Date dateValue = (com.sun.star.util.Date) + com.sun.star.uno.AnyConverter.toObject( + com.sun.star.util.Date.class, Value); + if ( isDedicatedInvalidDate( dateValue ) ) + return false; + + if ( !isNextMonthsDate( dateValue ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + e.printStackTrace( System.err ); + } + return false; + } + + private boolean isDedicatedInvalidDate( com.sun.star.util.Date dateValue ) + { + return ( dateValue.Day == 0 ) && ( dateValue.Month == 0 ) && ( dateValue.Year == 0 ); + } + + private boolean isNextMonthsDate( com.sun.star.util.Date dateValue ) + { + int overallMonth = dateValue.Year * 12 + dateValue.Month - 1; + + int todaysMonth = new java.util.Date().getMonth(); + int todaysYear = new java.util.Date().getYear() + 1900; + int todaysOverallMonth = todaysYear * 12 + todaysMonth; + + return overallMonth == todaysOverallMonth; + } +} diff --git a/forms/qa/integration/forms/DocumentHelper.java b/forms/qa/integration/forms/DocumentHelper.java new file mode 100644 index 000000000000..81b0c3a86f5a --- /dev/null +++ b/forms/qa/integration/forms/DocumentHelper.java @@ -0,0 +1,390 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DocumentHelper.java,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XChild; +import com.sun.star.container.XIndexContainer; +import com.sun.star.container.XNameContainer; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.drawing.XDrawPageSupplier; +import com.sun.star.drawing.XDrawPages; +import com.sun.star.drawing.XDrawPagesSupplier; +import com.sun.star.form.XFormsSupplier; +import com.sun.star.frame.XComponentLoader; +import com.sun.star.frame.XController; +import com.sun.star.frame.XFrame; +import com.sun.star.frame.XModel; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XInterface; +import com.sun.star.util.XModifiable; + +/**************************************************************************/ + +/**************************************************************************/ +/** provides a small wrapper around a document +*/ +public class DocumentHelper +{ + private XMultiServiceFactory m_orb; + private XComponent m_documentComponent; + + /* ================================================================== */ + /* ------------------------------------------------------------------ */ + public DocumentHelper( XMultiServiceFactory orb, XComponent document ) + { + m_orb = orb; + m_documentComponent = document; + } + + /* ------------------------------------------------------------------ */ + protected static XComponent implLoadAsComponent( XMultiServiceFactory orb, String documentOrFactoryURL ) throws com.sun.star.uno.Exception + { + XComponentLoader aLoader = (XComponentLoader)UnoRuntime.queryInterface( + XComponentLoader.class, + orb.createInstance( "com.sun.star.frame.Desktop" ) + ); + + XComponent document = dbfTools.queryComponent( + aLoader.loadComponentFromURL( documentOrFactoryURL, "_blank", 0, new PropertyValue[ 0 ] ) + ); + return document; + } + + /* ------------------------------------------------------------------ */ + private static DocumentHelper implLoadDocument( XMultiServiceFactory orb, String documentOrFactoryURL ) throws com.sun.star.uno.Exception + { + XComponent document = implLoadAsComponent( orb, documentOrFactoryURL ); + + XServiceInfo xSI = (XServiceInfo)UnoRuntime.queryInterface( XServiceInfo.class, + document ); + if ( xSI.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) ) + return new SpreadsheetDocument( orb, document ); + return new DocumentHelper( orb, document ); + } + + /* ------------------------------------------------------------------ */ + public static DocumentHelper loadDocument( XMultiServiceFactory orb, String documentURL ) throws com.sun.star.uno.Exception + { + return implLoadDocument( orb, documentURL ); + } + + /* ------------------------------------------------------------------ */ + public static DocumentHelper blankTextDocument( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception + { + return blankDocument( orb, DocumentType.WRITER ); + } + + /* ------------------------------------------------------------------ */ + public static DocumentHelper blankXMLForm( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception + { + return blankDocument( orb, DocumentType.XMLFORM ); + } + + /* ------------------------------------------------------------------ */ + public static DocumentHelper blankDocument( XMultiServiceFactory orb, DocumentType eType ) throws com.sun.star.uno.Exception + { + return implLoadDocument( orb, getDocumentFactoryURL( eType ) ); + } + + /* ================================================================== */ + /* ------------------------------------------------------------------ */ + public XComponent getDocument( ) + { + return m_documentComponent; + } + + /* ------------------------------------------------------------------ */ + public boolean isModified() + { + XModifiable modify = (XModifiable)query( XModifiable.class ); + return modify.isModified(); + } + + /* ------------------------------------------------------------------ */ + public Object query( Class aInterfaceClass ) + { + return UnoRuntime.queryInterface( aInterfaceClass, m_documentComponent ); + } + + /* ------------------------------------------------------------------ */ + public XMultiServiceFactory getOrb( ) + { + return m_orb; + } + + /* ------------------------------------------------------------------ */ + /** retrieves the current view of the document + @return + the view component, queried for the interface described by aInterfaceClass + */ + public DocumentViewHelper getCurrentView( ) + { + // get the model interface for the document + XModel xDocModel = (XModel)UnoRuntime.queryInterface(XModel.class, m_documentComponent ); + // get the current controller for the document - as a controller is tied to a view, + // this gives us the currently active view for the document. + XController xController = xDocModel.getCurrentController(); + + if ( classify() == DocumentType.CALC ) + return new SpreadsheetView( m_orb, this, xController ); + + return new DocumentViewHelper( m_orb, this, xController ); + } + + /* ------------------------------------------------------------------ */ + /** reloads the document + * + * The reload is done by dispatching the respective URL at a frame of the document. + * As a consequence, if you have references to a view of the document, or any interface + * of the document, they will become invalid. + * The Model instance itself, at which you called reload, will still be valid, it will + * automatically update its internal state after the reload. + * + * Another consequence is that if the document does not have a view at all, it cannot + * be reloaded. + */ + public void reload() throws Exception + { + DocumentViewHelper view = getCurrentView(); + XFrame frame = view.getController().getFrame(); + XModel oldModel = frame.getController().getModel(); + + getCurrentView().dispatch( ".uno:Reload" ); + + m_documentComponent = (XComponent)UnoRuntime.queryInterface( XComponent.class, + frame.getController().getModel() ); + + XModel newModel = getCurrentView().getController().getModel(); + if ( UnoRuntime.areSame( oldModel, newModel ) ) + throw new java.lang.IllegalStateException( "reload failed" ); + } + + /* ------------------------------------------------------------------ */ + /** creates a new form which is a child of the given form components container + + @param xParentContainer + The parent container for the new form + @param sInitialName + The initial name of the form. May be null, in this case the default (which + is an implementation detail) applies. + */ + protected XIndexContainer createSubForm( XIndexContainer xParentContainer, String sInitialName ) + throws com.sun.star.uno.Exception + { + // create a new form + Object xNewForm = m_orb.createInstance( "com.sun.star.form.component.DataForm" ); + + // insert + xParentContainer.insertByIndex( xParentContainer.getCount(), xNewForm ); + + // set the name if necessary + if ( null != sInitialName ) + { + XPropertySet xFormProps = dbfTools.queryPropertySet( xNewForm ); + xFormProps.setPropertyValue( "Name", sInitialName ); + } + + // outta here + return (XIndexContainer)UnoRuntime.queryInterface( XIndexContainer.class, xNewForm ); + } + + /* ------------------------------------------------------------------ */ + /** creates a new form which is a child of the given form components container + + @param aParentContainer + The parent container for the new form + @param sInitialName + The initial name of the form. May be null, in this case the default (which + is an implementation detail) applies. + */ + public XIndexContainer createSubForm( Object aParentContainer, String sInitialName ) + throws com.sun.star.uno.Exception + { + XIndexContainer xParentContainer = (XIndexContainer)UnoRuntime.queryInterface( + XIndexContainer.class, aParentContainer ); + return createSubForm( xParentContainer, sInitialName ); + } + + /* ------------------------------------------------------------------ */ + /** creates a form which is a sibling of the given form + @param aForm + A sinbling of the to be created form. + + @param sInitialName + The initial name of the form. May be null, in this case the default (which + is an implementation detail) applies. + */ + public XIndexContainer createSiblingForm( Object aForm, String sInitialName ) throws com.sun.star.uno.Exception + { + // get the parent + XIndexContainer xContainer = (XIndexContainer)dbfTools.getParent( + aForm, XIndexContainer.class ); + // append a new form to this parent container + return createSubForm( xContainer, sInitialName ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the document model which a given form component belongs to + */ + static public DocumentHelper getDocumentForComponent( Object aFormComponent, XMultiServiceFactory orb ) + { + XChild xChild = (XChild)UnoRuntime.queryInterface( XChild.class, aFormComponent ); + XModel xModel = null; + while ( ( null != xChild ) && ( null == xModel ) ) + { + XInterface xParent = (XInterface)xChild.getParent(); + xModel = (XModel)UnoRuntime.queryInterface( XModel.class, xParent ); + xChild = (XChild)UnoRuntime.queryInterface( XChild.class, xParent ); + } + + return new DocumentHelper( orb, xModel ); + } + + /* ------------------------------------------------------------------ */ + /** returns a URL which can be used to create a document of a certain type + */ + public static String getDocumentFactoryURL( DocumentType eType ) + { + if ( eType == DocumentType.WRITER ) + return "private:factory/swriter"; + if ( eType == DocumentType.CALC ) + return "private:factory/scalc"; + if ( eType == DocumentType.DRAWING ) + return "private:factory/sdraw"; + if ( eType == DocumentType.XMLFORM ) + return "private:factory/swriter?slot=21053"; + return "private:factory/swriter"; + } + + /* ------------------------------------------------------------------ */ + /** classifies a document + */ + public DocumentType classify( ) + { + XServiceInfo xSI = (XServiceInfo)UnoRuntime.queryInterface( + XServiceInfo.class, m_documentComponent ); + + if ( xSI.supportsService( "com.sun.star.text.TextDocument" ) ) + return DocumentType.WRITER; + else if ( xSI.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) ) + return DocumentType.CALC; + else if ( xSI.supportsService( "com.sun.star.drawing.DrawingDocument" ) ) + return DocumentType.DRAWING; + + return DocumentType.UNKNOWN; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a com.sun.star.drawing.DrawPage of the document, denoted by index + * @param index + * the index of the draw page + * @throws + * com.sun.star.lang.IndexOutOfBoundsException + * com.sun.star.lang.WrappedTargetException + */ + protected XDrawPage getDrawPage( int index ) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException + { + XDrawPagesSupplier xSuppPages = (XDrawPagesSupplier)UnoRuntime.queryInterface( + XDrawPagesSupplier.class, getDocument() ); + XDrawPages xPages = xSuppPages.getDrawPages(); + + return (XDrawPage)UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( index ) ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the <type scope="com.sun.star.drawing">DrawPage</type> of the document + */ + protected XDrawPage getMainDrawPage( ) throws com.sun.star.uno.Exception + { + XDrawPage xReturn; + + // in case of a Writer document, this is rather easy: simply ask the XDrawPageSupplier + XDrawPageSupplier xSuppPage = (XDrawPageSupplier)UnoRuntime.queryInterface( + XDrawPageSupplier.class, getDocument() ); + if ( null != xSuppPage ) + xReturn = xSuppPage.getDrawPage(); + else + { // the model itself is no draw page supplier - okay, it may be a Writer or Calc document + // (or any other multi-page document) + XDrawPagesSupplier xSuppPages = (XDrawPagesSupplier)UnoRuntime.queryInterface( + XDrawPagesSupplier.class, getDocument() ); + XDrawPages xPages = xSuppPages.getDrawPages(); + + xReturn = (XDrawPage)UnoRuntime.queryInterface( XDrawPage.class, xPages.getByIndex( 0 ) ); + + // Note that this is no really error-proof code: If the document model does not support the + // XDrawPagesSupplier interface, or if the pages collection returned is empty, this will break. + } + + return xReturn; + } + + /* ------------------------------------------------------------------ */ + /** retrieves the root of the hierarchy of form components + */ + protected XNameContainer getFormComponentTreeRoot( ) throws com.sun.star.uno.Exception + { + XFormsSupplier xSuppForms = (XFormsSupplier)UnoRuntime.queryInterface( + XFormsSupplier.class, getMainDrawPage( ) ); + + XNameContainer xFormsCollection = null; + if ( null != xSuppForms ) + { + xFormsCollection = xSuppForms.getForms(); + } + return xFormsCollection; + } + + /* ------------------------------------------------------------------ */ + /** creates a component at the service factory provided by the document + */ + public XInterface createInstance( String serviceSpecifier ) throws com.sun.star.uno.Exception + { + XMultiServiceFactory xORB = (XMultiServiceFactory)UnoRuntime.queryInterface( XMultiServiceFactory.class, + m_documentComponent ); + return (XInterface)xORB.createInstance( serviceSpecifier ); + } + + /* ------------------------------------------------------------------ */ + /** creates a component at the service factory provided by the document + */ + public XInterface createInstanceWithArguments( String serviceSpecifier, Object[] arguments ) throws com.sun.star.uno.Exception + { + XMultiServiceFactory xORB = (XMultiServiceFactory)UnoRuntime.queryInterface( XMultiServiceFactory.class, + m_documentComponent ); + return (XInterface) xORB.createInstanceWithArguments( serviceSpecifier, arguments ); + } +}; + diff --git a/forms/qa/integration/forms/DocumentType.java b/forms/qa/integration/forms/DocumentType.java new file mode 100644 index 000000000000..855ea286e9e0 --- /dev/null +++ b/forms/qa/integration/forms/DocumentType.java @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DocumentType.java,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +/** a helper "enumeration class" for classifying a document type +*/ +public class DocumentType extends com.sun.star.uno.Enum +{ + private DocumentType( int value ) + { + super( value ); + } + + public static DocumentType getDefault() + { + return WRITER; + } + + public static final DocumentType WRITER = new DocumentType(0); + public static final DocumentType CALC = new DocumentType(1); + public static final DocumentType DRAWING = new DocumentType(2); + public static final DocumentType XMLFORM = new DocumentType(3); + public static final DocumentType UNKNOWN = new DocumentType(-1); + + public static DocumentType fromInt(int value) + { + switch(value) + { + case 0: return WRITER; + case 1: return CALC; + case 2: return DRAWING; + case 3: return XMLFORM; + default: return UNKNOWN; + } + } +}; + diff --git a/forms/qa/integration/forms/DocumentViewHelper.java b/forms/qa/integration/forms/DocumentViewHelper.java new file mode 100644 index 000000000000..f106ba070f8c --- /dev/null +++ b/forms/qa/integration/forms/DocumentViewHelper.java @@ -0,0 +1,261 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: DocumentViewHelper.java,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +/**************************************************************************/ + +import com.sun.star.awt.XControl; +import com.sun.star.awt.XControlModel; +import com.sun.star.awt.XWindow; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XIndexContainer; +import com.sun.star.form.FormComponentType; +import com.sun.star.form.XForm; +import com.sun.star.form.XFormController; +import com.sun.star.frame.XController; +import com.sun.star.frame.XDispatch; +import com.sun.star.frame.XDispatchProvider; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.URL; +import com.sun.star.util.XURLTransformer; +import com.sun.star.view.XControlAccess; +import com.sun.star.view.XFormLayerAccess; +import org.openoffice.xforms.XMLDocument; + +/**************************************************************************/ +/** provides a small wrapper around a document view +*/ +public class DocumentViewHelper +{ + private XMultiServiceFactory m_orb; + private XController m_controller; + private DocumentHelper m_document; + + /* ------------------------------------------------------------------ */ + final protected XController getController() + { + return m_controller; + } + + /* ------------------------------------------------------------------ */ + final protected DocumentHelper getDocument() + { + return m_document; + } + + /* ------------------------------------------------------------------ */ + public DocumentViewHelper( XMultiServiceFactory orb, DocumentHelper document, XController controller ) + { + m_orb = orb; + m_document = document; + m_controller = controller; + } + + /* ------------------------------------------------------------------ */ + /** Quick access to a given interface of the view + @param aInterfaceClass + the class of the interface which shall be returned + */ + public Object query( Class aInterfaceClass ) + { + return UnoRuntime.queryInterface( aInterfaceClass, m_controller ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves a dispatcher for the given URL, obtained at the current view of the document + @param aURL + a one-element array. The first element must contain a valid + <member scope="com.sun.star.util">URL::Complete</member> value. Upon return, the URL is correctly + parsed. + @return + the dispatcher for the URL in question + */ + public XDispatch getDispatcher( URL[] aURL ) throws java.lang.Exception + { + XDispatch xReturn = null; + + // go get the current view + XController xController = (XController)query( XController.class ); + // go get the dispatch provider of it's frame + XDispatchProvider xProvider = (XDispatchProvider)UnoRuntime.queryInterface( + XDispatchProvider.class, xController.getFrame() ); + if ( null != xProvider ) + { + // need an URLTransformer + XURLTransformer xTransformer = (XURLTransformer)UnoRuntime.queryInterface( + XURLTransformer.class, m_orb.createInstance( "com.sun.star.util.URLTransformer" ) ); + xTransformer.parseStrict( aURL ); + + xReturn = xProvider.queryDispatch( aURL[0], new String( ), 0 ); + } + return xReturn; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a dispatcher for the given URL, obtained at the current view of the document + */ + public XDispatch getDispatcher( String url ) throws java.lang.Exception + { + URL[] aURL = new URL[] { new URL() }; + aURL[0].Complete = url; + return getDispatcher( aURL ); + } + + /* ------------------------------------------------------------------ */ + /** dispatches the given URL into the view, if there's a dispatcher for it + + @return + <TRUE/> if the URL was successfully dispatched + */ + public boolean dispatch( String url ) throws java.lang.Exception + { + URL[] completeURL = new URL[] { new URL() }; + completeURL[0].Complete = url; + XDispatch dispatcher = getDispatcher( completeURL ); + if ( dispatcher == null ) + return false; + + PropertyValue[] aDummyArgs = new PropertyValue[] { }; + dispatcher.dispatch( completeURL[0], aDummyArgs ); + return true; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a control within the current view of a document + @param xModel + specifies the control model whose control should be located + @return + the control tied to the model + */ + public XControl getControl( XControlModel xModel ) throws com.sun.star.uno.Exception + { + // the current view of the document + XControlAccess xCtrlAcc = (XControlAccess)query( XControlAccess.class ); + // delegate the task of looking for the control + return xCtrlAcc.getControl( xModel ); + } + + /* ------------------------------------------------------------------ */ + public XControl getControl( Object aModel ) throws com.sun.star.uno.Exception + { + XControlModel xModel = (XControlModel)UnoRuntime.queryInterface( XControlModel.class, aModel ); + return getControl( xModel ); + } + + /* ------------------------------------------------------------------ */ + public Object getControl( Object aModel, Class aInterfaceClass ) throws com.sun.star.uno.Exception + { + XControlModel xModel = (XControlModel)UnoRuntime.queryInterface( XControlModel.class, aModel ); + return UnoRuntime.queryInterface( aInterfaceClass, getControl( xModel ) ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the form controller for a given logical form + */ + public XFormController getFormController( XForm _form ) + { + XFormLayerAccess formLayerAccess = (XFormLayerAccess)query( XFormLayerAccess.class ); + return formLayerAccess.getFormController( _form ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the form controller for a given logical form + */ + public XFormController getFormController( XPropertySet _form ) + { + XFormLayerAccess formLayerAccess = (XFormLayerAccess)query( XFormLayerAccess.class ); + return formLayerAccess.getFormController( (XForm)UnoRuntime.queryInterface( XForm.class, _form ) ); + } + + /* ------------------------------------------------------------------ */ + /** toggles the design mode of the form layer of active view of our sample document + */ + protected void toggleFormDesignMode( ) throws java.lang.Exception + { + if ( m_document instanceof XMLDocument ) + dispatch( ".uno:SwitchXFormsDesignMode" ); + else + dispatch( ".uno:SwitchControlDesignMode" ); + } + + /* ------------------------------------------------------------------ */ + /** sets the focus to a specific control + @param xModel + a control model. The focus is set to that control which is part of our view + and associated with the given model. + */ + public void grabControlFocus( Object xModel ) throws com.sun.star.uno.Exception + { + // look for the control from the current view which belongs to the model + XControl xControl = getControl( xModel ); + + // the focus can be set to an XWindow only + XWindow xControlWindow = (XWindow)UnoRuntime.queryInterface( XWindow.class, + xControl ); + + // grab the focus + xControlWindow.setFocus(); + } + + /* ------------------------------------------------------------------ */ + /** sets the focus to the first control + */ + protected void grabControlFocus( ) throws java.lang.Exception + { + // the forms container of our document + XIndexContainer xForms = dbfTools.queryIndexContainer( m_document.getFormComponentTreeRoot( ) ); + // the first form + XIndexContainer xForm = dbfTools.queryIndexContainer( xForms.getByIndex( 0 ) ); + + // the first control model which is no FixedText (FixedText's can't have the focus) + for ( int i = 0; i<xForm.getCount(); ++i ) + { + XPropertySet xControlProps = dbfTools.queryPropertySet( xForm.getByIndex( i ) ); + if ( FormComponentType.FIXEDTEXT != ((Short)xControlProps.getPropertyValue( "ClassId" )).shortValue() ) + { + XControlModel xControlModel = (XControlModel)UnoRuntime.queryInterface( + XControlModel.class, xControlProps ); + // set the focus to this control + grabControlFocus( xControlModel ); + // outta here + break; + } + } + + // Note that we simply took the first control model from the hierarchy. This does state nothing + // about the location of the respective control in the view. A control model is tied to a control + // shape, and the shapes are where the geometry information such as position and size is hung up. + // So you could easily have a document where the first control model is bound to a shape which + // has a greater ordinate than any other control model. + } +}; + diff --git a/forms/qa/integration/forms/FormComponent.java b/forms/qa/integration/forms/FormComponent.java new file mode 100644 index 000000000000..2fa05113ad3d --- /dev/null +++ b/forms/qa/integration/forms/FormComponent.java @@ -0,0 +1,200 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: FormComponent.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.form.XFormsSupplier; +import com.sun.star.container.XNameAccess; +import com.sun.star.container.XIndexAccess; +import com.sun.star.container.XChild; +import com.sun.star.container.XNamed; +import com.sun.star.drawing.XDrawPage; +import com.sun.star.lang.XServiceInfo; + +public class FormComponent +{ + private Object m_component; + private XNameAccess m_nameAccess; + private XIndexAccess m_indexAccess; + private XChild m_child; + private XNamed m_named; + + /* ------------------------------------------------------------------ */ + private FormComponent() + { + m_component = null; + m_nameAccess = null; + m_indexAccess = null; + m_child = null; + m_named = null; + } + + /* ------------------------------------------------------------------ */ + public FormComponent( XDrawPage drawPage ) + { + XFormsSupplier supp = (XFormsSupplier)UnoRuntime.queryInterface( + XFormsSupplier.class, drawPage ); + m_component = supp.getForms(); + + m_nameAccess = (XNameAccess)m_component; + m_indexAccess = (XIndexAccess)UnoRuntime.queryInterface( + XIndexAccess.class, m_component ); + m_child = (XChild)UnoRuntime.queryInterface( + XChild.class, m_component ); + m_named = (XNamed)UnoRuntime.queryInterface( + XNamed.class, m_component ); + } + + /* ------------------------------------------------------------------ */ + public FormComponent( Object element ) + { + m_component = element; + m_nameAccess = (XNameAccess)UnoRuntime.queryInterface( + XNameAccess.class, m_component ); + m_indexAccess = (XIndexAccess)UnoRuntime.queryInterface( + XIndexAccess.class, m_component ); + m_child = (XChild)UnoRuntime.queryInterface( + XChild.class, m_component ); + m_named = (XNamed)UnoRuntime.queryInterface( + XNamed.class, m_component ); + } + + /* ------------------------------------------------------------------ */ + /** Quick access to a given interface of the view + @param aInterfaceClass + the class of the interface which shall be returned + */ + public Object query( Class aInterfaceClass ) + { + return UnoRuntime.queryInterface( aInterfaceClass, m_component ); + } + + /* ------------------------------------------------------------------ */ + public FormComponent getByName( String name ) + { + try + { + if ( m_nameAccess != null ) + return new FormComponent( m_nameAccess.getByName( name ) ); + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + return new FormComponent(); + } + + /* ------------------------------------------------------------------ */ + public String[] getElementNames() + { + if ( m_nameAccess != null ) + return m_nameAccess.getElementNames(); + return new String[]{}; + } + + /* ------------------------------------------------------------------ */ + public boolean hasByName( String name ) + { + if ( m_nameAccess != null ) + return m_nameAccess.hasByName( name ); + return false; + } + + /* ------------------------------------------------------------------ */ + public int getCount() + { + if ( m_indexAccess != null ) + return m_indexAccess.getCount(); + return 0; + } + + /* ------------------------------------------------------------------ */ + public FormComponent getByIndex( int index ) + { + try + { + if ( m_indexAccess != null ) + return new FormComponent( m_indexAccess.getByIndex( index ) ); + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + return new FormComponent(); + } + + /* ------------------------------------------------------------------ */ + public com.sun.star.uno.Type getElementType( ) + { + if ( m_indexAccess != null ) + return m_indexAccess.getElementType(); + else if ( m_nameAccess != null ) + return m_nameAccess.getElementType(); + return new com.sun.star.uno.Type( String.class ); + } + + /* ------------------------------------------------------------------ */ + public boolean hasElements() + { + if ( m_indexAccess != null ) + return m_indexAccess.hasElements(); + else if ( m_nameAccess != null ) + return m_nameAccess.hasElements(); + return false; + } + + /* ------------------------------------------------------------------ */ + public FormComponent getParent() + { + if ( m_child != null ) + return new FormComponent( m_child.getParent() ); + return new FormComponent(); + } + + /* ------------------------------------------------------------------ */ + public String getName() + { + if ( m_named != null ) + return m_named.getName(); + return ""; + } + + /* ------------------------------------------------------------------ */ + public String getImplementationName() + { + XServiceInfo si = (XServiceInfo)UnoRuntime.queryInterface( + XServiceInfo.class, m_component ); + if ( si != null ) + return si.getImplementationName(); + return ""; + } +} diff --git a/forms/qa/integration/forms/FormControlTest.java b/forms/qa/integration/forms/FormControlTest.java new file mode 100644 index 000000000000..91193ff479e5 --- /dev/null +++ b/forms/qa/integration/forms/FormControlTest.java @@ -0,0 +1,954 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: FormControlTest.java,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.awt.XImageProducer; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XNameAccess; +import com.sun.star.form.XFormController; +import com.sun.star.form.XImageProducerSupplier; +import com.sun.star.frame.XDispatch; +import com.sun.star.lang.EventObject; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.sdb.CommandType; +import com.sun.star.sdb.SQLErrorEvent; +import com.sun.star.sdb.XSQLErrorBroadcaster; +import com.sun.star.sdb.XSQLErrorListener; +import com.sun.star.sdbc.XConnection; +import com.sun.star.sdbc.XDataSource; +import com.sun.star.sdbc.XResultSet; +import com.sun.star.sdbc.XResultSetUpdate; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XNamingService; +import com.sun.star.util.URL; +import com.sun.star.util.XCloseable; +import com.sun.star.util.XURLTransformer; +import connectivity.tools.HsqlDatabase; +import java.io.FileOutputStream; + + +public class FormControlTest extends complexlib.ComplexTestCase implements XSQLErrorListener +{ + private static String s_tableName = "CTC_form_controls"; + + private HsqlDatabase m_databaseDocument; + private XDataSource m_dataSource; + private XPropertySet m_dataSourceProps; + private XMultiServiceFactory m_orb; + private DocumentHelper m_document; + private FormLayer m_formLayer; + private XPropertySet m_masterForm; + private XFormController m_masterFormController; + private String m_sImageURL; + private SQLErrorEvent m_mostRecentErrorEvent; + + private final String m_dataSourceName = "integration.forms.FormControlTest"; + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkFirstRow", + "checkInsertRow", + "checkImageControl", + "checkCrossUpdates_checkBox", + "checkCrossUpdates_radioButton", + "checkRowUpdates", + "checkEmptyIsNull" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Database Form Controls Test"; + } + + /* ------------------------------------------------------------------ */ + /// pre-test initialization + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + // ensure that we have a data source to work with, and the required tables + if ( !ensureDataSource() || !ensureTables() ) + { + failed( "could not access the required data source or table therein." ); + return; + } + + // create the document which we work on + createSampleDocument(); + + createImageFile(); + } + + /* ------------------------------------------------------------------ */ + public void checkFirstRow() throws com.sun.star.uno.Exception, java.lang.Exception + { + moveToFirst(); + + // and check the content of the various controls + if ( !checkRadios( (short)1, (short)0, (short)0 ) + || !checkDoubleValue( 1, "ID", "Value" ) + || !checkDoubleValue( 42, "f_integer", "EffectiveValue" ) + || !checkStringValue( "the answer", "f_text", "Text" ) + || !checkDoubleValue( 0.12, "f_decimal", "Value" ) + || !checkIntValue ( 20030922, "f_date", "Date" ) + || !checkIntValue ( 15000000, "f_time", "Time" ) + || !checkIntValue ( 20030923, "f_timestamp_date", "Date" ) + || !checkIntValue ( 17152300, "f_timestamp_time", "Time" ) + || !checkShortValue ( (short)1, "f_tinyint", "State" ) + ) + { + failed( "checking the content of one or more controls on the first row failed (see the log for details)" ); + return; + } + } + + /* ------------------------------------------------------------------ */ + public void checkInsertRow() throws com.sun.star.uno.Exception, java.lang.Exception + { + // move the cursor to the insert row + moveToInsertRow(); + + // and check the content of the various controls + if ( !verifyCleanInsertRow() ) + { + failed( "checking the content of one or more controls on the insert row failed (see the log for details)" ); + return; + } + } + + /* ------------------------------------------------------------------ */ + /// some tests with the image control + public void checkImageControl() throws com.sun.star.uno.Exception, java.lang.Exception + { + // since we did not yet insert any image, the control should not display one ... + moveToFirst(); + if ( !verifyReferenceImage( new byte[0] ) ) + { + failed( "image control failed to display empty image" ); + return; + } + + // check if the image control is able to insert our sample image into the database + // insert an + XPropertySet xImageModel = getControlModel( "f_blob" ); + xImageModel.setPropertyValue( "ImageURL", m_sImageURL ); + + if ( !verifyReferenceImage( getSamplePictureBytes() ) ) + { + failed( "image control does not display the sample image as required" ); + return; + } + + // save the record + saveRecordByUI(); + + // still needs to be the sample image + if ( !verifyReferenceImage( getSamplePictureBytes() ) ) + { + failed( "image control does not, after saving the record, display the sample image as required" ); + return; + } + + // on the next record, the image should be empty + moveToNext(); + if ( !verifyReferenceImage( new byte[0] ) ) + { + failed( "image control failed to display empty image, after coming from a non-empty image" ); + return; + } + + // back to the record where we just inserted the image, it should be our sample image + moveToFirst(); + if ( !verifyReferenceImage( getSamplePictureBytes() ) ) + { + failed( "image control does not, after coming back to the record, display the sample image as required" ); + return; + } + + // okay, now remove the image + xImageModel.setPropertyValue( "ImageURL", new String() ); + if ( !verifyReferenceImage( new byte[0] ) ) + { + failed( "image control failed to remove the image" ); + return; + } + nextRecordByUI(); + previousRecordByUI(); + if ( !verifyReferenceImage( new byte[0] ) ) + { + failed( "image still there after coming back, though we just removed it" ); + return; + } + } + + /* ------------------------------------------------------------------ */ + /** This is both a test for controls which are bound to the same column (they must reflect + * each others updates), and for the immediate updates which need to happen for both check + * boxes and radio buttons: They must commit their content to the underlying column as soon + * as the change is made, *not* only upon explicit commit + */ + public void checkCrossUpdates_checkBox() throws com.sun.star.uno.Exception, java.lang.Exception + { + // move to the first record + moveToFirst(); + if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) + || !checkDoubleValue( 1, "f_tinyint_format", "EffectiveValue" ) + ) + { + failed( "huh? inconsistence in the test!" ); + // we created the sample data in a way that the f_tinyint field should contain a "1" at the first + // record. We already asserted the proper function of the check box in checkFirstRow, so if this + // fails here, the script became inconsistent + return; + } + + XPropertySet checkModel = getControlModel( "f_tinyint" ); + checkModel.setPropertyValue( "State", new Short( (short)0 ) ); + + // setting the state of the check box needs to be reflected in the formatted field immediately + if ( !checkDoubleValue( 0, "f_tinyint_format", "EffectiveValue" ) ) + { + failed( "cross-update failed: updating the check box should result in updating the same-bound formatted field (1)!" ); + return; + } + + // same for the "indetermined" state of the check box + checkModel.setPropertyValue( "State", new Short( (short)2 ) ); + if ( !checkNullValue( "f_tinyint_format", "EffectiveValue" ) ) + { + failed( "cross-update failed: updating the check box should result in updating the same-bound formatted field (2)!" ); + return; + } + + // undo the changes done so far + undoRecordByUI(); + // and see if this is properly reflected in the controls + if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) + || !checkDoubleValue( 1, "f_tinyint_format", "EffectiveValue" ) + ) + { + failed( "either the check box or the formatted field failed to recognize the UNDO!" ); + return; + } + + // the other way round - when changing the formatted field - the change should *not* + // be reflected to the check box, since the formatted field needs an explicit commit + XPropertySet tinyFormattedModel = getControlModel( "f_tinyint_format" ); + m_document.getCurrentView().grabControlFocus( tinyFormattedModel ); + m_formLayer.userTextInput( tinyFormattedModel, "0" ); + if ( !checkShortValue ( (short)1, "f_tinyint", "State" ) + ) + { + failed( "the check box should not be updated here! (did the formatted model commit immediately?)" ); + return; + } + + // set the focus to *any* other control (since we just have it at hand, we use the check box control) + // this should result in the formatted control being committed, and thus in the check box updating + m_document.getCurrentView().grabControlFocus( checkModel ); + if ( !checkShortValue ( (short)0, "f_tinyint", "State" ) + ) + { + failed( "formatted field did not commit (or check box did not update)" ); + return; + } + + // undo the changes done so far, so we leave the document in a clean state for the next test + undoRecordByUI(); + } + + /* ------------------------------------------------------------------ */ + /** very similar to checkCrossUpdates_checkBox - does nearly the same for the radio buttons. See there for more + * explanations. + */ + public void checkCrossUpdates_radioButton() throws com.sun.star.uno.Exception, java.lang.Exception + { + // move to the first record + moveToFirst(); + if ( !checkRadios( (short)1, (short)0, (short)0 ) + || !checkStringValue( "none", "f_text_enum_text", "Text" ) + ) + { + failed( "huh? inconsistence in the test!" ); + return; + } + + XPropertySet radioModel = getRadioModel( "radio_group", "normal" ); + radioModel.setPropertyValue( "State", new Short( (short)1 ) ); + + // setting the state of the radio button needs to be reflected in the formatted field immediately + if ( !checkStringValue( "normal", "f_text_enum_text", "Text" ) ) + { + failed( "cross-update failed: updating the radio button should result in updating the same-bound text field (1)!" ); + return; + } + + // same for the "indetermined" state of the check box + getRadioModel( "radio_group", "important" ).setPropertyValue( "State", new Short( (short)1 ) ); + if ( !checkStringValue( "important", "f_text_enum_text", "Text" ) ) + { + failed( "cross-update failed: updating the radio button should result in updating the same-bound text field (2)!" ); + return; + } + + // undo the changes done so far + undoRecordByUI(); + // and see if this is properly reflected in the controls + if ( !checkRadios( (short)1, (short)0, (short)0 ) + || !checkStringValue( "none", "f_text_enum_text", "Text" ) + ) + { + failed( "either the radio button or the text field failed to recognize the UNDO!" ); + return; + } + + // the other way round - when changing the formatted field - the change should *not* + // be reflected to the check box, since the formatted field needs an explicit commit + XPropertySet textModel = getControlModel( "f_text_enum_text" ); + m_document.getCurrentView().grabControlFocus( textModel ); + m_formLayer.userTextInput( textModel, "normal" ); + if ( !checkRadios( (short)1, (short)0, (short)0 ) + ) + { + failed( "the radio buttons should not be updated here! (did the formatted model commit immediately?)" ); + return; + } + + // set the focus to *any* other control (since we just have it at hand, we use the check box control) + // this should result in the formatted control being committed, and thus in the check box updating + m_document.getCurrentView().grabControlFocus( radioModel ); + if ( !checkRadios( (short)0, (short)1, (short)0 ) + ) + { + failed( "text field did not commit (or radio button did not update)" ); + return; + } + + // undo the changes done so far, so we leave the document in a clean state for the next test + undoRecordByUI(); + } + + /* ------------------------------------------------------------------ */ + /** some tests with updating the table via our controls + */ + public void checkRowUpdates() throws com.sun.star.uno.Exception, java.lang.Exception + { + // start with inserting a new record + moveToInsertRow(); + assure( "insert row not in expected clean state", verifyCleanInsertRow() ); + + userTextInput( "ID", "3", true ); + userTextInput( "f_integer", "729", true ); + userTextInput( "f_text", "test", true ); + userTextInput( "f_decimal", "152343", true ); + userTextInput( "f_date", "31.12.1999", true ); + userTextInput( "f_time", "23:59:59", true ); + + // move to the next row, this should automatically commit the changes we made + nextRecordByUI(); + // and back to the row we just inserted + previousRecordByUI(); + + if ( !checkDoubleValue( 3, "ID", "Value" ) + || !checkDoubleValue( 729, "f_integer", "EffectiveValue" ) + || !checkStringValue( "test", "f_text", "Text" ) + || !checkDoubleValue( 152343, "f_decimal", "Value" ) + || !checkIntValue ( 19991231, "f_date", "Date" ) + || !checkIntValue ( 23595900, "f_time", "Time" ) + ) + { + failed( "the changes we made on the insert row have not been committed" ); + return; + } + + // now change the data, to see if regular updates work, too + userTextInput( "ID", "4", true ); + userTextInput( "f_integer", "618", true ); + userTextInput( "f_text", "yet another stupid, meaningless text", true ); + userTextInput( "f_required_text", "this must not be NULL", true ); + userTextInput( "f_decimal", "4562", true ); + userTextInput( "f_date", "26.03.2004", true ); + userTextInput( "f_time", "17:05:00", true ); + + // move to the next row, this should automatically commit the changes we made + nextRecordByUI(); + // and back to the row we just inserted + previousRecordByUI(); + + if ( !checkDoubleValue( 4, "ID", "Value" ) + || !checkDoubleValue( 618, "f_integer", "EffectiveValue" ) + || !checkStringValue( "yet another stupid, meaningless text", "f_text", "Text" ) + || !checkDoubleValue( 4562, "f_decimal", "Value" ) + || !checkIntValue ( 20040326, "f_date", "Date" ) + || !checkIntValue ( 17050000, "f_time", "Time" ) + ) + { + failed( "the changes we made on the insert row have not been committed" ); + return; + } + + m_document.getCurrentView().grabControlFocus( getControlModel( "ID" ) ); + } + + /* ------------------------------------------------------------------ */ + /** checks the "ConvertEmptyToNull" property behavior of an edit control + * + */ + public void checkEmptyIsNull() throws com.sun.star.uno.Exception, java.lang.Exception + { + // start with inserting a new record + moveToInsertRow(); + assure( "insert row not in expected clean state", verifyCleanInsertRow() ); + + // make an input in any field, but leave the edit control which is bound to a required field + // empty + userTextInput( "ID", "5", true ); + userTextInput( "f_text", "more text", true ); + + // this should *not* fail. Even if we did not input anything into the control bound to the + // f_required_text column, this control's reset (done when moving to the insertion row) is + // expected to write an empty string into its bound column, since its EmptyIsNULL property + // is set to FALSE + // (#i92471#) + m_mostRecentErrorEvent = null; + nextRecordByUI(); + assure( "updating an incomplete record did not work as expected", m_mostRecentErrorEvent == null ); + } + + /* ------------------------------------------------------------------ */ + private boolean verifyCleanInsertRow( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + // and check the content of the various controls + return ( checkRadios( (short)0, (short)0, (short)0 ) + && checkShortValue( (short)2, "f_tinyint", "State" ) + && checkStringValue( "", "f_text", "Text" ) + && checkNullValue( "ID", "Value" ) + && checkNullValue( "f_integer", "EffectiveValue" ) + && checkNullValue( "f_decimal", "Value" ) + ); + } + + /* ------------------------------------------------------------------ */ + /// post-test cleanup + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + + //========================================================================= + /* ------------------------------------------------------------------ */ + private boolean ensureDataSource() throws Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + + XNameAccess databaseContext = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, + m_orb.createInstance( "com.sun.star.sdb.DatabaseContext" ) ); + XNamingService namingService = (XNamingService)UnoRuntime.queryInterface( XNamingService.class, + databaseContext ); + + // revoke the data source, if it previously existed + if ( databaseContext.hasByName( m_dataSourceName ) ) + namingService.revokeObject( m_dataSourceName ); + + // // create a new ODB file, and register it with its URL + m_databaseDocument = new HsqlDatabase( m_orb ); + String documentURL = m_databaseDocument.getDocumentURL(); + namingService.registerObject( m_dataSourceName, databaseContext.getByName( documentURL ) ); + + m_dataSource = (XDataSource)UnoRuntime.queryInterface( XDataSource.class, + databaseContext.getByName( m_dataSourceName ) ); + m_dataSourceProps = dbfTools.queryPropertySet( m_dataSource ); + + XPropertySet dataSourceSettings = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, + m_dataSourceProps.getPropertyValue( "Settings" ) ); + dataSourceSettings.setPropertyValue( "FormsCheckRequiredFields", new Boolean( false ) ); + + return m_dataSource != null; + } + + /* ------------------------------------------------------------------ */ + /** retrives the control model with the given name + */ + private XPropertySet getControlModel( String name ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XNameAccess nameAccess = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, + m_masterForm ); + return (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, + nameAccess.getByName( name ) ); + } + + /* ------------------------------------------------------------------ */ + private void createSampleDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + + m_document = DocumentHelper.blankTextDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + + // insert some controls + XPropertySet xIDField = m_formLayer.insertControlLine( "DatabaseNumericField", "ID", "", 3 ); + m_formLayer.insertControlLine( "DatabaseFormattedField","f_integer", "", 11 ); + m_formLayer.insertControlLine( "DatabaseTextField", "f_text", "", 19 ); + XPropertySet xReqField = m_formLayer.insertControlLine( "DatabaseTextField", "f_required_text", "", 27 ); + m_formLayer.insertControlLine( "DatabaseNumericField", "f_decimal", "", 35 ); + m_formLayer.insertControlLine( "DatabaseDateField", "f_date", "", 43 ); + XPropertySet xTimeField = m_formLayer.insertControlLine( "DatabaseTimeField", "f_time", "", 51 ); + m_formLayer.insertControlLine( "DatabaseDateField", "f_timestamp", "_date", 59 ); + m_formLayer.insertControlLine( "DatabaseTimeField", "f_timestamp", "_time", 67 ); + XPropertySet xImageField = m_formLayer.insertControlLine( "DatabaseImageControl", "f_blob", "", 2, 75, 40 ); + m_formLayer.insertControlLine( "DatabaseTextField", "f_text_enum", "_text", 80, 25, 6 ); + XPropertySet xCheckBox = m_formLayer.insertControlLine( "DatabaseCheckBox", "f_tinyint", "", 80, 33, 6 ); + m_formLayer.insertControlLine( "DatabaseFormattedField","f_tinyint", "_format",80, 41, 6 ); + m_formLayer.insertControlLine( "DatabaseTextField", "dummy", "", 150 ); + + xIDField.setPropertyValue( "DecimalAccuracy", new Short( (short)0 ) ); + xImageField.setPropertyValue( "ScaleImage", new Boolean( true) ); + xImageField.setPropertyValue( "Tabstop", new Boolean( true ) ); + xCheckBox.setPropertyValue( "TriState", new Boolean( true ) ); + xCheckBox.setPropertyValue( "DefaultState", new Short( (short)2 ) ); + xTimeField.setPropertyValue( "TimeFormat", new Short( (short)1 ) ); + xTimeField.setPropertyValue( "TimeMax", new Integer( 23595999 ) ); + xReqField.setPropertyValue( "ConvertEmptyToNull", new Boolean( false ) ); + + // the logical form + m_masterForm = (XPropertySet)dbfTools.getParent( xIDField, XPropertySet.class ); + m_masterForm.setPropertyValue( "DataSourceName", m_dataSourceProps.getPropertyValue( "Name" ) ); + m_masterForm.setPropertyValue( "CommandType", new Integer( CommandType.TABLE ) ); + m_masterForm.setPropertyValue( "Command", s_tableName ); + + insertRadio( 3, "none", "none" ); + insertRadio( 10, "normal", "normal" ); + insertRadio( 17, "important", "important" ); + + // switch the forms into data entry mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + + m_masterFormController = m_document.getCurrentView().getFormController( m_masterForm ); + XSQLErrorBroadcaster errorBroadcaster = (XSQLErrorBroadcaster)UnoRuntime.queryInterface( XSQLErrorBroadcaster.class, + m_masterFormController ); + errorBroadcaster.addSQLErrorListener( this ); + + // set the focus to the ID control + m_document.getCurrentView().grabControlFocus( xIDField ); + } + + /* ------------------------------------------------------------------ */ + private void insertRadio( int nYPos, String label, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet xRadio = m_formLayer.createControlAndShape( "DatabaseRadioButton", 106, nYPos, 25, 6 ); + xRadio.setPropertyValue( "Label", label ); + xRadio.setPropertyValue( "RefValue", refValue ); + xRadio.setPropertyValue( "Name", new String( "radio_group" ) ); + xRadio.setPropertyValue( "DataField", new String( "f_text_enum" ) ); + } + + /* ------------------------------------------------------------------ */ + private String getCreateTableStatement( ) + { + String sCreateTableStatement = "CREATE TABLE \"" + s_tableName + "\" ("; + sCreateTableStatement += "\"ID\" INTEGER NOT NULL PRIMARY KEY,"; + sCreateTableStatement += "\"f_integer\" INTEGER default NULL,"; + sCreateTableStatement += "\"f_text\" VARCHAR(50) default NULL,"; + sCreateTableStatement += "\"f_required_text\" VARCHAR(50) NOT NULL,"; + sCreateTableStatement += "\"f_decimal\" DECIMAL(10,2) default NULL,"; + sCreateTableStatement += "\"f_date\" DATE default NULL,"; + sCreateTableStatement += "\"f_time\" TIME default NULL,"; + sCreateTableStatement += "\"f_timestamp\" DATETIME default NULL,"; + sCreateTableStatement += "\"f_blob\" VARBINARY,"; + sCreateTableStatement += "\"f_text_enum\" VARCHAR(50) default NULL,"; + sCreateTableStatement += "\"f_tinyint\" TINYINT default NULL"; + sCreateTableStatement += ");"; + return sCreateTableStatement; + } + + /* ------------------------------------------------------------------ */ + private String[] getSampleDataValueString( ) throws java.lang.Exception + { + String[] aValues = new String[] { + "1,42,'the answer','foo',0.12,'2003-09-22','15:00:00','2003-09-23 17:15:23',NULL,'none',1", + "2,13,'the question','bar',12.43,'2003-09-24','16:18:00','2003-09-24 08:45:12',NULL,'none',0" + }; + return aValues; + } + + /* ------------------------------------------------------------------ */ + private boolean ensureTables() throws com.sun.star.uno.Exception, java.lang.Exception + { + XConnection xConn = m_dataSource.getConnection( "", "" ); + assure( "could not connect to the data source", xConn != null ); + + // drop the table, if it already exists + if ( !implExecuteStatement( "DROP TABLE \"" + s_tableName + "\" IF EXISTS" ) + || !implExecuteStatement( getCreateTableStatement() ) + ) + { + failed( "could not create the required sample table!" ); + return false; + } + + String sInsertionPrefix = "INSERT INTO \"" + s_tableName + "\" VALUES ("; + String[] aValues = getSampleDataValueString(); + for ( int i=0; i<aValues.length; ++i ) + if ( !implExecuteStatement( sInsertionPrefix + aValues[ i ] + ")" ) ) + { + failed( "could not create the required sample data" ); + return false; + } + + m_databaseDocument.getDataSource().refreshTables( xConn ); + + // do not need the connection anymore + dbfTools.disposeComponent( xConn ); + + return true; + } + + /* ------------------------------------------------------------------ */ + /// checks the 3 radio buttons for the given states + private boolean checkRadios( short stateNone, short stateNormal, short stateImportant ) throws com.sun.star.uno.Exception, java.lang.Exception + { + if ( ((Short)getRadioModel( "radio_group", "none" ).getPropertyValue( "State" )).shortValue() != stateNone ) + { + failed( "wrong value of the 'none' radio button!" ); + } + else if ( ((Short)getRadioModel( "radio_group", "normal" ).getPropertyValue( "State" )).shortValue() != stateNormal ) + { + failed( "wrong value of the 'normal' radio button!" ); + } + else if ( ((Short)getRadioModel( "radio_group", "important" ).getPropertyValue( "State" )).shortValue() != stateImportant ) + { + failed( "wrong value of the 'important' radio button!" ); + } + else + return true; + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkNullValue( String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + Object value = getControlModel( fieldName ).getPropertyValue( propertyName ); + if ( !util.utils.isVoid( value ) ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: <null/>" ); + log.println( " found : " + value.toString() ); + } + else + return true; + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkIntValue( int requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + try + { + if ( fieldName.equals( "f_time" ) ) + // http://bugs.mysql.com/bug.php?id=5681 + return true; + + int currentValue = ((Integer)getControlModel( fieldName ).getPropertyValue( propertyName )).intValue(); + if ( currentValue != requiredValue ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: " + String.valueOf( requiredValue ) ); + log.println( " found : " + String.valueOf( currentValue ) ); + } + else + return true; + } + catch( com.sun.star.uno.Exception e ) + { + log.println( "caught an exception while retrieving property value '" + propertyName + "' of control model '" + fieldName + "'" ); + throw e; + } + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkShortValue( short requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + try + { + short currentValue = ((Short)getControlModel( fieldName ).getPropertyValue( propertyName )).shortValue(); + if ( currentValue != requiredValue ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: " + String.valueOf( requiredValue ) ); + log.println( " found : " + String.valueOf( currentValue ) ); + } + else + return true; + } + catch( com.sun.star.uno.Exception e ) + { + log.println( "caught an exception while retrieving property value '" + propertyName + "' of control model '" + fieldName + "'" ); + throw e; + } + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkDoubleValue( double requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + double currentValue = ((Double)getControlModel( fieldName ).getPropertyValue( propertyName )).doubleValue(); + if ( currentValue != requiredValue ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: " + String.valueOf( requiredValue ) ); + log.println( " found : " + String.valueOf( currentValue ) ); + } + else + return true; + + return false; + } + + /* ------------------------------------------------------------------ */ + private boolean checkStringValue( String requiredValue, String fieldName, String propertyName ) throws com.sun.star.uno.Exception, java.lang.Exception + { + String currentValue = (String)getControlModel( fieldName ).getPropertyValue( propertyName ); + if ( !currentValue.equals( requiredValue ) ) + { + log.println( "wrong value of the " + fieldName + " field!" ); + log.println( " expected: " + requiredValue ); + log.println( " found : " + currentValue ); + } + else + return true; + + return false; + } + + /* ------------------------------------------------------------------ */ + private XPropertySet getRadioModel( String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + return m_formLayer.getRadioModelByRefValue( m_masterForm, name, refValue ); + } + + /* ------------------------------------------------------------------ */ + /** executes the given statement on the given connection + */ + protected boolean implExecuteStatement( String sStatement ) throws java.lang.Exception + { + try + { + m_databaseDocument.executeSQL( sStatement ); + } + catch(com.sun.star.sdbc.SQLException e) + { + System.err.println( e ); + return false; + } + + return true; + } + + /* ------------------------------------------------------------------ */ + /** simulates a user's text input into a control given by model name + */ + private void userTextInput( String modelName, String text, boolean withCommit ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet controlModel = getControlModel( modelName ); + // the form runtime environment (namely the form controller) rely on focus events for recognizing + // control content changes ... + if ( withCommit ) + m_document.getCurrentView().grabControlFocus( controlModel ); + + m_formLayer.userTextInput( controlModel, text ); + + // focus back to a dummy control model so the content of the model we just changed will + // be committed to the underlying database column + if ( withCommit ) + m_document.getCurrentView().grabControlFocus( getControlModel( "dummy" ) ); + } + + /* ------------------------------------------------------------------ */ + private void moveToInsertRow() throws com.sun.star.uno.Exception, java.lang.Exception + { + XResultSetUpdate xResultSet = (XResultSetUpdate)UnoRuntime.queryInterface( XResultSetUpdate.class, m_masterForm ); + xResultSet.moveToInsertRow( ); + } + + /* ------------------------------------------------------------------ */ + private void moveToFirst() throws com.sun.star.uno.Exception, java.lang.Exception + { + XResultSet xResultSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, m_masterForm ); + xResultSet.first( ); + } + + /* ------------------------------------------------------------------ */ + private void moveToNext() throws com.sun.star.uno.Exception, java.lang.Exception + { + XResultSet xResultSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, m_masterForm ); + xResultSet.next( ); + } + + /* ------------------------------------------------------------------ */ + /** simulates pressing a toolbox button with the given URL + */ + private void executeSlot( String slotURL ) throws java.lang.Exception + { + XDispatch xDispatch = m_document.getCurrentView().getDispatcher( slotURL ); + + URL[] url = new URL[] { new URL() }; + url[0].Complete = slotURL; + XURLTransformer xTransformer = (XURLTransformer)UnoRuntime.queryInterface( + XURLTransformer.class, m_orb.createInstance( "com.sun.star.util.URLTransformer" ) ); + xTransformer.parseStrict( url ); + + PropertyValue[] aArgs = new PropertyValue[0]; + xDispatch.dispatch( url[0], aArgs ); + } + + /* ------------------------------------------------------------------ */ + /** undos the changes on the current record, by simulating pressing of the respective toolbox button + */ + private void undoRecordByUI() throws java.lang.Exception + { + executeSlot( ".uno:RecUndo" ); + } + + /* ------------------------------------------------------------------ */ + /** saves the current record, by simulating pressing of the respective toolbox button + */ + private void saveRecordByUI() throws java.lang.Exception + { + executeSlot( ".uno:RecSave" ); + } + + /* ------------------------------------------------------------------ */ + /** moves to the next record, by simulating pressing of the respective toolbox button + */ + private void nextRecordByUI() throws java.lang.Exception + { + executeSlot( ".uno:NextRecord" ); + } + /* ------------------------------------------------------------------ */ + /** moves to the previous record, by simulating pressing of the respective toolbox button + */ + private void previousRecordByUI() throws java.lang.Exception + { + executeSlot( ".uno:PrevRecord" ); + } + + /* ------------------------------------------------------------------ */ + private void createImageFile() throws java.io.IOException + { + m_sImageURL = util.utils.getOfficeTempDir( m_orb ) + "image.gif"; + + FileOutputStream aFile = new FileOutputStream( m_sImageURL ); + aFile.write( getSamplePicture() ); + aFile.close(); + log.println( "created temporary image file: " + m_sImageURL ); + + // for later setting the url at the imaghe control, we need a real URL, no system path + m_sImageURL = util.utils.getOfficeTemp( m_orb ) + "image.gif"; + } + + /* ------------------------------------------------------------------ */ + private byte[] getSamplePicture() + { + byte[] aBytes = new byte[] { + (byte)0x47, (byte)0x49, (byte)0x46, (byte)0x38, (byte)0x39, (byte)0x61, (byte)0x0A, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0xB3, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0x00, (byte)0x00, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF, (byte)0x00, (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xFF, (byte)0xFF, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x2C, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x0A, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x20, (byte)0x10, (byte)0xC8, (byte)0x49, (byte)0x41, (byte)0xB9, (byte)0xF8, (byte)0xCA, + (byte)0x12, (byte)0xBA, (byte)0x2F, (byte)0x5B, (byte)0x30, (byte)0x8C, (byte)0x43, (byte)0x00, (byte)0x5A, (byte)0x22, (byte)0x41, (byte)0x94, (byte)0x27, (byte)0x37, (byte)0xA8, (byte)0x6C, + (byte)0x48, (byte)0xC6, (byte)0xA8, (byte)0xD7, (byte)0xB5, (byte)0x19, (byte)0x56, (byte)0xED, (byte)0x11, (byte)0x00, (byte)0x3B + }; + + return aBytes; + } + + /* ------------------------------------------------------------------ */ + private byte[] getSamplePictureBytes() + { + byte[] aBytes = new byte[] { + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, + (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, + (byte)0x01, (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, (byte)0x04, (byte)0x04, (byte)0x03, (byte)0x01, + (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, (byte)0x04, (byte)0x04, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x03, + (byte)0x03, (byte)0x03, (byte)0x03, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, + (byte)0x00, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x05, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 + }; + return aBytes; + } + + /* ------------------------------------------------------------------ */ + private boolean verifyReferenceImage( byte[] referenceBytes ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet xImageModel = getControlModel( "f_blob" ); + + // check if the image control properly says that there currently is no image on the first record + XImageProducerSupplier xSuppProducer = (XImageProducerSupplier)UnoRuntime.queryInterface( XImageProducerSupplier.class, + xImageModel ); + XImageProducer xProducer = xSuppProducer.getImageProducer(); + + ImageComparison compareImages = new ImageComparison( referenceBytes, this ); + synchronized( this ) + { + xProducer.addConsumer( compareImages ); + xProducer.startProduction(); +// wait(); + } + xProducer.removeConsumer( compareImages ); + + return compareImages.imagesEqual( ); + } + + /* ------------------------------------------------------------------ */ + public void errorOccured( SQLErrorEvent _event ) + { + // just remember for the moment + m_mostRecentErrorEvent = _event; + } + + /* ------------------------------------------------------------------ */ + public void disposing( EventObject _event ) + { + // not interested in + } +} diff --git a/forms/qa/integration/forms/FormLayer.java b/forms/qa/integration/forms/FormLayer.java new file mode 100644 index 000000000000..032ca5e7331a --- /dev/null +++ b/forms/qa/integration/forms/FormLayer.java @@ -0,0 +1,367 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: FormLayer.java,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleEditableText; +import com.sun.star.container.XNameAccess; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XIndexContainer; +import com.sun.star.container.XIndexAccess; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.drawing.XControlShape; +import com.sun.star.drawing.XShapes; +import com.sun.star.awt.Size; +import com.sun.star.awt.Point; +import com.sun.star.awt.XControlModel; +import com.sun.star.text.TextContentAnchorType; +import com.sun.star.drawing.XDrawPage; + +/** + * + * @author fs@openoffice.org + */ +public class FormLayer +{ + private DocumentHelper m_document; + private XDrawPage m_page; + + /* ------------------------------------------------------------------ */ + /** Creates a new instance of FormLayer */ + public FormLayer( DocumentHelper _document ) + { + m_document = _document; + } + + /* ------------------------------------------------------------------ */ + /** sets the page which is to be used for subsequent insertions of controls/shapes + */ + void setInsertPage( int page ) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException + { + m_page = m_document.getDrawPage( page ); + } + + /* ------------------------------------------------------------------ */ + /** creates a control in the document + + <p>Note that <em>control<em> here is an incorrect terminology. What the method really does is + it creates a control shape, together with a control model, and inserts them into the document model. + This will result in every view to this document creating a control described by the model-shape pair. + </p> + + @param sFormComponentService + the service name of the form component to create, e.g. "TextField" + @param nXPos + the abscissa of the position of the newly inserted shape + @param nXPos + the ordinate of the position of the newly inserted shape + @param nWidth + the width of the newly inserted shape + @param nHeight + the height of the newly inserted shape + @param xParentForm + the form to use as parent for the newly create form component. May be null, in this case + a default parent is chosen by the implementation + @return + the property access to the control's model + */ + public XPropertySet createControlAndShape( String sFormComponentService, int nXPos, + int nYPos, int nWidth, int nHeight, XIndexContainer xParentForm ) throws java.lang.Exception + { + // let the document create a shape + XMultiServiceFactory xDocAsFactory = (XMultiServiceFactory)UnoRuntime.queryInterface( + XMultiServiceFactory.class, m_document.getDocument() ); + XControlShape xShape = (XControlShape)UnoRuntime.queryInterface( XControlShape.class, + xDocAsFactory.createInstance( "com.sun.star.drawing.ControlShape" ) ); + + // position and size of the shape + xShape.setSize( new Size( nWidth * 100, nHeight * 100 ) ); + xShape.setPosition( new Point( nXPos * 100, nYPos * 100 ) ); + + // adjust the anchor so that the control is tied to the page + XPropertySet xShapeProps = dbfTools.queryPropertySet( xShape ); + TextContentAnchorType eAnchorType = TextContentAnchorType.AT_PARAGRAPH; + xShapeProps.setPropertyValue( "AnchorType", eAnchorType ); + + // create the form component (the model of a form control) + String sQualifiedComponentName = "com.sun.star.form.component." + sFormComponentService; + XControlModel xModel = (XControlModel)UnoRuntime.queryInterface( XControlModel.class, + m_document.getOrb().createInstance( sQualifiedComponentName ) ); + + // insert the model into the form component hierarchy, if the caller gave us a location + if ( null != xParentForm ) + { + xParentForm.insertByIndex( xParentForm.getCount(), xModel ); + } + + // knitt them + xShape.setControl( xModel ); + + // add the shape to the shapes collection of the document + XDrawPage pageWhereToInsert = ( m_page != null ) ? m_page : m_document.getMainDrawPage(); + + XShapes xDocShapes = (XShapes)UnoRuntime.queryInterface( XShapes.class, pageWhereToInsert ); + xDocShapes.add( xShape ); + + // and outta here with the XPropertySet interface of the model + XPropertySet xModelProps = dbfTools.queryPropertySet( xModel ); + return xModelProps; + } + + /* ------------------------------------------------------------------ */ + /** creates a control in the document + + <p>Note that <em>control<em> here is an incorrect terminology. What the method really does is + it creates a control shape, together with a control model, and inserts them into the document model. + This will result in every view to this document creating a control described by the model-shape pair. + </p> + + @param sFormComponentService + the service name of the form component to create, e.g. "TextField" + @param nXPos + the abscissa of the position of the newly inserted shape + @param nXPos + the ordinate of the position of the newly inserted shape + @param nWidth + the width of the newly inserted shape + @param nHeight + the height of the newly inserted shape + @return + the property access to the control's model + */ + public XPropertySet createControlAndShape( String sFormComponentService, int nXPos, + int nYPos, int nWidth, int nHeight ) throws java.lang.Exception + { + return createControlAndShape( sFormComponentService, nXPos, nYPos, nWidth, nHeight, null ); + } + + /** creates a pair of controls, namely a label control, and another control labeled by it + * + * @param _formComponentServiceName + * the service name for the control which is not the label control + * @param _label + * the label to be shown in the label control + * @param _xPos + * the horizontal position of the control pair + * @param _yPos + * the vertical position of the control pair + * @param _height + * the height of the control which is not the label control + * @return + * the model of the control which is not the label control + * @throws java.lang.Exception + */ + public XPropertySet createLabeledControl( String _formComponentServiceName, String _label, int _xPos, + int _yPos, int _height ) + throws java.lang.Exception + { + // insert the label control + XPropertySet label = createControlAndShape( "FixedText", _xPos, _yPos, 25, 6 ); + label.setPropertyValue( "Label", _label ); + + // insert the text field control + XPropertySet field = createControlAndShape( _formComponentServiceName, + _xPos + 25, _yPos, 40, _height ); + // knit it to it's label component + field.setPropertyValue( "LabelControl", label ); + + // names + label.setPropertyValue( "Name", _label + "_Label" ); + field.setPropertyValue( "Name", _label ); + + return field; + } + + /* ------------------------------------------------------------------ */ + /** creates a line of controls, consisting of a label and a field for data input. + + <p>In opposite to the second form of this method, here the height of the field, + as well as the abscissa of the label, are under the control of the caller.</p> + + @param sControlType + specifies the type of the data input control + @param sFieldName + specifies the field name the text field should be bound to + @param sControlNamePostfix + specifies a postfix to append to the logical control names + @param nYPos + specifies the Y position of the line to start at + @param nHeight + the height of the field + @return + the control model of the created data input field + */ + public XPropertySet insertControlLine( String sControlType, String sFieldName, String sControlNamePostfix, + int nXPos, int nYPos, int nHeight ) + throws java.lang.Exception + { + // insert the label control + XPropertySet xLabelModel = createControlAndShape( "FixedText", nXPos, nYPos, 25, 6 ); + xLabelModel.setPropertyValue( "Label", sFieldName ); + + // insert the text field control + XPropertySet xFieldModel = createControlAndShape( sControlType, nXPos + 26, nYPos, 40, nHeight ); + xFieldModel.setPropertyValue( "DataField", sFieldName ); + // knit it to it's label component + xFieldModel.setPropertyValue( "LabelControl", xLabelModel ); + + // some names, so later on we can find them + xLabelModel.setPropertyValue( "Name", sFieldName + sControlNamePostfix + "_Label" ); + xFieldModel.setPropertyValue( "Name", sFieldName + sControlNamePostfix ); + + return xFieldModel; + } + + /* ------------------------------------------------------------------ */ + /** creates a line of controls, consisting of a label and a field for data input. + + @param sControlType + specifies the type of the data input control + @param sFieldName + specifies the field name the text field should be bound to + @param nYPos + specifies the Y position of the line to start at + @return + the control model of the created data input field + */ + public XPropertySet insertControlLine( String sControlType, String sFieldName, String sControlNamePostfix, int nYPos ) + throws java.lang.Exception + { + return insertControlLine( sControlType, sFieldName, sControlNamePostfix, 2, nYPos, 6 ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the radio button model with the given name and the given ref value + * @param form + * the parent form of the radio button model to find + * @param name + * the name of the radio button + * @param refValue + * the reference value of the radio button + */ + public XPropertySet getRadioModelByRefValue( XPropertySet form, String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XIndexAccess indexAccess = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, + form ); + + for ( int i=0; i<indexAccess.getCount(); ++i ) + { + XPropertySet control = dbfTools.queryPropertySet( indexAccess.getByIndex( i ) ); + + if ( ((String)control.getPropertyValue( "Name" )).equals( name ) ) + if ( ((String)control.getPropertyValue( "RefValue" )).equals( refValue ) ) + return control; + } + return null; + } + + /* ------------------------------------------------------------------ */ + /** retrieves the radio button model with the given name and the given tag + * @param form + * the parent form of the radio button model to find + * @param name + * the name of the radio button + * @param refValue + * the tag of the radio button + */ + public XPropertySet getRadioModelByTag( XPropertySet form, String name, String tag ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XIndexAccess indexAccess = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, + form ); + + for ( int i=0; i<indexAccess.getCount(); ++i ) + { + XPropertySet control = dbfTools.queryPropertySet( indexAccess.getByIndex( i ) ); + + if ( ((String)control.getPropertyValue( "Name" )).equals( name ) ) + if ( ((String)control.getPropertyValue( "Tag" )).equals( tag ) ) + return control; + } + return null; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a control model with a given (integer) access path + */ + public XPropertySet getControlModel( int[] _accessPath ) throws com.sun.star.uno.Exception + { + XIndexAccess indexAcc = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, + m_document.getFormComponentTreeRoot() ); + XPropertySet controlModel = null; + int i=0; + while ( ( indexAcc != null ) && ( i < _accessPath.length ) ) + { + controlModel = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, + indexAcc.getByIndex( _accessPath[i] ) ); + indexAcc = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, + controlModel ); + ++i; + } + return controlModel; + } + + /* ------------------------------------------------------------------ */ + /** retrieves a control model with a given (string) access path + */ + public XPropertySet getControlModel( String[] _accessPath ) throws com.sun.star.uno.Exception + { + XNameAccess nameAcc = m_document.getFormComponentTreeRoot(); + XPropertySet controlModel = null; + int i=0; + while ( ( nameAcc != null ) && ( i < _accessPath.length ) ) + { + controlModel = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, + nameAcc.getByName( _accessPath[i] ) ); + nameAcc = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, + controlModel ); + ++i; + } + return controlModel; + } + + /* ------------------------------------------------------------------ */ + /** simulates a user's text input into a control given by control model + */ + public void userTextInput( XPropertySet controlModel, String text ) throws com.sun.star.uno.Exception, java.lang.Exception + { + // we will *not* simply set the value property at the model. This is not the same as + // doing a user input, as the latter will trigger a lot of notifications, which the forms runtime environment + // (namely the FormController) relies on to notice that the control changed. + // Instead, we use the Accessibility interfaces of the control to simulate text input + XAccessible formattedAccessible = (XAccessible)UnoRuntime.queryInterface( XAccessible.class, + m_document.getCurrentView().getControl( controlModel ) + ); + XAccessibleEditableText textAccess = (XAccessibleEditableText)UnoRuntime.queryInterface( XAccessibleEditableText.class, + formattedAccessible.getAccessibleContext() ); + textAccess.setText( text ); + } +} diff --git a/forms/qa/integration/forms/FormPropertyBags.java b/forms/qa/integration/forms/FormPropertyBags.java new file mode 100644 index 000000000000..4adb04796030 --- /dev/null +++ b/forms/qa/integration/forms/FormPropertyBags.java @@ -0,0 +1,215 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: FormPropertyBags.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.beans.PropertyChangeEvent; +import com.sun.star.beans.PropertyExistException; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertyChangeListener; +import com.sun.star.beans.XPropertyContainer; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.frame.XStorable; +import com.sun.star.lang.EventObject; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.lang.XMultiServiceFactory; + +import com.sun.star.util.XCloseable; + +import integration.forms.DocumentHelper; + +public class FormPropertyBags extends complexlib.ComplexTestCase implements XPropertyChangeListener +{ + private DocumentHelper m_document; + private FormLayer m_formLayer; + private XMultiServiceFactory m_orb; + + private PropertyChangeEvent m_propertyChangeEvent; + + /** Creates a new instance of FormPropertyBags */ + public FormPropertyBags() + { + m_propertyChangeEvent = new PropertyChangeEvent(); + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkSomething" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Component Property Bag Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + m_document = DocumentHelper.blankTextDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + } + + /* ------------------------------------------------------------------ */ + private void impl_closeDoc() throws com.sun.star.uno.Exception + { + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + impl_closeDoc(); + } + + /* ------------------------------------------------------------------ */ + public void checkSomething() throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet textFieldModel = m_formLayer.createControlAndShape( "DatabaseTextField", 10, 10, 25, 6 ); + + // check whether adding new properties is successful + XPropertyContainer propContainer = (XPropertyContainer)UnoRuntime.queryInterface( + XPropertyContainer.class, textFieldModel ); + assure("XPropertyContainer not supported!", propContainer != null ); + + propContainer.addProperty( "SomeBoundText", PropertyAttribute.BOUND, "InitialBoundText" ); + propContainer.addProperty( "SomeTransientText", PropertyAttribute.TRANSIENT, "InitialTransientProperty" ); + propContainer.addProperty( "SomeReadonlyText", PropertyAttribute.READONLY, "InitialReadonlyText" ); + propContainer.addProperty( "SomeNumericValue", PropertyAttribute.BOUND, new Integer( 42 ) ); + + XPropertySetInfo propertyInfo = textFieldModel.getPropertySetInfo(); + assure( "Per service definition, dynamic properties are expected to be forced to be removeable", + ( propertyInfo.getPropertyByName("SomeBoundText").Attributes & PropertyAttribute.REMOVEABLE ) != 0 ); + + // a second addition of a property with an existent name should be rejected + boolean caughtExpected = false; + try { propContainer.addProperty( "SomeBoundText", PropertyAttribute.BOUND, "InitialBoundText" ); } + catch( PropertyExistException e ) { caughtExpected = true; } + catch( Exception e ) { } + assure( "repeated additions of a property with the same name should be rejected", + caughtExpected ); + + // check whether the properties are bound as expected + impl_checkPropertyValueNotification( textFieldModel ); + + // check property value persistence + impl_checkPropertyPersistence(); + } + + /* ------------------------------------------------------------------ */ + private void impl_checkPropertyValueNotification( XPropertySet _controlModel ) throws com.sun.star.uno.Exception + { + _controlModel.addPropertyChangeListener( "", this ); + + _controlModel.setPropertyValue( "SomeBoundText", "ChangedBoundText" ); + assure( "changes in the bound property are not properly notified", + m_propertyChangeEvent.PropertyName.equals( "SomeBoundText" ) + && m_propertyChangeEvent.OldValue.equals( "InitialBoundText" ) + && m_propertyChangeEvent.NewValue.equals( "ChangedBoundText" ) ); + + m_propertyChangeEvent = null; + _controlModel.setPropertyValue( "SomeTransientText", "ChangedTransientText" ); + assure( "changes in non-bound properties should not be notified", + m_propertyChangeEvent == null ); + + boolean caughtExpected = false; + try { _controlModel.setPropertyValue( "SomeReadonlyText", "ChangedReadonlyText" ); } + catch( PropertyVetoException e ) { caughtExpected = true; } + catch( Exception e ) { } + assure( "trying to write a read-only property did not give the expected result", + caughtExpected ); + + _controlModel.removePropertyChangeListener( "", this ); + } + + /* ------------------------------------------------------------------ */ + private void impl_checkPropertyPersistence() throws com.sun.star.uno.Exception + { + // store the document + XStorable store = (XStorable)UnoRuntime.queryInterface( XStorable.class, + m_document.getDocument() ); + String documentURL = util.utils.getOfficeTemp( m_orb ) + "document.odt"; + PropertyValue[] storeArguments = new PropertyValue[] { new PropertyValue() }; + storeArguments[0].Name = "FilterName"; + storeArguments[0].Value = "writer8"; + store.storeAsURL( documentURL, storeArguments ); + + // close and re-load it + impl_closeDoc(); + + m_document = DocumentHelper.loadDocument( m_orb, documentURL ); + m_formLayer = new FormLayer( m_document ); + + XPropertySet textFieldModel = m_formLayer.getControlModel( new int[] { 0, 0 } ); + + // all persistent properties should have the expected values + assure( "persistent properties did not survive reload (1)!", ((String)textFieldModel.getPropertyValue( "SomeBoundText" )).equals( "ChangedBoundText" ) ); + assure( "persistent properties did not survive reload (2)!", ((String)textFieldModel.getPropertyValue( "SomeReadonlyText" )).equals( "InitialReadonlyText" ) ); +// assure( "persistent properties did not survive reload (3)!", ((Integer)textFieldModel.getPropertyValue( "SomeNumericValue" )).equals( new Integer( 42 ) ) ); + // cannot check this until the types really survice - at the moment, integers are converted to doubles ... + + // the transient property should not have survived + boolean caughtExpected = false; + try { textFieldModel.getPropertyValue( "SomeTransientText" ); } + catch( UnknownPropertyException e ) { caughtExpected = true; } + assure( "transient property did survive reload!", caughtExpected ); + + // There would be more things to check. + // For instance, it would be desirable of the property attributes would have survived + // the reload, and the property defaults (XPropertyState). + // However, the file format currently doesn't allow for this, so those information + // is lost when saving the document. + } + + /* ------------------------------------------------------------------ */ + public void propertyChange(PropertyChangeEvent _propertyChangeEvent) + { + m_propertyChangeEvent = _propertyChangeEvent; + } + + /* ------------------------------------------------------------------ */ + public void disposing(EventObject eventObject) + { + // not interested in + } +} diff --git a/forms/qa/integration/forms/ImageComparison.java b/forms/qa/integration/forms/ImageComparison.java new file mode 100644 index 000000000000..87f2c82f928d --- /dev/null +++ b/forms/qa/integration/forms/ImageComparison.java @@ -0,0 +1,73 @@ +/* + * ImageComparison.java + * + * Created on 23. September 2003, 17:40 + */ + +package integration.forms; + +/** + * + * @author fs93730 + */ +public final class ImageComparison implements com.sun.star.awt.XImageConsumer +{ + + private byte[] m_referenceBytes; + private int m_referencePosition; + private java.io.FileOutputStream m_stream; + private Object m_notifyDone; + + public boolean imagesEqual( ) + { + return m_referencePosition == m_referenceBytes.length; + } + + /** Creates a new instance of ImageComparison */ + public ImageComparison( byte[] referenceBytes, Object toNotify ) + { + m_referenceBytes = referenceBytes; + m_referencePosition = 0; + m_notifyDone = toNotify; + } + + public void complete(int param, com.sun.star.awt.XImageProducer xImageProducer) + { + synchronized( m_notifyDone ) + { + m_notifyDone.notify(); + } + } + + public void init(int param, int param1) + { + } + + public void setColorModel(short param, int[] values, int param2, int param3, int param4, int param5) + { + } + + public void setPixelsByBytes(int param, int param1, int param2, int param3, byte[] values, int param5, int param6) + { + if ( m_referencePosition == -1 ) + // already failed + return; + + int i = 0; + while ( ( m_referencePosition < m_referenceBytes.length ) && ( i < values.length ) ) + { + if ( m_referenceBytes[ m_referencePosition ] != values[ i ] ) + { + m_referencePosition = -1; + break; + } + ++i; + ++m_referencePosition; + } + } + + public void setPixelsByLongs(int param, int param1, int param2, int param3, int[] values, int param5, int param6) + { + } + +} diff --git a/forms/qa/integration/forms/ListSelection.java b/forms/qa/integration/forms/ListSelection.java new file mode 100644 index 000000000000..110380cc660f --- /dev/null +++ b/forms/qa/integration/forms/ListSelection.java @@ -0,0 +1,369 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ListSelection.java,v $ + * $Revision: 1.7.44.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.beans.XPropertySet; +import com.sun.star.sheet.XSpreadsheet; +import com.sun.star.sheet.XSpreadsheets; +import com.sun.star.sheet.XSpreadsheetView; +import com.sun.star.container.XNamed; +import com.sun.star.container.XNameContainer; +import com.sun.star.container.XIndexContainer; +import com.sun.star.drawing.XDrawPageSupplier; +import com.sun.star.awt.XControl; +import com.sun.star.awt.XControlModel; +import com.sun.star.awt.XListBox; +import com.sun.star.script.XLibraryContainer; +import com.sun.star.script.XEventAttacherManager; +import com.sun.star.script.ScriptEventDescriptor; +import com.sun.star.accessibility.XAccessible; +import com.sun.star.accessibility.XAccessibleContext; +import com.sun.star.accessibility.XAccessibleSelection; +import com.sun.star.accessibility.XAccessibleAction; +import com.sun.star.frame.XStorable; + +import integration.forms.DocumentHelper; + +public class ListSelection extends integration.forms.TestCase implements com.sun.star.awt.XItemListener +{ + private final static boolean m_useJavaCallbacks = false; + + /** Creates a new instance of ListSelection */ + public ListSelection() + { + super( DocumentType.CALC ); + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkUserListSelection" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Control List Selection Test"; + } + + /* ------------------------------------------------------------------ */ + public void checkUserListSelection() throws com.sun.star.uno.Exception, java.lang.Exception + { + boolean interactiveTest = param.getBool( "Interactive" ); + + if ( interactiveTest ) + { + prepareDocument(); + waitForUserInput(); + closeDocumentByUI(); + } + else + { + int runs = param.getInt( "Runs" ); + if ( runs == 0 ) + runs = 10; + + for ( int i = 0; i < runs; ++i ) + { + log.println( "Round " + ( i + 1 ) + " of " + runs ); + prepareDocument(); + clickTheListBox(); + synchronized( this ) { this.wait( 1000 ); } + closeDocument(); + } + } + } + + /* ------------------------------------------------------------------ */ + final protected void clickTheListBox() + { + try + { + final int runs = 10; + java.util.Random generator = new java.util.Random(); + for ( int i = 0; i < runs; ++i ) + { + // obtain the active sheet + XSpreadsheetView view = (XSpreadsheetView)m_document.getCurrentView().query( XSpreadsheetView.class ); + XSpreadsheet activeSheet = view.getActiveSheet(); + + // Accessibility access to the list box control in this sheet + XAccessible accessibleListBox = (XAccessible)UnoRuntime.queryInterface( + XAccessible.class, getListBoxControl( activeSheet ) ); + XAccessibleContext context = accessibleListBox.getAccessibleContext(); + + // open the popup of the list box (not really necessary, but to better + // simlate user action ...) +/* XAccessibleAction listBoxActions = (XAccessibleAction)UnoRuntime.queryInterface( + XAccessibleAction.class, context ); + listBoxActions.doAccessibleAction( 0 ); +*/ + + // the first "accessible child" of a list box is its list + XAccessibleSelection accessibleList = (XAccessibleSelection)UnoRuntime.queryInterface( + XAccessibleSelection.class, context.getAccessibleChild( 1 ) ); + + int selectPosition = generator.nextInt( 5 ); + String selectSheetName = getListBoxControl( activeSheet ).getItem( (short)selectPosition ); + accessibleList.selectAccessibleChild( selectPosition ); + try + { + synchronized( this ) + { + this.wait( 500 ); + } + } + catch( java.lang.InterruptedException e ) { } + + XNamed sheetName = (XNamed)UnoRuntime.queryInterface( XNamed.class, view.getActiveSheet() ); + assure( "sheet was not selected as expected!", sheetName.getName().equals( selectSheetName ) ); + } + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + final protected void createListenerScript() + { + try + { + XPropertySet docProps = dbfTools.queryPropertySet( m_document.getDocument() ); + XLibraryContainer basicLibs = (XLibraryContainer)UnoRuntime.queryInterface( + XLibraryContainer.class, docProps.getPropertyValue( "BasicLibraries" ) ); + XNameContainer basicLib = basicLibs.createLibrary( "default" ); + + String sListSelectionScript = + "Option Explicit\n" + + "\n" + + "Sub onListBoxSelected( oEvent as Object )\n" + + " Dim oView as Object\n" + + " Dim oSheet as Object\n" + + " Dim oSheets as Object\n" + + "\n" + + " Dim oControlModel as Object\n" + + " Dim sSheet as String\n" + + "\n" + + " if ( oEvent.Selected <> 65535 ) Then\n" + + " oControlModel = oEvent.Source.Model\n" + + " sSheet = oControlModel.StringItemList( oEvent.Selected )\n" + + "\n" + + " oSheets = thisComponent.Sheets\n" + + " oSheet = oSheets.getByName(sSheet)\n" + + "\n" + + " oView = thisComponent.CurrentController\n" + + " oView.setActiveSheet( oSheet )\n" + + " End If\n" + + "End Sub\n" + + "\n" + + "Sub onButtonClicked\n" + + " MsgBox \"clicked\"\n" + + "End Sub\n"; + + basicLib.insertByName( "callbacks", sListSelectionScript ); + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + final protected void assignCallbackScript( XPropertySet controlModel, String interfaceName, String interfaceMethod, String scriptCode ) + { + try + { + XIndexContainer parentForm = (XIndexContainer)dbfTools.getParent( controlModel, XIndexContainer.class ); + + XEventAttacherManager manager = (XEventAttacherManager)UnoRuntime.queryInterface( + XEventAttacherManager.class, parentForm ); + + int containerPosition = -1; + for ( int i = 0; i < parentForm.getCount(); ++i ) + { + XPropertySet child = dbfTools.queryPropertySet( parentForm.getByIndex( i ) ); + if ( child.equals( controlModel ) ) + { + containerPosition = i; + break; + } + } + manager.registerScriptEvent( containerPosition, new ScriptEventDescriptor( + interfaceName, + interfaceMethod, + "", + "StarBasic", + scriptCode + ) ); + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.prepareDocument(); + if ( !m_useJavaCallbacks ) + createListenerScript(); + + SpreadsheetDocument document = (SpreadsheetDocument)m_document; + XSpreadsheets sheets = document.getSheets(); + + // delete all sheets except one + String[] sheetNames = sheets.getElementNames(); + for ( short i = 1; i < sheetNames.length; ++i ) + sheets.removeByName( sheetNames[ i ] ); + + // need 5 sheets + String[] newSheetNames = new String[] { "first", "second", "third", "forth", "fifth" }; + + // give the first one the right name + XNamed sheet = (XNamed)UnoRuntime.queryInterface( XNamed.class, + sheets.getByName( sheetNames[ 0 ] ) + ); + sheet.setName( newSheetNames[ 0 ] ); + + // add some dummy buttons + for ( int i = 0; i < 4; ++i ) + { + XPropertySet buttonModel = m_formLayer.createControlAndShape( "CommandButton", 10, 10 + i * 10, 30, 8 ); + assignCallbackScript( buttonModel, "XActionListener", "actionPerformed", "document:default.callbacks.onButtonClicked" ); + } + + // and a list box + XPropertySet listBox = m_formLayer.createControlAndShape( "ListBox", 50, 10, 40, 6 ); + listBox.setPropertyValue( "Dropdown", new Boolean( true ) ); + listBox.setPropertyValue( "StringItemList", newSheetNames ); + listBox.setPropertyValue( "Name", "ListBox" ); + + if ( !m_useJavaCallbacks ) + assignCallbackScript( listBox, "XItemListener", "itemStateChanged", "document:default.callbacks.onListBoxSelected" ); + + // clone this sheet + for ( short i = 1; i < newSheetNames.length; ++i ) + sheets.copyByName( newSheetNames[0], newSheetNames[i], (short)i ); + + // switch the thing to alive mode + m_document.getCurrentView().toggleFormDesignMode(); + + // add to the list box control as item listener + if ( m_useJavaCallbacks ) + { + XControl control = m_document.getCurrentView().getControl( listBox ); + XListBox listBoxControl = (XListBox)UnoRuntime.queryInterface( + XListBox.class, control ); + listBoxControl.addItemListener( this ); + } + + try + { + XStorable storable = (XStorable)m_document.query( XStorable.class ); + java.io.File testFile = java.io.File.createTempFile( getTestObjectName(),".ods"); + storable.storeAsURL( testFile.getAbsoluteFile().toURL().toString(), new com.sun.star.beans.PropertyValue[]{} ); + testFile.deleteOnExit(); + } + catch( java.lang.Throwable e ) + { + e.printStackTrace(); + } + } + + /* ------------------------------------------------------------------ */ + protected XControlModel getListBoxModel( XSpreadsheet sheet ) + { + XDrawPageSupplier suppPage = (XDrawPageSupplier)UnoRuntime.queryInterface( + XDrawPageSupplier.class, sheet ); + FormComponent formsRoot = new FormComponent( suppPage.getDrawPage() ); + XControlModel listBoxModel = (XControlModel)formsRoot.getByIndex( 0 ). + getByName( "ListBox" ).query( XControlModel.class ); + return listBoxModel; + } + + /* ------------------------------------------------------------------ */ + protected XListBox getListBoxControl( XSpreadsheet sheet ) throws com.sun.star.uno.Exception + { + return (XListBox)UnoRuntime.queryInterface( + XListBox.class, m_document.getCurrentView().getControl( getListBoxModel( sheet ) ) ); + } + + /* ------------------------------------------------------------------ */ + public void itemStateChanged( com.sun.star.awt.ItemEvent event ) throws com.sun.star.uno.RuntimeException + { + try + { + // get the selected string + XControl control = (XControl)UnoRuntime.queryInterface( XControl.class, + event.Source ); + XPropertySet model = dbfTools.queryPropertySet( control.getModel() ); + String[] entries = (String[])model.getPropertyValue( "StringItemList" ); + String selectedEntry = entries[ event.Selected ]; + + // activate this sheet + SpreadsheetDocument document = (SpreadsheetDocument)m_document; + XSpreadsheet sheet = (XSpreadsheet)UnoRuntime.queryInterface( + XSpreadsheet.class, document.getSheets().getByName( selectedEntry ) ); + XSpreadsheetView view = (XSpreadsheetView)m_document.getCurrentView().query( XSpreadsheetView.class ); + view.setActiveSheet( sheet ); + + if ( m_useJavaCallbacks ) + { + // after we switched to another sheet, we need to register at its list box + // control, again. The reason is that controls exist as long as their sheet is active. + XListBox listBoxControl = getListBoxControl( sheet ); + listBoxControl.addItemListener( this ); + + // in the list box of this new sheet, select its name. Everything else + // is way too confusing + listBoxControl.selectItem( selectedEntry, true ); + // don't do it. It deadlocks :( + } + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + public void disposing( com.sun.star.lang.EventObject rEvent ) throws com.sun.star.uno.RuntimeException + { + // not interested in by now + } + } diff --git a/forms/qa/integration/forms/ListSelection.props b/forms/qa/integration/forms/ListSelection.props new file mode 100644 index 000000000000..4464e320561c --- /dev/null +++ b/forms/qa/integration/forms/ListSelection.props @@ -0,0 +1,3 @@ +ThreadTimeOut=600000 +Interactive=false +Runs=5 diff --git a/forms/qa/integration/forms/ListSelectionValidator.java b/forms/qa/integration/forms/ListSelectionValidator.java new file mode 100644 index 000000000000..92535240b0f4 --- /dev/null +++ b/forms/qa/integration/forms/ListSelectionValidator.java @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ListSelectionValidator.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +/** + * + * @author fs@openoffice.org + */ +public class ListSelectionValidator extends integration.forms.ControlValidator +{ + /** Creates a new instance of ListSelectionValidator */ + public ListSelectionValidator() + { + } + + public String explainInvalid( Object Value ) + { + try + { + short[] selectionIndexes = (short[])Value; + if ( selectionIndexes.length > 2 ) + return "please 2 entries, at most"; + } + catch( java.lang.Exception e ) + { + return "oops. What's this?"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + short[] selectionIndexes = (short[])Value; + if ( selectionIndexes.length > 2 ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + } + return false; + } + +} diff --git a/forms/qa/integration/forms/MasterDetailForms.java b/forms/qa/integration/forms/MasterDetailForms.java new file mode 100644 index 000000000000..2b83a11dd223 --- /dev/null +++ b/forms/qa/integration/forms/MasterDetailForms.java @@ -0,0 +1,266 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: MasterDetailForms.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import java.lang.reflect.Method; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.beans.*; +import com.sun.star.container.XNameContainer; +import com.sun.star.form.XLoadable; +import com.sun.star.sdbc.*; + +import connectivity.tools.*; + + +public class MasterDetailForms extends complexlib.ComplexTestCase implements com.sun.star.form.XLoadListener +{ + private XMultiServiceFactory m_orb; + + private HsqlDatabase m_databaseDocument; + private XPropertySet m_masterForm; + private XPropertySet m_detailForm; + private XResultSet m_masterSet; + private XResultSet m_detailSet; + private XRow m_masterRow; + private XRow m_detailRow; + + private Object m_waitForLoad; + private boolean m_loaded; + + /** Creates a new instance of ValueBinding */ + public MasterDetailForms() + { + m_loaded = false; + m_waitForLoad = new Object(); + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkMultipleKeys" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Control Spreadsheet Cell Binding Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + m_databaseDocument = new HsqlDatabase( m_orb ); + createTableStructure(); + createForms(); + } + + /* ------------------------------------------------------------------ */ + /** creates the table structure needed for the test + */ + private void createTableStructure() throws SQLException + { + HsqlColumnDescriptor[] masterColumns = { + new HsqlColumnDescriptor( "ID1", "INTEGER", HsqlColumnDescriptor.PRIMARY ), + new HsqlColumnDescriptor( "ID2", "INTEGER", HsqlColumnDescriptor.PRIMARY ), + new HsqlColumnDescriptor( "value", "VARCHAR(50)" ), + }; + HsqlColumnDescriptor[] detailColumns = { + new HsqlColumnDescriptor( "ID", "INTEGER", HsqlColumnDescriptor.PRIMARY ), + new HsqlColumnDescriptor( "FK_ID1", "INTEGER", HsqlColumnDescriptor.REQUIRED, "master", "ID1" ), + new HsqlColumnDescriptor( "FK_ID2", "INTEGER", HsqlColumnDescriptor.REQUIRED, "master", "ID2" ), + new HsqlColumnDescriptor( "name", "VARCHAR(50)" ), + }; + m_databaseDocument.createTable( new HsqlTableDescriptor( "master", masterColumns ) ); + m_databaseDocument.createTable( new HsqlTableDescriptor( "detail", detailColumns ) ); + + m_databaseDocument.executeSQL( "INSERT INTO \"master\" VALUES ( 1, 1, 'First Record' )" ); + m_databaseDocument.executeSQL( "INSERT INTO \"master\" VALUES ( 1, 2, 'Second Record' )" ); + m_databaseDocument.executeSQL( "INSERT INTO \"detail\" VALUES ( 1, 1, 1, 'record 1.1 (1)')"); + m_databaseDocument.executeSQL( "INSERT INTO \"detail\" VALUES ( 2, 1, 1, 'record 1.1 (2)')"); + m_databaseDocument.executeSQL( "INSERT INTO \"detail\" VALUES ( 3, 1, 2, 'record 1.2 (1)')"); + + m_databaseDocument.getDataSource().refreshTables( m_databaseDocument.defaultConnection() ); + } + + /* ------------------------------------------------------------------ */ + public void createForms() throws com.sun.star.uno.Exception + { + m_masterForm = dbfTools.queryPropertySet( m_orb.createInstance( "com.sun.star.form.component.DataForm" ) ); + m_masterRow = (XRow)UnoRuntime.queryInterface( XRow.class, m_masterForm ); + m_masterSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, m_masterForm ); + m_masterForm.setPropertyValue( "ActiveConnection", m_databaseDocument.defaultConnection() ); + m_masterForm.setPropertyValue( "CommandType", new Integer( com.sun.star.sdb.CommandType.TABLE ) ); + m_masterForm.setPropertyValue( "Command", "master" ); + + m_detailForm = dbfTools.queryPropertySet( m_orb.createInstance( "com.sun.star.form.component.DataForm" ) ); + m_detailRow = (XRow)UnoRuntime.queryInterface( XRow.class, m_detailForm ); + m_detailSet = (XResultSet)UnoRuntime.queryInterface( XResultSet.class, m_detailForm ); + m_detailForm.setPropertyValue( "ActiveConnection", m_databaseDocument.defaultConnection() ); + m_detailForm.setPropertyValue( "CommandType", new Integer( com.sun.star.sdb.CommandType.TABLE ) ); + m_detailForm.setPropertyValue( "Command", "detail" ); + + XNameContainer masterContainer = (XNameContainer)UnoRuntime.queryInterface( XNameContainer.class, + m_masterForm ); + masterContainer.insertByName( "slave", m_detailForm ); + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_databaseDocument.closeAndDelete(); + dbfTools.disposeComponent( m_masterForm ); + dbfTools.disposeComponent( m_detailForm ); + } + + /* ------------------------------------------------------------------ */ + /** checks if master-detail relationships including multiple keys work + */ + public void checkMultipleKeys() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_detailForm.setPropertyValue( "MasterFields", new String[] { "ID1", "ID2" } ); + m_detailForm.setPropertyValue( "DetailFields", new String[] { "FK_ID1", "FK_ID2" } ); + + XLoadable loadMaster = (XLoadable)UnoRuntime.queryInterface( XLoadable.class, m_masterForm ); + XLoadable loadDetail = (XLoadable)UnoRuntime.queryInterface( XLoadable.class, m_detailForm ); + loadDetail.addLoadListener( this ); + + // wait until the detail form is loaded + operateMasterAndWaitForDetailForm( loadMaster.getClass().getMethod( "load", new Class[] {} ), loadMaster, new Object[] { } ); + + // okay, now the master form should be on the first record + assure( "wrong form state after loading (ID1)", m_masterRow.getInt(1) == 1 ); + assure( "wrong form state after loading (ID2)", m_masterRow.getInt(2) == 1 ); + assure( "wrong form state after loading (value)", m_masterRow.getString(3).equals( "First Record" ) ); + + // the "XResultSet.next" method + Method methodNext = m_masterSet.getClass().getMethod( "next" , new Class[] {} ); + + // the values in the linked fields should be identical + int expectedDetailRowCounts[] = { 2, 1 }; + do + { + verifyColumnValueIdentity( "ID1", "FK_ID1" ); + verifyColumnValueIdentity( "ID2", "FK_ID2" ); + + m_detailSet.last(); + int masterPos = m_masterSet.getRow(); + assure( "wrong number of records in detail form, for master form at pos " + masterPos, + ((Integer)m_detailForm.getPropertyValue( "RowCount" )).intValue() == expectedDetailRowCounts[ masterPos - 1 ] ); + + operateMasterAndWaitForDetailForm( methodNext, m_masterSet, new Object[] {} ); + } + while ( !m_masterSet.isAfterLast() ); + assure( "wrong number of records in master form", 2 == ((Integer)m_masterForm.getPropertyValue( "RowCount" )).intValue() ); + } + + /** executes an operation on the master, and waits until the detail form has been (re)loaded aferwards + */ + private void operateMasterAndWaitForDetailForm( Method _masterMethod, Object _masterInterface, Object[] _methodParameters ) throws SQLException + { + m_loaded = false; + Object result; + try + { + result = _masterMethod.invoke( _masterInterface, _methodParameters ); + } + catch( java.lang.Exception e ) + { + throw new SQLException( "invoking " + _masterMethod.getName() + " failed",new Object(), "", 0, new Object() ); + } + + if ( _masterMethod.getReturnType().getName().equals( "boolean" ) ) + if ( !((Boolean)result).booleanValue() ) + return; + + synchronized( m_waitForLoad ) + { + if ( !m_loaded ) + { + try { m_waitForLoad.wait(); } + catch( java.lang.InterruptedException e ) { } + } + } + } + + /** assures that the (integer) values in the given columns of our master and detail forms are identical + */ + public void verifyColumnValueIdentity( String masterColName, String detailColName ) throws SQLException + { + XColumnLocate locateMasterCols = (XColumnLocate)UnoRuntime.queryInterface( XColumnLocate.class, m_masterForm ); + XColumnLocate locateDetailCols = (XColumnLocate)UnoRuntime.queryInterface( XColumnLocate.class, m_detailForm ); + + int masterValue = m_masterRow.getInt( locateMasterCols.findColumn( masterColName ) ); + int detailValue = m_detailRow.getInt( locateDetailCols.findColumn( detailColName ) ); + + assure( "values in linked column pair " + detailColName + "->" + masterColName + " (" + + detailValue + "->" + masterValue + ") do not match (master position: " + m_masterSet.getRow() + ")!", + masterValue == detailValue ); + } + + public void disposing(com.sun.star.lang.EventObject eventObject) + { + } + + public void loaded(com.sun.star.lang.EventObject eventObject) + { + synchronized( m_waitForLoad ) + { + m_loaded = true; + m_waitForLoad.notify(); + } + } + + public void reloaded(com.sun.star.lang.EventObject eventObject) + { + synchronized( m_waitForLoad ) + { + m_loaded = true; + m_waitForLoad.notify(); + } + } + + public void reloading(com.sun.star.lang.EventObject eventObject) + { + } + + public void unloaded(com.sun.star.lang.EventObject eventObject) + { + } + + public void unloading(com.sun.star.lang.EventObject eventObject) + { + } +} diff --git a/forms/qa/integration/forms/NumericValidator.java b/forms/qa/integration/forms/NumericValidator.java new file mode 100644 index 000000000000..1afc2c378509 --- /dev/null +++ b/forms/qa/integration/forms/NumericValidator.java @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: NumericValidator.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.form.binding.*; + +/** + * + * @author fs@openoffice.org + */ +public class NumericValidator extends integration.forms.ControlValidator +{ + + /** Creates a new instance of NumericValidator */ + public NumericValidator( ) + { + } + + public String explainInvalid( Object Value ) + { + try + { + double value = ((Double)Value).doubleValue(); + if ( Double.compare( Double.NaN, value ) == 0 ) + return "This is NotANumber"; + if ( !isProperRange( value ) ) + return "The value must be between 0 and 100"; + if ( !isProperDigitCount( value ) ) + return "The value must have at most one decimal digit"; + } + catch( java.lang.Exception e ) + { + return "This is no valid number"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + double value = ((Double)Value).doubleValue(); + if ( Double.compare( Double.NaN, value ) == 0 ) + return false; + if ( !isProperRange( value ) ) + return false; + if ( !isProperDigitCount( value ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + } + return false; + } + + private boolean isProperRange( double value) + { + return ( value >= 0 ) && ( value <= 100 ); + } + + private boolean isProperDigitCount( double value) + { + return ( java.lang.Math.floor( value * 10 ) == value * 10 ); + } +} diff --git a/forms/qa/integration/forms/RadioButtons.java b/forms/qa/integration/forms/RadioButtons.java new file mode 100644 index 000000000000..64711cad8346 --- /dev/null +++ b/forms/qa/integration/forms/RadioButtons.java @@ -0,0 +1,462 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: RadioButtons.java,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.util.*; +import com.sun.star.lang.*; +import com.sun.star.container.*; +import com.sun.star.beans.*; +import com.sun.star.awt.XRadioButton; + +import integration.forms.dbfTools; +import integration.forms.DocumentHelper; +import integration.forms.SpreadsheetDocument; + +import util.utils; +import java.util.*; +import java.io.*; +import java.lang.*; + +/** + * + * @author fs@openoffice.org + */ +public class RadioButtons extends complexlib.ComplexTestCase +{ + private DocumentHelper m_document; /// our current test document + private FormLayer m_formLayer; /// quick access to the form layer + private XMultiServiceFactory m_orb; /// our service factory + private XPropertySet m_primaryForm; /// the primary form, to be used in text documents and in the first page of spreadsheets + private XPropertySet m_secondaryForm; /// the secondary form, to be used in the second page of spreadsheets + + /* ------------------------------------------------------------------ */ + public RadioButtons() + { + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkSingleButtons", + "checkThreeGroups", + "checkMultipleForms", + "checkCalcPageSwitch" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Radio Buttons Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + } + + /* ------------------------------------------------------------------ */ + private XPropertySet insertRadio( int nXPos, int nYPos, String label, String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + return insertRadio( nXPos, nYPos, label, name, refValue, null ); + } + + /* ------------------------------------------------------------------ */ + private XPropertySet insertRadio( int nXPos, int nYPos, String label, String name, String refValue, XPropertySet parentForm ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XIndexContainer parentContainer = dbfTools.queryIndexContainer( parentForm ); + XPropertySet xRadio = m_formLayer.createControlAndShape( "DatabaseRadioButton", nXPos, nYPos, 25, 6, parentContainer ); + xRadio.setPropertyValue( "Label", label ); + xRadio.setPropertyValue( "RefValue", refValue ); + xRadio.setPropertyValue( "Name", name ); + + if ( null == m_primaryForm ) + m_primaryForm = (XPropertySet)dbfTools.getParent( xRadio, XPropertySet.class ); + + return xRadio; + } + + /* ------------------------------------------------------------------ */ + /** this checks whether n groups of radio buttons, consisting of only one button each, + * behave properly + */ + public void checkSingleButtons() throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep( false ); + + insertRadio( 20, 30, "group 1", "group 1", "" ); + insertRadio( 20, 38, "group 2", "group 2", "" ); + insertRadio( 20, 46, "group 3", "group 3", "" ); + insertRadio( 20, 54, "group 4", "group 4", "" ); + + // switch to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + + checkRadio( "group 1", "" ); + verifySingleRadios( 1, 0, 0, 0 ); + + checkRadio( "group 4", "" ); + verifySingleRadios( 1, 0, 0, 1 ); + + checkRadio( "group 2", "" ); + verifySingleRadios( 1, 1, 0, 1 ); + + checkRadio( "group 3", "" ); + verifySingleRadios( 1, 1, 1, 1 ); + + cleanupTestStep(); + } + + /* ------------------------------------------------------------------ */ + /** creates three groups of radio buttons in a sample document, and checks whether they're working + */ + public void checkThreeGroups( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep( false ); + + insertRadio( 20, 30, "group 1 (a)", "group 1", "a" ); + insertRadio( 20, 38, "group 1 (b)", "group 1", "b" ); + + insertRadio( 20, 50, "group 2 (a)", "group 2", "a" ); + insertRadio( 20, 58, "group 2 (b)", "group 2", "b" ); + + insertRadio( 20, 70, "group 3 (a)", "group 3", "a" ); + insertRadio( 20, 78, "group 3 (b)", "group 3", "b" ); + + // switch to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + + // initially, after switching to alive mode, all buttons should be unchecked + verifySixPack( 0, 0, 0, 0, 0, 0 ); + + // check one button in every group + checkRadio( "group 1", "a" ); + checkRadio( "group 2", "b" ); + checkRadio( "group 3", "a" ); + // and verify that this worked + verifySixPack( 1, 0, 0, 1, 1, 0 ); + + // check all buttons which are currently unchecked + checkRadio( "group 1", "b" ); + checkRadio( "group 2", "a" ); + checkRadio( "group 3", "b" ); + // this should have reset the previous checks in the respective groups + verifySixPack( 0, 1, 1, 0, 0, 1 ); + + // and back to the previous check state + checkRadio( "group 1", "a" ); + checkRadio( "group 2", "b" ); + checkRadio( "group 3", "a" ); + verifySixPack( 1, 0, 0, 1, 1, 0 ); + + cleanupTestStep(); + } + + /* ------------------------------------------------------------------ */ + /** tests whether radio buttons which belong to different forms behave properly + */ + public void checkMultipleForms( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep( false ); + + insertRadio( 20, 30, "group 1 (a)", "group 1", "a" ); + insertRadio( 20, 38, "group 1 (b)", "group 1", "b" ); + insertRadio( 20, 46, "group 1 (c)", "group 1", "c" ); + + m_secondaryForm = dbfTools.queryPropertySet( m_document.createSiblingForm( m_primaryForm, "secondary" ) ); + + insertRadio( 70, 30, "group 2 (a)", "group 2", "a", m_secondaryForm ); + insertRadio( 70, 38, "group 2 (b)", "group 2", "b", m_secondaryForm ); + insertRadio( 70, 46, "group 2 (c)", "group 2", "c", m_secondaryForm ); + + // switch to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + + // play around with different check states + checkRadio( "group 1", "b", m_primaryForm ); + checkRadio( "group 2", "c", m_secondaryForm ); + verifyTwoFormRadios( 0, 1, 0, 0, 0, 1 ); + + checkRadio( "group 1", "c", m_primaryForm ); + verifyTwoFormRadios( 0, 0, 1, 0, 0, 1 ); + + checkRadio( "group 2", "a", m_secondaryForm ); + verifyTwoFormRadios( 0, 0, 1, 1, 0, 0 ); + + checkRadio( "group 1", "a", m_primaryForm ); + verifyTwoFormRadios( 1, 0, 0, 1, 0, 0 ); + + checkRadio( "group 2", "b", m_secondaryForm ); + verifyTwoFormRadios( 1, 0, 0, 0, 1, 0 ); + + cleanupTestStep(); + } + + /* ------------------------------------------------------------------ */ + /** tests for a special bug which we once had, where radio buttons lost their state after + * switching spreadsheet pages + */ + public void checkCalcPageSwitch( ) throws com.sun.star.uno.Exception, java.lang.Exception + { + prepareTestStep( true ); + + m_formLayer.setInsertPage( 0 ); + insertRadio( 15, 20, "group 1 (a)", "group 1", "a" ); + insertRadio( 15, 26, "group 1 (b)", "group 1", "b" ); + + m_formLayer.setInsertPage( 1 ); + XPropertySet xRadio = insertRadio( 15, 20, "group 2 (a)", "group 2", "a" ); + insertRadio( 15, 26, "group 2 (b)", "group 2", "b" ); + m_secondaryForm = (XPropertySet)dbfTools.getParent( xRadio, XPropertySet.class ); + + // switch to alive mode + SpreadsheetView view = (SpreadsheetView)m_document.getCurrentView( ); + view.toggleFormDesignMode( ); + // and do initial checking + checkRadio( "group 1", "a", m_primaryForm ); + view.activateSheet( 1 ); + checkRadio( "group 2", "b", m_secondaryForm ); + + // see whether the check states on the first page survived the page switch + verifySheetRadios( 1, 0, 0, 1 ); + // switch back to the first sheet, and see whether the check states survived + view.activateSheet( 0 ); + verifySheetRadios( 1, 0, 0, 1 ); + // and for completely, check again after switching to third sheet and back to the first + view.activateSheet( 2 ); + view.activateSheet( 1 ); + verifySheetRadios( 1, 0, 0, 1 ); + + cleanupTestStep(); + } + + /* ------------------------------------------------------------------ */ + public void after() + { + closeDocument(); + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one + */ + private void closeDocument() + { + try + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + catch ( com.sun.star.uno.Exception e ) + { + } + } + + /* ------------------------------------------------------------------ */ + private void prepareTestStep( boolean useSpreadsheetDocument ) throws com.sun.star.uno.Exception, java.lang.Exception + { + m_primaryForm = null; + + m_document = useSpreadsheetDocument ? new SpreadsheetDocument( m_orb ) : DocumentHelper.blankTextDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + } + + /* ------------------------------------------------------------------ */ + private void cleanupTestStep( ) + { + closeDocument(); + } + + /* ------------------------------------------------------------------ */ + /** checks or unchecks the radio button (in our primary form) with the given name and the given ref value + */ + private void checkRadio( String groupName, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + checkRadio( groupName, refValue, m_primaryForm ); + } + + /* ------------------------------------------------------------------ */ + /** checks or unchecks the radio button with the given name and the given ref value + */ + private void checkRadio( String groupName, String refValue, XPropertySet form ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet xRadio = getRadioModel( groupName, refValue, form ); + + XRadioButton radioButton = (XRadioButton)UnoRuntime.queryInterface( + XRadioButton.class, m_document.getCurrentView().getControl( xRadio ) ); + radioButton.setState( true ); + } + + /* ------------------------------------------------------------------ */ + private XPropertySet getRadioModel( String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception + { + return getRadioModel( name, refValue, m_primaryForm ); + } + + /* ------------------------------------------------------------------ */ + private XPropertySet getRadioModel( String name, String refValue, XPropertySet form ) throws com.sun.star.uno.Exception, java.lang.Exception + { + return m_formLayer.getRadioModelByRefValue( form, name, refValue ); + } + + /* ------------------------------------------------------------------ */ + private String stateString( short[] states ) + { + StringBuffer buf = new StringBuffer(); + for ( int i=0; i<states.length; ++i ) + buf.append( states[i] ); + return buf.toString(); + } + + /* ------------------------------------------------------------------ */ + /** verifies a number of radio buttons for their states + */ + private boolean verifyRadios( XPropertySet[] radios, short[] expectedStates, String errorMessage ) throws com.sun.star.uno.Exception + { + short[] actualStates = new short[radios.length]; + + // collect all current states. This is just to be able to emit them, in case of a failure + for ( int i = 0; i<radios.length; ++i ) + { + actualStates[i] = ((Short)radios[i].getPropertyValue( "State" )).shortValue(); + } + + // now actually check the states + for ( int i = 0; i<radios.length; ++i ) + { + if ( actualStates[i] != expectedStates[i] ) + { + failed( errorMessage + " (expected: " + stateString( expectedStates ) + ", found: " + stateString( actualStates ) + ")" ); + return false; + } + } + + return true; + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of the 4 radio buttons from the checkSingleButtons test + */ + private boolean verifySingleRadios( int state1, int state2, int state3, int state4 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet[] radios = new XPropertySet[4]; + radios[0] = getRadioModel( "group 1", "" ); + radios[1] = getRadioModel( "group 2", "" ); + radios[2] = getRadioModel( "group 3", "" ); + radios[3] = getRadioModel( "group 4", "" ); + + short[] states = new short[4]; + states[0] = (short)state1; + states[1] = (short)state2; + states[2] = (short)state3; + states[3] = (short)state4; + + return verifyRadios( radios, states, "single-group radio buttons do not work!" ); + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of 6 radio buttons form the checkThreeGroups test + */ + private boolean verifySixPack( XPropertySet[] radios, String errorMessage, + int state1, int state2, int state3, int state4, int state5, int state6 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + short[] states = new short[6]; + states[0] = (short)state1; + states[1] = (short)state2; + states[2] = (short)state3; + states[3] = (short)state4; + states[4] = (short)state5; + states[5] = (short)state6; + + return verifyRadios( radios, states, errorMessage ); + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of 6 radio buttons + */ + private boolean verifySixPack( int state1, int state2, int state3, int state4, int state5, int state6 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet[] radios = new XPropertySet[6]; + radios[0] = getRadioModel( "group 1", "a" ); + radios[1] = getRadioModel( "group 1", "b" ); + radios[2] = getRadioModel( "group 2", "a" ); + radios[3] = getRadioModel( "group 2", "b" ); + radios[4] = getRadioModel( "group 3", "a" ); + radios[5] = getRadioModel( "group 3", "b" ); + + return verifySixPack( radios, "six radio buttons, forming three different groups, do not properly work!", + state1, state2, state3, state4, state5, state6 ); + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of the 6 radio buttons in our checkMultipleForms test + */ + private boolean verifyTwoFormRadios( int state1, int state2, int state3, int state4, int state5, int state6 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet[] radios = new XPropertySet[6]; + radios[0] = getRadioModel( "group 1", "a", m_primaryForm ); + radios[1] = getRadioModel( "group 1", "b", m_primaryForm ); + radios[2] = getRadioModel( "group 1", "c", m_primaryForm ); + radios[3] = getRadioModel( "group 2", "a", m_secondaryForm ); + radios[4] = getRadioModel( "group 2", "b", m_secondaryForm ); + radios[5] = getRadioModel( "group 2", "c", m_secondaryForm ); + + return verifySixPack( radios, "radio buttons on different forms do not work properly!", + state1, state2, state3, state4, state5, state6 ); + } + + /* ------------------------------------------------------------------ */ + /** verifies the states of the 4 radio buttons in our spreadsheet document (checkCalcPageSwitch) + */ + private boolean verifySheetRadios( int state1, int state2, int state3, int state4 ) throws com.sun.star.uno.Exception, java.lang.Exception + { + XPropertySet[] radios = new XPropertySet[4]; + radios[0] = getRadioModel( "group 1", "a", m_primaryForm ); + radios[1] = getRadioModel( "group 1", "b", m_primaryForm ); + radios[2] = getRadioModel( "group 2", "a", m_secondaryForm ); + radios[3] = getRadioModel( "group 2", "b", m_secondaryForm ); + + short[] states = new short[4]; + states[0] = (short)state1; + states[1] = (short)state2; + states[2] = (short)state3; + states[3] = (short)state4; + + return verifyRadios( radios, states, "seems some of the radio button check states didn't survive the page activation(s)!" ); + } +} + diff --git a/forms/qa/integration/forms/SingleControlValidation.java b/forms/qa/integration/forms/SingleControlValidation.java new file mode 100644 index 000000000000..353f64c1f76a --- /dev/null +++ b/forms/qa/integration/forms/SingleControlValidation.java @@ -0,0 +1,194 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: SingleControlValidation.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.util.*; +import com.sun.star.lang.*; +import com.sun.star.accessibility.*; +import com.sun.star.container.*; +import com.sun.star.beans.*; +import com.sun.star.form.binding.*; +import com.sun.star.form.validation.*; + +import integration.forms.DocumentHelper; + +/** + * + * @author fs@openoffice.org + */ +public class SingleControlValidation implements XFormComponentValidityListener +{ + private DocumentHelper m_document; /// our current test document + private FormLayer m_formLayer; /// quick access to the form layer + private XMultiServiceFactory m_orb; /// our service factory + + private XPropertySet m_inputField; + private XPropertySet m_inputLabel; + private XPropertySet m_statusField; + private XPropertySet m_explanationField; + private XValidator m_validator; + + /* ------------------------------------------------------------------ */ + public SingleControlValidation( DocumentHelper document, int columnPos, int rowPos, String formComponentService, XValidator validator ) + { + m_document = document; + m_validator = validator; + m_formLayer = new FormLayer( m_document ); + createControls( columnPos, rowPos, formComponentService, 1, 0 ); + } + + /* ------------------------------------------------------------------ */ + public SingleControlValidation( DocumentHelper document, int columnPos, int rowPos, String formComponentService, XValidator validator, int controlCount, int controlHeight ) + { + m_document = document; + m_validator = validator; + m_formLayer = new FormLayer( m_document ); + createControls( columnPos, rowPos, formComponentService, controlCount, controlHeight ); + } + + /* ------------------------------------------------------------------ */ + public XPropertySet getInputField() + { + return m_inputField; + } + + /* ------------------------------------------------------------------ */ + public void setExplanatoryText( String text ) + { + try + { + m_inputLabel.setPropertyValue( "Label", text ); + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.err ); + } + } + + /* ------------------------------------------------------------------ */ + private void createControls( int columnPos, int rowPos, String formComponentService, int controlCount, int controlHeight ) + { + try + { + m_inputLabel = m_formLayer.createControlAndShape( "FixedText", columnPos, rowPos, 70, 12, null ); + m_inputLabel.setPropertyValue( "MultiLine", new Boolean( true ) ); + + com.sun.star.awt.FontDescriptor font = (com.sun.star.awt.FontDescriptor)m_inputLabel.getPropertyValue( "FontDescriptor" ); + font.Weight = com.sun.star.awt.FontWeight.BOLD; + m_inputLabel.setPropertyValue( "FontDescriptor", font ); + + if ( controlHeight == 0 ) + controlHeight = 6; + + int controlPos = rowPos + 12; + XPropertySet[] controls = new XPropertySet[ controlCount ]; + for ( int i = 0; i < controlCount; ++i, controlPos += controlHeight ) + { + controls[ i ] = m_formLayer.createControlAndShape( formComponentService, columnPos, controlPos, 25, controlHeight, null ); + controls[ i ].setPropertyValue( "Name", formComponentService ); + controls[ i ].setPropertyValue( "Tag", String.valueOf( i ) ); + + if ( controls[ i ].getPropertySetInfo().hasPropertyByName( "Border" ) ) + controls[ i ].setPropertyValue( "Border", new Short( (short)2 ) ); + + XValidatableFormComponent xComp = (XValidatableFormComponent)UnoRuntime.queryInterface( XValidatableFormComponent.class, + controls[ i ] ); + xComp.addFormComponentValidityListener( this ); + } + m_inputField = controls[ 0 ]; + + // ---------------------------------- + controlPos += 4; + XPropertySet xLabel = m_formLayer.createControlAndShape( "FixedText", columnPos, controlPos, 70, 4, null ); + xLabel.setPropertyValue( "Label", new String( "Status:" ) ); + controlPos += 4; + m_statusField = m_formLayer.createControlAndShape( "FixedText", columnPos, controlPos, 70, 4, null ); + m_statusField.setPropertyValue( "Label", new String( "" ) ); + + // ---------------------------------- + controlPos += 6; + xLabel = m_formLayer.createControlAndShape( "FixedText", columnPos, controlPos, 70, 4, null ); + xLabel.setPropertyValue( "Label", new String( "Explanation for invalidity:" ) ); + controlPos += 4; + m_explanationField = m_formLayer.createControlAndShape( "FixedText", columnPos, controlPos, 70, 4, null ); + m_explanationField.setPropertyValue( "Label", new String( "" ) ); + + XValidatable xValidatable = (XValidatable)UnoRuntime.queryInterface( XValidatable.class, m_inputField ); + xValidatable.setValidator( m_validator ); + } + catch( java.lang.Exception e ) + { + e.printStackTrace( System.out ); + } + } + + /* ------------------------------------------------------------------ */ + /* XEventListener overridables */ + /* ------------------------------------------------------------------ */ + public void disposing( com.sun.star.lang.EventObject eventObject ) + { + // not interested in + } + + /* ------------------------------------------------------------------ */ + /* XFormComponentValidityListener overridables */ + /* ------------------------------------------------------------------ */ + public void componentValidityChanged( com.sun.star.lang.EventObject eventObject ) + { + try + { + if ( m_inputField.equals( eventObject.Source ) ) + { + XValidatableFormComponent xComp = (XValidatableFormComponent)UnoRuntime.queryInterface( XValidatableFormComponent.class, + eventObject.Source ); + // the current value + Object value = xComp.getCurrentValue(); + + // the current validity flag + boolean isValid = xComp.isValid(); + + m_statusField.setPropertyValue("Label", isValid ? "valid" : "invalid" ); + m_statusField.setPropertyValue( "TextColor", new Integer( isValid ? 0x008000 : 0x800000 ) ); + + String validityMessage = ""; + if ( !isValid ) + validityMessage = m_validator.explainInvalid( value ); + m_explanationField.setPropertyValue( "Label", validityMessage ); + } + } + catch( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.out ); + } + } + +} diff --git a/forms/qa/integration/forms/SpreadsheetDocument.java b/forms/qa/integration/forms/SpreadsheetDocument.java new file mode 100644 index 000000000000..344b1f667bab --- /dev/null +++ b/forms/qa/integration/forms/SpreadsheetDocument.java @@ -0,0 +1,154 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: SpreadsheetDocument.java,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XComponent; +import com.sun.star.table.XCellRange; +import com.sun.star.table.CellAddress; +import com.sun.star.table.CellRangeAddress; +import com.sun.star.container.XIndexAccess; +import com.sun.star.sheet.XSpreadsheetDocument; +import com.sun.star.sheet.XSpreadsheets; +import com.sun.star.beans.NamedValue; + +/** + * + * @author fs93730 + */ +public class SpreadsheetDocument extends DocumentHelper +{ + /** Creates a new blank spreadsheet document */ + /* ------------------------------------------------------------------ */ + public SpreadsheetDocument( XMultiServiceFactory orb ) throws com.sun.star.uno.Exception + { + super( orb, implLoadAsComponent( orb, "private:factory/scalc" ) ); + } + + /* ------------------------------------------------------------------ */ + public SpreadsheetDocument( XMultiServiceFactory orb, XComponent document ) throws com.sun.star.uno.Exception + { + super( orb, document ); + } + + /* ------------------------------------------------------------------ */ + /** returns the sheets collection + */ + public XSpreadsheets getSheets() throws com.sun.star.uno.Exception + { + XSpreadsheetDocument spreadsheetDoc = (XSpreadsheetDocument)UnoRuntime.queryInterface( XSpreadsheetDocument.class, + getDocument() + ); + return spreadsheetDoc.getSheets(); + } + + /* ------------------------------------------------------------------ */ + /** returns the sheet with the given index + */ + public XCellRange getSheet( int index ) throws com.sun.star.uno.Exception + { + XIndexAccess sheets = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, + getSheets() + ); + return (XCellRange)UnoRuntime.queryInterface( XCellRange.class, + sheets.getByIndex( index ) + ); + } + + /* ------------------------------------------------------------------ */ + /** creates a value binding for a given cell + */ + public com.sun.star.form.binding.XValueBinding createCellBinding( short sheet, short column, short row ) + { + return createCellBinding( sheet, column, row, false ); + } + + /* ------------------------------------------------------------------ */ + /** creates a value binding which can be used to exchange a list box selection <em>index</em> with a cell + */ + public com.sun.star.form.binding.XValueBinding createListIndexBinding( short sheet, short column, short row ) + { + return createCellBinding( sheet, column, row, true ); + } + + /* ------------------------------------------------------------------ */ + /** creates a value binding for a given cell, with or without support for integer value exchange + */ + private com.sun.star.form.binding.XValueBinding createCellBinding( short sheet, short column, short row, boolean supportIntegerValues ) + { + com.sun.star.form.binding.XValueBinding cellBinding = null; + try + { + CellAddress address = new CellAddress( sheet, column, row ); + Object[] initParam = new Object[] { new NamedValue( "BoundCell", address ) }; + cellBinding = (com.sun.star.form.binding.XValueBinding)UnoRuntime.queryInterface( + com.sun.star.form.binding.XValueBinding.class, + createInstanceWithArguments( + supportIntegerValues ? "com.sun.star.table.ListPositionCellBinding" + : "com.sun.star.table.CellValueBinding", + initParam + ) + ); + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + return cellBinding; + } + + /* ------------------------------------------------------------------ */ + /** creates a source of list entries associated with a (one-column) cell range + */ + public com.sun.star.form.binding.XListEntrySource createListEntrySource( short sheet, short column, + short topRow, short bottomRow ) + { + com.sun.star.form.binding.XListEntrySource entrySource = null; + try + { + CellRangeAddress rangeAddress = new CellRangeAddress( sheet, column, + topRow, column, bottomRow ); + Object[] initParam = new Object[] { new NamedValue( "CellRange", rangeAddress ) }; + entrySource = (com.sun.star.form.binding.XListEntrySource)UnoRuntime.queryInterface( + com.sun.star.form.binding.XListEntrySource.class, + createInstanceWithArguments( + "com.sun.star.table.CellRangeListSource", initParam ) ); + } + catch( com.sun.star.uno.Exception e ) + { + System.err.println( e ); + e.printStackTrace( System.err ); + } + return entrySource; + } +} diff --git a/forms/qa/integration/forms/SpreadsheetView.java b/forms/qa/integration/forms/SpreadsheetView.java new file mode 100644 index 000000000000..45e014874a61 --- /dev/null +++ b/forms/qa/integration/forms/SpreadsheetView.java @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: SpreadsheetView.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +/* + * SpreadsheetView.java + * + * Created on 2. Oktober 2003, 14:02 + */ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.lang.*; +import com.sun.star.frame.*; +import com.sun.star.sheet.*; +import com.sun.star.container.*; + +import integration.forms.DocumentViewHelper; +import integration.forms.DocumentHelper; + +/** + * + * @author fs93730 + */ +public class SpreadsheetView extends integration.forms.DocumentViewHelper +{ + + /** Creates a new instance of SpreadsheetView */ + public SpreadsheetView( XMultiServiceFactory orb, DocumentHelper document, XController controller ) + { + super( orb, document, controller ); + } + + /** activates the sheet with the given index + */ + void activateSheet( int sheetIndex ) + { + try + { + // get the sheet to activate + XSpreadsheetDocument doc = (XSpreadsheetDocument)UnoRuntime.queryInterface( + XSpreadsheetDocument.class, getDocument().getDocument() ); + XIndexAccess sheets = (XIndexAccess)UnoRuntime.queryInterface( + XIndexAccess.class, doc.getSheets() ); + + XSpreadsheet sheet = (XSpreadsheet)UnoRuntime.queryInterface( + XSpreadsheet.class, sheets.getByIndex( sheetIndex ) ); + + // activate + XSpreadsheetView view = (XSpreadsheetView)UnoRuntime.queryInterface( + XSpreadsheetView.class, getController() ); + view.setActiveSheet( sheet ); + } + catch( com.sun.star.uno.Exception e ) + { + } + } +} diff --git a/forms/qa/integration/forms/TableCellTextBinding.java b/forms/qa/integration/forms/TableCellTextBinding.java new file mode 100644 index 000000000000..83a79dddbb33 --- /dev/null +++ b/forms/qa/integration/forms/TableCellTextBinding.java @@ -0,0 +1,216 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: TableCellTextBinding.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.Type; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.table.XCell; +import com.sun.star.util.XModifyListener; +import com.sun.star.beans.XPropertySet; +import com.sun.star.text.XTextRange; +import com.sun.star.form.binding.IncompatibleTypesException; + +/** a value binding to be connected to a form control + + This binding synchronizes the text contained in a table cell (which you must + pass upon construction) to the text in an XBindableValue. + + Well, in real it does not synchronize both directions. The ValueBinding + service has not much room for own activity: It allows notification of changes + in the own value, and it allows external instances to set the current value. + + Note that we implement this binding as a separate thread, which is (more or + less permanently) polling for a new text at the cell. This is unfortunate, but + sadly the Writer table cells do not support actively notifying changes in their + content to other interested parties. +*/ +public class TableCellTextBinding + extends java.lang.Thread + implements com.sun.star.form.binding.XValueBinding, + com.sun.star.util.XModifyBroadcaster +{ + private XTextRange m_cellText; + private Object m_writeSignal; + private String m_newCellText; + private String m_lastKnownCellText; + private boolean m_haveNewCellText; + private java.util.List m_listeners; + + /** Creates a new instance of TableCellTextBinding */ + public TableCellTextBinding( XCell cell ) + { + m_cellText = (XTextRange)UnoRuntime.queryInterface( XTextRange.class, cell ); + + m_newCellText = new String(); + m_listeners = new java.util.LinkedList(); + + start(); + } + + /** retrieves the list of data types which this binding can exchange + */ + public com.sun.star.uno.Type[] getSupportedValueTypes() + { + try + { + // well, only strings here ... + return new Type[] { + getStringType() + }; + } + catch( java.lang.Exception e ) + { + } + return new Type[] { }; + } + + /** retrieves the current value + */ + public Object getValue(com.sun.star.uno.Type type) throws com.sun.star.form.binding.IncompatibleTypesException + { + if ( !type.equals( getStringType() ) ) + throw new com.sun.star.form.binding.IncompatibleTypesException(); + + return m_cellText.getString(); + } + + /** sets a new value + */ + public void setValue(Object obj) throws com.sun.star.form.binding.IncompatibleTypesException + { + String text; + try + { + text = (String)obj; + } + catch( java.lang.ClassCastException e ) + { + throw new com.sun.star.form.binding.IncompatibleTypesException(); + } + // remember the new text + synchronized( m_newCellText ) + { + m_newCellText = text; + m_haveNewCellText = true; + } + // and wake up the thread which is waiting for it + synchronized( m_writeSignal ) + { + m_writeSignal.notify(); + } + } + + /** determines whether a given value type is supported + */ + public boolean supportsType(com.sun.star.uno.Type type) + { + return type.equals( getStringType() ); + } + + /** retrieves the UNO type for the string class + */ + private static final Type getStringType() + { + return new com.sun.star.uno.Type( String.class ); + } + + /** runs the thread + */ + public void run() + { + try + { + m_writeSignal = new Object(); + while ( true ) + { + // go sleep a while + synchronized( m_writeSignal ) + { + m_writeSignal.wait( 200 ); + } + + // if there's new text in the control, propagate it to the cell + synchronized ( m_newCellText ) + { + if ( m_haveNewCellText ) + { + m_cellText.setString( m_newCellText ); + m_lastKnownCellText = m_newCellText; + } + m_haveNewCellText = false; + } + + // if there's new text in the cell, propagate it to the control + String currentCellText = m_cellText.getString(); + if ( !currentCellText.equals( m_lastKnownCellText ) ) + { + m_lastKnownCellText = currentCellText; + // notify the modification + synchronized( m_listeners ) + { + com.sun.star.lang.EventObject eventSource = new com.sun.star.lang.EventObject( this ); + + java.util.Iterator loop = m_listeners.iterator(); + while ( loop.hasNext() ) + { + ((XModifyListener)loop.next()).modified( eventSource ); + } + } + } + } + } + catch( java.lang.Exception e ) + { + e.printStackTrace(System.err); + } + } + + public void addModifyListener(com.sun.star.util.XModifyListener xModifyListener) + { + synchronized( m_listeners ) + { + m_listeners.add( xModifyListener ); + } + } + + public void removeModifyListener(com.sun.star.util.XModifyListener xModifyListener) + { + synchronized( m_listeners ) + { + m_listeners.remove( xModifyListener ); + } + } + + public void disposing(com.sun.star.lang.EventObject eventObject) + { + // not interested in + } +} diff --git a/forms/qa/integration/forms/TestCase.java b/forms/qa/integration/forms/TestCase.java new file mode 100644 index 000000000000..1f019d6fa278 --- /dev/null +++ b/forms/qa/integration/forms/TestCase.java @@ -0,0 +1,152 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: TestCase.java,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.util.XCloseable; +import com.sun.star.util.XModifiable; +import integration.forms.DocumentType; + +public abstract class TestCase extends complexlib.ComplexTestCase implements com.sun.star.lang.XEventListener +{ + protected XMultiServiceFactory m_orb; /// our service factory + protected DocumentType m_documentType; /// the type of our document + protected DocumentHelper m_document; /// our current test document + protected FormLayer m_formLayer; + + /** Creates a new instance of TestCase */ + public TestCase( DocumentType docType ) + { + m_documentType = docType; + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_orb = (XMultiServiceFactory)param.getMSF(); + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one, via (simulated) user input + */ + protected void closeDocumentByUI() + { + try + { + if ( m_document != null ) + { + // first, set the document to "unmodified" + XModifiable docModify = (XModifiable)m_document.query( XModifiable.class ); + docModify.setModified( false ); + + m_document.getCurrentView().dispatch( ".uno:CloseDoc" ); + + // CloseDoc is asynchronous, so wait until it's done - or 1 second, at most + synchronized ( this ) { wait( 1000 ); } + } + } + catch ( java.lang.Exception e ) + { + e.printStackTrace( System.out ); + } + } + + /* ------------------------------------------------------------------ */ + /** closes our document, if we have an open one + */ + protected void closeDocument() + { + try + { + // close our document + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)m_document.query( XCloseable.class ); + closeDoc.close( true ); + } + } + catch ( com.sun.star.uno.Exception e ) + { + e.printStackTrace( System.out ); + } + } + + /* ------------------------------------------------------------------ */ + /** prepares a new document to work with + */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + m_document = DocumentHelper.blankDocument( m_orb, m_documentType ); + m_document.getDocument( ).addEventListener( this ); + m_formLayer = new FormLayer( m_document ); + } + + /* ------------------------------------------------------------------ */ + /* internal methods */ + /* ------------------------------------------------------------------ */ + /** waits for the user to press a key (on the console where she started the java program) + or the document to be closed by the user. + @return + <TRUE/> if the user pressed a key on the console, <FALSE/> if she closed the document + */ + protected boolean waitForUserInput() throws java.lang.Exception + { + synchronized (this) + { + integration.forms.WaitForInput aWait = new integration.forms.WaitForInput( this ); + aWait.start(); + wait(); + + // if the waiter thread is done, the user pressed enter + boolean bKeyPressed = aWait.isDone(); + if ( !bKeyPressed ) + aWait.interrupt(); + + return bKeyPressed; + } + } + + /* ------------------------------------------------------------------ */ + /* XEventListener overridables */ + /* ------------------------------------------------------------------ */ + public void disposing( com.sun.star.lang.EventObject eventObject ) + { + if ( m_document.getDocument().equals( eventObject.Source ) ) + { + // notify ourself that we can stop waiting for user input + synchronized (this) + { + notify(); + } + } + } +} diff --git a/forms/qa/integration/forms/TestSkeleton.java b/forms/qa/integration/forms/TestSkeleton.java new file mode 100644 index 000000000000..8f2765b3a6d5 --- /dev/null +++ b/forms/qa/integration/forms/TestSkeleton.java @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.Exception; + +public class TestSkeleton extends TestCase +{ + /** Creates a new instance of TestSkeleton */ + public TestSkeleton() + { + super( DocumentType.WRITER ); + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkTestSkeleton" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Test Skeleton"; + } + + /* ------------------------------------------------------------------ */ + public void checkTestSkeleton() throws com.sun.star.uno.Exception, java.lang.Exception + { + } + + /* ------------------------------------------------------------------ */ + public void before() throws Exception, java.lang.Exception + { + super.before(); + } + + /* ------------------------------------------------------------------ */ + public void after() throws Exception, java.lang.Exception + { + super.before(); + } + + /* ------------------------------------------------------------------ */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.prepareDocument(); + } + } diff --git a/forms/qa/integration/forms/TextValidator.java b/forms/qa/integration/forms/TextValidator.java new file mode 100644 index 000000000000..cdad49640f65 --- /dev/null +++ b/forms/qa/integration/forms/TextValidator.java @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: TextValidator.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.form.binding.*; + +/** + * + * @author fs@openoffice.org + */ +public class TextValidator extends integration.forms.ControlValidator +{ + + /** Creates a new instance of NumericValidator */ + public TextValidator( ) + { + } + + public String explainInvalid( Object Value ) + { + try + { + String value = (String)Value; + if ( containsZs( value ) ) + return "No Z's allowed here"; + if ( !isProperChunks( value ) ) + return "Need 3 * n characters"; + } + catch( java.lang.Exception e ) + { + return "ooops. Unknown error"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + String value = (String)Value; + if ( containsZs( value ) ) + return false; + if ( !isProperChunks( value ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + } + return false; + } + + private boolean isProperChunks( String value ) + { + return ( value.length() % 3 ) == 0; + } + + private boolean containsZs( String value ) + { + if ( ( value.indexOf( 'Z' ) != -1 ) + || ( value.indexOf( 'z' ) != -1 ) + ) + return true; + return false; + } +} diff --git a/forms/qa/integration/forms/TimeValidator.java b/forms/qa/integration/forms/TimeValidator.java new file mode 100644 index 000000000000..190db9f99f1d --- /dev/null +++ b/forms/qa/integration/forms/TimeValidator.java @@ -0,0 +1,98 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: TimeValidator.java,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.form.binding.*; + +/** + * + * @author fs@openoffice.org + */ +public class TimeValidator extends integration.forms.ControlValidator +{ + + /** Creates a new instance of NumericValidator */ + public TimeValidator( ) + { + } + + public String explainInvalid( Object Value ) + { + try + { + if ( isVoid( Value ) ) + return "empty input"; + + com.sun.star.util.Time timeValue = (com.sun.star.util.Time)Value; + if ( isInvalidTime( timeValue ) ) + return "this is no valid time"; + if ( !isFullHour( timeValue ) ) + return "time must denote a full hour"; + } + catch( java.lang.Exception e ) + { + return "this is no valid time"; + } + return ""; + } + + public boolean isValid( Object Value ) + { + try + { + if ( isVoid( Value ) ) + return false; + + com.sun.star.util.Time timeValue = (com.sun.star.util.Time) + com.sun.star.uno.AnyConverter.toObject( + com.sun.star.util.Time.class, Value); + if ( isInvalidTime( timeValue ) ) + return false; + if ( !isFullHour( timeValue ) ) + return false; + return true; + } + catch( java.lang.Exception e ) + { + e.printStackTrace( System.err ); + } + return false; + } + + private boolean isInvalidTime( com.sun.star.util.Time timeValue ) + { + return ( timeValue.Hours == -1 ) && ( timeValue.Minutes == -1 ) && ( timeValue.Seconds == -1 ) && ( timeValue.HundredthSeconds == -1 ); + } + + private boolean isFullHour( com.sun.star.util.Time timeValue ) + { + return ( timeValue.Minutes == 0 ) && ( timeValue.Seconds == 0 ) && ( timeValue.HundredthSeconds == 0 ); + } +} diff --git a/forms/qa/integration/forms/ValueBinding.java b/forms/qa/integration/forms/ValueBinding.java new file mode 100644 index 000000000000..c95c100b33a9 --- /dev/null +++ b/forms/qa/integration/forms/ValueBinding.java @@ -0,0 +1,123 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: ValueBinding.java,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.beans.XPropertySet; +import com.sun.star.text.XTextDocument; +import com.sun.star.text.XText; +import com.sun.star.text.XTextTable; +import com.sun.star.text.XTextCursor; +import com.sun.star.form.binding.XValueBinding; +import com.sun.star.form.binding.XBindableValue; + +import integration.forms.DocumentHelper; +import integration.forms.TableCellTextBinding; + +public class ValueBinding extends integration.forms.TestCase +{ + /** Creates a new instance of ValueBinding */ + public ValueBinding() + { + super( DocumentType.WRITER ); + } + + public static boolean isInteractiveTest() + { + return true; + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkBindingProperties" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Control Value Binding Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.before(); + prepareDocument(); + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.waitForUserInput(); + super.closeDocument(); + } + + /* ------------------------------------------------------------------ */ + public void checkBindingProperties() throws com.sun.star.uno.Exception, java.lang.Exception + { + } + + /* ------------------------------------------------------------------ */ + protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception + { + super.prepareDocument(); + + // insert a table with exactly one cell. The content of this table will be synced with + // the content of a form control + XTextDocument textDoc = (XTextDocument)UnoRuntime.queryInterface( XTextDocument.class, m_document.getDocument() ); + XText documentText = textDoc.getText(); + XTextCursor textCursor = documentText.createTextCursor(); + + XTextTable table = (XTextTable)UnoRuntime.queryInterface( XTextTable.class, + m_document.createInstance( "com.sun.star.text.TextTable" ) + ); + table.initialize( 1, 1 ); + documentText.insertTextContent( textCursor, table, false ); + + // insert our sample control + XPropertySet textControl = m_formLayer.insertControlLine( "DatabaseTextField", "Test", "", 10 ); + + // create a value binding for the first cell of the table + XValueBinding cellBinding = new TableCellTextBinding( table.getCellByName( "A1" ) ); + // and bind it to the control + XBindableValue bindable = (XBindableValue)UnoRuntime.queryInterface( + XBindableValue.class, textControl + ); + bindable.setValueBinding( cellBinding ); + + // toggle the view to alive mode + m_document.getCurrentView( ).toggleFormDesignMode( ); + } + } diff --git a/forms/qa/integration/forms/WaitForInput.java b/forms/qa/integration/forms/WaitForInput.java new file mode 100644 index 000000000000..54a5dab2263a --- /dev/null +++ b/forms/qa/integration/forms/WaitForInput.java @@ -0,0 +1,69 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: WaitForInput.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +package integration.forms; + +class WaitForInput extends java.lang.Thread +{ + private Object m_aToNotify; + private boolean m_bDone; + + public WaitForInput( Object aToNotify ) + { + m_aToNotify = aToNotify; + m_bDone = false; + } + + public boolean isDone() + { + return m_bDone; + } + + public void run() + { + try + { + System.out.println( "\npress enter to exit" ); + System.in.read(); + + m_bDone = true; + // notify that the user pressed the key + synchronized (m_aToNotify) + { + m_aToNotify.notify(); + } + } + catch( java.lang.Exception e ) + { + // not really interested in + System.err.println( e ); + } + } +}; + diff --git a/forms/qa/integration/forms/XMLFormSettings.java b/forms/qa/integration/forms/XMLFormSettings.java new file mode 100644 index 000000000000..f36bcb38cca4 --- /dev/null +++ b/forms/qa/integration/forms/XMLFormSettings.java @@ -0,0 +1,232 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: XMLFormSettings.java,v $ + * $Revision: 1.2.24.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package integration.forms; + +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.XPropertySet; +import com.sun.star.form.binding.IncompatibleTypesException; +import com.sun.star.form.binding.XBindableValue; +import com.sun.star.form.binding.XValueBinding; +import com.sun.star.frame.XStorable; +import com.sun.star.io.IOException; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.util.CloseVetoException; +import com.sun.star.util.XCloseable; +import com.sun.star.xml.dom.XNode; +import com.sun.star.xsd.DataTypeClass; +import java.io.File; +import org.openoffice.xforms.Instance; +import org.openoffice.xforms.Model; +import org.openoffice.xforms.XMLDocument; + +public class XMLFormSettings extends complexlib.ComplexTestCase +{ + private XMultiServiceFactory m_orb; + private XMLDocument m_document; + private Model m_defaultModel; + private FormLayer m_formLayer; + private XPropertySet m_stringBinding; + private XPropertySet m_booleanBinding; + private XPropertySet m_dateBinding; + + /** Creates a new instance of XMLFormSettings */ + public XMLFormSettings() + { + } + + /* ------------------------------------------------------------------ */ + public String[] getTestMethodNames() + { + return new String[] { + "checkExternalData" + }; + } + + /* ------------------------------------------------------------------ */ + public String getTestObjectName() + { + return "Form Control Spreadsheet Cell Binding Test"; + } + + /* ------------------------------------------------------------------ */ + public void before() throws java.lang.Exception + { + // create the document and assign related members + m_orb = (XMultiServiceFactory)param.getMSF(); + m_document = new XMLDocument( m_orb ); + m_formLayer = new FormLayer( m_document ); + + // create a simple structure in the DOM tree: an element with two attributes + String[] modelNames = m_document.getXFormModelNames(); + m_defaultModel = m_document.getXFormModel( modelNames[0] ); + Instance defaultInstance = m_defaultModel.getDefaultInstance(); + XNode stringElement = defaultInstance.createElement( "stringElement" ); + XNode booleanAttrib = defaultInstance.createAttribute( stringElement, "booleanAttribute", "true" ); + XNode dateAttrib = defaultInstance.createAttribute( stringElement, "dateAttribute" ); + + // when it comes to saving and loading, only one child of the root element of the instance + // is handled (is this a bug? see xmloff/source/xforms/XFormsInstanceContext.cxx, method + // CreateChildContext). + // So, we remove the default node of the instance which it has all the time + defaultInstance.removeNode( "instanceData" ); + + assure( "booleanAttrib's parent is wrong", + UnoRuntime.areSame( stringElement, booleanAttrib.getParentNode() ) ); + assure( "dateAttrib's parent is wrong", + UnoRuntime.areSame( stringElement, dateAttrib.getParentNode() ) ); + + // also create bindings for the element and its attributes, of the proper type + m_stringBinding = m_defaultModel.createBindingForNode( stringElement, DataTypeClass.STRING ); + m_booleanBinding = m_defaultModel.createBindingForNode( booleanAttrib, DataTypeClass.BOOLEAN ); + m_dateBinding = m_defaultModel.createBindingForNode( dateAttrib, DataTypeClass.DATE ); + + // TODO: set up the bindings so that the date bindings is relevant if and only if + // the boolean value is true + + // store the document + File tempFile = File.createTempFile( "xmlforms", ".odt" ); + tempFile.deleteOnExit(); + String fileURL = tempFile.toURL().toExternalForm(); + XStorable store = (XStorable)UnoRuntime.queryInterface( XStorable.class, + m_document.getDocument() ); + store.storeAsURL( fileURL, new PropertyValue[] {} ); + assure( "document still modified after saving it", !m_document.isModified() ); + } + + /* ------------------------------------------------------------------ */ + public void after() throws com.sun.star.uno.Exception, java.lang.Exception + { + impl_closeDocument(); + } + + /* ------------------------------------------------------------------ */ + private void impl_closeDocument() throws CloseVetoException + { + if ( m_document != null ) + { + XCloseable closeDoc = (XCloseable)UnoRuntime.queryInterface( XCloseable.class, + m_document.getDocument() ); + closeDoc.close( true ); + } + } + + /* ------------------------------------------------------------------ */ + private static void impl_bind( XPropertySet _control, XPropertySet _binding ) throws IncompatibleTypesException + { + XBindableValue bindableControl = (XBindableValue)UnoRuntime.queryInterface( + XBindableValue.class, _control ); + XValueBinding binding = (XValueBinding)UnoRuntime.queryInterface( + XValueBinding.class, _binding ); + bindableControl.setValueBinding( binding ); + } + + /* ------------------------------------------------------------------ */ + /** checks if master-detail relationships including multiple keys work + */ + public void checkExternalData() throws com.sun.star.uno.Exception, java.lang.Exception + { + // some controls + XPropertySet stringControl = m_formLayer.createLabeledControl( + "DatabaseTextField", "Task", 10, 10, 6 ); + impl_bind( stringControl, m_stringBinding ); + + XPropertySet booleanControl = m_formLayer.createControlAndShape( + "DatabaseCheckBox", 35, 18, 25, 6 ); + booleanControl.setPropertyValue( "Label", "has due date" ); + impl_bind( booleanControl, m_booleanBinding ); + + XPropertySet dateControl = m_formLayer.createControlAndShape( + "DatabaseDateField", 40, 26, 25, 6 ); + dateControl.setPropertyValue( "Dropdown", new Boolean( true ) ); + impl_bind( dateControl, m_dateBinding ); + + m_document.getCurrentView( ).toggleFormDesignMode( ); + + // ensure the model is set up as containing "document-internal" data + m_defaultModel.setIsDocumentInternalData( true ); + assure( "setting up the document to contain 'internal data' failed", + m_defaultModel.getIsDocumentInternalData() ); + impl_storeDocument(); + + // okay, here we go ... + // what this particular test is about is to check whether we can set up the model + // so that any changes to any controls bound to any data in this model actually marks + // the containing document as modified + m_formLayer.userTextInput( stringControl, "don't break this test" ); + assure( "model data changed, but document is not modified", + m_document.isModified() ); + + // TODO: do this with the other control/binding types, too + + // no the other way round: set up the model to contain "document-external" data + m_defaultModel.setIsDocumentInternalData( false ); + assure( "setting up the document to contain 'internal data' failed", + !m_defaultModel.getIsDocumentInternalData() ); + impl_storeDocument(); + + // and check that now, changes in the controls / model data are not reflected in + // document's modified state + m_formLayer.userTextInput( stringControl, "(or any other test, that is)" ); + assure( "model data changed, but document is modified", + !m_document.isModified() ); + + // ................................................................. + // finally, check whether the flag survives loading and saving + Model internalDataModel = m_document.addXFormModel( "internalData" ); + internalDataModel.setIsDocumentInternalData( true ); + Model externalDataModel = m_document.addXFormModel( "externalData" ); + externalDataModel.setIsDocumentInternalData( false ); + + impl_storeDocument(); + m_document.reload(); + + internalDataModel = m_document.getXFormModel( "internalData" ); + externalDataModel = m_document.getXFormModel( "externalData" ); + + assure( "setting up a model to contain 'internal data' did not survive reloading", + internalDataModel.getIsDocumentInternalData() ); + assure( "setting up a model to contain 'external data' did not survive reloading", + !externalDataModel.getIsDocumentInternalData() ); + } + + /* ------------------------------------------------------------------ */ + /** stores our document + * @throws com.sun.star.io.IOException + */ + private void impl_storeDocument() throws IOException + { + XStorable store = (XStorable)UnoRuntime.queryInterface( XStorable.class, + m_document.getDocument() ); + store.store(); + assure( "document still modified after saving it", !m_document.isModified() ); + } +} diff --git a/forms/qa/integration/forms/dbfTools.java b/forms/qa/integration/forms/dbfTools.java new file mode 100644 index 000000000000..2f100a2c2128 --- /dev/null +++ b/forms/qa/integration/forms/dbfTools.java @@ -0,0 +1,54 @@ +package integration.forms; + +import com.sun.star.uno.*; +import com.sun.star.lang.*; +import com.sun.star.beans.*; +import com.sun.star.container.*; + +/** provides global helpers +*/ +class dbfTools +{ + /* ------------------------------------------------------------------ */ + /** disposes the component given + */ + static public void disposeComponent( Object xComp ) throws java.lang.RuntimeException + { + XComponent xComponent = queryComponent( xComp ); + if ( null != xComponent ) + xComponent.dispose(); + } + + /* ------------------------------------------------------------------ */ + /** queries an object for the XPropertySet interface + */ + static public XPropertySet queryPropertySet( Object aComp ) + { + return (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, aComp ); + } + + /* ------------------------------------------------------------------ */ + /** queries an object for the XIndexContainer interface + */ + static public XIndexContainer queryIndexContainer( Object aComp ) + { + return (XIndexContainer)UnoRuntime.queryInterface( XIndexContainer.class, aComp ); + } + + /* ------------------------------------------------------------------ */ + /** queries an object for the XComponent interface + */ + static public XComponent queryComponent( Object aComp ) + { + return (XComponent)UnoRuntime.queryInterface( XComponent.class, aComp ); + } + + /* ------------------------------------------------------------------ */ + /** retrieves the parent of the given object + */ + static Object getParent( Object aComponent, Class aInterfaceClass ) + { + XChild xAsChild = (XChild)UnoRuntime.queryInterface( XChild.class, aComponent ); + return UnoRuntime.queryInterface( aInterfaceClass, xAsChild.getParent() ); + } +}; diff --git a/forms/qa/makefile.mk b/forms/qa/makefile.mk new file mode 100644 index 000000000000..b34529e2fbcf --- /dev/null +++ b/forms/qa/makefile.mk @@ -0,0 +1,95 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.2.20.2 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ = .. +TARGET = FormIntegrationTest +PRJNAME = forms + +# --- Settings ----------------------------------------------------- +.INCLUDE: settings.mk + + +.IF "$(BUILD_QADEVOOO)" == "YES" +#----- compile .java files ----------------------------------------- + +JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar ConnectivityTools.jar +JAVAFILES := $(shell @$(FIND) org -name "*.java") \ + $(shell @$(FIND) integration -name "*.java") +JAVACLASSFILES := $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(i:d)$/$(i:b).class) + +#----- make a jar from compiled files ------------------------------ + +MAXLINELENGTH = 100000 + +#JARCLASSDIRS = +JARTARGET = $(TARGET).jar +JARCOMPRESS = TRUE + +# --- Runner Settings ---------------------------------------------- + +# classpath and argument list +RUNNER_CLASSPATH = -cp "$(CLASSPATH)$(PATH_SEPERATOR)$(SOLARBINDIR)$/OOoRunner.jar$(PATH_SEPERATOR)$(SOLARBINDIR)$/ConnectivityTools.jar" +RUNNER_ARGS = org.openoffice.Runner -TestBase java_complex +.END + +# --- Targets ------------------------------------------------------ + +.IF "$(depend)" == "" +ALL : ALLTAR + @echo ----------------------------------------------------- + @echo - do a 'dmake show_targets' to show available targets + @echo ----------------------------------------------------- +.ELSE +ALL: ALLDEP +.ENDIF + +.INCLUDE : target.mk + +test: + echo $(SOLARBINDIR) + +.IF "$(BUILD_QADEVOOO)" == "YES" +show_targets: + +@$(AUGMENT_LIBRARY_PATH) java $(RUNNER_CLASSPATH) complexlib.ShowTargets $(foreach,i,$(JAVAFILES) $(i:s/.\$///:s/.java//)) + +run: + +$(COPY) integration$/forms$/*.props $(CLASSDIR)$/$(PACKAGE) && $(AUGMENT_LIBRARY_PATH) java $(RUNNER_CLASSPATH) $(RUNNER_ARGS) -sce forms_all.sce + +run_%: + +$(COPY) integration$/forms$/*.props $(CLASSDIR)$/$(PACKAGE) && $(AUGMENT_LIBRARY_PATH) java $(RUNNER_CLASSPATH) $(RUNNER_ARGS) -o integration.$(PRJNAME).$(@:s/run_//) + +.ELSE +run: show_targets + +show_targets: + +@echo "Built without qadevOOo, no QA tests" + +.ENDIF diff --git a/forms/qa/org/openoffice/xforms/Instance.java b/forms/qa/org/openoffice/xforms/Instance.java new file mode 100644 index 000000000000..5e4e04741995 --- /dev/null +++ b/forms/qa/org/openoffice/xforms/Instance.java @@ -0,0 +1,198 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.openoffice.xforms; + +import com.sun.star.xml.dom.DOMException; +import com.sun.star.xml.dom.XDocument; +import com.sun.star.xml.dom.XNode; +import com.sun.star.xml.dom.XNodeList; +import java.util.NoSuchElementException; + +/** + * + * @author fs93730 + */ +public class Instance +{ + private Model m_model; + private XDocument m_domInstance; + + protected Instance( Model _model, XDocument _domInstance ) + { + m_model = _model; + m_domInstance = _domInstance; + } + + /** creates a new element in the instance + * + * The element will be inserted immediately below the root node of the instance. + * + * @param _elementName + * the name of the to-be-created element + * @return + * the node of the newly created element + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createElement( String _elementName ) throws DOMException + { + return createElement( m_domInstance, _elementName, null ); + } + + /** creates a new element in the instance + * + * The element will be inserted immediately below the root node of the instance. + * + * @param _elementName + * the name of the to-be-created element + * @param _initialNodeValue + * the initial value to set at the node. Might be null, in this case no value is set. + * @return + * the node of the newly created element + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createElement( String _elementName, String _initialNodeValue ) throws DOMException + { + return createElement( m_domInstance, _elementName, _initialNodeValue ); + } + + /** creates a new element in the instance + * + * The element will be inserted immediately below a given XNode. + * + * @param _parentElement + * the node whose child shall be created + * @param _elementName + * the name of the to-be-created element + * @return + * the node of the newly created element + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createElement( XNode _parentElement, String _elementName ) throws DOMException + { + return createElement( _parentElement, _elementName, null ); + } + + /** creates a new element in the instance + * + * The element will be inserted immediately below a given XNode. + * + * @param _parentElement + * the node whose child shall be created + * @param _elementName + * the name of the to-be-created element + * @param _initialNodeValue + * the initial value to set at the node. Might be null, in this case no value is set. + * @return + * the node of the newly created element + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createElement( XNode _parentElement, String _elementName, String _initialNodeValue ) throws DOMException + { + XNode node = _parentElement.appendChild( + m_model.getUIHelper().createElement( _parentElement, _elementName ) + ); + if ( _initialNodeValue != null ) + node.setNodeValue( _initialNodeValue ); + return node; + } + + /** removes a child of the root-level node from the instance + * + * @param _elementName + * the name of the to-be-removed child + */ + public XNode removeNode( String _elementName ) throws DOMException + { + return removeNode( m_domInstance, _elementName ); + } + + /** removes a node from the instance + * + * @param _parentElement + * the node whose child is to be removed + * @param _elementName + * the name of the to-be-removed child + */ + public XNode removeNode( XNode _parentElement, String _elementName ) throws DOMException + { + XNodeList nodes = _parentElement.getChildNodes(); + for ( int i=0; i<nodes.getLength(); ++i ) + { + XNode node = nodes.item(i); + if ( node.getLocalName().equals( _elementName ) ) + { + _parentElement.removeChild( node ); + return node; + } + } + throw new NoSuchElementException(); + } + + /** creates an attribute for the root node of the instance + * + * @param _attribName + * the name of the to-be-created attribute + * @return + * the DOM node, which has already been inserted into the DOM tree + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createAttribute( String _attribName ) throws DOMException + { + return createAttribute( m_domInstance, _attribName, null ); + } + + /** creates an attribute for the root node of the instance + * + * @param _attribName + * the name of the to-be-created attribute + * @param _initialNodeValue + * the initial value to set at the node. Might be null, in this case no value is set. + * @return + * the DOM node, which has already been inserted into the DOM tree + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createAttribute( String _attribName, String _initialNodeValue ) throws DOMException + { + return createAttribute( m_domInstance, _attribName, _initialNodeValue ); + } + + /** creates an attribute for the given node + * + * @param _parentElement + * the element at which the attribute should be created + * @param _attribName + * the name of the to-be-created attribute + * @return + * the DOM node, which has already been inserted into the DOM tree + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createAttribute( XNode _parentElement, String _attribName ) throws DOMException + { + return createAttribute( _parentElement, _attribName, null ); + } + + /** creates an attribute for the given node + * + * @param _parentElement + * the element at which the attribute should be created + * @param _attribName + * the name of the to-be-created attribute + * @param _initialNodeValue + * the initial value to set at the node. Might be null, in this case no value is set. + * @return + * the DOM node, which has already been inserted into the DOM tree + * @throws com.sun.star.xml.dom.DOMException + */ + public XNode createAttribute( XNode _parentElement, String _attribName, String _initialNodeValue ) throws DOMException + { + XNode node = _parentElement.appendChild( + m_model.getUIHelper().createAttribute( _parentElement, _attribName ) + ); + if ( _initialNodeValue != null ) + node.setNodeValue( _initialNodeValue ); + return node; + } +} diff --git a/forms/qa/org/openoffice/xforms/Model.java b/forms/qa/org/openoffice/xforms/Model.java new file mode 100644 index 000000000000..ee4ed6caa7e8 --- /dev/null +++ b/forms/qa/org/openoffice/xforms/Model.java @@ -0,0 +1,100 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.openoffice.xforms; + +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.XPropertySet; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.xforms.XFormsUIHelper1; +import com.sun.star.xforms.XModel; +import com.sun.star.xml.dom.XNode; + +/** encapsulates an XForms model + * + * @author fs93730 + */ +public class Model +{ + private XModel m_model; + private XPropertySet m_modelProps; + private XFormsUIHelper1 m_helper; + + protected Model( Object _model ) + { + m_model = (XModel)UnoRuntime.queryInterface( XModel.class, _model ); + m_modelProps = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, _model ); + m_helper = (XFormsUIHelper1)UnoRuntime.queryInterface( XFormsUIHelper1.class, + m_model ); + } + + protected XModel getXModel() + { + return m_model; + } + + protected XFormsUIHelper1 getUIHelper() + { + return m_helper; + } + + public Instance getDefaultInstance() + { + return new Instance( this, m_model.getDefaultInstance() ); + } + + /** creates a binding for the given DOM node + * + * @param _node + * the DOM node to create a binding for + * @param _dataType + * the data type to be used for the binding + * @return + */ + public XPropertySet createBindingForNode( XNode _node, short _dataTypeClass ) + { + XPropertySet binding = m_helper.getBindingForNode(_node, true); + try + { + String basicTypeName = (String)m_model.getDataTypeRepository().getBasicDataType( _dataTypeClass ). + getPropertyValue( "Name" ); + binding.setPropertyValue( "Type", basicTypeName ); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + return binding; + } + + public void setIsDocumentInternalData( boolean _internalData ) + { + try + { + m_modelProps.setPropertyValue("ExternalData", new Boolean(!_internalData)); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + public boolean getIsDocumentInternalData() + { + boolean isInternalData = false; + try + { + isInternalData = !((Boolean)m_modelProps.getPropertyValue( "ExternalData" )).booleanValue(); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + return isInternalData; + } +} diff --git a/forms/qa/org/openoffice/xforms/XMLDocument.java b/forms/qa/org/openoffice/xforms/XMLDocument.java new file mode 100644 index 000000000000..9ca35b3801da --- /dev/null +++ b/forms/qa/org/openoffice/xforms/XMLDocument.java @@ -0,0 +1,96 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.openoffice.xforms; + +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.XNameContainer; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.XComponent; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.uno.Exception; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.xforms.XFormsSupplier; +import com.sun.star.xforms.XFormsUIHelper1; +import com.sun.star.xforms.XModel; +import integration.forms.DocumentType; + +/** + * + * @author fs93730 + */ +public class XMLDocument extends integration.forms.DocumentHelper +{ + private XFormsSupplier m_formsSupplier; + private XNameContainer m_forms; + + /* ------------------------------------------------------------------ */ + public XMLDocument( XMultiServiceFactory _orb ) throws Exception + { + super( _orb, implLoadAsComponent( _orb, getDocumentFactoryURL( DocumentType.XMLFORM ) ) ); + impl_initialize( getDocument() ); + } + + /* ------------------------------------------------------------------ */ + public XMLDocument( XMultiServiceFactory _orb, XComponent _document ) + { + super( _orb, _document ); + impl_initialize( _document ); + } + + /* ------------------------------------------------------------------ */ + private void impl_initialize( XComponent _document ) + { + m_formsSupplier = (XFormsSupplier)UnoRuntime.queryInterface( XFormsSupplier.class, + _document ); + + if ( m_formsSupplier == null ) + throw new IllegalArgumentException(); + + m_forms = m_formsSupplier.getXForms(); + } + + /* ------------------------------------------------------------------ */ + public String[] getXFormModelNames() + { + return m_forms.getElementNames(); + } + + /* ------------------------------------------------------------------ */ + public Model getXFormModel( String _modelName ) throws NoSuchElementException + { + try + { + return new Model(m_forms.getByName(_modelName)); + } + catch (WrappedTargetException ex) + { + throw new NoSuchElementException(); + } + } + + /* ------------------------------------------------------------------ */ + public Model addXFormModel( String _modelName ) + { + XModel newModel = null; + try + { + newModel = (XModel) UnoRuntime.queryInterface( XModel.class, + getOrb().createInstance( "com.sun.star.xforms.Model" ) ); + newModel.setID(_modelName); + XFormsUIHelper1 modelHelper = (XFormsUIHelper1) UnoRuntime.queryInterface( + XFormsUIHelper1.class, newModel ); + modelHelper.newInstance( "Instance 1", new String(), true ); + newModel.initialize(); + + m_forms.insertByName(_modelName, newModel); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + return new Model( newModel ); + } +} diff --git a/forms/qa/unoapi/forms.sce b/forms/qa/unoapi/forms.sce new file mode 100644 index 000000000000..97e9c7422f35 --- /dev/null +++ b/forms/qa/unoapi/forms.sce @@ -0,0 +1,40 @@ +-o forms.OButtonControl +-o forms.OButtonModel +-o forms.OCheckBoxControl +-o forms.OCheckBoxModel +-o forms.OComboBoxControl +-o forms.OComboBoxModel +-o forms.OCurrencyControl +-o forms.OCurrencyModel +#-o forms.ODatabaseForm +-o forms.ODateControl +-o forms.ODateModel +-o forms.OEditControl +-o forms.OEditModel +-o forms.OFileControlModel +-o forms.OFixedTextModel +-o forms.OFormattedControl +-o forms.OFormattedFieldWrapper +# LäSST EIN DOKUMENT OFFEN -o forms.OFormsCollection +-o forms.OGridControlModel +-o forms.OGroupBoxControl +-o forms.OGroupBoxModel +-o forms.OHiddenModel +-o forms.OImageButtonControl +-o forms.OImageButtonModel +-o forms.OImageControlControl +-o forms.OImageControlModel +-o forms.OListBoxControl +-o forms.OListBoxModel +-o forms.ONavigationBarControl +-o forms.ONavigationBarModel +-o forms.ONumericControl +-o forms.ONumericModel +-o forms.OPatternControl +-o forms.OPatternModel +-o forms.ORadioButtonControl +-o forms.ORadioButtonModel +-o forms.OScrollBarModel +-o forms.OSpinButtonModel +-o forms.OTimeControl +-o forms.OTimeModel diff --git a/forms/qa/unoapi/knownissues.xcl b/forms/qa/unoapi/knownissues.xcl new file mode 100644 index 000000000000..1cec8ac106a2 --- /dev/null +++ b/forms/qa/unoapi/knownissues.xcl @@ -0,0 +1,118 @@ +### i45204 ### +forms.OCurrencyModel::com::sun::star::form::XUpdateBroadcaster + +### i84235 ### +forms.ODatabaseForm::com::sun::star::sdbc::XWarningsSupplier + +### i45204 ### +forms.OCurrencyModel::com::sun::star::form::XUpdateBroadcaster + +### i79098 ### +forms.OScrollBarModel::com::sun::star::awt::UnoControlScrollBarModel + +### i79100 ### +forms.ORadioButtonModel::com::sun::star::awt::UnoControlRadioButtonModel + +### i79108 ### +forms.OButtonControl::com::sun::star::form::submission::XSubmission + +### i79108 ### +forms.OImageButtonControl::com::sun::star::form::submission::XSubmission + +### i79109 ### +forms.OFixedTextModel::com::sun::star::awt::UnoControlFixedTextModel + +### i79110 ### +forms.OCheckBoxModel::com::sun::star::awt::UnoControlCheckBoxModel + +### i79111 ### +forms.OButtonModel::com::sun::star::awt::UnoControlButtonModel + +### i84283 ### +forms.ODatabaseForm::com::sun::star::form::XDatabaseParameterBroadcaster + +### i84298 ### +forms.ODatabaseForm::com::sun::star::sdbc::XParameters + +### i73994 ### +forms.OEditModel::com::sun::star::style::ParagraphProperties + +### i84311 ### +forms.OFixedTextModel::com::sun::star::beans::XMultiPropertySet + +### i84311 ### +forms.OFixedTextModel::com::sun::star::beans::XFastPropertySet + +### i84314 ### +forms.OImageButtonModel::com::sun::star::awt::UnoControlImageControlModel + +### i84315 ### +forms.OImageControlModel::com::sun::star::awt::UnoControlImageControlModel + +### i84316 ### +forms.ONumericModel::com::sun::star::form::XUpdateBroadcaster + +### i46489 ### +forms.ORadioButtonControl::com::sun::star::awt::XWindow +forms.OCheckBoxControl::com::sun::star::awt::XWindow +forms.OGroupBoxControl::com::sun::star::awt::XWindow +forms.OListBoxControl::com::sun::star::awt::XWindow +forms.OComboBoxControl::com::sun::star::awt::XWindow +forms.OEditControl::com::sun::star::awt::XWindow +forms.ODateControl::com::sun::star::awt::XWindow +forms.OTimeControl::com::sun::star::awt::XWindow +forms.ONumericControl::com::sun::star::awt::XWindow +forms.OCurrencyControl::com::sun::star::awt::XWindow +forms.OPatternControl::com::sun::star::awt::XWindow +forms.OFormattedControl::com::sun::star::awt::XWindow +forms.OButtonControl::com::sun::star::awt::XWindow +forms.OImageButtonControl::com::sun::star::awt::XWindow +forms.OImageControlControl::com::sun::star::awt::XWindow +forms.ONavigationBarControl::com::sun::star::awt::XWindow + +### i87212 ### +forms.ONavigationBarControl::com::sun::star::lang::XComponent + +### i87213 ### +forms.OGroupBoxControl::com::sun::star::awt::XView +forms.OListBoxControl::com::sun::star::awt::XView +forms.OEditControl::com::sun::star::awt::XView +forms.ORadioButtonControl::com::sun::star::awt::XView +forms.OButtonControl::com::sun::star::awt::XView +forms.OPatternControl::com::sun::star::awt::XView +forms.OCheckBoxControl::com::sun::star::awt::XView +forms.OTimeControl::com::sun::star::awt::XView +forms.OCurrencyControl::com::sun::star::awt::XView +forms.OFormattedControl::com::sun::star::awt::XView +forms.ONumericControl::com::sun::star::awt::XView +forms.OImageButtonControl::com::sun::star::awt::XView +forms.OComboBoxControl::com::sun::star::awt::XView +forms.ODateControl::com::sun::star::awt::XView +forms.OImageControlControl::com::sun::star::awt::XView +forms.ONavigationBarControl::com::sun::star::awt::XView + +### i87214 ### +forms.OEditControl::com::sun::star::form::XChangeBroadcaster + +### i87215 ### +forms.OListBoxControl::com::sun::star::form::XChangeBroadcaster + +### i87861 ### +forms.OEditModel::com::sun::star::form::XUpdateBroadcaster + +### i89421 ### +forms.OGroupBoxModel::com::sun::star::lang::XComponent + +### i89422 ### +forms.OHiddenModel::com::sun::star::form::component::HiddenControl + +### i90352 ### +forms.OListBoxControl::com::sun::star::lang::XComponent + +### i94950 ### +forms.OTimeModel::com::sun::star::form::XUpdateBroadcaster +forms.OPatternModel::com::sun::star::form::XUpdateBroadcaster +forms.OListBoxModel::com::sun::star::form::XUpdateBroadcaster +forms.OFormattedFieldWrapper::com::sun::star::form::XUpdateBroadcaster +forms.ODateModel::com::sun::star::form::XUpdateBroadcaster +forms.OComboBoxModel::com::sun::star::form::XUpdateBroadcaster diff --git a/forms/qa/unoapi/makefile.mk b/forms/qa/unoapi/makefile.mk new file mode 100644 index 000000000000..bebfe057c4d2 --- /dev/null +++ b/forms/qa/unoapi/makefile.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.8 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=forms +TARGET=qa_unoapi + +.INCLUDE: settings.mk + +.INCLUDE: target.mk + +ALLTAR : UNOAPI_TEST + +UNOAPI_TEST: + +$(SOLARENV)$/bin$/checkapi -sce forms.sce -xcl knownissues.xcl -DOCPTH $(PWD)$/testdocuments -THRCNT 1 -tdoc $(PWD)$/testdocuments + @echo ======================================================================= + @echo Problems with controls might me focus problems during the run of XView + @echo these seems to appear by chance ... just re-run those testcases with + @echo $(SOLARENV)$/bin$/checkapi -o componentName -xcl knownissues.xcl -DOCPTH $(PWD)$/testdocuments -THRCNT 1 -tdoc $(PWD)$/testdocuments + @echo ======================================================================= + +run_%: + +$(SOLARENV)$/bin$/checkapi -o $(PRJNAME).$(@:s/run_//) -xcl knownissues.xcl -DOCPTH $(PWD)$/testdocuments -THRCNT 1 -tdoc $(PWD)$/testdocuments diff --git a/forms/qa/unoapi/testdocuments/TestDB/testDB.dbf b/forms/qa/unoapi/testdocuments/TestDB/testDB.dbf Binary files differnew file mode 100644 index 000000000000..aa3c8262a5e0 --- /dev/null +++ b/forms/qa/unoapi/testdocuments/TestDB/testDB.dbf diff --git a/forms/qa/unoapi/testdocuments/TestDB/testDB.dbt b/forms/qa/unoapi/testdocuments/TestDB/testDB.dbt Binary files differnew file mode 100644 index 000000000000..2183ea7ba67d --- /dev/null +++ b/forms/qa/unoapi/testdocuments/TestDB/testDB.dbt |