1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <svx/svdsnpv.hxx>
33 #include <svx/svdetc.hxx>
34 #include <svx/svdobj.hxx>
35 #include <svx/svdpagv.hxx>
36 #include <svx/svdpage.hxx>
37 #include "svx/svditer.hxx"
38 #include <svx/sdr/overlay/overlayobjectlist.hxx>
39 #include <svx/sdr/overlay/overlaycrosshair.hxx>
40 #include <svx/sdr/overlay/overlayhelpline.hxx>
41 #include <svx/sdr/overlay/overlaymanager.hxx>
42 #include <basegfx/matrix/b2dhommatrix.hxx>
43 #include <svx/sdrpaintwindow.hxx>
45 ////////////////////////////////////////////////////////////////////////////////////////////////////
46 class ImplPageOriginOverlay
49 ::sdr::overlay::OverlayObjectList maObjects
;
51 // The current position in logical coodinates
52 basegfx::B2DPoint maPosition
;
55 ImplPageOriginOverlay(const SdrPaintView
& rView
, const basegfx::B2DPoint
& rStartPos
);
56 ~ImplPageOriginOverlay();
58 void SetPosition(const basegfx::B2DPoint
& rNewPosition
);
61 ImplPageOriginOverlay::ImplPageOriginOverlay(const SdrPaintView
& rView
, const basegfx::B2DPoint
& rStartPos
)
62 : maPosition(rStartPos
)
64 for(sal_uInt32
a(0L); a
< rView
.PaintWindowCount(); a
++)
66 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
67 rtl::Reference
< ::sdr::overlay::OverlayManager
> xTargetOverlay
= pCandidate
->GetOverlayManager();
69 if (xTargetOverlay
.is())
71 ::sdr::overlay::OverlayCrosshairStriped
* aNew
= new ::sdr::overlay::OverlayCrosshairStriped(
73 xTargetOverlay
->add(*aNew
);
74 maObjects
.append(*aNew
);
79 ImplPageOriginOverlay::~ImplPageOriginOverlay()
81 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
82 // That destructor calls clear() at the list which removes all objects from the
83 // OverlayManager and deletes them.
86 void ImplPageOriginOverlay::SetPosition(const basegfx::B2DPoint
& rNewPosition
)
88 if(rNewPosition
!= maPosition
)
90 // apply to OverlayObjects
91 for(sal_uInt32
a(0); a
< maObjects
.count(); a
++)
93 sdr::overlay::OverlayCrosshairStriped
* pCandidate
=
94 static_cast< sdr::overlay::OverlayCrosshairStriped
* >(&maObjects
.getOverlayObject(a
));
98 pCandidate
->setBasePosition(rNewPosition
);
102 // remember new position
103 maPosition
= rNewPosition
;
107 ////////////////////////////////////////////////////////////////////////////////////////////////////
108 class ImplHelpLineOverlay
110 // The OverlayObjects
111 ::sdr::overlay::OverlayObjectList maObjects
;
113 // The current position in logical coodinates
114 basegfx::B2DPoint maPosition
;
116 // HelpLine specific stuff
117 SdrPageView
* mpPageView
;
118 sal_uInt16 mnHelpLineNumber
;
119 SdrHelpLineKind meHelpLineKind
;
122 ImplHelpLineOverlay(const SdrPaintView
& rView
, const basegfx::B2DPoint
& rStartPos
,
123 SdrPageView
* pPageView
, sal_uInt16 nHelpLineNumber
, SdrHelpLineKind eKind
);
124 ~ImplHelpLineOverlay();
126 void SetPosition(const basegfx::B2DPoint
& rNewPosition
);
128 // access to HelpLine specific stuff
129 SdrPageView
* GetPageView() const { return mpPageView
; }
130 sal_uInt16
GetHelpLineNumber() const { return mnHelpLineNumber
; }
131 SdrHelpLineKind
GetHelpLineKind() const { return meHelpLineKind
; }
134 ImplHelpLineOverlay::ImplHelpLineOverlay(
135 const SdrPaintView
& rView
, const basegfx::B2DPoint
& rStartPos
,
136 SdrPageView
* pPageView
, sal_uInt16 nHelpLineNumber
, SdrHelpLineKind eKind
)
137 : maPosition(rStartPos
),
138 mpPageView(pPageView
),
139 mnHelpLineNumber(nHelpLineNumber
),
140 meHelpLineKind(eKind
)
142 for(sal_uInt32
a(0L); a
< rView
.PaintWindowCount(); a
++)
144 SdrPaintWindow
* pCandidate
= rView
.GetPaintWindow(a
);
145 rtl::Reference
< ::sdr::overlay::OverlayManager
> xTargetOverlay
= pCandidate
->GetOverlayManager();
147 if (xTargetOverlay
.is())
149 ::sdr::overlay::OverlayHelplineStriped
* aNew
= new ::sdr::overlay::OverlayHelplineStriped(
150 maPosition
, meHelpLineKind
);
151 xTargetOverlay
->add(*aNew
);
152 maObjects
.append(*aNew
);
157 ImplHelpLineOverlay::~ImplHelpLineOverlay()
159 // The OverlayObjects are cleared using the destructor of OverlayObjectList.
160 // That destructor calls clear() at the list which removes all objects from the
161 // OverlayManager and deletes them.
164 void ImplHelpLineOverlay::SetPosition(const basegfx::B2DPoint
& rNewPosition
)
166 if(rNewPosition
!= maPosition
)
168 // apply to OverlayObjects
169 for(sal_uInt32
a(0); a
< maObjects
.count(); a
++)
171 sdr::overlay::OverlayHelplineStriped
* pCandidate
=
172 static_cast< sdr::overlay::OverlayHelplineStriped
* >(&maObjects
.getOverlayObject(a
));
176 pCandidate
->setBasePosition(rNewPosition
);
180 // remember new position
181 maPosition
= rNewPosition
;
186 void SdrSnapView::ClearVars()
191 bSnapTo1Pix
=sal_True
;
197 bMoveMFrmSnap
=sal_True
;
198 bMoveOFrmSnap
=sal_True
;
199 bMoveOPntSnap
=sal_True
;
200 bMoveOConSnap
=sal_True
;
201 bMoveSnapOnlyTopLeft
=sal_False
;
205 bAngleSnapEnab
=sal_False
;
206 bMoveOnlyDragging
=sal_False
;
207 bSlantButShear
=sal_False
;
208 bCrookNoContortion
=sal_False
;
209 eCrookMode
=SDRCROOK_ROTATE
;
210 bHlplFixed
=sal_False
;
211 bEliminatePolyPoints
=sal_False
;
212 nEliminatePolyPointLimitAngle
=0;
218 SdrSnapView::SdrSnapView(SdrModel
* pModel1
, OutputDevice
* pOut
):
219 SdrPaintView(pModel1
,pOut
),
220 mpPageOriginOverlay(0L),
221 mpHelpLineOverlay(0L)
226 SdrSnapView::~SdrSnapView()
232 ////////////////////////////////////////////////////////////////////////////////////////////////////
234 sal_Bool
SdrSnapView::IsAction() const
236 return IsSetPageOrg() || IsDragHelpLine() || SdrPaintView::IsAction();
239 void SdrSnapView::MovAction(const Point
& rPnt
)
241 SdrPaintView::MovAction(rPnt
);
242 if (IsSetPageOrg()) {
245 if (IsDragHelpLine()) {
246 MovDragHelpLine(rPnt
);
250 void SdrSnapView::EndAction()
252 if (IsSetPageOrg()) {
255 if (IsDragHelpLine()) {
258 SdrPaintView::EndAction();
261 void SdrSnapView::BckAction()
265 SdrPaintView::BckAction();
268 void SdrSnapView::BrkAction()
272 SdrPaintView::BrkAction();
275 void SdrSnapView::TakeActionRect(Rectangle
& rRect
) const
277 if (IsSetPageOrg() || IsDragHelpLine()) {
278 rRect
=Rectangle(aDragStat
.GetNow(),aDragStat
.GetNow());
280 SdrPaintView::TakeActionRect(rRect
);
284 ////////////////////////////////////////////////////////////////////////////////////////////////////
286 Point
SdrSnapView::GetSnapPos(const Point
& rPnt
, const SdrPageView
* pPV
) const
293 #define NOT_SNAPPED 0x7FFFFFFF
294 sal_uInt16
SdrSnapView::SnapPos(Point
& rPnt
, const SdrPageView
* pPV
) const
296 if (!bSnapEnab
) return SDRSNAP_NOTSNAPPED
;
300 pPV
=GetSdrPageView();
301 if (pPV
==NULL
) return SDRSNAP_NOTSNAPPED
;
307 long mx
=aMagnSiz
.Width();
308 long my
=aMagnSiz
.Height();
309 if (bHlplVisible
&& bHlplSnap
&& !IsDragHelpLine())
311 const SdrHelpLineList
& rHLL
=pPV
->GetHelpLines();
312 sal_uInt16 nAnz
=rHLL
.GetCount();
313 for (sal_uInt16 i
=nAnz
; i
>0;) {
315 const SdrHelpLine
& rHL
=rHLL
[i
];
316 const Point
& rPos
=rHL
.GetPos();
317 switch (rHL
.GetKind()) {
318 case SDRHELPLINE_VERTICAL
: {
320 if (Abs(a
)<=mx
) { dx1
=-a
; if (Abs(dx1
)<Abs(dx
)) dx
=dx1
; }
322 case SDRHELPLINE_HORIZONTAL
: {
324 if (Abs(b
)<=my
) { dy1
=-b
; if (Abs(dy1
)<Abs(dy
)) dy
=dy1
; }
326 case SDRHELPLINE_POINT
: {
329 if (Abs(a
)<=mx
&& Abs(b
)<=my
) {
331 if (Abs(dx1
)<Abs(dx
) && Abs(dy1
)<Abs(dy
)) { dx
=dx1
; dy
=dy1
; }
337 if (bBordVisible
&& bBordSnap
) {
338 SdrPage
* pPage
=pPV
->GetPage();
339 long xs
=pPage
->GetWdt();
340 long ys
=pPage
->GetHgt();
341 long lft
=pPage
->GetLftBorder();
342 long rgt
=pPage
->GetRgtBorder();
343 long upp
=pPage
->GetUppBorder();
344 long lwr
=pPage
->GetLwrBorder();
346 a
=x
- lft
; if (Abs(a
)<=mx
) { dx1
=-a
; if (Abs(dx1
)<Abs(dx
)) dx
=dx1
; } // left margin
347 a
=x
-(xs
-rgt
); if (Abs(a
)<=mx
) { dx1
=-a
; if (Abs(dx1
)<Abs(dx
)) dx
=dx1
; } // right margin
348 a
=x
; if (Abs(a
)<=mx
) { dx1
=-a
; if (Abs(dx1
)<Abs(dx
)) dx
=dx1
; } // left edge of paper
349 a
=x
- xs
; if (Abs(a
)<=mx
) { dx1
=-a
; if (Abs(dx1
)<Abs(dx
)) dx
=dx1
; } // right edge of paper
350 a
=y
- upp
; if (Abs(a
)<=my
) { dy1
=-a
; if (Abs(dy1
)<Abs(dy
)) dy
=dy1
; } // left margin
351 a
=y
-(ys
-lwr
); if (Abs(a
)<=my
) { dy1
=-a
; if (Abs(dy1
)<Abs(dy
)) dy
=dy1
; } // right margin
352 a
=y
; if (Abs(a
)<=my
) { dy1
=-a
; if (Abs(dy1
)<Abs(dy
)) dy
=dy1
; } // left edge of paper
353 a
=y
- ys
; if (Abs(a
)<=my
) { dy1
=-a
; if (Abs(dy1
)<Abs(dy
)) dy
=dy1
; } // right edge of paper
355 if (bOFrmSnap
|| bOPntSnap
) {
356 sal_uIntPtr nMaxPointSnapCount
=200;
357 sal_uIntPtr nMaxFrameSnapCount
=200;
359 // go back to IM_DEEPNOGROUPS runthrough for snap to object comparisons
360 SdrObjListIter
aIter(*pPV
->GetPage(),IM_DEEPNOGROUPS
,sal_True
);
362 while (aIter
.IsMore() && (nMaxPointSnapCount
>0 || nMaxFrameSnapCount
>0)) {
363 SdrObject
* pO
=aIter
.Next();
364 Rectangle
aRect(pO
->GetCurrentBoundRect());
369 if (aRect
.IsInside(rPnt
)) {
370 if (bOPntSnap
&& nMaxPointSnapCount
>0)
372 sal_uInt32
nAnz(pO
->GetSnapPointCount());
373 for (sal_uInt32
i(0L); i
< nAnz
&& nMaxPointSnapCount
> 0L; i
++)
375 Point
aP(pO
->GetSnapPoint(i
));
378 if (Abs(dx1
)<=mx
&& Abs(dy1
)<=my
&& Abs(dx1
)<Abs(dx
) && Abs(dy1
)<Abs(dy
)) {
382 nMaxPointSnapCount
--;
385 if (bOFrmSnap
&& nMaxFrameSnapCount
>0) {
386 Rectangle
aLog(pO
->GetSnapRect());
392 if (aR1
.IsInside(rPnt
)) {
393 if (Abs(x
-aLog
.Left ())<=mx
) { dx1
=-(x
-aLog
.Left ()); if (Abs(dx1
)<Abs(dx
)) dx
=dx1
; }
394 if (Abs(x
-aLog
.Right ())<=mx
) { dx1
=-(x
-aLog
.Right ()); if (Abs(dx1
)<Abs(dx
)) dx
=dx1
; }
395 if (Abs(y
-aLog
.Top ())<=my
) { dy1
=-(y
-aLog
.Top ()); if (Abs(dy1
)<Abs(dy
)) dy
=dy1
; }
396 if (Abs(y
-aLog
.Bottom())<=my
) { dy1
=-(y
-aLog
.Bottom()); if (Abs(dy1
)<Abs(dy
)) dy
=dy1
; }
398 nMaxFrameSnapCount
--;
405 double fSnapWidth
= aSnapWdtX
;
406 if(dx
== NOT_SNAPPED
&& fSnapWidth
!= 0.0)
408 double fx
= (double)x
;
410 // round instead of trunc
411 if(fx
- (double)pPV
->GetPageOrigin().X() >= 0.0)
412 fx
+= fSnapWidth
/ 2.0;
414 fx
-= fSnapWidth
/ 2.0;
416 x
= (long)((fx
- (double)pPV
->GetPageOrigin().X()) / fSnapWidth
);
417 x
= (long)((double)x
* fSnapWidth
+ (double)pPV
->GetPageOrigin().X());
420 fSnapWidth
= aSnapWdtY
;
421 if(dy
== NOT_SNAPPED
&& fSnapWidth
)
423 double fy
= (double)y
;
425 // round instead of trunc
426 if(fy
- (double)pPV
->GetPageOrigin().Y() >= 0.0)
427 fy
+= fSnapWidth
/ 2.0;
429 fy
-= fSnapWidth
/ 2.0;
431 y
= (long)((fy
- (double)pPV
->GetPageOrigin().Y()) / fSnapWidth
);
432 y
= (long)((double)y
* fSnapWidth
+ (double)pPV
->GetPageOrigin().Y());
436 sal_Bool bRet
=SDRSNAP_NOTSNAPPED
;
437 if (dx
==NOT_SNAPPED
) dx
=0; else bRet
|=SDRSNAP_XSNAPPED
;
438 if (dy
==NOT_SNAPPED
) dy
=0; else bRet
|=SDRSNAP_YSNAPPED
;
444 void SdrSnapView::CheckSnap(const Point
& rPt
, const SdrPageView
* pPV
, long& nBestXSnap
, long& nBestYSnap
, bool& bXSnapped
, bool& bYSnapped
) const
447 sal_uInt16 nRet
=SnapPos(aPt
,pPV
);
449 if ((nRet
& SDRSNAP_XSNAPPED
) !=0) {
451 if (Abs(aPt
.X())<Abs(nBestXSnap
)) {
459 if ((nRet
& SDRSNAP_YSNAPPED
) !=0) {
461 if (Abs(aPt
.Y())<Abs(nBestYSnap
)) {
471 ////////////////////////////////////////////////////////////////////////////////////////////////////
473 sal_Bool
SdrSnapView::BegSetPageOrg(const Point
& rPnt
)
477 DBG_ASSERT(0L == mpPageOriginOverlay
, "SdrSnapView::BegSetPageOrg: There exists a ImplPageOriginOverlay (!)");
478 basegfx::B2DPoint
aStartPos(rPnt
.X(), rPnt
.Y());
479 mpPageOriginOverlay
= new ImplPageOriginOverlay(*this, aStartPos
);
480 aDragStat
.Reset(GetSnapPos(rPnt
,NULL
));
485 void SdrSnapView::MovSetPageOrg(const Point
& rPnt
)
489 aDragStat
.NextMove(GetSnapPos(rPnt
,NULL
));
490 DBG_ASSERT(mpPageOriginOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
491 basegfx::B2DPoint
aNewPos(aDragStat
.GetNow().X(), aDragStat
.GetNow().Y());
492 mpPageOriginOverlay
->SetPosition(aNewPos
);
496 sal_Bool
SdrSnapView::EndSetPageOrg()
498 sal_Bool
bRet(sal_False
);
502 SdrPageView
* pPV
= GetSdrPageView();
506 Point
aPnt(aDragStat
.GetNow());
507 pPV
->SetPageOrigin(aPnt
);
518 void SdrSnapView::BrkSetPageOrg()
522 DBG_ASSERT(mpPageOriginOverlay
, "SdrSnapView::MovSetPageOrg: no ImplPageOriginOverlay (!)");
523 delete mpPageOriginOverlay
;
524 mpPageOriginOverlay
= 0L;
528 ////////////////////////////////////////////////////////////////////////////////////////////////////
530 sal_Bool
SdrSnapView::PickHelpLine(const Point
& rPnt
, short nTol
, const OutputDevice
& rOut
, sal_uInt16
& rnHelpLineNum
, SdrPageView
*& rpPV
) const
533 nTol
=ImpGetHitTolLogic(nTol
,&rOut
);
534 SdrPageView
* pPV
= GetSdrPageView();
539 sal_uInt16 nIndex
=pPV
->GetHelpLines().HitTest(aPnt
,sal_uInt16(nTol
),rOut
);
540 if (nIndex
!=SDRHELPLINE_NOTFOUND
) {
542 rnHelpLineNum
=nIndex
;
549 // start HelpLine drag for new HelpLine
550 sal_Bool
SdrSnapView::BegDragHelpLine(sal_uInt16 nHelpLineNum
, SdrPageView
* pPV
)
552 sal_Bool
bRet(sal_False
);
558 if(pPV
&& nHelpLineNum
< pPV
->GetHelpLines().GetCount())
560 const SdrHelpLineList
& rHelpLines
= pPV
->GetHelpLines();
561 const SdrHelpLine
& rHelpLine
= rHelpLines
[nHelpLineNum
];
562 Point aHelpLinePos
= rHelpLine
.GetPos();
563 basegfx::B2DPoint
aStartPos(aHelpLinePos
.X(), aHelpLinePos
.Y());
565 DBG_ASSERT(0L == mpHelpLineOverlay
, "SdrSnapView::BegDragHelpLine: There exists a ImplHelpLineOverlay (!)");
566 mpHelpLineOverlay
= new ImplHelpLineOverlay(*this, aStartPos
, pPV
, nHelpLineNum
, rHelpLine
.GetKind());
568 aDragStat
.Reset(GetSnapPos(aHelpLinePos
, pPV
));
569 aDragStat
.SetMinMove(ImpGetMinMovLogic(-3, 0L));
578 // start HelpLine drag with existing HelpLine
579 sal_Bool
SdrSnapView::BegDragHelpLine(const Point
& rPnt
, SdrHelpLineKind eNewKind
)
581 sal_Bool
bRet(sal_False
);
587 DBG_ASSERT(0L == mpHelpLineOverlay
, "SdrSnapView::BegDragHelpLine: There exists a ImplHelpLineOverlay (!)");
588 basegfx::B2DPoint
aStartPos(rPnt
.X(), rPnt
.Y());
589 mpHelpLineOverlay
= new ImplHelpLineOverlay(*this, aStartPos
, 0L, 0, eNewKind
);
590 aDragStat
.Reset(GetSnapPos(rPnt
, 0L));
597 Pointer
SdrSnapView::GetDraggedHelpLinePointer() const
601 switch(mpHelpLineOverlay
->GetHelpLineKind())
603 case SDRHELPLINE_VERTICAL
: return Pointer(POINTER_ESIZE
);
604 case SDRHELPLINE_HORIZONTAL
: return Pointer(POINTER_SSIZE
);
605 default : return Pointer(POINTER_MOVE
);
609 return Pointer(POINTER_MOVE
);
612 void SdrSnapView::MovDragHelpLine(const Point
& rPnt
)
614 if(IsDragHelpLine() && aDragStat
.CheckMinMoved(rPnt
))
616 Point
aPnt(GetSnapPos(rPnt
, 0L));
618 if(aPnt
!= aDragStat
.GetNow())
620 aDragStat
.NextMove(aPnt
);
621 DBG_ASSERT(mpHelpLineOverlay
, "SdrSnapView::MovDragHelpLine: no ImplHelpLineOverlay (!)");
622 basegfx::B2DPoint
aNewPos(aDragStat
.GetNow().X(), aDragStat
.GetNow().Y());
623 mpHelpLineOverlay
->SetPosition(aNewPos
);
628 sal_Bool
SdrSnapView::EndDragHelpLine()
630 sal_Bool
bRet(sal_False
);
634 if(aDragStat
.IsMinMoved())
636 SdrPageView
* pPageView
= mpHelpLineOverlay
->GetPageView();
640 // moved existing one
641 Point
aPnt(aDragStat
.GetNow());
642 const SdrHelpLineList
& rHelpLines
= pPageView
->GetHelpLines();
643 SdrHelpLine aChangedHelpLine
= rHelpLines
[mpHelpLineOverlay
->GetHelpLineNumber()];
644 aChangedHelpLine
.SetPos(aPnt
);
645 pPageView
->SetHelpLine(mpHelpLineOverlay
->GetHelpLineNumber(), aChangedHelpLine
);
652 pPageView
= GetSdrPageView();
656 Point
aPnt(aDragStat
.GetNow());
657 SdrHelpLine
aNewHelpLine(mpHelpLineOverlay
->GetHelpLineKind(), aPnt
);
658 pPageView
->InsertHelpLine(aNewHelpLine
);
672 void SdrSnapView::BrkDragHelpLine()
676 DBG_ASSERT(mpHelpLineOverlay
, "SdrSnapView::EndDragHelpLine: no ImplHelpLineOverlay (!)");
677 delete mpHelpLineOverlay
;
678 mpHelpLineOverlay
= 0L;
682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */