/************************************************************** * * 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. * *************************************************************/ package com.sun.star.comp.extensionoptions; import com.sun.star.lib.uno.helper.Factory; import com.sun.star.lib.uno.helper.WeakBase; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.lang.XSingleComponentFactory; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.lang.WrappedTargetException; import com.sun.star.lang.IllegalArgumentException; import com.sun.star.lang.XInitialization; import com.sun.star.lang.XTypeProvider; import com.sun.star.lang.XServiceInfo; import com.sun.star.lang.WrappedTargetException; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.Any; import com.sun.star.uno.AnyConverter; import com.sun.star.uno.XComponentContext; import com.sun.star.uno.Exception; import com.sun.star.registry.XRegistryKey; import com.sun.star.awt.XContainerWindowEventHandler; import com.sun.star.awt.XControl; import com.sun.star.awt.XControlModel; import com.sun.star.awt.XControlContainer; import com.sun.star.container.XNameAccess; import com.sun.star.container.NoSuchElementException; import com.sun.star.beans.PropertyValue; import com.sun.star.beans.PropertyState; import com.sun.star.beans.XPropertySet; import com.sun.star.beans.UnknownPropertyException; import com.sun.star.beans.PropertyVetoException; import com.sun.star.util.XChangesBatch; /** A handler which supports multiple options pages which all * have the same controls. */ public class OptionsEventHandler { public static class _OptionsEventHandler extends WeakBase implements XServiceInfo, XContainerWindowEventHandler { static private final String __serviceName = "com.sun.star.comp.extensionoptions.OptionsEventHandler"; private XComponentContext m_cmpCtx; private XMultiComponentFactory m_xMCF; private XNameAccess m_xAccessLeaves; /**Names of supported options pages. */ private String[] m_arWindowNames = { "Writer1", "Writer2", "Writer3", "Calc1", "Calc2", "Calc3", "Draw1", "Draw2", "Draw3", "Node1_1", "Node1_2", "Node1_3", "Node2_1", "Node2_2", "Node2_3", "Node3_1", "Node3_2", "Node3_3"}; /**Names of the controls which are supported by this handler. All these *controls must have a "Text" property. */ private String[] m_arStringControls = { "String0", "String1", "String2", "String3", "String4"}; public _OptionsEventHandler(XComponentContext xCompContext) { m_cmpCtx = xCompContext; m_xMCF = m_cmpCtx.getServiceManager(); //Create the com.sun.star.configuration.ConfigurationUpdateAccess //for the registry node which contains the data for our option //pages. XMultiServiceFactory xConfig; try { xConfig = (XMultiServiceFactory) UnoRuntime.queryInterface( XMultiServiceFactory.class, m_cmpCtx.getServiceManager().createInstanceWithContext( "com.sun.star.configuration.ConfigurationProvider", m_cmpCtx)); } catch (com.sun.star.uno.Exception e) { e.printStackTrace(); return; } //One argument for creating the ConfigurationUpdateAccess is the "nodepath". //Our nodepath point to the node of which the direct subnodes represent the //different options pages. Object[] args = new Object[1]; args[0] = new PropertyValue( "nodepath", 0, "/org.openoffice.desktop.deployment.options.ExtensionData/Leaves", PropertyState.DIRECT_VALUE); //We get the com.sun.star.container.XNameAccess from the instance of //ConfigurationUpdateAccess and save it for later use. try { m_xAccessLeaves = (XNameAccess) UnoRuntime.queryInterface( XNameAccess.class, xConfig.createInstanceWithArguments( "com.sun.star.configuration.ConfigurationUpdateAccess", args)); } catch (com.sun.star.uno.Exception e) { e.printStackTrace(); return; } } /** This method returns an array of all supported service names. * @return Array of supported service names. */ public String[] getSupportedServiceNames() { return getServiceNames(); } /** This method is a simple helper function to used in the * static component initialisation functions as well as in * getSupportedServiceNames. */ public static String[] getServiceNames() { String[] sSupportedServiceNames = { __serviceName }; return sSupportedServiceNames; } /** This method returns true, if the given service will be * supported by the component. * @param sServiceName Service name. * @return True, if the given service name will be supported. */ public boolean supportsService( String sServiceName ) { return sServiceName.equals( __serviceName ); } /** Return the class name of the component. * @return Class name of the component. */ public String getImplementationName() { return _OptionsEventHandler.class.getName(); } //XContainerWindowEventHandler public boolean callHandlerMethod(com.sun.star.awt.XWindow aWindow, Object aEventObject, String sMethod) throws WrappedTargetException { if (sMethod.equals("external_event") ){ try { return handleExternalEvent(aWindow, aEventObject); } catch (com.sun.star.uno.RuntimeException re) { throw re; } catch (com.sun.star.uno.Exception e) { throw new WrappedTargetException(sMethod, this, e); } } return true; } //XContainerWindowEventHandler public String[] getSupportedMethodNames() { return new String[] {"external_event"}; } private boolean handleExternalEvent(com.sun.star.awt.XWindow aWindow, Object aEventObject) throws com.sun.star.uno.Exception { try { String sMethod = AnyConverter.toString(aEventObject); if (sMethod.equals("ok")) { saveData(aWindow); } else if (sMethod.equals("back") || sMethod.equals("initialize")) { loadData(aWindow); } } catch (com.sun.star.lang.IllegalArgumentException e) { throw new com.sun.star.lang.IllegalArgumentException( "Method external_event requires a string in the event object argument.", this, (short) -1); } return true; } private void saveData(com.sun.star.awt.XWindow aWindow) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.uno.Exception { //Determine the name of the options page. This serves two purposes. First, if this //options page is supported by this handler and second we use the name two locate //the corresponding data in the registry. String sWindowName = getWindowName(aWindow); if (sWindowName == null) throw new com.sun.star.lang.IllegalArgumentException( "This window is not supported by this handler", this, (short) -1); //To access the separate controls of the window we need to obtain the //XControlContainer from the window implementation XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( XControlContainer.class, aWindow); if (xContainer == null) throw new com.sun.star.uno.Exception( "Could not get XControlContainer from window.", this); //This is an implementation which will be used for several options pages //which all have the same controls. m_arStringControls is an array which //contains the names. for (int i = 0; i < m_arStringControls.length; i++) { //To obtain the data from the controls we need to get their model. //First get the respective control from the XControlContainer. XControl xControl = xContainer.getControl(m_arStringControls[i]); //This generic handler and the corresponding registry schema support //up to five text controls. However, if a options page does not use all //five controls then we will not complain here. if (xControl == null) continue; //From the control we get the model, which in turn supports the //XPropertySet interface, which we finally use to get the data from //the control. XPropertySet xProp = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xControl.getModel()); if (xProp == null) throw new com.sun.star.uno.Exception( "Could not get XPropertySet from control.", this); //Get the "Text" property. Object aText = xProp.getPropertyValue("Text"); String sValue = null; //The value is still contained in a com.sun.star.uno.Any - so convert it. try { sValue = AnyConverter.toString(aText); } catch (com.sun.star.lang.IllegalArgumentException e) { throw new com.sun.star.lang.IllegalArgumentException( "Wrong property type.", this, (short) -1); } //Now we have the actual string value of the control. What we need now is //the XPropertySet of the respective property in the registry, so that we //can store the value. //To access the registry we have previously created a service instance //of com.sun.star.configuration.ConfigurationUpdateAccess which supports //com.sun.star.container.XNameAccess. The XNameAccess is used to get the //particular registry node which represents this options page. //Fortunately the name of the window is the same as the registry node. XPropertySet xLeaf = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, m_xAccessLeaves.getByName(sWindowName)); if (xLeaf == null) throw new com.sun.star.uno.Exception( "XPropertySet not supported.", this); //Finally we can set the value xLeaf.setPropertyValue(m_arStringControls[i], sValue); } //Committing the changes will cause or changes to be written to the registry. XChangesBatch xUpdateCommit = (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class, m_xAccessLeaves); xUpdateCommit.commitChanges(); } private void loadData(com.sun.star.awt.XWindow aWindow) throws com.sun.star.uno.Exception { //Determine the name of the window. This serves two purposes. First, if this //window is supported by this handler and second we use the name two locate //the corresponding data in the registry. String sWindowName = getWindowName(aWindow); if (sWindowName == null) throw new com.sun.star.lang.IllegalArgumentException( "The window is not supported by this handler", this, (short) -1); //To access the separate controls of the window we need to obtain the //XControlContainer from window implementation XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( XControlContainer.class, aWindow); if (xContainer == null) throw new com.sun.star.uno.Exception( "Could not get XControlContainer from window.", this); //This is an implementation which will be used for several options pages //which all have the same controls. m_arStringControls is an array which //contains the names. for (int i = 0; i < m_arStringControls.length; i++) { //load the values from the registry //To access the registry we have previously created a service instance //of com.sun.star.configuration.ConfigurationUpdateAccess which supports //com.sun.star.container.XNameAccess. We obtain now the section //of the registry which is assigned to this options page. XPropertySet xLeaf = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, m_xAccessLeaves.getByName(sWindowName)); if (xLeaf == null) throw new com.sun.star.uno.Exception( "XPropertySet not supported.", this); //The properties in the registry have the same name as the respective //controls. We use the names now to obtain the property values. Object aValue = xLeaf.getPropertyValue(m_arStringControls[i]); //Now that we have the value we need to set it at the corresponding //control in the window. The XControlContainer, which we obtained earlier //is the means to get hold of all the controls. XControl xControl = xContainer.getControl(m_arStringControls[i]); //This generic handler and the corresponding registry schema support //up to five text controls. However, if a options page does not use all //five controls then we will not complain here. if (xControl == null) continue; //From the control we get the model, which in turn supports the //XPropertySet interface, which we finally use to set the data at the //control XPropertySet xProp = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xControl.getModel()); if (xProp == null) throw new com.sun.star.uno.Exception( "Could not get XPropertySet from control.", this); //This handler supports only text controls, which are named "Pattern Field" //in the dialog editor. We set the "Text" property. xProp.setPropertyValue("Text", aValue); } } //Checks if the name property of the window is one of the supported names and returns //always a valid string or null private String getWindowName(com.sun.star.awt.XWindow aWindow) throws com.sun.star.uno.Exception { if (aWindow == null) new com.sun.star.lang.IllegalArgumentException( "Method external_event requires that a window is passed as argument", this, (short) -1); //We need to get the control model of the window. Therefore the first step is //to query for it. XControl xControlDlg = (XControl) UnoRuntime.queryInterface( XControl.class, aWindow); if (xControlDlg == null) throw new com.sun.star.uno.Exception( "Cannot obtain XControl from XWindow in method external_event."); //Now get model XControlModel xModelDlg = xControlDlg.getModel(); if (xModelDlg == null) throw new com.sun.star.uno.Exception( "Cannot obtain XControlModel from XWindow in method external_event.", this); //The model itself does not provide any information except that its //implementation supports XPropertySet which is used to access the data. XPropertySet xPropDlg = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xModelDlg); if (xPropDlg == null) throw new com.sun.star.uno.Exception( "Cannot obtain XPropertySet from window in method external_event.", this); //Get the "Name" property of the window Object aWindowName = xPropDlg.getPropertyValue("Name"); //Get the string from the returned com.sun.star.uno.Any String sName = null; try { sName = AnyConverter.toString(aWindowName); } catch (com.sun.star.lang.IllegalArgumentException e) { throw new com.sun.star.uno.Exception( "Name - property of window is not a string.", this); } //Eventually we can check if we this handler can "handle" this options page. //The class has a member m_arWindowNames which contains all names of windows //for which it is intended for (int i = 0; i < m_arWindowNames.length; i++) { if (m_arWindowNames[i].equals(sName)) { return sName; } } return null; } } /** * Gives a factory for creating the service. * This method is called by the JavaLoader *

* @return returns a XSingleComponentFactory for creating * the component * @param sImplName the name of the implementation for which a * service is desired * @see com.sun.star.comp.loader.JavaLoader */ public static XSingleComponentFactory __getComponentFactory(String sImplName) { XSingleComponentFactory xFactory = null; if ( sImplName.equals( _OptionsEventHandler.class.getName() ) ) xFactory = Factory.createComponentFactory(_OptionsEventHandler.class, _OptionsEventHandler.getServiceNames()); return xFactory; } /** * Writes the service information into the given registry key. * This method is called by the JavaLoader *

* @return returns true if the operation succeeded * @param regKey the registryKey * @see com.sun.star.comp.loader.JavaLoader */ public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { return Factory.writeRegistryServiceInfo(_OptionsEventHandler.class.getName(), _OptionsEventHandler.getServiceNames(), regKey); } /** This method is a member of the interface for initializing an object * directly after its creation. * @param object This array of arbitrary objects will be passed to the * component after its creation. * @throws Exception Every exception will not be handled, but will be * passed to the caller. */ public void initialize( Object[] object ) throws com.sun.star.uno.Exception { } }