| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| import com.sun.star.beans.PropertyChangeEvent; |
| import com.sun.star.beans.XPropertyChangeListener; |
| import com.sun.star.beans.XPropertySet; |
| |
| |
| // __________ Imports __________ |
| import com.sun.star.beans.XPropertySetInfo; |
| |
| // base classes |
| import com.sun.star.container.XIndexContainer; |
| import com.sun.star.container.XNameAccess; |
| import com.sun.star.container.XNamed; |
| import com.sun.star.form.FormComponentType; |
| import com.sun.star.form.ListSourceType; |
| import com.sun.star.form.XGridColumnFactory; |
| import com.sun.star.form.XReset; |
| import com.sun.star.form.XResetListener; |
| import com.sun.star.form.runtime.FormFeature; |
| import com.sun.star.lang.EventObject; |
| import com.sun.star.lang.XComponent; |
| import com.sun.star.sdb.CommandType; |
| import com.sun.star.sdb.XColumnUpdate; |
| import com.sun.star.sdbc.ResultSetConcurrency; |
| import com.sun.star.sdbc.XConnection; |
| import com.sun.star.sdbc.XDataSource; |
| import com.sun.star.sdbc.XStatement; |
| import com.sun.star.sdbcx.XColumnsSupplier; |
| import com.sun.star.uno.UnoRuntime; |
| import com.sun.star.uno.XInterface; |
| |
| /**************************************************************************/ |
| /** a class for enumerating a form component tree |
| */ |
| class PrintComponentTree extends ComponentTreeTraversal |
| { |
| private String m_sPrefix; |
| |
| public PrintComponentTree() |
| { |
| m_sPrefix = new String(); |
| } |
| |
| public void handle( Object aFormComponent ) throws com.sun.star.uno.Exception |
| { |
| // the name of the child |
| XNamed xName = (XNamed)UnoRuntime.queryInterface( XNamed.class, aFormComponent ); |
| |
| // if it's a form control model, check it's type |
| XPropertySet xProps = UNO.queryPropertySet( aFormComponent ); |
| String sTypeName = FLTools.classifyFormComponentType( xProps ); |
| |
| String sName; |
| if ( null == xName ) |
| sName = "<unnamed>"; |
| else |
| sName = xName.getName(); |
| |
| // print the component's name |
| if ( 0 != sTypeName.length() ) |
| { |
| System.out.println( m_sPrefix + sName + " (" + sTypeName + ")" ); |
| } |
| else |
| { |
| System.out.println( m_sPrefix + sName ); |
| } |
| |
| // let the super class step down the tree |
| m_sPrefix = m_sPrefix + " "; |
| super.handle( aFormComponent ); |
| m_sPrefix = m_sPrefix.substring( 0, m_sPrefix.length() - 1 ); |
| } |
| }; |
| |
| /**************************************************************************/ |
| /** a class revoking button models from a ButtonOperator instance |
| */ |
| class RevokeButtons extends ComponentTreeTraversal |
| { |
| private ButtonOperator m_aOperator; |
| |
| public RevokeButtons( ButtonOperator aOperator ) |
| { |
| m_aOperator = aOperator; |
| } |
| |
| public void handle( Object aFormComponent ) throws com.sun.star.uno.Exception |
| { |
| // check if it's a button |
| XPropertySet xProps = UNO.queryPropertySet( aFormComponent ); |
| XPropertySetInfo xPI = null; |
| if ( null != xProps ) |
| xPI = xProps.getPropertySetInfo(); |
| if ( ( null != xPI ) && xPI.hasPropertyByName( "ClassId" ) ) |
| { |
| Short nClassId = (Short)xProps.getPropertyValue( "ClassId" ); |
| if ( FormComponentType.COMMANDBUTTON == nClassId.shortValue() ) |
| { |
| // yes, it is |
| m_aOperator.revokeButton( xProps ); |
| } |
| } |
| |
| // let the super class step down the tree (if possible) |
| super.handle( aFormComponent ); |
| } |
| } |
| |
| /**************************************************************************/ |
| public class DataAwareness extends DocumentBasedExample implements XPropertyChangeListener, XResetListener |
| { |
| /* ================================================================== */ |
| private HsqlDatabase m_database; |
| |
| private static final String s_tableNameSalesmen = "SALESMEN"; |
| private static final String s_tableNameCustomers = "CUSTOMERS"; |
| private static final String s_tableNameSales = "SALES"; |
| |
| private XPropertySet m_xMasterForm; |
| private ButtonOperator m_aOperator; |
| private SalesFilter m_aSalesFilter; |
| |
| private KeyGenerator m_aSalesmanKeyGenerator; |
| private KeyGenerator m_aSalesKeyGenerator; |
| private ControlLock m_aSalesmenLocker; |
| private ControlLock m_aSalesLocker; |
| private GridFieldValidator m_aSalesNameValidator; |
| |
| private boolean m_bDefaultSalesDate; |
| private boolean m_bProtectKeyFields; |
| private boolean m_bAllowEmptySales; |
| |
| /* ------------------------------------------------------------------ */ |
| public DataAwareness() |
| { |
| super( DocumentType.WRITER ); |
| m_bDefaultSalesDate = false; |
| m_bProtectKeyFields = false; |
| m_bAllowEmptySales = false; |
| } |
| |
| /* ================================================================== |
| = form components |
| ================================================================== */ |
| |
| /* ------------------------------------------------------------------ */ |
| /** enumerates and prints all the elements in the given container, together with the container itself |
| */ |
| protected void enumFormComponents( XNameAccess xContainer ) throws java.lang.Exception |
| { |
| String sObjectName; |
| |
| XNamed xNameAcc = (XNamed)UnoRuntime.queryInterface( XNamed.class, xContainer ); |
| if ( null == xNameAcc ) |
| sObjectName = new String( "<unnamed>" ); |
| else |
| sObjectName = xNameAcc.getName(); |
| System.out.println( new String( "enumerating the container named \"" ) + sObjectName + |
| new String( "\"\n" ) ); |
| |
| PrintComponentTree aPrinter = new PrintComponentTree(); |
| aPrinter.handle( xContainer ); |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** enumerates and prints all form elements in the document |
| */ |
| protected void enumFormComponents( ) throws java.lang.Exception |
| { |
| enumFormComponents( m_document.getFormComponentTreeRoot() ); |
| } |
| |
| /* ================================================================== |
| = UNO callbacks |
| ================================================================== */ |
| |
| /* ------------------------------------------------------------------ */ |
| // XResetListener overridables |
| /* ------------------------------------------------------------------ */ |
| public boolean approveReset( EventObject aEvent ) throws com.sun.star.uno.RuntimeException |
| { |
| // not interested in vetoing this |
| return true; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| public void resetted( EventObject aEvent ) throws com.sun.star.uno.RuntimeException |
| { |
| // check if this reset occured becase we're on a new record |
| XPropertySet xFormProps = UNO.queryPropertySet( aEvent.Source ); |
| try |
| { |
| Boolean aIsNew = (Boolean)xFormProps.getPropertyValue( "IsNew" ); |
| if ( aIsNew.booleanValue() ) |
| { // yepp |
| |
| if ( !m_bDefaultSalesDate ) |
| { // we're interested to do all this only if the user told us to default the sales date |
| // to "today" |
| // As date fields do this defaulting automatically, the semantics is inverted here: |
| // If we're told to default, we must do nothing, if we should not default, we must |
| // reset the value which the date field set automatically. |
| |
| Integer aConcurrency = (Integer)xFormProps.getPropertyValue( "ResultSetConcurrency" ); |
| if ( ResultSetConcurrency.READ_ONLY != aConcurrency.intValue() ) |
| { |
| // we're going to modify the record, though after that, to the user, it should look |
| // like it has not been modified |
| // So we need to ensure that we do not change the IsModified property with whatever we do |
| Object aModifiedFlag = xFormProps.getPropertyValue( "IsModified" ); |
| |
| |
| // get the columns of our master form |
| XColumnsSupplier xSuppCols = (XColumnsSupplier)UnoRuntime.queryInterface( |
| XColumnsSupplier.class, xFormProps ); |
| XNameAccess xCols = xSuppCols.getColumns(); |
| |
| // and update the date column with a NULL value |
| XColumnUpdate xDateColumn = (XColumnUpdate)UnoRuntime.queryInterface( |
| XColumnUpdate.class, xCols.getByName( "SALEDATE" ) ); |
| xDateColumn.updateNull(); |
| |
| |
| // then restore the flag |
| xFormProps.setPropertyValue( "IsModified", aModifiedFlag ); |
| } |
| } |
| } |
| } |
| catch( com.sun.star.uno.Exception e ) |
| { |
| System.out.println(e); |
| e.printStackTrace(); |
| } |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| // XPropertyChangeListener overridables |
| /* ------------------------------------------------------------------ */ |
| public void propertyChange( PropertyChangeEvent aEvent ) throws com.sun.star.uno.RuntimeException |
| { |
| try |
| { |
| // did it come from a radio button or checkbox? |
| if ( aEvent.PropertyName.equals( "State" ) ) |
| { // yep |
| Short aNewState = (Short)aEvent.NewValue; |
| |
| XPropertySet xModel = UNO.queryPropertySet( aEvent.Source ); |
| String sName = (String)xModel.getPropertyValue( "Name" ); |
| |
| Short aClassId = (Short)xModel.getPropertyValue( "ClassId" ); |
| if ( FormComponentType.RADIOBUTTON == aClassId.shortValue() ) |
| { |
| String sRefValue = (String)xModel.getPropertyValue( "RefValue" ); |
| |
| short nNewValue = ((Short)aEvent.NewValue).shortValue(); |
| if ( sName.equals( "KeyGen" ) ) |
| { |
| // it's one of the options for key generation |
| if ( sRefValue.equals( "none" ) ) |
| { // no automatic generation at all |
| m_aSalesmanKeyGenerator.stopGenerator( ); |
| m_aSalesKeyGenerator.stopGenerator( ); |
| } |
| else |
| { |
| boolean bGenerateOnReset = true; |
| if ( sRefValue.equals( "update" ) ) |
| { // generate on update |
| bGenerateOnReset = ( 0 == nNewValue ); |
| } |
| else if ( sRefValue.equals( "reset" ) ) |
| { // generat on reset |
| bGenerateOnReset = ( 0 != nNewValue ); |
| } |
| m_aSalesmanKeyGenerator.activateKeyGenerator( bGenerateOnReset ); |
| m_aSalesKeyGenerator.activateKeyGenerator( bGenerateOnReset ); |
| } |
| } |
| } |
| else if ( FormComponentType.CHECKBOX == aClassId.shortValue() ) |
| { |
| boolean bEnabled = ( 0 != aNewState.shortValue() ); |
| if ( sName.equals( "defaultdate" ) ) |
| { |
| m_bDefaultSalesDate = bEnabled; |
| } |
| else if ( sName.equals( "protectkeys" ) ) |
| { |
| m_bProtectKeyFields = bEnabled; |
| m_aSalesmenLocker.enableLock( m_bProtectKeyFields ); |
| m_aSalesLocker.enableLock( m_bProtectKeyFields ); |
| } |
| else if ( sName.equals( "emptysales" ) ) |
| { |
| m_bAllowEmptySales = bEnabled; |
| m_aSalesNameValidator.enableColumnWatch( m_bAllowEmptySales ); |
| } |
| } |
| } |
| } |
| catch(com.sun.star.uno.Exception e) |
| { |
| System.out.println(e); |
| e.printStackTrace(); |
| } |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| // XEventListener overridables |
| /* ------------------------------------------------------------------ */ |
| public void disposing( EventObject aEvent ) |
| { |
| // simply disambiguate |
| super.disposing( aEvent ); |
| } |
| |
| /* ================================================================== |
| = miscellaneous |
| ================================================================== */ |
| |
| /* ------------------------------------------------------------------ */ |
| /** skips line feeds in the input stream |
| |
| @returns |
| the first character which does not belong to a line feed |
| */ |
| protected int skipLineFeeds( java.io.InputStream aInput ) throws java.io.IOException |
| { |
| // read characters, until we encounter something which is not a line feed character |
| int nChar = aInput.read( ); |
| while ( ( 13 == nChar ) || ( 10 == nChar ) ) |
| nChar = aInput.read( ); |
| |
| // now read everything which is behind this single character we are interested in |
| while ( 0 < aInput.available() ) |
| aInput.read( ); |
| |
| return nChar; |
| } |
| |
| /* ================================================================== |
| = table handling |
| ================================================================== */ |
| /* ------------------------------------------------------------------ */ |
| /** checks if a given table exists. |
| |
| <p>The check is made using a SELECT statement, so even if the connection |
| is a n SDB-level connection, which may filter tables in it's table |
| supplier, the result may be reliable ....</p> |
| */ |
| protected boolean existsInvisibleTable( XConnection xConn, String sTableName ) throws java.lang.Exception |
| { |
| String sStatement = "SELECT * FROM "; |
| sStatement += sTableName; |
| sStatement += " WHERE 0=1"; |
| |
| boolean bSuccess = false; |
| try |
| { |
| XStatement xStatement = xConn.createStatement(); |
| xStatement.execute( sStatement ); |
| // if we reached this point, the table probably exists |
| bSuccess = true; |
| } |
| catch(com.sun.star.sdbc.SQLException e) |
| { |
| } |
| return bSuccess; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** add a specified table name to the table filter of the given data source. |
| */ |
| protected void makeTableVisible( XDataSource xDS, XConnection xConn, String sTableName ) throws java.lang.Exception |
| { |
| // get the table filter |
| XPropertySet xDSP = UNO.queryPropertySet( xDS ); |
| String[] aCurrentFilter = (String[])xDSP.getPropertyValue( "TableFilter" ); |
| |
| // check if the table name is already part of it |
| String sAllTables = "*"; // all tables |
| |
| for ( int i=0; i<aCurrentFilter.length; ++i ) |
| { |
| String sCurrentTableFilter = aCurrentFilter[i]; |
| |
| if ( sCurrentTableFilter.equals( sTableName ) ) |
| return; |
| if ( sCurrentTableFilter.equals( sAllTables ) ) |
| return; |
| } |
| |
| // if we are here, we have to add our table to the filter sequence |
| String[] aNewFilter = new String[ aCurrentFilter.length + 1 ]; |
| // copy the existent filter entries |
| for ( int i=0; i<aCurrentFilter.length; ++i ) |
| aNewFilter[i] = aCurrentFilter[i]; |
| // add our table |
| aNewFilter[ aCurrentFilter.length ] = sTableName; |
| |
| xDSP.setPropertyValue( "TableFilter", aNewFilter ); |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** executes the given statement on the given connection |
| */ |
| protected boolean implExecuteStatement( XConnection xConn, String sStatement ) throws java.lang.Exception |
| { |
| try |
| { |
| XStatement xStatement = xConn.createStatement( ); |
| xStatement.execute( sStatement ); |
| } |
| catch(com.sun.star.sdbc.SQLException e) |
| { |
| System.err.println( e ); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** creates the table witht the given name, using the given statement |
| */ |
| protected boolean implCreateTable( XConnection xConn, String sCreateStatement, String sTableName ) throws java.lang.Exception |
| { |
| if ( !implExecuteStatement( xConn, sCreateStatement ) ) |
| { |
| System.out.println( " could not create the table " + sTableName + "." ); |
| System.out.println( ); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** creates the table SALESMEN |
| |
| @return |
| <TRUE/> if and only if the creation succeeded |
| */ |
| protected boolean createTableSalesman( XConnection xConn ) throws java.lang.Exception |
| { |
| String sCreateStatement = "CREATE TABLE " + s_tableNameSalesmen + " "; |
| sCreateStatement += "(SNR INTEGER NOT NULL, "; |
| sCreateStatement += "FIRSTNAME VARCHAR(50), "; |
| sCreateStatement += "LASTNAME VARCHAR(100), "; |
| sCreateStatement += "STREET VARCHAR(50), "; |
| sCreateStatement += "STATE VARCHAR(50), "; |
| sCreateStatement += "ZIP INTEGER, "; |
| sCreateStatement += "BIRTHDATE DATE, "; |
| sCreateStatement += "PRIMARY KEY(SNR))"; |
| |
| if ( implCreateTable( xConn, sCreateStatement, s_tableNameSalesmen) ) |
| { |
| String sInsertionPrefix = "INSERT INTO " + s_tableNameSalesmen + " VALUES "; |
| |
| implExecuteStatement( xConn, sInsertionPrefix + "(1, 'Joseph', 'Smith', 'Bond Street', 'CA', 95460, '1946-07-02')" ); |
| implExecuteStatement( xConn, sInsertionPrefix + "(2, 'Frank', 'Jones', 'Lake silver', 'CA', 95460, '1963-12-24')" ); |
| implExecuteStatement( xConn, sInsertionPrefix + "(3, 'Jane', 'Esperansa', '23 Hollywood driver', 'CA', 95460, '1972-04-01')" ); |
| |
| return true; |
| } |
| return false; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** creates the table CUSTOMERS |
| |
| @return |
| <TRUE/> if and only if the creation succeeded |
| */ |
| protected boolean createTableCustomer( XConnection xConn ) throws java.lang.Exception |
| { |
| String sCreateStatement = "CREATE TABLE " + s_tableNameCustomers + " "; |
| sCreateStatement += "(COS_NR INTEGER NOT NULL, "; |
| sCreateStatement += "LASTNAME VARCHAR(100), "; |
| sCreateStatement += "STREET VARCHAR(50), "; |
| sCreateStatement += "CITY VARCHAR(50), "; |
| sCreateStatement += "STATE VARCHAR(50), "; |
| sCreateStatement += "ZIP INTEGER, "; |
| sCreateStatement += "PRIMARY KEY(COS_NR))"; |
| |
| if ( implCreateTable( xConn, sCreateStatement, s_tableNameCustomers ) ) |
| { |
| String sInsertionPrefix = "INSERT INTO " + s_tableNameCustomers + " VALUES "; |
| |
| implExecuteStatement( xConn, sInsertionPrefix + "(100, 'Acme, Inc.', '99 Market Street', 'Groundsville', 'CA', 95199)" ); |
| implExecuteStatement( xConn, sInsertionPrefix + "(101, 'Superior BugSoft', '1 Party Place', 'Mendocino', 'CA', 95460)"); |
| implExecuteStatement( xConn, sInsertionPrefix + "(102, 'WeKnowAll, Inc.', '100 Coffee Lane', 'Meadows', 'CA', 93699)"); |
| |
| return true; |
| } |
| return false; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** creates the table SALES |
| |
| @return |
| <TRUE/> if and only if the creation succeeded |
| */ |
| protected boolean createTableSales( XConnection xConn ) throws java.lang.Exception |
| { |
| String sCreateStatement = "CREATE TABLE " + s_tableNameSales + " "; |
| sCreateStatement += "(SALENR INTEGER NOT NULL, "; |
| sCreateStatement += "COS_NR INTEGER NOT NULL, "; |
| sCreateStatement += "SNR INTEGER NOT NULL, "; |
| sCreateStatement += "NAME VARCHAR(50), "; |
| sCreateStatement += "SALEDATE DATE, "; |
| sCreateStatement += "PRICE DECIMAL(8,2), "; |
| sCreateStatement += "PRIMARY KEY(SALENR))"; |
| |
| if ( implCreateTable( xConn, sCreateStatement, s_tableNameSales ) ) |
| { |
| String sInsertionPrefix = "INSERT INTO " + s_tableNameSales + " VALUES "; |
| |
| implExecuteStatement( xConn, sInsertionPrefix + "(1, 100, 1, 'Fruits', '2005-02-12', 39.99)" ); |
| implExecuteStatement( xConn, sInsertionPrefix + "(2, 101, 3, 'Beef', '2005-10-18', 15.78)" ); |
| implExecuteStatement( xConn, sInsertionPrefix + "(3, 102, 3, 'Orange Juice', '2005-09-08', 25.63)" ); |
| implExecuteStatement( xConn, sInsertionPrefix + "(4, 101, 2, 'Oil', '2005-03-01', 12.30)" ); |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** ensures that the tables we need for our example exist |
| */ |
| protected void ensureTables() throws java.lang.Exception |
| { |
| // get the data source |
| XDataSource xDS = m_database.getDataSource(); |
| XPropertySet xDSProps = UNO.queryPropertySet( xDS ); |
| |
| // connect to this data source |
| XConnection xConn = xDS.getConnection( "", "" ); |
| XComponent xConnComp = UNO.queryComponent( xConn ); |
| |
| createTableSalesman( xConn ); |
| createTableCustomer( xConn ); |
| createTableSales( xConn ); |
| |
| // free the resources acquired by the connection |
| xConnComp.dispose(); |
| } |
| |
| /* ================================================================== |
| = sample document handling |
| ================================================================== */ |
| |
| /* ------------------------------------------------------------------ */ |
| /** creates the button used for demonstrating (amonst others) event handling |
| @param nXPos |
| x-position of the to be inserted shape |
| @param nYPos |
| y-position of the to be inserted shape |
| @param nXSize |
| width of the to be inserted shape |
| @param sName |
| the name of the model in the form component hierarchy |
| @param sLabel |
| the label of the button control |
| @param sActionURL |
| the URL of the action which should be triggered by the button |
| @return |
| the model of the newly created button |
| */ |
| protected XPropertySet createButton( int nXPos, int nYPos, int nXSize, String sName, String sLabel, short _formFeature ) throws java.lang.Exception |
| { |
| XPropertySet xButton = m_formLayer.createControlAndShape( "CommandButton", nXPos, nYPos, nXSize, 6 ); |
| // the name for referring to it later: |
| xButton.setPropertyValue( "Name", sName ); |
| // the label |
| xButton.setPropertyValue( "Label", sLabel ); |
| // use the name as help text |
| xButton.setPropertyValue( "HelpText", sName ); |
| // don't want buttons to be accessible by the "tab" key - this would be uncomfortable when traveling |
| // with records with "tab" |
| xButton.setPropertyValue( "Tabstop", new Boolean( false ) ); |
| // similar, they should not steal the focus when clicked |
| xButton.setPropertyValue( "FocusOnClick", new Boolean( false ) ); |
| |
| m_aOperator.addButton( xButton, _formFeature ); |
| |
| return xButton; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** creates a column in a grid |
| @param xGridModel |
| specifies the model of the grid where the new column should be inserted |
| @param sColumnService |
| specifies the service name of the column to create (e.g. "NumericField") |
| @param sDataField |
| specifies the database field to which the column should be bound |
| @param nWidth |
| specifies the column width (in mm). If 0, no width is set. |
| @return |
| the newly created column |
| */ |
| XPropertySet createGridColumn( Object aGridModel, String sColumnService, String sDataField, int nWidth ) |
| throws com.sun.star.uno.Exception |
| { |
| // the container to insert columns into |
| XIndexContainer xColumnContainer = UNO.queryIndexContainer( aGridModel ); |
| // the factory for creating column models |
| XGridColumnFactory xColumnFactory = (XGridColumnFactory)UnoRuntime.queryInterface( |
| XGridColumnFactory.class, aGridModel ); |
| |
| // (let) create the new col |
| XInterface xNewCol = (XInterface)xColumnFactory.createColumn( sColumnService ); |
| XPropertySet xColProps = UNO.queryPropertySet( xNewCol ); |
| |
| // some props |
| // the field the column is bound to |
| xColProps.setPropertyValue( "DataField", sDataField ); |
| // the "display name" of the column |
| xColProps.setPropertyValue( "Label", sDataField ); |
| // the name of the column within it's parent |
| xColProps.setPropertyValue( "Name", sDataField ); |
| |
| if ( nWidth > 0 ) |
| xColProps.setPropertyValue( "Width", new Integer( nWidth * 10 ) ); |
| |
| // insert |
| xColumnContainer.insertByIndex( xColumnContainer.getCount(), xNewCol ); |
| |
| // outta here |
| return xColProps; |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** creates a column in a grid |
| */ |
| XPropertySet createGridColumn( Object aGridModel, String sColumnService, String sDataField ) |
| throws com.sun.star.uno.Exception |
| { |
| return createGridColumn( aGridModel, sColumnService, sDataField ); |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** creates our sample document |
| */ |
| protected void prepareDocument() throws com.sun.star.uno.Exception, java.lang.Exception |
| { |
| super.prepareDocument(); |
| |
| m_database = new HsqlDatabase( m_xCtx ); |
| |
| // ensure that we have the tables needed for our example |
| ensureTables(); |
| |
| // -------------------------------------------------------------- |
| /* create some shapes */ |
| XPropertySet xSNRField = m_formLayer.insertControlLine( "NumericField", "SNR", "", 3 ); |
| m_formLayer.insertControlLine( "TextField", "FIRSTNAME", "", 11); |
| m_formLayer.insertControlLine( "TextField", "LASTNAME", "", 19 ); |
| m_formLayer.insertControlLine( "TextField", "STREET", "", 27 ); |
| m_formLayer.insertControlLine( "TextField", "STATE", "", 35 ); |
| XPropertySet xZipField = m_formLayer.insertControlLine( "NumericField", "ZIP", "", 43 ); |
| m_formLayer.insertControlLine( "FormattedField", "BIRTHDATE", "", 51 ); |
| |
| // for the salesman number / zip code, we don't want to have decimal places: |
| xSNRField.setPropertyValue( "DecimalAccuracy", new Short( (short)0 ) ); |
| xZipField.setPropertyValue( "DecimalAccuracy", new Short( (short)0 ) ); |
| |
| // -------------------------------------------------------------- |
| /** need the form the control models belong to |
| for this, we simply obtain the parent for any of the control models we have |
| |
| Note that this involves knowledge about the implementation: If a control shape is |
| inserted into a document, where the control model does not belong to the form component |
| hierarchy, yet, it is automatically inserted into the first form, which is created |
| if necessary. |
| */ |
| m_xMasterForm = FLTools.getParent( xZipField ); |
| |
| // set the data source signature at the form |
| m_xMasterForm.setPropertyValue( "DataSourceName", m_database.getDocumentURL() ); |
| m_xMasterForm.setPropertyValue( "CommandType", new Integer( CommandType.TABLE ) ); |
| m_xMasterForm.setPropertyValue( "Command", "SALESMEN" ); |
| |
| // -------------------------------------------------------------- |
| // insert the buttons |
| // create our button operator, if necessary |
| m_aOperator = new ButtonOperator( m_xCtx, m_document, m_xMasterForm ); |
| |
| createButton( 2, 63, 8, "first", "<<", FormFeature.MoveToFirst ); |
| createButton( 12, 63, 8, "prev", "<", FormFeature.MoveToPrevious ); |
| createButton( 22, 63, 8, "next", ">", FormFeature.MoveToNext ); |
| createButton( 32, 63, 8, "last", ">>", FormFeature.MoveToLast ); |
| createButton( 42, 63, 8, "new", ">*", FormFeature.MoveToInsertRow ); |
| createButton( 58, 63, 13, "reload", "reload", FormFeature.ReloadForm ); |
| |
| // -------------------------------------------------------------- |
| // create a sub for for the sales |
| |
| // for this, first create a sub form and bind it to the SALES table |
| XIndexContainer xSalesForm = m_document.createSubForm( m_xMasterForm, "Sales" ); |
| XPropertySet xSalesFormProps = UNO.queryPropertySet( xSalesForm ); |
| |
| xSalesFormProps.setPropertyValue( "DataSourceName", m_database.getDocumentURL() ); |
| xSalesFormProps.setPropertyValue( "CommandType", new Integer( CommandType.COMMAND ) ); |
| |
| String sCommand = new String( "SELECT * FROM " ); |
| sCommand += s_tableNameSales; |
| sCommand += " WHERE " + s_tableNameSales + ".SNR = :salesmen"; |
| xSalesFormProps.setPropertyValue( "Command", sCommand ); |
| |
| // the master-details connection |
| String[] aMasterFields = new String[] { "SNR" }; // the field in the master form |
| String[] aDetailFields = new String[] { "salesmen" }; // the name in the detail form |
| xSalesFormProps.setPropertyValue( "MasterFields", aMasterFields ); |
| xSalesFormProps.setPropertyValue( "DetailFields", aDetailFields ); |
| |
| // the create thr grid model |
| XPropertySet xSalesGridModel = m_formLayer.createControlAndShape( "GridControl", 2, 80, 162, 40, xSalesForm ); |
| xSalesGridModel.setPropertyValue( "Name", "SalesTable" ); |
| XPropertySet xKeyColumn = createGridColumn( xSalesGridModel, "NumericField", "SALENR", 12 ); |
| XPropertySet xCustomerColumn = createGridColumn( xSalesGridModel, "ListBox", "COS_NR", 40 ); |
| XPropertySet xSalesNameColumn = createGridColumn( xSalesGridModel, "TextField", "NAME", 25 ); |
| createGridColumn( xSalesGridModel, "DateField", "SALEDATE", 24 ); |
| createGridColumn( xSalesGridModel, "CurrencyField", "PRICE", 16 ); |
| |
| // please note that a better solution for the SALEDATE field would have been to use |
| // a FormattedField. But we want to demonstrate some effects with DateFields here ... |
| |
| m_aSalesNameValidator = new GridFieldValidator( m_xCtx, xSalesNameColumn ); |
| m_aSalesNameValidator.enableColumnWatch( m_bAllowEmptySales ); |
| |
| xKeyColumn.setPropertyValue( "DecimalAccuracy", new Short( (short)0 ) ); |
| |
| // init the list box which is for choosing the customer a sale belongs to |
| xCustomerColumn.setPropertyValue( "BoundColumn", new Short( (short)1 ) ); |
| xCustomerColumn.setPropertyValue( "Label", "Customer" ); |
| xCustomerColumn.setPropertyValue( "ListSourceType", ListSourceType.SQL ); |
| |
| String sListSource = "SELECT LASTNAME, COS_NR FROM "; |
| sListSource += s_tableNameCustomers; |
| String[] aListSource = new String[] { sListSource }; |
| xCustomerColumn.setPropertyValue( "ListSource", aListSource ); |
| |
| // We want to demonstrate how to reset fields to NULL, we do this with the SALEDATE field |
| // above. For this, we add as reset listener to the form |
| XReset xFormReset = UNO.queryReset( xSalesForm ); |
| xFormReset.addResetListener( this ); |
| |
| |
| // -------------------------------------------------------------- |
| // the option for filtering the sales form |
| XIndexContainer xSalesFilterForm = m_document.createSiblingForm( xSalesForm, "SalesFilter" ); |
| XPropertySet xSFFProps = UNO.queryPropertySet( xSalesFilterForm ); |
| XPropertySet xLabel = m_formLayer.createControlAndShape( "FixedText", 2, 125, 35, 6, xSalesFilterForm ); |
| xLabel.setPropertyValue( "Label", "show only sales since" ); |
| xLabel.setPropertyValue( "Name", "FilterLabel" ); |
| |
| XPropertySet xFilterSelection = m_formLayer.createControlAndShape( "ListBox", 40, 125, 59, 6, xSalesFilterForm ); |
| xFilterSelection.setPropertyValue( "Name", "FilterList" ); |
| xFilterSelection.setPropertyValue( "LabelControl", xLabel ); |
| XPropertySet xManualFilter = m_formLayer.createControlAndShape( "DateField", 104, 125, 30, 6, xSalesFilterForm ); |
| xManualFilter.setPropertyValue( "Name", "ManualFilter" ); |
| XPropertySet xApplyFilter = m_formLayer.createControlAndShape( "CommandButton", 139, 125, 25, 6, xSalesFilterForm ); |
| xApplyFilter.setPropertyValue( "Name", "ApplyFilter" ); |
| xApplyFilter.setPropertyValue( "DefaultButton", new Boolean( true ) ); |
| m_aSalesFilter = new SalesFilter( m_document, xSalesFormProps, xFilterSelection, |
| xManualFilter, xApplyFilter ); |
| |
| |
| // -------------------------------------------------------------- |
| // the options section |
| // for this, we need a form which is a sibling of our master form (don't want to interfere |
| // the controls which represent options only with the controls which are used for data access) |
| |
| XIndexContainer xOptionsForm = m_document.createSiblingForm( m_xMasterForm, "Options" ); |
| |
| xLabel = m_formLayer.createControlAndShape( "GroupBox", 98, 0, 66, 62, xOptionsForm ); |
| xLabel.setPropertyValue( "Name", "Options" ); |
| xLabel.setPropertyValue( "Label", "Options" ); |
| |
| // radio buttons which controls how we generate unique keys |
| xLabel = m_formLayer.createControlAndShape( "GroupBox", 103, 5, 56, 25, xOptionsForm ); |
| xLabel.setPropertyValue( "Label", "key generation" ); |
| xLabel.setPropertyValue( "Name", "KeyGeneration" ); |
| XPropertySet xKeyGen = m_formLayer.createControlAndShape( "RadioButton", 106, 11, 50, 6, xOptionsForm ); |
| xKeyGen.setPropertyValue( "Name", "KeyGen" ); |
| xKeyGen.setPropertyValue( "Label", "no automatic generation" ); |
| xKeyGen.setPropertyValue( "RefValue", "none" ); |
| xKeyGen.addPropertyChangeListener( "State", this ); |
| |
| xKeyGen = m_formLayer.createControlAndShape( "RadioButton", 106, 17, 50, 6, xOptionsForm ); |
| xKeyGen.setPropertyValue( "Name", "KeyGen" ); |
| xKeyGen.setPropertyValue( "Label", "before inserting a record" ); |
| xKeyGen.setPropertyValue( "RefValue", "update" ); |
| xKeyGen.addPropertyChangeListener( "State", this ); |
| |
| xKeyGen = m_formLayer.createControlAndShape( "RadioButton", 106, 23, 50, 6, xOptionsForm ); |
| xKeyGen.setPropertyValue( "Name", "KeyGen" ); |
| xKeyGen.setPropertyValue( "Label", "when moving to a new record" ); |
| xKeyGen.setPropertyValue( "RefValue", "reset" ); |
| xKeyGen.addPropertyChangeListener( "State", this ); |
| |
| // initialize listeners |
| // master form - key generation |
| m_aSalesmanKeyGenerator = new KeyGenerator( m_xMasterForm, "SNR", m_xCtx ); |
| m_aSalesmanKeyGenerator.activateKeyGenerator( true ); |
| // master form - control locking |
| m_aSalesmenLocker = new ControlLock( m_xMasterForm, "SNR" ); |
| m_aSalesmenLocker.enableLock( m_bProtectKeyFields ); |
| |
| // details form - key generation |
| m_aSalesKeyGenerator = new KeyGenerator( xSalesFormProps, "SALENR", m_xCtx ); |
| m_aSalesKeyGenerator.activateKeyGenerator( true ); |
| |
| // details form - control locking |
| m_aSalesLocker = new ControlLock( xSalesFormProps, "SALENR" ); |
| m_aSalesLocker.enableLock( m_bProtectKeyFields ); |
| |
| // initally, we want to generate keys when moving to a new record |
| xKeyGen.setPropertyValue( "DefaultState", new Short( (short)1 ) ); |
| |
| // -------------------------------------------------------------- |
| // second options block |
| xLabel = m_formLayer.createControlAndShape( "GroupBox", 103, 33, 56, 25, xOptionsForm ); |
| xLabel.setPropertyValue( "Name", "Misc" ); |
| xLabel.setPropertyValue( "Label", "Miscellaneous" ); |
| |
| XPropertySet xCheck = m_formLayer.createControlAndShape( "CheckBox", 106, 39, 60, 6, xOptionsForm ); |
| xCheck.setPropertyValue( "Name", "defaultdate" ); |
| xCheck.setPropertyValue( "Label", "default sales date to \"today\"" ); |
| xCheck.setPropertyValue( "HelpText", "When checked, newly entered sales records are pre-filled with today's date, else left empty." ); |
| xCheck.addPropertyChangeListener( "State", this ); |
| |
| xCheck = m_formLayer.createControlAndShape( "CheckBox", 106, 45, 60, 6, xOptionsForm ); |
| xCheck.setPropertyValue( "Name", "protectkeys" ); |
| xCheck.setPropertyValue( "Label", "protect key fields from editing" ); |
| xCheck.setPropertyValue( "HelpText", "When checked, you cannot modify the values in the table's key fields (SNR and SALENR)" ); |
| xCheck.addPropertyChangeListener( "State", this ); |
| |
| xCheck = m_formLayer.createControlAndShape( "CheckBox", 106, 51, 60, 6, xOptionsForm ); |
| xCheck.setPropertyValue( "Name", "emptysales" ); |
| xCheck.setPropertyValue( "Label", "check for empty sales names" ); |
| xCheck.setPropertyValue( "HelpText", "When checked, you cannot enter empty values into the NAME column of the 'Sales' table." ); |
| xCheck.addPropertyChangeListener( "State", this ); |
| |
| // dump the form component tree |
| enumFormComponents( ); |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| protected void onFormsAlive() |
| { |
| m_aOperator.onFormsAlive(); |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** performs any cleanup before exiting the program |
| */ |
| protected void cleanUp( ) throws java.lang.Exception |
| { |
| // remove the listeners at the buttons |
| RevokeButtons aRevoke = new RevokeButtons( m_aOperator ); |
| aRevoke.handle( m_document.getFormComponentTreeRoot( ) ); |
| |
| // remove the key generator listeners from the form |
| m_aSalesmanKeyGenerator.stopGenerator( ); |
| m_aSalesKeyGenerator.stopGenerator( ); |
| |
| // and the control lockers |
| m_aSalesmenLocker.enableLock( false ); |
| m_aSalesLocker.enableLock( false ); |
| |
| // the validator for the grid column |
| m_aSalesNameValidator.enableColumnWatch( false ); |
| |
| // remove our own reset listener from the form |
| XNameAccess xMasterAsNames = (XNameAccess)UnoRuntime.queryInterface( |
| XNameAccess.class, m_xMasterForm ); |
| XReset xFormReset = UNO.queryReset( xMasterAsNames.getByName( "Sales" ) ); |
| xFormReset.removeResetListener( this ); |
| |
| super.cleanUp(); |
| } |
| |
| /* ------------------------------------------------------------------ */ |
| /** class entry point |
| */ |
| public static void main(String argv[]) throws java.lang.Exception |
| { |
| DataAwareness aSample = new DataAwareness(); |
| aSample.run( argv ); |
| } |
| } |