1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/EmbedMisc.hpp>
21 #include <com/sun/star/embed/XEmbeddedObject.hpp>
23 #include <editeng/eeitem.hxx>
24 #include <editeng/sizeitem.hxx>
25 #include <svx/svdpagv.hxx>
26 #include <svx/xdef.hxx>
27 #include <sfx2/objsh.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <svl/ptitem.hxx>
30 #include <svx/svdobj.hxx>
31 #include <svx/svdouno.hxx>
32 #include <svx/extrusionbar.hxx>
33 #include <svx/fontworkbar.hxx>
34 #include <svx/sidebar/SelectionChangeHandler.hxx>
35 #include <svx/sidebar/SelectionAnalyzer.hxx>
36 #include <svx/sidebar/ContextChangeEventMultiplexer.hxx>
39 #include <drawview.hxx>
40 #include <viewdata.hxx>
42 #include <tabvwsh.hxx>
43 #include <document.hxx>
44 #include <drwlayer.hxx>
45 #include <userdat.hxx>
46 #include <drtxtob.hxx>
47 #include <gridwin.hxx>
48 #include <svx/svdoole2.hxx>
50 using namespace com::sun::star
;
52 ScDrawShell::ScDrawShell( ScViewData
* pData
) :
53 SfxShell(pData
->GetViewShell()),
55 mpSelectionChangeHandler(new svx::sidebar::SelectionChangeHandler(
56 [this] () { return this->GetSidebarContextName(); },
57 GetFrame()->GetFrame().GetController(),
58 vcl::EnumContext::Context::Cell
))
60 SetPool( &pViewData
->GetScDrawView()->GetModel()->GetItemPool() );
61 SfxUndoManager
* pMgr
= pViewData
->GetSfxDocShell()->GetUndoManager();
62 SetUndoManager( pMgr
);
63 if ( !pViewData
->GetDocument()->IsUndoEnabled() )
65 pMgr
->SetMaxUndoActionCount( 0 );
69 mpSelectionChangeHandler
->Connect();
72 ScDrawShell::~ScDrawShell()
74 mpSelectionChangeHandler
->Disconnect();
77 void ScDrawShell::GetState( SfxItemSet
& rSet
) // Conditions / Toggles
79 ScDrawView
* pView
= pViewData
->GetScDrawView();
80 SdrDragMode eMode
= pView
->GetDragMode();
82 rSet
.Put( SfxBoolItem( SID_OBJECT_ROTATE
, eMode
== SdrDragMode::Rotate
) );
83 rSet
.Put( SfxBoolItem( SID_OBJECT_MIRROR
, eMode
== SdrDragMode::Mirror
) );
84 rSet
.Put( SfxBoolItem( SID_BEZIER_EDIT
, !pView
->IsFrameDragSingles() ) );
86 sal_uInt16 nFWId
= ScGetFontWorkId();
87 SfxViewFrame
* pViewFrm
= pViewData
->GetViewShell()->GetViewFrame();
88 rSet
.Put(SfxBoolItem(SID_FONTWORK
, pViewFrm
->HasChildWindow(nFWId
)));
90 // Notes always default to Page anchor.
91 bool bDisableAnchor
= false;
92 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
93 if ( rMarkList
.GetMarkCount() == 1 )
95 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
96 if( ScDrawLayer::IsNoteCaption( pObj
) )
98 bDisableAnchor
= true;
99 rSet
.DisableItem( SID_ANCHOR_PAGE
);
100 rSet
.DisableItem( SID_ANCHOR_CELL
);
101 rSet
.DisableItem( SID_ANCHOR_CELL_RESIZE
);
105 if ( !bDisableAnchor
)
107 switch( pView
->GetAnchorType() )
110 rSet
.Put( SfxBoolItem( SID_ANCHOR_PAGE
, true ) );
111 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL
, false ) );
112 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE
, false ) );
116 rSet
.Put( SfxBoolItem( SID_ANCHOR_PAGE
, false ) );
117 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL
, true ) );
118 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE
, false ) );
121 case SCA_CELL_RESIZE
:
122 rSet
.Put( SfxBoolItem( SID_ANCHOR_PAGE
, false ) );
123 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL
, false ) );
124 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE
, true ) );
128 rSet
.Put( SfxBoolItem( SID_ANCHOR_PAGE
, false ) );
129 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL
, false ) );
130 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE
, false ) );
136 void ScDrawShell::GetDrawFuncState( SfxItemSet
& rSet
) // disable functions
138 ScDrawView
* pView
= pViewData
->GetScDrawView();
140 // call IsMirrorAllowed first to make sure ForcePossibilities (and thus CheckMarked)
141 // is called before GetMarkCount, so the nMarkCount value is valid for the rest of this method.
142 if (!pView
->IsMirrorAllowed(true,true))
144 rSet
.DisableItem( SID_MIRROR_HORIZONTAL
);
145 rSet
.DisableItem( SID_MIRROR_VERTICAL
);
146 rSet
.DisableItem( SID_FLIP_HORIZONTAL
);
147 rSet
.DisableItem( SID_FLIP_VERTICAL
);
150 if (pViewData
->GetViewShell()->isContentExtractionLocked())
152 rSet
.DisableItem(SID_COPY
);
153 rSet
.DisableItem(SID_CUT
);
156 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
157 const size_t nMarkCount
= rMarkList
.GetMarkCount();
159 if ( nMarkCount
<= 1 || !pView
->IsGroupPossible() )
160 rSet
.DisableItem( SID_GROUP
);
161 if ( nMarkCount
== 0 || !pView
->IsUnGroupPossible() )
162 rSet
.DisableItem( SID_UNGROUP
);
163 if ( nMarkCount
!= 1 || !pView
->IsGroupEnterPossible() )
164 rSet
.DisableItem( SID_ENTER_GROUP
);
165 if ( !pView
->IsGroupEntered() )
166 rSet
.DisableItem( SID_LEAVE_GROUP
);
168 if ( nMarkCount
<= 1 ) // Nothing or only one object selected
171 rSet
.DisableItem( SID_OBJECT_ALIGN_LEFT
); // no alignment on the side
172 rSet
.DisableItem( SID_OBJECT_ALIGN_CENTER
);
173 rSet
.DisableItem( SID_OBJECT_ALIGN_RIGHT
);
174 rSet
.DisableItem( SID_OBJECT_ALIGN_UP
);
175 rSet
.DisableItem( SID_OBJECT_ALIGN_MIDDLE
);
176 rSet
.DisableItem( SID_OBJECT_ALIGN_DOWN
);
177 rSet
.DisableItem( SID_OBJECT_ALIGN
);
179 // pseudo slots for Format menu
180 rSet
.DisableItem( SID_ALIGN_ANY_LEFT
);
181 rSet
.DisableItem( SID_ALIGN_ANY_HCENTER
);
182 rSet
.DisableItem( SID_ALIGN_ANY_RIGHT
);
183 rSet
.DisableItem( SID_ALIGN_ANY_TOP
);
184 rSet
.DisableItem( SID_ALIGN_ANY_VCENTER
);
185 rSet
.DisableItem( SID_ALIGN_ANY_BOTTOM
);
188 // do not change layer of form controls
189 // #i83729# do not change layer of cell notes (on internal layer)
190 if ( !nMarkCount
|| pView
->HasMarkedControl() || pView
->HasMarkedInternal() )
192 rSet
.DisableItem( SID_OBJECT_HEAVEN
);
193 rSet
.DisableItem( SID_OBJECT_HELL
);
197 if(AreAllObjectsOnLayer(SC_LAYER_FRONT
,rMarkList
))
199 rSet
.DisableItem( SID_OBJECT_HEAVEN
);
201 else if(AreAllObjectsOnLayer(SC_LAYER_BACK
,rMarkList
))
203 rSet
.DisableItem( SID_OBJECT_HELL
);
207 bool bCanRename
= false;
208 if ( nMarkCount
> 1 )
210 // no hypelink options for a selected group
211 rSet
.DisableItem( SID_DRAW_HLINK_EDIT
);
212 rSet
.DisableItem( SID_DRAW_HLINK_DELETE
);
213 rSet
.DisableItem( SID_OPEN_HYPERLINK
);
214 // Fit to cell only works with a single graphic
215 rSet
.DisableItem( SID_FITCELLSIZE
);
217 else if ( nMarkCount
== 1 )
219 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
220 ScMacroInfo
* pInfo
= ScDrawLayer::GetMacroInfo( pObj
);
221 if ( !pInfo
|| pInfo
->GetHlink().isEmpty() )
223 rSet
.DisableItem( SID_DRAW_HLINK_DELETE
);
224 rSet
.DisableItem( SID_OPEN_HYPERLINK
);
226 SdrLayerID nLayerID
= pObj
->GetLayer();
227 if ( nLayerID
!= SC_LAYER_INTERN
)
228 bCanRename
= true; // #i51351# anything except internal objects can be renamed
230 // #91929#; don't show original size entry if not possible
231 sal_uInt16 nObjType
= pObj
->GetObjIdentifier();
232 if ( nObjType
== OBJ_OLE2
)
234 SdrOle2Obj
* pOleObj
= static_cast<SdrOle2Obj
*>(rMarkList
.GetMark( 0 )->GetMarkedSdrObj());
235 if (pOleObj
->GetObjRef().is() &&
236 (pOleObj
->GetObjRef()->getStatus( pOleObj
->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE
) )
237 //TODO/LATER: why different slots in Draw and Calc?
238 rSet
.DisableItem(SID_ORIGINALSIZE
);
240 else if ( nObjType
== OBJ_CAPTION
)
242 if ( nLayerID
== SC_LAYER_INTERN
)
244 // SdrCaptionObj() Notes cannot be cut/copy in isolation from
246 rSet
.DisableItem( SID_CUT
);
247 rSet
.DisableItem( SID_COPY
);
248 // Notes always default to Page anchor.
249 rSet
.DisableItem( SID_ANCHOR_TOGGLE
);
250 rSet
.DisableItem( SID_ANCHOR_MENU
);
254 // Fit to cell is only available for cell anchored graphics obviously
255 if (pView
->GetAnchorType() != SCA_CELL
&&
256 pView
->GetAnchorType() != SCA_CELL_RESIZE
)
257 rSet
.DisableItem( SID_FITCELLSIZE
);
262 rSet
.DisableItem( SID_RENAME_OBJECT
);
263 rSet
.DisableItem( SID_TITLE_DESCRIPTION_OBJECT
);
266 if ( !nMarkCount
) // nothing selected
269 rSet
.DisableItem( SID_FRAME_UP
);
270 rSet
.DisableItem( SID_FRAME_DOWN
);
271 rSet
.DisableItem( SID_FRAME_TO_TOP
);
272 rSet
.DisableItem( SID_FRAME_TO_BOTTOM
);
273 // Clipboard / delete
274 rSet
.DisableItem( SID_DELETE
);
275 rSet
.DisableItem( SID_DELETE_CONTENTS
);
276 rSet
.DisableItem( SID_CUT
);
277 rSet
.DisableItem( SID_COPY
);
279 rSet
.DisableItem( SID_ANCHOR_TOGGLE
);
280 rSet
.DisableItem( SID_ANCHOR_MENU
);
281 rSet
.DisableItem( SID_ORIGINALSIZE
);
282 rSet
.DisableItem( SID_FITCELLSIZE
);
283 rSet
.DisableItem( SID_ATTR_TRANSFORM
);
286 if ( rSet
.GetItemState( SID_ENABLE_HYPHENATION
) != SfxItemState::UNKNOWN
)
288 SfxItemSet
aAttrs( pView
->GetModel()->GetItemPool() );
289 pView
->GetAttributes( aAttrs
);
290 if( aAttrs
.GetItemState( EE_PARA_HYPHENATE
) >= SfxItemState::DEFAULT
)
292 bool bValue
= aAttrs
.Get( EE_PARA_HYPHENATE
).GetValue();
293 rSet
.Put( SfxBoolItem( SID_ENABLE_HYPHENATION
, bValue
) );
297 svx::ExtrusionBar::getState( pView
, rSet
);
298 svx::FontworkBar::getState( pView
, rSet
);
301 // Attributes for Drawing-Objects
303 void ScDrawShell::GetDrawAttrState( SfxItemSet
& rSet
)
305 Point aMousePos
= pViewData
->GetMousePosPixel();
306 vcl::Window
* pWindow
= pViewData
->GetActiveWin();
307 ScDrawView
* pDrView
= pViewData
->GetScDrawView();
308 Point aPos
= pWindow
->PixelToLogic(aMousePos
);
309 bool bHasMarked
= pDrView
->AreObjectsMarked();
313 rSet
.Put( pDrView
->GetAttrFromMarked(false), false );
317 rSet
.Put( pDrView
->GetDefaultAttr() );
320 SdrPageView
* pPV
= pDrView
->GetSdrPageView();
323 // #i52073# when a sheet with an active OLE object is deleted,
324 // the slot state is queried without an active page view
326 // Items for position and size (see ScGridWindow::UpdateStatusPosSize, #108137#)
328 // #i34458# The SvxSizeItem in SID_TABLE_CELL is no longer needed by
329 // SvxPosSizeStatusBarControl, it's enough to have it in SID_ATTR_SIZE.
331 bool bActionItem
= false;
332 if ( pDrView
->IsAction() ) // action rectangle
334 tools::Rectangle aRect
;
335 pDrView
->TakeActionRect( aRect
);
336 if ( !aRect
.IsEmpty() )
338 pPV
->LogicToPagePos(aRect
);
339 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aRect
.TopLeft() ) );
340 Size
aSize( aRect
.Right() - aRect
.Left(), aRect
.Bottom() - aRect
.Top() );
341 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, aSize
) );
347 if ( pDrView
->AreObjectsMarked() ) // selected objects
349 tools::Rectangle aRect
= pDrView
->GetAllMarkedRect();
350 pPV
->LogicToPagePos(aRect
);
351 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aRect
.TopLeft() ) );
352 Size
aSize( aRect
.Right() - aRect
.Left(), aRect
.Bottom() - aRect
.Top() );
353 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, aSize
) );
355 else // mouse position
357 // aPos is initialized above
358 pPV
->LogicToPagePos(aPos
);
359 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aPos
) );
360 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, Size( 0, 0 ) ) );
366 void ScDrawShell::GetAttrFuncState(SfxItemSet
&rSet
)
368 // Disable dialogs for Draw-attributes if necessary
370 ScDrawView
* pDrView
= pViewData
->GetScDrawView();
371 SfxItemSet aViewSet
= pDrView
->GetAttrFromMarked(false);
372 const SdrMarkList
& rMarkList
= pDrView
->GetMarkedObjectList();
373 const size_t nMarkCount
= rMarkList
.GetMarkCount();
374 bool bShowArea
= true, bShowMeasure
= true;
376 for ( size_t i
= 0; i
< nMarkCount
&& i
< 50; ++i
)
378 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
379 sal_uInt16 nObjType
= pObj
->GetObjIdentifier();
381 if ( nObjType
!= OBJ_MEASURE
)
382 bShowMeasure
= false;
384 // If marked object is 2D, disable format area command.
385 if ( nObjType
== OBJ_PLIN
||
386 nObjType
== OBJ_LINE
||
387 nObjType
== OBJ_PATHLINE
||
388 nObjType
== OBJ_FREELINE
||
389 nObjType
== OBJ_EDGE
||
390 nObjType
== OBJ_CARC
||
394 if ( !bShowArea
&& !bShowMeasure
)
399 rSet
.DisableItem( SID_ATTRIBUTES_AREA
);
402 rSet
.DisableItem( SID_MEASURE_DLG
);
404 if ( aViewSet
.GetItemState( XATTR_LINESTYLE
) == SfxItemState::DEFAULT
)
406 rSet
.DisableItem( SID_ATTRIBUTES_LINE
);
407 rSet
.DisableItem( SID_ATTR_LINEEND_STYLE
); // Tbx-Controller
410 if ( aViewSet
.GetItemState( XATTR_FILLSTYLE
) == SfxItemState::DEFAULT
)
411 rSet
.DisableItem( SID_ATTRIBUTES_AREA
);
414 bool ScDrawShell::AreAllObjectsOnLayer(SdrLayerID nLayerNo
,const SdrMarkList
& rMark
)
417 const size_t nCount
= rMark
.GetMarkCount();
418 for (size_t i
=0; i
<nCount
; ++i
)
420 SdrObject
* pObj
= rMark
.GetMark(i
)->GetMarkedSdrObj();
421 if ( dynamic_cast<const SdrUnoObj
*>( pObj
) == nullptr )
423 if(nLayerNo
!=pObj
->GetLayer())
433 void ScDrawShell::GetDrawAttrStateForIFBX( SfxItemSet
& rSet
)
435 ScDrawView
* pView
= pViewData
->GetScDrawView();
436 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
438 if( rMarkList
.GetMark(0) != nullptr )
440 SfxItemSet
aNewAttr(pView
->GetGeoAttrFromMarked());
441 rSet
.Put(aNewAttr
, false);
445 void ScDrawShell::Activate (const bool)
447 ContextChangeEventMultiplexer::NotifyContextChange(
448 GetFrame()->GetFrame().GetController(),
449 vcl::EnumContext::GetContextEnum(
450 GetSidebarContextName()));
453 const OUString
& ScDrawShell::GetSidebarContextName()
455 return vcl::EnumContext::GetContextName(
456 svx::sidebar::SelectionAnalyzer::GetContextForSelection_SC(
457 GetDrawView()->GetMarkedObjectList()));
460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */