diff options
Diffstat (limited to 'oox/source/drawingml/chart')
-rw-r--r-- | oox/source/drawingml/chart/axisconverter.cxx | 5 | ||||
-rw-r--r-- | oox/source/drawingml/chart/chartcontextbase.cxx | 61 | ||||
-rw-r--r-- | oox/source/drawingml/chart/chartspaceconverter.cxx | 19 | ||||
-rw-r--r-- | oox/source/drawingml/chart/converterbase.cxx | 265 | ||||
-rw-r--r-- | oox/source/drawingml/chart/modelbase.cxx | 20 | ||||
-rw-r--r-- | oox/source/drawingml/chart/objectformatter.cxx | 19 | ||||
-rw-r--r-- | oox/source/drawingml/chart/plotareaconverter.cxx | 50 | ||||
-rw-r--r-- | oox/source/drawingml/chart/seriesconverter.cxx | 21 | ||||
-rw-r--r-- | oox/source/drawingml/chart/titlecontext.cxx | 59 | ||||
-rw-r--r-- | oox/source/drawingml/chart/titleconverter.cxx | 62 | ||||
-rw-r--r-- | oox/source/drawingml/chart/titlemodel.cxx | 19 |
11 files changed, 488 insertions, 112 deletions
diff --git a/oox/source/drawingml/chart/axisconverter.cxx b/oox/source/drawingml/chart/axisconverter.cxx index 3ad1c0023ebe..77cf21698c62 100644 --- a/oox/source/drawingml/chart/axisconverter.cxx +++ b/oox/source/drawingml/chart/axisconverter.cxx @@ -301,11 +301,12 @@ void AxisConverter::convertFromModel( const Reference< XCoordinateSystem >& rxCo // axis title --------------------------------------------------------- - if( mrModel.mxTitle.is() ) + // in radar charts, title objects may exist, but are not shown + if( mrModel.mxTitle.is() && (rTypeGroup.getTypeInfo().meTypeCategory != TYPECATEGORY_RADAR) ) { Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW ); TitleConverter aTitleConv( *this, *mrModel.mxTitle ); - aTitleConv.convertFromModel( xTitled, CREATE_OUSTRING( "Axis Title" ), OBJECTTYPE_AXISTITLE ); + aTitleConv.convertFromModel( xTitled, CREATE_OUSTRING( "Axis Title" ), OBJECTTYPE_AXISTITLE, nAxesSetIdx, nAxisIdx ); } } catch( Exception& ) diff --git a/oox/source/drawingml/chart/chartcontextbase.cxx b/oox/source/drawingml/chart/chartcontextbase.cxx index 2666d22ccbe0..d3746f07ba6c 100644 --- a/oox/source/drawingml/chart/chartcontextbase.cxx +++ b/oox/source/drawingml/chart/chartcontextbase.cxx @@ -27,6 +27,7 @@ #include "oox/drawingml/chart/chartcontextbase.hxx" #include "oox/drawingml/shapepropertiescontext.hxx" +#include "oox/drawingml/chart/modelbase.hxx" using ::oox::core::ContextHandler2Helper; using ::oox::core::ContextHandlerRef; @@ -53,6 +54,66 @@ ContextHandlerRef ShapePrWrapperContext::onCreateContext( sal_Int32 nElement, co // ============================================================================ +LayoutContext::LayoutContext( ContextHandler2Helper& rParent, LayoutModel& rModel ) : + ContextBase< LayoutModel >( rParent, rModel ) +{ +} + +LayoutContext::~LayoutContext() +{ +} + +ContextHandlerRef LayoutContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( getCurrentElement() ) + { + case C_TOKEN( layout ): + switch( nElement ) + { + case C_TOKEN( manualLayout ): + mrModel.mbAutoLayout = false; + return this; + } + break; + + case C_TOKEN( manualLayout ): + switch( nElement ) + { + case C_TOKEN( x ): + mrModel.mfX = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( y ): + mrModel.mfY = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( w ): + mrModel.mfW = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( h ): + mrModel.mfH = rAttribs.getDouble( XML_val, 0.0 ); + return 0; + case C_TOKEN( xMode ): + mrModel.mnXMode = rAttribs.getToken( XML_val, XML_factor ); + return 0; + case C_TOKEN( yMode ): + mrModel.mnYMode = rAttribs.getToken( XML_val, XML_factor ); + return 0; + case C_TOKEN( wMode ): + mrModel.mnWMode = rAttribs.getToken( XML_val, XML_factor ); + return 0; + case C_TOKEN( hMode ): + mrModel.mnHMode = rAttribs.getToken( XML_val, XML_factor ); + return 0; + case C_TOKEN( layoutTarget ): + mrModel.mnTarget = rAttribs.getToken( XML_val, XML_outer ); + return 0; + } + break; + } + return 0; +} + +// ============================================================================ + } // namespace chart } // namespace drawingml } // namespace oox diff --git a/oox/source/drawingml/chart/chartspaceconverter.cxx b/oox/source/drawingml/chart/chartspaceconverter.cxx index 6460e94a4f3b..54212f1bdbda 100644 --- a/oox/source/drawingml/chart/chartspaceconverter.cxx +++ b/oox/source/drawingml/chart/chartspaceconverter.cxx @@ -26,12 +26,12 @@ ************************************************************************/ #include "oox/drawingml/chart/chartspaceconverter.hxx" -#include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/chart/MissingValueTreatment.hpp> #include <com/sun/star/chart/XChartDocument.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart2/XTitled.hpp> #include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include "oox/core/xmlfilterbase.hxx" #include "oox/drawingml/chart/chartconverter.hxx" #include "oox/drawingml/chart/chartdrawingfragment.hxx" @@ -147,14 +147,23 @@ void ChartSpaceConverter::convertFromModel( const Reference< XShapes >& rxExtern aDiaProp.setProperty( PROP_MissingValueTreatment, nMissingValues ); } - Reference< com::sun::star::chart::XChartDocument > xOldChartDoc( getChartDocument(), UNO_QUERY ); - if( xOldChartDoc.is() ) + /* Following all conversions needing the old Chart1 API that involves full + initialization of the chart view. */ + namespace cssc = ::com::sun::star::chart; + Reference< cssc::XChartDocument > xChart1Doc( getChartDocument(), UNO_QUERY ); + if( xChart1Doc.is() ) { /* Set the IncludeHiddenCells property via the old API as only this ensures that the data provider and all created sequences get this flag correctly. */ - PropertySet aOldDiaProp( xOldChartDoc->getDiagram() ); - aOldDiaProp.setProperty( PROP_IncludeHiddenCells, !mrModel.mbPlotVisOnly ); + PropertySet aDiaProp( xChart1Doc->getDiagram() ); + aDiaProp.setProperty( PROP_IncludeHiddenCells, !mrModel.mbPlotVisOnly ); + + // plot area position and size + aPlotAreaConv.convertPositionFromModel(); + + // positions of main title and all axis titles + convertTitlePositions(); } // embedded drawing shapes diff --git a/oox/source/drawingml/chart/converterbase.cxx b/oox/source/drawingml/chart/converterbase.cxx index 534ce48e0278..b5a0511bf1b8 100644 --- a/oox/source/drawingml/chart/converterbase.cxx +++ b/oox/source/drawingml/chart/converterbase.cxx @@ -30,6 +30,14 @@ #include <com/sun/star/frame/XModel.hpp> #include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/chart/XAxisXSupplier.hpp> +#include <com/sun/star/chart/XAxisYSupplier.hpp> +#include <com/sun/star/chart/XAxisZSupplier.hpp> +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> +#include <tools/solar.h> // for F_PI180 +#include "properties.hxx" #include "oox/core/xmlfilterbase.hxx" #include "oox/drawingml/theme.hxx" @@ -37,22 +45,126 @@ using ::rtl::OUString; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::XInterface; using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::frame::XModel; +using ::com::sun::star::awt::Point; +using ::com::sun::star::awt::Rectangle; using ::com::sun::star::awt::Size; +using ::com::sun::star::chart2::RelativePosition; using ::com::sun::star::chart2::XChartDocument; +using ::com::sun::star::chart2::XTitle; +using ::com::sun::star::drawing::XShape; using ::oox::core::XmlFilterBase; +namespace cssc = ::com::sun::star::chart; + namespace oox { namespace drawingml { namespace chart { // ============================================================================ +namespace { + +struct TitleKey : public ::std::pair< ObjectType, ::std::pair< sal_Int32, sal_Int32 > > +{ + inline explicit TitleKey( ObjectType eObjType, sal_Int32 nMainIdx = -1, sal_Int32 nSubIdx = -1 ) + { first = eObjType; second.first = nMainIdx; second.second = nSubIdx; } +}; + +// ---------------------------------------------------------------------------- + +/** A helper structure to store all data related to title objects. Needed for + the conversion of manual title positions that needs the old Chart1 API. + */ +struct TitleLayoutInfo +{ + typedef Reference< XShape > (*GetShapeFunc)( const Reference< cssc::XChartDocument >& ); + + ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTitle > + mxTitle; /// The API title object. + ModelRef< LayoutModel > mxLayout; /// The layout model, if existing. + GetShapeFunc mpGetShape; /// Helper function to receive the title shape. + + inline explicit TitleLayoutInfo() : mpGetShape( 0 ) {} + + void convertTitlePos( + ConverterRoot& rRoot, + const Reference< cssc::XChartDocument >& rxChart1Doc ); +}; + +void TitleLayoutInfo::convertTitlePos( ConverterRoot& rRoot, const Reference< cssc::XChartDocument >& rxChart1Doc ) +{ + if( mxTitle.is() && mpGetShape ) try + { + // try to get the title shape + Reference< XShape > xTitleShape( mpGetShape( rxChart1Doc ), UNO_SET_THROW ); + // get title rotation angle, needed for correction of position of top-left edge + double fAngle = 0.0; + PropertySet aTitleProp( mxTitle ); + aTitleProp.getProperty( fAngle, PROP_TextRotation ); + // convert the position + LayoutModel& rLayout = mxLayout.getOrCreate(); + LayoutConverter aLayoutConv( rRoot, rLayout ); + aLayoutConv.convertFromModel( xTitleShape, fAngle ); + } + catch( Exception& ) + { + } +} + +// ---------------------------------------------------------------------------- + +/* The following local functions implement getting the XShape interface of all + supported title objects (chart and axes). This needs some effort due to the + design of the old Chart1 API used to access these objects. */ + +/** A code fragment that returns a shape object from the passed shape supplier + using the specified interface function. Checks a boolean property first. */ +#define OOX_FRAGMENT_GETTITLESHAPE( shape_supplier, supplier_func, property_name ) \ + PropertySet aPropSet( shape_supplier ); \ + if( shape_supplier.is() && aPropSet.getBoolProperty( PROP_##property_name ) ) \ + return shape_supplier->supplier_func(); \ + return Reference< XShape >(); \ + +/** Implements a function returning the drawing shape of an axis title, if + existing, using the specified API interface and its function. */ +#define OOX_DEFINEFUNC_GETAXISTITLESHAPE( func_name, interface_type, supplier_func, property_name ) \ +Reference< XShape > func_name( const Reference< cssc::XChartDocument >& rxChart1Doc ) \ +{ \ + Reference< cssc::interface_type > xAxisSupp( rxChart1Doc->getDiagram(), UNO_QUERY ); \ + OOX_FRAGMENT_GETTITLESHAPE( xAxisSupp, supplier_func, property_name ) \ +} + +/** Returns the drawing shape of the main title, if existing. */ +Reference< XShape > lclGetMainTitleShape( const Reference< cssc::XChartDocument >& rxChart1Doc ) +{ + OOX_FRAGMENT_GETTITLESHAPE( rxChart1Doc, getTitle, HasMainTitle ) +} + +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetXAxisTitleShape, XAxisXSupplier, getXAxisTitle, HasXAxisTitle ) +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetYAxisTitleShape, XAxisYSupplier, getYAxisTitle, HasYAxisTitle ) +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetZAxisTitleShape, XAxisZSupplier, getZAxisTitle, HasZAxisTitle ) +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecXAxisTitleShape, XSecondAxisTitleSupplier, getSecondXAxisTitle, HasSecondaryXAxisTitle ) +OOX_DEFINEFUNC_GETAXISTITLESHAPE( lclGetSecYAxisTitleShape, XSecondAxisTitleSupplier, getSecondYAxisTitle, HasSecondaryYAxisTitle ) + +#undef OOX_DEFINEFUNC_GETAXISTITLESHAPE +#undef OOX_IMPLEMENT_GETTITLESHAPE + +} // namespace + +// ============================================================================ + struct ConverterData { + typedef ::std::map< TitleKey, TitleLayoutInfo > TitleMap; + ObjectFormatter maFormatter; + TitleMap maTitles; XmlFilterBase& mrFilter; ChartConverter& mrConverter; Reference< XChartDocument > mxDoc; @@ -91,6 +203,14 @@ ConverterData::ConverterData( catch( Exception& ) { } + + // prepare conversion of title positions + maTitles[ TitleKey( OBJECTTYPE_CHARTTITLE ) ].mpGetShape = lclGetMainTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_X_AXIS ) ].mpGetShape = lclGetXAxisTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_Y_AXIS ) ].mpGetShape = lclGetYAxisTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_PRIM_AXESSET, API_Z_AXIS ) ].mpGetShape = lclGetZAxisTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_SECN_AXESSET, API_X_AXIS ) ].mpGetShape = lclGetSecXAxisTitleShape; + maTitles[ TitleKey( OBJECTTYPE_AXISTITLE, API_SECN_AXESSET, API_Y_AXIS ) ].mpGetShape = lclGetSecYAxisTitleShape; } ConverterData::~ConverterData() @@ -122,13 +242,12 @@ ConverterRoot::~ConverterRoot() { } -Reference< XInterface > ConverterRoot::createInstance( - const Reference< XMultiServiceFactory >& rxFactory, const OUString& rServiceName ) +Reference< XInterface > ConverterRoot::createInstance( const OUString& rServiceName ) const { Reference< XInterface > xInt; - if( rxFactory.is() ) try + try { - xInt = rxFactory->createInstance( rServiceName ); + xInt = mxData->mrFilter.getGlobalFactory()->createInstance( rServiceName ); } catch( Exception& ) { @@ -137,11 +256,6 @@ Reference< XInterface > ConverterRoot::createInstance( return xInt; } -Reference< XInterface > ConverterRoot::createInstance( const OUString& rServiceName ) const -{ - return createInstance( mxData->mrFilter.getGlobalFactory(), rServiceName ); -} - XmlFilterBase& ConverterRoot::getFilter() const { return mxData->mrFilter; @@ -167,6 +281,139 @@ ObjectFormatter& ConverterRoot::getFormatter() const return mxData->maFormatter; } +void ConverterRoot::registerTitleLayout( const Reference< XTitle >& rxTitle, + const ModelRef< LayoutModel >& rxLayout, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx ) +{ + OSL_ENSURE( rxTitle.is(), "ConverterRoot::registerTitleLayout - missing title object" ); + TitleLayoutInfo& rTitleInfo = mxData->maTitles[ TitleKey( eObjType, nMainIdx, nSubIdx ) ]; + OSL_ENSURE( rTitleInfo.mpGetShape, "ConverterRoot::registerTitleLayout - invalid title key" ); + rTitleInfo.mxTitle = rxTitle; + rTitleInfo.mxLayout = rxLayout; +} + +void ConverterRoot::convertTitlePositions() +{ + try + { + Reference< cssc::XChartDocument > xChart1Doc( mxData->mxDoc, UNO_QUERY_THROW ); + for( ConverterData::TitleMap::iterator aIt = mxData->maTitles.begin(), aEnd = mxData->maTitles.end(); aIt != aEnd; ++aIt ) + aIt->second.convertTitlePos( *this, xChart1Doc ); + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +namespace { + +/** Returns a position value in the chart area in 1/100 mm. */ +sal_Int32 lclCalcPosition( sal_Int32 nChartSize, double fPos, sal_Int32 nPosMode ) +{ + switch( nPosMode ) + { + case XML_edge: // absolute start position as factor of chart size + return getLimitedValue< sal_Int32, double >( nChartSize * fPos + 0.5, 0, nChartSize ); + case XML_factor: // position relative to object default position + OSL_ENSURE( false, "lclCalcPosition - relative positioning not supported" ); + return -1; + }; + + OSL_ENSURE( false, "lclCalcPosition - unknown positioning mode" ); + return -1; +} + +/** Returns a size value in the chart area in 1/100 mm. */ +sal_Int32 lclCalcSize( sal_Int32 nPos, sal_Int32 nChartSize, double fSize, sal_Int32 nSizeMode ) +{ + sal_Int32 nValue = getLimitedValue< sal_Int32, double >( nChartSize * fSize + 0.5, 0, nChartSize ); + switch( nSizeMode ) + { + case XML_factor: // size as factor of chart size + return nValue; + case XML_edge: // absolute end position as factor of chart size + return nValue - nPos + 1; + }; + + OSL_ENSURE( false, "lclCalcSize - unknown size mode" ); + return -1; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +LayoutConverter::LayoutConverter( const ConverterRoot& rParent, LayoutModel& rModel ) : + ConverterBase< LayoutModel >( rParent, rModel ) +{ +} + +LayoutConverter::~LayoutConverter() +{ +} + +bool LayoutConverter::calcAbsRectangle( Rectangle& orRect ) const +{ + if( !mrModel.mbAutoLayout ) + { + const Size& rChartSize = getChartSize(); + orRect.X = lclCalcPosition( rChartSize.Width, mrModel.mfX, mrModel.mnXMode ); + orRect.Y = lclCalcPosition( rChartSize.Height, mrModel.mfY, mrModel.mnYMode ); + if( (orRect.X >= 0) && (orRect.Y >= 0) ) + { + orRect.Width = lclCalcSize( orRect.X, rChartSize.Width, mrModel.mfW, mrModel.mnWMode ); + orRect.Height = lclCalcSize( orRect.Y, rChartSize.Height, mrModel.mfH, mrModel.mnHMode ); + return (orRect.Width > 0) && (orRect.Height > 0); + } + } + return false; +} + +bool LayoutConverter::convertFromModel( PropertySet& rPropSet ) +{ + if( !mrModel.mbAutoLayout && + (mrModel.mnXMode == XML_edge) && (mrModel.mfX >= 0.0) && + (mrModel.mnYMode == XML_edge) && (mrModel.mfY >= 0.0) ) + { + RelativePosition aPos; + aPos.Primary = getLimitedValue< double, double >( mrModel.mfX, 0.0, 1.0 ); + aPos.Secondary = getLimitedValue< double, double >( mrModel.mfY, 0.0, 1.0 ); + aPos.Anchor = ::com::sun::star::drawing::Alignment_TOP_LEFT; + rPropSet.setProperty( PROP_RelativePosition, aPos ); + return true; + } + return false; +} + +bool LayoutConverter::convertFromModel( const Reference< XShape >& rxShape, double fRotationAngle ) +{ + if( !mrModel.mbAutoLayout ) + { + const Size& rChartSize = getChartSize(); + Point aShapePos( + lclCalcPosition( rChartSize.Width, mrModel.mfX, mrModel.mnXMode ), + lclCalcPosition( rChartSize.Height, mrModel.mfY, mrModel.mnYMode ) ); + if( (aShapePos.X >= 0) && (aShapePos.Y >= 0) ) + { + // the call to XShape.getSize() may recalc the chart view + Size aShapeSize = rxShape->getSize(); + // rotated shapes need special handling... + double fSin = fabs( sin( fRotationAngle * F_PI180 ) ); + // add part of height to X direction, if title is rotated down + if( fRotationAngle > 180.0 ) + aShapePos.X += static_cast< sal_Int32 >( fSin * aShapeSize.Height + 0.5 ); + // add part of width to Y direction, if title is rotated up + else if( fRotationAngle > 0.0 ) + aShapePos.Y += static_cast< sal_Int32 >( fSin * aShapeSize.Width + 0.5 ); + // set the resulting position at the shape + rxShape->setPosition( aShapePos ); + return true; + } + } + return false; +} + // ============================================================================ } // namespace chart diff --git a/oox/source/drawingml/chart/modelbase.cxx b/oox/source/drawingml/chart/modelbase.cxx index 3aa6b1f0047f..c182d8e3e410 100644 --- a/oox/source/drawingml/chart/modelbase.cxx +++ b/oox/source/drawingml/chart/modelbase.cxx @@ -50,6 +50,26 @@ void NumberFormat::setAttributes( const AttributeList& rAttribs ) // ============================================================================ +LayoutModel::LayoutModel() : + mfX( 0.0 ), + mfY( 0.0 ), + mfW( 0.0 ), + mfH( 0.0 ), + mnXMode( XML_factor ), + mnYMode( XML_factor ), + mnWMode( XML_factor ), + mnHMode( XML_factor ), + mnTarget( XML_outer ), + mbAutoLayout( true ) +{ +} + +LayoutModel::~LayoutModel() +{ +} + +// ============================================================================ + } // namespace chart } // namespace drawingml } // namespace oox diff --git a/oox/source/drawingml/chart/objectformatter.cxx b/oox/source/drawingml/chart/objectformatter.cxx index 5b898d4da6ed..d96e2d43dd6f 100644 --- a/oox/source/drawingml/chart/objectformatter.cxx +++ b/oox/source/drawingml/chart/objectformatter.cxx @@ -1142,18 +1142,19 @@ void ObjectFormatter::convertTextRotation( PropertySet& rPropSet, const ModelRef { if( rxTextProp.is() ) { - /* Chart2 expects rotation angle as double value in range of [0,360). - OOXML counts clockwise, Chart2 counts counterclockwise. */ - double fAngle = rxTextProp->getTextProperties().moRotation.get( 0 ); - fAngle = getDoubleIntervalValue< double >( -fAngle / 60000.0, 0.0, 360.0 ); - rPropSet.setProperty( PROP_TextRotation, fAngle ); - + bool bStacked = false; if( bSupportsStacked ) { sal_Int32 nVert = rxTextProp->getTextProperties().moVert.get( XML_horz ); - bool bStacked = (nVert == XML_wordArtVert) || (nVert == XML_wordArtVertRtl); + bStacked = (nVert == XML_wordArtVert) || (nVert == XML_wordArtVertRtl); rPropSet.setProperty( PROP_StackCharacters, bStacked ); } + + /* Chart2 expects rotation angle as double value in range of [0,360). + OOXML counts clockwise, Chart2 counts counterclockwise. */ + double fAngle = static_cast< double >( bStacked ? 0 : rxTextProp->getTextProperties().moRotation.get( 0 ) ); + fAngle = getDoubleIntervalValue< double >( -fAngle / 60000.0, 0.0, 360.0 ); + rPropSet.setProperty( PROP_TextRotation, fAngle ); } } @@ -1195,12 +1196,12 @@ void ObjectFormatter::convertAutomaticFill( PropertySet& rPropSet, ObjectType eO pFormat->convertAutomaticFill( rPropSet, nSeriesIdx ); } -bool ObjectFormatter::isAutomaticLine( const ModelRef< Shape >& rxShapeProp ) +/*static*/ bool ObjectFormatter::isAutomaticLine( const ModelRef< Shape >& rxShapeProp ) { return !rxShapeProp || !rxShapeProp->getLineProperties().maLineFill.moFillType.has(); } -bool ObjectFormatter::isAutomaticFill( const ModelRef< Shape >& rxShapeProp ) +/*static*/ bool ObjectFormatter::isAutomaticFill( const ModelRef< Shape >& rxShapeProp ) { return !rxShapeProp || !rxShapeProp->getFillProperties().moFillType.has(); } diff --git a/oox/source/drawingml/chart/plotareaconverter.cxx b/oox/source/drawingml/chart/plotareaconverter.cxx index f69fde409c0e..c3f74899ed97 100644 --- a/oox/source/drawingml/chart/plotareaconverter.cxx +++ b/oox/source/drawingml/chart/plotareaconverter.cxx @@ -29,6 +29,8 @@ #include <com/sun/star/drawing/Direction3D.hpp> #include <com/sun/star/drawing/ProjectionMode.hpp> #include <com/sun/star/drawing/ShadeMode.hpp> +#include <com/sun/star/chart/XChartDocument.hpp> +#include <com/sun/star/chart/XDiagramPositioning.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> #include <com/sun/star/chart2/XDiagram.hpp> @@ -42,6 +44,7 @@ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::awt::Rectangle; using ::com::sun::star::chart2::XCoordinateSystem; using ::com::sun::star::chart2::XCoordinateSystemContainer; using ::com::sun::star::chart2::XDiagram; @@ -54,14 +57,15 @@ namespace chart { namespace { -/** Axes set model. This is a helper class for the plot area converter. */ +/** Axes set model. This is a helper for the plot area converter collecting all + type groups and axes of the primary or secondary axes set. */ struct AxesSetModel { typedef ModelVector< TypeGroupModel > TypeGroupVector; typedef ModelMap< sal_Int32, AxisModel > AxisMap; - TypeGroupVector maTypeGroups; - AxisMap maAxes; + TypeGroupVector maTypeGroups; /// All type groups containing data series. + AxisMap maAxes; /// All axes mapped by API axis type. inline explicit AxesSetModel() {} inline ~AxesSetModel() {} @@ -90,11 +94,14 @@ public: inline bool is3dChart() const { return mb3dChart; } /** Returns true, if chart type supports wall and floor format in 3D mode. */ inline bool isWall3dChart() const { return mbWall3dChart; } + /** Returns true, if chart is a pie chart or doughnut chart. */ + inline bool isPieChart() const { return mbPieChart; } private: ::rtl::OUString maAutoTitle; bool mb3dChart; bool mbWall3dChart; + bool mbPieChart; }; // ---------------------------------------------------------------------------- @@ -102,7 +109,8 @@ private: AxesSetConverter::AxesSetConverter( const ConverterRoot& rParent, AxesSetModel& rModel ) : ConverterBase< AxesSetModel >( rParent, rModel ), mb3dChart( false ), - mbWall3dChart( false ) + mbWall3dChart( false ), + mbPieChart( false ) { } @@ -159,6 +167,7 @@ void AxesSetConverter::convertFromModel( const Reference< XDiagram >& rxDiagram, // 3D view settings mb3dChart = rFirstTypeGroup.is3dChart(); mbWall3dChart = rFirstTypeGroup.isWall3dChart(); + mbPieChart = rFirstTypeGroup.getTypeInfo().meTypeCategory == TYPECATEGORY_PIE; if( mb3dChart ) { View3DConverter aView3DConv( *this, rView3DModel ); @@ -305,7 +314,8 @@ void WallFloorConverter::convertFromModel( const Reference< XDiagram >& rxDiagra PlotAreaConverter::PlotAreaConverter( const ConverterRoot& rParent, PlotAreaModel& rModel ) : ConverterBase< PlotAreaModel >( rParent, rModel ), mb3dChart( false ), - mbWall3dChart( false ) + mbWall3dChart( false ), + mbPieChart( false ) { } @@ -392,6 +402,7 @@ void PlotAreaConverter::convertFromModel( View3DModel& rView3DModel ) maAutoTitle = aAxesSetConv.getAutomaticTitle(); mb3dChart = aAxesSetConv.is3dChart(); mbWall3dChart = aAxesSetConv.isWall3dChart(); + mbPieChart = aAxesSetConv.isPieChart(); } else { @@ -407,6 +418,35 @@ void PlotAreaConverter::convertFromModel( View3DModel& rView3DModel ) } } +void PlotAreaConverter::convertPositionFromModel() +{ + LayoutModel& rLayout = mrModel.mxLayout.getOrCreate(); + LayoutConverter aLayoutConv( *this, rLayout ); + Rectangle aDiagramRect; + if( aLayoutConv.calcAbsRectangle( aDiagramRect ) ) try + { + namespace cssc = ::com::sun::star::chart; + Reference< cssc::XChartDocument > xChart1Doc( getChartDocument(), UNO_QUERY_THROW ); + Reference< cssc::XDiagramPositioning > xPositioning( xChart1Doc->getDiagram(), UNO_QUERY_THROW ); + // for pie charts, always set inner plot area size to exclude the data labels as Excel does + sal_Int32 nTarget = (mbPieChart && (rLayout.mnTarget == XML_outer)) ? XML_inner : rLayout.mnTarget; + switch( nTarget ) + { + case XML_inner: + xPositioning->setDiagramPositionExcludingAxes( aDiagramRect ); + break; + case XML_outer: + xPositioning->setDiagramPositionIncludingAxes( aDiagramRect ); + break; + default: + OSL_ENSURE( false, "PlotAreaConverter::convertPositionFromModel - unknown positioning target" ); + } + } + catch( Exception& ) + { + } +} + // ============================================================================ } // namespace chart diff --git a/oox/source/drawingml/chart/seriesconverter.cxx b/oox/source/drawingml/chart/seriesconverter.cxx index a4cf7c1f3eb2..717a3972550e 100644 --- a/oox/source/drawingml/chart/seriesconverter.cxx +++ b/oox/source/drawingml/chart/seriesconverter.cxx @@ -344,6 +344,23 @@ Reference< XLabeledDataSequence > ErrorBarConverter::createLabeledDataSequence( // ============================================================================ +TrendlineLabelConverter::TrendlineLabelConverter( const ConverterRoot& rParent, TrendlineLabelModel& rModel ) : + ConverterBase< TrendlineLabelModel >( rParent, rModel ) +{ +} + +TrendlineLabelConverter::~TrendlineLabelConverter() +{ +} + +void TrendlineLabelConverter::convertFromModel( PropertySet& rPropSet ) +{ + // formatting + getFormatter().convertFormatting( rPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_TRENDLINELABEL ); +} + +// ============================================================================ + TrendlineConverter::TrendlineConverter( const ConverterRoot& rParent, TrendlineModel& rModel ) : ConverterBase< TrendlineModel >( rParent, rModel ) { @@ -385,8 +402,8 @@ void TrendlineConverter::convertFromModel( const Reference< XDataSeries >& rxDat // #i83100# formatting of the equation text box if( mrModel.mbDispEquation || mrModel.mbDispRSquared ) { - TrendlineLabelModel& rLabel = mrModel.mxLabel.getOrCreate(); - getFormatter().convertFormatting( aLabelProp, rLabel.mxShapeProp, rLabel.mxTextProp, OBJECTTYPE_TRENDLINELABEL ); + TrendlineLabelConverter aLabelConv( *this, mrModel.mxLabel.getOrCreate() ); + aLabelConv.convertFromModel( aLabelProp ); } // unsupported: #i5085# manual trendline size diff --git a/oox/source/drawingml/chart/titlecontext.cxx b/oox/source/drawingml/chart/titlecontext.cxx index e9007e4d53d7..963ccdad595a 100644 --- a/oox/source/drawingml/chart/titlecontext.cxx +++ b/oox/source/drawingml/chart/titlecontext.cxx @@ -41,65 +41,6 @@ namespace chart { // ============================================================================ -LayoutContext::LayoutContext( ContextHandler2Helper& rParent, LayoutModel& rModel ) : - ContextBase< LayoutModel >( rParent, rModel ) -{ -} - -LayoutContext::~LayoutContext() -{ -} - -ContextHandlerRef LayoutContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) -{ - switch( getCurrentElement() ) - { - case C_TOKEN( layout ): - switch( nElement ) - { - case C_TOKEN( manualLayout ): - return this; - } - break; - - case C_TOKEN( manualLayout ): - switch( nElement ) - { - case C_TOKEN( x ): - mrModel.mfX = rAttribs.getDouble( XML_val, 0.0 ); - return 0; - case C_TOKEN( y ): - mrModel.mfY = rAttribs.getDouble( XML_val, 0.0 ); - return 0; - case C_TOKEN( w ): - mrModel.mfW = rAttribs.getDouble( XML_val, 0.0 ); - return 0; - case C_TOKEN( h ): - mrModel.mfH = rAttribs.getDouble( XML_val, 0.0 ); - return 0; - case C_TOKEN( xMode ): - mrModel.mnXMode = rAttribs.getToken( XML_val, XML_factor ); - return 0; - case C_TOKEN( yMode ): - mrModel.mnYMode = rAttribs.getToken( XML_val, XML_factor ); - return 0; - case C_TOKEN( wMode ): - mrModel.mnWMode = rAttribs.getToken( XML_val, XML_factor ); - return 0; - case C_TOKEN( hMode ): - mrModel.mnHMode = rAttribs.getToken( XML_val, XML_factor ); - return 0; - case C_TOKEN( layoutTarget ): - mrModel.mnTarget = rAttribs.getToken( XML_val, XML_outer ); - return 0; - } - break; - } - return 0; -} - -// ============================================================================ - TextContext::TextContext( ContextHandler2Helper& rParent, TextModel& rModel ) : ContextBase< TextModel >( rParent, rModel ) { diff --git a/oox/source/drawingml/chart/titleconverter.cxx b/oox/source/drawingml/chart/titleconverter.cxx index 6316ee5f7ee4..bca53f1a2c01 100644 --- a/oox/source/drawingml/chart/titleconverter.cxx +++ b/oox/source/drawingml/chart/titleconverter.cxx @@ -26,11 +26,14 @@ ************************************************************************/ #include "oox/drawingml/chart/titleconverter.hxx" +#include <com/sun/star/chart2/LegendExpansion.hpp> +#include <com/sun/star/chart2/LegendPosition.hpp> #include <com/sun/star/chart2/XDiagram.hpp> #include <com/sun/star/chart2/XFormattedString.hpp> #include <com/sun/star/chart2/XLegend.hpp> #include <com/sun/star/chart2/XTitle.hpp> #include <com/sun/star/chart2/XTitled.hpp> +#include "properties.hxx" #include "oox/drawingml/textbody.hxx" #include "oox/drawingml/textparagraph.hxx" #include "oox/drawingml/chart/datasourceconverter.hxx" @@ -41,6 +44,7 @@ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::awt::Rectangle; using ::com::sun::star::chart2::XDiagram; using ::com::sun::star::chart2::XFormattedString; using ::com::sun::star::chart2::XLegend; @@ -149,7 +153,7 @@ TitleConverter::~TitleConverter() { } -void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType ) +void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, const OUString& rAutoTitle, ObjectType eObjType, sal_Int32 nMainIdx, sal_Int32 nSubIdx ) { if( rxTitled.is() ) { @@ -172,6 +176,9 @@ void TitleConverter::convertFromModel( const Reference< XTitled >& rxTitled, con OSL_ENSURE( !mrModel.mxTextProp || !rText.mxTextBody, "TitleConverter::convertFromModel - multiple text properties" ); ModelRef< TextBody > xTextProp = mrModel.mxTextProp.is() ? mrModel.mxTextProp : rText.mxTextBody; getFormatter().convertTextRotation( aPropSet, xTextProp, true ); + + // register the title and layout data for conversion of position + registerTitleLayout( xTitle, mrModel.mxLayout, eObjType, nMainIdx, nSubIdx ); } catch( Exception& ) { @@ -194,13 +201,64 @@ void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) { if( rxDiagram.is() ) try { + namespace cssc2 = ::com::sun::star::chart2; + // create the legend Reference< XLegend > xLegend( createInstance( CREATE_OUSTRING( "com.sun.star.chart2.Legend" ) ), UNO_QUERY_THROW ); rxDiagram->setLegend( xLegend ); + PropertySet aPropSet( xLegend ); + aPropSet.setProperty( PROP_Show, true ); // legend formatting - PropertySet aPropSet( xLegend ); getFormatter().convertFormatting( aPropSet, mrModel.mxShapeProp, mrModel.mxTextProp, OBJECTTYPE_LEGEND ); + + // predefined legend position and expansion + cssc2::LegendPosition eLegendPos = cssc2::LegendPosition_CUSTOM; + cssc2::LegendExpansion eLegendExpand = cssc2::LegendExpansion_HIGH; + switch( mrModel.mnPosition ) + { + case XML_l: + eLegendPos = cssc2::LegendPosition_LINE_START; + eLegendExpand = cssc2::LegendExpansion_HIGH; + break; + case XML_r: + eLegendPos = cssc2::LegendPosition_LINE_END; + eLegendExpand = cssc2::LegendExpansion_HIGH; + break; + case XML_t: + eLegendPos = cssc2::LegendPosition_PAGE_START; + eLegendExpand = cssc2::LegendExpansion_WIDE; + break; + case XML_b: + eLegendPos = cssc2::LegendPosition_PAGE_END; + eLegendExpand = cssc2::LegendExpansion_WIDE; + break; + case XML_tr: + eLegendPos = cssc2::LegendPosition_LINE_END; // top-right not supported + eLegendExpand = cssc2::LegendExpansion_HIGH; + break; + } + + // manual positioning + LayoutModel& rLayout = mrModel.mxLayout.getOrCreate(); + LayoutConverter aLayoutConv( *this, rLayout ); + aLayoutConv.convertFromModel( aPropSet ); + Rectangle aLegendRect; + if( aLayoutConv.calcAbsRectangle( aLegendRect ) ) + { + // #i71697# it is not possible to set the size directly, do some magic here + double fRatio = static_cast< double >( aLegendRect.Width ) / aLegendRect.Height; + if( fRatio > 1.5 ) + eLegendExpand = cssc2::LegendExpansion_WIDE; + else if( fRatio < 0.75 ) + eLegendExpand = cssc2::LegendExpansion_HIGH; + else + eLegendExpand = cssc2::LegendExpansion_BALANCED; + } + + // set position and expansion properties + aPropSet.setProperty( PROP_AnchorPosition, eLegendPos ); + aPropSet.setProperty( PROP_Expansion, eLegendExpand ); } catch( Exception& ) { diff --git a/oox/source/drawingml/chart/titlemodel.cxx b/oox/source/drawingml/chart/titlemodel.cxx index 51c51a62c4b7..bb5501e05f32 100644 --- a/oox/source/drawingml/chart/titlemodel.cxx +++ b/oox/source/drawingml/chart/titlemodel.cxx @@ -33,25 +33,6 @@ namespace chart { // ============================================================================ -LayoutModel::LayoutModel() : - mfX( 0.0 ), - mfY( 0.0 ), - mfW( 0.0 ), - mfH( 0.0 ), - mnXMode( XML_factor ), - mnYMode( XML_factor ), - mnWMode( XML_factor ), - mnHMode( XML_factor ), - mnTarget( XML_outer ) -{ -} - -LayoutModel::~LayoutModel() -{ -} - -// ============================================================================ - TextModel::TextModel() { } |