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