diff options
author | Daniel Rentz <dr@openoffice.org> | 2010-06-17 11:32:18 +0200 |
---|---|---|
committer | Daniel Rentz <dr@openoffice.org> | 2010-06-17 11:32:18 +0200 |
commit | f3f36bb0e3626fa4016184849c8bbf20b207a9b3 (patch) | |
tree | 39c299074d11b08abb5d067157e728e05a45f3f2 /sc/source/filter/excel/xichart.cxx | |
parent | d28ea3c4c5ff5ff51e89016fe53dcf53426e337e (diff) | |
parent | 5729138f6f974939f75ce5f9c4191f3d6680a22b (diff) |
mib16: rebase to m82
Diffstat (limited to 'sc/source/filter/excel/xichart.cxx')
-rwxr-xr-x[-rw-r--r--] | sc/source/filter/excel/xichart.cxx | 433 |
1 files changed, 327 insertions, 106 deletions
diff --git a/sc/source/filter/excel/xichart.cxx b/sc/source/filter/excel/xichart.cxx index e7669abce05d..e9bfb8ca3f60 100644..100755 --- a/sc/source/filter/excel/xichart.cxx +++ b/sc/source/filter/excel/xichart.cxx @@ -37,12 +37,14 @@ #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/drawing/XShape.hpp> #include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/chart/ChartAxisArrangeOrderType.hpp> #include <com/sun/star/chart/ChartAxisLabelPosition.hpp> #include <com/sun/star/chart/ChartAxisMarkPosition.hpp> #include <com/sun/star/chart/ChartAxisPosition.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/XDiagram.hpp> #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> @@ -57,8 +59,11 @@ #include <com/sun/star/chart2/CurveStyle.hpp> #include <com/sun/star/chart2/DataPointGeometry3D.hpp> #include <com/sun/star/chart2/DataPointLabel.hpp> +#include <com/sun/star/chart2/LegendExpansion.hpp> +#include <com/sun/star/chart2/LegendPosition.hpp> #include <com/sun/star/chart2/StackingDirection.hpp> #include <com/sun/star/chart2/TickmarkStyle.hpp> +#include <com/sun/star/chart2/RelativePosition.hpp> #include <com/sun/star/chart/DataLabelPlacement.hpp> #include <com/sun/star/chart/ErrorBarStyle.hpp> #include <com/sun/star/chart/MissingValueTreatment.hpp> @@ -98,36 +103,41 @@ using ::com::sun::star::frame::XModel; using ::com::sun::star::util::XNumberFormatsSupplier; using ::com::sun::star::drawing::XDrawPage; using ::com::sun::star::drawing::XDrawPageSupplier; +using ::com::sun::star::drawing::XShape; +using ::com::sun::star::chart2::IncrementData; +using ::com::sun::star::chart2::RelativePosition; +using ::com::sun::star::chart2::ScaleData; +using ::com::sun::star::chart2::SubIncrement; +using ::com::sun::star::chart2::XAxis; using ::com::sun::star::chart2::XChartDocument; -using ::com::sun::star::chart2::XDiagram; -using ::com::sun::star::chart2::XCoordinateSystemContainer; -using ::com::sun::star::chart2::XCoordinateSystem; -using ::com::sun::star::chart2::XChartTypeContainer; using ::com::sun::star::chart2::XChartType; -using ::com::sun::star::chart2::XDataSeriesContainer; +using ::com::sun::star::chart2::XChartTypeContainer; +using ::com::sun::star::chart2::XCoordinateSystem; +using ::com::sun::star::chart2::XCoordinateSystemContainer; using ::com::sun::star::chart2::XDataSeries; +using ::com::sun::star::chart2::XDataSeriesContainer; +using ::com::sun::star::chart2::XDiagram; +using ::com::sun::star::chart2::XFormattedString; +using ::com::sun::star::chart2::XLegend; using ::com::sun::star::chart2::XRegressionCurve; using ::com::sun::star::chart2::XRegressionCurveContainer; -using ::com::sun::star::chart2::XAxis; using ::com::sun::star::chart2::XScaling; -using ::com::sun::star::chart2::ScaleData; -using ::com::sun::star::chart2::IncrementData; -using ::com::sun::star::chart2::SubIncrement; -using ::com::sun::star::chart2::XLegend; -using ::com::sun::star::chart2::XTitled; using ::com::sun::star::chart2::XTitle; -using ::com::sun::star::chart2::XFormattedString; +using ::com::sun::star::chart2::XTitled; using ::com::sun::star::chart2::data::XDataProvider; using ::com::sun::star::chart2::data::XDataReceiver; +using ::com::sun::star::chart2::data::XDataSequence; using ::com::sun::star::chart2::data::XDataSink; using ::com::sun::star::chart2::data::XLabeledDataSequence; -using ::com::sun::star::chart2::data::XDataSequence; using ::formula::FormulaToken; using ::formula::StackVar; +namespace cssc = ::com::sun::star::chart; +namespace cssc2 = ::com::sun::star::chart2; + // Helpers ==================================================================== namespace { @@ -158,28 +168,18 @@ void lclSetExpValueOrClearAny( Any& rAny, double fValue, bool bLogScale, bool bC // Common ===================================================================== /** Stores global data needed in various classes of the Chart import filter. */ -class XclImpChRootData : public XclChRootData +struct XclImpChRootData : public XclChRootData { -public: - explicit XclImpChRootData( XclImpChChart* pChartData ); + XclImpChChart& mrChartData; /// The chart data object. - /** Returns a reference to the parent chart data object. */ - inline XclImpChChart& GetChartData() const { return *mpChartData; } - -private: - XclImpChChart* mpChartData; /// Pointer to the chart data object. + inline explicit XclImpChRootData( XclImpChChart& rChartData ) : mrChartData( rChartData ) {} }; -XclImpChRootData::XclImpChRootData( XclImpChChart* pChartData ) : - mpChartData( pChartData ) -{ -} - // ---------------------------------------------------------------------------- -XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart* pChartData ) : +XclImpChRoot::XclImpChRoot( const XclImpRoot& rRoot, XclImpChChart& rChartData ) : XclImpRoot( rRoot ), - mxChData( new XclImpChRootData( pChartData ) ) + mxChData( new XclImpChRootData( rChartData ) ) { } @@ -189,22 +189,22 @@ XclImpChRoot::~XclImpChRoot() XclImpChChart& XclImpChRoot::GetChartData() const { - return mxChData->GetChartData(); + return mxChData->mrChartData; } const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( XclChTypeId eType ) const { - return mxChData->GetTypeInfoProvider().GetTypeInfo( eType ); + return mxChData->mxTypeInfoProv->GetTypeInfo( eType ); } const XclChTypeInfo& XclImpChRoot::GetChartTypeInfo( sal_uInt16 nRecId ) const { - return mxChData->GetTypeInfoProvider().GetTypeInfoFromRecId( nRecId ); + return mxChData->mxTypeInfoProv->GetTypeInfoFromRecId( nRecId ); } const XclChFormatInfo& XclImpChRoot::GetFormatInfo( XclChObjectType eObjType ) const { - return mxChData->GetFormatInfoProvider().GetFormatInfo( eObjType ); + return mxChData->mxFmtInfoProv->GetFormatInfo( eObjType ); } Color XclImpChRoot::GetFontAutoColor() const @@ -225,10 +225,10 @@ Color XclImpChRoot::GetSeriesFillAutoColor( sal_uInt16 nFormatIdx ) const return ScfTools::GetMixedColor( aColor, rPal.GetColor( EXC_COLOR_CHWINDOWBACK ), nTrans ); } -void XclImpChRoot::InitConversion( Reference< XChartDocument > xChartDoc ) const +void XclImpChRoot::InitConversion( Reference< XChartDocument > xChartDoc, const Rectangle& rChartRect ) const { // create formatting object tables - mxChData->InitConversion( xChartDoc ); + mxChData->InitConversion( GetRoot(), xChartDoc, rChartRect ); // lock the model to suppress any internal updates Reference< XModel > xModel( xChartDoc, UNO_QUERY ); @@ -255,7 +255,7 @@ void XclImpChRoot::FinishConversion( XclImpDffConverter& rDffConv ) const { rDffConv.Progress( EXC_CHART_PROGRESS_SIZE ); // unlock the model - Reference< XModel > xModel( mxChData->GetChartDoc(), UNO_QUERY ); + Reference< XModel > xModel( mxChData->mxChartDoc, UNO_QUERY ); if( xModel.is() ) xModel->unlockControllers(); rDffConv.Progress( EXC_CHART_PROGRESS_SIZE ); @@ -265,14 +265,48 @@ void XclImpChRoot::FinishConversion( XclImpDffConverter& rDffConv ) const Reference< XDataProvider > XclImpChRoot::GetDataProvider() const { - return mxChData->GetChartDoc()->getDataProvider(); + return mxChData->mxChartDoc->getDataProvider(); +} + +Reference< XShape > XclImpChRoot::GetTitleShape( const XclChTextKey& rTitleKey ) const +{ + return mxChData->GetTitleShape( rTitleKey ); +} + +sal_Int32 XclImpChRoot::CalcHmmFromChartX( sal_Int32 nPosX ) const +{ + return static_cast< sal_Int32 >( mxChData->mfUnitSizeX * nPosX + mxChData->mnBorderGapX + 0.5 ); +} + +sal_Int32 XclImpChRoot::CalcHmmFromChartY( sal_Int32 nPosY ) const +{ + return static_cast< sal_Int32 >( mxChData->mfUnitSizeY * nPosY + mxChData->mnBorderGapY + 0.5 ); +} + +::com::sun::star::awt::Rectangle XclImpChRoot::CalcHmmFromChartRect( const XclChRectangle& rRect ) const +{ + return ::com::sun::star::awt::Rectangle( + CalcHmmFromChartX( rRect.mnX ), + CalcHmmFromChartY( rRect.mnY ), + CalcHmmFromChartX( rRect.mnWidth ), + CalcHmmFromChartY( rRect.mnHeight ) ); +} + +double XclImpChRoot::CalcRelativeFromChartX( sal_Int32 nPosX ) const +{ + return static_cast< double >( CalcHmmFromChartX( nPosX ) ) / mxChData->maChartRect.GetWidth(); +} + +double XclImpChRoot::CalcRelativeFromChartY( sal_Int32 nPosY ) const +{ + return static_cast< double >( CalcHmmFromChartY( nPosY ) ) / mxChData->maChartRect.GetHeight(); } void XclImpChRoot::ConvertLineFormat( ScfPropertySet& rPropSet, const XclChLineFormat& rLineFmt, XclChPropertyMode ePropMode ) const { GetChartPropSetHelper().WriteLineProperties( - rPropSet, mxChData->GetLineDashTable(), rLineFmt, ePropMode ); + rPropSet, *mxChData->mxLineDashTable, rLineFmt, ePropMode ); } void XclImpChRoot::ConvertAreaFormat( ScfPropertySet& rPropSet, @@ -286,7 +320,7 @@ void XclImpChRoot::ConvertEscherFormat( ScfPropertySet& rPropSet, XclChPropertyMode ePropMode ) const { GetChartPropSetHelper().WriteEscherProperties( rPropSet, - mxChData->GetGradientTable(), mxChData->GetHatchTable(), mxChData->GetBitmapTable(), + *mxChData->mxGradientTable, *mxChData->mxHatchTable, *mxChData->mxBitmapTable, rEscherFmt, rPicFmt, ePropMode ); } @@ -357,7 +391,13 @@ void XclImpChGroupBase::SkipBlock( XclImpStream& rStrm ) void XclImpChFramePos::ReadChFramePos( XclImpStream& rStrm ) { - rStrm >> maData.mnObjType >> maData.mnSizeMode >> maData.maRect; + rStrm >> maData.mnTLMode >> maData.mnBRMode; + /* According to the spec, the upper 16 bits of all members in the + rectangle are unused and may contain garbage. */ + maData.maRect.mnX = rStrm.ReadInt16(); rStrm.Ignore( 2 ); + maData.maRect.mnY = rStrm.ReadInt16(); rStrm.Ignore( 2 ); + maData.maRect.mnWidth = rStrm.ReadInt16(); rStrm.Ignore( 2 ); + maData.maRect.mnHeight = rStrm.ReadInt16(); rStrm.Ignore( 2 ); } // ---------------------------------------------------------------------------- @@ -862,9 +902,7 @@ void XclImpChText::ReadHeaderRecord( XclImpStream& rStrm ) // #116397# BIFF8: index into palette used instead of RGB data maData.maTextColor = GetPalette().GetColor( rStrm.ReaduInt16() ); // placement and rotation - rStrm >> maData.mnPlacement >> maData.mnRotation; - // lower 4 bits used for placement, other bits contain garbage - maData.mnPlacement &= 0x000F; + rStrm >> maData.mnFlags2 >> maData.mnRotation; } else { @@ -878,6 +916,10 @@ void XclImpChText::ReadSubRecord( XclImpStream& rStrm ) { switch( rStrm.GetRecId() ) { + case EXC_ID_CHFRAMEPOS: + mxFramePos.reset( new XclImpChFramePos ); + mxFramePos->ReadChFramePos( rStrm ); + break; case EXC_ID_CHFONT: mxFont.reset( new XclImpChFont ); mxFont->ReadChFont( rStrm ); @@ -1002,8 +1044,7 @@ void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeIn bool bShowSymbol = bShowAny && ::get_flag( maData.mnFlags, EXC_CHTEXT_SHOWSYMBOL ); // create API struct for label values, set API label separator - namespace cssc = ::com::sun::star::chart2; - cssc::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol ); + cssc2::DataPointLabel aPointLabel( bShowValue, bShowPercent, bShowCateg, bShowSymbol ); rPropSet.SetProperty( EXC_CHPROP_LABEL, aPointLabel ); String aSep = mxLabelProps.is() ? mxLabelProps->maSeparator : String( sal_Unicode( '\n' ) ); if( aSep.Len() == 0 ) @@ -1016,9 +1057,9 @@ void XclImpChText::ConvertDataLabel( ScfPropertySet& rPropSet, const XclChTypeIn ConvertFont( rPropSet ); ConvertRotation( rPropSet, false ); // label placement - using namespace ::com::sun::star::chart::DataLabelPlacement; + using namespace cssc::DataLabelPlacement; sal_Int32 nPlacement = rTypeInfo.mnDefaultLabelPos; - switch( maData.mnPlacement ) + switch( ::extract_value< sal_uInt16 >( maData.mnFlags2, 0, 4 ) ) { case EXC_CHTEXT_POS_DEFAULT: nPlacement = rTypeInfo.mnDefaultLabelPos; break; case EXC_CHTEXT_POS_OUTSIDE: nPlacement = OUTSIDE; break; @@ -1064,6 +1105,62 @@ Reference< XTitle > XclImpChText::CreateTitle() const return xTitle; } +void XclImpChText::ConvertTitlePosition( const XclChTextKey& rTitleKey ) const +{ + if( !mxFramePos ) return; + + const XclChFramePos& rPosData = mxFramePos->GetFramePosData(); + OSL_ENSURE( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rPosData.mnBRMode == EXC_CHFRAMEPOS_PARENT), + "XclImpChText::ConvertTitlePosition - unexpected frame position mode" ); + + /* Check if title is moved manually. To get the actual position of the + title, we do some kind of hack and use the values from the CHTEXT + record, effectively ignoring the contents of the CHFRAMEPOS record + which contains the position relative to the default title position + (according to the spec, the CHFRAMEPOS supersedes the CHTEXT record). + Especially when it comes to axis titles, things would become very + complicated here, because the relative title position is stored in a + measurement unit that is dependent on the size of the inner plot area, + the interpretation of the X and Y coordinate is dependent on the + direction of the axis, and in 3D charts, and the title default + positions are dependent on the 3D view settings (rotation, elevation, + and perspective). Thus, it is easier to assume that the creator has + written out the correct absolute position and size of the title in the + CHTEXT record. This is assured by checking that the shape size stored + in the CHTEXT record is non-zero. */ + if( (rPosData.mnTLMode == EXC_CHFRAMEPOS_PARENT) && + ((rPosData.maRect.mnX != 0) || (rPosData.maRect.mnY != 0)) && + (maData.maRect.mnWidth > 0) && (maData.maRect.mnHeight > 0) ) try + { + Reference< XShape > xTitleShape( GetTitleShape( rTitleKey ), UNO_SET_THROW ); + // the call to XShape.getSize() may recalc the chart view + ::com::sun::star::awt::Size aTitleSize = xTitleShape->getSize(); + // rotated titles need special handling... + sal_Int32 nScRot = XclTools::GetScRotation( GetRotation(), 0 ); + double fRad = nScRot * F_PI18000; + double fSin = fabs( sin( fRad ) ); + double fCos = fabs( cos( fRad ) ); + ::com::sun::star::awt::Size aBoundSize( + static_cast< sal_Int32 >( fCos * aTitleSize.Width + fSin * aTitleSize.Height + 0.5 ), + static_cast< sal_Int32 >( fSin * aTitleSize.Width + fCos * aTitleSize.Height + 0.5 ) ); + // calculate the title position from the values in the CHTEXT record + ::com::sun::star::awt::Point aTitlePos( + CalcHmmFromChartX( maData.maRect.mnX ), + CalcHmmFromChartY( maData.maRect.mnY ) ); + // add part of height to X direction, if title is rotated down (clockwise) + if( nScRot > 18000 ) + aTitlePos.X += static_cast< sal_Int32 >( fSin * aTitleSize.Height + 0.5 ); + // add part of width to Y direction, if title is rotated up (counterclockwise) + else if( nScRot > 0 ) + aTitlePos.Y += static_cast< sal_Int32 >( fSin * aTitleSize.Width + 0.5 ); + // set the resulting position at the title shape + xTitleShape->setPosition( aTitlePos ); + } + catch( Exception& ) + { + } +} + void XclImpChText::ReadChFrLabelProps( XclImpStream& rStrm ) { if( GetBiff() == EXC_BIFF8 ) @@ -1087,12 +1184,14 @@ void lclUpdateText( XclImpChTextRef& rxText, XclImpChTextRef xDefText ) rxText = xDefText; } -void lclFinalizeTitle( XclImpChTextRef& rxTitle, XclImpChTextRef xDefText ) +void lclFinalizeTitle( XclImpChTextRef& rxTitle, XclImpChTextRef xDefText, const String& rAutoTitle ) { /* Do not update a title, if it is not visible (if rxTitle is null). Existing reference indicates enabled title. */ if( rxTitle.is() ) { + if( !rxTitle->HasString() ) + rxTitle->SetString( rAutoTitle ); if( rxTitle->HasString() ) rxTitle->UpdateText( xDefText.get() ); else @@ -1544,7 +1643,6 @@ Reference< XPropertySet > XclImpChSerErrorBar::CreateErrorBar( const XclImpChSer aBarProp.SetBoolProperty( EXC_CHPROP_SHOWNEGATIVEERROR, pNegBar != 0 ); // type of displayed error - namespace cssc = ::com::sun::star::chart; switch( pPrimaryBar->maData.mnSourceType ) { case EXC_CHSERERR_PERCENT: @@ -2281,6 +2379,10 @@ void XclImpChLegend::ReadSubRecord( XclImpStream& rStrm ) { switch( rStrm.GetRecId() ) { + case EXC_ID_CHFRAMEPOS: + mxFramePos.reset( new XclImpChFramePos ); + mxFramePos->ReadChFramePos( rStrm ); + break; case EXC_ID_CHTEXT: mxText.reset( new XclImpChText( GetChRoot() ) ); mxText->ReadRecordGroup( rStrm ); @@ -2307,6 +2409,7 @@ Reference< XLegend > XclImpChLegend::CreateLegend() const if( xLegend.is() ) { ScfPropertySet aLegendProp( xLegend ); + aLegendProp.SetBoolProperty( EXC_CHPROP_SHOW, true ); // frame properties if( mxFrame.is() ) @@ -2314,8 +2417,69 @@ Reference< XLegend > XclImpChLegend::CreateLegend() const // text properties if( mxText.is() ) mxText->ConvertFont( aLegendProp ); - // special legend properties - GetChartPropSetHelper().WriteLegendProperties( aLegendProp, maData ); + + /* Legend position and size. Default positions are used only if the + plot area is positioned automatically (Excel sets the plot area to + manual mode, if the legend is moved or resized). With manual plot + areas, Excel ignores the value in maData.mnDockMode completely. */ + cssc2::LegendPosition eApiPos = cssc2::LegendPosition_CUSTOM; + cssc2::LegendExpansion eApiExpand = cssc2::LegendExpansion_BALANCED; + if( !GetChartData().IsManualPlotArea() ) switch( maData.mnDockMode ) + { + case EXC_CHLEGEND_LEFT: eApiPos = cssc2::LegendPosition_LINE_START; eApiExpand = cssc2::LegendExpansion_HIGH; break; + case EXC_CHLEGEND_RIGHT: eApiPos = cssc2::LegendPosition_LINE_END; eApiExpand = cssc2::LegendExpansion_HIGH; break; + case EXC_CHLEGEND_TOP: eApiPos = cssc2::LegendPosition_PAGE_START; eApiExpand = cssc2::LegendExpansion_WIDE; break; + case EXC_CHLEGEND_BOTTOM: eApiPos = cssc2::LegendPosition_PAGE_END; eApiExpand = cssc2::LegendExpansion_WIDE; break; + // top-right not supported + case EXC_CHLEGEND_CORNER: eApiPos = cssc2::LegendPosition_LINE_END; eApiExpand = cssc2::LegendExpansion_HIGH; break; + } + + // no automatic position: try to find the correct position and size + if( eApiPos == cssc2::LegendPosition_CUSTOM ) + { + const XclChFramePos* pFramePos = mxFramePos.is() ? &mxFramePos->GetFramePosData() : 0; + + /* Legend position. Only the settings from the CHFRAMEPOS record + are used by Excel, the position in the CHLEGEND record will be + ignored. */ + if( pFramePos ) + { + RelativePosition aRelPos; + aRelPos.Primary = CalcRelativeFromChartX( pFramePos->maRect.mnX ); + aRelPos.Secondary = CalcRelativeFromChartY( pFramePos->maRect.mnY ); + aRelPos.Anchor = ::com::sun::star::drawing::Alignment_TOP_LEFT; + aLegendProp.SetProperty( EXC_CHPROP_RELATIVEPOSITION, aRelPos ); + } + else + { + // no manual position found, just go for the default + eApiPos = cssc2::LegendPosition_LINE_END; + } + + + /* Legend size. #i71697# It is not possible to set the legend size + directly in the Chart, do some magic here. */ + if( !pFramePos || (pFramePos->mnBRMode != EXC_CHFRAMEPOS_ABSSIZE_POINTS) || + (pFramePos->maRect.mnWidth == 0) || (pFramePos->maRect.mnHeight == 0) ) + { + // automatic size: determine entry direction from flags + eApiExpand = ::get_flagvalue( maData.mnFlags, EXC_CHLEGEND_STACKED, + cssc2::LegendExpansion_HIGH, cssc2::LegendExpansion_WIDE ); + } + else + { + // legend size is given in points, not in chart units + double fRatio = static_cast< double >( pFramePos->maRect.mnWidth ) / pFramePos->maRect.mnHeight; + if( fRatio > 1.5 ) + eApiExpand = cssc2::LegendExpansion_WIDE; + else if( fRatio < 0.75 ) + eApiExpand = cssc2::LegendExpansion_HIGH; + else + eApiExpand = cssc2::LegendExpansion_BALANCED; + } + } + aLegendProp.SetProperty( EXC_CHPROP_ANCHORPOSITION, eApiPos ); + aLegendProp.SetProperty( EXC_CHPROP_EXPANSION, eApiExpand ); } return xLegend; } @@ -2358,7 +2522,8 @@ XclImpChTypeGroup::XclImpChTypeGroup( const XclImpChRoot& rRoot ) : void XclImpChTypeGroup::ReadHeaderRecord( XclImpStream& rStrm ) { - rStrm >> maData.maRect >> maData.mnFlags >> maData.mnGroupIdx; + rStrm.Ignore( 16 ); + rStrm >> maData.mnFlags >> maData.mnGroupIdx; } void XclImpChTypeGroup::ReadSubRecord( XclImpStream& rStrm ) @@ -2548,13 +2713,12 @@ void XclImpChTypeGroup::InsertDataSeries( Reference< XChartType > xChartType, if( xSeriesCont.is() && xSeries.is() ) { // series stacking mode - namespace cssc = ::com::sun::star::chart2; - cssc::StackingDirection eStacking = cssc::StackingDirection_NO_STACKING; + cssc2::StackingDirection eStacking = cssc2::StackingDirection_NO_STACKING; // stacked overrides deep-3d if( maType.IsStacked() || maType.IsPercent() ) - eStacking = cssc::StackingDirection_Y_STACKING; + eStacking = cssc2::StackingDirection_Y_STACKING; else if( Is3dDeepChart() ) - eStacking = cssc::StackingDirection_Z_STACKING; + eStacking = cssc2::StackingDirection_Z_STACKING; // additional series properties ScfPropertySet aSeriesProp( xSeries ); @@ -2674,11 +2838,9 @@ void XclImpChLabelRange::Convert( ScfPropertySet& rPropSet, ScaleData& rScaleDat // do not break text into several lines unless all labels are visible rPropSet.SetBoolProperty( EXC_CHPROP_TEXTBREAK, maData.mnLabelFreq == 1 ); // do not stagger labels in two lines - namespace cssc = ::com::sun::star::chart; rPropSet.SetProperty( EXC_CHPROP_ARRANGEORDER, cssc::ChartAxisArrangeOrderType_SIDE_BY_SIDE ); // reverse order - namespace cssc2 = ::com::sun::star::chart2; bool bReverse = ::get_flag( maData.mnFlags, EXC_CHLABELRANGE_REVERSE ) != bMirrorOrient; rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL; @@ -2692,7 +2854,6 @@ void XclImpChLabelRange::ConvertAxisPosition( ScfPropertySet& rPropSet, bool b3d But: the Y axis has to be moved to "end", if the X axis is mirrored, to keep it at the left end of the chart. */ bool bMaxCross = ::get_flag( maData.mnFlags, b3dChart ? EXC_CHLABELRANGE_REVERSE : EXC_CHLABELRANGE_MAXCROSS ); - namespace cssc = ::com::sun::star::chart; cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE; rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos ); @@ -2756,7 +2917,6 @@ void XclImpChValueRange::Convert( ScaleData& rScaleData, bool bMirrorOrient ) co } // reverse order - namespace cssc2 = ::com::sun::star::chart2; bool bReverse = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_REVERSE ) != bMirrorOrient; rScaleData.Orientation = bReverse ? cssc2::AxisOrientation_REVERSE : cssc2::AxisOrientation_MATHEMATICAL; } @@ -2768,7 +2928,6 @@ void XclImpChValueRange::ConvertAxisPosition( ScfPropertySet& rPropSet ) const bool bLogScale = ::get_flag( maData.mnFlags, EXC_CHVALUERANGE_LOGSCALE ); // crossing mode (max-cross flag overrides other crossing settings) - namespace cssc = ::com::sun::star::chart; cssc::ChartAxisPosition eAxisPos = bMaxCross ? cssc::ChartAxisPosition_END : cssc::ChartAxisPosition_VALUE; rPropSet.SetProperty( EXC_CHPROP_CROSSOVERPOSITION, eAxisPos ); @@ -2791,7 +2950,7 @@ sal_Int32 lclGetApiTickmarks( sal_uInt8 nXclTickPos ) return nApiTickmarks; } -::com::sun::star::chart::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos ) +cssc::ChartAxisLabelPosition lclGetApiLabelPosition( sal_Int8 nXclLabelPos ) { using namespace ::com::sun::star::chart; switch( nXclLabelPos ) @@ -2815,9 +2974,9 @@ void XclImpChTick::ReadChTick( XclImpStream& rStrm ) rStrm >> maData.mnMajor >> maData.mnMinor >> maData.mnLabelPos - >> maData.mnBackMode - >> maData.maRect - >> maData.maTextColor + >> maData.mnBackMode; + rStrm.Ignore( 16 ); + rStrm >> maData.maTextColor >> maData.mnFlags; if( GetBiff() == EXC_BIFF8 ) @@ -2850,7 +3009,7 @@ void XclImpChTick::Convert( ScfPropertySet& rPropSet ) const rPropSet.SetProperty( EXC_CHPROP_MAJORTICKS, lclGetApiTickmarks( maData.mnMajor ) ); rPropSet.SetProperty( EXC_CHPROP_MINORTICKS, lclGetApiTickmarks( maData.mnMinor ) ); rPropSet.SetProperty( EXC_CHPROP_LABELPOSITION, lclGetApiLabelPosition( maData.mnLabelPos ) ); - rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, ::com::sun::star::chart::ChartAxisMarkPosition_AT_AXIS ); + rPropSet.SetProperty( EXC_CHPROP_MARKPOSITION, cssc::ChartAxisMarkPosition_AT_AXIS ); } // ---------------------------------------------------------------------------- @@ -2864,7 +3023,7 @@ XclImpChAxis::XclImpChAxis( const XclImpChRoot& rRoot, sal_uInt16 nAxisType ) : void XclImpChAxis::ReadHeaderRecord( XclImpStream& rStrm ) { - rStrm >> maData.mnType >> maData.maRect; + rStrm >> maData.mnType; } void XclImpChAxis::ReadSubRecord( XclImpStream& rStrm ) @@ -2941,8 +3100,6 @@ sal_uInt16 XclImpChAxis::GetRotation() const Reference< XAxis > XclImpChAxis::CreateAxis( const XclImpChTypeGroup& rTypeGroup, const XclImpChAxis* pCrossingAxis ) const { - namespace cssc2 = ::com::sun::star::chart2; - // create the axis object (always) Reference< XAxis > xAxis( ScfApiHelper::CreateInstance( SERVICE_CHART2_AXIS ), UNO_QUERY ); if( xAxis.is() ) @@ -3136,8 +3293,8 @@ void XclImpChAxesSet::ReadSubRecord( XclImpStream& rStrm ) switch( rStrm.GetRecId() ) { case EXC_ID_CHFRAMEPOS: - mxPos.reset( new XclImpChFramePos ); - mxPos->ReadChFramePos( rStrm ); + mxFramePos.reset( new XclImpChFramePos ); + mxFramePos->ReadChFramePos( rStrm ); break; case EXC_ID_CHAXIS: ReadChAxis( rStrm ); @@ -3188,9 +3345,10 @@ void XclImpChAxesSet::Finalize() // finalize axis titles XclImpChTextRef xDefText = GetChartData().GetDefaultText( EXC_CHTEXTTYPE_AXISTITLE ); - lclFinalizeTitle( mxXAxisTitle, xDefText ); - lclFinalizeTitle( mxYAxisTitle, xDefText ); - lclFinalizeTitle( mxZAxisTitle, xDefText ); + String aAutoTitle = CREATE_STRING( "Axis Title" ); + lclFinalizeTitle( mxXAxisTitle, xDefText, aAutoTitle ); + lclFinalizeTitle( mxYAxisTitle, xDefText, aAutoTitle ); + lclFinalizeTitle( mxZAxisTitle, xDefText, aAutoTitle ); // #i47745# missing plot frame -> invisible border and area if( !mxPlotFrame ) @@ -3252,6 +3410,16 @@ void XclImpChAxesSet::Convert( Reference< XDiagram > xDiagram ) const } } +void XclImpChAxesSet::ConvertTitlePositions() const +{ + if( mxXAxisTitle.is() ) + mxXAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_X ) ); + if( mxYAxisTitle.is() ) + mxYAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Y ) ); + if( mxZAxisTitle.is() ) + mxZAxisTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_AXISTITLE, maData.mnAxesSetId, EXC_CHAXIS_Z ) ); +} + void XclImpChAxesSet::ReadChAxis( XclImpStream& rStrm ) { XclImpChAxisRef xAxis( new XclImpChAxis( GetChRoot() ) ); @@ -3358,11 +3526,15 @@ void XclImpChAxesSet::ConvertAxis( if( xAxis.is() ) { // create and attach the axis title - if( xChAxisTitle.is() ) + if( xChAxisTitle.is() ) try { - Reference< XTitled > xTitled( xAxis, UNO_QUERY ); - if( xTitled.is() ) - xTitled->setTitleObject( xChAxisTitle->CreateTitle() ); + Reference< XTitled > xTitled( xAxis, UNO_QUERY_THROW ); + Reference< XTitle > xTitle( xChAxisTitle->CreateTitle(), UNO_SET_THROW ); + xTitled->setTitleObject( xTitle ); + } + catch( Exception& ) + { + DBG_ERRORFILE( "XclImpChAxesSet::ConvertAxis - cannot set axis title" ); } // insert axis into coordinate system @@ -3416,7 +3588,7 @@ void XclImpChAxesSet::ConvertBackground( Reference< XDiagram > xDiagram ) const // The chart object =========================================================== XclImpChChart::XclImpChChart( const XclImpRoot& rRoot ) : - XclImpChRoot( rRoot, this ) + XclImpChRoot( rRoot, *this ) { mxPrimAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_PRIMARY ) ); mxSecnAxesSet.reset( new XclImpChAxesSet( GetChRoot(), EXC_CHAXESSET_SECONDARY ) ); @@ -3516,23 +3688,34 @@ XclImpChTextRef XclImpChChart::GetDefaultText( XclChTextType eTextType ) const return maDefTexts.get( nDefTextId ); } -void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, XclImpDffConverter& rDffConv, const OUString& rObjName ) const +bool XclImpChChart::IsManualPlotArea() const +{ + // there is no real automatic mode in BIFF5 charts + return (GetBiff() <= EXC_BIFF5) || ::get_flag( maProps.mnFlags, EXC_CHPROPS_USEMANPLOTAREA ); +} + +void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, + XclImpDffConverter& rDffConv, const OUString& rObjName, const Rectangle& rChartRect ) const { // initialize conversion (locks the model to suppress any internal updates) - InitConversion( xChartDoc ); + InitConversion( xChartDoc, rChartRect ); - // chart frame and title + // chart frame formatting if( mxFrame.is() ) { ScfPropertySet aFrameProp( xChartDoc->getPageBackground() ); mxFrame->Convert( aFrameProp ); } - if( mxTitle.is() ) + + // chart title + if( mxTitle.is() ) try + { + Reference< XTitled > xTitled( xChartDoc, UNO_QUERY_THROW ); + Reference< XTitle > xTitle( mxTitle->CreateTitle(), UNO_SET_THROW ); + xTitled->setTitleObject( xTitle ); + } + catch( Exception& ) { - Reference< XTitled > xTitled( xChartDoc, UNO_QUERY ); - Reference< XTitle > xTitle = mxTitle->CreateTitle(); - if( xTitled.is() && xTitle.is() ) - xTitled->setTitleObject( xTitle ); } /* Create the diagram object and attach it to the chart document. Currently, @@ -3548,13 +3731,48 @@ void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, XclImpDffCon if( xDiagram.is() && mxLegend.is() ) xDiagram->setLegend( mxLegend->CreateLegend() ); - // set the IncludeHiddenCells property via the old API as only this ensures that the data provider and al created sequences get this flag correctly - Reference< com::sun::star::chart::XChartDocument > xStandardApiChartDoc( xChartDoc, UNO_QUERY ); - if( xStandardApiChartDoc.is() ) + /* Following all conversions needing the old Chart1 API that involves full + initialization of the chart view. */ + Reference< cssc::XChartDocument > xChart1Doc( xChartDoc, UNO_QUERY ); + if( xChart1Doc.is() ) { - ScfPropertySet aDiagramProp( xStandardApiChartDoc->getDiagram() ); - bool bShowVisCells = (maProps.mnFlags & EXC_CHPROPS_SHOWVISIBLEONLY); - aDiagramProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells ); + Reference< cssc::XDiagram > xDiagram1 = xChart1Doc->getDiagram(); + + /* Set the 'IncludeHiddenCells' property via the old API as only this + ensures that the data provider and all created sequences get this + flag correctly. */ + ScfPropertySet aDiaProp( xDiagram1 ); + bool bShowVisCells = ::get_flag( maProps.mnFlags, EXC_CHPROPS_SHOWVISIBLEONLY ); + aDiaProp.SetBoolProperty( EXC_CHPROP_INCLUDEHIDDENCELLS, !bShowVisCells ); + + // plot area position and size (there is no real automatic mode in BIFF5 charts) + XclImpChFramePosRef xPlotAreaPos = mxPrimAxesSet->GetPlotAreaFramePos(); + if( IsManualPlotArea() && xPlotAreaPos.is() ) try + { + const XclChFramePos& rFramePos = xPlotAreaPos->GetFramePosData(); + if( (rFramePos.mnTLMode == EXC_CHFRAMEPOS_PARENT) && (rFramePos.mnBRMode == EXC_CHFRAMEPOS_PARENT) ) + { + Reference< cssc::XDiagramPositioning > xPositioning( xDiagram1, UNO_QUERY_THROW ); + ::com::sun::star::awt::Rectangle aDiagramRect = CalcHmmFromChartRect( rFramePos.maRect ); + // for pie charts, always set inner plot area size to exclude the data labels as Excel does + const XclImpChTypeGroup* pFirstTypeGroup = mxPrimAxesSet->GetFirstTypeGroup().get(); + if( pFirstTypeGroup && (pFirstTypeGroup->GetTypeInfo().meTypeCateg == EXC_CHTYPECATEG_PIE) ) + xPositioning->setDiagramPositionExcludingAxes( aDiagramRect ); + else if( pFirstTypeGroup && pFirstTypeGroup->Is3dChart() ) + xPositioning->setDiagramPositionIncludingAxesAndAxisTitles( aDiagramRect ); + else + xPositioning->setDiagramPositionIncludingAxes( aDiagramRect ); + } + } + catch( Exception& ) + { + } + + // positions of all title objects + if( mxTitle.is() ) + mxTitle->ConvertTitlePosition( XclChTextKey( EXC_CHTEXTTYPE_TITLE ) ); + mxPrimAxesSet->ConvertTitlePositions(); + mxSecnAxesSet->ConvertTitlePositions(); } // unlock the model @@ -3689,21 +3907,24 @@ void XclImpChChart::FinalizeDataFormats() void XclImpChChart::FinalizeTitle() { - if( (!mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString())) && !mxSecnAxesSet->IsValidAxesSet() ) + // special handling for auto-generated title + String aAutoTitle; + if( !mxTitle || (!mxTitle->IsDeleted() && !mxTitle->HasString()) ) { - /* Chart title is auto-generated from series title, if there is only - one series with title in the chart. */ - const String& rSerTitle = mxPrimAxesSet->GetSingleSeriesTitle(); - if( rSerTitle.Len() > 0 ) + // automatic title from first series name (if there are no series on secondary axes set) + if( !mxSecnAxesSet->IsValidAxesSet() ) + aAutoTitle = mxPrimAxesSet->GetSingleSeriesTitle(); + if( mxTitle.is() || (aAutoTitle.Len() > 0) ) { if( !mxTitle ) mxTitle.reset( new XclImpChText( GetChRoot() ) ); - mxTitle->SetString( rSerTitle ); + if( aAutoTitle.Len() == 0 ) + aAutoTitle = CREATE_STRING( "Chart Title" ); } } - // will reset mxTitle, if it does not contain a string - lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ) ); + // will reset mxTitle, if it does not contain a string and no auto title exists + lclFinalizeTitle( mxTitle, GetDefaultText( EXC_CHTEXTTYPE_TITLE ), aAutoTitle ); } Reference< XDiagram > XclImpChChart::CreateDiagram() const @@ -3715,7 +3936,7 @@ Reference< XDiagram > XclImpChChart::CreateDiagram() const ScfPropertySet aDiaProp( xDiagram ); // treatment of missing values - using namespace ::com::sun::star::chart::MissingValueTreatment; + using namespace cssc::MissingValueTreatment; sal_Int32 nMissingValues = LEAVE_GAP; switch( maProps.mnEmptyMode ) { @@ -3775,10 +3996,10 @@ Rectangle XclImpChartDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool in the cell address components of the client anchor. In old BIFF3-BIFF5 objects, the position is stored in the offset components of the anchor. */ Rectangle aRect( - static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_UNIT * maChartRect.GetWidth() + 0.5 ), - static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_UNIT * maChartRect.GetHeight() + 0.5 ), - static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol : rAnchor.mnRX ) / EXC_CHART_UNIT * maChartRect.GetWidth() + 0.5 ), - static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow : rAnchor.mnBY ) / EXC_CHART_UNIT * maChartRect.GetHeight() + 0.5 ) ); + static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnCol : rAnchor.mnLX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ), + static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maFirst.mnRow : rAnchor.mnTY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ), + static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnCol : rAnchor.mnRX ) / EXC_CHART_TOTALUNITS * maChartRect.GetWidth() + 0.5 ), + static_cast< long >( static_cast< double >( bDffAnchor ? rAnchor.maLast.mnRow : rAnchor.mnBY ) / EXC_CHART_TOTALUNITS * maChartRect.GetHeight() + 0.5 ) ); aRect.Justify(); // move shapes into chart area for sheet charts if( mbOwnTab ) @@ -3894,7 +4115,7 @@ void XclImpChart::Convert( Reference< XModel > xModel, XclImpDffConverter& rDffC if( xChartDoc.is() ) { if( mxChartData.is() ) - mxChartData->Convert( xChartDoc, rDffConv, rObjName ); + mxChartData->Convert( xChartDoc, rDffConv, rObjName, rChartRect ); if( mxChartDrawing.is() ) mxChartDrawing->ConvertObjects( rDffConv, xModel, rChartRect ); } |