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 if (rMEvt
.IsLeft() && IsIgnoreUnexpectedMouseButtonUp())
196 bool bReturn
= false;
197 bool bCreated
= false;
200 mpView
->PickAnything(rMEvt
, SdrMouseEventKind::BUTTONUP
, aVEvt
);
202 const size_t nCount
= mpView
->GetSdrPageView()->GetObjList()->GetObjCount();
204 if (mpView
->IsInsObjPoint())
206 mpView
->EndInsObjPoint(SdrCreateCmd::ForceEnd
);
210 mpView
->MouseButtonUp(rMEvt
, mpWindow
->GetOutDev());
213 if (aVEvt
.meEvent
== SdrEventKind::EndCreate
)
217 if (nCount
+1 == mpView
->GetSdrPageView()->GetObjList()->GetObjCount())
222 // trick to suppress FuDraw::DoubleClick
227 bReturn
= FuConstruct::MouseButtonUp(rMEvt
) || bReturn
;
229 bool bDeleted
= false;
230 if( bCreated
&& maTargets
.hasValue() )
232 SdrPathObj
* pPathObj
= dynamic_cast< SdrPathObj
* >( mpView
->GetSdrPageView()->GetObjList()->GetObj( nCount
) );
233 SdPage
* pPage
= dynamic_cast< SdPage
* >( pPathObj
? pPathObj
->getSdrPageFromSdrObject() : nullptr );
236 std::shared_ptr
< sd::MainSequence
> pMainSequence( pPage
->getMainSequence() );
239 Sequence
< Any
> aTargets
;
240 maTargets
>>= aTargets
;
242 sal_Int32 nTCount
= aTargets
.getLength();
245 const Any
* pTarget
= aTargets
.getConstArray();
246 double fDuration
= 0.0;
247 *pTarget
++ >>= fDuration
;
253 case SID_DRAW_BEZIER_NOFILL
:
254 sPresetId
= "libo-motionpath-curve";
256 case SID_DRAW_POLYGON_NOFILL
:
257 sPresetId
= "libo-motionpath-polygon";
259 case SID_DRAW_FREELINE_NOFILL
:
260 sPresetId
= "libo-motionpath-freeform-line";
266 CustomAnimationEffectPtr
pCreated( pMainSequence
->append( *pPathObj
, *pTarget
++, fDuration
, sPresetId
) );
270 pCreated
->setNodeType( css::presentation::EffectNodeType::WITH_PREVIOUS
);
275 mpView
->DeleteMarked();
279 if ((!bPermanent
&& bCreated
) || bDeleted
)
281 mpViewShell
->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT
, SfxCallMode::ASYNCHRON
);
287 void FuConstructBezierPolygon::Activate()
289 mpView
->EnableExtendedMouseEventDispatcher(true);
295 case SID_DRAW_POLYGON_NOFILL
:
296 case SID_DRAW_XPOLYGON_NOFILL
:
298 eKind
= SdrObjKind::PolyLine
;
302 case SID_DRAW_POLYGON
:
303 case SID_DRAW_XPOLYGON
:
305 eKind
= SdrObjKind::Polygon
;
309 case SID_DRAW_BEZIER_NOFILL
:
311 eKind
= SdrObjKind::PathLine
;
315 case SID_DRAW_BEZIER_FILL
:
317 eKind
= SdrObjKind::PathFill
;
321 case SID_DRAW_FREELINE_NOFILL
:
323 eKind
= SdrObjKind::FreehandLine
;
327 case SID_DRAW_FREELINE
:
329 eKind
= SdrObjKind::FreehandFill
;
335 eKind
= SdrObjKind::PathLine
;
340 mpView
->SetCurrentObj(eKind
);
342 FuConstruct::Activate();
345 void FuConstructBezierPolygon::Deactivate()
347 mpView
->EnableExtendedMouseEventDispatcher(false);
349 FuConstruct::Deactivate();
352 void FuConstructBezierPolygon::SelectionHasChanged()
354 FuDraw::SelectionHasChanged();
356 mpViewShell
->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(
362 /// Returns the color based on the color names listed in core/include/tools/color.hxx
363 /// Feel free to extend with more color names from color.hxx
364 Color
strToColor(std::u16string_view sColor
)
366 Color aColor
= COL_AUTO
;
368 if (sColor
== u
"COL_GRAY")
370 else if (sColor
== u
"COL_GRAY3")
372 else if (sColor
== u
"COL_GRAY7")
379 void FuConstructBezierPolygon::SetAttributes(SfxItemSet
& rAttr
, SdrObject
*pObj
)
381 if (nSlotId
== SID_DRAW_FREELINE_NOFILL
)
383 if (mnTransparence
> 0 && mnTransparence
<= 100)
384 rAttr
.Put(XLineTransparenceItem(mnTransparence
));
385 if (!msColor
.isEmpty())
386 rAttr
.Put(XLineColorItem(OUString(), strToColor(msColor
)));
388 rAttr
.Put(XLineWidthItem(mnWidth
));
389 if (!msShapeName
.isEmpty())
390 pObj
->SetName(msShapeName
);
395 * Set current bezier edit mode
397 void FuConstructBezierPolygon::SetEditMode(sal_uInt16 nMode
)
402 SfxBindings
& rBindings
= mpViewShell
->GetViewFrame()->GetBindings();
403 rBindings
.Invalidate(SID_BEZIER_MOVE
);
404 rBindings
.Invalidate(SID_BEZIER_INSERT
);
407 rtl::Reference
<SdrObject
> FuConstructBezierPolygon::CreateDefaultObject(const sal_uInt16 nID
, const ::tools::Rectangle
& rRectangle
)
409 // case SID_DRAW_POLYGON:
410 // case SID_DRAW_POLYGON_NOFILL:
411 // case SID_DRAW_XPOLYGON:
412 // case SID_DRAW_XPOLYGON_NOFILL:
413 // case SID_DRAW_FREELINE:
414 // case SID_DRAW_FREELINE_NOFILL:
415 // case SID_DRAW_BEZIER_FILL: // BASIC
416 // case SID_DRAW_BEZIER_NOFILL: // BASIC
418 rtl::Reference
<SdrObject
> pObj(SdrObjFactory::MakeNewObject(
419 mpView
->getSdrModelFromSdrView(),
420 mpView
->GetCurrentObjInventor(),
421 mpView
->GetCurrentObjIdentifier()));
425 if( auto pPathObj
= dynamic_cast< SdrPathObj
*>( pObj
.get() ) )
427 basegfx::B2DPolyPolygon aPoly
;
431 case SID_DRAW_BEZIER_FILL
:
433 const sal_Int32
nWdt(rRectangle
.GetWidth() / 2);
434 const sal_Int32
nHgt(rRectangle
.GetHeight() / 2);
435 const basegfx::B2DPolygon
aInnerPoly(basegfx::utils::createPolygonFromEllipse(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()), nWdt
, nHgt
));
437 aPoly
.append(aInnerPoly
);
440 case SID_DRAW_BEZIER_NOFILL
:
442 basegfx::B2DPolygon aInnerPoly
;
444 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
446 const basegfx::B2DPoint
aCenterBottom(rRectangle
.Center().X(), rRectangle
.Bottom());
447 aInnerPoly
.appendBezierSegment(
450 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
452 const basegfx::B2DPoint
aCenterTop(rRectangle
.Center().X(), rRectangle
.Top());
453 aInnerPoly
.appendBezierSegment(
456 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
458 aPoly
.append(aInnerPoly
);
461 case SID_DRAW_FREELINE
:
462 case SID_DRAW_FREELINE_NOFILL
:
464 basegfx::B2DPolygon aInnerPoly
;
466 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
468 aInnerPoly
.appendBezierSegment(
469 basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()),
470 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Top()),
471 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
473 aInnerPoly
.appendBezierSegment(
474 basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()),
475 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()),
476 basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Top()));
478 if(SID_DRAW_FREELINE
== nID
)
480 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
484 aInnerPoly
.setClosed(true);
487 aPoly
.append(aInnerPoly
);
490 case SID_DRAW_XPOLYGON
:
491 case SID_DRAW_XPOLYGON_NOFILL
:
493 basegfx::B2DPolygon aInnerPoly
;
495 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
496 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top()));
497 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Top()));
498 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Center().Y()));
499 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Center().Y()));
500 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Right(), rRectangle
.Bottom()));
502 if(SID_DRAW_XPOLYGON_NOFILL
== nID
)
504 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()));
508 aInnerPoly
.setClosed(true);
511 aPoly
.append(aInnerPoly
);
514 case SID_DRAW_POLYGON
:
515 case SID_DRAW_POLYGON_NOFILL
:
517 basegfx::B2DPolygon aInnerPoly
;
518 const sal_Int32
nWdt(rRectangle
.GetWidth());
519 const sal_Int32
nHgt(rRectangle
.GetHeight());
521 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Bottom()));
522 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 30) / 100, rRectangle
.Top() + (nHgt
* 70) / 100));
523 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left(), rRectangle
.Top() + (nHgt
* 15) / 100));
524 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 65) / 100, rRectangle
.Top()));
525 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + nWdt
, rRectangle
.Top() + (nHgt
* 30) / 100));
526 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 80) / 100, rRectangle
.Top() + (nHgt
* 50) / 100));
527 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Left() + (nWdt
* 80) / 100, rRectangle
.Top() + (nHgt
* 75) / 100));
528 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Bottom(), rRectangle
.Right()));
530 if(SID_DRAW_POLYGON_NOFILL
== nID
)
532 aInnerPoly
.append(basegfx::B2DPoint(rRectangle
.Center().X(), rRectangle
.Bottom()));
536 aInnerPoly
.setClosed(true);
539 aPoly
.append(aInnerPoly
);
544 pPathObj
->SetPathPoly(aPoly
);
548 OSL_FAIL("Object is NO path object");
551 pObj
->SetLogicRect(rRectangle
);
557 } // end of namespace sd
559 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */