From 91f97fc2234ae939076e751cb613c0712bd4a7e6 Mon Sep 17 00:00:00 2001 From: Vladimir Glazounov Date: Tue, 22 May 2007 18:22:45 +0000 Subject: [PATCH] INTEGRATION: CWS chart2mst3 (1.32.4); FILE MERGED 2007/04/20 08:13:21 iha 1.32.4.93: #i75393# Connect Bars per diagram not per series 2007/04/19 16:13:26 iha 1.32.4.92: #i76130# write attribute sort-by-x-values per plot-area not per series 2007/03/19 15:23:43 bm 1.32.4.91: #i75418# support XTransferable in model and offer a high-contrast replacement image 2007/02/26 14:35:17 iha 1.32.4.90: special resize only for pie and donut 2007/02/06 16:30:30 iha 1.32.4.89: missing SolarMutex 2006/12/15 13:37:58 iha 1.32.4.88: #i72360# use axis number format for data labels when one is provided 2006/12/01 18:36:52 iha 1.32.4.87: #68896# always save the explicit number format 2006/11/26 12:48:23 bm 1.32.4.86: includes for solar mutex missing 2006/11/22 17:26:21 iha 1.32.4.85: RESYNC: (1.34-1.35); FILE MERGED 2006/11/16 13:43:16 iha 1.32.4.84: #i71215# corrected position for diagrams with axis title - don't create empty titles 2006/11/10 21:04:49 iha 1.32.4.83: set modified only when resolution gets higher 2006/11/09 15:24:22 iha 1.32.4.82: #i16280# better performance for charts with many data (bar,column,line,area,xy,net charts) 2006/10/18 17:22:42 bm 1.32.4.81: RESYNC: (1.33-1.34); FILE MERGED 2006/10/12 10:55:12 iha 1.32.4.80: wrong selection of series - due to weakreferences of draw shapes dying to early -> switch back to normal references 2006/10/06 19:16:44 iha 1.32.4.79: recreate pies and donuts with corrected size to get correct labels even with legend entries 2006/10/05 15:28:26 iha 1.32.4.78: saved diagram size is corrupted 2006/09/27 17:24:39 iha 1.32.4.77: some cleanup around pie size 2006/09/27 17:22:58 iha 1.32.4.76: corrected reference size for data labels 2006/09/24 09:12:58 iha 1.32.4.75: #i61970# correct implementation of axis at 2006/08/25 17:16:26 iha 1.32.4.74: text- and diagram-size dependent auto main step width 2006/08/23 17:07:28 iha 1.32.4.73: enable axis to estimate the maximum automatic MainIncrementCount, reduce count to 2 for net charts 2006/08/10 15:58:24 iha 1.32.4.72: Axis Label Layout - Font&Diagram Size 2006/08/08 15:02:30 iha 1.32.4.71: don't refresh addin when loading is not finished 2006/08/08 12:24:48 iha 1.32.4.70: always remove automatically created shapes before creating new 2006/08/08 12:22:51 iha 1.32.4.69: correct dirty state for view 2006/08/08 12:11:40 iha 1.32.4.68: guard access to native drawinglayer with SolarMutex 2006/08/01 09:48:32 bm 1.32.4.67: #i29600# resize the label sizes of data series with the diagram size if a reference size is set 2006/07/04 12:28:16 iha 1.32.4.66: aspect ratio 2006/07/01 21:05:53 iha 1.32.4.65: define and respect aspect ratio of diagram 2006/04/10 15:03:38 iha 1.32.4.64: api restructure axis, grids, scales and increments 2006/04/10 12:25:19 iha 1.32.4.63: api restructure axis, grids, scales and increments 2006/04/03 12:28:00 iha 1.32.4.62: correct selection handles for data point labels and legend entries 2006/03/29 22:24:49 iha 1.32.4.61: restructure legend entry creation + legend entries in data labels 2006/03/23 15:32:45 iha 1.32.4.60: cleanup category handling 2006/03/23 09:28:24 iha 1.32.4.59: categories for data labels 2006/03/12 01:14:31 iha 1.32.4.58: changed communication between model, view and controller; implemented old AddIn Interface; changed owneship and lifetime of view 2006/02/20 14:34:46 iha 1.32.4.57: move SchItemPool from controller to view lib -> ChartItemPool 2006/02/16 17:35:58 iha 1.32.4.56: return size of axis lines only instead of axis including labels for old api 2006/01/15 16:41:58 iha 1.32.4.55: correct distance between diagram and legend 2006/01/09 14:30:47 iha 1.32.4.54: diagram is not resizeable via mouse anymore 2005/12/21 21:29:42 iha 1.32.4.53: remove identifiers from model objects and create an index based CID protocol instead for selection purposes 2005/12/01 18:53:40 iha 1.32.4.52: create axis title with correct rotation default + don't mix x and y in barcharts 2005/12/01 16:41:28 iha 1.32.4.51: #124571# load & save position of rotated titles correctly 2005/11/25 16:33:56 iha 1.32.4.50: correct labels at z axis for deep stacking 2005/11/02 16:37:55 bm 1.32.4.49: safeness when XScale is 0 2005/10/25 11:57:18 bm 1.32.4.48: Solaris compiler did not like map access 2005/10/25 10:41:54 bm 1.32.4.47: & too much in variable declaration 2005/10/24 11:07:14 iha 1.32.4.46: coordinate system restructure 2005/10/13 17:39:14 iha 1.32.4.45: renamed BoundedCoordinateSystem to CoordinateSystem 2005/10/07 12:24:13 bm 1.32.4.44: RESYNC: (1.32-1.33); FILE MERGED 2005/09/16 16:50:23 iha 1.32.4.43: no creation of dummy categories in model - instead trigger generation of missing labels and categories in view 2005/08/24 11:50:37 iha 1.32.4.42: direct initialization for less warnings 2005/08/18 11:42:05 iha 1.32.4.41: moved colorscheme transport 2005/07/28 09:34:57 bm 1.32.4.40: usage of color schemes and the VaryColorsByPoint property to have correct pie colors and legend entries 2005/07/23 00:01:21 iha 1.32.4.39: include axis title sizes in diagram position to support old api and fileformat 2005/07/21 14:47:16 bm 1.32.4.38: support for number formats from data provider 2005/07/18 19:03:27 iha 1.32.4.37: don't display axes in pie chart 2005/07/15 07:24:46 iha 1.32.4.36: remove extra space hack for axis label 2005/07/13 15:22:45 iha 1.32.4.35: update draw model tables before use in view and dialogs 2005/07/12 08:41:15 iha 1.32.4.34: correct assertion text 2005/07/08 15:20:27 iha 1.32.4.33: index violation 2005/07/08 12:49:31 iha 1.32.4.32: provide and keep view as service only 2005/07/05 16:02:44 iha 1.32.4.31: redefine diagram size 2005/06/23 16:39:17 iha 1.32.4.30: quick hack for more complete visibility of the diagram as long as the correct layout is missing 2005/06/09 15:43:52 iha 1.32.4.29: support positions and sizes via view for old api wrapper 2005/06/07 15:42:31 iha 1.32.4.28: use numberformatter from model 2005/06/03 14:43:09 iha 1.32.4.27: construct chartview with drawmodelwrapper 2005/06/01 17:03:15 iha 1.32.4.26: export metafile 2005/05/31 19:20:26 iha 1.32.4.25: create view without controller 2005/05/09 09:51:38 bm 1.32.4.24: moved parts of API to data namespace 2004/09/27 14:41:23 iha 1.32.4.23: reduce direct access to draw model 2004/09/17 17:24:34 iha 1.32.4.22: correct positions for titles also after move 2004/09/17 11:26:20 iha 1.32.4.21: implement api redesign - dimension property 2004/09/17 10:24:29 iha 1.32.4.20: correct x stacking 2004/09/16 14:45:33 iha 1.32.4.19: implement api redesign 2004/09/15 09:57:15 iha 1.32.4.18: implement api redesign 2004/08/26 13:14:01 iha 1.32.4.17: saver page creation 2004/08/25 16:38:56 iha 1.32.4.16: View independent loading - relative position with dynamic anchor point 2004/04/27 15:00:43 iha 1.32.4.15: warnings removed 2004/04/26 11:45:06 iha 1.32.4.14: getExplicitValuesForMeter returns bool + CID for page 2004/04/22 09:32:34 iha 1.32.4.13: more explicit default for 'no stacking' 2004/04/13 16:34:24 iha 1.32.4.12: corrected stacking 2004/03/24 10:26:12 bm 1.32.4.11: safety check for empty tree in initializeDiagramAndGetCooSys 2004/03/22 19:34:51 iha 1.32.4.10: transport information bSwapXAndYAxis over method setScales 2004/03/19 10:59:08 iha 1.32.4.9: modified creation of plotter for attaching series to secondary axis 2004/03/18 16:36:46 iha 1.32.4.8: create axis even if no plotter is attached to the coordinate system 2004/03/12 15:34:39 iha 1.32.4.7: removed shadow warning 2004/03/11 12:26:30 iha 1.32.4.6: calculate PreferredAspectRatio for charttype dependent 3D scene aspect ratio and set to diagram + some cleanup 2004/03/02 13:03:13 iha 1.32.4.5: use PropertyMapper::getPropertyNameMapForFillAndLineProperties 2004/02/26 14:03:44 iha 1.32.4.4: remove warnings 2004/02/26 13:53:12 iha 1.32.4.3: share coordinate systems and scales for combi charts 2004/02/26 12:18:10 iha 1.32.4.2: share coordinate systems and scales for combi charts 2004/02/13 16:52:00 bm 1.32.4.1: join from changes on branch bm_post_chart01 --- chart2/source/view/main/ChartView.cxx | 2366 ++++++++++++++++++++----- 1 file changed, 1912 insertions(+), 454 deletions(-) diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx index fcf714941afa..56bf08c93c2a 100644 --- a/chart2/source/view/main/ChartView.cxx +++ b/chart2/source/view/main/ChartView.cxx @@ -4,9 +4,9 @@ * * $RCSfile: ChartView.cxx,v $ * - * $Revision: 1.35 $ + * $Revision: 1.36 $ * - * last change: $Author: ihi $ $Date: 2006-11-14 15:35:32 $ + * last change: $Author: vg $ $Date: 2007-05-22 19:22:45 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -33,9 +33,12 @@ * ************************************************************************/ + // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_chart2.hxx" -#include "ChartViewImpl.hxx" + +#include "ChartView.hxx" +#include "chartview/DrawModelWrapper.hxx" #include "ViewDefines.hxx" #include "VDiagram.hxx" #include "VTitle.hxx" @@ -50,48 +53,105 @@ #include "PropertyMapper.hxx" #include "ChartModelHelper.hxx" #include "ChartTypeHelper.hxx" +#include "ScaleAutomatism.hxx" +#include "MinimumAndMaximumSupplier.hxx" +#include "ObjectIdentifier.hxx" +#include "DiagramHelper.hxx" +#include "RelativePositionHelper.hxx" +#include "servicenames.hxx" +#include "AxisHelper.hxx" +#include "AxisIndexDefines.hxx" +#include "ControllerLockGuard.hxx" +#include "BaseGFXHelper.hxx" +#include "DataSeriesHelper.hxx" + +#include +#include + +#ifndef _UTL_STREAM_WRAPPER_HXX_ +#include +#endif +// header for class LocaleDataWrapper +#ifndef _UNOTOOLS_LOCALEDATAWRAPPER_HXX +#include +#endif +// header for class SdrPage +#ifndef _SVDPAGE_HXX +#include +#endif +// header for class SvxDrawPage +#ifndef _SVX_UNOWPAGE_HXX +#include +#endif +// header for class SvxShape +#ifndef _SVX_UNOSHAPE_HXX +#include +#endif +// header for class Application +#ifndef _SV_SVAPP_HXX +#include +#endif +#ifndef _VOS_MUTEX_HXX_ +#include +#endif + +#include #ifndef _COM_SUN_STAR_CHART2_EXPLICITSUBINCREMENT_HPP_ #include #endif -#ifndef _COM_SUN_STAR_CHART2_XAXISCONTAINER_HPP_ -#include +#ifndef _COM_SUN_STAR_CHART2_STACKINGDIRECTION_HPP_ +#include #endif #ifndef _COM_SUN_STAR_CHART2_XCHARTDOCUMENT_HPP_ #include #endif -#ifndef _COM_SUN_STAR_CHART2_XCHARTTYPEGROUP_HPP_ -#include +#ifndef _COM_SUN_STAR_CHART2_XCOORDINATESYSTEMCONTAINER_HPP_ +#include #endif -#ifndef _COM_SUN_STAR_CHART2_XDATASERIES_HPP_ -#include +#ifndef _COM_SUN_STAR_CHART2_XCHARTTYPECONTAINER_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_CHART2_XDATASERIESCONTAINER_HPP_ +#include #endif #ifndef _COM_SUN_STAR_CHART2_XDIAGRAM_HPP_ #include #endif -#ifndef _COM_SUN_STAR_CHART2_XGRIDCONTAINER_HPP_ -#include -#endif -#ifndef _COM_SUN_STAR_CHART2_XSTACKABLESCALEGROUP_HPP_ -#include -#endif #ifndef _COM_SUN_STAR_CHART2_XTITLED_HPP_ #include #endif -#ifndef _COM_SUN_STAR_LAYOUT_RELATIVEPOSITION_HPP_ -#include +#ifndef _COM_SUN_STAR_CHART2_RELATIVEPOSITION_HPP_ +#include #endif -#ifndef _COM_SUN_STAR_LAYOUT_RELATIVESIZE_HPP_ -#include +#ifndef _COM_SUN_STAR_CHART2_RELATIVESIZE_HPP_ +#include #endif +#ifndef _COM_SUN_STAR_DRAWING_FILLSTYLE_HPP_ +#include +#endif #ifndef _COM_SUN_STAR_DRAWING_LINESTYLE_HPP_ #include #endif - -#ifndef _BGFX_MATRIX_B3DHOMMATRIX_HXX -#include +#ifndef _COM_SUN_STAR_DRAWING_XSHAPEGROUP_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_DOCUMENT_XEXPORTER_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_DOCUMENT_XFILTER_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_UTIL_XREFRESHABLE_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_UTIL_NUMBERFORMAT_HPP_ +#include #endif //............................................................................. @@ -101,46 +161,99 @@ namespace chart using namespace ::com::sun::star; using namespace ::com::sun::star::chart2; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Any; +using rtl::OUString; -ChartView::~ChartView() +//static +const uno::Sequence& ExplicitValueProvider::getUnoTunnelId() { + static uno::Sequence * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; } //static -ChartView* ChartView::createView( - const uno::Reference< uno::XComponentContext >& xCC - , const uno::Reference< frame::XModel >& xChartModel - , const uno::Reference& xDrawPagesSuplier - , NumberFormatterWrapper* pNumberFormatterWrapper ) +ExplicitValueProvider* ExplicitValueProvider::getExplicitValueProvider( + const Reference< uno::XInterface >& xChartView ) { - return new ChartViewImpl(xCC,xChartModel,xDrawPagesSuplier,pNumberFormatterWrapper); + ExplicitValueProvider* pExplicitValueProvider=0; + + Reference< lang::XUnoTunnel > xTunnel( xChartView, uno::UNO_QUERY ); + if( xTunnel.is() ) + { + pExplicitValueProvider = reinterpret_cast(xTunnel->getSomething( + ExplicitValueProvider::getUnoTunnelId() )); + } + return pExplicitValueProvider; } -ChartViewImpl::ChartViewImpl( - const uno::Reference< uno::XComponentContext >& xCC - , const uno::Reference< frame::XModel >& xChartModel - , const uno::Reference& xDrawPagesSuplier - , NumberFormatterWrapper* pNumberFormatterWrapper ) - : m_xCC(xCC) - , m_xChartModel(xChartModel) - , m_xShapeFactory(NULL) - , m_xDrawPage(NULL) - , m_xDrawPages(NULL) - , m_pNumberFormatterWrapper( pNumberFormatterWrapper ) +ChartView::ChartView( + uno::Reference const & xContext) + : m_aMutex() + , m_xCC(xContext) + , m_xChartModel() + , m_xShapeFactory() + , m_xDrawPage() + , m_pDrawModelWrapper() + , m_aListenerContainer( m_aMutex ) + , m_bViewDirty(true) + , m_bInViewUpdate(false) + , m_bViewUpdatePending(false) + , m_bRefreshAddIn(true) + , m_aPageResolution(1000,1000) { - //get factory from draw model - m_xShapeFactory = uno::Reference( xDrawPagesSuplier, uno::UNO_QUERY ); - - //create draw page: - m_xDrawPages = xDrawPagesSuplier->getDrawPages (); - m_xDrawPage = m_xDrawPages->insertNewByIndex ( 0 ); } -ChartViewImpl::~ChartViewImpl() +void ChartView::impl_setChartModel( const uno::Reference< frame::XModel >& xChartModel ) +{ + if( m_xChartModel != xChartModel ) + { + m_xChartModel = xChartModel; + m_bViewDirty = true; + } +} + +void SAL_CALL ChartView::initialize( const uno::Sequence< uno::Any >& aArguments ) + throw ( uno::Exception, uno::RuntimeException) +{ + DBG_ASSERT(aArguments.getLength() >= 1,"need 1 argument to initialize the view: xModel"); + if( !(aArguments.getLength() >= 1) ) + return; + + uno::Reference< frame::XModel > xNewChartModel; + if( !(aArguments[0] >>= xNewChartModel) ) + { + DBG_ERROR( "need a Reference to frame::XModel as first parameter for view initialization" ); + } + impl_setChartModel( xNewChartModel ); + + if( !m_pDrawModelWrapper.get() ) + { + m_pDrawModelWrapper = ::boost::shared_ptr< DrawModelWrapper >( new DrawModelWrapper( m_xCC ) ); + m_xShapeFactory = m_pDrawModelWrapper->getShapeFactory(); + m_xDrawPage = m_pDrawModelWrapper->getMainDrawPage(); + } +} + +ChartView::~ChartView() { - m_xDrawPages->remove( m_xDrawPage ); m_xDrawPage = NULL; + impl_deleteCoordinateSystems(); +} +void ChartView::impl_deleteCoordinateSystems() +{ //delete all coordinate systems ::std::vector< VCoordinateSystem* >::const_iterator aIter = m_aVCooSysList.begin(); const ::std::vector< VCoordinateSystem* >::const_iterator aEnd = m_aVCooSysList.end(); @@ -151,331 +264,1312 @@ ChartViewImpl::~ChartViewImpl() m_aVCooSysList.clear(); } + +//----------------------------------------------------------------- +// datatransfer::XTransferable +namespace +{ +const rtl::OUString lcl_aGDIMetaFileMIMEType( + RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"")); +const rtl::OUString lcl_aGDIMetaFileMIMETypeHighContrast( + RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"")); +} // anonymous namespace + +void ChartView::getMetaFile( const uno::Reference< io::XOutputStream >& xOutStream + , bool bUseHighContrast ) +{ + if( !m_xDrawPage.is() ) + return; + + uno::Reference< lang::XMultiServiceFactory > xFactory( m_xCC->getServiceManager(), uno::UNO_QUERY ); + if( !xFactory.is() ) + return; + + // creating the graphic exporter + uno::Reference< document::XExporter > xExporter( xFactory->createInstance( + C2U("com.sun.star.drawing.GraphicExportFilter")), uno::UNO_QUERY); + uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY ); + + if( !xExporter.is() || !xFilter.is() ) + return; + + uno::Sequence< beans::PropertyValue > aProps(3); + aProps[0].Name = C2U("FilterName"); + aProps[0].Value <<= C2U("SVM"); + + aProps[1].Name = C2U("OutputStream"); + aProps[1].Value <<= xOutStream; + + uno::Sequence< beans::PropertyValue > aFilterData(4); + aFilterData[0].Name = C2U("ExportOnlyBackground"); + aFilterData[0].Value <<= sal_False; + aFilterData[1].Name = C2U("HighContrast"); + aFilterData[1].Value <<= bUseHighContrast; + + aFilterData[2].Name = C2U("Version"); + const sal_Int32 nVersion = SOFFICE_FILEFORMAT_50; + aFilterData[2].Value <<= nVersion; + + aFilterData[3].Name = C2U("CurrentPage"); + aFilterData[3].Value <<= uno::Reference< uno::XInterface >( m_xDrawPage, uno::UNO_QUERY ); + + aProps[2].Name = C2U("FilterData"); + aProps[2].Value <<= aFilterData; + + xExporter->setSourceDocument( uno::Reference< lang::XComponent >( m_xDrawPage, uno::UNO_QUERY) ); + if( xFilter->filter( aProps ) ) + { + xOutStream->flush(); + xOutStream->closeOutput(); + uno::Reference< io::XSeekable > xSeekable( xOutStream, uno::UNO_QUERY ); + if( xSeekable.is() ) + xSeekable->seek(0); + } +} + +uno::Any SAL_CALL ChartView::getTransferData( const datatransfer::DataFlavor& aFlavor ) + throw (datatransfer::UnsupportedFlavorException, io::IOException, uno::RuntimeException) +{ + bool bHighContrastMetaFile( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast)); + uno::Any aRet; + if( ! (bHighContrastMetaFile || aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType)) ) + return aRet; + + impl_updateView(); + + SvMemoryStream aStream( 1024, 1024 ); + utl::OStreamWrapper* pStreamWrapper = new utl::OStreamWrapper( aStream ); + + uno::Reference< io::XOutputStream > xOutStream( pStreamWrapper ); + uno::Reference< io::XInputStream > xInStream( pStreamWrapper ); + uno::Reference< io::XSeekable > xSeekable( pStreamWrapper ); + + if( xOutStream.is() ) + { + this->getMetaFile( xOutStream, bHighContrastMetaFile ); + + if( xInStream.is() && xSeekable.is() ) + { + xSeekable->seek(0); + sal_Int32 nBytesToRead = xInStream->available(); + uno::Sequence< sal_Int8 > aSeq( nBytesToRead ); + xInStream->readBytes( aSeq, nBytesToRead); + aRet <<= aSeq; + xInStream->closeInput(); + } + } + + return aRet; +} +uno::Sequence< datatransfer::DataFlavor > SAL_CALL ChartView::getTransferDataFlavors() + throw (uno::RuntimeException) +{ + uno::Sequence< datatransfer::DataFlavor > aRet(2); + + aRet[0] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMEType, + C2U( "GDIMetaFile" ), + ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); + aRet[1] = datatransfer::DataFlavor( lcl_aGDIMetaFileMIMETypeHighContrast, + C2U( "GDIMetaFile" ), + ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); + + return aRet; +} +::sal_Bool SAL_CALL ChartView::isDataFlavorSupported( const datatransfer::DataFlavor& aFlavor ) + throw (uno::RuntimeException) +{ + return ( aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMEType) || + aFlavor.MimeType.equals(lcl_aGDIMetaFileMIMETypeHighContrast) ); +} + +//----------------------------------------------------------------- +// ____ XUnoTunnel ___ +::sal_Int64 SAL_CALL ChartView::getSomething( const uno::Sequence< ::sal_Int8 >& aIdentifier ) + throw( uno::RuntimeException) +{ + if( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( ExplicitValueProvider::getUnoTunnelId().getConstArray(), + aIdentifier.getConstArray(), 16 ) ) + { + ExplicitValueProvider* pProvider = this; + return (sal_Int64)pProvider; + } + return 0; +} + +//----------------------------------------------------------------- +// lang::XServiceInfo + +APPHELPER_XSERVICEINFO_IMPL(ChartView,CHART_VIEW_SERVICE_IMPLEMENTATION_NAME) + + uno::Sequence< rtl::OUString > ChartView +::getSupportedServiceNames_Static() +{ + uno::Sequence< rtl::OUString > aSNS( 1 ); + aSNS.getArray()[ 0 ] = CHART_VIEW_SERVICE_NAME; + return aSNS; +} + +//----------------------------------------------------------------- +//----------------------------------------------------------------- + ::basegfx::B3DHomMatrix createTransformationSceneToScreen( - const awt::Point& rPos, const awt::Size& rSize ) + const ::basegfx::B2IRectangle& rDiagramRectangleWithoutAxes ) { - ::basegfx::B3DHomMatrix aM4; - aM4.scale(double(rSize.Width)/FIXED_SIZE_FOR_3D_CHART_VOLUME - , -double(rSize.Height)/FIXED_SIZE_FOR_3D_CHART_VOLUME, 1.0 ); - aM4.translate(double(rPos.X), double(rPos.Y+rSize.Height-1), 0); - return aM4; + ::basegfx::B3DHomMatrix aM; + aM.scale(double(rDiagramRectangleWithoutAxes.getWidth())/FIXED_SIZE_FOR_3D_CHART_VOLUME + , -double(rDiagramRectangleWithoutAxes.getHeight())/FIXED_SIZE_FOR_3D_CHART_VOLUME, 1.0 ); + aM.translate(double(rDiagramRectangleWithoutAxes.getMinX()) + , double(rDiagramRectangleWithoutAxes.getMinY()+rDiagramRectangleWithoutAxes.getHeight()-1), 0); + return aM; } -uno::Reference< drawing::XShapes > createDiagram( - const uno::Reference< drawing::XShapes>& xPageShapes - , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory - , const awt::Point& rPos, const awt::Size& rSize - , sal_Int32 nDimension - , const uno::Reference< XDiagram > & xDia - ) -{ - VDiagram aVDiagram(xDia, nDimension); - aVDiagram.init(xPageShapes,xPageShapes,xShapeFactory); - aVDiagram.createShapes(rPos,rSize); - uno::Reference< drawing::XShapes > xTarget = aVDiagram.getCoordinateRegion(); - return xTarget; -} - -void getCoordinateOrigin( double* fCoordinateOrigin, const uno::Reference< XBoundedCoordinateSystem >& xCoordSys ) -{ - if(xCoordSys.is()) - try - { - uno::Sequence< uno::Any > aCoord( xCoordSys->getOrigin()); - if( aCoord.getLength() >= 1 ) - aCoord[0]>>=fCoordinateOrigin[0]; - if( aCoord.getLength() >= 2 ) - aCoord[1]>>=fCoordinateOrigin[1]; - if( aCoord.getLength() >= 3 ) - aCoord[2]>>=fCoordinateOrigin[2]; - } - catch( uno::Exception& ex) - { - ASSERT_EXCEPTION( ex ); - } -} - -sal_Int32 getDimension( const uno::Reference< XDiagram >& xDiagram ) -{ - return ChartTypeHelper::getDimensionCount( - ChartModelHelper::getFirstChartType( xDiagram ) ); -} - -// void getCoordinateSystems( std::vector< VCoordinateSystem >& rVCooSysList, const uno::Reference< XDiagram >& xDiagram ) -// { -// uno::Reference< XBoundedCoordinateSystemContainer > xCooSysContainer = -// uno::Reference< XBoundedCoordinateSystemContainer >::query( xDiagram ); -// if(xCooSysContainer.is()) -// { -// uno::Sequence< uno::Reference< XBoundedCoordinateSystem > > aXCooSysList = xCooSysContainer->getCoordinateSystems(); -// for( sal_Int32 nC=0; nC < aXCooSysList.getLength(); nC++) -// { -// VCoordinateSystem aCooSys(aXCooSysList[nC]); - -// double fCoordinateOrigin[3] = { 0.0, 0.0, 0.0 }; -// getCoordinateOrigin( fCoordinateOrigin, aXCooSysList ); -// aCooSys.setOrigin(fCoordinateOrigin); - -// rVCooSysList.push_back( aCooSys ); -// } -// if(!aXCooSysList.getLength()) -// { -// //get coosys from diagram tree -// //... -// } -// } -// } - -const VCoordinateSystem* findInCooSysList( const std::vector< VCoordinateSystem* >& rVCooSysList - , const uno::Reference< XBoundedCoordinateSystem >& xCooSys ) +VCoordinateSystem* findInCooSysList( const std::vector< VCoordinateSystem* >& rVCooSysList + , const uno::Reference< XCoordinateSystem >& xCooSys ) { for( size_t nC=0; nC < rVCooSysList.size(); nC++) { - const VCoordinateSystem* pVCooSys = rVCooSysList[nC]; + VCoordinateSystem* pVCooSys = rVCooSysList[nC]; if(pVCooSys->getModel()==xCooSys) return pVCooSys; } return NULL; } -void addCooSysToList( std::vector< VCoordinateSystem* >& rVCooSysList - , const uno::Reference< XBoundedCoordinateSystem >& xCooSys - , double fCoordinateOrigin [] ) +VCoordinateSystem* addCooSysToList( std::vector< VCoordinateSystem* >& rVCooSysList + , const uno::Reference< XCoordinateSystem >& xCooSys + , const uno::Reference< frame::XModel >& xChartModel ) { - if( !findInCooSysList( rVCooSysList, xCooSys ) ) + VCoordinateSystem* pVCooSys = findInCooSysList( rVCooSysList, xCooSys ); + if( !pVCooSys ) { - VCoordinateSystem* pVCooSys( VCoordinateSystem::createCoordinateSystem(xCooSys ) ); + pVCooSys = VCoordinateSystem::createCoordinateSystem(xCooSys ); if(pVCooSys) { - pVCooSys->setOrigin(fCoordinateOrigin); + rtl::OUString aCooSysParticle( ObjectIdentifier::createParticleForCoordinateSystem( xCooSys, xChartModel ) ); + pVCooSys->setParticle(aCooSysParticle); + rVCooSysList.push_back( pVCooSys ); } } + return pVCooSys; } -void getAxesAndAddToCooSys( uno::Sequence< uno::Reference< XAxis > >& rAxisList - , const uno::Reference< XDiagram >& xDiagram - , std::vector< VCoordinateSystem* >& rVCooSysList ) +VCoordinateSystem* lcl_getCooSysForPlotter( const std::vector< VCoordinateSystem* >& rVCooSysList, MinimumAndMaximumSupplier* pMinimumAndMaximumSupplier ) { - uno::Reference< XAxisContainer > xAxisContainer( xDiagram, uno::UNO_QUERY ); - if( xAxisContainer.is()) + if(!pMinimumAndMaximumSupplier) + return 0; + for( size_t nC=0; nC < rVCooSysList.size(); nC++) { - rAxisList = xAxisContainer->getAxes(); - for( sal_Int32 nA = 0; nA < rAxisList.getLength(); nA++ ) - { - uno::Reference< XAxis > xAxis( rAxisList[nA] ); - for( size_t nC=0; nC < rVCooSysList.size(); nC++) - { - if(xAxis->getCoordinateSystem() == rVCooSysList[nC]->getModel() ) - { - rVCooSysList[nC]->addAxis( xAxis ); - } - } - } + VCoordinateSystem* pVCooSys = rVCooSysList[nC]; + if(pVCooSys->hasMinimumAndMaximumSupplier( pMinimumAndMaximumSupplier )) + return pVCooSys; } + return 0; } -void addGridsToCooSys( const uno::Reference< XDiagram >& xDiagram - , std::vector< VCoordinateSystem* >& rVCooSysList ) +typedef std::pair< sal_Int32, sal_Int32 > tFullAxisIndex; //first index is the dimension, second index is the axis index that indicates wether this is a main or secondary axis +typedef std::pair< VCoordinateSystem* , tFullAxisIndex > tFullCoordinateSystem; +typedef std::map< VCoordinateSystem*, tFullAxisIndex > tCoordinateSystemMap; + +struct AxisUsage +{ + AxisUsage(); + ~AxisUsage(); + + void addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); + ::std::vector< VCoordinateSystem* > getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ); + sal_Int32 getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex ); + //tFullAxisIndex getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys ); + + ScaleAutomatism aScaleAutomatism; + +private: + tCoordinateSystemMap aCoordinateSystems; + std::map< sal_Int32, sal_Int32 > aMaxIndexPerDimension; +}; + +AxisUsage::AxisUsage() + : aScaleAutomatism(AxisHelper::createDefaultScale()) { - uno::Reference< XGridContainer > xGridContainer( xDiagram, uno::UNO_QUERY ); - if( xGridContainer.is()) - { - uno::Sequence< uno::Reference< XGrid > > aGridList( - xGridContainer->getGrids() ); - for( sal_Int32 nA = 0; nA < aGridList.getLength(); nA++ ) - { - uno::Reference< XGrid > xGrid( aGridList[nA] ); - for( size_t nC=0; nC < rVCooSysList.size(); nC++) - { - if(xGrid->getCoordinateSystem() == rVCooSysList[nC]->getModel() ) - { - rVCooSysList[nC]->addGrid( xGrid ); - } - } - } - } } -void addSeriesToPlotter( const uno::Sequence< uno::Reference< XDataSeriesTreeNode > >& rSeriesList - , VSeriesPlotter* pPlotter - , StackMode eYStackMode ) +AxisUsage::~AxisUsage() { - if(!pPlotter) + aCoordinateSystems.clear(); +} + +/* +tFullScaleIndex AxisUsage::getDimensionAndIndexForCooSys( VCoordinateSystem* pCooSys ) +{ + tFullScaleIndex aRet(0,0); + + tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) ); + if(aFound!=aCoordinateSystems.end()) + aRet = aFound->second; + + return aRet; +} +*/ + +void AxisUsage::addCoordinateSystem( VCoordinateSystem* pCooSys, sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) +{ + if(!pCooSys) return; - for( sal_Int32 nS = 0; nS < rSeriesList.getLength(); ++nS ) + + tFullAxisIndex aFullAxisIndex( nDimensionIndex, nAxisIndex ); + tCoordinateSystemMap::const_iterator aFound( aCoordinateSystems.find(pCooSys) ); + + //use one scale only once for each coordinate system + //main axis are preferred over secondary axis + //value scales are preferred + if(aFound!=aCoordinateSystems.end()) { - uno::Reference< XDataSeries > xDataSeries( rSeriesList[nS], uno::UNO_QUERY ); - if(!xDataSeries.is()) - continue; - VDataSeries* pTestSeries = new VDataSeries( xDataSeries ); - //virtual void addSeries( VDataSeries* pSeries, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 ); - sal_Int32 nXSlot2 = 0; - if(eYStackMode==StackMode_NONE) - nXSlot2=-1; - //@todo - pPlotter->addSeries( pTestSeries, nXSlot2 ); - // pPlotter->addSeries( pTestSeries, nXSlot2, nYSlot ); - /* - if(nN==nSeriesCount-1) - pPlotter->addSeries( pTestSeries, -1 ); - else - pPlotter->addSeries( pTestSeries, 0 ); - */ + sal_Int32 nFoundAxisIndex = aFound->second.second; + if( nFoundAxisIndex < nAxisIndex ) + return; + sal_Int32 nFoundDimension = aFound->second.first; + if( nFoundDimension ==1 ) + return; + if( nFoundDimension < nDimensionIndex ) + return; } + aCoordinateSystems[pCooSys] = aFullAxisIndex; + + //set maximum scale index + std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex); + if( aIter != aMaxIndexPerDimension.end() ) + { + sal_Int32 nCurrentMaxIndex = aIter->second; + if( nCurrentMaxIndex < nAxisIndex ) + aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex; + } + else + aMaxIndexPerDimension[nDimensionIndex]=nAxisIndex; } -void initializeDiagramAndGetCooSys( std::vector< VCoordinateSystem* >& rVCooSysList - , const uno::Reference< uno::XComponentContext>& xCC - , const uno::Reference< drawing::XShapes>& xPageShapes - , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory - , NumberFormatterWrapper* pNumberFormatterWrapper - , const awt::Point& rPos, const awt::Size& rSize - , const uno::Reference< frame::XModel >& xChartModel ) +::std::vector< VCoordinateSystem* > AxisUsage::getCoordinateSystems( sal_Int32 nDimensionIndex, sal_Int32 nAxisIndex ) +{ + ::std::vector< VCoordinateSystem* > aRet; + + tCoordinateSystemMap::const_iterator aIter; + for( aIter = aCoordinateSystems.begin(); aIter!=aCoordinateSystems.end();++aIter ) + { + if( aIter->second.first != nDimensionIndex ) + continue; + if( aIter->second.second != nAxisIndex ) + continue; + aRet.push_back( aIter->first ); + } + + return aRet; +} +sal_Int32 AxisUsage::getMaxAxisIndexForDimension( sal_Int32 nDimensionIndex ) +{ + sal_Int32 nRet = -1; + std::map< sal_Int32, sal_Int32 >::const_iterator aIter = aMaxIndexPerDimension.find(nDimensionIndex); + if( aIter != aMaxIndexPerDimension.end() ) + nRet = aIter->second; + return nRet; +} + +//----------------------------------------------------- + +class SeriesPlotterContainer +{ +public: + SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList ); + ~SeriesPlotterContainer(); + + void initializeCooSysAndSeriesPlotter( const uno::Reference< frame::XModel >& xChartModel ); + void initAxisUsageList(); + void doAutoScaling(); + void updateScalesAndIncrementsOnAxes(); + void setScalesFromCooSysToPlotter(); + void setNumberFormatsFromAxes(); + drawing::Direction3D getPreferredAspectRatio(); + bool shouldKeep2DAspectRatio(); + + std::vector< VSeriesPlotter* >& getSeriesPlotterList() { return m_aSeriesPlotterList; } + std::vector< VCoordinateSystem* >& getCooSysList() { return m_rVCooSysList; } + std::vector< LegendEntryProvider* > getLegendEntryProviderList(); + +private: + std::vector< VSeriesPlotter* > m_aSeriesPlotterList; + std::vector< VCoordinateSystem* >& m_rVCooSysList; + ::std::map< uno::Reference< XAxis >, AxisUsage > m_aAxisUsageList; + sal_Int32 m_nMaxAxisIndex; +}; + +SeriesPlotterContainer::SeriesPlotterContainer( std::vector< VCoordinateSystem* >& rVCooSysList ) + : m_rVCooSysList( rVCooSysList ) + , m_nMaxAxisIndex(0) +{ +} + +SeriesPlotterContainer::~SeriesPlotterContainer() +{ + // - remove plotter from coordinatesystems + for( sal_Int32 nC=0; nC < m_rVCooSysList.size(); nC++) + m_rVCooSysList[nC]->clearMinimumAndMaximumSupplierList(); + // - delete all plotter + ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin(); + const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end(); + for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ ) + delete *aPlotterIter; + m_aSeriesPlotterList.clear(); +} + +std::vector< LegendEntryProvider* > SeriesPlotterContainer::getLegendEntryProviderList() +{ + std::vector< LegendEntryProvider* > aRet( m_aSeriesPlotterList.size() ); + ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin(); + const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end(); + sal_Int32 nN = 0; + for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; ++aPlotterIter, nN++ ) + aRet[nN] = *aPlotterIter; + return aRet; +} + +void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter( + const uno::Reference< frame::XModel >& xChartModel ) { //------------ get model series from model + sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( xChartModel ) ); if( !xDiagram.is()) return; - sal_Int32 nDimension = getDimension( xDiagram ); + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY ); - //------------ create Diagram shapes - uno::Reference< drawing::XShapes > xTarget = createDiagram( xPageShapes, xShapeFactory, rPos, rSize, nDimension, xDiagram ); - - //------------ get all coordinatesystems -// getCoordinateSystems( rVCooSysList, xDiagram ); - - //------------ add series to plotter and thus prepare him for providing minimum and maximum values - uno::Reference< XDataSeriesTreeParent > xTree = xDiagram->getTree(); - uno::Sequence< uno::Reference< XDataSeriesTreeNode > > aChartTypes( xTree->getChildren() ); - for( sal_Int32 i = 0; i < aChartTypes.getLength(); ++i ) + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + if(!nDimensionCount) { - //iterate through different charttypes: + //@todo handle mixed dimension + nDimensionCount = 2; + } - uno::Reference< XChartTypeGroup > xChartTypeGroup( aChartTypes[i], uno::UNO_QUERY ); - DBG_ASSERT(xChartTypeGroup.is(),"First node at the diagram tree needs to be a ChartTypeGroup"); - if( !xChartTypeGroup.is() ) + sal_Bool bSortByXValues = sal_False; + sal_Bool bConnectBars = sal_False; + try + { + uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW ); + xDiaProp->getPropertyValue( C2U( "SortByXValues" ) ) >>= bSortByXValues; + xDiaProp->getPropertyValue( C2U( "ConnectBars" ) ) >>= bConnectBars; + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + //--------------------------------------------------------------------- + //prepare for autoscaling and shape creation + // - create plotter for charttypes (for each first scale group at each plotter, as they are independent) + // - add series to plotter (thus each charttype can provide minimum and maximum values for autoscaling) + // - add plotter to coordinate systems + + //iterate through all coordinate systems + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + OSL_ASSERT( xCooSysContainer.is()); + if( !xCooSysContainer.is()) + return; + uno::Reference< XColorScheme > xColorScheme( xDiagram->getDefaultColorScheme()); + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) + { + uno::Reference< XCoordinateSystem > xCooSys( aCooSysList[nCS] ); + VCoordinateSystem* pVCooSys = addCooSysToList(m_rVCooSysList,xCooSys,xChartModel); + + //iterate through all chart types in the current coordinate system + uno::Reference< XChartTypeContainer > xChartTypeContainer( xCooSys, uno::UNO_QUERY ); + OSL_ASSERT( xChartTypeContainer.is()); + if( !xChartTypeContainer.is() ) continue; - ::std::auto_ptr< VSeriesPlotter > apPlotter( VSeriesPlotter::createSeriesPlotter( xChartTypeGroup->getChartType() ) ); - - //------------ add series to plotter and thus prepare him for providing minimum and maximum values - - sal_Int32 nXSlot = -1; - sal_Int32 nYSlot = -1; - uno::Sequence< uno::Reference< XDataSeriesTreeNode > > aXSlots( xChartTypeGroup->getChildren() ); - for( sal_Int32 nX = 0; nX < aXSlots.getLength(); ++nX ) + uno::Sequence< uno::Reference< XChartType > > aChartTypeList( xChartTypeContainer->getChartTypes() ); + for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) { - uno::Reference< XDataSeriesTreeParent > xXSlot( aXSlots[nX], uno::UNO_QUERY ); - DBG_ASSERT( xXSlot.is(), "a node for the first dimension of a chart tree should always be a parent" ); - if(!xXSlot.is()) + uno::Reference< XChartType > xChartType( aChartTypeList[nT] ); + + VSeriesPlotter* pPlotter = VSeriesPlotter::createSeriesPlotter( xChartType, nDimensionCount ); + if( !pPlotter ) continue; - uno::Reference< XStackableScaleGroup > xStackGroup( xXSlot, uno::UNO_QUERY ); - if( xStackGroup.is() && xStackGroup->getStackMode()==StackMode_STACKED) - nXSlot++; - uno::Sequence< uno::Reference< XDataSeriesTreeNode > > aYSlots( xXSlot->getChildren() ); - for( sal_Int32 nY = 0; nY < aYSlots.getLength(); ++nY ) + m_aSeriesPlotterList.push_back( pPlotter ); + pPlotter->setNumberFormatsSupplier( xNumberFormatsSupplier ); + pPlotter->setColorScheme( xColorScheme ); + pPlotter->setExplicitCategoriesProvider( pVCooSys->getExplicitCategoriesProvider() ); + + if(pVCooSys) + pVCooSys->addMinimumAndMaximumSupplier(pPlotter); + + //------------ add series to plotter and thus prepare him for providing minimum and maximum values + uno::Reference< XDataSeriesContainer > xDataSeriesContainer( xChartType, uno::UNO_QUERY ); + OSL_ASSERT( xDataSeriesContainer.is()); + if( !xDataSeriesContainer.is() ) + continue; + sal_Int32 zSlot=-1; + sal_Int32 xSlot=-1; + sal_Int32 ySlot=-1; + uno::Sequence< uno::Reference< XDataSeries > > aSeriesList( xDataSeriesContainer->getDataSeries() ); + for( sal_Int32 nS = 0; nS < aSeriesList.getLength(); ++nS ) { - uno::Reference< XDataSeriesTreeParent > xYSlot( aYSlots[nY], uno::UNO_QUERY ); - DBG_ASSERT( xYSlot.is(), "a node for the second dimension of a chart tree should always be a parent" ); - if(!xYSlot.is()) + uno::Reference< XDataSeries > xDataSeries( aSeriesList[nS], uno::UNO_QUERY ); + if(!xDataSeries.is()) continue; - xStackGroup.set( uno::Reference< XStackableScaleGroup >::query( xYSlot )); - StackMode aYStackMode = StackMode_NONE; - if(xStackGroup.is()) - aYStackMode = xStackGroup->getStackMode(); - if(aYStackMode==StackMode_STACKED) - nYSlot++; - if( 2 == nDimension ) + VDataSeries* pSeries = new VDataSeries( xDataSeries ); + + if( bSortByXValues ) + pSeries->doSortByXValues(); + + pSeries->setConnectBars( bConnectBars ); + + rtl::OUString aSeriesParticle( ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCS, nT, nS ) ); + pSeries->setParticle(aSeriesParticle); + + //ignore secondary axis for charttypes that do not suppoert them + if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX && + !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, 1 ) ) { - uno::Reference< XScaleGroup > xScaleGroup( xYSlot, uno::UNO_QUERY ); - { - double fCoordinateOrigin[3] = { 0.0, 0.0, 0.0 }; - getCoordinateOrigin( fCoordinateOrigin, xScaleGroup->getCoordinateSystem() ); - addCooSysToList(rVCooSysList,xScaleGroup->getCoordinateSystem(),fCoordinateOrigin); - } - addSeriesToPlotter( xYSlot->getChildren(), apPlotter.get(), aYStackMode ); - } - else + pSeries->setAttachedAxisIndex(MAIN_AXIS_INDEX); + } + + StackingDirection eDirection = pSeries->getStackingDirection(); + switch(eDirection) { - uno::Sequence< uno::Reference< XDataSeriesTreeNode > > aZSlots( xYSlot->getChildren() ); - for( sal_Int32 nZ = 0; nZ < aZSlots.getLength(); ++nZ ) - { - uno::Reference< XScaleGroup > xScaleGroup( aZSlots[nZ], uno::UNO_QUERY ); - if(xScaleGroup.is()) - { - double fCoordinateOrigin[3] = { 0.0, 0.0, 0.0 }; - getCoordinateOrigin( fCoordinateOrigin, xScaleGroup->getCoordinateSystem() ); - addCooSysToList(rVCooSysList,xScaleGroup->getCoordinateSystem(),fCoordinateOrigin); - } - uno::Reference< XDataSeriesTreeParent > xZSlot( aZSlots[nZ], uno::UNO_QUERY ); - DBG_ASSERT( xZSlot.is(), "a node for the third dimension of a 3 dimensional chart tree should always be a parent" ); - if(!xZSlot.is()) - continue; - addSeriesToPlotter( xZSlot->getChildren(), apPlotter.get(), aYStackMode ); - } + case StackingDirection_NO_STACKING: + xSlot++; ySlot=-1; + if(zSlot<0) + zSlot=0; + break; + case StackingDirection_Y_STACKING: + ySlot++; + if(xSlot<0) + xSlot=0; + if(zSlot<0) + zSlot=0; + break; + case StackingDirection_Z_STACKING: + zSlot++; xSlot=-1; ySlot=-1; + break; + } + pPlotter->addSeries( pSeries, zSlot, xSlot, ySlot ); + } + } + } + + //transport seriesnames to the coordinatesystems if needed + if( m_aSeriesPlotterList.size() ) + { + uno::Sequence< rtl::OUString > aSeriesNames; + bool bSeriesNamesInitialized = false; + for( size_t nC=0; nC < m_rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = m_rVCooSysList[nC]; + if(!pVCooSys) + continue; + if( pVCooSys->needSeriesNamesForAxis() ) + { + if(!bSeriesNamesInitialized) + { + VSeriesPlotter* pSeriesPlotter = m_aSeriesPlotterList[0]; + if( pSeriesPlotter ) + aSeriesNames = pSeriesPlotter->getSeriesNames(); + bSeriesNamesInitialized = true; + } + pVCooSys->setSeriesNamesForAxis( aSeriesNames ); + } + } + } +} + +void SeriesPlotterContainer::initAxisUsageList() +{ + m_aAxisUsageList.clear(); + size_t nC; + for( nC=0; nC < m_rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = m_rVCooSysList[nC]; + for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++) + { + uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel(); + if( nDimensionIndex >= xCooSys->getDimension() ) + continue; + const sal_Int32 nMaximumAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nDimensionIndex); + for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex) + { + uno::Reference< XAxis > xAxis( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ) ); + OSL_ASSERT( xAxis.is()); + if( xAxis.is()) + { + if(m_aAxisUsageList.find(xAxis)==m_aAxisUsageList.end()) + m_aAxisUsageList[xAxis].aScaleAutomatism = ScaleAutomatism(xAxis->getScaleData()); + AxisUsage& rAxisUsage = m_aAxisUsageList[xAxis]; + rAxisUsage.addCoordinateSystem(pVCooSys,nDimensionIndex,nAxisIndex); } } } + } - //------------ get all axes from model and add to VCoordinateSystems - uno::Sequence< uno::Reference< XAxis > > aAxisList; - getAxesAndAddToCooSys( aAxisList, xDiagram, rVCooSysList ); - addGridsToCooSys( xDiagram, rVCooSysList ); + ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin(); + const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end(); - //------------ iterate through all coordinate systems - for( size_t nC=0; nC < rVCooSysList.size(); nC++) + //init m_nMaxAxisIndex + m_nMaxAxisIndex = 0; + for(sal_Int32 nDimensionIndex=0; nDimensionIndex<3; nDimensionIndex++) + { + for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ ) { - //------------ create explicit scales and increments - VCoordinateSystem* pVCooSys = rVCooSysList[nC]; - pVCooSys->doAutoScale( apPlotter.get() ); - - ::basegfx::B3DHomMatrix aM4_SceneToScreen( createTransformationSceneToScreen(rPos,rSize) ); - drawing::HomogenMatrix aHM_SceneToScreen( Matrix4DToHomogenMatrix(aM4_SceneToScreen) ); - - pVCooSys->initPlottingTargets(xTarget,xPageShapes,xShapeFactory); - pVCooSys->setTransformationSceneToScreen(aHM_SceneToScreen); - - //------------ create axes and grids --- @todo do auto layout / fontscaling - pVCooSys->createAxesShapes( rSize, pNumberFormatterWrapper ); - pVCooSys->createGridShapes(); - - //------------ set scale to plotter / create series - if(apPlotter.get()) - { - apPlotter->init(xTarget,xPageShapes,xShapeFactory); - if(2==nDimension) - apPlotter->setTransformationSceneToScreen( aHM_SceneToScreen ); - apPlotter->setScales( pVCooSys->getExplicitScales() ); - apPlotter->createShapes(); - } + sal_Int32 nLocalMax = aAxisIter->second.getMaxAxisIndexForDimension( nDimensionIndex ); + if( m_nMaxAxisIndex < nLocalMax ) + m_nMaxAxisIndex = nLocalMax; } } } +void SeriesPlotterContainer::setScalesFromCooSysToPlotter() +{ + //set scales to plotter to enable them to provide the preferred scene AspectRatio + ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin(); + const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end(); + for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ ) + { + VSeriesPlotter* pSeriesPlotter = *aPlotterIter; + VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter ); + if(pVCooSys) + { + pSeriesPlotter->setScales( pVCooSys->getExplicitScales(0,0), pVCooSys->getPropertySwapXAndYAxis() ); + sal_Int32 nMaxAxisIndex = pVCooSys->getMaximumAxisIndexByDimension(1);//only additional value axis are relevant for series plotter + for( sal_Int32 nI=1; nI<=nMaxAxisIndex; nI++ ) + pSeriesPlotter->addSecondaryValueScale( pVCooSys->getExplicitScale(1,nI), nI ); + } + } +} + +void SeriesPlotterContainer::setNumberFormatsFromAxes() +{ + //set numberfarmats to plotter to enable them to display the data labels in the numberfromat of teh axis + + ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin(); + const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end(); + for( aPlotterIter = m_aSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ ) + { + VSeriesPlotter* pSeriesPlotter = *aPlotterIter; + VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( m_rVCooSysList, pSeriesPlotter ); + if(pVCooSys) + { + AxesNumberFormats aAxesNumberFormats; + uno::Reference< XCoordinateSystem > xCooSys = pVCooSys->getModel(); + sal_Int32 nDimensionCount = xCooSys->getDimension(); + for(sal_Int32 nDimensionIndex=0; nDimensionIndexgetMaximumAxisIndexByDimension(nDimensionIndex); + for(sal_Int32 nAxisIndex=0; nAxisIndex<=nMaximumAxisIndex; ++nAxisIndex) + { + try + { + Reference< beans::XPropertySet > xAxisProp( xCooSys->getAxisByDimension( nDimensionIndex, nAxisIndex ), uno::UNO_QUERY ); + if( xAxisProp.is()) + { + sal_Int32 nNumberFormatKey(0); + if( xAxisProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey ) + { + aAxesNumberFormats.setFormat( nNumberFormatKey, nDimensionIndex, nAxisIndex ); + } + } + } + catch( lang::IndexOutOfBoundsException& e ) + { + ASSERT_EXCEPTION( e ); + } + } + } + pSeriesPlotter->setAxesNumberFormats( aAxesNumberFormats ); + } + } +} + +void SeriesPlotterContainer::updateScalesAndIncrementsOnAxes() +{ + for( sal_Int32 nC=0; nC < m_rVCooSysList.size(); nC++) + m_rVCooSysList[nC]->updateScalesAndIncrementsOnAxes(); +} + +void SeriesPlotterContainer::doAutoScaling() +{ + //precondition: need a initialized m_aSeriesPlotterList + //precondition: need a initialized m_aAxisUsageList + + ::std::map< uno::Reference< XAxis >, AxisUsage >::iterator aAxisIter = m_aAxisUsageList.begin(); + const ::std::map< uno::Reference< XAxis >, AxisUsage >::const_iterator aAxisEndIter = m_aAxisUsageList.end(); + + //iterate over the main scales first than secondary axis + size_t nC; + for( sal_Int32 nAxisIndex=0; nAxisIndex<=m_nMaxAxisIndex; nAxisIndex++ ) + { + + // - first do autoscale for all x and z scales (because they are treated independent) + for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ ) + { + AxisUsage& rAxisUsage = (*aAxisIter).second; + ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex); + ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex); + + for( nC=0; nC < aVCooSysList_X.size(); nC++) + aVCooSysList_X[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,0,nAxisIndex); + for( nC=0; nC < aVCooSysList_Z.size(); nC++) + aVCooSysList_Z[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,2,nAxisIndex); + + ExplicitScaleData aExplicitScale; + ExplicitIncrementData aExplicitIncrement; + rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement ); + + for( nC=0; nC < aVCooSysList_X.size(); nC++) + aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement ); + for( nC=0; nC < aVCooSysList_Z.size(); nC++) + aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement ); + } + + // - second do autoscale for the dependent y scales (the coordinate systems are prepared with x and z scales already ) + for( aAxisIter = m_aAxisUsageList.begin(); aAxisIter != aAxisEndIter; aAxisIter++ ) + { + AxisUsage& rAxisUsage = (*aAxisIter).second; + ::std::vector< VCoordinateSystem* > aVCooSysList_X = rAxisUsage.getCoordinateSystems(0,nAxisIndex); + ::std::vector< VCoordinateSystem* > aVCooSysList_Y = rAxisUsage.getCoordinateSystems(1,nAxisIndex); + ::std::vector< VCoordinateSystem* > aVCooSysList_Z = rAxisUsage.getCoordinateSystems(2,nAxisIndex); + + if(!aVCooSysList_Y.size()) + continue; + + for( nC=0; nC < aVCooSysList_Y.size(); nC++) + aVCooSysList_Y[nC]->prepareScaleAutomatismForDimensionAndIndex(rAxisUsage.aScaleAutomatism,1,nAxisIndex); + + ExplicitScaleData aExplicitScale; + ExplicitIncrementData aExplicitIncrement; + rAxisUsage.aScaleAutomatism.calculateExplicitScaleAndIncrement( aExplicitScale, aExplicitIncrement ); + + for( nC=0; nC < aVCooSysList_X.size(); nC++) + aVCooSysList_X[nC]->setExplicitScaleAndIncrement( 0, nAxisIndex, aExplicitScale, aExplicitIncrement ); + for( nC=0; nC < aVCooSysList_Y.size(); nC++) + aVCooSysList_Y[nC]->setExplicitScaleAndIncrement( 1, nAxisIndex, aExplicitScale, aExplicitIncrement ); + for( nC=0; nC < aVCooSysList_Z.size(); nC++) + aVCooSysList_Z[nC]->setExplicitScaleAndIncrement( 2, nAxisIndex, aExplicitScale, aExplicitIncrement ); + } + } +} + +drawing::Direction3D SeriesPlotterContainer::getPreferredAspectRatio() +{ + drawing::Direction3D aPreferredAspectRatio(1.0,1.0,1.0); + + sal_Int32 nPlotterCount=0; + //get a list of all preferred aspect ratios and combine them + //first with special demands wins (less or equal zero <-> arbitrary) + double fx, fy, fz; + fx = fy = fz = -1.0; + ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin(); + const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end(); + for( aPlotterIter = m_aSeriesPlotterList.begin(), nPlotterCount=0 + ; aPlotterIter != aPlotterEnd; aPlotterIter++, nPlotterCount++ ) + { + drawing::Direction3D aSingleRatio( (*aPlotterIter)->getPreferredDiagramAspectRatio() ); + if( fx<0 && aSingleRatio.DirectionX>0 ) + fx = aSingleRatio.DirectionX; + + if( fy<0 && aSingleRatio.DirectionY>0 ) + { + if( fx>0 && aSingleRatio.DirectionX>0 ) + fy = fx*aSingleRatio.DirectionY/aSingleRatio.DirectionX; + else if( fz>0 && aSingleRatio.DirectionZ>0 ) + fy = fz*aSingleRatio.DirectionY/aSingleRatio.DirectionZ; + else + fy = aSingleRatio.DirectionY; + } + + if( fz<0 && aSingleRatio.DirectionZ>0 ) + { + if( fx>0 && aSingleRatio.DirectionX>0 ) + fz = fx*aSingleRatio.DirectionZ/aSingleRatio.DirectionX; + else if( fy>0 && aSingleRatio.DirectionY>0 ) + fz = fy*aSingleRatio.DirectionZ/aSingleRatio.DirectionY; + else + fz = aSingleRatio.DirectionZ; + } + + if( fx>0 && fy>0 && fz>0 ) + break; + } + aPreferredAspectRatio = drawing::Direction3D(fx, fy, fz); + return aPreferredAspectRatio; +} + +bool SeriesPlotterContainer::shouldKeep2DAspectRatio() +{ + bool bOutKeep2DAspectRatio = false; + + //detect wether the aspect ratio needs to be kept + ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = m_aSeriesPlotterList.begin(); + const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = m_aSeriesPlotterList.end(); + for( aPlotterIter = m_aSeriesPlotterList.begin() + ; aPlotterIter != aPlotterEnd; aPlotterIter++ ) + { + bOutKeep2DAspectRatio = bOutKeep2DAspectRatio || (*aPlotterIter)->keepAspectRatio(); + } + + return bOutKeep2DAspectRatio; +} + +//----------------------------------------------------- + +namespace +{ +bool lcl_resizeAfterCompleteCreation( const uno::Reference< XDiagram >& xDiagram ) +{ + //special treatment for pie charts + //the size is checked after complete creation to get the datalabels into the given space + + //todo: this is just a workaround at the moment for pie and donut labels + return DiagramHelper::isPieOrDonutChart( xDiagram ); +} + +} //end anonymous namespace + +//------------ create complete diagram shape (inclusive axis and series) +void ChartView::impl_createDiagramAndContent( SeriesPlotterContainer& rSeriesPlotterContainer + , const uno::Reference< drawing::XShapes>& xDiagramPlusAxes_Shapes + , const awt::Point& rAvailablePos + , const awt::Size& rAvailableSize + , const awt::Size& rPageSize ) +{ + sal_Int32 nDiagramIndex = 0;//todo if more than one diagam is supported + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) ); + if( !xDiagram.is()) + return; + + sal_Int32 nDimensionCount = DiagramHelper::getDimension( xDiagram ); + if(!nDimensionCount) + { + //@todo handle mixed dimension + nDimensionCount = 2; + } + + ::basegfx::B2IRectangle aAvailableOuterRect( BaseGFXHelper::makeRectangle(rAvailablePos,rAvailableSize) ); + + const std::vector< VCoordinateSystem* >& rVCooSysList( rSeriesPlotterContainer.getCooSysList() ); + const std::vector< VSeriesPlotter* >& rSeriesPlotterList( rSeriesPlotterContainer.getSeriesPlotterList() ); + + //create VAxis, so they can give necessary information for automatic scaling + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_xChartModel, uno::UNO_QUERY ); + sal_Int32 nC = 0; + for( nC=0; nC < rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = rVCooSysList[nC]; + pVCooSys->createVAxisList( xNumberFormatsSupplier + , rAvailableSize //font reference size + , BaseGFXHelper::B2IRectangleToAWTRectangle( aAvailableOuterRect ) //maximum space for labels + ); + } + + + // - prepare list of all axis and how they are used + rSeriesPlotterContainer.initAxisUsageList(); + rSeriesPlotterContainer.doAutoScaling(); + rSeriesPlotterContainer.setScalesFromCooSysToPlotter(); + rSeriesPlotterContainer.setNumberFormatsFromAxes(); + + //--------------------------------------------------------------------- + //create shapes + + //------------ create diagram shapes + //aspect ratio + drawing::Direction3D aPreferredAspectRatio( + rSeriesPlotterContainer.getPreferredAspectRatio() ); + bool bKeepAspectRatio = rSeriesPlotterContainer.shouldKeep2DAspectRatio(); + + uno::Reference< drawing::XShapes > xCoordinateRegionTarget(0); + VDiagram aVDiagram(xDiagram, aPreferredAspectRatio, nDimensionCount); + {//create diagram + aVDiagram.init(xDiagramPlusAxes_Shapes,xDiagramPlusAxes_Shapes,m_xShapeFactory); + aVDiagram.createShapes(rAvailablePos,rAvailableSize); + xCoordinateRegionTarget = aVDiagram.getCoordinateRegion(); + aVDiagram.reduceToMimimumSize(); + } + + uno::Reference< drawing::XShapes > xTextTargetShapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxes_Shapes) ); + + // - create axis and grids for all coordinate systems + + //init all coordinate systems + for( nC=0; nC < rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = rVCooSysList[nC]; + pVCooSys->initPlottingTargets(xCoordinateRegionTarget,xTextTargetShapes,m_xShapeFactory); + + pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) )); + + pVCooSys->initVAxisInList(); + } + + //calculate resulting size respecting axis label layout and fontscaling + + //use first coosys only so far; todo: calculate for more than one coosys if we have more in future + //todo: this is just a workaround at the moment for pie and donut labels + if( !lcl_resizeAfterCompleteCreation(xDiagram) && rVCooSysList.size() > 0 ) + { + uno::Reference< drawing::XShape > xBoundingShape( xDiagramPlusAxes_Shapes, uno::UNO_QUERY ); + + ::basegfx::B2IRectangle aFirstConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) ); + + VCoordinateSystem* pVCooSys = rVCooSysList[0]; + pVCooSys->createMaximumAxesLabels(); + + ::basegfx::B2IRectangle aConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) ); + ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.adjustInnerSize( aConsumedOuterRect ) ); + + pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen( aNewInnerRect ) )); + + //redo autoscaling to get size and text dependent automatic main increment count + rSeriesPlotterContainer.doAutoScaling(); + rSeriesPlotterContainer.updateScalesAndIncrementsOnAxes(); + rSeriesPlotterContainer.setScalesFromCooSysToPlotter(); + + pVCooSys->createAxesLabels(); + + bool bLessSpaceConsumedThanExpected = false; + { + ::basegfx::B2IRectangle aOldRect( aConsumedOuterRect ); + aConsumedOuterRect = ShapeFactory::getRectangleOfShape(xBoundingShape); + if( aConsumedOuterRect.getMinX() > aAvailableOuterRect.getMinX() + || aConsumedOuterRect.getMaxX() < aAvailableOuterRect.getMaxX() + || aConsumedOuterRect.getMinY() > aAvailableOuterRect.getMinY() + || aConsumedOuterRect.getMinY() < aAvailableOuterRect.getMaxY() ) + bLessSpaceConsumedThanExpected = true; + } + + if( bLessSpaceConsumedThanExpected ) + { + aVDiagram.adjustInnerSize( aConsumedOuterRect ); + pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) )); + pVCooSys->updatePositions(); + } + } + + //create axes and grids for the final size + for( nC=0; nC < rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = rVCooSysList[nC]; + + pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen( aVDiagram.getCurrentRectangle() ) )); + + pVCooSys->createAxesShapes(); + pVCooSys->createGridShapes(); + } + + // - create data series for all charttypes + ::std::vector< VSeriesPlotter* >::const_iterator aPlotterIter = rSeriesPlotterList.begin(); + const ::std::vector< VSeriesPlotter* >::const_iterator aPlotterEnd = rSeriesPlotterList.end(); + for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ ) + { + //------------ set transformation to plotter / create series + VSeriesPlotter* pSeriesPlotter = *aPlotterIter; + rtl::OUString aCID; //III + pSeriesPlotter->initPlotter(xCoordinateRegionTarget,xTextTargetShapes,m_xShapeFactory,aCID); + pSeriesPlotter->setDiagramReferenceSize( rAvailableSize ); + VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter ); + if(2==nDimensionCount) + pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() ); + //better performance for big data + awt::Size aCoordinateRegionResolution(1000,1000); + { + //calculate resolution for coordinate system + Sequence aCoordinateSystemResolution = pVCooSys->getCoordinateSystemResolution( rPageSize, m_aPageResolution ); + pSeriesPlotter->setCoordinateSystemResolution( aCoordinateSystemResolution ); + } + // + pSeriesPlotter->createShapes(); + } + + //recreate with corrected sizes if requested + if( lcl_resizeAfterCompleteCreation(xDiagram) ) + { + uno::Reference< drawing::XShape > xBoundingShape( xDiagramPlusAxes_Shapes, uno::UNO_QUERY ); + ::basegfx::B2IRectangle aConsumedOuterRect( ShapeFactory::getRectangleOfShape(xBoundingShape) ); + + ::basegfx::B2IRectangle aNewInnerRect( aVDiagram.adjustInnerSize( aConsumedOuterRect ) ); + + for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ ) + { + VSeriesPlotter* pSeriesPlotter = *aPlotterIter; + pSeriesPlotter->releaseShapes(); + } + + //clear and recreate + ShapeFactory::removeSubShapes( xCoordinateRegionTarget ); + ShapeFactory::removeSubShapes( xTextTargetShapes ); + + //set new transformation + for( nC=0; nC < rVCooSysList.size(); nC++) + { + VCoordinateSystem* pVCooSys = rVCooSysList[nC]; + pVCooSys->setTransformationSceneToScreen( B3DHomMatrixToHomogenMatrix( + createTransformationSceneToScreen( aNewInnerRect ) )); + } + + // - create data series for all charttypes + for( aPlotterIter = rSeriesPlotterList.begin(); aPlotterIter != aPlotterEnd; aPlotterIter++ ) + { + //------------ set transformation to plotter / create series + VSeriesPlotter* pSeriesPlotter = *aPlotterIter; + VCoordinateSystem* pVCooSys = lcl_getCooSysForPlotter( rVCooSysList, pSeriesPlotter ); + if(2==nDimensionCount) + pSeriesPlotter->setTransformationSceneToScreen( pVCooSys->getTransformationSceneToScreen() ); + pSeriesPlotter->createShapes(); + } + + /* + uno::Reference< drawing::XShape > xDiagramPlusAxes_KeepRatio( xDiagramPlusAxes_Shapes, uno::UNO_QUERY ); + + awt::Size aNewSize( rAvailableSize ); + awt::Point aNewPos( rAvailablePos ); + if( bKeepAspectRatio ) + { + awt::Size aCurrentSize( xDiagramPlusAxes_KeepRatio->getSize()); + + aNewSize = ShapeFactory::calculateNewSizeRespectingAspectRatio( + rAvailableSize, aCurrentSize ); + aNewPos = ShapeFactory::calculateTopLeftPositionToCenterObject( + rAvailablePos, rAvailableSize, aNewSize ); + } + + xDiagramPlusAxes_KeepRatio->setPosition( aNewPos ); + xDiagramPlusAxes_KeepRatio->setSize( aNewSize ); + */ + } +} + //------------------------------------------------------------- //------------------------------------------------------------- //------------------------------------------------------------- -void ChartViewImpl::getExplicitValuesForMeter( - uno::Reference< XMeter > xMeter +sal_Bool ChartView::getExplicitValuesForAxis( + uno::Reference< XAxis > xAxis , ExplicitScaleData& rExplicitScale - , ExplicitIncrementData& rExplicitIncrement - , double& rfExplicitOrigin ) + , ExplicitIncrementData& rExplicitIncrement ) { - if(!xMeter.is()) - return; - uno::Reference< XBoundedCoordinateSystem > xCooSys = xMeter->getCoordinateSystem(); + impl_updateView(); + + if(!xAxis.is()) + return sal_False; + + uno::Reference< XCoordinateSystem > xCooSys( AxisHelper::getCoordinateSystemOfAxis(xAxis,ChartModelHelper::findDiagram( m_xChartModel ) ) ); const VCoordinateSystem* pVCooSys = findInCooSysList(m_aVCooSysList,xCooSys); if(!pVCooSys) - return; - const uno::Sequence< ExplicitScaleData >& rScales =pVCooSys->getExplicitScales(); - const uno::Sequence< ExplicitIncrementData >& rIncrements =pVCooSys->getExplicitIncrements(); - sal_Int32 nDim = xMeter->getRepresentedDimension(); - if(nDim<=rScales.getLength()) - rExplicitScale=rScales[nDim]; - if(nDim<=rIncrements.getLength()) - rExplicitIncrement=rIncrements[nDim]; - rfExplicitOrigin = pVCooSys->getOriginByDimension( nDim ); + return sal_False; + + sal_Int32 nDimensionIndex=-1; + sal_Int32 nAxisIndex=-1; + if( AxisHelper::getIndicesForAxis( xAxis, xCooSys, nDimensionIndex, nAxisIndex ) ) + { + rExplicitScale = pVCooSys->getExplicitScale(nDimensionIndex,nAxisIndex); + rExplicitIncrement = pVCooSys->getExplicitIncrement(nDimensionIndex,nAxisIndex); + return sal_True; + } + return sal_False; +} + +SdrPage* ChartView::getSdrPage() +{ + SdrPage* pPage=0; + Reference< lang::XUnoTunnel> xUnoTunnel(m_xDrawPage,uno::UNO_QUERY); + if(xUnoTunnel.is()) + { + SvxDrawPage* pSvxDrawPage = reinterpret_cast(xUnoTunnel->getSomething( + SvxDrawPage::getUnoTunnelId() )); + if(pSvxDrawPage) + { + pPage = pSvxDrawPage->GetSdrPage(); + } + } + return pPage; +} + +uno::Reference< drawing::XShape > ChartView::getShapeForCID( const rtl::OUString& rObjectCID ) +{ + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + SdrObject* pObj = DrawModelWrapper::getNamedSdrObject( rObjectCID, this->getSdrPage() ); + if( pObj ) + return uno::Reference< drawing::XShape >( pObj->getUnoShape(), uno::UNO_QUERY); + return 0; +} + +awt::Rectangle ChartView::getRectangleOfObject( const rtl::OUString& rObjectCID, bool bSnapRect ) +{ + impl_updateView(); + + awt::Rectangle aRet; + uno::Reference< drawing::XShape > xShape( getShapeForCID(rObjectCID) ); + if(xShape.is()) + { + //special handling for axis for old api: + //same special handling for diagram + ObjectType eObjectType( ObjectIdentifier::getObjectType( rObjectCID ) ); + if( eObjectType == OBJECTTYPE_AXIS || eObjectType == OBJECTTYPE_DIAGRAM ) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + SvxShape* pRoot = SvxShape::getImplementation( xShape ); + if( pRoot ) + { + SdrObject* pRootSdrObject = pRoot->GetSdrObject(); + if( pRootSdrObject ) + { + SdrObjList* pRootList = pRootSdrObject->GetSubList(); + if( pRootList ) + { + SdrObject* pShape = DrawModelWrapper::getNamedSdrObject( C2U("MarkHandles"), pRootList ); + if( pShape ) + xShape = uno::Reference< drawing::XShape >( pShape->getUnoShape(), uno::UNO_QUERY); + } + } + } + } + + awt::Size aSize( xShape->getSize() ); + awt::Point aPoint( xShape->getPosition() ); + aRet = awt::Rectangle( aPoint.X, aPoint.Y, aSize.Width, aSize.Height ); + if( bSnapRect ) + { + //for rotated objects the shape size and position differs from the visible rectangle + SvxShape* pShape = SvxShape::getImplementation( xShape ); + if( pShape ) + { + SdrObject* pSdrObject = pShape->GetSdrObject(); + if( pSdrObject ) + { + Rectangle aSnapRect( pSdrObject->GetSnapRect() ); + aRet = awt::Rectangle(aSnapRect.Left(),aSnapRect.Top(),aSnapRect.GetWidth(),aSnapRect.GetHeight()); + } + } + } + } + return aRet; +} + +::boost::shared_ptr< DrawModelWrapper > ChartView::getDrawModelWrapper() +{ + return m_pDrawModelWrapper; +} + +namespace +{ +sal_Int32 lcl_getDiagramTitleSpace() +{ + return 200; //=0,2 cm spacing +} +bool lcl_getPropertySwapXAndYAxis( const uno::Reference< XDiagram >& xDiagram ) +{ + bool bSwapXAndY = false; + + uno::Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY ); + if( xCooSysContainer.is() ) + { + uno::Sequence< uno::Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); + if( aCooSysList.getLength() ) + { + uno::Reference xProp(aCooSysList[0], uno::UNO_QUERY ); + if( xProp.is()) try + { + xProp->getPropertyValue( C2U( "SwapXAndYAxis" ) ) >>= bSwapXAndY; + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } + } + } + return bSwapXAndY; +} + +} + +//static +sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForAxis( + const Reference< chart2::XAxis >& xAxis + , const Reference< chart2::XCoordinateSystem > & xCorrespondingCoordinateSystem + , const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier ) +{ + sal_Int32 nNumberFormatKey(0); + Reference< beans::XPropertySet > xProp( xAxis, uno::UNO_QUERY ); + if( xProp.is() && !( xProp->getPropertyValue( C2U( "NumberFormat" ) ) >>= nNumberFormatKey ) ) + { + bool bPercentFormatSet = false; + //check wether we have a percent scale -> use percent format + if( xNumberFormatsSupplier.is() ) + { + ScaleData aData = xAxis->getScaleData(); + if( aData.AxisType==AxisType::PERCENT ) + { + sal_Int32 nPercentFormat = ExplicitValueProvider::getPercentNumberFormat( xNumberFormatsSupplier ); + if( nPercentFormat != -1 ) + { + nNumberFormatKey = nPercentFormat; + bPercentFormatSet = true; + } + } + } + + if( !bPercentFormatSet ) + { + typedef ::std::map< sal_Int32, sal_Int32 > tNumberformatFrequency; + tNumberformatFrequency aKeyMap; + + try + { + Reference< XChartTypeContainer > xCTCnt( xCorrespondingCoordinateSystem, uno::UNO_QUERY_THROW ); + if( xCTCnt.is() ) + { + sal_Int32 nDimensionIndex = 1; + sal_Int32 nAxisIndex = 0; + AxisHelper::getIndicesForAxis( xAxis, xCorrespondingCoordinateSystem, nDimensionIndex, nAxisIndex ); + ::rtl::OUString aRoleToMatch; + if( nDimensionIndex == 0 ) + aRoleToMatch = C2U("values-x"); + Sequence< Reference< XChartType > > aChartTypes( xCTCnt->getChartTypes()); + for( sal_Int32 nCTIdx=0; nCTIdxgetRoleOfSequenceForSeriesLabel(); + Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW ); + Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries()); + for( sal_Int32 nSeriesIdx=0; nSeriesIdx xDataSeries(aDataSeriesSeq[nSeriesIdx]); + Reference< data::XDataSource > xSource( xDataSeries, uno::UNO_QUERY_THROW ); + + if( nDimensionIndex == 1 ) + { + //only take those series into accoutn that are attached to this axis + sal_Int32 nAttachedAxisIndex = DataSeriesHelper::getAttachedAxisIndex(xDataSeries); + if( nAttachedAxisIndex != nAxisIndex ) + continue; + } + + Sequence< Reference< data::XLabeledDataSequence > > aLabeledSeq( xSource->getDataSequences()); + for( sal_Int32 nLSeqIdx=0; nLSeqIdx xSeq( aLabeledSeq[nLSeqIdx]->getValues()); + OSL_ASSERT( xSeq.is()); + Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY ); + ::rtl::OUString aRole; + bool bTakeIntoAccount = + ( xProp.is() && (aRoleToMatch.getLength() > 0) && + (xProp->getPropertyValue(C2U("Role")) >>= aRole ) && + aRole.equals( aRoleToMatch )); + + if( bTakeIntoAccount ) + { + sal_Int32 nKey = xSeq->getNumberFormatKeyByIndex( -1 ); + // initialize the value + if( aKeyMap.find( nKey ) == aKeyMap.end()) + aKeyMap[ nKey ] = 0; + // increase frequency + aKeyMap[ nKey ] = (aKeyMap[ nKey ] + 1); + } + } + } + } + } + } + catch( const uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + if( ! aKeyMap.empty()) + { + sal_Int32 nMaxFreq = 0; + // find most frequent key + for( tNumberformatFrequency::const_iterator aIt = aKeyMap.begin(); + aIt != aKeyMap.end(); ++aIt ) + { + OSL_TRACE( "NumberFormatKey %d appears %d times", (*aIt).first, (*aIt).second ); + // all values must at least be 1 + if( (*aIt).second > nMaxFreq ) + { + nNumberFormatKey = (*aIt).first; + nMaxFreq = (*aIt).second; + } + } + } + } + } + return nNumberFormatKey; +} + +//static +sal_Int32 ExplicitValueProvider::getPercentNumberFormat( const Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier ) +{ + sal_Int32 nRet=-1; + Reference< util::XNumberFormats > xNumberFormats( xNumberFormatsSupplier->getNumberFormats() ); + if( xNumberFormats.is() ) + { + sal_Bool bCreate = sal_True; + const LocaleDataWrapper& rLocaleDataWrapper = Application::GetSettings().GetLocaleDataWrapper(); + Sequence aKeySeq = xNumberFormats->queryKeys( util::NumberFormat::PERCENT, + rLocaleDataWrapper.getLocale(), bCreate ); + if( aKeySeq.getLength() ) + { + nRet = aKeySeq[0]; + } + } + return nRet; +} + +//static +awt::Rectangle ExplicitValueProvider::calculateDiagramPositionAndSizeInclusiveTitle( + const Reference< frame::XModel >& xChartModel + , const Reference< uno::XInterface >& xChartView + , const awt::Rectangle& rExclusivePositionAndSize ) +{ + awt::Rectangle aRet(rExclusivePositionAndSize); + + //add axis title sizes to the diagram size + uno::Reference< chart2::XTitle > xTitle_Height( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, xChartModel ) ); + uno::Reference< chart2::XTitle > xTitle_Width( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, xChartModel ) ); + if( xTitle_Height.is() || xTitle_Width.is() ) + { + ExplicitValueProvider* pExplicitValueProvider = ExplicitValueProvider::getExplicitValueProvider(xChartView); + if( pExplicitValueProvider ) + { + //detect wether x axis points into x direction or not + if( lcl_getPropertySwapXAndYAxis( ChartModelHelper::findDiagram( xChartModel ) ) ) + std::swap( xTitle_Height, xTitle_Width ); + + sal_Int32 nTitleSpaceWidth = 0; + sal_Int32 nTitleSpaceHeight = 0; + + if( xTitle_Height.is() ) + { + rtl::OUString aCID_X( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Height, xChartModel ) ); + nTitleSpaceHeight = pExplicitValueProvider->getRectangleOfObject( aCID_X, true ).Height; + if( nTitleSpaceHeight ) + nTitleSpaceHeight+=lcl_getDiagramTitleSpace(); + } + if( xTitle_Width.is() ) + { + rtl::OUString aCID_Y( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle_Width, xChartModel ) ); + nTitleSpaceWidth = pExplicitValueProvider->getRectangleOfObject( aCID_Y, true ).Width; + if(nTitleSpaceWidth) + nTitleSpaceWidth+=lcl_getDiagramTitleSpace(); + } + + aRet.X -= nTitleSpaceWidth; + aRet.Width += nTitleSpaceWidth; + aRet.Height += nTitleSpaceHeight; + } + } + return aRet; } double lcl_getPageLayoutDistancePercentage() @@ -483,11 +1577,12 @@ double lcl_getPageLayoutDistancePercentage() return 0.02; } -bool getPosAndSizeForDiagram( - awt::Point& rOutPos, awt::Size& rOutSize +bool getAvailablePosAndSizeForDiagram( + awt::Point& rOutPos, awt::Size& rOutAvailableDiagramSize , const awt::Rectangle& rSpaceLeft , const awt::Size & rPageSize - , const uno::Reference< XDiagram > & xDiagram ) + , const uno::Reference< XDiagram > & xDiagram + , VTitle* pXTitle, VTitle* pYTitle ) { //@todo: we need a size dependent on the axis labels awt::Rectangle aRemainingSpace(rSpaceLeft); @@ -502,50 +1597,66 @@ bool getPosAndSizeForDiagram( if(aRemainingSpace.Width <= 0 || aRemainingSpace.Height <= 0 ) return false; - //long nHeight = aRemainingSpace.Height * 5 / 6; - // (1 - 5/6) / 2 = 1/12 - //long nOffsetY = aRemainingSpace.Y + aRemainingSpace.Height / 12; - long nHeight = aRemainingSpace.Height * 11 / 12; - long nOffsetY = aRemainingSpace.Y; - - long nWidth = aRemainingSpace.Width * 5 / 6; - // (1 - 5/6) / 2 = 1/12 - long nOffsetX = aRemainingSpace.X + aRemainingSpace.Width / 12; - - if( nHeight <= 0 || nWidth <= 0 ) - return false; - uno::Reference< beans::XPropertySet > xProp(xDiagram, uno::UNO_QUERY); + bool bMakeRoomForTitle = false; + //size: - ::com::sun::star::layout::RelativeSize aRelativeSize; + ::com::sun::star::chart2::RelativeSize aRelativeSize; if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativeSize" ) )>>=aRelativeSize) ) { - rOutSize.Height = static_cast(aRelativeSize.Secondary*rPageSize.Height); - rOutSize.Width = static_cast(aRelativeSize.Primary*rPageSize.Width); + rOutAvailableDiagramSize.Height = static_cast(aRelativeSize.Secondary*rPageSize.Height); + rOutAvailableDiagramSize.Width = static_cast(aRelativeSize.Primary*rPageSize.Width); + bMakeRoomForTitle = true; } else - rOutSize = awt::Size(nWidth,nHeight); + rOutAvailableDiagramSize = awt::Size(aRemainingSpace.Width,aRemainingSpace.Height); //position: - ::com::sun::star::layout::RelativePosition aRelativePosition; + chart2::RelativePosition aRelativePosition; if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) ) { //@todo decide wether x is primary or secondary - //the anchor point at the page is in the middle of the page - double fX = rPageSize.Width/2.0+aRelativePosition.Primary*rPageSize.Width; - double fY = rPageSize.Height/2.0+aRelativePosition.Secondary*rPageSize.Height; + //the coordinates re relative to the page + double fX = aRelativePosition.Primary*rPageSize.Width; + double fY = aRelativePosition.Secondary*rPageSize.Height; - //the anchor point at the diagram object is in the middle - fY -= rOutSize.Height/2; - fX -= rOutSize.Width/2; - - rOutPos.X = static_cast(fX); - rOutPos.Y = static_cast(fY); + rOutPos = RelativePositionHelper::getUpperLeftCornerOfAnchoredObject( + awt::Point(static_cast(fX),static_cast(fY)) + , rOutAvailableDiagramSize, aRelativePosition.Anchor ); + bMakeRoomForTitle = true; } else - rOutPos = awt::Point(nOffsetX,nOffsetY); + rOutPos = awt::Point(aRemainingSpace.X,aRemainingSpace.Y); + + if( bMakeRoomForTitle ) + { + sal_Int32 nTitleSpaceWidth = 0; + sal_Int32 nTitleSpaceHeight = 0; + { + //todo detect wether x axis points into x direction or not + //detect wether x axis points into x direction or not + if( lcl_getPropertySwapXAndYAxis( xDiagram ) ) + std::swap( pXTitle, pYTitle ); + + if( pXTitle ) + { + nTitleSpaceHeight = pXTitle->getFinalSize().Height; + if(nTitleSpaceHeight) + nTitleSpaceHeight+=lcl_getDiagramTitleSpace(); + } + if( pYTitle ) + { + nTitleSpaceWidth = pYTitle->getFinalSize().Width; + if(nTitleSpaceWidth) + nTitleSpaceWidth+=lcl_getDiagramTitleSpace(); + } + } + rOutAvailableDiagramSize.Height -= nTitleSpaceHeight; + rOutAvailableDiagramSize.Width -= nTitleSpaceWidth; + rOutPos.X += nTitleSpaceWidth; + } return true; } @@ -583,9 +1694,10 @@ void changePositionOfAxisTitle( VTitle* pVTitle, TitleAlignment eAlignment pVTitle->changePosition( aNewPosition ); } -std::auto_ptr createTitle( const uno::Reference< XTitle >& xTitle +std::auto_ptr lcl_createTitle( const uno::Reference< XTitle >& xTitle , const uno::Reference< drawing::XShapes>& xPageShapes , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory + , const uno::Reference< frame::XModel >& xChartModel , awt::Rectangle& rRemainingSpace , const awt::Size & rPageSize , TitleAlignment eAlignment @@ -594,14 +1706,16 @@ std::auto_ptr createTitle( const uno::Reference< XTitle >& xTitle std::auto_ptr apVTitle; if(xTitle.is()) { - //create title - double fAdditionalRotationAngleDegree = 0.0; - if( ALIGN_LEFT==eAlignment) - fAdditionalRotationAngleDegree = 90.0; + rtl::OUString aCompleteString( TitleHelper::getCompleteString( xTitle ) ); + if( aCompleteString.getLength()==0 ) + return apVTitle;//don't create empty titles as the resulting diagram position is wrong then - apVTitle = std::auto_ptr(new VTitle(xTitle,fAdditionalRotationAngleDegree)); - apVTitle->init(xPageShapes,xShapeFactory); + //create title + apVTitle = std::auto_ptr(new VTitle(xTitle)); + rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifierForObject( xTitle, xChartModel ) ); + apVTitle->init(xPageShapes,xShapeFactory,aCID); apVTitle->createShapes( awt::Point(0,0), rPageSize ); + awt::Size aTitleUnrotatedSize = apVTitle->getUnrotatedSize(); awt::Size aTitleSize = apVTitle->getFinalSize(); //position @@ -609,18 +1723,20 @@ std::auto_ptr createTitle( const uno::Reference< XTitle >& xTitle awt::Point aNewPosition(0,0); sal_Int32 nYDistance = static_cast(rPageSize.Height*lcl_getPageLayoutDistancePercentage()); sal_Int32 nXDistance = static_cast(rPageSize.Width*lcl_getPageLayoutDistancePercentage()); - ::com::sun::star::layout::RelativePosition aRelativePosition; + chart2::RelativePosition aRelativePosition; uno::Reference< beans::XPropertySet > xProp(xTitle, uno::UNO_QUERY); if( xProp.is() && (xProp->getPropertyValue( C2U( "RelativePosition" ) )>>=aRelativePosition) ) { rbAutoPosition = false; //@todo decide wether x is primary or secondary - aNewPosition.X = static_cast(aRelativePosition.Primary*rPageSize.Width); - aNewPosition.Y = static_cast(aRelativePosition.Secondary*rPageSize.Height); + double fX = aRelativePosition.Primary*rPageSize.Width; + double fY = aRelativePosition.Secondary*rPageSize.Height; - //the anchor point at the title object is top/middle - aNewPosition.Y += aTitleSize.Height/2; + double fAnglePi = apVTitle->getRotationAnglePi(); + aNewPosition = RelativePositionHelper::getCenterOfAnchoredObject( + awt::Point(static_cast(fX),static_cast(fY)) + , aTitleUnrotatedSize, aRelativePosition.Anchor, fAnglePi ); } else //auto position { @@ -673,20 +1789,22 @@ std::auto_ptr createTitle( const uno::Reference< XTitle >& xTitle return apVTitle; } -bool createLegend( const uno::Reference< XLegend > & xLegend +bool lcl_createLegend( const uno::Reference< XLegend > & xLegend , const uno::Reference< drawing::XShapes>& xPageShapes , const uno::Reference< lang::XMultiServiceFactory>& xShapeFactory - , awt::Rectangle & rOutSpaceLeft + , const uno::Reference< uno::XComponentContext > & xContext + , awt::Rectangle & rRemainingSpace , const awt::Size & rPageSize - , const uno::Reference< frame::XModel > & xModel ) + , const uno::Reference< frame::XModel > & xModel + , const std::vector< LegendEntryProvider* >& rLegendEntryProviderList ) { if( VLegend::isVisible( xLegend )) { - VLegend aVLegend( xLegend ); + VLegend aVLegend( xLegend, xContext, rLegendEntryProviderList ); aVLegend.init( xPageShapes, xShapeFactory, xModel ); - aVLegend.createShapes( awt::Size( rOutSpaceLeft.Width, rOutSpaceLeft.Height ), + aVLegend.createShapes( awt::Size( rRemainingSpace.Width, rRemainingSpace.Height ), rPageSize ); - aVLegend.changePosition( rOutSpaceLeft, rPageSize ); + aVLegend.changePosition( rRemainingSpace, rPageSize ); return true; } return false; @@ -709,37 +1827,37 @@ void formatPage( if( ! xModelPage.is()) return; - uno::Reference< beans::XPropertySet > xPageProp( xTarget, uno::UNO_QUERY ); - // the following is just a workaround as the draw page is no XPropertySet - // ------------ workaround - if( ! xPageProp.is() ) + + if( !xShapeFactory.is() ) + return; + + uno::Reference< beans::XPropertySet > xPageProp; + // create a shape for the background { - // if we get here, we need a shape to place on the page - if( xShapeFactory.is()) + uno::Reference< drawing::XShape > xShape( + xShapeFactory->createInstance( + C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY ); + if( xTarget.is() && + xShape.is()) { - uno::Reference< drawing::XShape > xShape( - xShapeFactory->createInstance( - C2U( "com.sun.star.drawing.RectangleShape" )), uno::UNO_QUERY ); - if( xTarget.is() && - xShape.is()) + xTarget->add( xShape ); + xShape->setSize( rPageSize ); + xPageProp.set( xShape, uno::UNO_QUERY ); + if( xPageProp.is()) { - xTarget->add( xShape ); - xShape->setSize( rPageSize ); - xPageProp.set( xShape, uno::UNO_QUERY ); - if( xPageProp.is()) - xPageProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE )); + xPageProp->setPropertyValue( C2U("LineStyle"), uno::makeAny( drawing::LineStyle_NONE )); } } } - // ------------ workaround + //format page if( xPageProp.is()) { tPropertyNameValueMap aNameValueMap; - tMakePropertyNameMap aNameMap = PropertyMapper::getPropertyNameMapForFillProperties(); - const tMakePropertyNameMap& rLineNameMap = PropertyMapper::getPropertyNameMapForLineProperties(); - aNameMap.insert( rLineNameMap.begin(), rLineNameMap.end()); - PropertyMapper::getValueMap( aNameValueMap, aNameMap, xModelPage ); + PropertyMapper::getValueMap( aNameValueMap, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), xModelPage ); + + rtl::OUString aCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_PAGE, rtl::OUString() ) ); + aNameValueMap.insert( tPropertyNameValueMap::value_type( C2U("Name"), uno::makeAny( aCID ) ) ); //CID rtl::OUString tNameSequence aNames; tAnySequence aValues; @@ -753,91 +1871,431 @@ void formatPage( } } -bool ChartViewImpl::create( const awt::Size& rPageSize ) +void lcl_removeEmptyGroupShapes( const Reference< drawing::XShapes>& xParent ) { - uno::Reference xPageShapes = - uno::Reference( m_xDrawPage, uno::UNO_QUERY ); - - //------------ apply fill properties to page - // todo: it would be nicer to just pass the page m_xDrawPage and format it, - // but the page we have here does not support XPropertySet - formatPage( m_xChartModel, rPageSize, xPageShapes, m_xShapeFactory ); - - //sal_Int32 nYDistance = static_cast(rPageSize.Height*lcl_getPageLayoutDistancePercentage()); - awt::Rectangle aRemainingSpace( 0, 0, rPageSize.Width, rPageSize.Height ); - - //create the group shape for diagram and axes first to have title and legends on top of it - uno::Reference< drawing::XShapes > xDiagramPlusAxesGroup_Shapes = ShapeFactory(m_xShapeFactory).createGroup2D(xPageShapes,C2U("CID/Diagram=XXX_CID"));//@todo read CID from model - - //------------ create some titles - std::auto_ptr apVTitle(0); - bool bAutoPositionDummy; - - //------------ create main title shape - createTitle( TitleHelper::getTitle( TitleHelper::MAIN_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory - , aRemainingSpace, rPageSize, ALIGN_TOP, bAutoPositionDummy ); - if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) - return true; - - //------------ create sub title shape - createTitle( TitleHelper::getTitle( TitleHelper::SUB_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory - , aRemainingSpace, rPageSize, ALIGN_TOP, bAutoPositionDummy ); - if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) - return true; - - //------------ create legend - createLegend( LegendHelper::getLegend( m_xChartModel ), xPageShapes, m_xShapeFactory - , aRemainingSpace, rPageSize, m_xChartModel ); - if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) - return true; - - //------------ create x axis title - bool bAutoPosition_XTitle; - std::auto_ptr apVTitle_X( createTitle( TitleHelper::getTitle( TitleHelper::X_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory - , aRemainingSpace, rPageSize, ALIGN_BOTTOM, bAutoPosition_XTitle) ); - if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) - return true; - - //------------ create y axis title - bool bAutoPosition_YTitle; - std::auto_ptr apVTitle_Y( createTitle( TitleHelper::getTitle( TitleHelper::Y_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory - , aRemainingSpace, rPageSize, ALIGN_LEFT, bAutoPosition_YTitle) ); - if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) - return true; - - //------------ create z axis title - bool bAutoPosition_ZTitle; - std::auto_ptr apVTitle_Z( createTitle( TitleHelper::getTitle( TitleHelper::Z_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory - , aRemainingSpace, rPageSize, ALIGN_RIGHT, bAutoPosition_ZTitle) ); - if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) - return true; - - //------------ create complete diagram shape (inclusive axis and series) - awt::Point aPosDia; - awt::Size aSizeDia; - if( getPosAndSizeForDiagram( aPosDia, aSizeDia, aRemainingSpace, rPageSize, ChartModelHelper::findDiagram( m_xChartModel ) ) ) + if(!xParent.is()) + return; + Reference< drawing::XShapeGroup > xParentGroup( xParent, uno::UNO_QUERY ); + if( !xParentGroup.is() ) { - //create diagram and all its content - initializeDiagramAndGetCooSys( m_aVCooSysList - , m_xCC, xDiagramPlusAxesGroup_Shapes, m_xShapeFactory, m_pNumberFormatterWrapper - , aPosDia ,aSizeDia, m_xChartModel ); - - //correct axis title position - uno::Reference< drawing::XShape > xDiagramPlusAxesGroup_Shape( xDiagramPlusAxesGroup_Shapes, uno::UNO_QUERY ); - awt::Point aPos = xDiagramPlusAxesGroup_Shape->getPosition(); - awt::Size aSize = xDiagramPlusAxesGroup_Shape->getSize(); - awt::Rectangle aRect(aPos.X,aPos.Y,aSize.Width,aSize.Height); - awt::Rectangle aDiagramPlusAxesRect(aPos.X,aPos.Y,aSize.Width,aSize.Height); - if(bAutoPosition_XTitle) - changePositionOfAxisTitle( apVTitle_X.get(), ALIGN_BOTTOM, aDiagramPlusAxesRect, rPageSize ); - if(bAutoPosition_YTitle) - changePositionOfAxisTitle( apVTitle_Y.get(), ALIGN_LEFT, aDiagramPlusAxesRect, rPageSize ); - if(bAutoPosition_ZTitle) - changePositionOfAxisTitle( apVTitle_Z.get(), ALIGN_Z, aDiagramPlusAxesRect, rPageSize ); + Reference< drawing::XDrawPage > xPage( xParent, uno::UNO_QUERY ); + if( !xPage.is() ) + return; + } + + //iterate from back! + for( sal_Int32 nN = xParent->getCount(); nN--; ) + { + uno::Any aAny = xParent->getByIndex( nN ); + Reference< drawing::XShapes> xShapes(0); + if( aAny >>= xShapes ) + lcl_removeEmptyGroupShapes( xShapes ); + if( xShapes.is() && xShapes->getCount()==0 ) + { + //remove empty group shape + Reference< drawing::XShapeGroup > xGroup( xShapes, uno::UNO_QUERY ); + Reference< drawing::XShape > xShape( xShapes, uno::UNO_QUERY ); + if( xGroup.is() ) + xParent->remove( xShape ); + } } - return true; } +bool ChartView::impl_AddInDrawsAllByItself() +{ + bool bRet = false; + /* + uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY ); + if( xProp.is()) try + { + uno::Reference< util::XRefreshable > xAddIn; + xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn; + if( xAddIn.is() ) + { + rtl::OUString aBaseDiagram; + xProp->getPropertyValue( C2U( "BaseDiagram" ) ) >>= aBaseDiagram; + if(aBaseDiagram.getLength()) + bRet = true; + } + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } + */ + return bRet; +} + +void ChartView::impl_refreshAddIn() +{ + if( !m_bRefreshAddIn ) + return; + + uno::Reference< beans::XPropertySet > xProp( m_xChartModel, uno::UNO_QUERY ); + if( xProp.is()) try + { + uno::Reference< util::XRefreshable > xAddIn; + xProp->getPropertyValue( C2U( "AddIn" ) ) >>= xAddIn; + if( xAddIn.is() ) + { + sal_Bool bRefreshAddInAllowed = sal_True; + xProp->getPropertyValue( C2U( "RefreshAddInAllowed" ) ) >>= bRefreshAddInAllowed; + if( bRefreshAddInAllowed ) + xAddIn->refresh(); + } + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } +} + +void ChartView::createShapes() +{ +#if OSL_DEBUG_LEVEL > 0 + clock_t nStart = clock(); + OSL_TRACE( "\nPPPPPPPPP>>>>>>>>>>>> chart view :: createShapes()" ); +#endif + + //make sure add-in is refreshed after creating the shapes + const ::comphelper::ScopeGuard aGuard( boost::bind( &ChartView::impl_refreshAddIn, this ) ); + if( impl_AddInDrawsAllByItself() ) + return; + + impl_deleteCoordinateSystems(); + if( m_pDrawModelWrapper ) + m_pDrawModelWrapper->clearMainDrawPage(); + + awt::Size aPageSize = ChartModelHelper::getPageSize( m_xChartModel ); + + uno::Reference xPageShapes( ShapeFactory(m_xShapeFactory) + .getOrCreateChartRootShape( m_xDrawPage ) ); + + SdrPage* pPage = ChartView::getSdrPage(); + if(pPage) //it is neccessary to use the implementation here as the uno page does not provide a propertyset + pPage->SetSize(Size(aPageSize.Width,aPageSize.Height)); + else + { + DBG_ERROR("could not set page size correctly"); + } + + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex()); + + //------------ apply fill properties to page + // todo: it would be nicer to just pass the page m_xDrawPage and format it, + // but the draw page does not support XPropertySet + formatPage( m_xChartModel, aPageSize, xPageShapes, m_xShapeFactory ); + + //sal_Int32 nYDistance = static_cast(aPageSize.Height*lcl_getPageLayoutDistancePercentage()); + awt::Rectangle aRemainingSpace( 0, 0, aPageSize.Width, aPageSize.Height ); + + //create the group shape for diagram and axes first to have title and legends on top of it + uno::Reference< XDiagram > xDiagram( ChartModelHelper::findDiagram( m_xChartModel ) ); + rtl::OUString aDiagramCID( ObjectIdentifier::createClassifiedIdentifier( OBJECTTYPE_DIAGRAM, rtl::OUString::valueOf( sal_Int32(0) ) ) );//todo: other index if more than one diagram is possible + uno::Reference< drawing::XShapes > xDiagramPlusAxesPlusMarkHandlesGroup_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xPageShapes,aDiagramCID) ); + uno::Reference< drawing::XShape > xDiagramPlusAxes_MarkHandles( ShapeFactory(m_xShapeFactory).createInvisibleRectangle( + xDiagramPlusAxesPlusMarkHandlesGroup_Shapes, awt::Size(0,0) ) ); + ShapeFactory::setShapeName( xDiagramPlusAxes_MarkHandles, C2U("MarkHandles") ); + uno::Reference< drawing::XShapes > xDiagramPlusAxes_Shapes( ShapeFactory(m_xShapeFactory).createGroup2D(xDiagramPlusAxesPlusMarkHandlesGroup_Shapes ) ); + + //------------ create some titles + std::auto_ptr apVTitle(0); + bool bAutoPositionDummy = true; + + //------------ create main title shape + lcl_createTitle( TitleHelper::getTitle( TitleHelper::MAIN_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel + , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy ); + if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) + return; + + //------------ create sub title shape + lcl_createTitle( TitleHelper::getTitle( TitleHelper::SUB_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel + , aRemainingSpace, aPageSize, ALIGN_TOP, bAutoPositionDummy ); + if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) + return; + + + //------------ prepare series to give input to the legend (create categories and symbols etc.) + SeriesPlotterContainer aSeriesPlotterContainer( m_aVCooSysList ); + aSeriesPlotterContainer.initializeCooSysAndSeriesPlotter( m_xChartModel ); + + //------------ create legend + lcl_createLegend( LegendHelper::getLegend( m_xChartModel ), xPageShapes, m_xShapeFactory, m_xCC + , aRemainingSpace, aPageSize, m_xChartModel, aSeriesPlotterContainer.getLegendEntryProviderList() ); + if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) + return; + + //------------ create x axis title + bool bAutoPosition_XTitle = true; + std::auto_ptr apVTitle_X( lcl_createTitle( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_X_AXIS_POSITION, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel + , aRemainingSpace, aPageSize, ALIGN_BOTTOM, bAutoPosition_XTitle) ); + if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) + return; + + //------------ create y axis title + bool bAutoPosition_YTitle = true; + std::auto_ptr apVTitle_Y( lcl_createTitle( TitleHelper::getTitle( TitleHelper::TITLE_AT_STANDARD_Y_AXIS_POSITION, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel + , aRemainingSpace, aPageSize, ALIGN_LEFT, bAutoPosition_YTitle) ); + if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) + return; + + //------------ create z axis title + bool bAutoPosition_ZTitle = true; + std::auto_ptr apVTitle_Z( lcl_createTitle( TitleHelper::getTitle( TitleHelper::Z_AXIS_TITLE, m_xChartModel ), xPageShapes, m_xShapeFactory, m_xChartModel + , aRemainingSpace, aPageSize, ALIGN_RIGHT, bAutoPosition_ZTitle) ); + if(aRemainingSpace.Width<=0||aRemainingSpace.Height<=0) + return; + + //------------ create complete diagram shape (inclusive axis and series) + awt::Point aAvailablePosDia; + awt::Size aAvailableSizeForDiagram; + if( getAvailablePosAndSizeForDiagram( aAvailablePosDia, aAvailableSizeForDiagram, aRemainingSpace, aPageSize, ChartModelHelper::findDiagram( m_xChartModel ) + , apVTitle_X.get(), apVTitle_Y.get() ) ) + { + impl_createDiagramAndContent( aSeriesPlotterContainer + , xDiagramPlusAxes_Shapes + , aAvailablePosDia ,aAvailableSizeForDiagram, aPageSize ); + + if(xDiagramPlusAxes_MarkHandles.is()) + { + xDiagramPlusAxes_MarkHandles->setPosition( aAvailablePosDia ); + xDiagramPlusAxes_MarkHandles->setSize( aAvailableSizeForDiagram ); + } + + //correct axis title position + awt::Rectangle aDiagramPlusAxesRect(aAvailablePosDia.X,aAvailablePosDia.Y,aAvailableSizeForDiagram.Width,aAvailableSizeForDiagram.Height); + if(bAutoPosition_XTitle) + changePositionOfAxisTitle( apVTitle_X.get(), ALIGN_BOTTOM, aDiagramPlusAxesRect, aPageSize ); + if(bAutoPosition_YTitle) + changePositionOfAxisTitle( apVTitle_Y.get(), ALIGN_LEFT, aDiagramPlusAxesRect, aPageSize ); + if(bAutoPosition_ZTitle) + changePositionOfAxisTitle( apVTitle_Z.get(), ALIGN_Z, aDiagramPlusAxesRect, aPageSize ); + } + + //cleanup: remove all empty group shapes to avoid grey border lines: + lcl_removeEmptyGroupShapes( xPageShapes ); + } + +#if OSL_DEBUG_LEVEL > 0 + clock_t nEnd = clock(); + double fDuration =(double(nEnd-nStart)*1000.0)/double(CLOCKS_PER_SEC); + + OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< chart view :: createShapes():: needed %f msec", fDuration ); +#endif +} + +//----------------------------------------------------------------- +// util::XEventListener (base of XCloseListener) +//----------------------------------------------------------------- +void SAL_CALL ChartView::disposing( const lang::EventObject& rSource ) + throw(uno::RuntimeException) +{ + impl_setChartModel( 0 ); +} + +void ChartView::impl_updateView() +{ + if( !m_xChartModel.is() || !m_pDrawModelWrapper ) + return; + + if( m_bViewDirty && !m_bInViewUpdate ) + { + m_bInViewUpdate = true; + //bool bOldRefreshAddIn = m_bRefreshAddIn; + //m_bRefreshAddIn = false; + try + { + impl_notifyModeChangeListener(C2U("invalid")); + + //prepare draw model + m_pDrawModelWrapper->lockControllers(); + m_pDrawModelWrapper->updateTablesFromChartModel( m_xChartModel ); + + //create chart view + { + /* + ::vos::OGuard aGuard( Application::GetSolarMutex()); + while( m_bViewDirty ) + { + createShapes(); + m_bViewDirty = m_bViewUpdatePending; + m_bViewUpdatePending = false; + m_bInViewUpdate = false; + } + */ + + m_bViewDirty = false; + m_bViewUpdatePending = false; + createShapes(); + + if( m_bViewDirty ) + { + //avoid recursions due to add-in + m_bRefreshAddIn = false; + m_bViewDirty = false; + m_bViewUpdatePending = false; + //delete old chart view + createShapes(); + m_bRefreshAddIn = true; + } + } + + m_bViewDirty = m_bViewUpdatePending; + m_bViewUpdatePending = false; + m_bInViewUpdate = false; + } + catch( uno::Exception& ex) + { + m_bViewDirty = m_bViewUpdatePending; + m_bViewUpdatePending = false; + m_bInViewUpdate = false; + ASSERT_EXCEPTION( ex ); + } + + m_pDrawModelWrapper->unlockControllers(); + + impl_notifyModeChangeListener(C2U("valid")); + + //m_bRefreshAddIn = bOldRefreshAddIn; + } +} + +// ____ XModifyListener ____ +void SAL_CALL ChartView::modified( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + m_bViewDirty = sal_True; + if( m_bInViewUpdate ) + m_bViewUpdatePending = true; + + impl_notifyModeChangeListener(C2U("dirty")); +} + +void ChartView::impl_notifyModeChangeListener( const rtl::OUString& rNewMode ) +{ + try + { + ::cppu::OInterfaceContainerHelper* pIC = m_aListenerContainer + .getContainer( ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0) ); + if( pIC ) + { + util::ModeChangeEvent aEvent( static_cast< uno::XWeak* >( this ), rNewMode ); + ::cppu::OInterfaceIteratorHelper aIt( *pIC ); + while( aIt.hasMoreElements() ) + (static_cast< util::XModeChangeListener*>(aIt.next()))->modeChanged( aEvent ); + } + } + catch( uno::Exception& ex) + { + ASSERT_EXCEPTION( ex ); + } +} + +// ____ XModeChangeBroadcaster ____ + +void SAL_CALL ChartView::addModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + m_aListenerContainer.addInterface( + ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener ); +} +void SAL_CALL ChartView::removeModeChangeListener( const uno::Reference< util::XModeChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + m_aListenerContainer.removeInterface( + ::getCppuType((const uno::Reference< util::XModeChangeListener >*)0), xListener ); +} +void SAL_CALL ChartView::addModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& _rxListener ) + throw (lang::NoSupportException, uno::RuntimeException) +{ + +} +void SAL_CALL ChartView::removeModeChangeApproveListener( const uno::Reference< util::XModeChangeApproveListener >& _rxListener ) + throw (lang::NoSupportException, uno::RuntimeException) +{ + +} + +// ____ XUpdatable ____ +void SAL_CALL ChartView::update() throw (uno::RuntimeException) +{ + impl_updateView(); +} + +// ____ XPropertySet ____ +Reference< beans::XPropertySetInfo > SAL_CALL ChartView::getPropertySetInfo() + throw (uno::RuntimeException) +{ + OSL_ENSURE(false,"not implemented"); + return 0; +} + +void SAL_CALL ChartView::setPropertyValue( const ::rtl::OUString& rPropertyName + , const Any& rValue ) + throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException + , lang::WrappedTargetException, uno::RuntimeException) +{ + if( rPropertyName.equals(C2U("Resolution")) ) + { + awt::Size aNewResolution; + if( ! (rValue >>= aNewResolution) ) + throw lang::IllegalArgumentException( C2U("Property 'Resolution' requires value of type awt::Size"), 0, 0 ); + + if( m_aPageResolution.Width!=aNewResolution.Width || m_aPageResolution.Height!=aNewResolution.Height ) + { + //set modified only when the new resolution is higher + bool bSetModified = m_aPageResolution.Widthmodified( lang::EventObject( static_cast< uno::XWeak* >( this ) ) ); + } + } + else + throw beans::UnknownPropertyException( C2U("unknown property was tried to set to chart wizard"), 0 ); +} + +Any SAL_CALL ChartView::getPropertyValue( const ::rtl::OUString& rPropertyName ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + Any aRet; + if( rPropertyName.equals(C2U("Resolution")) ) + { + aRet = uno::makeAny( m_aPageResolution ); + } + else + throw beans::UnknownPropertyException( C2U("unknown property was tried to get from chart wizard"), 0 ); + return aRet; +} + +void SAL_CALL ChartView::addPropertyChangeListener( + const ::rtl::OUString& aPropertyName, const Reference< beans::XPropertyChangeListener >& xListener ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE(false,"not implemented"); +} +void SAL_CALL ChartView::removePropertyChangeListener( + const ::rtl::OUString& aPropertyName, const Reference< beans::XPropertyChangeListener >& aListener ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE(false,"not implemented"); +} + +void SAL_CALL ChartView::addVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< beans::XVetoableChangeListener >& aListener ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE(false,"not implemented"); +} + +void SAL_CALL ChartView::removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< beans::XVetoableChangeListener >& aListener ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE(false,"not implemented"); +} + + //............................................................................. } //namespace chart //.............................................................................