summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorNoel Power <noel.power@suse.com>2012-11-27 17:56:33 +0000
committerNoel Power <noel.power@suse.com>2012-11-28 14:50:25 +0000
commitc4e649f0cd013e86adbd794859bcc3cb9ee3aa61 (patch)
tree41038de6c78c01a15e730d218ea5a61a28de8fdd /sc/source
parent24c0e7ed9971663dfcaf9c4c1182dd6da9df005f (diff)
Sync draw object to calc grid for better alignment when zooming
There can be some serious rounding errors involved when calculating where to draw the grid lines for the various row heights in a document. This can be especially true for a document that has many different row heights. This results in draw objects appearing to move relative to the grid line at different zoom levels. This patch attempts to fix this problem adjusting the position of the shapes as they are drawn to ensure their position relative to grid appears to be stable. We do this by translating the position of the shape to the corrosponding position of it's cell anchor. Of course not all shapes are cell anchored and in this case we position the shape relative a temporary synthesized cell anchor. The patch essentially does the following a) calculates the offset to be applied for each shape at the current zoom level to ensure that the shape will be drawn relative to the correct cell grid see drwlayer.cxx, drawview.cxx & gridwin3.cxx, svdobj.[ch]xx b) apply the offset in the drawing layer for each of the different drawing primitives see svx/source/sdr/contact/* c) making sure the position and size of the newly created shape ( at any zoom level ) are still as expected when zoom level is changed. see. sc/source/ui/drawfunc/fuco*.cxx & d) making sure that overlays and handles are displayed at the correct position see svx/source/svdraw/* it could also be that a full blown transform might be needed to additionally scale the object ( to ensure that the edges of the object stay stable relative to ajacent grid lines ) If necessary we could do that in a later step. Change-Id: I02232f8ba192d58dbf96b80adf66c281cd0f65e8
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/core/data/drwlayer.cxx26
-rw-r--r--sc/source/ui/drawfunc/fuconarc.cxx6
-rw-r--r--sc/source/ui/drawfunc/fuconcustomshape.cxx7
-rw-r--r--sc/source/ui/drawfunc/fuconrec.cxx8
-rw-r--r--sc/source/ui/drawfunc/fuconstr.cxx41
-rw-r--r--sc/source/ui/drawfunc/fuconuno.cxx7
-rw-r--r--sc/source/ui/drawfunc/futext.cxx21
-rw-r--r--sc/source/ui/inc/drawview.hxx1
-rw-r--r--sc/source/ui/inc/fuconstr.hxx4
-rw-r--r--sc/source/ui/view/drawview.cxx60
-rw-r--r--sc/source/ui/view/gridwin3.cxx12
11 files changed, 177 insertions, 16 deletions
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx
index 0034d92caca2..129f1da48803 100644
--- a/sc/source/core/data/drwlayer.cxx
+++ b/sc/source/core/data/drwlayer.cxx
@@ -1748,33 +1748,39 @@ void ScDrawLayer::SetCellAnchored( SdrObject &rObj, const ScDrawObjData &rAnchor
pAnchor->maEndOffset = rAnchor.maEndOffset;
}
+
void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab )
{
+ ScDrawObjData aAnchor;
+ GetCellAnchorFromPosition( rObj, aAnchor, rDoc, nTab );
+ SetCellAnchored( rObj, aAnchor );
+}
+
+void ScDrawLayer::GetCellAnchorFromPosition( SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab )
+{
Rectangle aObjRect(rObj.GetLogicRect());
ScRange aRange = rDoc.GetRange( nTab, aObjRect );
Rectangle aCellRect;
- ScDrawObjData aAnchor;
- aAnchor.maStart = aRange.aStart;
+ rAnchor.maStart = aRange.aStart;
aCellRect = rDoc.GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(),
aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab() );
- aAnchor.maStartOffset.Y() = aObjRect.Top()-aCellRect.Top();
+ rAnchor.maStartOffset.Y() = aObjRect.Top()-aCellRect.Top();
if (!rDoc.IsNegativePage(nTab))
- aAnchor.maStartOffset.X() = aObjRect.Left()-aCellRect.Left();
+ rAnchor.maStartOffset.X() = aObjRect.Left()-aCellRect.Left();
else
- aAnchor.maStartOffset.X() = aCellRect.Right()-aObjRect.Right();
+ rAnchor.maStartOffset.X() = aCellRect.Right()-aObjRect.Right();
- aAnchor.maEnd = aRange.aEnd;
+ rAnchor.maEnd = aRange.aEnd;
aCellRect = rDoc.GetMMRect( aRange.aEnd.Col(), aRange.aEnd.Row(),
aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab() );
- aAnchor.maEndOffset.Y() = aObjRect.Bottom()-aCellRect.Top();
+ rAnchor.maEndOffset.Y() = aObjRect.Bottom()-aCellRect.Top();
if (!rDoc.IsNegativePage(nTab))
- aAnchor.maEndOffset.X() = aObjRect.Right()-aCellRect.Left();
+ rAnchor.maEndOffset.X() = aObjRect.Right()-aCellRect.Left();
else
- aAnchor.maEndOffset.X() = aCellRect.Right()-aObjRect.Left();
+ rAnchor.maEndOffset.X() = aCellRect.Right()-aObjRect.Left();
- SetCellAnchored( rObj, aAnchor );
}
void ScDrawLayer::UpdateCellAnchorFromPositionEnd( SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab )
diff --git a/sc/source/ui/drawfunc/fuconarc.cxx b/sc/source/ui/drawfunc/fuconarc.cxx
index a0b2bed7110d..e7507b6e6703 100644
--- a/sc/source/ui/drawfunc/fuconarc.cxx
+++ b/sc/source/ui/drawfunc/fuconarc.cxx
@@ -74,8 +74,14 @@ sal_Bool FuConstArc::MouseButtonDown( const MouseEvent& rMEvt )
if ( rMEvt.IsLeft() && !pView->IsAction() )
{
Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+ // Hack to align object to nearest grid position where object
+ // would be anchored ( if it were cell anchored )
+ // Get grid offset for current position ( note: aPnt is
+ // also adjusted )
+ Point aGridOff = CurrentGridSyncOffsetAndPos( aPnt );
pWindow->CaptureMouse();
pView->BegCreateObj( aPnt );
+ pView->GetCreateObj()->SetGridOffset( aGridOff );
bReturn = sal_True;
}
return bReturn;
diff --git a/sc/source/ui/drawfunc/fuconcustomshape.cxx b/sc/source/ui/drawfunc/fuconcustomshape.cxx
index 80322d1948db..532a803ea093 100644
--- a/sc/source/ui/drawfunc/fuconcustomshape.cxx
+++ b/sc/source/ui/drawfunc/fuconcustomshape.cxx
@@ -83,6 +83,12 @@ sal_Bool FuConstCustomShape::MouseButtonDown(const MouseEvent& rMEvt)
if ( rMEvt.IsLeft() && !pView->IsAction() )
{
Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+ // Hack to align object to nearest grid position where object
+ // would be anchored ( if it were cell anchored )
+ // Get grid offset for current position ( note: aPnt is
+ // also adjusted )
+ Point aGridOff = CurrentGridSyncOffsetAndPos( aPnt );
+
pWindow->CaptureMouse();
pView->BegCreateObj(aPnt);
@@ -95,6 +101,7 @@ sal_Bool FuConstCustomShape::MouseButtonDown(const MouseEvent& rMEvt)
bForceNoFillStyle = sal_True;
if ( bForceNoFillStyle )
pObj->SetMergedItem( XFillStyleItem( XFILL_NONE ) );
+ pObj->SetGridOffset( aGridOff );
}
bReturn = sal_True;
diff --git a/sc/source/ui/drawfunc/fuconrec.cxx b/sc/source/ui/drawfunc/fuconrec.cxx
index 8ef1ce7ab1ef..9a77e4e9d343 100644
--- a/sc/source/ui/drawfunc/fuconrec.cxx
+++ b/sc/source/ui/drawfunc/fuconrec.cxx
@@ -82,7 +82,11 @@ sal_Bool FuConstRectangle::MouseButtonDown(const MouseEvent& rMEvt)
if ( rMEvt.IsLeft() && !pView->IsAction() )
{
Point aPos( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
-
+ // Hack to align object to nearest grid position where object
+ // would be anchored ( if it were cell anchored )
+ // Get grid offset for current position ( note: aPnt is
+ // also adjusted )
+ Point aGridOff = CurrentGridSyncOffsetAndPos( aPos );
pWindow->CaptureMouse();
if ( pView->GetCurrentObjIdentifier() == OBJ_CAPTION )
@@ -95,6 +99,8 @@ sal_Bool FuConstRectangle::MouseButtonDown(const MouseEvent& rMEvt)
}
else
bReturn = pView->BegCreateObj(aPos);
+ if ( bReturn )
+ pView->GetCreateObj()->SetGridOffset( aGridOff );
}
return bReturn;
}
diff --git a/sc/source/ui/drawfunc/fuconstr.cxx b/sc/source/ui/drawfunc/fuconstr.cxx
index e7786de03d8a..320b70182ad5 100644
--- a/sc/source/ui/drawfunc/fuconstr.cxx
+++ b/sc/source/ui/drawfunc/fuconstr.cxx
@@ -39,6 +39,8 @@
#include "futext.hxx"
#include "sc.hrc"
#include "drawview.hxx"
+#include "document.hxx"
+#include "gridwin.hxx"
// Maximal erlaubte Mausbewegung um noch Drag&Drop zu starten
//! fusel,fuconstr,futext - zusammenfassen!
@@ -75,6 +77,39 @@ sal_uInt8 FuConstruct::Command(const CommandEvent& rCEvt)
return FuDraw::Command( rCEvt );
}
+// Calculate and return offset at current zoom. rInOutPos is adjusted by
+// the calculated offset. rInOutPos now points to the position than when
+// scaled to 100% actually would be at the position you see at the current zoom
+// ( relative to the grid ) note: units are expected to be in 100th mm
+Point FuConstruct::CurrentGridSyncOffsetAndPos( Point& rInOutPos )
+{
+ Point aRetGridOff;
+ ScViewData* pViewData = pViewShell->GetViewData();
+ ScDocument* pDoc = pViewData ? pViewData->GetDocument() : NULL;
+ if ( pViewData && pDoc )
+ {
+ // rInOutPos mightn't be where you think it is if there is zoom
+ // involved. Lets calculate where aPos would be at 100% zoom
+ // that's the actual correct position for the object ( when you
+ // restore the zoom.
+ Rectangle aObjRect( rInOutPos, rInOutPos );
+ ScRange aRange = pDoc->GetRange( pView->GetTab(), aObjRect );
+ ScAddress aOldStt = aRange.aStart;
+ Point aOldPos( pDoc->GetColOffset( aOldStt.Col(), aOldStt.Tab() ), pDoc->GetRowOffset( aOldStt.Row(), aOldStt.Tab() ) );
+ aOldPos.X() = sc::TwipsToHMM( aOldPos.X() );
+ aOldPos.Y() = sc::TwipsToHMM( aOldPos.Y() );
+ ScSplitPos eWhich = pViewData->GetActivePart();
+ ScGridWindow* pGridWin = (ScGridWindow*)pViewData->GetActiveWin();
+ // and equiv screen pos
+ Point aScreenPos = pViewShell->GetViewData()->GetScrPos( aOldStt.Col(), aOldStt.Row(), eWhich, sal_True );
+ MapMode aDrawMode = pGridWin->GetDrawMapMode();
+ Point aCurPosHmm = pGridWin->PixelToLogic(aScreenPos, aDrawMode );
+ Point aOff = ( rInOutPos - aCurPosHmm );
+ rInOutPos = aOldPos + aOff;
+ aRetGridOff = aCurPosHmm - aOldPos;
+ }
+ return aRetGridOff;
+}
/*************************************************************************
|*
|* MouseButtonDown-event
@@ -144,6 +179,12 @@ sal_Bool FuConstruct::MouseMove(const MouseEvent& rMEvt)
Point aPix(rMEvt.GetPosPixel());
Point aPnt( pWindow->PixelToLogic(aPix) );
+ // if object is being created then more than likely the mouse
+ // position has been 'adjusted' for the current zoom, need to
+ // restore the mouse position here to ensure resize works as expected
+ if ( pView->GetCreateObj() )
+ aPnt -= pView->GetCreateObj()->GetGridOffset();
+
if ( pView->IsAction() )
{
ForceScroll(aPix);
diff --git a/sc/source/ui/drawfunc/fuconuno.cxx b/sc/source/ui/drawfunc/fuconuno.cxx
index 924ab3e60aad..ba0e4b71613a 100644
--- a/sc/source/ui/drawfunc/fuconuno.cxx
+++ b/sc/source/ui/drawfunc/fuconuno.cxx
@@ -76,8 +76,15 @@ sal_Bool FuConstUnoControl::MouseButtonDown(const MouseEvent& rMEvt)
if ( rMEvt.IsLeft() && !pView->IsAction() )
{
Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
+ // Hack to align object to nearest grid position where object
+ // would be anchored ( if it were cell anchored )
+ // Get grid offset for current position ( note: aPnt is
+ // also adjusted )
+ Point aGridOff = CurrentGridSyncOffsetAndPos( aPnt );
+
pWindow->CaptureMouse();
pView->BegCreateObj(aPnt);
+ pView->GetCreateObj()->SetGridOffset( aGridOff );
bReturn = sal_True;
}
return bReturn;
diff --git a/sc/source/ui/drawfunc/futext.cxx b/sc/source/ui/drawfunc/futext.cxx
index 2505ada36399..f014ad29f169 100644
--- a/sc/source/ui/drawfunc/futext.cxx
+++ b/sc/source/ui/drawfunc/futext.cxx
@@ -314,7 +314,15 @@ sal_Bool FuText::MouseButtonDown(const MouseEvent& rMEvt)
/**********************************************************
* Objekt erzeugen
**********************************************************/
- pView->BegCreateObj(aMDPos, (OutputDevice*) NULL);
+ // Hack to align object to nearest grid position where object
+ // would be anchored ( if it were cell anchored )
+ // Get grid offset for current position ( note: aPnt is
+ // also adjusted )
+ Point aGridOff = CurrentGridSyncOffsetAndPos( aMDPos );
+
+ bool bRet = pView->BegCreateObj(aMDPos, (OutputDevice*) NULL);
+ if ( bRet )
+ pView->GetCreateObj()->SetGridOffset( aGridOff );
}
}
}
@@ -359,14 +367,19 @@ sal_Bool FuText::MouseMove(const MouseEvent& rMEvt)
aDragTimer.Stop();
}
+ Point aPix(rMEvt.GetPosPixel());
+ Point aPnt(pWindow->PixelToLogic(aPix));
+ // if object is being created then more than likely the mouse
+ // position has been 'adjusted' for the current zoom, need to
+ // restore the mouse position here to ensure resize works as expected
+ if ( pView->GetCreateObj() )
+ aPnt -= pView->GetCreateObj()->GetGridOffset();
+
if ( pView->MouseMove(rMEvt, pWindow) )
return (sal_True); // Event von der SdrView ausgewertet
if ( pView->IsAction() )
{
- Point aPix(rMEvt.GetPosPixel());
- Point aPnt(pWindow->PixelToLogic(aPix));
-
ForceScroll(aPix);
pView->MovAction(aPnt);
}
diff --git a/sc/source/ui/inc/drawview.hxx b/sc/source/ui/inc/drawview.hxx
index 6574cac15d0b..650d6d9e46e9 100644
--- a/sc/source/ui/inc/drawview.hxx
+++ b/sc/source/ui/inc/drawview.hxx
@@ -139,6 +139,7 @@ public:
::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > CopyToTransferable();
static void CheckOle( const SdrMarkList& rMarkList, sal_Bool& rAnyOle, sal_Bool& rOneOle );
+ virtual void SyncForGrid( SdrObject* pObj );
};
diff --git a/sc/source/ui/inc/fuconstr.hxx b/sc/source/ui/inc/fuconstr.hxx
index 2f4c0d5dd290..c50feba8db7c 100644
--- a/sc/source/ui/inc/fuconstr.hxx
+++ b/sc/source/ui/inc/fuconstr.hxx
@@ -46,6 +46,10 @@ class FuConstruct : public FuDraw
virtual void Activate();
virtual void Deactivate();
+
+ // Returns grid sync offset for rInOutPos, additionally adjusts rInOutPos
+ // by the offset
+ Point CurrentGridSyncOffsetAndPos( Point& rInOutPos);
};
diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx
index adea01304019..85e5402f9d39 100644
--- a/sc/source/ui/view/drawview.cxx
+++ b/sc/source/ui/view/drawview.cxx
@@ -59,6 +59,7 @@
#include "userdat.hxx"
#include "postit.hxx"
#include "undocell.hxx"
+#include "gridwin.hxx"
#include "sc.hrc"
@@ -330,6 +331,20 @@ void ScDrawView::RecalcScale()
ScDrawUtil::CalcScale( pDoc, nTab, 0,0, nEndCol,nEndRow, pDev,aZoomX,aZoomY,nPPTX,nPPTY,
aScaleX,aScaleY );
+ SdrPageView* pPV = GetSdrPageView();
+ if ( pViewData && pPV )
+ {
+ if ( SdrPage* pPage = pPV->GetPage() )
+ {
+ sal_uLong nCount = pPage->GetObjCount();
+ for ( sal_uLong i = 0; i < nCount; i++ )
+ {
+ SdrObject* pObj = pPage->GetObj( i );
+ // Align objects to nearset grid position
+ SyncForGrid( pObj );
+ }
+ }
+ }
}
void ScDrawView::DoConnect(SdrOle2Obj* pOleObj)
@@ -741,4 +756,49 @@ void ScDrawView::MarkDropObj( SdrObject* pObj )
}
}
+// In order to counteract the effects of rounding due to the nature of how the
+// grid positions are calcuated and drawn we calculate the offset needed at the
+// current zoom to be applied to an SrdObject when it is drawn in order to make
+// sure that it's position relative to the nearest cell anchor doesn't change.
+// Of course not all shape(s)/control(s) are cell anchored, if the
+// object doesn't have a cell anchor we synthesise a temporary anchor.
+void ScDrawView::SyncForGrid( SdrObject* pObj )
+{
+ // process members of a group shape separately
+ if ( pObj->ISA( SdrObjGroup ) )
+ {
+ SdrObjList *pLst = ((SdrObjGroup*)pObj)->GetSubList();
+ for ( sal_uLong i = 0, nCount = pLst->GetObjCount(); i < nCount; ++i )
+ SyncForGrid( pLst->GetObj( i ) ); }
+ ScSplitPos eWhich = pViewData->GetActivePart();
+ ScGridWindow* pGridWin = (ScGridWindow*)pViewData->GetActiveWin();
+ ScDrawObjData* pData = ScDrawLayer::GetObjDataTab( pObj, nTab );
+ if ( pGridWin )
+ {
+ ScAddress aOldStt;
+ if( pData )
+ {
+ aOldStt = pData->maStart;
+ }
+ else
+ {
+ // Page anchored object so...
+ // synthesise an anchor ( but don't attach it to
+ // the object as we want to maintain page anchoring )
+ ScDrawObjData aAnchor;
+ ScDrawLayer::GetCellAnchorFromPosition( *pObj, aAnchor, *pDoc, GetTab() );
+ aOldStt = aAnchor.maStart;
+ }
+ MapMode aDrawMode = pGridWin->GetDrawMapMode();
+ // find pos anchor position
+ Point aOldPos( pDoc->GetColOffset( aOldStt.Col(), aOldStt.Tab() ), pDoc->GetRowOffset( aOldStt.Row(), aOldStt.Tab() ) );
+ aOldPos.X() = sc::TwipsToHMM( aOldPos.X() );
+ aOldPos.Y() = sc::TwipsToHMM( aOldPos.Y() );
+ // find position of same point on the screen ( e.g. grid )
+ Point aCurPos = pViewData->GetScrPos( aOldStt.Col(), aOldStt.Row(), eWhich, sal_True );
+ Point aCurPosHmm = pGridWin->PixelToLogic(aCurPos, aDrawMode );
+ Point aGridOff = ( aCurPosHmm - aOldPos );
+ pObj->SetGridOffset( aGridOff );
+ }
+}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/gridwin3.cxx b/sc/source/ui/view/gridwin3.cxx
index 228bdd3c4e3a..7e44ccebb2ba 100644
--- a/sc/source/ui/view/gridwin3.cxx
+++ b/sc/source/ui/view/gridwin3.cxx
@@ -49,7 +49,9 @@
#include "document.hxx"
#include "drwlayer.hxx"
#include <vcl/svapp.hxx>
-
+#include "userdat.hxx"
+#include "unitconv.hxx"
+#include <svx/svdpage.hxx>
// -----------------------------------------------------------------------
bool ScGridWindow::DrawMouseButtonDown(const MouseEvent& rMEvt)
@@ -351,6 +353,10 @@ void ScGridWindow::UpdateStatusPosSize()
pDrView->TakeActionRect( aRect );
if ( !aRect.IsEmpty() )
{
+ // mouse position will have been adjusted for offset
+ // at current position and zoom, restore that adjustment here
+ // so status shows correct value
+ aRect -= pDrView->GetGridOffset();
pPV->LogicToPagePos(aRect);
aSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
aSet.Put( SvxSizeItem( SID_ATTR_SIZE,
@@ -363,6 +369,10 @@ void ScGridWindow::UpdateStatusPosSize()
if ( pDrView->AreObjectsMarked() ) // selected objects
{
Rectangle aRect = pDrView->GetAllMarkedRect();
+ // mouse position will have been adjusted for offset
+ // at current position and zoom, restore that adjustment here
+ // so status shows correct value
+ aRect -= pDrView->GetGridOffset();
pPV->LogicToPagePos(aRect);
aSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
aSet.Put( SvxSizeItem( SID_ATTR_SIZE,