summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoel Power <noel.power@novell.com>2012-05-02 17:41:30 +0100
committerNoel Power <noel.power@novell.com>2012-05-03 16:06:43 +0100
commit9dc4fa1b22a533ba0a6ce0353112c55eef8a14ef (patch)
treeeb01bc22975f051b7e954b534e9c9844b58f8bbf
parenta393af6e9146596ba2a197f0e369775bda7faa51 (diff)
fix bad import positions of shapes & controls fdo#49430
Change-Id: I5635ee681288cb39a11d00c5573e61c582d7daf7
-rw-r--r--sc/inc/global.hxx18
-rw-r--r--sc/source/core/data/global.cxx149
-rw-r--r--sc/source/filter/oox/drawingbase.cxx5
-rw-r--r--sc/source/filter/oox/drawingfragment.cxx7
-rw-r--r--sc/source/ui/unoobj/docuno.cxx65
-rw-r--r--sc/source/ui/view/viewdata.cxx7
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)