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>
30 #include <osl/diagnose.h>
32 #include <svx/svxids.hrc>
33 #include <svx/svdpagv.hxx>
34 #include <svx/xlnclit.hxx>
35 #include <svx/xlntrit.hxx>
36 #include <svx/xlnwtit.hxx>
39 #include <ViewShell.hxx>
40 #include <ViewShellBase.hxx>
43 #include <ToolBarManager.hxx>
44 #include <drawdoc.hxx>
47 #include <basegfx/polygon/b2dpolygon.hxx>
48 #include <basegfx/polygon/b2dpolygontools.hxx>
50 #include <CustomAnimationEffect.hxx>
52 using namespace ::com::sun::star::uno
;
56 /*//Extra attributes coming from parameters
57 sal_uInt16 mnTransparence; // Default: 0
58 OUString msColor; // Default: ""
59 sal_uInt16 mnWidth; // Default: 0
60 OUString msShapeName; // Default: ""*/
61 FuConstructBezierPolygon::FuConstructBezierPolygon (
67 : FuConstruct(pViewSh
, pWin
, pView
, pDoc
, rReq
),
68 nEditMode(SID_BEZIER_MOVE
),
76 /// Checks to see if the request has a parameter of IsSticky:bool=true
77 /// It means that the selected command/button will stay selected after use
78 bool isSticky(const SfxRequest
& rReq
)
80 const SfxItemSet
*pArgs
= rReq
.GetArgs ();
83 const SfxBoolItem
* pIsSticky
= rReq
.GetArg
<SfxBoolItem
>(FN_PARAM_4
);
84 if (pIsSticky
&& pIsSticky
->GetValue())
93 rtl::Reference
<FuPoor
> FuConstructBezierPolygon::Create( ViewShell
* pViewSh
, ::sd::Window
* pWin
, ::sd::View
* pView
, SdDrawDocument
* pDoc
, SfxRequest
& rReq
, bool bPermanent
)
95 FuConstructBezierPolygon
* pFunc
;
96 rtl::Reference
<FuPoor
> xFunc( pFunc
= new FuConstructBezierPolygon( pViewSh
, pWin
, pView
, pDoc
, rReq
) );
97 xFunc
->DoExecute(rReq
);
98 pFunc
->SetPermanent(bPermanent
|| isSticky(rReq
));
102 void FuConstructBezierPolygon::DoExecute( SfxRequest
& rReq
)
104 FuConstruct::DoExecute( rReq
);
106 const SfxItemSet
* pArgs
= rReq
.GetArgs();
111 const SfxUnoAnyItem
* pPoolItem
= pArgs
->GetItemIfSet( SID_ADD_MOTION_PATH
);
113 maTargets
= pPoolItem
->GetValue();
115 if (nSlotId
!= SID_DRAW_FREELINE_NOFILL
)
118 const SfxUInt16Item
* pTransparence
= rReq
.GetArg
<SfxUInt16Item
>(FN_PARAM_1
);
119 const SfxStringItem
* pColor
= rReq
.GetArg
<SfxStringItem
>(FN_PARAM_2
);
120 const SfxUInt16Item
* pWidth
= rReq
.GetArg
<SfxUInt16Item
>(FN_PARAM_3
);
121 const SfxStringItem
* pShapeName
= rReq
.GetArg
<SfxStringItem
>(SID_SHAPE_NAME
);
123 if (pTransparence
&& pTransparence
->GetValue() > 0)
125 mnTransparence
= pTransparence
->GetValue();
127 if (pColor
&& !pColor
->GetValue().isEmpty())
129 msColor
= pColor
->GetValue();
131 if (pWidth
&& pWidth
->GetValue() > 0)
133 mnWidth
= pWidth
->GetValue();
135 if (pShapeName
&& !pShapeName
->GetValue().isEmpty())
137 msShapeName
= pShapeName
->GetValue();
141 bool FuConstructBezierPolygon::MouseButtonDown(const MouseEvent
& rMEvt
)
143 bool bReturn
= FuConstruct::MouseButtonDown(rMEvt
);
146 SdrHitKind eHit
= mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONDOWN
, aVEvt
);
148 if (eHit
== SdrHitKind::Handle
|| rMEvt
.IsMod1())
150 mpView
->SetEditMode(SdrViewEditMode::Edit
);
154 mpView
->SetEditMode(SdrViewEditMode::Create
);
157 if (aVEvt
.meEvent
== SdrEventKind::BeginTextEdit
)
159 // here, we do not allow text input
160 aVEvt
.meEvent
= SdrEventKind::BeginDragObj
;
161 mpView
->EnableExtendedMouseEventDispatcher(false);
165 mpView
->EnableExtendedMouseEventDispatcher(true);
168 if (eHit
== SdrHitKind::MarkedObject
&& nEditMode
== SID_BEZIER_INSERT
)
171 mpView
->BegInsObjPoint(aMDPos
, rMEvt
.IsMod1());
175 mpView
->MouseButtonDown(rMEvt
, mpWindow
->GetOutDev());
177 SdrObject
* pObj
= mpView
->GetCreateObj();
181 SfxItemSet
aAttr(mpDoc
->GetPool());
182 SetStyleSheet(aAttr
, pObj
);
183 SetAttributes(aAttr
, pObj
);
184 pObj
->SetMergedItemSet(aAttr
);
191 bool FuConstructBezierPolygon::MouseButtonUp(const MouseEvent
& rMEvt
)
193 bool bReturn
= false;
194 bool bCreated
= false;
197 mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONUP
, aVEvt
);
199 const size_t nCount
= mpView
->GetSdrPageView()->GetObjList()->GetObjCount();
201 if (mpView
->IsInsObjPoint())
203 mpView
->EndInsObjPoint(SdrCreateCmd::ForceEnd
);
207 mpView
->MouseButtonUp(rMEvt
, mpWindow
->GetOutDev());
210 if (aVEvt
.meEvent
== SdrEventKind::EndCreate
)
214 if (nCount
+1 == mpView
->GetSdrPageView()->GetObjList()->GetObjCount())
219 // trick to suppress FuDraw::DoubleClick
224 bReturn
= FuConstruct::MouseButtonUp(rMEvt
) || bReturn
;
226 bool bDeleted
= false;
227 if( bCreated
&& maTargets
.hasValue() )
229 SdrPathObj
* pPathObj
= dynamic_cast< SdrPathObj
* >( mpView
->GetSdrPageView()->GetObjList()->GetObj( nCount
) );
230 SdPage
* pPage
= dynamic_cast< SdPage
* >( pPathObj
? pPathObj
->getSdrPageFromSdrObject() : nullptr );
233 std::shared_ptr
< sd::MainSequence
> pMainSequence( pPage
->getMainSequence() );
236 Sequence
< Any
> aTargets
;
237 maTargets
>>= aTargets
;
239 sal_Int32 nTCount
= aTargets
.getLength();
242 const Any
* pTarget
= aTargets
.getConstArray();
243 double fDuration
= 0.0;
244 *pTarget
++ >>= fDuration
;
250 case SID_DRAW_BEZIER_NOFILL
:
251 sPresetId
= "libo-motionpath-curve";
253 case SID_DRAW_POLYGON_NOFILL
:
254 sPresetId
= "libo-motionpath-polygon";
256 case SID_DRAW_FREELINE_NOFILL
:
257 sPresetId
= "libo-motionpath-freeform-line";
263 CustomAnimationEffectPtr
pCreated( pMainSequence
->append( *pPathObj
, *pTarget
++, fDuration
, sPresetId
) );
267 pCreated
->setNodeType( css::presentation::EffectNodeType::WITH_PREVIOUS
);
272 mpView
->DeleteMarked();
276 if ((!bPermanent
&& bCreated
) || bDeleted
)
278 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
);
284 void FuConstructBezierPolygon::Activate()
286 mpView
->EnableExtendedMouseEventDispatcher(true);
292 case SID_DRAW_POLYGON_NOFILL
:
293 case SID_DRAW_XPOLYGON_NOFILL
:
295 eKind
= SdrObjKind::PolyLine
;
299 case SID_DRAW_POLYGON
:
300 case SID_DRAW_XPOLYGON
:
302 eKind
= SdrObjKind::Polygon
;
306 case SID_DRAW_BEZIER_NOFILL
:
308 eKind
= SdrObjKind::PathLine
;
312 case SID_DRAW_BEZIER_FILL
:
314 eKind
= SdrObjKind::PathFill
;
318 case SID_DRAW_FREELINE_NOFILL
:
320 eKind
= SdrObjKind::FreehandLine
;
324 case SID_DRAW_FREELINE
:
326 eKind
= SdrObjKind::FreehandFill
;
332 eKind
= SdrObjKind::PathLine
;
337 mpView
->SetCurrentObj(eKind
);
339 FuConstruct::Activate();
342 void FuConstructBezierPolygon::Deactivate()
344 mpView
->EnableExtendedMouseEventDispatcher(false);
346 FuConstruct::Deactivate();
349 void FuConstructBezierPolygon::SelectionHasChanged()
351 FuDraw::SelectionHasChanged();
353 mpViewShell
->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(
359 /// Returns the color based on the color names listed in core/include/tools/color.hxx
360 /// Feel free to extend with more color names from color.hxx
361 Color
strToColor(std::u16string_view sColor
)
363 Color aColor
= COL_AUTO
;
365 if (sColor
== u
"COL_GRAY")
367 else if (sColor
== u
"COL_GRAY3")
369 else if (sColor
== u
"COL_GRAY7")
376 void FuConstructBezierPolygon::SetAttributes(SfxItemSet
& rAttr
, SdrObject
*pObj
)
378 if (nSlotId
== SID_DRAW_FREELINE_NOFILL
)
380 if (mnTransparence
> 0 && mnTransparence
<= 100)
381 rAttr
.Put(XLineTransparenceItem(mnTransparence
));
382 if (!msColor
.isEmpty())
383 rAttr
.Put(XLineColorItem(OUString(), strToColor(msColor
)));
385 rAttr
.Put(XLineWidthItem(mnWidth
));
386 if (!msShapeName
.isEmpty())
387 pObj
->SetName(msShapeName
);
392 * Set current bezier edit mode
394 void FuConstructBezierPolygon::SetEditMode(sal_uInt16 nMode
)
399 SfxBindings
& rBindings
= mpViewShell
->GetViewFrame()->GetBindings();
400 rBindings
.Invalidate(SID_BEZIER_MOVE
);
401 rBindings
.Invalidate(SID_BEZIER_INSERT
);
404 rtl::Reference
<SdrObject
> FuConstructBezierPolygon::CreateDefaultObject(const sal_uInt16 nID
, const ::tools::Rectangle
& rRectangle
)
406 // case SID_DRAW_POLYGON:
407 // case SID_DRAW_POLYGON_NOFILL:
408 // case SID_DRAW_XPOLYGON:
409 // case SID_DRAW_XPOLYGON_NOFILL:
410 // case SID_DRAW_FREELINE:
411 // case SID_DRAW_FREELINE_NOFILL:
412 // case SID_DRAW_BEZIER_FILL: // BASIC
413 // case SID_DRAW_BEZIER_NOFILL: // BASIC
415 rtl::Reference
<SdrObject
> pObj(SdrObjFactory::MakeNewObject(
416 mpView
->getSdrModelFromSdrView(),
417 mpView
->GetCurrentObjInventor(),
418 mpView
->GetCurrentObjIdentifier()));
422 if( auto pPathObj
= dynamic_cast< SdrPathObj
*>( pObj
.get() ) )
424 basegfx::B2DPolyPolygon aPoly
;
428 case SID_DRAW_BEZIER_FILL
:
430 const sal_Int32
nWdt(rRectangle
.GetWidth() / 2);
431 const sal_Int32
nHgt(rRectangle
.GetHeight() / 2);
432 const basegfx::B2DPolygon
aInnerPoly(basegfx::utils::createPolygonFromEllipse(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()), nWdt
, nHgt
));
434 aPoly
.append(aInnerPoly
);
437 case SID_DRAW_BEZIER_NOFILL
:
439 basegfx::B2DPolygon aInnerPoly
;
441 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
443 const basegfx::B2DPoint
aCenterBottom(rRectangle
.Center().X(), rRectangle
.Bottom());
444 aInnerPoly
.appendBezierSegment(
447 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
449 const basegfx::B2DPoint
aCenterTop(rRectangle
.Center().X(), rRectangle
.Top());
450 aInnerPoly
.appendBezierSegment(
453 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
455 aPoly
.append(aInnerPoly
);
458 case SID_DRAW_FREELINE
:
459 case SID_DRAW_FREELINE_NOFILL
:
461 basegfx::B2DPolygon aInnerPoly
;
463 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
465 aInnerPoly
.appendBezierSegment(
466 basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()),
467 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Top()),
468 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
470 aInnerPoly
.appendBezierSegment(
471 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()),
472 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()),
473 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
475 if(SID_DRAW_FREELINE
== nID
)
477 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
481 aInnerPoly
.setClosed(true);
484 aPoly
.append(aInnerPoly
);
487 case SID_DRAW_XPOLYGON
:
488 case SID_DRAW_XPOLYGON_NOFILL
:
490 basegfx::B2DPolygon aInnerPoly
;
492 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
493 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()));
494 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Top()));
495 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
496 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Center().Y()));
497 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
499 if(SID_DRAW_XPOLYGON_NOFILL
== nID
)
501 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()));
505 aInnerPoly
.setClosed(true);
508 aPoly
.append(aInnerPoly
);
511 case SID_DRAW_POLYGON
:
512 case SID_DRAW_POLYGON_NOFILL
:
514 basegfx::B2DPolygon aInnerPoly
;
515 const sal_Int32
nWdt(rRectangle
.GetWidth());
516 const sal_Int32
nHgt(rRectangle
.GetHeight());
518 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
519 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 30) / 100, rRectangle
.Top() + (nHgt
* 70) / 100));
520 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top() + (nHgt
* 15) / 100));
521 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 65) / 100, rRectangle
.Top()));
522 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + nWdt
, rRectangle
.Top() + (nHgt
* 30) / 100));
523 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 80) / 100, rRectangle
.Top() + (nHgt
* 50) / 100));
524 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 80) / 100, rRectangle
.Top() + (nHgt
* 75) / 100));
525 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Bottom(), rRectangle
.Right()));
527 if(SID_DRAW_POLYGON_NOFILL
== nID
)
529 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()));
533 aInnerPoly
.setClosed(true);
536 aPoly
.append(aInnerPoly
);
541 pPathObj
->SetPathPoly(aPoly
);
545 OSL_FAIL("Object is NO path object");
548 pObj
->SetLogicRect(rRectangle
);
554 } // end of namespace sd
556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */