diff options
Diffstat (limited to 'chart2/workbench/addin/sampleaddin.cxx')
-rw-r--r-- | chart2/workbench/addin/sampleaddin.cxx | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/chart2/workbench/addin/sampleaddin.cxx b/chart2/workbench/addin/sampleaddin.cxx new file mode 100644 index 000000000..665a205ab --- /dev/null +++ b/chart2/workbench/addin/sampleaddin.cxx @@ -0,0 +1,652 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#include "sampleaddin.hxx" + +#include <cppuhelper/supportsservice.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; + +// code for creating instances of SampleAddIn + +extern "C" { + +sal_Bool SAL_CALL component_writeInfo( + void * /*pServiceManager*/, registry::XRegistryKey * pRegistryKey ) +{ + if( pRegistryKey ) + { + try + { + OUString aImpl = "/" + SampleAddIn::getImplementationName_Static() + "/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.(); i++ ) + xNewKey->createKey( pArray[i] ); + + return sal_True; + } + catch( const registry::InvalidRegistryException& ) + { + OSL_FAIL( "### InvalidRegistryException!" ); + } + } + return sal_False; +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const 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 + + +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( "Min" ); + aAny >>= fMin; + aAny = xProp->getPropertyValue( "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( const beans::UnknownPropertyException& ) + { + // the shape xAxis was no chart axis + } + } + } + + return bRet; +} + +OUString SampleAddIn::getImplementationName_Static() +{ + return "SampleAddIn"; +} + +uno::Sequence< OUString > SampleAddIn::getSupportedServiceNames_Static() +{ + return { + "com.sun.star.chart.ChartAxisXSupplier", + "com.sun.star.chart.ChartAxisYSupplier", + "com.sun.star.chart.Diagram", + "com.sun.star.chart.SampleAddIn" + }; +} + +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 <<= "com.sun.star.chart.XYDiagram"; + try + { + xDocProp->setPropertyValue( "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( "FillColor" , aAny ); + xLegendProp->setPropertyValue( "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.set( + xFactory->createInstance( "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( "LineColor" , aColor ); + xShapeProp->setPropertyValue( "LineWidth" , aWidth ); + } + catch( ... ) + {} + } + } + // create text object first time + if( ! mxMyText.is()) + { + mxMyText.set( + xFactory->createInstance( "com.sun.star.drawing.TextShape" ), + uno::UNO_QUERY ); + xPage->add( mxMyText ); + + // change text + OUString aText( "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( "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()) + { + xShapeProp->setPropertyValue( "PolyPolygon" , Any(aPtSeq) ); + } + } + 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 ); + } + } + } + } +} + +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 "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 ) +OUString SAL_CALL SampleAddIn::getShapeType() throw( css::uno::RuntimeException ) +{ + return "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 "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 ) +{ + return cppu::supportsService(this, ServiceName); +} + +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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |