diff options
author | Noel Power <noel.power@novell.com> | 2012-05-02 17:41:30 +0100 |
---|---|---|
committer | Noel Power <noel.power@novell.com> | 2012-05-03 16:06:43 +0100 |
commit | 9dc4fa1b22a533ba0a6ce0353112c55eef8a14ef (patch) | |
tree | eb01bc22975f051b7e954b534e9c9844b58f8bbf | |
parent | a393af6e9146596ba2a197f0e369775bda7faa51 (diff) |
fix bad import positions of shapes & controls fdo#49430
Change-Id: I5635ee681288cb39a11d00c5573e61c582d7daf7
-rw-r--r-- | sc/inc/global.hxx | 18 | ||||
-rw-r--r-- | sc/source/core/data/global.cxx | 149 | ||||
-rw-r--r-- | sc/source/filter/oox/drawingbase.cxx | 5 | ||||
-rw-r--r-- | sc/source/filter/oox/drawingfragment.cxx | 7 | ||||
-rw-r--r-- | sc/source/ui/unoobj/docuno.cxx | 65 | ||||
-rw-r--r-- | sc/source/ui/view/viewdata.cxx | 7 |
6 files changed, 190 insertions, 61 deletions
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx index ac10094ab4d1..4e49e36a0822 100644 --- a/sc/inc/global.hxx +++ b/sc/inc/global.hxx @@ -34,6 +34,7 @@ #include <tools/stream.hxx> #include <osl/endian.h> #include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/table/CellAddress.hpp> #include "scdllapi.h" #include <boost/unordered_map.hpp> @@ -497,12 +498,27 @@ namespace com { namespace sun { namespace star { namespace i18n { class XOrdinalSuffix; } + namespace frame { + class XModel; + } + namespace drawing { + class XShape; + } }}} namespace utl { class TransliterationWrapper; } #ifndef _SCALC_EXE +struct SC_DLLPUBLIC OrientationInfo +{ + OrientationInfo() : mnVert( 0 ), mnHori( 0 ) {} + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > mxShape; + ::com::sun::star::table::CellAddress maAddress; + sal_Int32 mnVert; + sal_Int32 mnHori; +}; + class ScGlobal { static SvxSearchItem* pSearchItem; @@ -695,6 +711,8 @@ SC_DLLPUBLIC static const sal_Unicode* FindUnquoted( const sal_Unicode* pStri /** Obtain the ordinal suffix for a number according to the system locale */ static String GetOrdinalSuffix( sal_Int32 nNumber); + SC_DLLPUBLIC static void CaptureShapeOrientationInfo( std::vector< OrientationInfo >& infos, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxModel ); + SC_DLLPUBLIC static void ApplyShapeOrientationInfo( std::vector< OrientationInfo >& infos, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxModel, ScDocument& rDoc ); }; #endif diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx index c43a8534fd0e..bfcd6f49e2b7 100644 --- a/sc/source/core/data/global.cxx +++ b/sc/source/core/data/global.cxx @@ -63,6 +63,15 @@ #include <unotools/calendarwrapper.hxx> #include <unotools/collatorwrapper.hxx> #include <com/sun/star/i18n/CollatorOptions.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/document/XViewDataSupplier.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/table/XCell.hpp> +#include <com/sun/star/sheet/XSpreadsheet.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/sheet/XCellAddressable.hpp> #include <unotools/intlwrapper.hxx> #include <unotools/syslocale.hxx> #include <unotools/transliterationwrapper.hxx> @@ -87,11 +96,15 @@ #include "sc.hrc" #include "scmod.hxx" #include "appoptio.hxx" - +#include "unonames.hxx" +#include "drawview.hxx" +#include "drawutil.hxx" +#include "viewdata.hxx" // ----------------------------------------------------------------------- using ::rtl::OUString; using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; #define CLIPST_AVAILABLE 0 #define CLIPST_CAPTURED 1 @@ -1180,5 +1193,139 @@ IntlWrapper* ScGlobal::GetScIntlWrapper() } return pLocale; } +void ScGlobal::CaptureShapeOrientationInfo( std::vector< OrientationInfo >& infos, const uno::Reference<frame::XModel >& rxModel ) +{ + rtl::OUString sHori( SC_UNONAME_HORIPOS ); + rtl::OUString sVert( SC_UNONAME_VERTPOS ); + uno::Reference<drawing::XDrawPagesSupplier> xDrwSupp( rxModel, uno::UNO_QUERY ); + uno::Reference<container::XIndexAccess> xPages( xDrwSupp.is() ? xDrwSupp->getDrawPages() : NULL, uno::UNO_QUERY ); + if ( xPages.is() ) + { + for ( sal_Int32 nIndex = 0, nPages = xPages->getCount(); nIndex < nPages; ++nIndex ) + { + uno::Reference<container::XIndexAccess> xShapes( xPages->getByIndex( nIndex ), uno::UNO_QUERY ); + for ( sal_Int32 nShapeIndex = 0, nShapes = xShapes->getCount(); nShapeIndex < nShapes; ++nShapeIndex ) + { + uno::Reference< beans::XPropertySet > xShape( xShapes->getByIndex( nShapeIndex ), uno::UNO_QUERY ); + uno::Reference< table::XCell > xCell( xShape->getPropertyValue( rtl::OUString( SC_UNONAME_ANCHOR ) ), uno::UNO_QUERY ); + uno::Reference< sheet::XSpreadsheetDocument > xSpreadSheet( rxModel, uno::UNO_QUERY ); + uno::Reference< container::XIndexAccess > xSheets( xSpreadSheet.is() ? xSpreadSheet->getSheets() : NULL, uno::UNO_QUERY ); + uno::Reference< sheet::XSpreadsheet > xSheet; + uno::Reference< sheet::XCellAddressable > xAddressable( xCell, uno::UNO_QUERY ); + if ( xSheets.is() && xAddressable.is() && xSpreadSheet.is() ) + xSheet.set( xSheets->getByIndex( xAddressable->getCellAddress().Sheet ), uno::UNO_QUERY ); + // only capture orientation if the shape is anchored to cell + if ( xShape.is() && xCell.is() && xAddressable.is() && xSheet.is() ) + { + uno::Reference< beans::XPropertySetInfo > xShapePropInfo = xShape->getPropertySetInfo(); + if ( xShapePropInfo.is() && xShapePropInfo->hasPropertyByName( sHori ) && xShapePropInfo->hasPropertyByName( sVert ) ) + { + OrientationInfo aShape; + aShape.mxShape.set( xShape, uno::UNO_QUERY ); + xShape->getPropertyValue( sHori ) >>= aShape.mnHori; + xShape->getPropertyValue( sVert ) >>= aShape.mnVert; + aShape.maAddress = xAddressable->getCellAddress(); + infos.push_back( aShape ); + // Remove temporary cell anchor. Ideally we should + // preserve the cell anchoring but the drawing layer + // and the ScGridWindow don't calcuate positions in the + // same way. This means unfortunately ( especially if + // row heights above the shape are not uniform ) that + // the shape anchor position and the shape position + // can be quite skewed. The only alterative + // unfortunately is to position the shape absolutely + // rather than relative to a cell address :-( + xShape->setPropertyValue( rtl::OUString( SC_UNONAME_ANCHOR ), uno::makeAny( xSheet ) ); + } + } + } + } + } +} + +// Note: this method is only expected to be called when importing an alien +// document. +void ScGlobal::ApplyShapeOrientationInfo( std::vector< OrientationInfo >& infos, const uno::Reference< frame::XModel >& rxModel, ScDocument& rDoc ) +{ + // For each shape previously anchored to a cell calculate the shape + // position ( as the view would ) based on the available zoom and scaling. + // This prevents the shape being being drawn in an unexpected postion due to + // a) differences in the calculation of shape position by drawinglayer and + // the postion of the actual rows drawn by ScGridwin + // b) affect of UpdateAllRowHeights + for ( std::vector< OrientationInfo >::iterator it = infos.begin(), it_end = infos.end(); it != it_end; ++it ) + { + OutputDevice* pDevice = Application::GetDefaultDevice(); + if ( pDevice ) + { + uno::Reference< document::XViewDataSupplier > xViewSup( rxModel, uno::UNO_QUERY ); + uno::Reference< container::XIndexAccess > xIndexAccess; + if ( xViewSup.is() ) + xIndexAccess = xViewSup->getViewData(); + uno::Sequence< beans::PropertyValue > aSeq; + // set up partial view data to calculate zoom, pptx & ppty values + ScViewData aViewData( NULL, NULL ); + aViewData.InitData( &rDoc ); + // support initialising view data from binary import + if ( ScExtDocOptions* pDocOptions = rDoc.GetExtDocOptions() ) + { + aViewData.ReadExtOptions( *pDocOptions ); + } + else // or from the view data from the model ( oox import ) + { + if ( xIndexAccess.is() && xIndexAccess->getCount() ) + xIndexAccess->getByIndex(0) >>= aSeq; + aViewData.ReadUserDataSequence( aSeq ); + } + + aViewData.SetTabNo( it->maAddress.Sheet ); + + long nHeight = 0; + long nWidth = 0; + + MapMode aTmpMode( MAP_TWIP ); + // get postion of shape based on the start anchor + for ( int i = 0; i < it->maAddress.Column; ++i ) + { + long nTwip = aViewData.GetDocument()->GetColWidth( i, it->maAddress.Sheet ); + Point aTmpPos = pDevice->LogicToPixel( Point( nTwip, nTwip ), aTmpMode ); + nWidth += ( nTwip * aViewData.GetPPTX() ); + } + for ( int i = 0; i < it->maAddress.Row; ++i ) + { + long nTwip = aViewData.GetDocument()->GetRowHeight( i, it->maAddress.Sheet ); + Point aTmpPos = pDevice->LogicToPixel( Point( nTwip, nTwip ), aTmpMode ); + nHeight += ( nTwip * aViewData.GetPPTY() ); + } + + // determine the scale that will be used by the view + Fraction aScaleX; + Fraction aScaleY; + SCROW nEndRow = it->maAddress.Row; + SCCOL nEndCol = it->maAddress.Column; + aViewData.GetDocument()->GetTableArea( aViewData.GetTabNo(), nEndCol, nEndRow ); + if (nEndCol<20) + nEndCol = 20; + if (nEndRow<20) + nEndRow = 20; + + ScDrawUtil::CalcScale( aViewData.GetDocument(), aViewData.GetTabNo(), 0,0, nEndCol,nEndRow, pDevice,aViewData.GetZoomX(),aViewData.GetZoomY(),aViewData.GetPPTX(),aViewData.GetPPTY(), aScaleX,aScaleY ); + + // finally calculate and apply the position of shape ( including + // any vertical and horizontal offsets ) + Point aTmpPos( nWidth, nHeight); + aTmpMode = MapMode ( MAP_100TH_MM ); + aTmpMode.SetScaleX(aScaleX); + aTmpMode.SetScaleY(aScaleY); + + aTmpPos = pDevice->PixelToLogic( aTmpPos, aTmpMode ); + if ( it->mxShape.is() ) + { + com::sun::star::awt::Point aUnoPos( aTmpPos.X() + it->mnHori, aTmpPos.Y() + it->mnVert ); + it->mxShape->setPosition( aUnoPos ); + } + } + } +} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/oox/drawingbase.cxx b/sc/source/filter/oox/drawingbase.cxx index 4a30a1520b26..c7ff392f00dd 100644 --- a/sc/source/filter/oox/drawingbase.cxx +++ b/sc/source/filter/oox/drawingbase.cxx @@ -161,6 +161,7 @@ void ShapeAnchor::setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, cons void ShapeAnchor::importVmlAnchor( const OUString& rAnchor ) { meAnchorType = ANCHOR_VML; + meCellAnchorType = CELLANCHOR_PIXEL; ::std::vector< OUString > aTokens; sal_Int32 nIndex = 0; @@ -278,16 +279,16 @@ ShapeAnchor::getFromCell() const void ShapeAnchor::applyToXShape( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape>& rxShape ) { - if ( ( meAnchorType == ANCHOR_TWOCELL || meAnchorType == ANCHOR_ONECELL ) && getFromCell().is() ) + if ( ( meAnchorType == ANCHOR_VML || meAnchorType == ANCHOR_TWOCELL || meAnchorType == ANCHOR_ONECELL ) && getFromCell().is() ) { PropertySet aShapeProp( rxShape ); - aShapeProp.setProperty( PROP_Anchor, getFromCell() ); CellAnchorModel offSets; offSets.mnColOffset = maFrom.mnColOffset; offSets.mnRowOffset = maFrom.mnRowOffset; EmuPoint aPos = calcCellAnchorEmu( offSets ); aShapeProp.setProperty( PROP_HoriOrientPosition, lclEmuToHmm( aPos.X ) ); aShapeProp.setProperty( PROP_VertOrientPosition, lclEmuToHmm( aPos.Y ) ); + aShapeProp.setProperty( PROP_Anchor, getFromCell() ); } } diff --git a/sc/source/filter/oox/drawingfragment.cxx b/sc/source/filter/oox/drawingfragment.cxx index f04128762507..012c9a19a3d0 100644 --- a/sc/source/filter/oox/drawingfragment.cxx +++ b/sc/source/filter/oox/drawingfragment.cxx @@ -614,7 +614,12 @@ Reference< XShape > VmlDrawing::createAndInsertClientXShape( const ::oox::vml::S getBaseFilter().getVbaProject().registerMacroAttacher( xAttacher ); } } - + if ( !pClientData->maAnchor.isEmpty() ) + { + ShapeAnchor aAnchor( *this ); + aAnchor.importVmlAnchor( pClientData->maAnchor ); + aAnchor.applyToXShape( xShape ); + } return xShape; } } diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index 0d03f9927ee7..45623348aa38 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -194,55 +194,6 @@ const SfxItemPropertyMapEntry* lcl_GetRowsPropertyMap() return aRowsPropertyMap_Impl; } -struct OrientationInfo -{ - OrientationInfo() : mnVert( 0 ), mnHori( 0 ) {} - uno::Reference< beans::XPropertySet > mxShape; - sal_Int32 mnVert; - sal_Int32 mnHori; -}; - -void lcl_captureShapeOrientationInfo( std::vector< OrientationInfo >& infos, ScModelObj& rModel ) -{ - rtl::OUString sHori( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_HORIPOS ) ); - rtl::OUString sVert( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_VERTPOS ) ); - - uno::Reference<container::XIndexAccess> xPages( rModel.getDrawPages(), uno::UNO_QUERY ); - if ( xPages.is() ) - { - for ( sal_Int32 nIndex = 0, nPages = xPages->getCount(); nIndex < nPages; ++nIndex ) - { - uno::Reference<container::XIndexAccess> xShapes( xPages->getByIndex( nIndex ), uno::UNO_QUERY ); - for ( sal_Int32 nShapeIndex = 0, nShapes = xShapes->getCount(); nShapeIndex < nShapes; ++nShapeIndex ) - { - uno::Reference< beans::XPropertySet > xShape( xShapes->getByIndex( nShapeIndex ), uno::UNO_QUERY ); - uno::Reference< table::XCell > xCell( xShape->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_ANCHOR ) ) ), uno::UNO_QUERY ); - // only capture orientation if the shape is anchored to cell - if ( xShape.is() && xCell.is() ) - { - uno::Reference< beans::XPropertySetInfo > xPropInfo = xShape->getPropertySetInfo(); - if ( xPropInfo.is() && xPropInfo->hasPropertyByName( sHori ) && xPropInfo->hasPropertyByName( sVert ) ) - { - OrientationInfo aShape; - aShape.mxShape = xShape; - xShape->getPropertyValue( sHori ) >>= aShape.mnHori; - xShape->getPropertyValue( sVert ) >>= aShape.mnVert; - infos.push_back( aShape ); - } - } - } - } - } -} - -void lcl_applyShapeOrientationInfo( std::vector< OrientationInfo >& infos ) -{ - for ( std::vector< OrientationInfo >::iterator it = infos.begin(), it_end = infos.end(); it != it_end; ++it ) - { - it->mxShape->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_HORIPOS ) ), uno::makeAny( it->mnHori ) ); - it->mxShape->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_VERTPOS ) ), uno::makeAny( it->mnVert ) ); - } -} using sc::HMMToTwips; using sc::TwipsToHMM; @@ -1738,13 +1689,19 @@ void SAL_CALL ScModelObj::setPropertyValue( // during import ( e.g. oox ) shapes anchored by cell lose // any additional Hori/Vert orientation ( which offsets the // shape position relative to the cell ) when - // UpdateAllRowHeights is called. Save Hori/Vert values - // before calling UpdateAllRowHeights and re-apply them - // after + // UpdateAllRowHeights is called. Here we save Hori/Vert + // values before calling UpdateAllRowHeights. Also due to + // differences between the drawing layer and gridwindow + // position calculations we actually can't reliably use cell + // anchoring so we need to remove the cell anchoring, custom + // calculate where the view would position the shape and + // then position the shape absolutely at the newly + // calculated postion. std::vector< OrientationInfo > savedOrientations; - lcl_captureShapeOrientationInfo( savedOrientations, *this ); + uno::Reference< frame::XModel > xModel( this ); + ScGlobal::CaptureShapeOrientationInfo( savedOrientations, xModel ); pDocShell->UpdateAllRowHeights(); - lcl_applyShapeOrientationInfo( savedOrientations ); + ScGlobal::ApplyShapeOrientationInfo( savedOrientations, xModel, *pDoc ); } } } diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 73c79a6ea5dc..b7de81a244a4 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -2486,7 +2486,8 @@ void ScViewData::ReadExtOptions( const ScExtDocOptions& rDocOpt ) /* Width of the tabbar, relative to frame window width. We do not have the correct width of the frame window here -> store in ScTabView, which sets the size in the next resize. */ - pView->SetPendingRelTabBarWidth( rDocSett.mfTabBarWidth ); + if ( pView ) + pView->SetPendingRelTabBarWidth( rDocSett.mfTabBarWidth ); // sheet settings for( SCTAB nTab = 0; nTab < static_cast<SCTAB>(maTabData.size()); ++nTab ) @@ -2786,12 +2787,12 @@ void ScViewData::ReadUserDataSequence(const uno::Sequence <beans::PropertyValue> nTabNo = nTab; } } - else if (sName.compareToAscii(SC_HORIZONTALSCROLLBARWIDTH) == 0) + else if (pView && sName.compareToAscii(SC_HORIZONTALSCROLLBARWIDTH) == 0) { if (rSettings[i].Value >>= nTemp32) pView->SetTabBarWidth(nTemp32); } - else if (sName.compareToAscii(SC_RELHORIZONTALTABBARWIDTH) == 0) + else if (pView && sName.compareToAscii(SC_RELHORIZONTALTABBARWIDTH) == 0 ) { double fWidth = 0.0; if (rSettings[i].Value >>= fWidth) |