/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star::drawing; using namespace com::sun::star; ScDrawShell::ScDrawShell( ScViewData& rData ) : SfxShell(rData.GetViewShell()), rViewData( rData ), mpSelectionChangeHandler(new svx::sidebar::SelectionChangeHandler( [this] () { return this->GetSidebarContextName(); }, GetFrame()->GetFrame().GetController(), vcl::EnumContext::Context::Cell)) { SetPool( &rViewData.GetScDrawView()->GetModel()->GetItemPool() ); SfxUndoManager* pMgr = rViewData.GetSfxDocShell()->GetUndoManager(); SetUndoManager( pMgr ); if ( !rViewData.GetDocument().IsUndoEnabled() ) { pMgr->SetMaxUndoActionCount( 0 ); } SetName("Drawing"); mpSelectionChangeHandler->Connect(); } ScDrawShell::~ScDrawShell() { mpSelectionChangeHandler->Disconnect(); } void ScDrawShell::GetState( SfxItemSet& rSet ) // Conditions / Toggles { ScDrawView* pView = rViewData.GetScDrawView(); SdrDragMode eMode = pView->GetDragMode(); rSet.Put( SfxBoolItem( SID_OBJECT_ROTATE, eMode == SdrDragMode::Rotate ) ); rSet.Put( SfxBoolItem( SID_OBJECT_MIRROR, eMode == SdrDragMode::Mirror ) ); rSet.Put( SfxBoolItem( SID_BEZIER_EDIT, !pView->IsFrameDragSingles() ) ); sal_uInt16 nFWId = ScGetFontWorkId(); SfxViewFrame* pViewFrm = rViewData.GetViewShell()->GetViewFrame(); rSet.Put(SfxBoolItem(SID_FONTWORK, pViewFrm->HasChildWindow(nFWId))); // Notes always default to Page anchor. bool bDisableAnchor = false; const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); if ( rMarkList.GetMarkCount() == 1 ) { SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); if( ScDrawLayer::IsNoteCaption( pObj ) ) { bDisableAnchor = true; rSet.DisableItem( SID_ANCHOR_PAGE ); rSet.DisableItem( SID_ANCHOR_CELL ); rSet.DisableItem( SID_ANCHOR_CELL_RESIZE ); } } if ( bDisableAnchor ) return; switch( pView->GetAnchorType() ) { case SCA_PAGE: rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, true ) ); rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, false ) ); rSet.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE, false ) ); break; case SCA_CELL: rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, false ) ); rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, true ) ); rSet.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE, false ) ); break; case SCA_CELL_RESIZE: rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, false ) ); rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, false ) ); rSet.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE, true ) ); break; default: rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, false ) ); rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, false ) ); rSet.Put( SfxBoolItem( SID_ANCHOR_CELL_RESIZE, false ) ); break; } } void ScDrawShell::GetDrawFuncState( SfxItemSet& rSet ) // disable functions { ScDrawView* pView = rViewData.GetScDrawView(); // call IsMirrorAllowed first to make sure ForcePossibilities (and thus CheckMarked) // is called before GetMarkCount, so the nMarkCount value is valid for the rest of this method. if (!pView->IsMirrorAllowed(true,true)) { rSet.DisableItem( SID_MIRROR_HORIZONTAL ); rSet.DisableItem( SID_MIRROR_VERTICAL ); rSet.DisableItem( SID_FLIP_HORIZONTAL ); rSet.DisableItem( SID_FLIP_VERTICAL ); } if (GetObjectShell()->isContentExtractionLocked()) { rSet.DisableItem(SID_COPY); rSet.DisableItem(SID_CUT); } const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); const size_t nMarkCount = rMarkList.GetMarkCount(); if ( nMarkCount <= 1 || !pView->IsGroupPossible() ) rSet.DisableItem( SID_GROUP ); if ( nMarkCount == 0 || !pView->IsUnGroupPossible() ) rSet.DisableItem( SID_UNGROUP ); if ( nMarkCount != 1 || !pView->IsGroupEnterPossible() ) rSet.DisableItem( SID_ENTER_GROUP ); if ( !pView->IsGroupEntered() ) rSet.DisableItem( SID_LEAVE_GROUP ); if ( nMarkCount <= 1 ) // Nothing or only one object selected { // alignment rSet.DisableItem( SID_OBJECT_ALIGN_LEFT ); // no alignment on the side rSet.DisableItem( SID_OBJECT_ALIGN_CENTER ); rSet.DisableItem( SID_OBJECT_ALIGN_RIGHT ); rSet.DisableItem( SID_OBJECT_ALIGN_UP ); rSet.DisableItem( SID_OBJECT_ALIGN_MIDDLE ); rSet.DisableItem( SID_OBJECT_ALIGN_DOWN ); rSet.DisableItem( SID_OBJECT_ALIGN ); // pseudo slots for Format menu rSet.DisableItem( SID_ALIGN_ANY_LEFT ); rSet.DisableItem( SID_ALIGN_ANY_HCENTER ); rSet.DisableItem( SID_ALIGN_ANY_RIGHT ); rSet.DisableItem( SID_ALIGN_ANY_TOP ); rSet.DisableItem( SID_ALIGN_ANY_VCENTER ); rSet.DisableItem( SID_ALIGN_ANY_BOTTOM ); } // do not change layer of form controls // #i83729# do not change layer of cell notes (on internal layer) if ( !nMarkCount || pView->HasMarkedControl() || pView->HasMarkedInternal() ) { rSet.DisableItem( SID_OBJECT_HEAVEN ); rSet.DisableItem( SID_OBJECT_HELL ); } else { if(AreAllObjectsOnLayer(SC_LAYER_FRONT,rMarkList)) { rSet.DisableItem( SID_OBJECT_HEAVEN ); } else if(AreAllObjectsOnLayer(SC_LAYER_BACK,rMarkList)) { rSet.DisableItem( SID_OBJECT_HELL ); } } bool bCanRename = false; if ( nMarkCount > 1 ) { // no hyperlink options for a selected group rSet.DisableItem( SID_EDIT_HYPERLINK ); rSet.DisableItem( SID_REMOVE_HYPERLINK ); rSet.DisableItem( SID_OPEN_HYPERLINK ); rSet.DisableItem( SID_COPY_HYPERLINK_LOCATION ); // Fit to cell only works with a single graphic rSet.DisableItem( SID_FITCELLSIZE ); } else if ( nMarkCount == 1 ) { SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj(); if (pObj->getHyperlink().isEmpty()) { rSet.DisableItem( SID_EDIT_HYPERLINK ); rSet.DisableItem( SID_OPEN_HYPERLINK ); rSet.DisableItem( SID_REMOVE_HYPERLINK ); rSet.DisableItem( SID_COPY_HYPERLINK_LOCATION ); } SdrLayerID nLayerID = pObj->GetLayer(); if ( nLayerID != SC_LAYER_INTERN ) bCanRename = true; // #i51351# anything except internal objects can be renamed // #91929#; don't show original size entry if not possible SdrObjKind nObjType = pObj->GetObjIdentifier(); if ( nObjType == SdrObjKind::OLE2 ) { SdrOle2Obj* pOleObj = static_cast(rMarkList.GetMark( 0 )->GetMarkedSdrObj()); if (pOleObj->GetObjRef().is() && (pOleObj->GetObjRef()->getStatus( pOleObj->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) ) //TODO/LATER: why different slots in Draw and Calc? rSet.DisableItem(SID_ORIGINALSIZE); } else if ( nObjType == SdrObjKind::Caption ) { if ( nLayerID == SC_LAYER_INTERN ) { // SdrCaptionObj() Notes cannot be cut/copy in isolation from // their cells. rSet.DisableItem( SID_CUT ); rSet.DisableItem( SID_COPY ); // Notes always default to Page anchor. rSet.DisableItem( SID_ANCHOR_TOGGLE ); rSet.DisableItem( SID_ANCHOR_MENU ); } } // Fit to cell is only available for cell anchored graphics obviously if (pView->GetAnchorType() != SCA_CELL && pView->GetAnchorType() != SCA_CELL_RESIZE) rSet.DisableItem( SID_FITCELLSIZE ); // Support advanced DiagramHelper if (!pObj->isDiagram()) { rSet.DisableItem( SID_REGENERATE_DIAGRAM ); rSet.DisableItem( SID_EDIT_DIAGRAM ); } } if ( !bCanRename ) { // #i68101# rSet.DisableItem( SID_RENAME_OBJECT ); rSet.DisableItem( SID_TITLE_DESCRIPTION_OBJECT ); } if ( !nMarkCount ) // nothing selected { // Arrangement rSet.DisableItem( SID_FRAME_UP ); rSet.DisableItem( SID_FRAME_DOWN ); rSet.DisableItem( SID_FRAME_TO_TOP ); rSet.DisableItem( SID_FRAME_TO_BOTTOM ); // Clipboard / delete rSet.DisableItem( SID_DELETE ); rSet.DisableItem( SID_DELETE_CONTENTS ); rSet.DisableItem( SID_CUT ); rSet.DisableItem( SID_COPY ); // other rSet.DisableItem( SID_ANCHOR_TOGGLE ); rSet.DisableItem( SID_ANCHOR_MENU ); rSet.DisableItem( SID_ORIGINALSIZE ); rSet.DisableItem( SID_FITCELLSIZE ); rSet.DisableItem( SID_ATTR_TRANSFORM ); } if ( rSet.GetItemState( SID_ENABLE_HYPHENATION ) != SfxItemState::UNKNOWN ) { SfxItemSet aAttrs( pView->GetModel()->GetItemPool() ); pView->GetAttributes( aAttrs ); if( aAttrs.GetItemState( EE_PARA_HYPHENATE ) >= SfxItemState::DEFAULT ) { bool bValue = aAttrs.Get( EE_PARA_HYPHENATE ).GetValue(); rSet.Put( SfxBoolItem( SID_ENABLE_HYPHENATION, bValue ) ); } } svx::ExtrusionBar::getState( pView, rSet ); svx::FontworkBar::getState( pView, rSet ); } static void setupFillColorForChart(const SfxViewShell* pShell, SfxItemSet& rSet) { if (!pShell) return; SfxInPlaceClient* pIPClient = pShell->GetIPClient(); if (!pIPClient) return; const css::uno::Reference<::css::embed::XEmbeddedObject>& xEmbObj = pIPClient->GetObject(); if( !xEmbObj.is() ) return; ::css::uno::Reference<::css::chart2::XChartDocument> xChart( xEmbObj->getComponent(), uno::UNO_QUERY ); if( !xChart.is() ) return; css::uno::Reference xPropSet = xChart->getPageBackground(); if (!xPropSet.is()) return; css::uno::Reference xInfo(xPropSet->getPropertySetInfo()); if (!xInfo.is()) return; if (xInfo->hasPropertyByName("FillColor")) { sal_uInt32 nFillColor = 0; xPropSet->getPropertyValue("FillColor") >>= nFillColor; XFillColorItem aFillColorItem("", Color(ColorTransparency, nFillColor)); rSet.Put(aFillColorItem); if (comphelper::LibreOfficeKit::isActive()) pShell->libreOfficeKitViewCallback(LOK_CALLBACK_STATE_CHANGED, (".uno:FillColor=" + std::to_string(nFillColor)).c_str()); } if (!(comphelper::LibreOfficeKit::isActive() && xInfo->hasPropertyByName("FillGradientName"))) return; OUString aGradientName; xPropSet->getPropertyValue("FillGradientName") >>= aGradientName; ::css::uno::Reference< ::css::frame::XController > xChartController = xChart->getCurrentController(); if( !xChartController.is() ) return; css::uno::Reference xFact(xChartController->getModel(), css::uno::UNO_QUERY); if (!xFact.is()) return; css::uno::Reference xNameAccess( xFact->createInstance("com.sun.star.drawing.GradientTable"), css::uno::UNO_QUERY); if (xNameAccess.is() && xNameAccess->hasByName(aGradientName)) { css::uno::Any aAny = xNameAccess->getByName(aGradientName); XFillGradientItem aItem; aItem.SetName(aGradientName); aItem.PutValue(aAny, MID_FILLGRADIENT); rSet.Put(aItem); } } // Attributes for Drawing-Objects void ScDrawShell::GetDrawAttrState( SfxItemSet& rSet ) { Point aMousePos = rViewData.GetMousePosPixel(); vcl::Window* pWindow = rViewData.GetActiveWin(); ScDrawView* pDrView = rViewData.GetScDrawView(); Point aPos = pWindow->PixelToLogic(aMousePos); bool bHasMarked = pDrView->AreObjectsMarked(); if( bHasMarked ) { SfxAllItemSet aSet(pDrView->GetAttrFromMarked(false)); if (const SfxPoolItem* pItem = nullptr; aSet.GetItemState(SDRATTR_TEXTCOLUMNS_NUMBER, false, &pItem) >= SfxItemState::DEFAULT && pItem) { aSet.Put(pItem->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_NUMBER)); } if (const SfxPoolItem* pItem = nullptr; aSet.GetItemState(SDRATTR_TEXTCOLUMNS_SPACING, false, &pItem) >= SfxItemState::DEFAULT && pItem) { aSet.Put(pItem->CloneSetWhich(SID_ATTR_TEXTCOLUMNS_SPACING)); } rSet.Put(aSet, false); } else { rSet.Put( pDrView->GetDefaultAttr() ); } SdrPageView* pPV = pDrView->GetSdrPageView(); if ( !pPV ) return; // #i52073# when a sheet with an active OLE object is deleted, // the slot state is queried without an active page view // Items for position and size (see ScGridWindow::UpdateStatusPosSize, #108137#) // #i34458# The SvxSizeItem in SID_TABLE_CELL is no longer needed by // SvxPosSizeStatusBarControl, it's enough to have it in SID_ATTR_SIZE. bool bActionItem = false; if ( pDrView->IsAction() ) // action rectangle { tools::Rectangle aRect; pDrView->TakeActionRect( aRect ); if ( !aRect.IsEmpty() ) { pPV->LogicToPagePos(aRect); rSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) ); Size aSize( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() ); rSet.Put( SvxSizeItem( SID_ATTR_SIZE, aSize ) ); bActionItem = true; } // Set correct colors for charts in sidebar setupFillColorForChart(pDrView->GetSfxViewShell(), rSet); } if ( bActionItem ) return; if ( pDrView->AreObjectsMarked() ) // selected objects { tools::Rectangle aRect = pDrView->GetAllMarkedRect(); pPV->LogicToPagePos(aRect); rSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) ); Size aSize( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() ); rSet.Put( SvxSizeItem( SID_ATTR_SIZE, aSize ) ); } else // mouse position { // aPos is initialized above pPV->LogicToPagePos(aPos); rSet.Put( SfxPointItem( SID_ATTR_POSITION, aPos ) ); rSet.Put( SvxSizeItem( SID_ATTR_SIZE, Size( 0, 0 ) ) ); } } void ScDrawShell::GetAttrFuncState(SfxItemSet &rSet) { // Disable dialogs for Draw-attributes if necessary ScDrawView* pDrView = rViewData.GetScDrawView(); SfxItemSet aViewSet = pDrView->GetAttrFromMarked(false); const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList(); const size_t nMarkCount = rMarkList.GetMarkCount(); bool bShowArea = true, bShowMeasure = true; for ( size_t i = 0; i < nMarkCount && i < 50; ++i ) { SdrObject* pObj = rMarkList.GetMark( i )->GetMarkedSdrObj(); SdrObjKind nObjType = pObj->GetObjIdentifier(); if ( nObjType != SdrObjKind::Measure ) bShowMeasure = false; // If marked object is 2D, disable format area command. if ( nObjType == SdrObjKind::PolyLine || nObjType == SdrObjKind::Line || nObjType == SdrObjKind::PathLine || nObjType == SdrObjKind::FreehandLine || nObjType == SdrObjKind::Edge || nObjType == SdrObjKind::CircleArc || bShowMeasure ) bShowArea = false; if ( !bShowArea && !bShowMeasure ) break; } if ( !bShowArea ) rSet.DisableItem( SID_ATTRIBUTES_AREA ); if ( !bShowMeasure ) rSet.DisableItem( SID_MEASURE_DLG ); if ( aViewSet.GetItemState( XATTR_LINESTYLE ) == SfxItemState::DEFAULT ) { rSet.DisableItem( SID_ATTRIBUTES_LINE ); rSet.DisableItem( SID_ATTR_LINEEND_STYLE ); // Tbx-Controller } if ( aViewSet.GetItemState( XATTR_FILLSTYLE ) == SfxItemState::DEFAULT ) rSet.DisableItem( SID_ATTRIBUTES_AREA ); } bool ScDrawShell::AreAllObjectsOnLayer(SdrLayerID nLayerNo,const SdrMarkList& rMark) { bool bResult=true; const size_t nCount = rMark.GetMarkCount(); for (size_t i=0; iGetMarkedSdrObj(); if ( dynamic_cast( pObj) == nullptr ) { if(nLayerNo!=pObj->GetLayer()) { bResult=false; break; } } } return bResult; } void ScDrawShell::GetDrawAttrStateForIFBX( SfxItemSet& rSet ) { ScDrawView* pView = rViewData.GetScDrawView(); const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); if( rMarkList.GetMark(0) != nullptr ) { SfxItemSet aNewAttr(pView->GetGeoAttrFromMarked()); rSet.Put(aNewAttr, false); } } void ScDrawShell::Activate (const bool) { ContextChangeEventMultiplexer::NotifyContextChange( GetFrame()->GetFrame().GetController(), vcl::EnumContext::GetContextEnum( GetSidebarContextName())); } const OUString & ScDrawShell::GetSidebarContextName() { return vcl::EnumContext::GetContextName( svx::sidebar::SelectionAnalyzer::GetContextForSelection_SC( GetDrawView()->GetMarkedObjectList())); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */