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 <svx/svdview.hxx>
21 #include <svx/svdotext.hxx>
22 #include <svl/whiter.hxx>
23 #include <svx/fontwork.hxx>
24 #include <sfx2/request.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/objface.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <svx/extrusionbar.hxx>
29 #include <svx/fontworkbar.hxx>
31 #include <dcontact.hxx>
32 #include <textboxhelper.hxx>
34 #include <swmodule.hxx>
36 #include <svx/svdoashp.hxx>
37 #include <svx/xfillit0.hxx>
38 #include <vcl/EnumContext.hxx>
39 #include <svx/svdoole2.hxx>
40 #include <sfx2/opengrf.hxx>
41 #include <svx/svdograf.hxx>
42 #include <svx/svdundo.hxx>
43 #include <svx/xbtmpit.hxx>
44 #include <svx/sdasitm.hxx>
45 #include <osl/diagnose.h>
50 #include <strings.hrc>
51 #include <drwbassh.hxx>
54 #define ShellClass_SwDrawShell
55 #include <sfx2/msg.hxx>
56 #include <swslots.hxx>
58 using namespace ::com::sun::star
;
59 using namespace ::com::sun::star::uno
;
61 SFX_IMPL_INTERFACE(SwDrawShell
, SwDrawBaseShell
)
63 void SwDrawShell::InitInterface_Impl()
65 GetStaticInterface()->RegisterPopupMenu("draw");
67 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT
, SfxVisibilityFlags::Invisible
, ToolbarId::Draw_Toolbox_Sw
);
69 GetStaticInterface()->RegisterChildWindow(SvxFontWorkChildWindow::GetChildWindowId());
73 // #i123922# check as the name implies
74 SdrObject
* SwDrawShell::IsSingleFillableNonOLESelected()
76 SwWrtShell
&rSh
= GetShell();
77 SdrView
* pSdrView
= rSh
.GetDrawView();
84 if(1 != pSdrView
->GetMarkedObjectCount())
89 SdrObject
* pPickObj
= pSdrView
->GetMarkedObjectByIndex(0);
96 if(!pPickObj
->IsClosedObj())
101 if(dynamic_cast< SdrOle2Obj
* >(pPickObj
))
109 // #i123922# insert given graphic data dependent of the object type in focus
110 void SwDrawShell::InsertPictureFromFile(SdrObject
& rObject
)
112 SwWrtShell
&rSh
= GetShell();
113 SdrView
* pSdrView
= rSh
.GetDrawView();
118 SvxOpenGraphicDialog
aDlg(SwResId(STR_INSERT_GRAPHIC
), GetView().GetFrameWeld());
120 if (ERRCODE_NONE
!= aDlg
.Execute())
124 ErrCode nError
= aDlg
.GetGraphic(aGraphic
);
126 if(ERRCODE_NONE
!= nError
)
129 const bool bAsLink(aDlg
.IsAsLink());
130 SdrObject
* pResult
= &rObject
;
132 rSh
.StartUndo(SwUndoId::PASTE_CLIPBOARD
);
134 if (SdrGrafObj
* pSdrGrafObj
= dynamic_cast<SdrGrafObj
*>(&rObject
))
136 rtl::Reference
<SdrGrafObj
> pNewGrafObj
= SdrObject::Clone(*pSdrGrafObj
, pSdrGrafObj
->getSdrModelFromSdrObject());
138 pNewGrafObj
->SetGraphic(aGraphic
);
140 // #i123922# for handling MasterObject and virtual ones correctly, SW
141 // wants us to call ReplaceObject at the page, but that also
142 // triggers the same assertion (I tried it), so stay at the view method
143 pSdrView
->ReplaceObjectAtView(&rObject
, *pSdrView
->GetSdrPageView(), pNewGrafObj
.get());
145 // set in all cases - the Clone() will have copied an existing link (!)
146 pNewGrafObj
->SetGraphicLink(
147 bAsLink
? aDlg
.GetPath() : OUString());
149 pResult
= pNewGrafObj
.get();
151 else // if(rObject.IsClosedObj() && !dynamic_cast< SdrOle2Obj* >(&rObject))
153 pSdrView
->AddUndo(std::make_unique
<SdrUndoAttrObj
>(rObject
));
155 SfxItemSetFixed
<XATTR_FILLSTYLE
, XATTR_FILLBITMAP
> aSet(pSdrView
->GetModel().GetItemPool());
157 aSet
.Put(XFillStyleItem(drawing::FillStyle_BITMAP
));
158 aSet
.Put(XFillBitmapItem(OUString(), std::move(aGraphic
)));
159 rObject
.SetMergedItemSetAndBroadcast(aSet
);
162 rSh
.EndUndo( SwUndoId::END
);
166 // we are done; mark the modified/new object
167 pSdrView
->MarkObj(pResult
, pSdrView
->GetSdrPageView());
171 void SwDrawShell::Execute(SfxRequest
&rReq
)
173 SwWrtShell
&rSh
= GetShell();
174 SdrView
*pSdrView
= rSh
.GetDrawView();
175 const SfxItemSet
*pArgs
= rReq
.GetArgs();
176 SfxBindings
&rBnd
= GetView().GetViewFrame().GetBindings();
177 sal_uInt16 nSlotId
= rReq
.GetSlot();
178 bool bChanged
= pSdrView
->GetModel().IsChanged();
180 pSdrView
->GetModel().SetChanged(false);
182 const SfxPoolItem
* pItem
;
184 pArgs
->GetItemState(nSlotId
, false, &pItem
);
190 case SID_OBJECT_ROTATE
:
191 if (rSh
.IsObjSelected() && pSdrView
->IsRotateAllowed())
193 if (GetView().IsDrawRotate())
194 rSh
.SetDragMode(SdrDragMode::Move
);
196 rSh
.SetDragMode(SdrDragMode::Rotate
);
198 GetView().FlipDrawRotate();
201 case SID_MOVE_SHAPE_HANDLE
:
203 if (pArgs
&& pArgs
->Count() >= 3)
205 const SfxUInt32Item
* handleNumItem
= rReq
.GetArg
<SfxUInt32Item
>(FN_PARAM_1
);
206 const SfxUInt32Item
* newPosXTwips
= rReq
.GetArg
<SfxUInt32Item
>(FN_PARAM_2
);
207 const SfxUInt32Item
* newPosYTwips
= rReq
.GetArg
<SfxUInt32Item
>(FN_PARAM_3
);
208 const SfxInt32Item
* OrdNum
= rReq
.GetArg
<SfxInt32Item
>(FN_PARAM_4
);
210 const sal_uLong handleNum
= handleNumItem
->GetValue();
211 const sal_uLong newPosX
= newPosXTwips
->GetValue();
212 const sal_uLong newPosY
= newPosYTwips
->GetValue();
213 const Point
mPoint(newPosX
, newPosY
);
214 const SdrHdl
* handle
= pSdrView
->GetHdlList().GetHdl(handleNum
);
220 if (handle
->GetKind() == SdrHdlKind::Anchor
|| handle
->GetKind() == SdrHdlKind::Anchor_TR
)
222 rSh
.FindAnchorPos(mPoint
, /*bMoveIt=*/true);
223 pSdrView
->ModelHasChanged();
226 pSdrView
->MoveShapeHandle(handleNum
, mPoint
, OrdNum
? OrdNum
->GetValue() : -1);
230 case SID_BEZIER_EDIT
:
231 if (GetView().IsDrawRotate())
233 rSh
.SetDragMode(SdrDragMode::Move
);
234 GetView().FlipDrawRotate();
236 GetView().FlipDrawSelMode();
237 pSdrView
->SetFrameDragSingles(GetView().IsDrawSelMode());
238 GetView().AttrChangedNotify(nullptr); // Shell switch
241 case SID_OBJECT_HELL
:
242 if (rSh
.IsObjSelected())
244 rSh
.StartUndo( SwUndoId::START
);
245 SetWrapMode(FN_FRAME_WRAPTHRU_TRANSP
);
246 rSh
.SelectionToHell();
247 rSh
.EndUndo( SwUndoId::END
);
248 rBnd
.Invalidate(SID_OBJECT_HEAVEN
);
252 case SID_OBJECT_HEAVEN
:
253 if (rSh
.IsObjSelected())
255 rSh
.StartUndo( SwUndoId::START
);
256 SetWrapMode(FN_FRAME_WRAPTHRU
);
257 rSh
.SelectionToHeaven();
258 rSh
.EndUndo( SwUndoId::END
);
259 rBnd
.Invalidate(SID_OBJECT_HELL
);
263 case FN_TOOL_HIERARCHIE
:
264 if (rSh
.IsObjSelected())
266 rSh
.StartUndo( SwUndoId::START
);
267 if (rSh
.GetLayerId() == SdrLayerID(0))
269 SetWrapMode(FN_FRAME_WRAPTHRU
);
270 rSh
.SelectionToHeaven();
274 SetWrapMode(FN_FRAME_WRAPTHRU_TRANSP
);
275 rSh
.SelectionToHell();
277 rSh
.EndUndo( SwUndoId::END
);
278 rBnd
.Invalidate( SID_OBJECT_HELL
);
279 rBnd
.Invalidate( SID_OBJECT_HEAVEN
);
283 case SID_FLIP_VERTICAL
:
286 case SID_FLIP_HORIZONTAL
:
287 rSh
.MirrorSelection( bMirror
);
292 FieldUnit eMetric
= ::GetDfltMetric( dynamic_cast<SwWebView
*>( &rSh
.GetView()) != nullptr );
293 SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC
, static_cast< sal_uInt16
>(eMetric
)) );
294 SfxViewFrame
& rVFrame
= GetView().GetViewFrame();
297 rVFrame
.SetChildWindow(SvxFontWorkChildWindow::GetChildWindowId(),
298 static_cast<const SfxBoolItem
&>((pArgs
->Get(SID_FONTWORK
))).GetValue());
301 rVFrame
.ToggleChildWindow( SvxFontWorkChildWindow::GetChildWindowId() );
302 rVFrame
.GetBindings().Invalidate(SID_FONTWORK
);
305 case FN_FORMAT_FOOTNOTE_DLG
:
307 GetView().ExecFormatFootnote();
310 case FN_NUMBERING_OUTLINE_DLG
:
312 GetView().ExecNumberingOutline(GetPool());
316 case SID_OPEN_XML_FILTERSETTINGS
:
318 HandleOpenXmlFilterSettings(rReq
);
321 case FN_WORDCOUNT_DIALOG
:
323 GetView().UpdateWordCount(this, nSlotId
);
326 case SID_EXTRUSION_TOGGLE
:
327 case SID_EXTRUSION_TILT_DOWN
:
328 case SID_EXTRUSION_TILT_UP
:
329 case SID_EXTRUSION_TILT_LEFT
:
330 case SID_EXTRUSION_TILT_RIGHT
:
331 case SID_EXTRUSION_3D_COLOR
:
332 case SID_EXTRUSION_DEPTH
:
333 case SID_EXTRUSION_DIRECTION
:
334 case SID_EXTRUSION_PROJECTION
:
335 case SID_EXTRUSION_LIGHTING_DIRECTION
:
336 case SID_EXTRUSION_LIGHTING_INTENSITY
:
337 case SID_EXTRUSION_SURFACE
:
338 case SID_EXTRUSION_DEPTH_FLOATER
:
339 case SID_EXTRUSION_DIRECTION_FLOATER
:
340 case SID_EXTRUSION_LIGHTING_FLOATER
:
341 case SID_EXTRUSION_SURFACE_FLOATER
:
342 case SID_EXTRUSION_DEPTH_DIALOG
:
343 svx::ExtrusionBar::execute( pSdrView
, rReq
, rBnd
);
347 case SID_FONTWORK_SHAPE
:
348 case SID_FONTWORK_SHAPE_TYPE
:
349 case SID_FONTWORK_ALIGNMENT
:
350 case SID_FONTWORK_SAME_LETTER_HEIGHTS
:
351 case SID_FONTWORK_CHARACTER_SPACING
:
352 case SID_FONTWORK_KERN_CHARACTER_PAIRS
:
353 case SID_FONTWORK_CHARACTER_SPACING_FLOATER
:
354 case SID_FONTWORK_ALIGNMENT_FLOATER
:
355 case SID_FONTWORK_CHARACTER_SPACING_DIALOG
:
356 svx::FontworkBar::execute(*pSdrView
, rReq
, rBnd
);
360 case SID_INSERT_GRAPHIC
:
362 // #i123922# check if we can do something
363 SdrObject
* pObj
= IsSingleFillableNonOLESelected();
367 // ...and if yes, do something
368 InsertPictureFromFile(*pObj
);
374 case FN_ADD_TEXT_BOX
:
376 if (SdrObject
* pObj
= IsSingleFillableNonOLESelected())
378 SwFrameFormat
* pFrameFormat
= ::FindFrameFormat(pObj
);
380 SwTextBoxHelper::create(pFrameFormat
, pObj
, pObj
->HasText());
384 case FN_REMOVE_TEXT_BOX
:
386 if (SdrObject
* pObj
= IsSingleFillableNonOLESelected())
388 SwFrameFormat
* pFrameFormat
= ::FindFrameFormat(pObj
);
390 SwTextBoxHelper::destroy(pFrameFormat
, pObj
);
395 OSL_ENSURE(false, "wrong dispatcher");
398 if (pSdrView
->GetModel().IsChanged())
401 pSdrView
->GetModel().SetChanged();
404 void SwDrawShell::GetState(SfxItemSet
& rSet
)
406 SwWrtShell
&rSh
= GetShell();
407 SdrView
* pSdrView
= rSh
.GetDrawViewWithValidMarkList();
408 SfxWhichIter
aIter( rSet
);
409 sal_uInt16 nWhich
= aIter
.FirstWhich();
410 bool bProtected
= rSh
.IsSelObjProtected(FlyProtectFlags::Content
) != FlyProtectFlags::NONE
;
412 if (!bProtected
) // Check the parent
413 bProtected
|= rSh
.IsSelObjProtected( FlyProtectFlags::Content
|FlyProtectFlags::Parent
) != FlyProtectFlags::NONE
;
419 case SID_OBJECT_HELL
:
420 if ( !rSh
.IsObjSelected() || rSh
.GetLayerId() == SdrLayerID(0) || bProtected
)
421 rSet
.DisableItem( nWhich
);
424 case SID_OBJECT_HEAVEN
:
425 if ( !rSh
.IsObjSelected() || rSh
.GetLayerId() == SdrLayerID(1) || bProtected
)
426 rSet
.DisableItem( nWhich
);
429 case FN_TOOL_HIERARCHIE
:
430 if ( !rSh
.IsObjSelected() || bProtected
)
431 rSet
.DisableItem( nWhich
);
434 case SID_OBJECT_ROTATE
:
436 const bool bIsRotate
= GetView().IsDrawRotate();
437 if ( (!bIsRotate
&& !pSdrView
->IsRotateAllowed()) || bProtected
)
438 rSet
.DisableItem( nWhich
);
440 rSet
.Put( SfxBoolItem( nWhich
, bIsRotate
) );
444 case SID_BEZIER_EDIT
:
445 if (!Disable(rSet
, nWhich
))
446 rSet
.Put( SfxBoolItem( nWhich
, !GetView().IsDrawSelMode()));
449 case SID_FLIP_VERTICAL
:
450 if ( !pSdrView
->IsMirrorAllowed() || bProtected
)
452 rSet
.DisableItem( nWhich
);
456 // TTTT - needs to be adapted in aw080:
457 // state is not kept for drawing objects --> provide not flipped state
458 rSet
.Put( SfxBoolItem( nWhich
, false ) );
462 case SID_FLIP_HORIZONTAL
:
463 if ( !pSdrView
->IsMirrorAllowed() || bProtected
)
465 rSet
.DisableItem( nWhich
);
469 // TTTT - needs to be adapted in aw080:
470 // state is not kept for drawing objects --> provide not flipped state
471 rSet
.Put( SfxBoolItem( nWhich
, false ) );
478 rSet
.DisableItem( nWhich
);
481 const sal_uInt16 nId
= SvxFontWorkChildWindow::GetChildWindowId();
482 rSet
.Put(SfxBoolItem( nWhich
, GetView().GetViewFrame().HasChildWindow(nId
)));
487 case SID_INSERT_GRAPHIC
:
489 // #i123922# check if we can do something
490 SdrObject
* pObj
= IsSingleFillableNonOLESelected();
494 rSet
.DisableItem(nWhich
);
499 case FN_ADD_TEXT_BOX
:
501 bool bDisable
= true;
502 if (SdrObject
* pObj
= IsSingleFillableNonOLESelected())
504 SwFrameFormat
* pFrameFormat
= ::FindFrameFormat(pObj
);
505 // Allow creating a TextBox only in case this is a draw format without a TextBox so far.
506 if (pFrameFormat
&& pFrameFormat
->Which() == RES_DRAWFRMFMT
&& !SwTextBoxHelper::isTextBox(pFrameFormat
, RES_DRAWFRMFMT
, pObj
))
508 if (SdrObjCustomShape
* pCustomShape
= dynamic_cast<SdrObjCustomShape
*>( pObj
) )
510 const SdrCustomShapeGeometryItem
& rGeometryItem
= pCustomShape
->GetMergedItem(SDRATTR_CUSTOMSHAPE_GEOMETRY
);
511 if (const uno::Any
* pAny
= rGeometryItem
.GetPropertyValueByName("Type"))
512 // But still disallow fontwork shapes.
513 bDisable
= pAny
->get
<OUString
>().startsWith("fontwork-");
519 rSet
.DisableItem(nWhich
);
522 case FN_REMOVE_TEXT_BOX
:
524 bool bDisable
= true;
525 if (SdrObject
* pObj
= IsSingleFillableNonOLESelected())
527 SwFrameFormat
* pFrameFormat
= ::FindFrameFormat(pObj
);
528 // Allow removing a TextBox only in case it has one.
529 if (pFrameFormat
&& SwTextBoxHelper::isTextBox(pFrameFormat
, RES_DRAWFRMFMT
, pObj
))
534 rSet
.DisableItem(nWhich
);
538 nWhich
= aIter
.NextWhich();
540 svx::ExtrusionBar::getState( pSdrView
, rSet
);
541 svx::FontworkBar::getState( pSdrView
, rSet
);
544 SwDrawShell::SwDrawShell(SwView
&_rView
) :
545 SwDrawBaseShell(_rView
)
549 vcl::EnumContext::Context eContext
= vcl::EnumContext::Context::Draw
;
551 SwWrtShell
&rSh
= GetShell();
552 SdrView
* pDrView
= rSh
.GetDrawView();
554 if (pDrView
&& svx::checkForSelectedFontWork(pDrView
))
555 eContext
= vcl::EnumContext::Context::DrawFontwork
;
557 SfxShell::SetContextName(vcl::EnumContext::GetContextName(eContext
));
560 // Edit SfxRequests for FontWork
562 void SwDrawShell::ExecFormText(SfxRequest
const & rReq
)
564 SwWrtShell
&rSh
= GetShell();
565 SdrView
* pDrView
= rSh
.GetDrawView();
566 bool bChanged
= pDrView
->GetModel().IsChanged();
567 pDrView
->GetModel().SetChanged(false);
569 const SdrMarkList
& rMarkList
= pDrView
->GetMarkedObjectList();
571 if ( rMarkList
.GetMarkCount() == 1 && rReq
.GetArgs() )
573 const SfxItemSet
& rSet
= *rReq
.GetArgs();
575 if ( pDrView
->IsTextEdit() )
577 pDrView
->SdrEndTextEdit( true );
578 GetView().AttrChangedNotify(nullptr);
581 pDrView
->SetAttributes(rSet
);
583 if (pDrView
->GetModel().IsChanged())
587 pDrView
->GetModel().SetChanged();
590 //Return status values for FontWork
592 void SwDrawShell::GetFormTextState(SfxItemSet
& rSet
)
594 SwWrtShell
&rSh
= GetShell();
595 SdrView
* pDrView
= rSh
.GetDrawView();
596 const SdrMarkList
& rMarkList
= pDrView
->GetMarkedObjectList();
597 const SdrObject
* pObj
= nullptr;
599 if ( rMarkList
.GetMarkCount() == 1 )
600 pObj
= rMarkList
.GetMark(0)->GetMarkedSdrObj();
602 const SdrTextObj
* pTextObj
= DynCastSdrTextObj(pObj
);
603 const bool bDeactivate(
606 !pTextObj
->HasText() ||
607 dynamic_cast< const SdrObjCustomShape
* >(pObj
)); // #121538# no FontWork for CustomShapes
611 rSet
.DisableItem(XATTR_FORMTXTSTYLE
);
612 rSet
.DisableItem(XATTR_FORMTXTADJUST
);
613 rSet
.DisableItem(XATTR_FORMTXTDISTANCE
);
614 rSet
.DisableItem(XATTR_FORMTXTSTART
);
615 rSet
.DisableItem(XATTR_FORMTXTMIRROR
);
616 rSet
.DisableItem(XATTR_FORMTXTHIDEFORM
);
617 rSet
.DisableItem(XATTR_FORMTXTOUTLINE
);
618 rSet
.DisableItem(XATTR_FORMTXTSHADOW
);
619 rSet
.DisableItem(XATTR_FORMTXTSHDWCOLOR
);
620 rSet
.DisableItem(XATTR_FORMTXTSHDWXVAL
);
621 rSet
.DisableItem(XATTR_FORMTXTSHDWYVAL
);
625 pDrView
->GetAttributes( rSet
);
629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */