1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <hintids.hxx>
21 #include <swtypes.hxx>
22 #include <sfx2/objface.hxx>
23 #include <sfx2/request.hxx>
24 #include <sfx2/bindings.hxx>
25 #include <sfx2/viewfrm.hxx>
26 #include <svx/svdview.hxx>
27 #include <svl/whiter.hxx>
28 #include <svx/swframevalidation.hxx>
29 #include <svx/anchorid.hxx>
30 #include <osl/diagnose.h>
31 #include <drawdoc.hxx>
32 #include <uitool.hxx>
33 #include <fmtornt.hxx>
34 #include <cmdid.h>
35 #include <swmodule.hxx>
36 #include <wrtsh.hxx>
37 #include <wview.hxx>
38 #include <edtwin.hxx>
39 #include <viewopt.hxx>
40 #include <dcontact.hxx>
41 #include <frmfmt.hxx>
42 #include <drawbase.hxx>
43 #include <drwbassh.hxx>
44 #include <swdtflvr.hxx>
45 #include <svx/svditer.hxx>
46 #define ShellClass_SwDrawBaseShell
47 #include <sfx2/msg.hxx>
48 #include <swslots.hxx>
49 #include <svx/svxdlg.hxx>
50 #include <swabstdlg.hxx>
51 #include <swundo.hxx>
52 #include <com/sun/star/text/HoriOrientation.hpp>
53 #include <com/sun/star/text/VertOrientation.hpp>
54 #include <com/sun/star/text/RelOrientation.hpp>
55 #include <IDocumentDrawModelAccess.hxx>
56 #include <fmtfollowtextflow.hxx>
57 #include <textboxhelper.hxx>
58 
59 using namespace ::com::sun::star;
60 
SFX_IMPL_SUPERCLASS_INTERFACE(SwDrawBaseShell,SwBaseShell)61 SFX_IMPL_SUPERCLASS_INTERFACE(SwDrawBaseShell, SwBaseShell)
62 
63 void SwDrawBaseShell::InitInterface_Impl()
64 {
65 }
66 
67 
SwDrawBaseShell(SwView & _rView)68 SwDrawBaseShell::SwDrawBaseShell(SwView &_rView)
69     : SwBaseShell(_rView)
70 {
71     GetShell().NoEdit();
72 
73     SwEditWin& rWin = GetView().GetEditWin();
74 
75     rWin.SetBezierMode(SID_BEZIER_MOVE);
76 
77     if ( !_rView.GetDrawFuncPtr() )
78         _rView.GetEditWin().StdDrawMode( OBJ_NONE, true );
79 
80     SwTransferable::CreateSelection( GetShell() );
81 }
82 
~SwDrawBaseShell()83 SwDrawBaseShell::~SwDrawBaseShell()
84 {
85     GetView().ExitDraw();
86     GetShell().Edit();
87     SwTransferable::ClearSelection( GetShell() );
88 }
89 
Execute(SfxRequest const & rReq)90 void SwDrawBaseShell::Execute(SfxRequest const &rReq)
91 {
92     SwWrtShell *pSh = &GetShell();
93     SdrView*    pSdrView = pSh->GetDrawView();
94     const SfxItemSet *pArgs = rReq.GetArgs();
95     sal_uInt16      nSlotId = rReq.GetSlot();
96     bool        bChanged = pSdrView->GetModel()->IsChanged();
97     pSdrView->GetModel()->SetChanged(false);
98     const SfxPoolItem* pItem = nullptr;
99     if(pArgs)
100         pArgs->GetItemState(nSlotId, false, &pItem);
101 
102     bool bAlignPossible = pSh->IsAlignPossible();
103 
104     bool bTopParam = true, bBottomParam = true;
105     bool bDone = false;
106     SfxBindings& rBind = GetView().GetViewFrame()->GetBindings();
107 
108     switch (nSlotId)
109     {
110         case FN_DRAW_WRAP_DLG:
111         {
112             if(pSdrView->AreObjectsMarked())
113             {
114                 if(!pArgs)
115                 {
116                     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
117                     if( rMarkList.GetMark(0) != nullptr )
118                     {
119                         SfxItemSet aSet(
120                             GetPool(),
121                             svl::Items<
122                                 RES_LR_SPACE, RES_UL_SPACE,
123                                 RES_SURROUND, RES_SURROUND,
124                                 RES_ANCHOR, RES_ANCHOR,
125                                 RES_WRAP_INFLUENCE_ON_OBJPOS, RES_WRAP_INFLUENCE_ON_OBJPOS,
126                                 SID_HTML_MODE, SID_HTML_MODE,
127                                 FN_DRAW_WRAP_DLG, FN_DRAW_WRAP_DLG>{});
128 
129                         aSet.Put(SfxBoolItem(SID_HTML_MODE,
130                             0 != ::GetHtmlMode(pSh->GetView().GetDocShell())));
131 
132                         aSet.Put(SfxInt16Item(FN_DRAW_WRAP_DLG, sal_uInt8(pSh->GetLayerId())));
133 
134                         pSh->GetObjAttr(aSet);
135                         SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
136                         ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSwWrapDlg(GetView().GetFrameWeld(), aSet, pSh));
137 
138                         if (pDlg->Execute() == RET_OK)
139                         {
140                             const SfxPoolItem* pWrapItem;
141                             const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
142                             if(SfxItemState::SET == pOutSet->GetItemState(FN_DRAW_WRAP_DLG, false, &pWrapItem))
143                             {
144                                 short nLayer = static_cast<const SfxInt16Item*>(pWrapItem)->GetValue();
145                                 if (nLayer == 1)
146                                     pSh->SelectionToHeaven();
147                                 else
148                                     pSh->SelectionToHell();
149                             }
150 
151                             pSh->SetObjAttr(*pOutSet);
152                         }
153                     }
154                 }
155             }
156         }
157         break;
158 
159         case SID_ATTR_TRANSFORM:
160         {
161             if(pSdrView->AreObjectsMarked())
162             {
163                 if(!pArgs)
164                 {
165                     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
166                     if( rMarkList.GetMark(0) != nullptr )
167                     {
168                         SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
169                         VclPtr<SfxAbstractTabDialog> pDlg;
170                         bool bCaption = false;
171 
172                         // Allowed anchorages:
173                         RndStdIds nAnchor = pSh->GetAnchorId();
174                         SvxAnchorIds nAllowedAnchors = SvxAnchorIds::Paragraph | SvxAnchorIds::Character | SvxAnchorIds::Page;
175                         sal_uInt16 nHtmlMode = ::GetHtmlMode(pSh->GetView().GetDocShell());
176 
177                         if ( pSh->IsFlyInFly() )
178                             nAllowedAnchors |= SvxAnchorIds::Fly;
179 
180                         if (pObj->GetObjIdentifier() == OBJ_CAPTION )
181                             bCaption = true;
182 
183                         if (bCaption)
184                         {
185                             SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
186                             VclPtr<AbstractSvxCaptionDialog> pCaptionDlg =
187                                     pFact->CreateCaptionDialog( rReq.GetFrameWeld(), pSdrView, nAllowedAnchors );
188                             pDlg.reset(pCaptionDlg);
189                             pCaptionDlg->SetValidateFramePosLink( LINK(this, SwDrawBaseShell, ValidatePosition) );
190                         }
191                         else
192                         {
193                             SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
194                             VclPtr<AbstractSvxTransformTabDialog> pTransform =
195                                         pFact->CreateSvxTransformTabDialog(rReq.GetFrameWeld(), nullptr, pSdrView, nAllowedAnchors);
196                             pDlg.reset(pTransform);
197                             pTransform->SetValidateFramePosLink( LINK(this, SwDrawBaseShell, ValidatePosition) );
198                         }
199                         SfxItemSet aNewAttr(pSdrView->GetGeoAttrFromMarked());
200 
201                         const sal_uInt16* pRange = pDlg->GetInputRanges( *aNewAttr.GetPool() );
202                         SfxItemSet aSet( *aNewAttr.GetPool(), pRange );
203                         FieldUnit eMetric = ::GetDfltMetric( dynamic_cast<SwWebView*>(&GetView()) != nullptr );
204                         SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric)) );
205 
206                         aSet.Put( aNewAttr, false );
207 
208                         if (bCaption)
209                             pSdrView->GetAttributes( aSet );
210 
211                         aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_ANCHOR, static_cast<sal_Int16>(nAnchor)));
212                         bool bRTL;
213                         bool bVertL2R;
214                         aSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_IN_VERTICAL_TEXT, pSh->IsFrameVertical(true, bRTL, bVertL2R)));
215                         aSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_IN_RTL_TEXT, bRTL));
216 
217                         SwFrameFormat* pFrameFormat = FindFrameFormat( pObj );
218 
219                         aSet.Put( pFrameFormat->GetFormatAttr(RES_FOLLOW_TEXT_FLOW) );
220 
221                         SwFormatVertOrient aVOrient(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT));
222                         aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_VERT_ORIENT, aVOrient.GetVertOrient()));
223                         aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_VERT_RELATION, aVOrient.GetRelationOrient() ));
224                         aSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_VERT_POSITION, aVOrient.GetPos()));
225 
226                         SwFormatHoriOrient aHOrient(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT));
227                         aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_HORI_ORIENT, aHOrient.GetHoriOrient()));
228                         aSet.Put(SfxInt16Item(SID_ATTR_TRANSFORM_HORI_RELATION, aHOrient.GetRelationOrient() ));
229                         aSet.Put(SfxBoolItem(SID_ATTR_TRANSFORM_HORI_MIRROR, aHOrient.IsPosToggle()));
230                         aSet.Put(SfxInt32Item(SID_ATTR_TRANSFORM_HORI_POSITION, aHOrient.GetPos()));
231 
232                         aSet.Put(SfxUInt16Item(SID_HTML_MODE, nHtmlMode));
233 
234                         pDlg->SetInputSet( &aSet );
235 
236                         pDlg->StartExecuteAsync([bCaption, bChanged, pDlg, pFrameFormat, pSdrView,
237                                                  pSh, &rMarkList, this](
238                                                     sal_Int32 nResult){
239                             pSdrView->GetModel()->SetChanged(false);
240 
241                             if (nResult == RET_OK)
242                             {
243                                 SwFormatVertOrient aVOrientFinal(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT));
244                                 SwFormatHoriOrient aHOrientFinal(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT));
245 
246                                 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
247                                 pSh->StartAllAction();
248 
249                                 // #i30451#
250                                 pSh->StartUndo(SwUndoId::INSFMTATTR);
251 
252                                 pSdrView->SetGeoAttrToMarked(*pOutSet);
253 
254                                 if (bCaption)
255                                     pSdrView->SetAttributes(*pOutSet);
256 
257                                 bool bPosCorr =
258                                     SfxItemState::SET != pOutSet->GetItemState(
259                                         SID_ATTR_TRANSFORM_POS_X, false ) &&
260                                     SfxItemState::SET != pOutSet->GetItemState(
261                                         SID_ATTR_TRANSFORM_POS_Y, false );
262 
263                                 SfxItemSet aFrameAttrSet(GetPool(), svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END - 1>{});
264 
265                                 bool bSingleSelection = rMarkList.GetMarkCount() == 1;
266 
267                                 const SfxPoolItem* pAnchorItem;
268                                 if(SfxItemState::SET == pOutSet->GetItemState(
269                                     SID_ATTR_TRANSFORM_ANCHOR, false, &pAnchorItem))
270                                 {
271                                     if(!bSingleSelection)
272                                         pSh->ChgAnchor(static_cast<RndStdIds>(static_cast<const SfxInt16Item*>(pAnchorItem)
273                                                 ->GetValue()), false, bPosCorr );
274                                     else
275                                     {
276                                         SwFormatAnchor aAnchor(pFrameFormat->GetAnchor());
277                                         aAnchor.SetType(static_cast<RndStdIds>(static_cast<const SfxInt16Item*>(pAnchorItem)->GetValue()));
278                                         aFrameAttrSet.Put( aAnchor );
279                                     }
280                                 }
281                                 const SfxPoolItem* pHoriOrient = nullptr;
282                                 const SfxPoolItem* pHoriRelation = nullptr;
283                                 const SfxPoolItem* pHoriPosition = nullptr;
284                                 const SfxPoolItem* pHoriMirror = nullptr;
285                                 pOutSet->GetItemState(SID_ATTR_TRANSFORM_HORI_ORIENT, false, &pHoriOrient);
286                                 pOutSet->GetItemState(SID_ATTR_TRANSFORM_HORI_RELATION, false, &pHoriRelation);
287                                 pOutSet->GetItemState(SID_ATTR_TRANSFORM_HORI_POSITION, false, &pHoriPosition);
288                                 pOutSet->GetItemState(SID_ATTR_TRANSFORM_HORI_MIRROR, false, &pHoriMirror);
289                                 if(pHoriOrient || pHoriRelation || pHoriPosition || pHoriMirror)
290                                 {
291                                     if(pHoriOrient)
292                                         aHOrientFinal.SetHoriOrient(
293                                               static_cast<const SfxInt16Item*>(pHoriOrient)->GetValue());
294                                     if(pHoriRelation)
295                                         aHOrientFinal.SetRelationOrient(
296                                                   static_cast<const SfxInt16Item*>(pHoriRelation)->GetValue());
297                                     if(pHoriPosition)
298                                         aHOrientFinal.SetPos( static_cast<const SfxInt32Item*>(pHoriPosition)->GetValue());
299                                     if(pHoriMirror)
300                                         aHOrientFinal.SetPosToggle( static_cast<const SfxBoolItem*>(pHoriMirror)->GetValue());
301                                     aFrameAttrSet.Put(aHOrientFinal);
302                                 }
303 
304                                 const SfxPoolItem* pVertOrient = nullptr;
305                                 const SfxPoolItem* pVertRelation = nullptr;
306                                 const SfxPoolItem* pVertPosition = nullptr;
307                                 pOutSet->GetItemState(SID_ATTR_TRANSFORM_VERT_ORIENT, false, &pVertOrient);
308                                 pOutSet->GetItemState(SID_ATTR_TRANSFORM_VERT_RELATION, false, &pVertRelation);
309                                 pOutSet->GetItemState(SID_ATTR_TRANSFORM_VERT_POSITION, false, &pVertPosition);
310                                 if(pVertOrient || pVertRelation || pVertPosition )
311                                 {
312                                     if(pVertOrient)
313                                         aVOrientFinal.SetVertOrient(
314                                             static_cast<const SfxInt16Item*>(pVertOrient)->GetValue());
315                                     if(pVertRelation)
316                                         aVOrientFinal.SetRelationOrient(
317                                             static_cast<const SfxInt16Item*>(pVertRelation)->GetValue());
318                                     if(pVertPosition)
319                                         aVOrientFinal.SetPos( static_cast<const SfxInt32Item*>(pVertPosition)->GetValue());
320                                     aFrameAttrSet.Put( aVOrientFinal );
321                                 }
322                                 const SfxPoolItem* pFollowItem = nullptr;
323                                 pOutSet->GetItemState(RES_FOLLOW_TEXT_FLOW, false, &pFollowItem);
324                                 if(pFollowItem)
325                                     aFrameAttrSet.Put(*pFollowItem);
326 
327                                 if(aFrameAttrSet.Count())
328                                     pSh->SetDrawingAttr(aFrameAttrSet);
329 
330                                 GetView().GetViewFrame()->GetBindings().InvalidateAll(false);
331 
332                                 // #i30451#
333                                 pSh->EndUndo( SwUndoId::INSFMTATTR );
334 
335                                 pSh->EndAllAction();
336                             }
337 
338                             if (pSdrView->GetModel()->IsChanged())
339                                 pSh->SetModified();
340                             else if (bChanged)
341                                 pSdrView->GetModel()->SetChanged();
342 
343                             pDlg->disposeOnce();
344                         });
345                     }
346                 }
347                 else
348                 {
349                     pSh->StartAllAction();
350                     pSdrView->SetGeoAttrToMarked( *pArgs );
351                     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
352                     SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
353                     if (pObj)
354                     {
355                         SwFrameFormat* pFrameFormat = FindFrameFormat(pObj);
356                         if (pFrameFormat)
357                         {
358                             const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
359                             // Don't change shape position / size, just update the anchor doc model
360                             // position.
361                             pSh->ChgAnchor(rAnchor.GetAnchorId(), /*bSameOnly=*/true);
362                         }
363                     }
364                     pSh->EndAllAction();
365                 }
366             }
367         }
368         break;
369 
370         case SID_DELETE:
371         case FN_BACKSPACE:
372             if (pSh->IsObjSelected() && !pSdrView->IsTextEdit())
373             {
374                 bDone = true;
375 
376                 if( GetView().IsDrawRotate() )
377                 {
378                     pSh->SetDragMode( SdrDragMode::Move );
379                     GetView().FlipDrawRotate();
380                 }
381 
382                 pSh->SetModified();
383                 pSh->DelSelectedObj();
384 
385                 if (rReq.IsAPI() ||
386                     GetView().GetEditWin().IsObjectSelect() )
387                 {
388                     // If basic call, then back to the text shell, because the
389                     // Basic otherwise has no possibility to return.
390                     if (GetView().GetDrawFuncPtr())
391                     {
392                         GetView().GetDrawFuncPtr()->Deactivate();
393                         GetView().SetDrawFuncPtr(nullptr);
394                     }
395                     GetView().LeaveDrawCreate();    // Switch to selection mode
396                 }
397 
398                 if (pSh->IsSelFrameMode())
399                 {
400                     pSh->LeaveSelFrameMode();
401                     // #105852# FME
402                 }
403             }
404             break;
405 
406         case SID_GROUP:
407             if (pSh->IsObjSelected() > 1 && pSh->IsGroupAllowed())
408             {
409                 pSh->GroupSelection();
410                 rBind.Invalidate(SID_UNGROUP);
411             }
412             break;
413 
414         case SID_UNGROUP:
415             if (pSh->IsGroupSelected() && pSh->IsUnGroupAllowed())
416             {
417                 pSh->UnGroupSelection();
418                 rBind.Invalidate(SID_GROUP);
419             }
420             break;
421 
422         case SID_ENTER_GROUP:
423             if (pSh->IsGroupSelected())
424             {
425                 pSdrView->EnterMarkedGroup();
426                 rBind.InvalidateAll(false);
427             }
428             break;
429 
430         case SID_LEAVE_GROUP:
431             if (pSdrView->IsGroupEntered())
432             {
433                 pSdrView->LeaveOneGroup();
434                 rBind.Invalidate(SID_ENTER_GROUP);
435                 rBind.Invalidate(SID_UNGROUP);
436             }
437             break;
438 
439         case SID_OBJECT_ALIGN_LEFT:
440         case SID_OBJECT_ALIGN_CENTER:
441         case SID_OBJECT_ALIGN_RIGHT:
442         case SID_OBJECT_ALIGN_UP:
443         case SID_OBJECT_ALIGN_MIDDLE:
444         case SID_OBJECT_ALIGN_DOWN:
445         {
446             if ( bAlignPossible )
447             {
448                 const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
449                 if (rMarkList.GetMarkCount() == 1
450                     && !SwTextBoxHelper::hasTextFrame(rMarkList.GetMark(0)->GetMarkedSdrObj()))
451                 {
452                     sal_Int16 nHorizOrient = -1, nVertOrient = -1;
453 
454                     switch (nSlotId)
455                     {
456                         case SID_OBJECT_ALIGN_LEFT:
457                             nHorizOrient = text::HoriOrientation::LEFT;
458                             break;
459                         case SID_OBJECT_ALIGN_CENTER:
460                             nHorizOrient = text::HoriOrientation::CENTER;
461                             break;
462                         case SID_OBJECT_ALIGN_RIGHT:
463                             nHorizOrient = text::HoriOrientation::RIGHT;
464                             break;
465                         case SID_OBJECT_ALIGN_UP:
466                             nVertOrient = text::VertOrientation::TOP;
467                             break;
468                         case SID_OBJECT_ALIGN_MIDDLE:
469                             nVertOrient = text::VertOrientation::CENTER;
470                             break;
471                         case SID_OBJECT_ALIGN_DOWN:
472                             nVertOrient = text::VertOrientation::BOTTOM;
473                             break;
474                         default:
475                             break;
476                     }
477 
478                     if (nHorizOrient != -1)
479                     {
480                         pSh->StartAction();
481                         SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
482                         SwFrameFormat* pFrameFormat = FindFrameFormat( pObj );
483                         SwFormatHoriOrient aHOrient(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT));
484                         aHOrient.SetHoriOrient( nHorizOrient );
485                         pFrameFormat->SetFormatAttr(aHOrient);
486                         pSh->EndAction();
487                     }
488 
489                     if (nVertOrient != -1)
490                     {
491                         pSh->StartAction();
492                         SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
493                         SwFrameFormat* pFrameFormat = FindFrameFormat( pObj );
494                         SwFormatVertOrient aVOrient(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT));
495                         aVOrient.SetVertOrient( nVertOrient );
496                         pFrameFormat->SetFormatAttr(aVOrient);
497                         pSh->EndAction();
498                     }
499 
500                     break;
501                 }
502 
503                 pSh->StartAction();
504                 switch (nSlotId)
505                 {
506                     case SID_OBJECT_ALIGN_LEFT:
507                         pSdrView->AlignMarkedObjects(SdrHorAlign::Left, SdrVertAlign::NONE);
508                         break;
509                     case SID_OBJECT_ALIGN_CENTER:
510                         pSdrView->AlignMarkedObjects(SdrHorAlign::Center, SdrVertAlign::NONE);
511                         break;
512                     case SID_OBJECT_ALIGN_RIGHT:
513                         pSdrView->AlignMarkedObjects(SdrHorAlign::Right, SdrVertAlign::NONE);
514                         break;
515                     case SID_OBJECT_ALIGN_UP:
516                         pSdrView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Top);
517                         break;
518                     case SID_OBJECT_ALIGN_MIDDLE:
519                         pSdrView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Center);
520                         break;
521                     case SID_OBJECT_ALIGN_DOWN:
522                         pSdrView->AlignMarkedObjects(SdrHorAlign::NONE, SdrVertAlign::Bottom);
523                         break;
524                 }
525                 pSh->EndAction();
526             }
527         }
528         break;
529 
530         case FN_FRAME_UP:
531             bTopParam = false;
532             [[fallthrough]];
533         case SID_FRAME_TO_TOP:
534             pSh->SelectionToTop( bTopParam );
535             break;
536 
537         case FN_FRAME_DOWN:
538             bBottomParam = false;
539             [[fallthrough]];
540         case SID_FRAME_TO_BOTTOM:
541             pSh->SelectionToBottom( bBottomParam );
542             break;
543 
544         case FN_NAME_SHAPE:
545         {
546             bDone = true;
547 
548             if(1 == pSdrView->GetMarkedObjectCount())
549             {
550                 // #i68101#
551                 SdrObject* pSelected = pSdrView->GetMarkedObjectByIndex(0);
552                 OSL_ENSURE(pSelected, "DrawViewShell::FuTemp03: nMarkCount, but no object (!)");
553                 OUString aName(pSelected->GetName());
554 
555                 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
556                 ScopedVclPtr<AbstractSvxObjectNameDialog> pDlg(pFact->CreateSvxObjectNameDialog(GetView().GetFrameWeld(), aName));
557 
558                 pDlg->SetCheckNameHdl(LINK(this, SwDrawBaseShell, CheckGroupShapeNameHdl));
559 
560                 if(RET_OK == pDlg->Execute())
561                 {
562                     pDlg->GetName(aName);
563                     pSelected->SetName(aName);
564                     pSh->SetModified();
565                 }
566             }
567 
568             break;
569         }
570 
571         // #i68101#
572         case FN_TITLE_DESCRIPTION_SHAPE:
573         {
574             bDone = true;
575 
576             if(1 == pSdrView->GetMarkedObjectCount())
577             {
578                 SdrObject* pSelected = pSdrView->GetMarkedObjectByIndex(0);
579                 OSL_ENSURE(pSelected, "DrawViewShell::FuTemp03: nMarkCount, but no object (!)");
580                 OUString aTitle(pSelected->GetTitle());
581                 OUString aDescription(pSelected->GetDescription());
582 
583                 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
584                 ScopedVclPtr<AbstractSvxObjectTitleDescDialog> pDlg(pFact->CreateSvxObjectTitleDescDialog(GetView().GetFrameWeld(),
585                             aTitle, aDescription));
586 
587                 if(RET_OK == pDlg->Execute())
588                 {
589                     pDlg->GetTitle(aTitle);
590                     pDlg->GetDescription(aDescription);
591 
592                     pSelected->SetTitle(aTitle);
593                     pSelected->SetDescription(aDescription);
594 
595                     pSh->SetModified();
596                 }
597             }
598 
599             break;
600         }
601 
602         default:
603             OSL_ENSURE(false, "wrong Dispatcher");
604             return;
605     }
606     if(!bDone)
607     {
608         if(nSlotId >= SID_OBJECT_ALIGN_LEFT && nSlotId <= SID_OBJECT_ALIGN_DOWN)
609             rBind.Invalidate(SID_ATTR_LONG_LRSPACE);
610         if (pSdrView->GetModel()->IsChanged())
611             pSh->SetModified();
612         else if (bChanged)
613             pSdrView->GetModel()->SetChanged();
614     }
615 }
616 
617 // Checks whether a given name is allowed for a group shape
618 
IMPL_LINK(SwDrawBaseShell,CheckGroupShapeNameHdl,AbstractSvxObjectNameDialog &,rNameDialog,bool)619 IMPL_LINK( SwDrawBaseShell, CheckGroupShapeNameHdl, AbstractSvxObjectNameDialog&, rNameDialog, bool )
620 {
621     SwWrtShell          &rSh = GetShell();
622     SdrView *pSdrView = rSh.GetDrawView();
623     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
624     OSL_ENSURE(rMarkList.GetMarkCount() == 1, "wrong draw selection");
625     SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
626     const OUString sCurrentName = pObj->GetName();
627     OUString sNewName;
628     rNameDialog.GetName(sNewName);
629     bool bRet = false;
630     if (sNewName.isEmpty() || sCurrentName == sNewName)
631         bRet = true;
632     else
633     {
634         bRet = true;
635         SwDrawModel* pModel = rSh.getIDocumentDrawModelAccess().GetDrawModel();
636         SdrObjListIter aIter( pModel->GetPage(0), SdrIterMode::DeepWithGroups );
637         while( aIter.IsMore() )
638         {
639             SdrObject* pTempObj = aIter.Next();
640             if ( pObj != pTempObj && pTempObj->GetName() == sNewName )
641             {
642                 bRet = false;
643                 break;
644             }
645         }
646     }
647     return bRet;
648 }
649 
GetState(SfxItemSet & rSet)650 void SwDrawBaseShell::GetState(SfxItemSet& rSet)
651 {
652     SwWrtShell &rSh = GetShell();
653     SdrView* pSdrView = rSh.GetDrawViewWithValidMarkList();
654     SfxWhichIter aIter( rSet );
655     sal_uInt16 nWhich = aIter.FirstWhich();
656     bool bProtected = rSh.IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE;
657 
658     if (!bProtected)    // Look in the parent
659         bProtected |= rSh.IsSelObjProtected( FlyProtectFlags::Content|FlyProtectFlags::Parent ) != FlyProtectFlags::NONE;
660 
661     while( nWhich )
662     {
663         switch( nWhich )
664         {
665             case FN_DRAW_WRAP_DLG:
666             case SID_ATTR_TRANSFORM:
667             case SID_FRAME_TO_TOP:
668             case SID_FRAME_TO_BOTTOM:
669             case FN_FRAME_UP:
670             case FN_FRAME_DOWN:
671             case SID_DELETE:
672             case FN_BACKSPACE:
673                 if( bProtected || !rSh.IsObjSelected() )
674                     rSet.DisableItem( nWhich );
675                 break;
676             case SID_GROUP:
677                 if ( rSh.IsObjSelected() < 2 || bProtected || !rSh.IsGroupAllowed() )
678                     rSet.DisableItem( nWhich );
679                 break;
680             case SID_UNGROUP:
681                 if ( !rSh.IsGroupSelected() || bProtected || !rSh.IsUnGroupAllowed() )
682                     rSet.DisableItem( nWhich );
683                 break;
684             case SID_ENTER_GROUP:
685                 if ( !rSh.IsGroupSelected() )
686                     rSet.DisableItem( nWhich );
687                 break;
688             case SID_LEAVE_GROUP:
689                 if ( !pSdrView->IsGroupEntered() )
690                     rSet.DisableItem( nWhich );
691                 break;
692             case SID_OBJECT_ALIGN_LEFT:
693             case SID_OBJECT_ALIGN_CENTER:
694             case SID_OBJECT_ALIGN_RIGHT:
695             case SID_OBJECT_ALIGN_UP:
696             case SID_OBJECT_ALIGN_MIDDLE:
697             case SID_OBJECT_ALIGN_DOWN:
698             case SID_OBJECT_ALIGN:
699                 {
700                     bool bDisableThis = false;
701                     bool bDisableHoriz = false;
702                     bool bHoriz = (nWhich == SID_OBJECT_ALIGN_LEFT || nWhich == SID_OBJECT_ALIGN_CENTER ||
703                             nWhich == SID_OBJECT_ALIGN_RIGHT);
704                     bool bVert = (nWhich == SID_OBJECT_ALIGN_UP || nWhich == SID_OBJECT_ALIGN_MIDDLE ||
705                             nWhich == SID_OBJECT_ALIGN_DOWN);
706                     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
707                     if ( !rSh.IsAlignPossible() || bProtected )
708                     {
709                         bDisableThis = true;
710                         rSet.DisableItem( nWhich );
711                     }
712                     else if ( rSh.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
713                     {
714                         //if only one object is selected it can only be vertically
715                         // aligned because it is character bound
716                         if( rMarkList.GetMarkCount() == 1 )
717                         {
718                             bDisableHoriz = true;
719                             rSet.DisableItem(SID_OBJECT_ALIGN_LEFT);
720                             rSet.DisableItem(SID_OBJECT_ALIGN_CENTER);
721                             rSet.DisableItem(SID_OBJECT_ALIGN_RIGHT);
722                         }
723                     }
724 
725                     if (bHoriz && !bDisableThis && !bDisableHoriz &&
726                         rMarkList.GetMarkCount() == 1)
727                     {
728                         sal_Int16 nHoriOrient = -1;
729                         switch(nWhich)
730                         {
731                             case SID_OBJECT_ALIGN_LEFT:
732                                 nHoriOrient = text::HoriOrientation::LEFT;
733                                 break;
734                             case SID_OBJECT_ALIGN_CENTER:
735                                 nHoriOrient = text::HoriOrientation::CENTER;
736                                 break;
737                             case SID_OBJECT_ALIGN_RIGHT:
738                                 nHoriOrient = text::HoriOrientation::RIGHT;
739                                 break;
740                             default:
741                                 break;
742                         }
743 
744                         SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
745                         SwFrameFormat* pFrameFormat = FindFrameFormat(pObj);
746                         SwFormatHoriOrient aHOrient(pFrameFormat->GetFormatAttr(RES_HORI_ORIENT));
747                         rSet.Put(SfxBoolItem(nWhich, aHOrient.GetHoriOrient() == nHoriOrient));
748                     }
749 
750                     if (bVert && !bDisableThis && rMarkList.GetMarkCount() == 1)
751                     {
752                         sal_Int16 nVertOrient = -1;
753                         switch(nWhich)
754                         {
755                             case SID_OBJECT_ALIGN_UP:
756                                 nVertOrient = text::VertOrientation::TOP;
757                                 break;
758                             case SID_OBJECT_ALIGN_MIDDLE:
759                                 nVertOrient = text::VertOrientation::CENTER;
760                                 break;
761                             case SID_OBJECT_ALIGN_DOWN:
762                                 nVertOrient = text::VertOrientation::BOTTOM;
763                                 break;
764                             default:
765                                 break;
766                         }
767 
768                         SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
769                         SwFrameFormat* pFrameFormat = FindFrameFormat(pObj);
770                         SwFormatVertOrient aVOrient(pFrameFormat->GetFormatAttr(RES_VERT_ORIENT));
771                         rSet.Put(SfxBoolItem(nWhich, aVOrient.GetVertOrient() == nVertOrient));
772                     }
773                 }
774                 break;
775 
776             case FN_NAME_SHAPE :
777                 {
778                     if(1 != pSdrView->GetMarkedObjectCount())
779                     {
780                         rSet.DisableItem( nWhich );
781                     }
782                 }
783                 break;
784 
785             // #i68101#
786             case FN_TITLE_DESCRIPTION_SHAPE:
787                 {
788                     const bool bIsWebView(nullptr != dynamic_cast<SwWebView*>(&GetView()));
789 
790                     if(!bIsWebView && 1 != pSdrView->GetMarkedObjectCount())
791                     {
792                         rSet.DisableItem( nWhich );
793                     }
794                 }
795                 break;
796         }
797         nWhich = aIter.NextWhich();
798     }
799 }
800 
GetDrawAttrStateForIFBX(SfxItemSet & rSet)801 void SwDrawBaseShell::GetDrawAttrStateForIFBX( SfxItemSet& rSet )
802 {
803     SwWrtShell *pSh = &GetShell();
804     SdrView*    pSdrView = pSh->GetDrawView();
805     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
806     if( rMarkList.GetMark(0) != nullptr )
807     {
808         SfxItemSet aNewAttr(pSdrView->GetGeoAttrFromMarked());
809         rSet.Put(aNewAttr,false);
810     }
811 }
812 
Disable(SfxItemSet & rSet,sal_uInt16 nWhich)813 bool SwDrawBaseShell::Disable(SfxItemSet& rSet, sal_uInt16 nWhich)
814 {
815     bool bDisable = GetShell().IsSelObjProtected(FlyProtectFlags::Content) != FlyProtectFlags::NONE;
816 
817     if (bDisable)
818     {
819         if (nWhich)
820             rSet.DisableItem( nWhich );
821         else
822         {
823             SfxWhichIter aIter( rSet );
824             nWhich = aIter.FirstWhich();
825             while (nWhich)
826             {
827                 rSet.DisableItem( nWhich );
828                 nWhich = aIter.NextWhich();
829             }
830         }
831     }
832 
833     return bDisable;
834 }
835 
DisableState(SfxItemSet & rSet)836 void SwDrawBaseShell::DisableState( SfxItemSet& rSet )
837 {
838     SwWrtShell *pSh = &GetShell();
839     SdrView*    pSdrView = pSh->GetDrawView();
840     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
841     const size_t nMarkCount = rMarkList.GetMarkCount();
842     bool bShowArea = true, bShowMeasure = true;
843 
844     for (size_t i = 0; i < nMarkCount && i < 50; ++i)
845     {
846         SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
847         sal_uInt16 nObjType = pObj->GetObjIdentifier();
848 
849         if ( nObjType != OBJ_MEASURE )
850             bShowMeasure = false;
851 
852         // If marked object is 2D, disable format area command.
853         if ( nObjType == OBJ_PLIN     ||
854              nObjType == OBJ_LINE     ||
855              nObjType == OBJ_PATHLINE ||
856              nObjType == OBJ_FREELINE ||
857              nObjType == OBJ_EDGE     ||
858              nObjType == OBJ_CARC     ||
859              bShowMeasure )
860             bShowArea = false;
861 
862         if (!bShowArea && !bShowMeasure)
863             break;
864     }
865 
866     if (!bShowArea)
867         rSet.DisableItem(SID_ATTRIBUTES_AREA);
868 
869     if (!bShowMeasure)
870         rSet.DisableItem(SID_MEASURE_DLG);
871 
872     Disable(rSet);
873 
874 }
875 
876 // Validate of drawing positions
877 
IMPL_LINK(SwDrawBaseShell,ValidatePosition,SvxSwFrameValidation &,rValidation,void)878 IMPL_LINK(SwDrawBaseShell, ValidatePosition, SvxSwFrameValidation&, rValidation, void )
879 {
880     SwWrtShell *pSh = &GetShell();
881     rValidation.nMinHeight = MINFLY;
882     rValidation.nMinWidth =  MINFLY;
883 
884     SwRect aBoundRect;
885 
886     // OD 18.09.2003 #i18732# - adjustment for allowing vertical position
887     //      aligned to page for fly frame anchored to paragraph or to character.
888     const RndStdIds eAnchorType = rValidation.nAnchorType;
889     const SwPosition* pContentPos = nullptr;
890     SdrView*  pSdrView = pSh->GetDrawView();
891     const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList();
892     if( rMarkList.GetMarkCount() == 1 )
893     {
894         SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
895         SwFrameFormat* pFrameFormat = FindFrameFormat( pObj );
896         pContentPos = pFrameFormat->GetAnchor().GetContentAnchor();
897     }
898 
899     pSh->CalcBoundRect( aBoundRect, eAnchorType,
900                            rValidation.nHRelOrient,
901                            rValidation.nVRelOrient,
902                            pContentPos,
903                            rValidation.bFollowTextFlow,
904                            rValidation.bMirror, nullptr, &rValidation.aPercentSize);
905 
906     bool bIsInVertical( false );
907     {
908         bool bRTL;
909         bool bVertL2R;
910         bIsInVertical = pSh->IsFrameVertical(true, bRTL, bVertL2R);
911     }
912     if(bIsInVertical)
913     {
914         Point aPos(aBoundRect.Pos());
915         tools::Long nTmp = aPos.X();
916         aPos.setX( aPos.Y() );
917         aPos.setY( nTmp );
918         Size aSize(aBoundRect.SSize());
919         nTmp = aSize.Width();
920         aSize.setWidth( aSize.Height() );
921         aSize.setHeight( nTmp );
922         aBoundRect.Chg( aPos, aSize );
923         //exchange width/height to enable correct values
924         nTmp = rValidation.nWidth;
925         rValidation.nWidth = rValidation.nHeight;
926         rValidation.nHeight = nTmp;
927     }
928     if ((eAnchorType == RndStdIds::FLY_AT_PAGE) || (eAnchorType == RndStdIds::FLY_AT_FLY))
929     {
930         // MinimalPosition
931         rValidation.nMinHPos = aBoundRect.Left();
932         rValidation.nMinVPos = aBoundRect.Top();
933         SwTwips nH = rValidation.nHPos;
934         SwTwips nV = rValidation.nVPos;
935 
936         if (rValidation.nHPos + rValidation.nWidth > aBoundRect.Right())
937         {
938             if (rValidation.nHoriOrient == text::HoriOrientation::NONE)
939             {
940                 rValidation.nHPos -= ((rValidation.nHPos + rValidation.nWidth) - aBoundRect.Right());
941                 nH = rValidation.nHPos;
942             }
943             else
944                 rValidation.nWidth = aBoundRect.Right() - rValidation.nHPos;
945         }
946 
947         if (rValidation.nHPos + rValidation.nWidth > aBoundRect.Right())
948             rValidation.nWidth = aBoundRect.Right() - rValidation.nHPos;
949 
950         if (rValidation.nVPos + rValidation.nHeight > aBoundRect.Bottom())
951         {
952             if (rValidation.nVertOrient == text::VertOrientation::NONE)
953             {
954                 rValidation.nVPos -= ((rValidation.nVPos + rValidation.nHeight) - aBoundRect.Bottom());
955                 nV = rValidation.nVPos;
956             }
957             else
958                 rValidation.nHeight = aBoundRect.Bottom() - rValidation.nVPos;
959         }
960 
961         if (rValidation.nVPos + rValidation.nHeight > aBoundRect.Bottom())
962             rValidation.nHeight = aBoundRect.Bottom() - rValidation.nVPos;
963 
964         if ( rValidation.nVertOrient != text::VertOrientation::NONE )
965             nV = aBoundRect.Top();
966 
967         if ( rValidation.nHoriOrient != text::HoriOrientation::NONE )
968             nH = aBoundRect.Left();
969 
970         rValidation.nMaxHPos   = aBoundRect.Right()  - rValidation.nWidth;
971         rValidation.nMaxHeight = aBoundRect.Bottom() - nV;
972 
973         rValidation.nMaxVPos   = aBoundRect.Bottom() - rValidation.nHeight;
974         rValidation.nMaxWidth  = aBoundRect.Right()  - nH;
975     }
976     else if ((eAnchorType == RndStdIds::FLY_AT_PARA) || (eAnchorType == RndStdIds::FLY_AT_CHAR))
977     {
978         if (rValidation.nHPos + rValidation.nWidth > aBoundRect.Right())
979         {
980             if (rValidation.nHoriOrient == text::HoriOrientation::NONE)
981             {
982                 rValidation.nHPos -= ((rValidation.nHPos + rValidation.nWidth) - aBoundRect.Right());
983             }
984             else
985                 rValidation.nWidth = aBoundRect.Right() - rValidation.nHPos;
986         }
987 
988         // OD 29.09.2003 #i17567#, #i18732# - consider following the text flow
989         // and alignment at page areas.
990         const bool bMaxVPosAtBottom = !rValidation.bFollowTextFlow ||
991                                       rValidation.nVRelOrient == text::RelOrientation::PAGE_FRAME ||
992                                       rValidation.nVRelOrient == text::RelOrientation::PAGE_PRINT_AREA ||
993                                       rValidation.nVRelOrient == text::RelOrientation::PAGE_PRINT_AREA_BOTTOM;
994         {
995             SwTwips nTmpMaxVPos = ( bMaxVPosAtBottom
996                                     ? aBoundRect.Bottom()
997                                     : aBoundRect.Height() ) -
998                                   rValidation.nHeight;
999             if ( rValidation.nVPos > nTmpMaxVPos )
1000             {
1001                 if (rValidation.nVertOrient == text::VertOrientation::NONE)
1002                 {
1003                     rValidation.nVPos = nTmpMaxVPos;
1004                 }
1005                 else
1006                 {
1007                     rValidation.nHeight = ( bMaxVPosAtBottom
1008                                      ? aBoundRect.Bottom()
1009                                      : aBoundRect.Height() ) - rValidation.nVPos;
1010                 }
1011             }
1012         }
1013 
1014         rValidation.nMinHPos  = aBoundRect.Left();
1015         rValidation.nMaxHPos  = aBoundRect.Right() - rValidation.nWidth;
1016 
1017         rValidation.nMinVPos  = aBoundRect.Top();
1018         // OD 26.09.2003 #i17567#, #i18732# - determine maximum vertical position
1019         if ( bMaxVPosAtBottom )
1020         {
1021             rValidation.nMaxVPos  = aBoundRect.Bottom() - rValidation.nHeight;
1022         }
1023         else
1024         {
1025             rValidation.nMaxVPos  = aBoundRect.Height() - rValidation.nHeight;
1026         }
1027 
1028         // Maximum width height
1029         const SwTwips nH = ( rValidation.nHoriOrient != text::HoriOrientation::NONE )
1030                            ? aBoundRect.Left()
1031                            : rValidation.nHPos;
1032         const SwTwips nV = ( rValidation.nVertOrient != text::VertOrientation::NONE )
1033                            ? aBoundRect.Top()
1034                            : rValidation.nVPos;
1035         rValidation.nMaxHeight  = rValidation.nMaxVPos + rValidation.nHeight - nV;
1036         rValidation.nMaxWidth   = rValidation.nMaxHPos + rValidation.nWidth - nH;
1037     }
1038     else if (eAnchorType == RndStdIds::FLY_AS_CHAR)
1039     {
1040         rValidation.nMinHPos = 0;
1041         rValidation.nMaxHPos = 0;
1042 
1043         rValidation.nMaxHeight = aBoundRect.Height();
1044         rValidation.nMaxWidth  = aBoundRect.Width();
1045 
1046         rValidation.nMaxVPos   = aBoundRect.Height();
1047         rValidation.nMinVPos   = -aBoundRect.Height() + rValidation.nHeight;
1048         if (rValidation.nMaxVPos < rValidation.nMinVPos)
1049         {
1050             rValidation.nMinVPos = rValidation.nMaxVPos;
1051             rValidation.nMaxVPos = -aBoundRect.Height();
1052         }
1053     }
1054     if(bIsInVertical)
1055     {
1056         //restore width/height exchange
1057         tools::Long nTmp = rValidation.nWidth;
1058         rValidation.nWidth = rValidation.nHeight;
1059         rValidation.nHeight = nTmp;
1060     }
1061 
1062     if (rValidation.nMaxWidth < rValidation.nWidth)
1063         rValidation.nWidth = rValidation.nMaxWidth;
1064     if (rValidation.nMaxHeight < rValidation.nHeight)
1065         rValidation.nHeight = rValidation.nMaxHeight;
1066 }
1067 
1068 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1069