1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 package integration.forms; 28 29 import com.sun.star.accessibility.XAccessible; 30 import com.sun.star.accessibility.XAccessibleEditableText; 31 import com.sun.star.uno.UnoRuntime; 32 33 import com.sun.star.beans.XPropertySet; 34 import com.sun.star.container.XIndexContainer; 35 import com.sun.star.container.XIndexAccess; 36 import com.sun.star.lang.XMultiServiceFactory; 37 import com.sun.star.drawing.XControlShape; 38 import com.sun.star.drawing.XShapes; 39 import com.sun.star.awt.Size; 40 import com.sun.star.awt.Point; 41 import com.sun.star.awt.VisualEffect; 42 import com.sun.star.awt.XControlModel; 43 import com.sun.star.container.XNameAccess; 44 import com.sun.star.text.TextContentAnchorType; 45 import com.sun.star.drawing.XDrawPage; 46 47 /** 48 * 49 * @author fs@openoffice.org 50 */ 51 public class FormLayer 52 { 53 private DocumentHelper m_document; 54 private XDrawPage m_page; 55 56 /* ------------------------------------------------------------------ */ 57 /** Creates a new instance of FormLayer */ 58 public FormLayer( DocumentHelper _document ) 59 { 60 m_document = _document; 61 } 62 63 /* ------------------------------------------------------------------ */ 64 /** sets the page which is to be used for subsequent insertions of controls/shapes 65 */ 66 void setInsertPage( int page ) throws com.sun.star.lang.IndexOutOfBoundsException, com.sun.star.lang.WrappedTargetException 67 { 68 m_page = m_document.getDrawPage( page ); 69 } 70 71 /* ------------------------------------------------------------------ */ 72 /** creates a control in the document 73 74 <p>Note that <em>control<em> here is an incorrect terminology. What the method really does is 75 it creates a control shape, together with a control model, and inserts them into the document model. 76 This will result in every view to this document creating a control described by the model-shape pair. 77 </p> 78 79 @param sFormComponentService 80 the service name of the form component to create, e.g. "TextField" 81 @param nXPos 82 the abscissa of the position of the newly inserted shape 83 @param nXPos 84 the ordinate of the position of the newly inserted shape 85 @param nWidth 86 the width of the newly inserted shape 87 @param nHeight 88 the height of the newly inserted shape 89 @param xParentForm 90 the form to use as parent for the newly create form component. May be null, in this case 91 a default parent is chosen by the implementation 92 @return 93 the property access to the control's model 94 */ 95 public XPropertySet createControlAndShape( String sFormComponentService, int nXPos, 96 int nYPos, int nWidth, int nHeight, Object _parentForm ) throws java.lang.Exception 97 { 98 // let the document create a shape 99 XMultiServiceFactory xDocAsFactory = UnoRuntime.queryInterface( 100 XMultiServiceFactory.class, m_document.getDocument() ); 101 XControlShape xShape = UnoRuntime.queryInterface( XControlShape.class, 102 xDocAsFactory.createInstance( "com.sun.star.drawing.ControlShape" ) ); 103 104 // position and size of the shape 105 xShape.setSize( new Size( nWidth * 100, nHeight * 100 ) ); 106 xShape.setPosition( new Point( nXPos * 100, nYPos * 100 ) ); 107 108 // adjust the anchor so that the control is tied to the page 109 XPropertySet xShapeProps = dbfTools.queryPropertySet( xShape ); 110 TextContentAnchorType eAnchorType = TextContentAnchorType.AT_PARAGRAPH; 111 xShapeProps.setPropertyValue( "AnchorType", eAnchorType ); 112 113 // create the form component (the model of a form control) 114 String sQualifiedComponentName = "com.sun.star.form.component." + sFormComponentService; 115 XControlModel xModel = UnoRuntime.queryInterface( XControlModel.class, 116 m_document.getOrb().createInstance( sQualifiedComponentName ) ); 117 118 // insert the model into the form component hierarchy, if the caller gave us a location 119 if ( null != _parentForm ) 120 { 121 XIndexContainer parentForm = null; 122 if ( _parentForm instanceof XIndexContainer ) 123 parentForm = (XIndexContainer)_parentForm; 124 else 125 parentForm = UnoRuntime.queryInterface( XIndexContainer.class, _parentForm ); 126 parentForm.insertByIndex( parentForm.getCount(), xModel ); 127 } 128 129 // knitt them 130 xShape.setControl( xModel ); 131 132 // add the shape to the shapes collection of the document 133 XDrawPage pageWhereToInsert = ( m_page != null ) ? m_page : m_document.getMainDrawPage(); 134 135 XShapes xDocShapes = UnoRuntime.queryInterface( XShapes.class, pageWhereToInsert ); 136 xDocShapes.add( xShape ); 137 138 // and outta here with the XPropertySet interface of the model 139 XPropertySet xModelProps = dbfTools.queryPropertySet( xModel ); 140 return xModelProps; 141 } 142 143 /* ------------------------------------------------------------------ */ 144 /** creates a control in the document 145 146 <p>Note that <em>control<em> here is an incorrect terminology. What the method really does is 147 it creates a control shape, together with a control model, and inserts them into the document model. 148 This will result in every view to this document creating a control described by the model-shape pair. 149 </p> 150 151 @param sFormComponentService 152 the service name of the form component to create, e.g. "TextField" 153 @param nXPos 154 the abscissa of the position of the newly inserted shape 155 @param nXPos 156 the ordinate of the position of the newly inserted shape 157 @param nWidth 158 the width of the newly inserted shape 159 @param nHeight 160 the height of the newly inserted shape 161 @return 162 the property access to the control's model 163 */ 164 public XPropertySet createControlAndShape( String sFormComponentService, int nXPos, 165 int nYPos, int nWidth, int nHeight ) throws java.lang.Exception 166 { 167 return createControlAndShape( sFormComponentService, nXPos, nYPos, nWidth, nHeight, null ); 168 } 169 170 /** creates a pair of controls, namely a label control, and another control labeled by it 171 * 172 * @param _formComponentServiceName 173 * the service name for the control which is not the label control 174 * @param _label 175 * the label to be shown in the label control 176 * @param _xPos 177 * the horizontal position of the control pair 178 * @param _yPos 179 * the vertical position of the control pair 180 * @param _height 181 * the height of the control which is not the label control 182 * @return 183 * the model of the control which is not the label control 184 * @throws java.lang.Exception 185 */ 186 public XPropertySet createLabeledControl( String _formComponentServiceName, String _label, int _xPos, 187 int _yPos, int _height ) 188 throws java.lang.Exception 189 { 190 // insert the label control 191 XPropertySet label = createControlAndShape( "FixedText", _xPos, _yPos, 25, 6 ); 192 label.setPropertyValue( "Label", _label ); 193 194 // insert the text field control 195 XPropertySet field = createControlAndShape( _formComponentServiceName, 196 _xPos + 25, _yPos, 40, _height ); 197 // knit it to it's label component 198 field.setPropertyValue( "LabelControl", label ); 199 200 // names 201 label.setPropertyValue( "Name", _label + "_Label" ); 202 field.setPropertyValue( "Name", _label ); 203 204 return field; 205 } 206 207 /* ------------------------------------------------------------------ */ 208 /** creates a line of controls, consisting of a label and a field for data input. 209 210 <p>In opposite to the second form of this method, here the height of the field, 211 as well as the abscissa of the label, are under the control of the caller.</p> 212 213 @param sControlType 214 specifies the type of the data input control 215 @param sFieldName 216 specifies the field name the text field should be bound to 217 @param sControlNamePostfix 218 specifies a postfix to append to the logical control names 219 @param nYPos 220 specifies the Y position of the line to start at 221 @param nHeight 222 the height of the field 223 @return 224 the control model of the created data input field 225 */ 226 public XPropertySet insertControlLine( String sControlType, String sFieldName, String _controlNamePostfix, 227 int nXPos, int nYPos, int nHeight ) 228 throws java.lang.Exception 229 { 230 // insert the label control 231 XPropertySet xLabelModel = createControlAndShape( "FixedText", nXPos, nYPos, 25, 6 ); 232 xLabelModel.setPropertyValue( "Label", sFieldName ); 233 234 // insert the text field control 235 XPropertySet xFieldModel = createControlAndShape( sControlType, nXPos + 26, nYPos, 40, nHeight ); 236 xFieldModel.setPropertyValue( "DataField", sFieldName ); 237 if ( xFieldModel.getPropertySetInfo().hasPropertyByName( "Border" ) ) 238 { 239 xFieldModel.setPropertyValue( "Border", new Short( VisualEffect.FLAT ) ); 240 if ( xFieldModel.getPropertySetInfo().hasPropertyByName( "BorderColor" ) ) 241 xFieldModel.setPropertyValue( "BorderColor", new Integer( 0x00C0C0C0 ) ); 242 } 243 // knit it to it's label component 244 xFieldModel.setPropertyValue( "LabelControl", xLabelModel ); 245 246 // some names, so later on we can find them 247 if ( _controlNamePostfix == null ) 248 _controlNamePostfix = ""; 249 xLabelModel.setPropertyValue( "Name", sFieldName + _controlNamePostfix + "_Label" ); 250 xFieldModel.setPropertyValue( "Name", sFieldName + _controlNamePostfix ); 251 252 return xFieldModel; 253 } 254 255 /* ------------------------------------------------------------------ */ 256 /** creates a line of controls, consisting of a label and a field for data input. 257 258 @param sControlType 259 specifies the type of the data input control 260 @param sFieldName 261 specifies the field name the text field should be bound to 262 @param nYPos 263 specifies the Y position of the line to start at 264 @return 265 the control model of the created data input field 266 */ 267 public XPropertySet insertControlLine( String sControlType, String sFieldName, String sControlNamePostfix, int nYPos ) 268 throws java.lang.Exception 269 { 270 return insertControlLine( sControlType, sFieldName, sControlNamePostfix, 10, nYPos, 6 ); 271 } 272 273 /* ------------------------------------------------------------------ */ 274 /** retrieves the radio button model with the given name and the given ref value 275 * @param form 276 * the parent form of the radio button model to find 277 * @param name 278 * the name of the radio button 279 * @param refValue 280 * the reference value of the radio button 281 */ 282 public XPropertySet getRadioModelByRefValue( XPropertySet form, String name, String refValue ) throws com.sun.star.uno.Exception, java.lang.Exception 283 { 284 XIndexAccess indexAccess = UnoRuntime.queryInterface( XIndexAccess.class, form ); 285 286 for ( int i=0; i<indexAccess.getCount(); ++i ) 287 { 288 XPropertySet control = dbfTools.queryPropertySet( indexAccess.getByIndex( i ) ); 289 290 if ( ((String)control.getPropertyValue( "Name" )).equals( name ) ) 291 if ( ((String)control.getPropertyValue( "RefValue" )).equals( refValue ) ) 292 return control; 293 } 294 return null; 295 } 296 297 /* ------------------------------------------------------------------ */ 298 /** retrieves the radio button model with the given name and the given tag 299 * @param form 300 * the parent form of the radio button model to find 301 * @param name 302 * the name of the radio button 303 * @param refValue 304 * the tag of the radio button 305 */ 306 public XPropertySet getRadioModelByTag( XPropertySet form, String name, String tag ) throws com.sun.star.uno.Exception, java.lang.Exception 307 { 308 XIndexAccess indexAccess = UnoRuntime.queryInterface( XIndexAccess.class, form ); 309 310 for ( int i=0; i<indexAccess.getCount(); ++i ) 311 { 312 XPropertySet control = dbfTools.queryPropertySet( indexAccess.getByIndex( i ) ); 313 314 if ( ((String)control.getPropertyValue( "Name" )).equals( name ) ) 315 if ( ((String)control.getPropertyValue( "Tag" )).equals( tag ) ) 316 return control; 317 } 318 return null; 319 } 320 321 /* ------------------------------------------------------------------ */ 322 /** retrieves a control model with a given (integer) access path 323 */ 324 public XPropertySet getControlModel( int[] _accessPath ) throws com.sun.star.uno.Exception 325 { 326 XIndexAccess indexAcc = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, 327 m_document.getFormComponentTreeRoot() ); 328 XPropertySet controlModel = null; 329 int i=0; 330 while ( ( indexAcc != null ) && ( i < _accessPath.length ) ) 331 { 332 controlModel = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, 333 indexAcc.getByIndex( _accessPath[i] ) ); 334 indexAcc = (XIndexAccess)UnoRuntime.queryInterface( XIndexAccess.class, 335 controlModel ); 336 ++i; 337 } 338 return controlModel; 339 } 340 341 /* ------------------------------------------------------------------ */ 342 /** retrieves a control model with a given (string) access path 343 */ 344 public XPropertySet getControlModel( String[] _accessPath ) throws com.sun.star.uno.Exception 345 { 346 XNameAccess nameAcc = m_document.getFormComponentTreeRoot(); 347 XPropertySet controlModel = null; 348 int i=0; 349 while ( ( nameAcc != null ) && ( i < _accessPath.length ) ) 350 { 351 controlModel = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, 352 nameAcc.getByName( _accessPath[i] ) ); 353 nameAcc = (XNameAccess)UnoRuntime.queryInterface( XNameAccess.class, 354 controlModel ); 355 ++i; 356 } 357 return controlModel; 358 } 359 360 /* ------------------------------------------------------------------ */ 361 /** simulates a user's text input into a control given by control model 362 */ 363 public void userTextInput( XPropertySet controlModel, String text ) throws com.sun.star.uno.Exception, java.lang.Exception 364 { 365 // we will *not* simply set the value property at the model. This is not the same as 366 // doing a user input, as the latter will trigger a lot of notifications, which the forms runtime environment 367 // (namely the FormController) relies on to notice that the control changed. 368 // Instead, we use the Accessibility interfaces of the control to simulate text input 369 XAccessible formattedAccessible = UnoRuntime.queryInterface( XAccessible.class, 370 m_document.getCurrentView().getControl( controlModel ) 371 ); 372 XAccessibleEditableText textAccess = UnoRuntime.queryInterface( XAccessibleEditableText.class, 373 formattedAccessible.getAccessibleContext() ); 374 textAccess.setText( text ); 375 } 376 } 377