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>
37 #include <svx/unomid.hxx>
40 #include <drawview.hxx>
41 #include <viewdata.hxx>
43 #include <tabvwsh.hxx>
44 #include <document.hxx>
45 #include <drwlayer.hxx>
46 #include <userdat.hxx>
47 #include <drtxtob.hxx>
48 #include <gridwin.hxx>
49 #include <svx/svdoole2.hxx>
50 #include <svx/xflgrit.hxx>
51 #include <comphelper/lok.hxx>
52 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
54 #include <svx/xflclit.hxx>
55 #include <com/sun/star/chart2/XChartDocument.hpp>
56 #include <sfx2/ipclient.hxx>
58 using namespace com::sun::star::drawing
;
59 using namespace com::sun::star
;
62 ScDrawShell::ScDrawShell( ScViewData
& rData
) :
63 SfxShell(rData
.GetViewShell()),
65 mpSelectionChangeHandler(new svx::sidebar::SelectionChangeHandler(
66 [this] () { return this->GetSidebarContextName(); },
67 GetFrame()->GetFrame().GetController(),
68 vcl::EnumContext::Context::Cell
))
70 SetPool( &rViewData
.GetScDrawView()->GetModel()->GetItemPool() );
71 SfxUndoManager
* pMgr
= rViewData
.GetSfxDocShell()->GetUndoManager();
72 SetUndoManager( pMgr
);
73 if ( !rViewData
.GetDocument().IsUndoEnabled() )
75 pMgr
->SetMaxUndoActionCount( 0 );
79 mpSelectionChangeHandler
->Connect();
82 ScDrawShell::~ScDrawShell()
84 mpSelectionChangeHandler
->Disconnect();
87 void ScDrawShell::GetState( SfxItemSet
& rSet
) // Conditions / Toggles
89 ScDrawView
* pView
= rViewData
.GetScDrawView();
90 SdrDragMode eMode
= pView
->GetDragMode();
92 rSet
.Put( SfxBoolItem( SID_OBJECT_ROTATE
, eMode
== SdrDragMode::Rotate
) );
93 rSet
.Put( SfxBoolItem( SID_OBJECT_MIRROR
, eMode
== SdrDragMode::Mirror
) );
94 rSet
.Put( SfxBoolItem( SID_BEZIER_EDIT
, !pView
->IsFrameDragSingles() ) );
96 sal_uInt16 nFWId
= ScGetFontWorkId();
97 SfxViewFrame
* pViewFrm
= rViewData
.GetViewShell()->GetViewFrame();
98 rSet
.Put(SfxBoolItem(SID_FONTWORK
, pViewFrm
->HasChildWindow(nFWId
)));
100 // Notes always default to Page anchor.
101 bool bDisableAnchor
= false;
102 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
103 if ( rMarkList
.GetMarkCount() == 1 )
105 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
106 if( ScDrawLayer::IsNoteCaption( pObj
) )
108 bDisableAnchor
= true;
109 rSet
.DisableItem( SID_ANCHOR_PAGE
);
110 rSet
.DisableItem( SID_ANCHOR_CELL
);
111 rSet
.DisableItem( SID_ANCHOR_CELL_RESIZE
);
115 if ( bDisableAnchor
)
118 switch( pView
->GetAnchorType() )
121 rSet
.Put( SfxBoolItem( SID_ANCHOR_PAGE
, true ) );
122 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL
, false ) );
123 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE
, false ) );
127 rSet
.Put( SfxBoolItem( SID_ANCHOR_PAGE
, false ) );
128 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL
, true ) );
129 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE
, false ) );
132 case SCA_CELL_RESIZE
:
133 rSet
.Put( SfxBoolItem( SID_ANCHOR_PAGE
, false ) );
134 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL
, false ) );
135 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE
, true ) );
139 rSet
.Put( SfxBoolItem( SID_ANCHOR_PAGE
, false ) );
140 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL
, false ) );
141 rSet
.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE
, false ) );
146 void ScDrawShell::GetDrawFuncState( SfxItemSet
& rSet
) // disable functions
148 ScDrawView
* pView
= rViewData
.GetScDrawView();
150 // call IsMirrorAllowed first to make sure ForcePossibilities (and thus CheckMarked)
151 // is called before GetMarkCount, so the nMarkCount value is valid for the rest of this method.
152 if (!pView
->IsMirrorAllowed(true,true))
154 rSet
.DisableItem( SID_MIRROR_HORIZONTAL
);
155 rSet
.DisableItem( SID_MIRROR_VERTICAL
);
156 rSet
.DisableItem( SID_FLIP_HORIZONTAL
);
157 rSet
.DisableItem( SID_FLIP_VERTICAL
);
161 if (GetObjectShell()->isContentExtractionLocked())
163 rSet
.DisableItem(SID_COPY
);
164 rSet
.DisableItem(SID_CUT
);
167 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
168 const size_t nMarkCount
= rMarkList
.GetMarkCount();
170 if ( nMarkCount
<= 1 || !pView
->IsGroupPossible() )
171 rSet
.DisableItem( SID_GROUP
);
172 if ( nMarkCount
== 0 || !pView
->IsUnGroupPossible() )
173 rSet
.DisableItem( SID_UNGROUP
);
174 if ( nMarkCount
!= 1 || !pView
->IsGroupEnterPossible() )
175 rSet
.DisableItem( SID_ENTER_GROUP
);
176 if ( !pView
->IsGroupEntered() )
177 rSet
.DisableItem( SID_LEAVE_GROUP
);
179 if ( nMarkCount
<= 1 ) // Nothing or only one object selected
182 rSet
.DisableItem( SID_OBJECT_ALIGN_LEFT
); // no alignment on the side
183 rSet
.DisableItem( SID_OBJECT_ALIGN_CENTER
);
184 rSet
.DisableItem( SID_OBJECT_ALIGN_RIGHT
);
185 rSet
.DisableItem( SID_OBJECT_ALIGN_UP
);
186 rSet
.DisableItem( SID_OBJECT_ALIGN_MIDDLE
);
187 rSet
.DisableItem( SID_OBJECT_ALIGN_DOWN
);
188 rSet
.DisableItem( SID_OBJECT_ALIGN
);
190 // pseudo slots for Format menu
191 rSet
.DisableItem( SID_ALIGN_ANY_LEFT
);
192 rSet
.DisableItem( SID_ALIGN_ANY_HCENTER
);
193 rSet
.DisableItem( SID_ALIGN_ANY_RIGHT
);
194 rSet
.DisableItem( SID_ALIGN_ANY_TOP
);
195 rSet
.DisableItem( SID_ALIGN_ANY_VCENTER
);
196 rSet
.DisableItem( SID_ALIGN_ANY_BOTTOM
);
199 // do not change layer of form controls
200 // #i83729# do not change layer of cell notes (on internal layer)
201 if ( !nMarkCount
|| pView
->HasMarkedControl() || pView
->HasMarkedInternal() )
203 rSet
.DisableItem( SID_OBJECT_HEAVEN
);
204 rSet
.DisableItem( SID_OBJECT_HELL
);
208 if(AreAllObjectsOnLayer(SC_LAYER_FRONT
,rMarkList
))
210 rSet
.DisableItem( SID_OBJECT_HEAVEN
);
212 else if(AreAllObjectsOnLayer(SC_LAYER_BACK
,rMarkList
))
214 rSet
.DisableItem( SID_OBJECT_HELL
);
218 bool bCanRename
= false;
219 if ( nMarkCount
> 1 )
221 // no hypelink options for a selected group
222 rSet
.DisableItem( SID_DRAW_HLINK_EDIT
);
223 rSet
.DisableItem( SID_DRAW_HLINK_DELETE
);
224 rSet
.DisableItem( SID_OPEN_HYPERLINK
);
225 // Fit to cell only works with a single graphic
226 rSet
.DisableItem( SID_FITCELLSIZE
);
228 else if ( nMarkCount
== 1 )
230 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
231 ScMacroInfo
* pInfo
= ScDrawLayer::GetMacroInfo( pObj
);
232 if ( !pInfo
|| pInfo
->GetHlink().isEmpty() )
234 rSet
.DisableItem( SID_DRAW_HLINK_DELETE
);
235 rSet
.DisableItem( SID_OPEN_HYPERLINK
);
237 SdrLayerID nLayerID
= pObj
->GetLayer();
238 if ( nLayerID
!= SC_LAYER_INTERN
)
239 bCanRename
= true; // #i51351# anything except internal objects can be renamed
241 // #91929#; don't show original size entry if not possible
242 sal_uInt16 nObjType
= pObj
->GetObjIdentifier();
243 if ( nObjType
== OBJ_OLE2
)
245 SdrOle2Obj
* pOleObj
= static_cast<SdrOle2Obj
*>(rMarkList
.GetMark( 0 )->GetMarkedSdrObj());
246 if (pOleObj
->GetObjRef().is() &&
247 (pOleObj
->GetObjRef()->getStatus( pOleObj
->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE
) )
248 //TODO/LATER: why different slots in Draw and Calc?
249 rSet
.DisableItem(SID_ORIGINALSIZE
);
251 else if ( nObjType
== OBJ_CAPTION
)
253 if ( nLayerID
== SC_LAYER_INTERN
)
255 // SdrCaptionObj() Notes cannot be cut/copy in isolation from
257 rSet
.DisableItem( SID_CUT
);
258 rSet
.DisableItem( SID_COPY
);
259 // Notes always default to Page anchor.
260 rSet
.DisableItem( SID_ANCHOR_TOGGLE
);
261 rSet
.DisableItem( SID_ANCHOR_MENU
);
265 // Fit to cell is only available for cell anchored graphics obviously
266 if (pView
->GetAnchorType() != SCA_CELL
&&
267 pView
->GetAnchorType() != SCA_CELL_RESIZE
)
268 rSet
.DisableItem( SID_FITCELLSIZE
);
273 rSet
.DisableItem( SID_RENAME_OBJECT
);
274 rSet
.DisableItem( SID_TITLE_DESCRIPTION_OBJECT
);
277 if ( !nMarkCount
) // nothing selected
280 rSet
.DisableItem( SID_FRAME_UP
);
281 rSet
.DisableItem( SID_FRAME_DOWN
);
282 rSet
.DisableItem( SID_FRAME_TO_TOP
);
283 rSet
.DisableItem( SID_FRAME_TO_BOTTOM
);
284 // Clipboard / delete
285 rSet
.DisableItem( SID_DELETE
);
286 rSet
.DisableItem( SID_DELETE_CONTENTS
);
287 rSet
.DisableItem( SID_CUT
);
288 rSet
.DisableItem( SID_COPY
);
290 rSet
.DisableItem( SID_ANCHOR_TOGGLE
);
291 rSet
.DisableItem( SID_ANCHOR_MENU
);
292 rSet
.DisableItem( SID_ORIGINALSIZE
);
293 rSet
.DisableItem( SID_FITCELLSIZE
);
294 rSet
.DisableItem( SID_ATTR_TRANSFORM
);
297 if ( rSet
.GetItemState( SID_ENABLE_HYPHENATION
) != SfxItemState::UNKNOWN
)
299 SfxItemSet
aAttrs( pView
->GetModel()->GetItemPool() );
300 pView
->GetAttributes( aAttrs
);
301 if( aAttrs
.GetItemState( EE_PARA_HYPHENATE
) >= SfxItemState::DEFAULT
)
303 bool bValue
= aAttrs
.Get( EE_PARA_HYPHENATE
).GetValue();
304 rSet
.Put( SfxBoolItem( SID_ENABLE_HYPHENATION
, bValue
) );
308 svx::ExtrusionBar::getState( pView
, rSet
);
309 svx::FontworkBar::getState( pView
, rSet
);
312 static void setupFillColorForChart(SfxViewShell
* pShell
, SfxItemSet
& rSet
)
317 SfxInPlaceClient
* pIPClient
= pShell
->GetIPClient();
321 const css::uno::Reference
<::css::embed::XEmbeddedObject
>& xEmbObj
= pIPClient
->GetObject();
325 ::css::uno::Reference
<::css::chart2::XChartDocument
> xChart( xEmbObj
->getComponent(), uno::UNO_QUERY
);
329 css::uno::Reference
<css::beans::XPropertySet
> xPropSet
= xChart
->getPageBackground();
333 css::uno::Reference
<css::beans::XPropertySetInfo
> xInfo(xPropSet
->getPropertySetInfo());
337 if (xInfo
->hasPropertyByName("FillColor"))
339 sal_uInt32 nFillColor
= 0;
340 xPropSet
->getPropertyValue("FillColor") >>= nFillColor
;
342 XFillColorItem
aFillColorItem("", Color(ColorTransparency
, nFillColor
));
343 rSet
.Put(aFillColorItem
);
345 if (comphelper::LibreOfficeKit::isActive())
346 pShell
->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED
,
347 (".uno:FillColor=" + std::to_string(nFillColor
)).c_str());
350 if (!(comphelper::LibreOfficeKit::isActive() && xInfo
->hasPropertyByName("FillGradientName")))
353 OUString aGradientName
;
354 xPropSet
->getPropertyValue("FillGradientName") >>= aGradientName
;
356 ::css::uno::Reference
< ::css::frame::XController
> xChartController
= xChart
->getCurrentController();
357 if( !xChartController
.is() )
360 css::uno::Reference
<css::lang::XMultiServiceFactory
> xFact(xChartController
->getModel(), css::uno::UNO_QUERY
);
365 css::uno::Reference
<css::container::XNameAccess
> xNameAccess(
366 xFact
->createInstance("com.sun.star.drawing.GradientTable"), css::uno::UNO_QUERY
);
368 if (xNameAccess
.is() && xNameAccess
->hasByName(aGradientName
))
370 css::uno::Any aAny
= xNameAccess
->getByName(aGradientName
);
372 XFillGradientItem aItem
;
373 aItem
.SetName(aGradientName
);
374 aItem
.PutValue(aAny
, MID_FILLGRADIENT
);
380 // Attributes for Drawing-Objects
382 void ScDrawShell::GetDrawAttrState( SfxItemSet
& rSet
)
384 Point aMousePos
= rViewData
.GetMousePosPixel();
385 vcl::Window
* pWindow
= rViewData
.GetActiveWin();
386 ScDrawView
* pDrView
= rViewData
.GetScDrawView();
387 Point aPos
= pWindow
->PixelToLogic(aMousePos
);
388 bool bHasMarked
= pDrView
->AreObjectsMarked();
392 SfxAllItemSet
aSet(pDrView
->GetAttrFromMarked(false));
393 if (const SfxPoolItem
* pItem
= nullptr;
394 aSet
.GetItemState(SDRATTR_TEXTCOLUMNS_NUMBER
, false, &pItem
) >= SfxItemState::DEFAULT
397 aSet
.Put(pItem
->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_NUMBER
));
399 if (const SfxPoolItem
* pItem
= nullptr;
400 aSet
.GetItemState(SDRATTR_TEXTCOLUMNS_SPACING
, false, &pItem
) >= SfxItemState::DEFAULT
403 aSet
.Put(pItem
->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_SPACING
));
405 rSet
.Put(aSet
, false);
409 rSet
.Put( pDrView
->GetDefaultAttr() );
412 SdrPageView
* pPV
= pDrView
->GetSdrPageView();
416 // #i52073# when a sheet with an active OLE object is deleted,
417 // the slot state is queried without an active page view
419 // Items for position and size (see ScGridWindow::UpdateStatusPosSize, #108137#)
421 // #i34458# The SvxSizeItem in SID_TABLE_CELL is no longer needed by
422 // SvxPosSizeStatusBarControl, it's enough to have it in SID_ATTR_SIZE.
424 bool bActionItem
= false;
425 if ( pDrView
->IsAction() ) // action rectangle
427 tools::Rectangle aRect
;
428 pDrView
->TakeActionRect( aRect
);
429 if ( !aRect
.IsEmpty() )
431 pPV
->LogicToPagePos(aRect
);
432 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aRect
.TopLeft() ) );
433 Size
aSize( aRect
.Right() - aRect
.Left(), aRect
.Bottom() - aRect
.Top() );
434 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, aSize
) );
438 // Set correct colors for charts in sidebar
439 setupFillColorForChart(pDrView
->GetSfxViewShell(), rSet
);
444 if ( pDrView
->AreObjectsMarked() ) // selected objects
446 tools::Rectangle aRect
= pDrView
->GetAllMarkedRect();
447 pPV
->LogicToPagePos(aRect
);
448 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aRect
.TopLeft() ) );
449 Size
aSize( aRect
.Right() - aRect
.Left(), aRect
.Bottom() - aRect
.Top() );
450 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, aSize
) );
452 else // mouse position
454 // aPos is initialized above
455 pPV
->LogicToPagePos(aPos
);
456 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aPos
) );
457 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, Size( 0, 0 ) ) );
461 void ScDrawShell::GetAttrFuncState(SfxItemSet
&rSet
)
463 // Disable dialogs for Draw-attributes if necessary
465 ScDrawView
* pDrView
= rViewData
.GetScDrawView();
466 SfxItemSet aViewSet
= pDrView
->GetAttrFromMarked(false);
467 const SdrMarkList
& rMarkList
= pDrView
->GetMarkedObjectList();
468 const size_t nMarkCount
= rMarkList
.GetMarkCount();
469 bool bShowArea
= true, bShowMeasure
= true;
471 for ( size_t i
= 0; i
< nMarkCount
&& i
< 50; ++i
)
473 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
474 sal_uInt16 nObjType
= pObj
->GetObjIdentifier();
476 if ( nObjType
!= OBJ_MEASURE
)
477 bShowMeasure
= false;
479 // If marked object is 2D, disable format area command.
480 if ( nObjType
== OBJ_PLIN
||
481 nObjType
== OBJ_LINE
||
482 nObjType
== OBJ_PATHLINE
||
483 nObjType
== OBJ_FREELINE
||
484 nObjType
== OBJ_EDGE
||
485 nObjType
== OBJ_CARC
||
489 if ( !bShowArea
&& !bShowMeasure
)
494 rSet
.DisableItem( SID_ATTRIBUTES_AREA
);
497 rSet
.DisableItem( SID_MEASURE_DLG
);
499 if ( aViewSet
.GetItemState( XATTR_LINESTYLE
) == SfxItemState::DEFAULT
)
501 rSet
.DisableItem( SID_ATTRIBUTES_LINE
);
502 rSet
.DisableItem( SID_ATTR_LINEEND_STYLE
); // Tbx-Controller
505 if ( aViewSet
.GetItemState( XATTR_FILLSTYLE
) == SfxItemState::DEFAULT
)
506 rSet
.DisableItem( SID_ATTRIBUTES_AREA
);
509 bool ScDrawShell::AreAllObjectsOnLayer(SdrLayerID nLayerNo
,const SdrMarkList
& rMark
)
512 const size_t nCount
= rMark
.GetMarkCount();
513 for (size_t i
=0; i
<nCount
; ++i
)
515 SdrObject
* pObj
= rMark
.GetMark(i
)->GetMarkedSdrObj();
516 if ( dynamic_cast<const SdrUnoObj
*>( pObj
) == nullptr )
518 if(nLayerNo
!=pObj
->GetLayer())
528 void ScDrawShell::GetDrawAttrStateForIFBX( SfxItemSet
& rSet
)
530 ScDrawView
* pView
= rViewData
.GetScDrawView();
531 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
533 if( rMarkList
.GetMark(0) != nullptr )
535 SfxItemSet
aNewAttr(pView
->GetGeoAttrFromMarked());
536 rSet
.Put(aNewAttr
, false);
540 void ScDrawShell::Activate (const bool)
542 ContextChangeEventMultiplexer::NotifyContextChange(
543 GetFrame()->GetFrame().GetController(),
544 vcl::EnumContext::GetContextEnum(
545 GetSidebarContextName()));
548 const OUString
& ScDrawShell::GetSidebarContextName()
550 return vcl::EnumContext::GetContextName(
551 svx::sidebar::SelectionAnalyzer::GetContextForSelection_SC(
552 GetDrawView()->GetMarkedObjectList()));
555 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */