1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
21 #include <comphelper/lok.hxx>
22 #include <svx/svdview.hxx>
23 #include <svx/svdobj.hxx>
24 #include <svl/ptitem.hxx>
25 #include <editeng/sizeitem.hxx>
26 #include <sfx2/request.hxx>
27 #include <sfx2/bindings.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <fmtclds.hxx>
34 #include <drawbase.hxx>
36 #include <swmodule.hxx>
38 #include <SwCapObjType.hxx>
39 #include <SwRewriter.hxx>
40 #include <strings.hrc>
42 using namespace ::com::sun::star
;
44 SwDrawBase::SwDrawBase(SwWrtShell
* pSwWrtShell
, SwEditWin
* pWindow
, SwView
* pSwView
) :
52 if ( !m_pSh
->HasDrawView() )
53 m_pSh
->MakeDrawView();
56 SwDrawBase::~SwDrawBase()
58 if (m_pView
->GetWrtShellPtr()) // In the view-dtor could the wrtsh already been deleted...
59 m_pSh
->GetDrawView()->SetEditMode();
62 bool SwDrawBase::MouseButtonDown(const MouseEvent
& rMEvt
)
66 SdrView
*pSdrView
= m_pSh
->GetDrawView();
69 pSdrView
->SetOrtho(doConstructOrthogonal() ? !rMEvt
.IsShift() : rMEvt
.IsShift());
70 pSdrView
->SetAngleSnapEnabled(rMEvt
.IsShift());
74 pSdrView
->SetCreate1stPointAsCenter(true);
75 pSdrView
->SetResizeAtCenter(true);
79 pSdrView
->SetCreate1stPointAsCenter(false);
80 pSdrView
->SetResizeAtCenter(false);
84 SdrHitKind eHit
= pSdrView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
86 // Only new object, if not in the basic mode (or pure selection mode).
87 if (rMEvt
.IsLeft() && !m_pWin
->IsDrawAction())
89 if (IsCreateObj() && (eHit
== SdrHitKind::UnmarkedObject
|| eHit
== SdrHitKind::NONE
|| m_pSh
->IsDrawCreate()))
91 g_bNoInterrupt
= true;
92 m_pWin
->CaptureMouse();
94 m_aStartPos
= m_pWin
->PixelToLogic(rMEvt
.GetPosPixel());
96 bReturn
= m_pSh
->BeginCreate(m_pWin
->GetSdrDrawMode(), m_aStartPos
);
101 m_pWin
->SetDrawAction(true);
103 else if (!pSdrView
->IsAction())
106 m_pWin
->CaptureMouse();
107 m_aStartPos
= m_pWin
->PixelToLogic(rMEvt
.GetPosPixel());
108 sal_uInt16 nEditMode
= m_pWin
->GetBezierMode();
110 if (eHit
== SdrHitKind::Handle
&& aVEvt
.mpHdl
->GetKind() == SdrHdlKind::BezierWeight
)
113 g_bNoInterrupt
= true;
114 bReturn
= pSdrView
->BegDragObj(m_aStartPos
, nullptr, aVEvt
.mpHdl
);
115 m_pWin
->SetDrawAction(true);
117 else if (eHit
== SdrHitKind::MarkedObject
&& nEditMode
== SID_BEZIER_INSERT
)
120 g_bNoInterrupt
= true;
121 bReturn
= pSdrView
->BegInsObjPoint(m_aStartPos
, rMEvt
.IsMod1());
122 m_pWin
->SetDrawAction(true);
124 else if (eHit
== SdrHitKind::MarkedObject
&& rMEvt
.IsMod1())
127 if (!rMEvt
.IsShift())
128 pSdrView
->UnmarkAllPoints();
130 bReturn
= pSdrView
->BegMarkPoints(m_aStartPos
);
131 m_pWin
->SetDrawAction(true);
133 else if (eHit
== SdrHitKind::MarkedObject
&& !rMEvt
.IsShift() && !rMEvt
.IsMod2())
138 else if (eHit
== SdrHitKind::Handle
)
141 if (pSdrView
->HasMarkablePoints() && (!pSdrView
->IsPointMarked(*aVEvt
.mpHdl
) || rMEvt
.IsShift()))
143 SdrHdl
* pHdl
= nullptr;
145 if (!rMEvt
.IsShift())
147 pSdrView
->UnmarkAllPoints();
148 pHdl
= pSdrView
->PickHandle(m_aStartPos
);
152 if (pSdrView
->IsPointMarked(*aVEvt
.mpHdl
))
154 bReturn
= pSdrView
->UnmarkPoint(*aVEvt
.mpHdl
);
159 pHdl
= pSdrView
->PickHandle(m_aStartPos
);
165 g_bNoInterrupt
= true;
166 pSdrView
->MarkPoint(*pHdl
);
172 // Select or drag object
173 if (m_pSh
->IsObjSelectable(m_aStartPos
) && eHit
== SdrHitKind::UnmarkedObject
)
175 if (pSdrView
->HasMarkablePoints())
176 pSdrView
->UnmarkAllPoints();
178 g_bNoInterrupt
= false;
179 // Use drag in edtwin
183 g_bNoInterrupt
= true;
185 if (m_pSh
->IsObjSelected())
187 if (!rMEvt
.IsShift())
189 if (!pSdrView
->HasMarkablePoints())
191 bool bUnlockView
= !m_pSh
->IsViewLocked();
192 m_pSh
->LockView( true ); //lock visible section
193 m_pSh
->SelectObj(Point(LONG_MAX
, LONG_MAX
)); // deselect all
195 m_pSh
->LockView( false );
198 pSdrView
->UnmarkAllPoints();
201 if (!m_pSh
->IsSelFrameMode())
202 m_pSh
->EnterSelFrameMode();
204 bReturn
= m_pSh
->BeginMark(m_aStartPos
);
206 m_pWin
->SetDrawAction(true);
215 bool SwDrawBase::MouseMove(const MouseEvent
& rMEvt
)
217 SdrView
*pSdrView
= m_pSh
->GetDrawView();
218 Point
aPnt(m_pWin
->PixelToLogic(rMEvt
.GetPosPixel()));
221 if (IsCreateObj() && !m_pWin
->IsDrawSelMode() && pSdrView
->IsCreateObj())
224 pSdrView
->SetOrtho(doConstructOrthogonal() ? !rMEvt
.IsShift() : rMEvt
.IsShift());
225 pSdrView
->SetAngleSnapEnabled(rMEvt
.IsShift());
227 m_pSh
->MoveCreate(aPnt
);
230 else if (pSdrView
->IsAction() || pSdrView
->IsInsObjPoint() || pSdrView
->IsMarkPoints())
232 m_pSh
->MoveMark(aPnt
);
239 bool SwDrawBase::MouseButtonUp(const MouseEvent
& rMEvt
)
241 bool bReturn
= false;
242 bool bCheckShell
= false;
243 bool bAutoCap
= false;
245 Point
aPnt(m_pWin
->PixelToLogic(rMEvt
.GetPosPixel()));
247 if (IsCreateObj() && m_pSh
->IsDrawCreate() && !m_pWin
->IsDrawSelMode())
249 const SdrObjKind nDrawMode
= m_pWin
->GetSdrDrawMode();
250 //objects with multiple point may end at the start position
251 bool bMultiPoint
= SdrObjKind::PolyLine
== nDrawMode
||
252 SdrObjKind::Polygon
== nDrawMode
||
253 SdrObjKind::PathLine
== nDrawMode
||
254 SdrObjKind::PathFill
== nDrawMode
||
255 SdrObjKind::FreehandLine
== nDrawMode
||
256 SdrObjKind::FreehandFill
== nDrawMode
;
259 m_pSh
->BreakCreate();
260 m_pView
->LeaveDrawCreate();
264 if (SdrObjKind::NewFrame
== nDrawMode
)
266 SwRewriter aRewriter
;
268 aRewriter
.AddRule(UndoArg1
, SwResId(STR_FRAME
));
269 m_pSh
->StartUndo(SwUndoId::INSERT
, &aRewriter
);
272 bool didCreate
= m_pSh
->EndCreate(SdrCreateCmd::ForceEnd
);
273 if(!didCreate
&& !bMultiPoint
)
275 CreateDefaultObjectAtPosWithSize(aPnt
, Size(1000, 1000));
278 if (SdrObjKind::NewFrame
== nDrawMode
) // Text border inserted
280 uno::Reference
< frame::XDispatchRecorder
> xRecorder
=
281 m_pSh
->GetView().GetViewFrame().GetBindings().GetRecorder();
282 if ( xRecorder
.is() )
284 SfxRequest
aReq(m_pSh
->GetView().GetViewFrame(), FN_INSERT_FRAME
);
285 aReq
.AppendItem(SfxUInt16Item( FN_INSERT_FRAME
,
286 static_cast<sal_uInt16
>(RndStdIds::FLY_AT_PARA
) ));
287 aReq
.AppendItem(SfxPointItem( FN_PARAM_1
, m_pSh
->GetAnchorObjDiff()));
288 aReq
.AppendItem(SvxSizeItem( FN_PARAM_2
, m_pSh
->GetObjSize()));
292 if(m_pWin
->GetFrameColCount() > 1)
294 SfxItemSetFixed
<RES_COL
,RES_COL
> aSet(m_pView
->GetPool());
295 SwFormatCol
aCol(aSet
.Get(RES_COL
));
296 aCol
.Init(m_pWin
->GetFrameColCount(), aCol
.GetGutterWidth(), aCol
.GetWishWidth());
298 // Template AutoUpdate
299 SwFrameFormat
* pFormat
= m_pSh
->GetSelectedFrameFormat();
300 if(pFormat
&& pFormat
->IsAutoUpdateOnDirectFormat())
301 m_pSh
->AutoUpdateFrame(pFormat
, aSet
);
303 m_pSh
->SetFlyFrameAttr( aSet
);
306 if (m_pWin
->GetSdrDrawMode() == SdrObjKind::NewFrame
)
314 EnterSelectMode(rMEvt
);
318 SdrView
*pSdrView
= m_pSh
->GetDrawView();
320 if (!pSdrView
->HasMarkablePoints())
323 if ((m_pSh
->GetDrawView()->IsMarkObj() || m_pSh
->GetDrawView()->IsMarkPoints())
326 bReturn
= m_pSh
->EndMark();
328 m_pWin
->SetDrawAction(false);
330 if (aPnt
== m_aStartPos
&& m_pSh
->IsObjSelectable(aPnt
))
332 m_pSh
->SelectObj(aPnt
, ( rMEvt
.IsShift() &&
333 m_pSh
->IsSelFrameMode()) ? SW_ADD_SELECT
: 0);
335 if (!m_pSh
->IsObjSelected())
337 m_pView
->LeaveDrawCreate(); // Switch to selection mode
339 m_pSh
->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW
);
341 if (m_pSh
->IsSelFrameMode())
342 m_pSh
->LeaveSelFrameMode();
346 bCheckShell
= true; // if necessary turn on BezierShell
348 else if (!m_pSh
->IsObjSelected() && !m_pWin
->IsDrawAction())
350 if (m_pSh
->IsObjSelectable(aPnt
))
351 m_pSh
->SelectObj(aPnt
, ( rMEvt
.IsShift() &&
352 m_pSh
->IsSelFrameMode() ) ? SW_ADD_SELECT
: 0 );
355 m_pView
->LeaveDrawCreate();
356 if (m_pSh
->IsSelFrameMode())
357 m_pSh
->LeaveSelFrameMode();
368 if ( pSdrView
->IsAction() )
370 if ( pSdrView
->IsInsObjPoint() )
371 bReturn
= pSdrView
->EndInsObjPoint(SdrCreateCmd::ForceEnd
);
372 else if (pSdrView
->IsMarkPoints() )
373 bReturn
= pSdrView
->EndMarkPoints();
376 pSdrView
->EndAction();
379 m_pWin
->SetDrawAction(false);
381 if (aPnt
== m_aStartPos
)
383 if (!m_pSh
->IsObjSelectable(aPnt
))
384 m_pSh
->SelectObj(Point(LONG_MAX
, LONG_MAX
));
387 if (!rMEvt
.IsShift())
388 pSdrView
->UnmarkAllPoints();
389 m_pSh
->SelectObj(aPnt
, (rMEvt
.IsShift() &&
390 m_pSh
->IsSelFrameMode()) ? SW_ADD_SELECT
:0);
393 if (!m_pSh
->IsObjSelected())
395 m_pView
->LeaveDrawCreate(); // Switch to selection mode
397 m_pSh
->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW
);
399 if (m_pSh
->IsSelFrameMode())
400 m_pSh
->LeaveSelFrameMode();
404 bCheckShell
= true; // if necessary turn on BezierShell
410 if (!m_pSh
->IsObjSelected() && !m_pWin
->IsDrawAction())
412 m_pView
->LeaveDrawCreate();
413 if (m_pSh
->IsSelFrameMode())
414 m_pSh
->LeaveSelFrameMode();
423 m_pView
->AttrChangedNotify(nullptr); // if necessary turn on BezierShell
425 //!!!!!!!!!! Attention suicide !!!!!!!!!!! Everything should be renewed once
427 m_pView
->AutoCaption(FRAME_CAP
); //Can currently only be FRAME, otherwise convert
432 void SwDrawBase::Activate(const sal_uInt16 nSlot
)
435 SdrView
*pSdrView
= m_pSh
->GetDrawView();
437 pSdrView
->SetCurrentObj(m_pWin
->GetSdrDrawMode());
438 pSdrView
->SetEditMode(false);
444 void SwDrawBase::Deactivate()
446 SdrView
*pSdrView
= m_pSh
->GetDrawView();
447 pSdrView
->SetOrtho(false);
448 pSdrView
->SetAngleSnapEnabled(false);
450 if (m_pWin
->IsDrawAction() && m_pSh
->IsDrawCreate())
451 m_pSh
->BreakCreate();
453 m_pWin
->SetDrawAction(false);
455 if (m_pWin
->IsMouseCaptured())
456 m_pWin
->ReleaseMouse();
457 g_bNoInterrupt
= false;
459 if (m_pWin
->GetApplyTemplate())
460 m_pWin
->SetApplyTemplate(SwApplyTemplate());
461 m_pSh
->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW
);
464 // Process keyboard events
466 // If a KeyEvent is processed then the return value is true, otherwise
469 void SwDrawBase::BreakCreate()
471 m_pSh
->BreakCreate();
472 m_pWin
->SetDrawAction(false);
473 m_pWin
->ReleaseMouse();
478 void SwDrawBase::SetDrawPointer()
480 SdrView
*pSdrView
= m_pSh
->GetDrawView();
481 Point
aPnt(m_pWin
->OutputToScreenPixel(m_pWin
->GetPointerPosPixel()));
482 aPnt
= m_pWin
->PixelToLogic(m_pWin
->ScreenToOutputPixel(aPnt
));
483 PointerStyle aPointTyp
= pSdrView
->GetPreferredPointer(aPnt
, m_pSh
->GetOut());
484 m_pWin
->SetPointer(aPointTyp
);
487 // If necessary switch into selection mode
489 void SwDrawBase::EnterSelectMode(const MouseEvent
& rMEvt
)
491 m_pWin
->SetDrawAction(false);
493 if (m_pSh
->IsObjSelected() || m_pWin
->IsDrawAction())
496 Point
aPnt(m_pWin
->PixelToLogic(rMEvt
.GetPosPixel()));
498 if (m_pSh
->IsObjSelectable(aPnt
))
500 m_pSh
->SelectObj(aPnt
);
501 if (rMEvt
.GetModifier() == KEY_SHIFT
|| !m_pSh
->IsObjSelected())
503 m_pView
->LeaveDrawCreate(); // Switch to selection mode
505 m_pSh
->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW
);
510 m_pView
->LeaveDrawCreate();
511 if (m_pSh
->IsSelFrameMode())
512 m_pSh
->LeaveSelFrameMode();
517 void SwDrawBase::CreateDefaultObject()
519 constexpr tools::Long constTwips_3cm
= o3tl::toTwips(3, o3tl::Length::cm
);
521 Point aStartPos
= GetDefaultCenterPos();
522 Point
aEndPos(aStartPos
);
523 aStartPos
.AdjustX(-constTwips_3cm
);
524 aStartPos
.AdjustY(-constTwips_3cm
);
525 aEndPos
.AdjustX(constTwips_3cm
);
526 aEndPos
.AdjustY(constTwips_3cm
);
527 tools::Rectangle
aRect(aStartPos
, aEndPos
);
528 m_pSh
->CreateDefaultShape(m_pWin
->GetSdrDrawMode(), aRect
, m_nSlotId
);
531 void SwDrawBase::CreateDefaultObjectAtPosWithSize(Point aPos
, Size aSize
)
533 aPos
.AdjustX(-sal_Int32(aSize
.getWidth() / 2));
534 aPos
.AdjustY(-sal_Int32(aSize
.getHeight() / 2));
536 SdrView
* sdrView
= m_pView
->GetDrawView();
537 SdrPageView
*pPV
= sdrView
->GetSdrPageView();
539 if(sdrView
->IsSnapEnabled())
540 aPos
= sdrView
->GetSnapPos(aPos
, pPV
);
542 ::tools::Rectangle
aNewObjectRectangle(aPos
, aSize
);
543 m_pSh
->CreateDefaultShape(m_pWin
->GetSdrDrawMode(), aNewObjectRectangle
, m_nSlotId
);
546 Point
SwDrawBase::GetDefaultCenterPos() const
548 Size
aDocSz(m_pSh
->GetDocSize());
550 SwRect
aVisArea(m_pSh
->VisArea());
551 if (comphelper::LibreOfficeKit::isActive())
553 aVisArea
= SwRect(m_pSh
->getLOKVisibleArea());
554 aVisArea
.Intersection(SwRect(Point(), aDocSz
));
557 Point aCenter
= aVisArea
.Center();
558 // To increase the chance that aCenter actually falls somewhere on a page (rather than on the
559 // background between pages), keep it centered horizontally for the "Single-page view"
560 // (GetViewLayoutColumns() == 1) and "Book view" (GetViewLayoutColumns() == 2) cases that
561 // display the pages centered on the background:
562 if (aVisArea
.Width() > aDocSz
.Width() && m_pSh
->GetViewOptions()->GetViewLayoutColumns() == 0)
563 aCenter
.setX(aDocSz
.Width() / 2 + aVisArea
.Left());
564 if (aVisArea
.Height() > aDocSz
.Height())
565 aCenter
.setY(aDocSz
.Height() / 2 + aVisArea
.Top());
571 bool SwDrawBase::doConstructOrthogonal() const
573 return ( m_nSlotId
== SID_DRAW_XPOLYGON
|| m_nSlotId
== SID_DRAW_XPOLYGON_NOFILL
|| m_nSlotId
== SID_DRAW_XLINE
);
576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */