How Add-Ins Work

From Apache OpenOffice Wiki
Jump to: navigation, search



The method initialize() from the com.sun.star.lang.XInitialization interface is the first method that is called for an add-in. It is called directly after it is created by the com.sun.star.lang.XMultiServiceFactory provided by the chart document. This method gets the XChartDocument object.

When initialize() is called, the argument returned is the chart document. Store this as a member to that it can be called later in the refresh() call to access all elements of the chart. The following is an example for the initialize() method of an add-in written in Java:

  // XInitialization
  public void initialize(Object[] aArguments) throws Exception, RuntimeException {
      if (aArguments.length > 0) {
          // maChartDocument is a member
          // which is set to the parent chart document 
          // that is given as first argument
          maChartDocument = (XChartDocument) UnoRuntime.queryInterface(
              XChartDocument.class, aArguments[0]);
 
          XPropertySet aDocProp = (XPropertySet) UnoRuntime.queryInterface(
              XPropertySet.class, maChartDocument);
          if (aDocProp != null) {
              // set base diagram which will be extended in refresh()
              aDocProp.setPropertyValue("BaseDiagram", "com.sun.star.chart.XYDiagram");
          }
 
          // remember the draw page, as it is frequently used by refresh()
          // (this is not necessary but convenient)
          XDrawPageSupplier aPageSupp = (XDrawPageSupplier) UnoRuntime.queryInterface(
              XDrawPageSupplier.class, maChartDocument);
          if( aPageSupp != null )
              maDrawPage = (XDrawPage) UnoRuntime.queryInterface(
                  XDrawPage.class, aPageSupp.getDrawPage());
      }
  }

An important method of an add-in component is refresh() from the com.sun.star.util.XRefreshable. This method is called every time the chart is rebuilt. A change of data results in a refresh, but also a resizing or changing of a property that affects the layout calls the refresh() method. For example, the property HasLegend that switches the legend on and off.

To add shapes to the chart, create them once and modify them later during the refresh calls. In the following example, a line is created in initialize() and modified during refresh():

  // XInitialization
  public void initialize(Object[] aArguments) throws Exception, RuntimeException {
      // get document and page -- see above
      // ...
 
          // get a shape factory
          maShapeFactory = ...;
 
          // create top line
          maTopLine = (XShape) UnoRuntime.queryInterface(
              XShape.class, maShapeFactory.createInstance("com.sun.star.drawing.LineShape"));
          maDrawPage.add(maTopLine);
 
          // make line red and thicker
          XPropertySet aShapeProp = (XPropertySet)UnoRuntime.queryInterface(
              XPropertySet.class, maTopLine);
          aShapeProp.setPropertyValue("LineColor", new Integer(0xe01010));
          aShapeProp.setPropertyValue("LineWidth", new Integer(50));
 
          // create bottom line
          maBottomLine = (XShape) UnoRuntime.queryInterface(
              XShape.class, maShapeFactory.createInstance("com.sun.star.drawing.LineShape"));
          maDrawPage.add(maBottomLine);
 
          // make line green and thicker
          aShapeProp = (XPropertySet) UnoRuntime.queryInterface(
              XPropertySet.class, maBottomLine);
          aShapeProp.setPropertyValue("LineColor", new Integer(0x10e010));
          aShapeProp.setPropertyValue("LineWidth", new Integer(50));
      }
 
  }
 
  // XRefreshable
  public void refresh() throws RuntimeException {
      // position lines
      // --------------
 
      // get data
      XChartDataArray aDataArray = (XChartDataArray) UnoRuntime.queryInterface(
          XChartDataArray.class, maChartDocument.getData());
      double aData[][] = aDataArray.getData();
 
      // get axes
      XDiagram aDiagram = maChartDocument.getDiagram();
      XShape aXAxis = (XShape) UnoRuntime.queryInterface(
          XShape.class, ((XAxisXSupplier) UnoRuntime.queryInterface( 
              XAxisXSupplier.class, aDiagram)).getXAxis());
      XShape aYAxis = (XShape) UnoRuntime.queryInterface(
          XShape.class, ((XAxisYSupplier) UnoRuntime.queryInterface(
              XAxisYSupplier.class, aDiagram)).getYAxis());
 
      // calculate points for hull
      final int nLength = aData.length;
      int i, j;
      double fMax, fMin;
 
      Point aMaxPtSeq[][] = new Point[1][];
      aMaxPtSeq[0] = new Point[nLength];
      Point aMinPtSeq[][] = new Point[1][];
      aMinPtSeq[0] = new Point[nLength];
 
      for (i = 0; i < nLength; i++) {
          fMin = fMax = aData[i][1];
          for (j = 1; j < aData[i].length; j++) {
              if (aData[i][j] > fMax)
                  fMax = aData[i][j];
              else if (aData[i][j] < fMin)
                  fMin = aData[i][j];
          }
          aMaxPtSeq[0][i] = new Point(getAxisPosition(aXAxis, aData[i][0], false),
              getAxisPosition(aYAxis, fMax, true));
          aMinPtSeq[0][i] = new Point(getAxisPosition(aXAxis, aData[i][0], false),
              getAxisPosition(aYAxis, fMin, true));
      }
 
      // apply point sequences to lines
      try {
          XPropertySet aShapeProp = (XPropertySet) UnoRuntime.queryInterface(
              XPropertySet.class, maTopLine);
          aShapeProp.setPropertyValue("PolyPolygon", aMaxPtSeq);
 
          aShapeProp = (XPropertySet) UnoRuntime.queryInterface(
              XPropertySet.class, maBottomLine);
          aShapeProp.setPropertyValue("PolyPolygon", aMinPtSeq);
      } catch (Exception ex) {
      }
  }
 
  // determine the position of a value along an axis
  // bVertical is true for the y-axis and false for the x-axis
  private int getAxisPosition(XShape aAxis, double fValue, boolean bVertical) {
      int nResult = 0;
 
      if (aAxis != null) {
          XPropertySet aAxisProp = (XPropertySet) UnoRuntime.queryInterface(
              XPropertySet.class, aAxis);
 
          try {
              double fMin, fMax;
              fMin = ((Double) aAxisProp.getPropertyValue("Min")).doubleValue();
              fMax = ((Double) aAxisProp.getPropertyValue("Max")).doubleValue();
              double fRange = fMax - fMin;
 
              if (fMin <= fValue && fValue <= fMax && fRange != 0) {
                  if (bVertical) {
                      // y==0 is at the top, thus take 1.0 - ...
                      nResult = aAxis.getPosition().Y +
                          (int)((double)(aAxis.getSize().Height) * (1.0 - ((fValue - fMin) / fRange)));
                  } else {
                      nResult = aAxis.getPosition().X +
                          (int)((double)(aAxis.getSize().Width) * ((fValue - fMin) / fRange));
                  }
              }
          } catch (Exception ex) {
          }
      }
  return nResult;
  }

The subroutine getAxisPosition() is a helper to determine the position of a point inside the diagram coordinates. This add-in calculates the maximum and minimum values for each slice of data points, and creates two polygons based on these points.

Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages