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