1 /*************************************************************************
2  *
3  *  The Contents of this file are made available subject to the terms of
4  *  the BSD license.
5  *
6  *  Copyright 2000, 2010 Oracle and/or its affiliates.
7  *  All rights reserved.
8  *
9  *  Redistribution and use in source and binary forms, with or without
10  *  modification, are permitted provided that the following conditions
11  *  are met:
12  *  1. Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *  2. Redistributions in binary form must reproduce the above copyright
15  *     notice, this list of conditions and the following disclaimer in the
16  *     documentation and/or other materials provided with the distribution.
17  *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
18  *     contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  *************************************************************************/
34 
35 // base classes
36 import com.sun.star.uno.XInterface;
37 import com.sun.star.uno.UnoRuntime;
38 import com.sun.star.uno.Type;
39 import com.sun.star.container.XIndexAccess;
40 import com.sun.star.lib.uno.helper.WeakBase;
41 
42 // factories
43 import com.sun.star.lang.XMultiServiceFactory;
44 import com.sun.star.lang.XSingleServiceFactory;
45 
46 // graphics stuff
47 import com.sun.star.drawing.*;
48 import com.sun.star.awt.Point;
49 import com.sun.star.awt.Rectangle;
50 import com.sun.star.awt.Size;
51 
52 // chart stuff
53 import com.sun.star.chart.*;
54 
55 // property access
56 import com.sun.star.beans.*;
57 
58 // Add-In stuff
59 import com.sun.star.lang.XInitialization;
60 import com.sun.star.util.XRefreshable;
61 import com.sun.star.lang.XServiceName;
62 import com.sun.star.lang.XServiceInfo;
63 import com.sun.star.lang.XTypeProvider;
64 
65 // Exceptions
66 import com.sun.star.uno.Exception;
67 import com.sun.star.uno.RuntimeException;
68 
69 import javax.swing.JOptionPane;
70 
71 public class JavaSampleChartAddIn extends WeakBase implements
72     XInitialization,
73     XRefreshable,
74     XDiagram,
75     XServiceName,
76     XServiceInfo
77 {
78     public JavaSampleChartAddIn()
79     {}
80 
81     // __________ interface methods __________
82 
83     // XInitialization
84     public void initialize( Object[] aArguments )
85         throws Exception, RuntimeException
86     {
87         if( aArguments.length > 0 )
88         {
89             maChartDocument = (XChartDocument) UnoRuntime.queryInterface(
90                 XChartDocument.class, aArguments[ 0 ]);
91 
92             XPropertySet aDocProp = (XPropertySet) UnoRuntime.queryInterface(
93                 XPropertySet.class, maChartDocument );
94             if( aDocProp != null )
95             {
96                 // set base diagram which will be extended in refresh()
97                 aDocProp.setPropertyValue( "BaseDiagram", "com.sun.star.chart.XYDiagram" );
98             }
99 
100             // get the draw page
101             XDrawPageSupplier aPageSupp = (XDrawPageSupplier) UnoRuntime.queryInterface(
102                 XDrawPageSupplier.class, maChartDocument );
103             if( aPageSupp != null )
104                 maDrawPage = (XDrawPage) UnoRuntime.queryInterface(
105                     XDrawPage.class, aPageSupp.getDrawPage() );
106 
107             // get a factory for creating shapes
108             maShapeFactory = (XMultiServiceFactory) UnoRuntime.queryInterface(
109                 XMultiServiceFactory.class, maChartDocument );
110         }
111     }
112 
113     // XRefreshable
114     public void refresh() throws RuntimeException
115     {
116         // recycle shapes in first call, if document was loaded
117         if( maBottomLine == null ||
118             maTopLine == null )
119         {
120             // try to recycle loaded shapes
121             XPropertySet aDocProp = (XPropertySet) UnoRuntime.queryInterface(
122                 XPropertySet.class, maChartDocument );
123             if( aDocProp != null )
124             {
125                 try
126                 {
127                     XIndexAccess aShapesIA = (XIndexAccess) UnoRuntime.queryInterface(
128                         XIndexAccess.class, aDocProp.getPropertyValue( "AdditionalShapes" ));
129                     if( aShapesIA != null &&
130                         aShapesIA.getCount() > 0 )
131                     {
132                         XShape aShape;
133                         String aName;
134                         for( int i = aShapesIA.getCount() - 1; i >= 0; --i )
135                         {
136                             aShape = (XShape) UnoRuntime.queryInterface(
137                                 XShape.class, aShapesIA.getByIndex( i ));
138                             if( aShape != null )
139                             {
140                                 XPropertySet aProp = (XPropertySet) UnoRuntime.queryInterface(
141                                     XPropertySet.class, aShape );
142                                 aName = (String) aProp.getPropertyValue( "Name" );
143 
144                                 if( aName.equals( "top" ))
145                                 {
146                                     maTopLine = aShape;
147                                 }
148                                 else if( aName.equals( "bottom" ))
149                                 {
150                                     maBottomLine = aShape;
151                                 }
152                             }
153                         }
154                     }
155                 }
156                 catch( Exception ex )
157                 {
158                     JOptionPane.showMessageDialog( null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE );
159                 }
160             }
161         }
162 
163         // create top line if it does not yet exist
164         try
165         {
166             if( maTopLine == null )
167             {
168                 maTopLine = (XShape) UnoRuntime.queryInterface(
169                     XShape.class, maShapeFactory.createInstance( "com.sun.star.drawing.LineShape" ));
170                 maDrawPage.add( maTopLine );
171 
172                 // make line red and thicker
173                 XPropertySet aShapeProp = (XPropertySet) UnoRuntime.queryInterface(
174                     XPropertySet.class, maTopLine );
175 
176                 aShapeProp.setPropertyValue( "LineColor", new Integer( 0xe01010 ));
177                 aShapeProp.setPropertyValue( "LineWidth", new Integer( 50 ));
178                 aShapeProp.setPropertyValue( "Name", "top" );
179             }
180         }
181         catch( Exception ex )
182         {
183             JOptionPane.showMessageDialog( null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE );
184         }
185 
186         // create bottom line if it does not yet exist
187         try
188         {
189             if( maBottomLine == null )
190             {
191                 maBottomLine = (XShape) UnoRuntime.queryInterface(
192                     XShape.class, maShapeFactory.createInstance( "com.sun.star.drawing.LineShape" ));
193                 maDrawPage.add( maBottomLine );
194 
195                 // make line green and thicker
196                 XPropertySet aShapeProp = (XPropertySet) UnoRuntime.queryInterface(
197                     XPropertySet.class, maBottomLine );
198 
199                 aShapeProp.setPropertyValue( "LineColor", new Integer( 0x10e010 ));
200                 aShapeProp.setPropertyValue( "LineWidth", new Integer( 50 ));
201                 aShapeProp.setPropertyValue( "Name", "bottom" );
202             }
203         }
204         catch( Exception ex )
205         {
206             JOptionPane.showMessageDialog( null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE );
207         }
208 
209         if( maTopLine == null ||
210             maBottomLine == null )
211         {
212             JOptionPane.showMessageDialog( null, "One of the lines is still null", "Assertion", JOptionPane.WARNING_MESSAGE );
213             return;
214         }
215 
216         // position lines
217         // --------------
218 
219         // get data
220         XChartDataArray aDataArray = (XChartDataArray) UnoRuntime.queryInterface(
221             XChartDataArray.class, maChartDocument.getData());
222         double aData[][] = aDataArray.getData();
223 
224         // get axes
225         XDiagram aDiagram = maChartDocument.getDiagram();
226         XShape aXAxis = (XShape) UnoRuntime.queryInterface(
227             XShape.class, ((XAxisXSupplier) UnoRuntime.queryInterface(
228                                XAxisXSupplier.class, aDiagram )).getXAxis() );
229         XShape aYAxis = (XShape) UnoRuntime.queryInterface(
230             XShape.class, ((XAxisYSupplier) UnoRuntime.queryInterface(
231                                XAxisYSupplier.class, aDiagram )).getYAxis() );
232 
233         // calculate points for hull
234         final int nLength = aData.length;
235         int i, j;
236         double fMax, fMin;
237 
238         Point aMaxPtSeq[][] = new Point[ 1 ][];
239         aMaxPtSeq[ 0 ] = new Point[ nLength ];
240         Point aMinPtSeq[][] = new Point[ 1 ][];
241         aMinPtSeq[ 0 ] = new Point[ nLength ];
242 
243         for( i = 0; i < nLength; i++ )
244         {
245             fMin = fMax = aData[ i ][ 1 ];
246             for( j = 1; j < aData[ i ].length; j++ )
247             {
248                 if( aData[ i ][ j ] > fMax )
249                     fMax = aData[ i ][ j ];
250                 else if( aData[ i ][ j ] < fMin )
251                     fMin = aData[ i ][ j ];
252             }
253             aMaxPtSeq[ 0 ][ i ] = new Point( getAxisPosition( aXAxis, aData[ i ][ 0 ], false ),
254                                              getAxisPosition( aYAxis, fMax, true ));
255             aMinPtSeq[ 0 ][ i ] = new Point( getAxisPosition( aXAxis, aData[ i ][ 0 ], false ),
256                                              getAxisPosition( aYAxis, fMin, true ));
257         }
258 
259         // apply point sequences to lines
260         try
261         {
262             XPropertySet aShapeProp = (XPropertySet) UnoRuntime.queryInterface(
263                 XPropertySet.class, maTopLine );
264             aShapeProp.setPropertyValue( "PolyPolygon", aMaxPtSeq );
265 
266             aShapeProp = (XPropertySet) UnoRuntime.queryInterface(
267                 XPropertySet.class, maBottomLine );
268             aShapeProp.setPropertyValue( "PolyPolygon", aMinPtSeq );
269         }
270         catch( Exception ex )
271         {
272             JOptionPane.showMessageDialog( null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE );
273         }
274     }
275 
276     public void addRefreshListener( com.sun.star.util.XRefreshListener aListener )
277         throws RuntimeException
278     {
279         // we don't want this but we have to implement the interface
280     }
281 
282     public void removeRefreshListener( com.sun.star.util.XRefreshListener aListener )
283         throws RuntimeException
284     {
285         // we don't want this but we have to implement the interface
286     }
287 
288 
289     // XServiceName
290     public String getServiceName() throws RuntimeException
291     {
292         return new String( smServiceName );
293     }
294 
295     // XServiceInfo
296     public boolean supportsService( String aServiceName )
297     {
298         String[] aServices = getSupportedServiceNames_Static();
299         int i, nLength = aServices.length;
300         boolean bResult = false;
301 
302         for( i = 0; !bResult && i < nLength; ++i )
303             bResult = aServiceName.equals( aServices[ i ] );
304 
305         return bResult;
306     }
307 
308     public String getImplementationName()
309     {
310         return( JavaSampleChartAddIn.class.getName() );
311     }
312 
313     public String[] getSupportedServiceNames()
314     {
315         return getSupportedServiceNames_Static();
316     }
317 
318     // XDiagram
319     public String getDiagramType() throws RuntimeException
320     {
321         return new String( smServiceName );
322     }
323 
324     public XPropertySet getDataRowProperties( int nRow )
325         throws com.sun.star.lang.IndexOutOfBoundsException, RuntimeException
326     {
327         return maChartDocument.getDiagram().getDataRowProperties( nRow );
328     }
329 
330     public XPropertySet getDataPointProperties( int nCol, int nRow )
331         throws com.sun.star.lang.IndexOutOfBoundsException, RuntimeException
332     {
333         return maChartDocument.getDiagram().getDataPointProperties( nCol, nRow );
334     }
335 
336     // XShape : XDiagram
337     public Size getSize() throws RuntimeException
338     {
339         return ((XShape) UnoRuntime.queryInterface( XShape.class, maChartDocument.getDiagram())).getSize();
340     }
341     public void setSize( Size aSize ) throws RuntimeException, PropertyVetoException
342     {
343         ((XShape) UnoRuntime.queryInterface( XShape.class, maChartDocument.getDiagram())).setSize( aSize );
344     }
345 
346     public Point getPosition() throws RuntimeException
347     {
348         return ((XShape) UnoRuntime.queryInterface( XShape.class, maChartDocument.getDiagram())).getPosition();
349     }
350     public void setPosition( Point aPos ) throws RuntimeException
351     {
352         ((XShape) UnoRuntime.queryInterface( XShape.class, maChartDocument.getDiagram())).setPosition( aPos );
353     }
354 
355     // XShapeDescriptor : XShape : XDiagram
356     public String getShapeType() throws RuntimeException
357     {
358         return new String( "com.sun.star.comp.Chart.JavaSampleDiagramShape" );
359     }
360 
361 
362     // __________ private members __________
363     private com.sun.star.chart.XChartDocument       maChartDocument;
364     private com.sun.star.drawing.XDrawPage          maDrawPage;
365     private com.sun.star.lang.XMultiServiceFactory  maShapeFactory;
366 
367     // shapes added by add-in
368     private com.sun.star.drawing.XShape             maTopLine;
369     private com.sun.star.drawing.XShape             maBottomLine;
370 
371     // __________ private methods __________
372 
373     private int getAxisPosition( XShape aAxis, double fValue, boolean bVertical )
374     {
375         int nResult = 0;
376 
377         if( aAxis != null )
378         {
379             XPropertySet aAxisProp = (XPropertySet) UnoRuntime.queryInterface(
380                 XPropertySet.class, aAxis );
381 
382             try
383             {
384                 double fMin, fMax;
385                 fMin = ((Double) aAxisProp.getPropertyValue( "Min" )).doubleValue();
386                 fMax = ((Double) aAxisProp.getPropertyValue( "Max" )).doubleValue();
387                 double fRange = fMax - fMin;
388 
389                 if( fMin <= fValue && fValue <= fMax &&
390                     fRange != 0 )
391                 {
392                     if( bVertical )
393                     {
394                         nResult = aAxis.getPosition().Y +
395                             (int)((double)(aAxis.getSize().Height) *
396                                   (1.0 - (( fValue - fMin ) / fRange )));
397                     }
398                     else
399                     {
400                         nResult = aAxis.getPosition().X +
401                             (int)((double)(aAxis.getSize().Width) *
402                                   (( fValue - fMin ) / fRange ));
403                     }
404                 }
405 			}
406 			catch( Exception ex )
407 			{
408                 JOptionPane.showMessageDialog( null, ex, "Exception caught", JOptionPane.WARNING_MESSAGE );
409             }
410 		}
411         return nResult;
412 	}
413 
414     // __________ static things __________
415 
416     private static final String smServiceName  = "com.sun.star.comp.Chart.JavaSampleChartAddIn";
417 
418     public static String[] getSupportedServiceNames_Static()
419     {
420         String[] aResult = { smServiceName,
421                              "com.sun.star.chart.Diagram",
422                              "com.sun.star.chart.ChartAxisYSupplier" };
423         return aResult;
424     }
425 
426 
427     /**
428      * Returns a factory for creating the service.
429      * This method is called by the <code>JavaLoader</code>
430      * <p>
431      * @return  returns a <code>XSingleServiceFactory</code> for creating the component
432      * @param   implName     the name of the implementation for which a service is desired
433      * @param   multiFactory the service manager to be used if needed
434      * @param   regKey       the registryKey
435      * @see                  com.sun.star.comp.loader.JavaLoader
436      */
437     public static XSingleServiceFactory __getServiceFactory(
438         String implName,
439         XMultiServiceFactory multiFactory,
440         com.sun.star.registry.XRegistryKey regKey )
441     {
442         XSingleServiceFactory xSingleServiceFactory = null;
443 
444         if( implName.equals( JavaSampleChartAddIn.class.getName()) )
445         {
446             xSingleServiceFactory = com.sun.star.comp.loader.FactoryHelper.getServiceFactory(
447                 JavaSampleChartAddIn.class, smServiceName,
448                 multiFactory,  regKey );
449         }
450 
451         return xSingleServiceFactory;
452     }
453 
454     /**
455      * Writes the service information into the given registry key.
456      * This method is called by the <code>JavaLoader</code>
457      * <p>
458      * @return  returns true if the operation succeeded
459      * @param   regKey       the registryKey
460      * @see                  com.sun.star.comp.loader.JavaLoader
461      */
462     // This method not longer necessary since OOo 3.4 where the component registration
463     // was changed to passive component registration. For more details see
464     // http://wiki.services.openoffice.org/wiki/Passive_Component_Registration
465 
466 //    public static boolean __writeRegistryServiceInfo( com.sun.star.registry.XRegistryKey regKey )
467 //     {
468 //         boolean bResult = true;
469 
470 //         String[] aServices = getSupportedServiceNames_Static();
471 //         int i, nLength = aServices.length;
472 
473 //         for( i = 0; i < nLength; ++i )
474 //         {
475 //             bResult = bResult && com.sun.star.comp.loader.FactoryHelper.writeRegistryServiceInfo(
476 //                 JavaSampleChartAddIn.class.getName(), aServices[ i ], regKey );
477 //         }
478 //         return bResult;
479 //     }
480 }
481