blob: 0d23dc675877d1b107f918d72333d5c67bf0ef16 [file] [log] [blame]
/**************************************************************
*
* 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.
*
*************************************************************/
#include "sampleaddin.hxx"
#include <cppuhelper/factory.hxx>
#include <osl/diagnose.h>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/drawing/XDrawPage.hpp>
#include <com/sun/star/chart/XChartDataArray.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/chart/X3DDisplay.hpp>
using namespace com::sun::star;
using namespace rtl;
// code for creating instances of SampleAddIn
extern "C" {
void SAL_CALL component_getImplementationEnvironment(
const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ )
{
*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
sal_Bool SAL_CALL component_writeInfo(
void * /*pServiceManager*/, registry::XRegistryKey * pRegistryKey )
{
if( pRegistryKey )
{
try
{
OUString aImpl = OUString::createFromAscii( "/" );
aImpl += SampleAddIn::getImplementationName_Static();
aImpl += OUString::createFromAscii( "/UNO/SERVICES" );
uno::Reference< registry::XRegistryKey> xNewKey(
reinterpret_cast<registry::XRegistryKey*>( pRegistryKey )->createKey( aImpl ) );
uno::Sequence< OUString > aSequ = SampleAddIn::getSupportedServiceNames_Static();
const OUString * pArray = aSequ.getConstArray();
for( sal_Int32 i = 0; i < aSequ.getLength(); i++ )
xNewKey->createKey( pArray[i] );
return sal_True;
}
catch( registry::InvalidRegistryException& )
{
OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
}
}
return sal_False;
}
void * SAL_CALL component_getFactory(
const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
{
void* pRet = 0;
if ( pServiceManager &&
OUString::createFromAscii( pImplName ) == SampleAddIn::getImplementationName_Static() )
{
uno::Reference< lang::XSingleServiceFactory> xFactory( cppu::createSingleFactory(
reinterpret_cast<lang::XMultiServiceFactory*>( pServiceManager ),
SampleAddIn::getImplementationName_Static(),
SampleAddIn_CreateInstance,
SampleAddIn::getSupportedServiceNames_Static() ) );
if( xFactory.is())
{
xFactory->acquire();
pRet = xFactory.get();
}
}
return pRet;
}
} // extern C
// --------------------
// class SampleAddIn
// --------------------
SampleAddIn::SampleAddIn()
{
}
SampleAddIn::~SampleAddIn()
{}
// this functionality should be provided by the chart API some day
sal_Bool SampleAddIn::getLogicalPosition( uno::Reference< drawing::XShape >& xAxis,
double fValue,
sal_Bool bVertical,
awt::Point& aOutPosition )
{
sal_Bool bRet = sal_False;
if( xAxis.is())
{
awt::Size aSize = xAxis->getSize();
sal_Int32 nLength = bVertical? aSize.Height: aSize.Width;
uno::Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY );
if( xProp.is())
{
try
{
double fMin(0.0), fMax(0.0);
uno::Any aAny = xProp->getPropertyValue( OUString::createFromAscii( "Min" ));
aAny >>= fMin;
aAny = xProp->getPropertyValue( OUString::createFromAscii( "Max" ));
aAny >>= fMax;
double fRange = fMax - fMin;
if( fMin <= fValue && fValue <= fMax &&
fRange != 0.0 )
{
double fPercentage = (fValue - fMin) / fRange;
awt::Point aPos = xAxis->getPosition();
if( bVertical )
{
aOutPosition.X = aPos.X;
aOutPosition.Y = static_cast<sal_Int32>(aPos.Y + nLength * (1.0 - fPercentage)); // y scale goes from top to bottom
}
else
{
aOutPosition.X = static_cast<sal_Int32>(aPos.X + nLength * fPercentage);
aOutPosition.Y = aPos.Y;
}
bRet = sal_True;
}
}
catch( beans::UnknownPropertyException )
{
// the shape xAxis was no chart axis
}
}
}
return bRet;
}
OUString SampleAddIn::getImplementationName_Static()
{
return OUString::createFromAscii( "SampleAddIn" );
}
uno::Sequence< ::rtl::OUString > SampleAddIn::getSupportedServiceNames_Static()
{
uno::Sequence< OUString > aSeq( 4 );
aSeq[ 0 ] = OUString::createFromAscii( "com.sun.star.chart.ChartAxisXSupplier" );
aSeq[ 1 ] = OUString::createFromAscii( "com.sun.star.chart.ChartAxisYSupplier" );
aSeq[ 2 ] = OUString::createFromAscii( "com.sun.star.chart.Diagram" );
aSeq[ 3 ] = OUString::createFromAscii( "com.sun.star.chart.SampleAddIn" );
return aSeq;
}
uno::Reference< uno::XInterface > SAL_CALL SampleAddIn_CreateInstance(
const uno::Reference< lang::XMultiServiceFactory >& )
{
uno::Reference< uno::XInterface > xInst = (cppu::OWeakObject*)new SampleAddIn();
return xInst;
}
// implementation of interface methods
// XInitialization
void SAL_CALL SampleAddIn::initialize( const uno::Sequence< uno::Any >& aArguments )
throw( uno::Exception, uno::RuntimeException )
{
// first argument should be the XChartDocument
OSL_ENSURE( aArguments.getLength() > 0, "Please initialize Chart AddIn with ChartDocument!" );
if( aArguments.getLength())
{
aArguments[ 0 ] >>= mxChartDoc;
OSL_ENSURE( mxChartDoc.is(), "First argument in initialization is not an XChartDocument!" );
// set XY chart as base type to be drawn
uno::Reference< beans::XPropertySet > xDocProp( mxChartDoc, uno::UNO_QUERY );
if( xDocProp.is())
{
uno::Any aBaseType;
aBaseType <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart.XYDiagram" ));
try
{
xDocProp->setPropertyValue( rtl::OUString::createFromAscii( "BaseDiagram" ), aBaseType );
}
catch( ... )
{}
}
// change background of plot area to light blue
uno::Reference< chart::X3DDisplay > xWallSupplier( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xWallSupplier.is())
{
uno::Reference< beans::XPropertySet > xDiaProp( xWallSupplier->getWall(), uno::UNO_QUERY );
uno::Reference< beans::XPropertySet > xLegendProp( mxChartDoc->getLegend(), uno::UNO_QUERY );
if( xDiaProp.is() &&
xLegendProp.is())
{
uno::Any aAny;
aAny <<= (sal_Int32)( 0xe0e0f0 );
xDiaProp->setPropertyValue( OUString::createFromAscii( "FillColor" ), aAny );
xLegendProp->setPropertyValue( OUString::createFromAscii( "FillColor" ), aAny );
}
}
}
}
// XRefreshable
/********************************************************************************
*
* The method refresh is the most important method - here all objects that
* are necessary for the chart are created
*
* in the first implementation you will have to insert everything in this
* routine - all old objects are deleted beforehand
*
********************************************************************************/
void SAL_CALL SampleAddIn::refresh() throw( uno::RuntimeException )
{
if( ! mxChartDoc.is())
return;
// first of all get the draw page
uno::Reference< drawing::XDrawPageSupplier > xPageSupp( mxChartDoc, uno::UNO_QUERY );
uno::Reference< lang::XMultiServiceFactory > xFactory( mxChartDoc, uno::UNO_QUERY );
if( xPageSupp.is() &&
xFactory.is() )
{
uno::Reference< drawing::XDrawPage > xPage = xPageSupp->getDrawPage();
if( xPage.is())
{
// now we have the page to insert objects
// add a horizontal line at the middle value of the first series
// -------------------------------------------------------------
// get the logical position from the coordinate
// get x- and y-axis
uno::Reference< drawing::XShape > xYAxisShape( getYAxis(), uno::UNO_QUERY );
uno::Reference< drawing::XShape > xXAxisShape( getXAxis(), uno::UNO_QUERY );
if( xXAxisShape.is() &&
xYAxisShape.is() )
{
// create line first time
if( ! mxMyRedLine.is())
{
mxMyRedLine = uno::Reference< drawing::XShape >(
xFactory->createInstance( OUString::createFromAscii( "com.sun.star.drawing.LineShape" )),
uno::UNO_QUERY );
xPage->add( mxMyRedLine );
// make line red and thick
uno::Reference< beans::XPropertySet > xShapeProp( mxMyRedLine, uno::UNO_QUERY );
if( xShapeProp.is())
{
uno::Any aColor, aWidth;
aColor <<= (sal_Int32)(0xe01010);
aWidth <<= (sal_Int32)(50); // 0.5 mm
try
{
xShapeProp->setPropertyValue( OUString::createFromAscii( "LineColor" ), aColor );
xShapeProp->setPropertyValue( OUString::createFromAscii( "LineWidth" ), aWidth );
}
catch( ... )
{}
}
}
// create text object first time
if( ! mxMyText.is())
{
mxMyText = uno::Reference< drawing::XShape >(
xFactory->createInstance( OUString::createFromAscii( "com.sun.star.drawing.TextShape" )),
uno::UNO_QUERY );
xPage->add( mxMyText );
// change text
OUString aText;
// if( maLocale.Language.equalsIgnoreCase( OUString::createFromAscii("DE")))
// aText = OUString::createFromAscii( "Kleines Beispiel" );
// else
aText = OUString::createFromAscii( "Little Example" );
uno::Reference< beans::XPropertySet > xTextProp( mxMyText, uno::UNO_QUERY );
if( xTextProp.is())
{
uno::Any aTrueAny;
aTrueAny <<= (sal_Bool)(sal_True);
try
{
xTextProp->setPropertyValue( rtl::OUString::createFromAscii( "TextAutoGrowWidth" ), aTrueAny );
}
catch( ... )
{}
}
uno::Reference< text::XTextRange > xTextRange( mxMyText, uno::UNO_QUERY );
if( xTextRange.is())
{
xTextRange->setString( aText );
}
}
// position line and text
// get the array. Note: the first dimension is the length
// of each series and the second one is the number of series
// this should be changed in the future
uno::Sequence< uno::Sequence< double > > aData;
uno::Reference< chart::XChartData > xData = mxChartDoc->getData();
uno::Reference< chart::XChartDataArray > xDataArray( xData, uno::UNO_QUERY );
if( xDataArray.is())
aData = xDataArray->getData();
// get row count == length of each series
sal_Int32 nSize = aData.getLength();
sal_Int32 nMiddle = nSize / 2;
// get value for first series
double fMiddleVal = xData->getNotANumber(); // set to NaN
if( aData[ nMiddle ].getLength()) // we have at least one series
fMiddleVal = aData[ nMiddle ][ 0 ];
awt::Point aPos;
getLogicalPosition( xYAxisShape, fMiddleVal, sal_True, aPos );
awt::Size aSize = xXAxisShape->getSize();
if( mxMyRedLine.is())
{
awt::Point aEnd = aPos;
aEnd.X += aSize.Width;
uno::Sequence< uno::Sequence< awt::Point > > aPtSeq( 1 );
aPtSeq[ 0 ].realloc( 2 );
aPtSeq[ 0 ][ 0 ] = aPos;
aPtSeq[ 0 ][ 1 ] = aEnd;
uno::Reference< beans::XPropertySet > xShapeProp( mxMyRedLine, uno::UNO_QUERY );
if( xShapeProp.is())
{
uno::Any aAny;
aAny <<= aPtSeq;
xShapeProp->setPropertyValue( rtl::OUString::createFromAscii( "PolyPolygon" ), aAny );
}
}
if( mxMyText.is())
{
// put the text centered below the red line
aPos.X += ( aSize.Width - mxMyRedLine->getPosition().X ) / 2;
aPos.Y += 1000;
aPos.Y += static_cast<sal_Int32>(0.1 * xYAxisShape->getSize().Height);
mxMyText->setPosition( aPos );
}
}
}
}
// set axis scale to 200
// uno::Reference< beans::XPropertySet > xXAxis( getXAxis(), uno::UNO_QUERY );
// if( xXAxis.is())
// {
// uno::Any aAny;
// aAny <<= (sal_Bool)(sal_False);
// xXAxis->setPropertyValue( rtl::OUString::createFromAscii( "AutoStepMain" ),
// aAny );
// aAny <<= (double)(200.0);
// xXAxis->setPropertyValue( rtl::OUString::createFromAscii( "StepMain" ),
// aAny );
// }
// try setting symbols
// uno::Reference< beans::XPropertySet > xProp = getDataRowProperties( 0 );
// if( xProp.is())
// {
// uno::Any aAny;
// aAny <<= (sal_Int32)(-1);
// xProp->setPropertyValue( OUString::createFromAscii( "SymbolType" ), aAny );
// aAny <<= rtl::OUString::createFromAscii( "http://mib-1168/www/images/go.gif" );
// xProp->setPropertyValue( OUString::createFromAscii( "SymbolBitmapURL" ), aAny );
// }
}
void SAL_CALL SampleAddIn::addRefreshListener( const uno::Reference< util::XRefreshListener >& )
throw( uno::RuntimeException )
{
// not implemented - this is not necessary
// (this method exists just because the interface requires it)
}
void SAL_CALL SampleAddIn::removeRefreshListener( const uno::Reference< util::XRefreshListener >& )
throw( uno::RuntimeException )
{
// not implemented - this is not necessary
// (this method exists just because the interface requires it)
}
// XDiagram
OUString SAL_CALL SampleAddIn::getDiagramType() throw( uno::RuntimeException )
{
return OUString::createFromAscii( "com.sun.star.chart.SampleDiagram" );
}
// the following methods just delegate to the "parent diagram" (which in the future might no longer exist)
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getDataRowProperties( sal_Int32 nRow )
throw( lang::IndexOutOfBoundsException,
uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XDiagram > xDia = mxChartDoc->getDiagram();
if( xDia.is())
return xDia->getDataRowProperties( nRow );
}
return uno::Reference< beans::XPropertySet >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getDataPointProperties( sal_Int32 nCol, sal_Int32 nRow )
throw( lang::IndexOutOfBoundsException,
uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XDiagram > xDia = mxChartDoc->getDiagram();
if( xDia.is())
return xDia->getDataPointProperties( nCol, nRow );
}
return uno::Reference< beans::XPropertySet >();
}
// XShape ( ::XDiagram )
awt::Size SAL_CALL SampleAddIn::getSize()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< drawing::XShape > xShape( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xShape.is())
return xShape->getSize();
}
return awt::Size();
}
void SAL_CALL SampleAddIn::setSize( const awt::Size& aSize )
throw( beans::PropertyVetoException, uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< drawing::XShape > xShape( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xShape.is())
xShape->setSize( aSize );
}
}
awt::Point SAL_CALL SampleAddIn::getPosition()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< drawing::XShape > xShape( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xShape.is())
return xShape->getPosition();
}
return awt::Point();
}
void SAL_CALL SampleAddIn::setPosition( const awt::Point& aPos )
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< drawing::XShape > xShape( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xShape.is())
xShape->setPosition( aPos );
}
}
// XShapeDescriptor ( ::XShape ::XDiagram )
rtl::OUString SAL_CALL SampleAddIn::getShapeType() throw( com::sun::star::uno::RuntimeException )
{
return OUString::createFromAscii( "com.sun.star.chart.SampleAddinShape" );
}
// XAxisXSupplier
uno::Reference< drawing::XShape > SAL_CALL SampleAddIn::getXAxisTitle()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XAxisXSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xAxisSupp.is())
return xAxisSupp->getXAxisTitle();
}
return uno::Reference< drawing::XShape >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getXAxis()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XAxisXSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xAxisSupp.is())
return xAxisSupp->getXAxis();
}
return uno::Reference< beans::XPropertySet >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getXMainGrid()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XAxisXSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xAxisSupp.is())
return xAxisSupp->getXMainGrid();
}
return uno::Reference< beans::XPropertySet >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getXHelpGrid()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XAxisXSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xAxisSupp.is())
return xAxisSupp->getXHelpGrid();
}
return uno::Reference< beans::XPropertySet >();
}
// XAxisYSupplier
uno::Reference< drawing::XShape > SAL_CALL SampleAddIn::getYAxisTitle()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XAxisYSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xAxisSupp.is())
return xAxisSupp->getYAxisTitle();
}
return uno::Reference< drawing::XShape >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getYAxis()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XAxisYSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xAxisSupp.is())
return xAxisSupp->getYAxis();
}
return uno::Reference< beans::XPropertySet >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getYMainGrid()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XAxisYSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xAxisSupp.is())
return xAxisSupp->getYMainGrid();
}
return uno::Reference< beans::XPropertySet >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getYHelpGrid()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XAxisYSupplier > xAxisSupp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xAxisSupp.is())
return xAxisSupp->getYHelpGrid();
}
return uno::Reference< beans::XPropertySet >();
}
// XStatisticDisplay
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getUpBar()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XStatisticDisplay > xStatDisp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xStatDisp.is())
return xStatDisp->getUpBar();
}
return uno::Reference< beans::XPropertySet >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getDownBar()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XStatisticDisplay > xStatDisp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xStatDisp.is())
return xStatDisp->getDownBar();
}
return uno::Reference< beans::XPropertySet >();
}
uno::Reference< beans::XPropertySet > SAL_CALL SampleAddIn::getMinMaxLine()
throw( uno::RuntimeException )
{
if( mxChartDoc.is())
{
uno::Reference< chart::XStatisticDisplay > xStatDisp( mxChartDoc->getDiagram(), uno::UNO_QUERY );
if( xStatDisp.is())
return xStatDisp->getMinMaxLine();
}
return uno::Reference< beans::XPropertySet >();
}
// XServiceName
OUString SAL_CALL SampleAddIn::getServiceName() throw( uno::RuntimeException )
{
return OUString::createFromAscii( "com.sun.star.chart.SampleAddIn" );
}
// XServiceInfo
OUString SAL_CALL SampleAddIn::getImplementationName() throw( uno::RuntimeException )
{
return getImplementationName_Static();
}
sal_Bool SAL_CALL SampleAddIn::supportsService( const OUString& ServiceName )
throw( uno::RuntimeException )
{
uno::Sequence< OUString > aServiceSeq = getSupportedServiceNames_Static();
sal_Int32 nLength = aServiceSeq.getLength();
for( sal_Int32 i=0; i < nLength; i++ )
{
if( ServiceName.equals( aServiceSeq[ i ] ))
return sal_True;
}
return sal_False;
}
uno::Sequence< OUString > SAL_CALL SampleAddIn::getSupportedServiceNames()
throw( uno::RuntimeException )
{
return getSupportedServiceNames_Static();
}
// XLocalizable
void SAL_CALL SampleAddIn::setLocale( const lang::Locale& eLocale )
throw( uno::RuntimeException )
{
maLocale = eLocale;
}
lang::Locale SAL_CALL SampleAddIn::getLocale()
throw( uno::RuntimeException )
{
return maLocale;
}