summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCédric Bosdonnat <cedric.bosdonnat@free.fr>2012-11-23 17:51:16 +0100
committerCédric Bosdonnat <cedric.bosdonnat@free.fr>2012-11-23 20:21:23 +0100
commite8fbe97900f13305b17015d9044993bde4adab36 (patch)
treeda16e4486ce75a24b768b316ca4e7abb1f697245
parent7d43a3b02fee1c89cf706e7f917ae5d462974fe5 (diff)
fdo#52182: Fixed click in frames located in header/footer
Using a distance to click to select the best object to select between normal text and background object. Change-Id: Ib5b53161c7af2c16f4df379382f2e53fc6d8092b
-rw-r--r--sw/source/core/doc/notxtfrm.cxx2
-rw-r--r--sw/source/core/inc/cellfrm.hxx2
-rw-r--r--sw/source/core/inc/flyfrm.hxx2
-rw-r--r--sw/source/core/inc/frame.hxx2
-rw-r--r--sw/source/core/inc/layfrm.hxx2
-rw-r--r--sw/source/core/inc/notxtfrm.hxx2
-rw-r--r--sw/source/core/inc/pagefrm.hxx2
-rw-r--r--sw/source/core/inc/rootfrm.hxx2
-rw-r--r--sw/source/core/inc/txtfrm.hxx2
-rw-r--r--sw/source/core/layout/trvlfrm.cxx96
-rw-r--r--sw/source/core/layout/unusedf.cxx2
-rw-r--r--sw/source/core/text/frmcrsr.cxx2
-rw-r--r--sw/source/ui/docvw/edtwin.cxx18
-rw-r--r--sw/source/ui/inc/edtwin.hxx2
14 files changed, 89 insertions, 49 deletions
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index 423dc355d2a9..914e189a2707 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -600,7 +600,7 @@ sal_Bool SwNoTxtFrm::GetCharRect( SwRect &rRect, const SwPosition& rPos,
sal_Bool SwNoTxtFrm::GetCrsrOfst(SwPosition* pPos, Point& ,
- SwCrsrMoveState* ) const
+ SwCrsrMoveState*, bool ) const
{
SwCntntNode* pCNd = (SwCntntNode*)GetNode();
pPos->nNode = *pCNd;
diff --git a/sw/source/core/inc/cellfrm.hxx b/sw/source/core/inc/cellfrm.hxx
index 98a9713691e7..050723ccea3e 100644
--- a/sw/source/core/inc/cellfrm.hxx
+++ b/sw/source/core/inc/cellfrm.hxx
@@ -39,7 +39,7 @@ public:
SwCellFrm( const SwTableBox &, SwFrm*, bool bInsertContent = true );
~SwCellFrm();
- virtual sal_Bool GetCrsrOfst( SwPosition *, Point&, SwCrsrMoveState* = 0 ) const;
+ virtual sal_Bool GetCrsrOfst( SwPosition *, Point&, SwCrsrMoveState* = 0, bool bTestBackground = false ) const;
virtual void Paint( SwRect const&,
SwPrintData const*const pPrintData = NULL ) const;
virtual void CheckDirection( sal_Bool bVert );
diff --git a/sw/source/core/inc/flyfrm.hxx b/sw/source/core/inc/flyfrm.hxx
index d3f62a6dc7f7..abfd2209e6ff 100644
--- a/sw/source/core/inc/flyfrm.hxx
+++ b/sw/source/core/inc/flyfrm.hxx
@@ -167,7 +167,7 @@ public:
SwPrintData const*const pPrintData = NULL ) const;
virtual Size ChgSize( const Size& aNewSize );
virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
- SwCrsrMoveState* = 0 ) const;
+ SwCrsrMoveState* = 0, bool bTestBackground = false ) const;
virtual void CheckDirection( sal_Bool bVert );
virtual void Cut();
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
index b6db9cf82f46..ebbde55d34f8 100644
--- a/sw/source/core/inc/frame.hxx
+++ b/sw/source/core/inc/frame.hxx
@@ -785,7 +785,7 @@ public:
virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
- SwCrsrMoveState* = 0 ) const;
+ SwCrsrMoveState* = 0, bool bTestBackground = false ) const;
virtual sal_Bool GetCharRect( SwRect &, const SwPosition&,
SwCrsrMoveState* = 0 ) const;
virtual void Paint( SwRect const&,
diff --git a/sw/source/core/inc/layfrm.hxx b/sw/source/core/inc/layfrm.hxx
index 14c03b088009..829c7fc8b7fa 100644
--- a/sw/source/core/inc/layfrm.hxx
+++ b/sw/source/core/inc/layfrm.hxx
@@ -92,7 +92,7 @@ public:
virtual bool FillSelection( SwSelectionList& rList, const SwRect& rRect ) const;
virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
- SwCrsrMoveState* = 0 ) const;
+ SwCrsrMoveState* = 0, bool bTestBackground = false ) const;
virtual void Cut();
virtual void Paste( SwFrm* pParent, SwFrm* pSibling = 0 );
diff --git a/sw/source/core/inc/notxtfrm.hxx b/sw/source/core/inc/notxtfrm.hxx
index cc680df185a7..bce88c45f209 100644
--- a/sw/source/core/inc/notxtfrm.hxx
+++ b/sw/source/core/inc/notxtfrm.hxx
@@ -60,7 +60,7 @@ public:
virtual sal_Bool GetCharRect( SwRect &, const SwPosition&,
SwCrsrMoveState* = 0) const;
sal_Bool GetCrsrOfst(SwPosition* pPos, Point& aPoint,
- SwCrsrMoveState* = 0) const;
+ SwCrsrMoveState* = 0, bool bTestBackground = false) const;
const Size &GetGrfSize() const { return GetSize(); }
void GetGrfArea( SwRect &rRect, SwRect * = 0, bool bMirror = true ) const;
diff --git a/sw/source/core/inc/pagefrm.hxx b/sw/source/core/inc/pagefrm.hxx
index 271e161a88e7..fc4d93c72a59 100644
--- a/sw/source/core/inc/pagefrm.hxx
+++ b/sw/source/core/inc/pagefrm.hxx
@@ -180,7 +180,7 @@ public:
void PlaceFly( SwFlyFrm* pFly, SwFlyFrmFmt* pFmt );
virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
- SwCrsrMoveState* = 0 ) const;
+ SwCrsrMoveState* = 0, bool bTestBackground = false ) const;
// erfrage vom Client Informationen
virtual bool GetInfo( SfxPoolItem& ) const;
diff --git a/sw/source/core/inc/rootfrm.hxx b/sw/source/core/inc/rootfrm.hxx
index fafdb0c762ff..02014dcd5cde 100644
--- a/sw/source/core/inc/rootfrm.hxx
+++ b/sw/source/core/inc/rootfrm.hxx
@@ -195,7 +195,7 @@ public:
void SetDrawPage( SdrPage* pNew ){ pDrawPage = pNew; }
virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
- SwCrsrMoveState* = 0 ) const;
+ SwCrsrMoveState* = 0, bool bTestBackground = false ) const;
virtual void Paint( SwRect const&,
SwPrintData const*const pPrintData = NULL ) const;
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 3942759dc1d1..cc1ceaf5ce5f 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -277,7 +277,7 @@ public:
//naechsten ist. Wenn der SPoint ausserhalb der SSize liegt,
//liefert die Funktion sal_False, sal_True sonst.
virtual sal_Bool GetCrsrOfst( SwPosition *, Point&,
- SwCrsrMoveState* = 0) const;
+ SwCrsrMoveState* = 0, bool bTestBackground = false ) const;
// GetKeyCrsrOfst sorgt dafuer, dass der Frame nicht gewechselt wird
// (z.B. Wechsel in den zeichengebundenen Frame).
diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx
index 60660f17c170..856845f5428d 100644
--- a/sw/source/core/layout/trvlfrm.cxx
+++ b/sw/source/core/layout/trvlfrm.cxx
@@ -29,6 +29,7 @@
#include <hintids.hxx>
#include <hints.hxx>
#include <tools/bigint.hxx>
+#include <tools/line.hxx>
#include <editeng/opaqitem.hxx>
#include <editeng/protitem.hxx>
#include <vcl/settings.hxx>
@@ -63,9 +64,11 @@
#include <cfloat>
#include <swselectionlist.hxx>
+#include <basegfx/numeric/ftools.hxx>
+
namespace {
bool lcl_GetCrsrOfst_Objects( const SwPageFrm* pPageFrm, bool bSearchBackground,
- SwPosition *pPos, Point& rPoint, SwCrsrMoveState* pCMS, long& rSurface )
+ SwPosition *pPos, Point& rPoint, SwCrsrMoveState* pCMS )
{
bool bRet = false;
Point aPoint( rPoint );
@@ -89,7 +92,6 @@ namespace {
!pFly->IsProtected() ) &&
pFly->GetCrsrOfst( pPos, aPoint, pCMS ) )
{
- rSurface = pFly->Frm().Width() * pFly->Frm().Height();
bRet = true;
break;
}
@@ -101,18 +103,19 @@ namespace {
return bRet;
}
- long lcl_GetSurface( SwPosition* pPos )
+ double lcl_getDistance( const SwRect& rRect, const Point& rPoint )
{
- SwRect aArea;
-
- SwNode& rNode = pPos->nNode.GetNode();
-
- if ( rNode.IsCntntNode() )
- aArea = rNode.GetCntntNode()->FindLayoutRect();
+ double nDist = 0.0;
- // FIXME Handle the other kinds of nodes?
+ // If the point is inside the rectangle, then distance is 0
+ // Otherwise, compute the distance to the center of the rectangle.
+ if ( !rRect.IsInside( rPoint ) )
+ {
+ Line aLine( rPoint, rRect.Center( ) );
+ nDist = aLine.GetLength( );
+ }
- return aArea.Height() * aArea.Width();
+ return nDist;
}
}
@@ -164,7 +167,7 @@ static SwCrsrOszControl aOszCtrl = { 0, 0, 0 };
|*
|*************************************************************************/
sal_Bool SwLayoutFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
- SwCrsrMoveState* pCMS ) const
+ SwCrsrMoveState* pCMS, bool ) const
{
sal_Bool bRet = sal_False;
const SwFrm *pFrm = Lower();
@@ -199,7 +202,7 @@ sal_Bool SwLayoutFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
|*************************************************************************/
sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
- SwCrsrMoveState* pCMS ) const
+ SwCrsrMoveState* pCMS, bool bTestBackground ) const
{
sal_Bool bRet = sal_False;
Point aPoint( rPoint );
@@ -220,14 +223,11 @@ sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
//hineinsetzen, dadurch sollten alle Aenderungen unmoeglich sein.
if ( GetSortedObjs() )
{
- long nObjSurface = 0; // Unused
- bRet = lcl_GetCrsrOfst_Objects( this, false, pPos, rPoint, pCMS, nObjSurface );
+ bRet = lcl_GetCrsrOfst_Objects( this, false, pPos, rPoint, pCMS );
}
if ( !bRet )
{
- long nTextSurface = 0;
- long nBackSurface = 0;
SwPosition aBackPos( *pPos );
SwPosition aTextPos( *pPos );
@@ -236,7 +236,6 @@ sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
//aktuellen an. Mit Flys ist es dann allerdings vorbei.
if ( SwLayoutFrm::GetCrsrOfst( &aTextPos, aPoint, pCMS ) )
{
- nTextSurface = lcl_GetSurface( &aTextPos );
bTextRet = sal_True;
}
else
@@ -250,8 +249,6 @@ sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
if ( pCMS && pCMS->bStop )
return sal_False;
- nTextSurface = pCnt->Frm().Height() * pCnt->Frm().Width();
-
OSL_ENSURE( pCnt, "Crsr is gone to a Black hole" );
if( pCMS && pCMS->pFill && pCnt->IsTxtFrm() )
bTextRet = pCnt->GetCrsrOfst( &aTextPos, rPoint, pCMS );
@@ -270,11 +267,10 @@ sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
// Check objects in the background if nothing else matched
if ( GetSortedObjs() )
{
- bBackRet = lcl_GetCrsrOfst_Objects( this, true, &aBackPos, rPoint, pCMS, nBackSurface );
+ bBackRet = lcl_GetCrsrOfst_Objects( this, true, &aBackPos, rPoint, pCMS );
}
- // TODO Pick up the best approaching selection
- if ( bTextRet && bBackRet && ( nTextSurface > nBackSurface ) )
+ if ( ( bTestBackground && bBackRet ) || !bTextRet )
{
bRet = bBackRet;
pPos->nNode = aBackPos.nNode;
@@ -282,9 +278,49 @@ sal_Bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
}
else
{
- bRet = bTextRet;
- pPos->nNode = aTextPos.nNode;
- pPos->nContent = aTextPos.nContent;
+ /* In order to provide a selection as accurable as possible when we have both
+ * text and brackground object, then we compute the distance between both
+ * would-be positions and the click point. The shortest distance wins.
+ */
+ SwCntntNode* pTextNd = aTextPos.nNode.GetNode( ).GetCntntNode( );
+ double nTextDistance = 0;
+ bool bValidTextDistance = false;
+ if ( pTextNd )
+ {
+ SwCntntFrm* pTextFrm = pTextNd->getLayoutFrm( getRootFrm( ) );
+ SwRect rTextRect;
+ pTextFrm->GetCharRect( rTextRect, aTextPos );
+
+ nTextDistance = lcl_getDistance( rTextRect, rPoint );
+ bValidTextDistance = true;
+ }
+
+ double nBackDistance = 0;
+ bool bValidBackDistance = false;
+ SwCntntNode* pBackNd = aBackPos.nNode.GetNode( ).GetCntntNode( );
+ if ( pBackNd )
+ {
+ // FIXME There are still cases were we don't have the proper node here.
+ SwCntntFrm* pBackFrm = pBackNd->getLayoutFrm( getRootFrm( ) );
+ SwRect rBackRect;
+ pBackFrm->GetCharRect( rBackRect, aBackPos );
+
+ nBackDistance = lcl_getDistance( rBackRect, rPoint );
+ bValidBackDistance = true;
+ }
+
+ if ( bValidTextDistance && bValidBackDistance && basegfx::fTools::more( nTextDistance, nBackDistance ) )
+ {
+ bRet = bBackRet;
+ pPos->nNode = aBackPos.nNode;
+ pPos->nContent = aBackPos.nContent;
+ }
+ else
+ {
+ bRet = bTextRet;
+ pPos->nNode = aTextPos.nNode;
+ pPos->nContent = aTextPos.nContent;
+ }
}
}
@@ -360,7 +396,7 @@ bool SwRootFrm::FillSelection( SwSelectionList& aSelList, const SwRect& rRect) c
|*
|*************************************************************************/
sal_Bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
- SwCrsrMoveState* pCMS ) const
+ SwCrsrMoveState* pCMS, bool bTestBackground ) const
{
sal_Bool bOldAction = IsCallbackActionEnabled();
((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
@@ -387,7 +423,7 @@ sal_Bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
}
if ( pPage )
{
- pPage->SwPageFrm::GetCrsrOfst( pPos, rPoint, pCMS );
+ pPage->SwPageFrm::GetCrsrOfst( pPos, rPoint, pCMS, bTestBackground );
}
((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
@@ -412,7 +448,7 @@ sal_Bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
|*
|*************************************************************************/
sal_Bool SwCellFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
- SwCrsrMoveState* pCMS ) const
+ SwCrsrMoveState* pCMS, bool ) const
{
// cell frame does not necessarily have a lower (split table cell)
if ( !Lower() )
@@ -489,7 +525,7 @@ sal_Bool SwCellFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
//am weitesten oben liegt.
sal_Bool SwFlyFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
- SwCrsrMoveState* pCMS ) const
+ SwCrsrMoveState* pCMS, bool ) const
{
aOszCtrl.Entry( this );
diff --git a/sw/source/core/layout/unusedf.cxx b/sw/source/core/layout/unusedf.cxx
index d28eb5fedb7a..f12f19cb8fb6 100644
--- a/sw/source/core/layout/unusedf.cxx
+++ b/sw/source/core/layout/unusedf.cxx
@@ -54,7 +54,7 @@ bool SwFrm::FillSelection( SwSelectionList& , const SwRect& ) const
return false;
}
-sal_Bool SwFrm::GetCrsrOfst( SwPosition *, Point&, SwCrsrMoveState* ) const
+sal_Bool SwFrm::GetCrsrOfst( SwPosition *, Point&, SwCrsrMoveState*, bool ) const
{
OSL_FAIL( "GetCrsrOfst of the base class, hi!" );
return sal_False;
diff --git a/sw/source/core/text/frmcrsr.cxx b/sw/source/core/text/frmcrsr.cxx
index 9562f1609808..059499c16c37 100644
--- a/sw/source/core/text/frmcrsr.cxx
+++ b/sw/source/core/text/frmcrsr.cxx
@@ -682,7 +682,7 @@ sal_Bool SwTxtFrm::_GetCrsrOfst(SwPosition* pPos, const Point& rPoint,
*************************************************************************/
sal_Bool SwTxtFrm::GetCrsrOfst(SwPosition* pPos, Point& rPoint,
- SwCrsrMoveState* pCMS ) const
+ SwCrsrMoveState* pCMS, bool ) const
{
MSHORT nChgFrm = 2;
if( pCMS )
diff --git a/sw/source/ui/docvw/edtwin.cxx b/sw/source/ui/docvw/edtwin.cxx
index e28afb12b3e2..99c4fbffc5f8 100644
--- a/sw/source/ui/docvw/edtwin.cxx
+++ b/sw/source/ui/docvw/edtwin.cxx
@@ -2779,11 +2779,12 @@ void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt)
// How many clicks do we need to select a fly frame?
FrameControlType eControl;
bool bOverFly = false;
- bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly );
+ bool bPageAnchored = false;
+ bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
int nNbFlyClicks = 1;
// !bOverHeaderFooterFly doesn't mean we have a frame to select
- if ( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) ||
- ( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly ) )
+ if ( !bPageAnchored && ( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) ||
+ ( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly ) ) )
{
nNbFlyClicks = 2;
if ( _rMEvt.GetClicks( ) < nNbFlyClicks )
@@ -4964,9 +4965,10 @@ void SwEditWin::Command( const CommandEvent& rCEvt )
// Don't trigger the command on a frame anchored to header/footer is not editing it
FrameControlType eControl;
bool bOverFly = false;
- bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly );
+ bool bPageAnchored = false;
+ bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored );
// !bOverHeaderFooterFly doesn't mean we have a frame to select
- if ( rCEvt.IsMouseEvent( ) &&
+ if ( !bPageAnchored && rCEvt.IsMouseEvent( ) &&
( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) ||
( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly ) ) )
{
@@ -5950,13 +5952,13 @@ bool SwEditWin::IsInHeaderFooter( const Point &rDocPt, FrameControlType &rContro
return false;
}
-bool SwEditWin::IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly ) const
+bool SwEditWin::IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly, bool& bPageAnchored ) const
{
bool bRet = false;
Point aPt( rDocPos );
SwWrtShell &rSh = rView.GetWrtShell();
SwPaM aPam( *rSh.GetCurrentShellCursor().GetPoint() );
- rSh.GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
+ rSh.GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt, NULL, true );
const SwStartNode* pStartFly = aPam.GetPoint()->nNode.GetNode().FindFlyStartNode();
if ( pStartFly )
@@ -5977,6 +5979,8 @@ bool SwEditWin::IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& r
else if ( bInFooter )
rControl = Footer;
}
+ else
+ bPageAnchored = pFlyFmt->GetAnchor( ).GetAnchorId( ) == FLY_AT_PAGE;
}
}
else
diff --git a/sw/source/ui/inc/edtwin.hxx b/sw/source/ui/inc/edtwin.hxx
index cdc9fdf71f18..5c15e325f892 100644
--- a/sw/source/ui/inc/edtwin.hxx
+++ b/sw/source/ui/inc/edtwin.hxx
@@ -228,7 +228,7 @@ protected:
/// Returns true if in header/footer area, or in the header/footer control.
bool IsInHeaderFooter( const Point &rDocPt, FrameControlType &rControl ) const;
- bool IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly ) const;
+ bool IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly, bool& bPageAnchored ) const;
public:
void UpdatePointer(const Point &, sal_uInt16 nButtons = 0);