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