/**************************************************************
 *
 * 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.awt.PushButtonType;
import com.sun.star.awt.XControl;
import com.sun.star.awt.XDialog;
import com.sun.star.awt.XFixedText;
import com.sun.star.awt.XListBox;
import com.sun.star.awt.XWindow;
import com.sun.star.beans.MethodConcept;
import com.sun.star.beans.Property;
import com.sun.star.beans.PropertyValue;
import com.sun.star.beans.XIntrospection;
import com.sun.star.beans.XIntrospectionAccess;
import com.sun.star.beans.XMultiPropertySet;
import com.sun.star.beans.XPropertySet;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XServiceInfo;
import com.sun.star.lang.XTypeProvider;
import com.sun.star.reflection.XIdlMethod;
import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;

public class UnoDialogSample2 extends UnoDialogSample {
    XIntrospectionAccess m_xIntrospectionAccess = null;
    Object m_oUnoObject = null;
    // define some constants used to set positions and sizes
    // of controls. For further information see
    // http://ui.openoffice.org/knowledge/DialogSpecificationandGuidelines.odt
    final static int nFixedTextHeight = 8;
    final static int nControlMargin = 6;
    final static int nDialogWidth = 250;
    final static int nDialogHeight = 140;
    // the default roadmap width == 80 MAPs
    final static int nRoadmapWidth = 80;
    final static int nButtonHeight = 14;
    final static int nButtonWidth = 50;


    public UnoDialogSample2(XComponentContext _xContext, XMultiComponentFactory _xMCF, Object _oUnoObject) {
        super(_xContext, _xMCF);
        try {
            m_oUnoObject = _oUnoObject;
            Object o = m_xMCF.createInstanceWithContext("com.sun.star.beans.Introspection", m_xContext);
            XIntrospection m_xIntrospection = ( XIntrospection ) UnoRuntime.queryInterface(XIntrospection.class, o );
            // the variable m_xIntrospectionAccess offers functionality to access all methods and properties
            // of a variable
            m_xIntrospectionAccess = m_xIntrospection.inspect(_oUnoObject);
        } catch (com.sun.star.uno.Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String args[]) {
        UnoDialogSample2 oUnoDialogSample2 = null;
        try {
            XComponentContext xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
            if(xContext != null )
                System.out.println("Connected to a running office ...");
            XMultiComponentFactory xMCF = xContext.getServiceManager();
            PropertyValue[] aPropertyValues = new PropertyValue[]{};
            // create an arbitrary Uno-Object - in this case an empty writer document..
            Object oDesktop =xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);
            XComponentLoader xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, oDesktop);
            Object oUnoObject = xComponentLoader.loadComponentFromURL("private:factory/swriter", "_default", 0, aPropertyValues);

            // define some coordinates where to position the controls
            final int nButtonPosX = (int)((nDialogWidth/2) - (nButtonWidth/2));
            final int nButtonPosY = nDialogHeight - nButtonHeight - nControlMargin;
            final int nControlPosX = nRoadmapWidth + 2*nControlMargin;
            final int nControlWidth = nDialogWidth - 3*nControlMargin - nRoadmapWidth;
            final int nListBoxHeight = nDialogHeight - 4*nControlMargin - nButtonHeight;
            oUnoDialogSample2 = new UnoDialogSample2(xContext, xMCF, oUnoObject);
            oUnoDialogSample2.initialize( new String[] {"Height", "Moveable", "Name","PositionX","PositionY", "Step", "TabIndex","Title","Width"},
                                          new Object[] { new Integer(nDialogHeight), Boolean.TRUE, "Dialog1", new Integer(102),new Integer(41), new Integer(1), new Short((short) 0), "Inspect a Uno-Object", new Integer(nDialogWidth)});
            String sIntroLabel = "This Dialog lists information about a given Uno-Object.\nIt offers a view to inspect all suppported servicenames, exported interfaces, methods and properties.";
            oUnoDialogSample2.insertMultiLineFixedText(nControlPosX, 27, nControlWidth, 4, 1, sIntroLabel);
            // get the data from the UNO object...
            String[] sSupportedServiceNames = oUnoDialogSample2.getSupportedServiceNames();
            String[] sInterfaceNames = oUnoDialogSample2.getExportedInterfaceNames();
            String[] sMethodNames = oUnoDialogSample2.getMethodNames();
            String[] sPropertyNames = oUnoDialogSample2.getPropertyNames();
            // add controls to the dialog...
            oUnoDialogSample2.insertListBox(nControlPosX, nControlMargin, nListBoxHeight, nControlWidth, 2, sSupportedServiceNames);
            oUnoDialogSample2.insertListBox(nControlPosX, nControlMargin, nListBoxHeight, nControlWidth, 3, sInterfaceNames);
            oUnoDialogSample2.insertListBox(nControlPosX, nControlMargin, nListBoxHeight, nControlWidth, 4, sMethodNames);
            oUnoDialogSample2.insertListBox(nControlPosX, nControlMargin, nListBoxHeight, nControlWidth, 5, sPropertyNames);
            oUnoDialogSample2.insertButton(oUnoDialogSample2, nButtonPosX, nButtonPosY, nButtonWidth, "~Close", (short) PushButtonType.OK_value);
            oUnoDialogSample2.insertHorizontalFixedLine(0, nButtonPosY - nControlMargin - 4, nDialogWidth, "");
            // create the windowpeer;
            // it must be kept in mind that it must be created after the insertion of the controls
            // (see http://qa.openoffice.org/issues/show_bug.cgi?id=75129)
            oUnoDialogSample2.createWindowPeer();
            // add the roadmap control. Note that the roadmap may not be created before the windowpeer of the dialog exists
            // (see http://qa.openoffice.org/issues/show_bug.cgi?id=67369)
            oUnoDialogSample2.addRoadmap(oUnoDialogSample2.getRoadmapItemStateChangeListener());
            oUnoDialogSample2.insertRoadmapItem(0, true, "Introduction", 1);
            oUnoDialogSample2.insertRoadmapItem(1, true, "Supported Services", 2);
            oUnoDialogSample2.insertRoadmapItem(2, true, "Interfaces", 3);
            oUnoDialogSample2.insertRoadmapItem(3, true, "Methods", 4);
            oUnoDialogSample2.insertRoadmapItem(4, true, "Properties", 5);
            oUnoDialogSample2.m_xRMPSet.setPropertyValue("CurrentItemID", new Short((short) 1));
            oUnoDialogSample2.m_xRMPSet.setPropertyValue("Complete", Boolean.TRUE);
            oUnoDialogSample2.xDialog = (XDialog) UnoRuntime.queryInterface(XDialog.class, oUnoDialogSample2.m_xDialogControl);
            oUnoDialogSample2.xDialog.execute();
        }catch( Exception ex ) {
            ex.printStackTrace(System.out);
        }
        finally{
            //make sure always to dispose the component and free the memory!
            if (oUnoDialogSample2 != null){
                if (oUnoDialogSample2.m_xComponent != null){
                    oUnoDialogSample2.m_xComponent.dispose();
                }
            }
        }

        System.exit( 0 );
    }


    public String[] getMethodNames() {
        String[] sMethodNames = new String[]{};
        try {
            XIdlMethod[] xIdlMethods = m_xIntrospectionAccess.getMethods(MethodConcept.ALL);
            sMethodNames = new String[xIdlMethods.length];
            for (int i = 0; i < xIdlMethods.length; i++){
                sMethodNames[i] = xIdlMethods[i].getName();
            }
        }
        catch( Exception e ) {
            System.err.println( e );
        }
        return sMethodNames;
    }

    // returns the names of all supported servicenames of a UNO object
    public String[] getSupportedServiceNames() {
        String[] sSupportedServiceNames = new String[]{};
        // If the Uno-Object supports "com.sun.star.lang.XServiceInfo"
        // this will give access to all supported servicenames
        XServiceInfo xServiceInfo = ( XServiceInfo ) UnoRuntime.queryInterface( XServiceInfo.class, m_oUnoObject);
        if ( xServiceInfo != null ) {
            sSupportedServiceNames = xServiceInfo.getSupportedServiceNames();
        }
        return sSupportedServiceNames;
    }

    // returns the names of all properties of a UNO object
    protected String[] getPropertyNames() {
        String[] sPropertyNames = new String[]{};
        try {
            Property[] aProperties = m_xIntrospectionAccess.getProperties(com.sun.star.beans.PropertyConcept.ATTRIBUTES + com.sun.star.beans.PropertyConcept.PROPERTYSET);
            sPropertyNames = new String[aProperties.length];
            for (int i = 0; i < aProperties.length; i++){
                sPropertyNames[i] = aProperties[i].Name;
            }
        }
        catch( Exception e ) {
            System.err.println( e );
        }
        return sPropertyNames;
    }


    // returns the names of all exported interfaces of a UNO object
    protected String[] getExportedInterfaceNames(){
        Type[] aTypes = new Type[]{};
        String[] sTypeNames = new String[]{};
        // The XTypeProvider interfaces offers access to all exported interfaces
        XTypeProvider xTypeProvider = ( XTypeProvider ) UnoRuntime.queryInterface( XTypeProvider.class, m_oUnoObject);
        if ( xTypeProvider != null ) {
            aTypes = xTypeProvider.getTypes();
            sTypeNames = new String[aTypes.length];
            for (int i = 0; i < aTypes.length - 1; i++){
                sTypeNames[i] = aTypes[i].getTypeName();
            }
        }
        return sTypeNames;
    }



    public XListBox insertListBox(int _nPosX, int _nPosY, int _nHeight, int _nWidth, int _nStep, String[] _sStringItemList) {
        XListBox xListBox = null;
        try{
            // create a unique name by means of an own implementation...
            String sName = createUniqueName(m_xDlgModelNameContainer, "ListBox");
            // create a controlmodel at the multiservicefactory of the dialog model...
            Object oListBoxModel = m_xMSFDialogModel.createInstance("com.sun.star.awt.UnoControlListBoxModel");
            XMultiPropertySet xLBModelMPSet = (XMultiPropertySet) UnoRuntime.queryInterface(XMultiPropertySet.class, oListBoxModel);
            // Set the properties at the model - keep in mind to pass the property names in alphabetical order!
            xLBModelMPSet.setPropertyValues(
                new String[]  {"Dropdown", "Height", "Name", "PositionX", "PositionY", "ReadOnly", "Step", "StringItemList", "Width" } ,
                new Object[] {Boolean.FALSE, new Integer(_nHeight), sName, new Integer(_nPosX), new Integer(_nPosY), Boolean.TRUE, new Integer(_nStep), _sStringItemList, new Integer(_nWidth)});
            m_xDlgModelNameContainer.insertByName(sName, xLBModelMPSet);
        }catch (com.sun.star.uno.Exception ex) {
            throw new java.lang.RuntimeException("cannot happen...");
        }
        return xListBox;
    }


    public void insertMultiLineFixedText(int _nPosX, int _nPosY, int _nWidth, int _nLineCount, int _nStep, String _sLabel) {
        try {
            // create a unique name by means of an own implementation...
            String sName = createUniqueName(m_xDlgModelNameContainer, "Label");
            int nHeight = _nLineCount * nFixedTextHeight;
            // create a controlmodel at the multiservicefactory of the dialog model...
            Object oFTModel = m_xMSFDialogModel.createInstance("com.sun.star.awt.UnoControlFixedTextModel");
            XMultiPropertySet xFTModelMPSet = (XMultiPropertySet) UnoRuntime.queryInterface(XMultiPropertySet.class, oFTModel);
            // Set the properties at the model - keep in mind to pass the property names in alphabetical order!
            xFTModelMPSet.setPropertyValues(
                new String[] {"Height", "Label", "MultiLine", "Name", "PositionX", "PositionY", "Step", "Width"},
                new Object[] { new Integer(nHeight), _sLabel, Boolean.TRUE, sName, new Integer(_nPosX), new Integer(_nPosY), new Integer(_nStep), new Integer(_nWidth)});
            // add the model to the NameContainer of the dialog model
            m_xDlgModelNameContainer.insertByName(sName, oFTModel);
        }catch (com.sun.star.uno.Exception ex){
            /* perform individual exception handling here.
             * Possible exception types are:
             * com.sun.star.lang.IllegalArgumentException,
             * com.sun.star.lang.WrappedTargetException,
             * com.sun.star.container.ElementExistException,
             * com.sun.star.beans.PropertyVetoException,
             * com.sun.star.beans.UnknownPropertyException,
             * com.sun.star.uno.Exception
             */
            ex.printStackTrace(System.out);
        }
    }

}// end of class
