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 package com.sun.star.comp.extensionoptions; 23 24 import com.sun.star.lib.uno.helper.Factory; 25 import com.sun.star.lib.uno.helper.WeakBase; 26 import com.sun.star.lang.XMultiComponentFactory; 27 import com.sun.star.lang.XSingleComponentFactory; 28 import com.sun.star.lang.XMultiServiceFactory; 29 import com.sun.star.lang.WrappedTargetException; 30 import com.sun.star.lang.IllegalArgumentException; 31 import com.sun.star.lang.XInitialization; 32 import com.sun.star.lang.XTypeProvider; 33 import com.sun.star.lang.XServiceInfo; 34 import com.sun.star.lang.WrappedTargetException; 35 import com.sun.star.uno.UnoRuntime; 36 import com.sun.star.uno.Any; 37 import com.sun.star.uno.AnyConverter; 38 import com.sun.star.uno.XComponentContext; 39 import com.sun.star.uno.Exception; 40 import com.sun.star.registry.XRegistryKey; 41 import com.sun.star.awt.XContainerWindowEventHandler; 42 import com.sun.star.awt.XControl; 43 import com.sun.star.awt.XControlModel; 44 import com.sun.star.awt.XControlContainer; 45 import com.sun.star.container.XNameAccess; 46 import com.sun.star.container.NoSuchElementException; 47 import com.sun.star.beans.PropertyValue; 48 import com.sun.star.beans.PropertyState; 49 import com.sun.star.beans.XPropertySet; 50 import com.sun.star.beans.UnknownPropertyException; 51 import com.sun.star.beans.PropertyVetoException; 52 import com.sun.star.util.XChangesBatch; 53 54 /** A handler which supports multiple options pages which all 55 * have the same controls. 56 */ 57 public class OptionsEventHandler { 58 59 public static class _OptionsEventHandler extends WeakBase 60 implements XServiceInfo, XContainerWindowEventHandler { 61 62 static private final String __serviceName = 63 "com.sun.star.comp.extensionoptions.OptionsEventHandler"; 64 65 private XComponentContext m_cmpCtx; 66 67 private XMultiComponentFactory m_xMCF; 68 69 private XNameAccess m_xAccessLeaves; 70 71 /**Names of supported options pages. 72 */ 73 private String[] m_arWindowNames = { 74 "Writer1", "Writer2", "Writer3", "Calc1", "Calc2", "Calc3", 75 "Draw1", "Draw2", "Draw3", "Node1_1", "Node1_2", "Node1_3", 76 "Node2_1", "Node2_2", "Node2_3", "Node3_1", "Node3_2", "Node3_3"}; 77 78 /**Names of the controls which are supported by this handler. All these 79 *controls must have a "Text" property. 80 */ 81 private String[] m_arStringControls = { 82 "String0", "String1", "String2", "String3", "String4"}; 83 _OptionsEventHandler(XComponentContext xCompContext)84 public _OptionsEventHandler(XComponentContext xCompContext) { 85 m_cmpCtx = xCompContext; 86 m_xMCF = m_cmpCtx.getServiceManager(); 87 88 //Create the com.sun.star.configuration.ConfigurationUpdateAccess 89 //for the registry node which contains the data for our option 90 //pages. 91 XMultiServiceFactory xConfig; 92 try { 93 xConfig = (XMultiServiceFactory) UnoRuntime.queryInterface( 94 XMultiServiceFactory.class, 95 m_cmpCtx.getServiceManager().createInstanceWithContext( 96 "com.sun.star.configuration.ConfigurationProvider", m_cmpCtx)); 97 } catch (com.sun.star.uno.Exception e) { 98 e.printStackTrace(); 99 return; 100 } 101 102 //One argument for creating the ConfigurationUpdateAccess is the "nodepath". 103 //Our nodepath point to the node of which the direct subnodes represent the 104 //different options pages. 105 Object[] args = new Object[1]; 106 args[0] = new PropertyValue( 107 "nodepath", 0, "/org.openoffice.desktop.deployment.options.ExtensionData/Leaves", 108 PropertyState.DIRECT_VALUE); 109 110 //We get the com.sun.star.container.XNameAccess from the instance of 111 //ConfigurationUpdateAccess and save it for later use. 112 try { 113 m_xAccessLeaves = (XNameAccess) UnoRuntime.queryInterface( 114 XNameAccess.class, xConfig.createInstanceWithArguments( 115 "com.sun.star.configuration.ConfigurationUpdateAccess", args)); 116 117 } catch (com.sun.star.uno.Exception e) { 118 e.printStackTrace(); 119 return; 120 } 121 } 122 123 /** This method returns an array of all supported service names. 124 * @return Array of supported service names. 125 */ getSupportedServiceNames()126 public String[] getSupportedServiceNames() { 127 return getServiceNames(); 128 } 129 130 /** This method is a simple helper function to used in the 131 * static component initialisation functions as well as in 132 * getSupportedServiceNames. 133 */ getServiceNames()134 public static String[] getServiceNames() { 135 String[] sSupportedServiceNames = { __serviceName }; 136 return sSupportedServiceNames; 137 } 138 139 /** This method returns true, if the given service will be 140 * supported by the component. 141 * @param sServiceName Service name. 142 * @return True, if the given service name will be supported. 143 */ supportsService( String sServiceName )144 public boolean supportsService( String sServiceName ) { 145 return sServiceName.equals( __serviceName ); 146 } 147 148 /** Return the class name of the component. 149 * @return Class name of the component. 150 */ getImplementationName()151 public String getImplementationName() { 152 return _OptionsEventHandler.class.getName(); 153 } 154 155 //XContainerWindowEventHandler callHandlerMethod(com.sun.star.awt.XWindow aWindow, Object aEventObject, String sMethod)156 public boolean callHandlerMethod(com.sun.star.awt.XWindow aWindow, 157 Object aEventObject, String sMethod) 158 throws WrappedTargetException { 159 if (sMethod.equals("external_event") ){ 160 try { 161 return handleExternalEvent(aWindow, aEventObject); 162 } catch (com.sun.star.uno.RuntimeException re) { 163 throw re; 164 } catch (com.sun.star.uno.Exception e) { 165 throw new WrappedTargetException(sMethod, this, e); 166 } 167 } 168 169 return true; 170 } 171 172 //XContainerWindowEventHandler getSupportedMethodNames()173 public String[] getSupportedMethodNames() { 174 return new String[] {"external_event"}; 175 } 176 handleExternalEvent(com.sun.star.awt.XWindow aWindow, Object aEventObject)177 private boolean handleExternalEvent(com.sun.star.awt.XWindow aWindow, Object aEventObject) 178 throws com.sun.star.uno.Exception { 179 try { 180 String sMethod = AnyConverter.toString(aEventObject); 181 if (sMethod.equals("ok")) { 182 saveData(aWindow); 183 } else if (sMethod.equals("back") || sMethod.equals("initialize")) { 184 loadData(aWindow); 185 } 186 } catch (com.sun.star.lang.IllegalArgumentException e) { 187 throw new com.sun.star.lang.IllegalArgumentException( 188 "Method external_event requires a string in the event object argument.", 189 this, (short) -1); 190 } 191 192 return true; 193 } 194 saveData(com.sun.star.awt.XWindow aWindow)195 private void saveData(com.sun.star.awt.XWindow aWindow) 196 throws com.sun.star.lang.IllegalArgumentException, 197 com.sun.star.uno.Exception { 198 199 //Determine the name of the options page. This serves two purposes. First, if this 200 //options page is supported by this handler and second we use the name two locate 201 //the corresponding data in the registry. 202 String sWindowName = getWindowName(aWindow); 203 if (sWindowName == null) 204 throw new com.sun.star.lang.IllegalArgumentException( 205 "This window is not supported by this handler", this, (short) -1); 206 207 //To access the separate controls of the window we need to obtain the 208 //XControlContainer from the window implementation 209 XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( 210 XControlContainer.class, aWindow); 211 if (xContainer == null) 212 throw new com.sun.star.uno.Exception( 213 "Could not get XControlContainer from window.", this); 214 215 //This is an implementation which will be used for several options pages 216 //which all have the same controls. m_arStringControls is an array which 217 //contains the names. 218 for (int i = 0; i < m_arStringControls.length; i++) { 219 220 //To obtain the data from the controls we need to get their model. 221 //First get the respective control from the XControlContainer. 222 XControl xControl = xContainer.getControl(m_arStringControls[i]); 223 224 //This generic handler and the corresponding registry schema support 225 //up to five text controls. However, if a options page does not use all 226 //five controls then we will not complain here. 227 if (xControl == null) 228 continue; 229 230 //From the control we get the model, which in turn supports the 231 //XPropertySet interface, which we finally use to get the data from 232 //the control. 233 XPropertySet xProp = (XPropertySet) UnoRuntime.queryInterface( 234 XPropertySet.class, xControl.getModel()); 235 236 if (xProp == null) 237 throw new com.sun.star.uno.Exception( 238 "Could not get XPropertySet from control.", this); 239 //Get the "Text" property. 240 Object aText = xProp.getPropertyValue("Text"); 241 String sValue = null; 242 243 //The value is still contained in a com.sun.star.uno.Any - so convert it. 244 try { 245 sValue = AnyConverter.toString(aText); 246 } catch (com.sun.star.lang.IllegalArgumentException e) { 247 throw new com.sun.star.lang.IllegalArgumentException( 248 "Wrong property type.", this, (short) -1); 249 } 250 251 //Now we have the actual string value of the control. What we need now is 252 //the XPropertySet of the respective property in the registry, so that we 253 //can store the value. 254 //To access the registry we have previously created a service instance 255 //of com.sun.star.configuration.ConfigurationUpdateAccess which supports 256 //com.sun.star.container.XNameAccess. The XNameAccess is used to get the 257 //particular registry node which represents this options page. 258 //Fortunately the name of the window is the same as the registry node. 259 XPropertySet xLeaf = (XPropertySet) UnoRuntime.queryInterface( 260 XPropertySet.class, m_xAccessLeaves.getByName(sWindowName)); 261 if (xLeaf == null) 262 throw new com.sun.star.uno.Exception( 263 "XPropertySet not supported.", this); 264 265 //Finally we can set the value 266 xLeaf.setPropertyValue(m_arStringControls[i], sValue); 267 } 268 269 //Committing the changes will cause or changes to be written to the registry. 270 XChangesBatch xUpdateCommit = 271 (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class, m_xAccessLeaves); 272 xUpdateCommit.commitChanges(); 273 } 274 loadData(com.sun.star.awt.XWindow aWindow)275 private void loadData(com.sun.star.awt.XWindow aWindow) 276 throws com.sun.star.uno.Exception { 277 278 //Determine the name of the window. This serves two purposes. First, if this 279 //window is supported by this handler and second we use the name two locate 280 //the corresponding data in the registry. 281 String sWindowName = getWindowName(aWindow); 282 if (sWindowName == null) 283 throw new com.sun.star.lang.IllegalArgumentException( 284 "The window is not supported by this handler", this, (short) -1); 285 286 //To acces the separate controls of the window we need to obtain the 287 //XControlContainer from window implementation 288 XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( 289 XControlContainer.class, aWindow); 290 if (xContainer == null) 291 throw new com.sun.star.uno.Exception( 292 "Could not get XControlContainer from window.", this); 293 294 //This is an implementation which will be used for several options pages 295 //which all have the same controls. m_arStringControls is an array which 296 //contains the names. 297 for (int i = 0; i < m_arStringControls.length; i++) { 298 299 //load the values from the registry 300 //To access the registry we have previously created a service instance 301 //of com.sun.star.configuration.ConfigurationUpdateAccess which supports 302 //com.sun.star.container.XNameAccess. We obtain now the section 303 //of the registry which is assigned to this options page. 304 XPropertySet xLeaf = (XPropertySet) UnoRuntime.queryInterface( 305 XPropertySet.class, m_xAccessLeaves.getByName(sWindowName)); 306 if (xLeaf == null) 307 throw new com.sun.star.uno.Exception( 308 "XPropertySet not supported.", this); 309 310 //The properties in the registry have the same name as the respective 311 //controls. We use the names now to obtain the property values. 312 Object aValue = xLeaf.getPropertyValue(m_arStringControls[i]); 313 314 //Now that we have the value we need to set it at the corresponding 315 //control in the window. The XControlContainer, which we obtained earlier 316 //is the means to get hold of all the controls. 317 XControl xControl = xContainer.getControl(m_arStringControls[i]); 318 319 //This generic handler and the corresponding registry schema support 320 //up to five text controls. However, if a options page does not use all 321 //five controls then we will not complain here. 322 if (xControl == null) 323 continue; 324 325 //From the control we get the model, which in turn supports the 326 //XPropertySet interface, which we finally use to set the data at the 327 //control 328 XPropertySet xProp = (XPropertySet) UnoRuntime.queryInterface( 329 XPropertySet.class, xControl.getModel()); 330 331 if (xProp == null) 332 throw new com.sun.star.uno.Exception( 333 "Could not get XPropertySet from control.", this); 334 335 //This handler supports only text controls, which are named "Pattern Field" 336 //in the dialog editor. We set the "Text" property. 337 xProp.setPropertyValue("Text", aValue); 338 } 339 } 340 341 //Checks if the name property of the window is one of the supported names and returns 342 //always a valid string or null getWindowName(com.sun.star.awt.XWindow aWindow)343 private String getWindowName(com.sun.star.awt.XWindow aWindow) 344 throws com.sun.star.uno.Exception { 345 346 if (aWindow == null) 347 new com.sun.star.lang.IllegalArgumentException( 348 "Method external_event requires that a window is passed as argument", 349 this, (short) -1); 350 351 //We need to get the control model of the window. Therefore the first step is 352 //to query for it. 353 XControl xControlDlg = (XControl) UnoRuntime.queryInterface( 354 XControl.class, aWindow); 355 356 if (xControlDlg == null) 357 throw new com.sun.star.uno.Exception( 358 "Cannot obtain XControl from XWindow in method external_event."); 359 //Now get model 360 XControlModel xModelDlg = xControlDlg.getModel(); 361 362 if (xModelDlg == null) 363 throw new com.sun.star.uno.Exception( 364 "Cannot obtain XControlModel from XWindow in method external_event.", this); 365 //The model itself does not provide any information except that its 366 //implementation supports XPropertySet which is used to access the data. 367 XPropertySet xPropDlg = (XPropertySet) UnoRuntime.queryInterface( 368 XPropertySet.class, xModelDlg); 369 if (xPropDlg == null) 370 throw new com.sun.star.uno.Exception( 371 "Cannot obtain XPropertySet from window in method external_event.", this); 372 373 //Get the "Name" property of the window 374 Object aWindowName = xPropDlg.getPropertyValue("Name"); 375 376 //Get the string from the returned com.sun.star.uno.Any 377 String sName = null; 378 try { 379 sName = AnyConverter.toString(aWindowName); 380 } catch (com.sun.star.lang.IllegalArgumentException e) { 381 throw new com.sun.star.uno.Exception( 382 "Name - property of window is not a string.", this); 383 } 384 385 //Eventually we can check if we this handler can "handle" this options page. 386 //The class has a member m_arWindowNames which contains all names of windows 387 //for which it is intended 388 for (int i = 0; i < m_arWindowNames.length; i++) { 389 if (m_arWindowNames[i].equals(sName)) { 390 return sName; 391 } 392 } 393 return null; 394 } 395 } 396 397 398 /** 399 * Gives a factory for creating the service. 400 * This method is called by the <code>JavaLoader</code> 401 * <p> 402 * @return returns a <code>XSingleComponentFactory</code> for creating 403 * the component 404 * @param sImplName the name of the implementation for which a 405 * service is desired 406 * @see com.sun.star.comp.loader.JavaLoader 407 */ __getComponentFactory(String sImplName)408 public static XSingleComponentFactory __getComponentFactory(String sImplName) 409 { 410 XSingleComponentFactory xFactory = null; 411 412 if ( sImplName.equals( _OptionsEventHandler.class.getName() ) ) 413 xFactory = Factory.createComponentFactory(_OptionsEventHandler.class, 414 _OptionsEventHandler.getServiceNames()); 415 416 return xFactory; 417 } 418 419 /** 420 * Writes the service information into the given registry key. 421 * This method is called by the <code>JavaLoader</code> 422 * <p> 423 * @return returns true if the operation succeeded 424 * @param regKey the registryKey 425 * @see com.sun.star.comp.loader.JavaLoader 426 */ __writeRegistryServiceInfo(XRegistryKey regKey)427 public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { 428 return Factory.writeRegistryServiceInfo(_OptionsEventHandler.class.getName(), 429 _OptionsEventHandler.getServiceNames(), 430 regKey); 431 } 432 433 /** This method is a member of the interface for initializing an object 434 * directly after its creation. 435 * @param object This array of arbitrary objects will be passed to the 436 * component after its creation. 437 * @throws Exception Every exception will not be handled, but will be 438 * passed to the caller. 439 */ initialize( Object[] object )440 public void initialize( Object[] object ) 441 throws com.sun.star.uno.Exception { 442 } 443 444 } 445