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 <com/sun/star/presentation/EffectNodeType.hpp>
22 #include <fuconbez.hxx>
23 #include <svx/svdopath.hxx>
24 #include <svl/intitem.hxx>
25 #include <sfx2/dispatch.hxx>
26 #include <svx/svdobj.hxx>
27 #include <sfx2/bindings.hxx>
28 #include <sfx2/request.hxx>
29 #include <sfx2/viewfrm.hxx>
31 #include <svx/svxids.hrc>
32 #include <svx/svdpagv.hxx>
33 #include <svx/xlnclit.hxx>
34 #include <svx/xlntrit.hxx>
35 #include <svx/xlnwtit.hxx>
38 #include <ViewShell.hxx>
39 #include <ViewShellBase.hxx>
42 #include <ToolBarManager.hxx>
43 #include <drawdoc.hxx>
46 #include <basegfx/polygon/b2dpolygon.hxx>
47 #include <basegfx/polygon/b2dpolygontools.hxx>
49 #include <CustomAnimationEffect.hxx>
51 using namespace ::com::sun::star::uno
;
55 /*//Extra attributes coming from parameters
56 sal_uInt16 mnTransparence; // Default: 0
57 OUString msColor; // Default: ""
58 sal_uInt16 mnWidth; // Default: 0
59 OUString msShapeName; // Default: ""*/
60 FuConstructBezierPolygon::FuConstructBezierPolygon (
66 : FuConstruct(pViewSh
, pWin
, pView
, pDoc
, rReq
),
67 nEditMode(SID_BEZIER_MOVE
),
75 /// Checks to see if the request has a parameter of IsSticky:bool=true
76 /// It means that the selected command/button will stay selected after use
77 bool isSticky(SfxRequest
& rReq
)
79 const SfxItemSet
*pArgs
= rReq
.GetArgs ();
82 const SfxBoolItem
* pIsSticky
= rReq
.GetArg
<SfxBoolItem
>(FN_PARAM_4
);
83 if (pIsSticky
&& pIsSticky
->GetValue())
92 rtl::Reference
<FuPoor
> FuConstructBezierPolygon::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
, bool bPermanent
)
94 FuConstructBezierPolygon
* pFunc
;
95 rtl::Reference
<FuPoor
> xFunc( pFunc
= new FuConstructBezierPolygon( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
96 xFunc
->DoExecute(rReq
);
97 pFunc
->SetPermanent(bPermanent
|| isSticky(rReq
));
101 void FuConstructBezierPolygon::DoExecute( SfxRequest
& rReq
)
103 FuConstruct::DoExecute( rReq
);
105 const SfxItemSet
* pArgs
= rReq
.GetArgs();
110 const SfxPoolItem
* pPoolItem
= nullptr;
111 if( SfxItemState::SET
== pArgs
->GetItemState( SID_ADD_MOTION_PATH
, true, &pPoolItem
) )
112 maTargets
= static_cast<const SfxUnoAnyItem
*>( pPoolItem
)->GetValue();
114 if (nSlotId
== SID_DRAW_FREELINE_NOFILL
)
116 const SfxUInt16Item
* pTransparence
= rReq
.GetArg
<SfxUInt16Item
>(FN_PARAM_1
);
117 const SfxStringItem
* pColor
= rReq
.GetArg
<SfxStringItem
>(FN_PARAM_2
);
118 const SfxUInt16Item
* pWidth
= rReq
.GetArg
<SfxUInt16Item
>(FN_PARAM_3
);
119 const SfxStringItem
* pShapeName
= rReq
.GetArg
<SfxStringItem
>(SID_SHAPE_NAME
);
121 if (pTransparence
&& pTransparence
->GetValue() > 0)
123 mnTransparence
= pTransparence
->GetValue();
125 if (pColor
&& !pColor
->GetValue().isEmpty())
127 msColor
= pColor
->GetValue();
129 if (pWidth
&& pWidth
->GetValue() > 0)
131 mnWidth
= pWidth
->GetValue();
133 if (pShapeName
&& !pShapeName
->GetValue().isEmpty())
135 msShapeName
= pShapeName
->GetValue();
140 bool FuConstructBezierPolygon::MouseButtonDown(const MouseEvent
& rMEvt
)
142 bool bReturn
= FuConstruct::MouseButtonDown(rMEvt
);
145 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
147 if (eHit
== SdrHitKind::Handle
|| rMEvt
.IsMod1())
149 mpView
->SetEditMode(SdrViewEditMode::Edit
);
153 mpView
->SetEditMode(SdrViewEditMode::Create
);
156 if (aVEvt
.eEvent
== SdrEventKind::BeginTextEdit
)
158 // here, we do not allow text input
159 aVEvt
.eEvent
= SdrEventKind::BeginDragObj
;
160 mpView
->EnableExtendedMouseEventDispatcher(false);
164 mpView
->EnableExtendedMouseEventDispatcher(true);
167 if (eHit
== SdrHitKind::MarkedObject
&& nEditMode
== SID_BEZIER_INSERT
)
170 mpView
->BegInsObjPoint(aMDPos
, rMEvt
.IsMod1());
174 mpView
->MouseButtonDown(rMEvt
, mpWindow
);
176 SdrObject
* pObj
= mpView
->GetCreateObj();
180 SfxItemSet
aAttr(mpDoc
->GetPool());
181 SetStyleSheet(aAttr
, pObj
);
182 SetAttributes(aAttr
, pObj
);
183 pObj
->SetMergedItemSet(aAttr
);
190 bool FuConstructBezierPolygon::MouseButtonUp(const MouseEvent
& rMEvt
)
192 bool bReturn
= false;
193 bool bCreated
= false;
196 mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONUP
, aVEvt
);
198 const size_t nCount
= mpView
->GetSdrPageView()->GetObjList()->GetObjCount();
200 if (mpView
->IsInsObjPoint())
202 mpView
->EndInsObjPoint(SdrCreateCmd::ForceEnd
);
206 mpView
->MouseButtonUp(rMEvt
, mpWindow
);
209 if (aVEvt
.eEvent
== SdrEventKind::EndCreate
)
213 if (nCount
+1 == mpView
->GetSdrPageView()->GetObjList()->GetObjCount())
218 // trick to suppress FuDraw::DoubleClick
223 bReturn
= FuConstruct::MouseButtonUp(rMEvt
) || bReturn
;
225 bool bDeleted
= false;
226 if( bCreated
&& maTargets
.hasValue() )
228 SdrPathObj
* pPathObj
= dynamic_cast< SdrPathObj
* >( mpView
->GetSdrPageView()->GetObjList()->GetObj( nCount
) );
229 SdPage
* pPage
= dynamic_cast< SdPage
* >( pPathObj
? pPathObj
->getSdrPageFromSdrObject() : nullptr );
232 std::shared_ptr
< sd::MainSequence
> pMainSequence( pPage
->getMainSequence() );
233 if( pMainSequence
.get() )
235 Sequence
< Any
> aTargets
;
236 maTargets
>>= aTargets
;
238 sal_Int32 nTCount
= aTargets
.getLength();
241 const Any
* pTarget
= aTargets
.getConstArray();
242 double fDuration
= 0.0;
243 *pTarget
++ >>= fDuration
;
247 CustomAnimationEffectPtr
pCreated( pMainSequence
->append( *pPathObj
, *pTarget
++, fDuration
) );
251 pCreated
->setNodeType( css::presentation::EffectNodeType::WITH_PREVIOUS
);
256 mpView
->DeleteMarked();
260 if ((!bPermanent
&& bCreated
) || bDeleted
)
262 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
);
268 void FuConstructBezierPolygon::Activate()
270 mpView
->EnableExtendedMouseEventDispatcher(true);
276 case SID_DRAW_POLYGON_NOFILL
:
277 case SID_DRAW_XPOLYGON_NOFILL
:
283 case SID_DRAW_POLYGON
:
284 case SID_DRAW_XPOLYGON
:
290 case SID_DRAW_BEZIER_NOFILL
:
292 eKind
= OBJ_PATHLINE
;
296 case SID_DRAW_BEZIER_FILL
:
298 eKind
= OBJ_PATHFILL
;
302 case SID_DRAW_FREELINE_NOFILL
:
304 eKind
= OBJ_FREELINE
;
308 case SID_DRAW_FREELINE
:
310 eKind
= OBJ_FREEFILL
;
316 eKind
= OBJ_PATHLINE
;
321 mpView
->SetCurrentObj(static_cast<sal_uInt16
>(eKind
));
323 FuConstruct::Activate();
326 void FuConstructBezierPolygon::Deactivate()
328 mpView
->EnableExtendedMouseEventDispatcher(false);
330 FuConstruct::Deactivate();
333 void FuConstructBezierPolygon::SelectionHasChanged()
335 FuDraw::SelectionHasChanged();
337 mpViewShell
->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(
343 /// Returns the color based on the color names listed in core/include/tools/color.hxx
344 /// Feel free to extend with more color names from color.hxx
345 Color
strToColor(const OUString
& sColor
)
347 Color aColor
= COL_AUTO
;
349 if (sColor
== "COL_GRAY")
351 else if (sColor
== "COL_GRAY3")
353 else if (sColor
== "COL_GRAY7")
360 void FuConstructBezierPolygon::SetAttributes(SfxItemSet
& rAttr
, SdrObject
*pObj
)
362 if (nSlotId
== SID_DRAW_FREELINE_NOFILL
)
364 if (mnTransparence
> 0 && mnTransparence
<= 100)
365 rAttr
.Put(XLineTransparenceItem(mnTransparence
));
366 if (!msColor
.isEmpty())
367 rAttr
.Put(XLineColorItem(OUString(), strToColor(msColor
)));
369 rAttr
.Put(XLineWidthItem(mnWidth
));
370 if (!msShapeName
.isEmpty())
371 pObj
->SetName(msShapeName
);
376 * Set current bezier edit mode
378 void FuConstructBezierPolygon::SetEditMode(sal_uInt16 nMode
)
383 SfxBindings
& rBindings
= mpViewShell
->GetViewFrame()->GetBindings();
384 rBindings
.Invalidate(SID_BEZIER_MOVE
);
385 rBindings
.Invalidate(SID_BEZIER_INSERT
);
388 SdrObjectUniquePtr
FuConstructBezierPolygon::CreateDefaultObject(const sal_uInt16 nID
, const ::tools::Rectangle
& rRectangle
)
390 // case SID_DRAW_POLYGON:
391 // case SID_DRAW_POLYGON_NOFILL:
392 // case SID_DRAW_XPOLYGON:
393 // case SID_DRAW_XPOLYGON_NOFILL:
394 // case SID_DRAW_FREELINE:
395 // case SID_DRAW_FREELINE_NOFILL:
396 // case SID_DRAW_BEZIER_FILL: // BASIC
397 // case SID_DRAW_BEZIER_NOFILL: // BASIC
399 SdrObjectUniquePtr
pObj(SdrObjFactory::MakeNewObject(
400 mpView
->getSdrModelFromSdrView(),
401 mpView
->GetCurrentObjInventor(),
402 mpView
->GetCurrentObjIdentifier()));
406 if( auto pPathObj
= dynamic_cast< SdrPathObj
*>( pObj
.get() ) )
408 basegfx::B2DPolyPolygon aPoly
;
412 case SID_DRAW_BEZIER_FILL
:
414 const sal_Int32
nWdt(rRectangle
.GetWidth() / 2);
415 const sal_Int32
nHgt(rRectangle
.GetHeight() / 2);
416 const basegfx::B2DPolygon
aInnerPoly(basegfx::utils::createPolygonFromEllipse(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()), nWdt
, nHgt
));
418 aPoly
.append(aInnerPoly
);
421 case SID_DRAW_BEZIER_NOFILL
:
423 basegfx::B2DPolygon aInnerPoly
;
425 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
427 const basegfx::B2DPoint
aCenterBottom(rRectangle
.Center().X(), rRectangle
.Bottom());
428 aInnerPoly
.appendBezierSegment(
431 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
433 const basegfx::B2DPoint
aCenterTop(rRectangle
.Center().X(), rRectangle
.Top());
434 aInnerPoly
.appendBezierSegment(
437 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
439 aPoly
.append(aInnerPoly
);
442 case SID_DRAW_FREELINE
:
443 case SID_DRAW_FREELINE_NOFILL
:
445 basegfx::B2DPolygon aInnerPoly
;
447 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
449 aInnerPoly
.appendBezierSegment(
450 basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()),
451 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Top()),
452 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
454 aInnerPoly
.appendBezierSegment(
455 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()),
456 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()),
457 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
459 if(SID_DRAW_FREELINE
== nID
)
461 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
465 aInnerPoly
.setClosed(true);
468 aPoly
.append(aInnerPoly
);
471 case SID_DRAW_XPOLYGON
:
472 case SID_DRAW_XPOLYGON_NOFILL
:
474 basegfx::B2DPolygon aInnerPoly
;
476 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
477 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()));
478 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Top()));
479 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
480 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Center().Y()));
481 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
483 if(SID_DRAW_XPOLYGON_NOFILL
== nID
)
485 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()));
489 aInnerPoly
.setClosed(true);
492 aPoly
.append(aInnerPoly
);
495 case SID_DRAW_POLYGON
:
496 case SID_DRAW_POLYGON_NOFILL
:
498 basegfx::B2DPolygon aInnerPoly
;
499 const sal_Int32
nWdt(rRectangle
.GetWidth());
500 const sal_Int32
nHgt(rRectangle
.GetHeight());
502 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
503 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 30) / 100, rRectangle
.Top() + (nHgt
* 70) / 100));
504 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top() + (nHgt
* 15) / 100));
505 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 65) / 100, rRectangle
.Top()));
506 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + nWdt
, rRectangle
.Top() + (nHgt
* 30) / 100));
507 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 80) / 100, rRectangle
.Top() + (nHgt
* 50) / 100));
508 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 80) / 100, rRectangle
.Top() + (nHgt
* 75) / 100));
509 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Bottom(), rRectangle
.Right()));
511 if(SID_DRAW_POLYGON_NOFILL
== nID
)
513 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()));
517 aInnerPoly
.setClosed(true);
520 aPoly
.append(aInnerPoly
);
525 pPathObj
->SetPathPoly(aPoly
);
529 OSL_FAIL("Object is NO path object");
532 pObj
->SetLogicRect(rRectangle
);
538 } // end of namespace sd
540 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */