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 <drtxtob.hxx>
47 #include <gridwin.hxx>
48 #include <svx/svdoole2.hxx>
49 #include <svx/xflgrit.hxx>
50 #include <comphelper/lok.hxx>
51 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
53 #include <svx/xflclit.hxx>
54 #include <com/sun/star/chart2/XChartDocument.hpp>
55 #include <sfx2/ipclient.hxx>
57 using namespace com::sun::star
;
60 ScDrawShell::ScDrawShell( ScViewData
& rData
) :
61 SfxShell(rData
.GetViewShell()),
64 SfxViewFrame
* pFrame
= GetFrame();
66 mpSelectionChangeHandler
= new svx::sidebar::SelectionChangeHandler(
67 [this] () { return this->GetSidebarContextName(); },
68 pFrame
->GetFrame().GetController(),
69 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 );
77 SetName(u
"Drawing"_ustr
);
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
& rViewFrm
= rViewData
.GetViewShell()->GetViewFrame();
98 rSet
.Put(SfxBoolItem(SID_FONTWORK
, rViewFrm
.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 hyperlink options for a selected group
222 rSet
.DisableItem( SID_EDIT_HYPERLINK
);
223 rSet
.DisableItem( SID_REMOVE_HYPERLINK
);
224 rSet
.DisableItem( SID_OPEN_HYPERLINK
);
225 rSet
.DisableItem( SID_COPY_HYPERLINK_LOCATION
);
226 // Fit to cell only works with a single graphic
227 rSet
.DisableItem( SID_FITCELLSIZE
);
229 else if ( nMarkCount
== 1 )
231 SdrObject
* pObj
= rMarkList
.GetMark( 0 )->GetMarkedSdrObj();
232 if (pObj
->getHyperlink().isEmpty())
234 rSet
.DisableItem( SID_EDIT_HYPERLINK
);
235 rSet
.DisableItem( SID_OPEN_HYPERLINK
);
236 rSet
.DisableItem( SID_REMOVE_HYPERLINK
);
237 rSet
.DisableItem( SID_COPY_HYPERLINK_LOCATION
);
239 SdrLayerID nLayerID
= pObj
->GetLayer();
240 if ( nLayerID
!= SC_LAYER_INTERN
)
241 bCanRename
= true; // #i51351# anything except internal objects can be renamed
243 // #91929#; don't show original size entry if not possible
244 SdrObjKind nObjType
= pObj
->GetObjIdentifier();
245 if ( nObjType
== SdrObjKind::OLE2
)
247 SdrOle2Obj
* pOleObj
= static_cast<SdrOle2Obj
*>(rMarkList
.GetMark( 0 )->GetMarkedSdrObj());
248 if (pOleObj
->GetObjRef().is() &&
249 (pOleObj
->GetObjRef()->getStatus( pOleObj
->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE
) )
250 //TODO/LATER: why different slots in Draw and Calc?
251 rSet
.DisableItem(SID_ORIGINALSIZE
);
253 else if ( nObjType
== SdrObjKind::Caption
)
255 if ( nLayerID
== SC_LAYER_INTERN
)
257 // SdrCaptionObj() Notes cannot be cut/copy in isolation from
259 rSet
.DisableItem( SID_CUT
);
260 rSet
.DisableItem( SID_COPY
);
261 // Notes always default to Page anchor.
262 rSet
.DisableItem( SID_ANCHOR_TOGGLE
);
263 rSet
.DisableItem( SID_ANCHOR_MENU
);
267 // Fit to cell is only available for cell anchored graphics obviously
268 if (pView
->GetAnchorType() != SCA_CELL
&&
269 pView
->GetAnchorType() != SCA_CELL_RESIZE
)
270 rSet
.DisableItem( SID_FITCELLSIZE
);
272 // Support advanced DiagramHelper
273 if (!pObj
->isDiagram())
275 rSet
.DisableItem( SID_REGENERATE_DIAGRAM
);
276 rSet
.DisableItem( SID_EDIT_DIAGRAM
);
282 rSet
.DisableItem( SID_RENAME_OBJECT
);
283 rSet
.DisableItem( SID_TITLE_DESCRIPTION_OBJECT
);
286 if ( !nMarkCount
) // nothing selected
289 rSet
.DisableItem( SID_FRAME_UP
);
290 rSet
.DisableItem( SID_FRAME_DOWN
);
291 rSet
.DisableItem( SID_FRAME_TO_TOP
);
292 rSet
.DisableItem( SID_FRAME_TO_BOTTOM
);
293 // Clipboard / delete
294 rSet
.DisableItem( SID_DELETE
);
295 rSet
.DisableItem( SID_DELETE_CONTENTS
);
296 rSet
.DisableItem( SID_CUT
);
297 rSet
.DisableItem( SID_COPY
);
299 rSet
.DisableItem( SID_ANCHOR_TOGGLE
);
300 rSet
.DisableItem( SID_ANCHOR_MENU
);
301 rSet
.DisableItem( SID_ORIGINALSIZE
);
302 rSet
.DisableItem( SID_FITCELLSIZE
);
303 rSet
.DisableItem( SID_ATTR_TRANSFORM
);
306 if ( rSet
.GetItemState( SID_ENABLE_HYPHENATION
) != SfxItemState::UNKNOWN
)
308 SfxItemSet
aAttrs( pView
->GetModel().GetItemPool() );
309 pView
->GetAttributes( aAttrs
);
310 if( aAttrs
.GetItemState( EE_PARA_HYPHENATE
) >= SfxItemState::DEFAULT
)
312 bool bValue
= aAttrs
.Get( EE_PARA_HYPHENATE
).GetValue();
313 rSet
.Put( SfxBoolItem( SID_ENABLE_HYPHENATION
, bValue
) );
317 svx::ExtrusionBar::getState( pView
, rSet
);
318 svx::FontworkBar::getState( pView
, rSet
);
321 static void setupFillColorForChart(const SfxViewShell
* pShell
, SfxItemSet
& rSet
)
326 SfxInPlaceClient
* pIPClient
= pShell
->GetIPClient();
330 const css::uno::Reference
<::css::embed::XEmbeddedObject
>& xEmbObj
= pIPClient
->GetObject();
334 ::css::uno::Reference
<::css::chart2::XChartDocument
> xChart( xEmbObj
->getComponent(), uno::UNO_QUERY
);
338 css::uno::Reference
<css::beans::XPropertySet
> xPropSet
= xChart
->getPageBackground();
342 css::uno::Reference
<css::beans::XPropertySetInfo
> xInfo(xPropSet
->getPropertySetInfo());
346 if (xInfo
->hasPropertyByName(u
"FillColor"_ustr
))
348 sal_uInt32 nFillColor
= 0;
349 xPropSet
->getPropertyValue(u
"FillColor"_ustr
) >>= nFillColor
;
351 XFillColorItem
aFillColorItem(u
""_ustr
, Color(ColorTransparency
, nFillColor
));
352 rSet
.Put(aFillColorItem
);
354 if (comphelper::LibreOfficeKit::isActive())
355 pShell
->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED
,
356 (".uno:FillColor=" + OString::number(nFillColor
)));
359 if (!(comphelper::LibreOfficeKit::isActive() && xInfo
->hasPropertyByName(u
"FillGradientName"_ustr
)))
362 OUString aGradientName
;
363 xPropSet
->getPropertyValue(u
"FillGradientName"_ustr
) >>= aGradientName
;
365 ::css::uno::Reference
< ::css::frame::XController
> xChartController
= xChart
->getCurrentController();
366 if( !xChartController
.is() )
369 css::uno::Reference
<css::lang::XMultiServiceFactory
> xFact(xChartController
->getModel(), css::uno::UNO_QUERY
);
374 css::uno::Reference
<css::container::XNameAccess
> xNameAccess(
375 xFact
->createInstance(u
"com.sun.star.drawing.GradientTable"_ustr
), css::uno::UNO_QUERY
);
377 if (xNameAccess
.is() && xNameAccess
->hasByName(aGradientName
))
379 css::uno::Any aAny
= xNameAccess
->getByName(aGradientName
);
381 XFillGradientItem aItem
;
382 aItem
.SetName(aGradientName
);
383 aItem
.PutValue(aAny
, MID_FILLGRADIENT
);
389 // Attributes for Drawing-Objects
391 void ScDrawShell::GetDrawAttrState( SfxItemSet
& rSet
)
393 Point aMousePos
= rViewData
.GetMousePosPixel();
394 vcl::Window
* pWindow
= rViewData
.GetActiveWin();
395 ScDrawView
* pDrView
= rViewData
.GetScDrawView();
396 Point aPos
= pWindow
->PixelToLogic(aMousePos
);
397 const SdrMarkList
& rMarkList
= pDrView
->GetMarkedObjectList();
398 bool bHasMarked
= rMarkList
.GetMarkCount() != 0;
402 SfxAllItemSet
aSet(pDrView
->GetAttrFromMarked(false));
403 if (const SfxPoolItem
* pItem
= nullptr;
404 aSet
.GetItemState(SDRATTR_TEXTCOLUMNS_NUMBER
, false, &pItem
) >= SfxItemState::DEFAULT
407 aSet
.Put(pItem
->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_NUMBER
));
409 if (const SfxPoolItem
* pItem
= nullptr;
410 aSet
.GetItemState(SDRATTR_TEXTCOLUMNS_SPACING
, false, &pItem
) >= SfxItemState::DEFAULT
413 aSet
.Put(pItem
->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_SPACING
));
415 rSet
.Put(aSet
, false);
419 pDrView
->GetAttributes(rSet
);
422 SdrPageView
* pPV
= pDrView
->GetSdrPageView();
426 // #i52073# when a sheet with an active OLE object is deleted,
427 // the slot state is queried without an active page view
429 // Items for position and size (see ScGridWindow::UpdateStatusPosSize, #108137#)
431 // #i34458# The SvxSizeItem in SID_TABLE_CELL is no longer needed by
432 // SvxPosSizeStatusBarControl, it's enough to have it in SID_ATTR_SIZE.
434 bool bActionItem
= false;
435 if ( pDrView
->IsAction() ) // action rectangle
437 tools::Rectangle aRect
;
438 pDrView
->TakeActionRect( aRect
);
439 if ( !aRect
.IsEmpty() )
441 pPV
->LogicToPagePos(aRect
);
442 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aRect
.TopLeft() ) );
443 Size
aSize( aRect
.Right() - aRect
.Left(), aRect
.Bottom() - aRect
.Top() );
444 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, aSize
) );
448 // Set correct colors for charts in sidebar
449 setupFillColorForChart(pDrView
->GetSfxViewShell(), rSet
);
454 if ( rMarkList
.GetMarkCount() != 0 ) // selected objects
456 tools::Rectangle aRect
= pDrView
->GetAllMarkedRect();
457 pPV
->LogicToPagePos(aRect
);
458 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aRect
.TopLeft() ) );
459 Size
aSize( aRect
.Right() - aRect
.Left(), aRect
.Bottom() - aRect
.Top() );
460 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, aSize
) );
462 else // mouse position
464 // aPos is initialized above
465 pPV
->LogicToPagePos(aPos
);
466 rSet
.Put( SfxPointItem( SID_ATTR_POSITION
, aPos
) );
467 rSet
.Put( SvxSizeItem( SID_ATTR_SIZE
, Size( 0, 0 ) ) );
471 void ScDrawShell::GetAttrFuncState(SfxItemSet
&rSet
)
473 // Disable dialogs for Draw-attributes if necessary
475 ScDrawView
* pDrView
= rViewData
.GetScDrawView();
476 SfxItemSet aViewSet
= pDrView
->GetAttrFromMarked(false);
477 const SdrMarkList
& rMarkList
= pDrView
->GetMarkedObjectList();
478 const size_t nMarkCount
= rMarkList
.GetMarkCount();
479 bool bShowArea
= true, bShowMeasure
= true;
481 for ( size_t i
= 0; i
< nMarkCount
&& i
< 50; ++i
)
483 SdrObject
* pObj
= rMarkList
.GetMark( i
)->GetMarkedSdrObj();
484 SdrObjKind nObjType
= pObj
->GetObjIdentifier();
486 if ( nObjType
!= SdrObjKind::Measure
)
487 bShowMeasure
= false;
489 // If marked object is 2D, disable format area command.
490 if ( nObjType
== SdrObjKind::PolyLine
||
491 nObjType
== SdrObjKind::Line
||
492 nObjType
== SdrObjKind::PathLine
||
493 nObjType
== SdrObjKind::FreehandLine
||
494 nObjType
== SdrObjKind::Edge
||
495 nObjType
== SdrObjKind::CircleArc
||
499 if ( !bShowArea
&& !bShowMeasure
)
504 rSet
.DisableItem( SID_ATTRIBUTES_AREA
);
507 rSet
.DisableItem( SID_MEASURE_DLG
);
509 if ( aViewSet
.GetItemState( XATTR_LINESTYLE
) == SfxItemState::DEFAULT
)
511 rSet
.DisableItem( SID_ATTRIBUTES_LINE
);
512 rSet
.DisableItem( SID_ATTR_LINEEND_STYLE
); // Tbx-Controller
515 if ( aViewSet
.GetItemState( XATTR_FILLSTYLE
) == SfxItemState::DEFAULT
)
516 rSet
.DisableItem( SID_ATTRIBUTES_AREA
);
519 bool ScDrawShell::AreAllObjectsOnLayer(SdrLayerID nLayerNo
,const SdrMarkList
& rMark
)
522 const size_t nCount
= rMark
.GetMarkCount();
523 for (size_t i
=0; i
<nCount
; ++i
)
525 SdrObject
* pObj
= rMark
.GetMark(i
)->GetMarkedSdrObj();
527 if ( dynamic_cast<const SdrUnoObj
*>( pObj
) == nullptr )
529 if(nLayerNo
!=pObj
->GetLayer())
539 void ScDrawShell::GetDrawAttrStateForIFBX( SfxItemSet
& rSet
)
541 ScDrawView
* pView
= rViewData
.GetScDrawView();
542 const SdrMarkList
& rMarkList
= pView
->GetMarkedObjectList();
544 if( rMarkList
.GetMark(0) != nullptr )
546 SfxItemSet
aNewAttr(pView
->GetGeoAttrFromMarked());
547 rSet
.Put(aNewAttr
, false);
551 void ScDrawShell::Activate (const bool)
553 if (SfxViewFrame
* pFrame
= GetFrame())
555 ContextChangeEventMultiplexer::NotifyContextChange(
556 pFrame
->GetFrame().GetController(),
557 vcl::EnumContext::GetContextEnum(
558 GetSidebarContextName()));
562 const OUString
& ScDrawShell::GetSidebarContextName()
564 return vcl::EnumContext::GetContextName(
565 svx::sidebar::SelectionAnalyzer::GetContextForSelection_SC(
566 GetDrawView()->GetMarkedObjectList()));
569 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */