diff options
Diffstat (limited to 'sc/source/ui/view/tabvwsha.cxx')
-rw-r--r-- | sc/source/ui/view/tabvwsha.cxx | 1817 |
1 files changed, 1817 insertions, 0 deletions
diff --git a/sc/source/ui/view/tabvwsha.cxx b/sc/source/ui/view/tabvwsha.cxx new file mode 100644 index 0000000000..c332c9542a --- /dev/null +++ b/sc/source/ui/view/tabvwsha.cxx @@ -0,0 +1,1817 @@ +/* -*- 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 <com/sun/star/table/BorderLineStyle.hpp> +#include <officecfg/Office/Calc.hxx> + +#include <comphelper/lok.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/langitem.hxx> +#include <o3tl/temporary.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/request.hxx> +#include <sfx2/sfxdlg.hxx> +#include <sfx2/sidebar/Sidebar.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/newstyle.hxx> +#include <sfx2/tplpitem.hxx> +#include <svl/ilstitem.hxx> +#include <svl/numformat.hxx> +#include <svl/zformat.hxx> +#include <svl/int64item.hxx> +#include <svl/ptitem.hxx> +#include <svl/srchitem.hxx> +#include <svl/srchdefs.hxx> +#include <svl/stritem.hxx> +#include <svl/whiter.hxx> +#include <svx/numinf.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflftrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/zoomslideritem.hxx> + +#include <global.hxx> +#include <appoptio.hxx> +#include <attrib.hxx> +#include <cellform.hxx> +#include <cellvalue.hxx> +#include <compiler.hxx> +#include <docsh.hxx> +#include <document.hxx> +#include <formulacell.hxx> +#include <globstr.hrc> +#include <inputhdl.hxx> +#include <inputwin.hxx> +#include <markdata.hxx> +#include <patattr.hxx> +#include <sc.hrc> +#include <scabstdlg.hxx> +#include <scitems.hxx> +#include <scmod.hxx> +#include <scresid.hxx> +#include <stlpool.hxx> +#include <tabvwsh.hxx> +#include <tokenarray.hxx> +#include <viewdata.hxx> +#include <docpool.hxx> +#include <printfun.hxx> +#include <undostyl.hxx> +#include <futext.hxx> + +#include <memory> + +using namespace com::sun::star; + +bool ScTabViewShell::GetFunction( OUString& rFuncStr, FormulaError nErrCode ) +{ + sal_uInt32 nFuncs = SC_MOD()->GetAppOptions().GetStatusFunc(); + ScViewData& rViewData = GetViewData(); + ScMarkData& rMark = rViewData.GetMarkData(); + bool bIgnoreError = (rMark.IsMarked() || rMark.IsMultiMarked()); + bool bFirst = true; + for ( sal_uInt16 nFunc = 0; nFunc < 32; nFunc++ ) + { + if ( !(nFuncs & (1U << nFunc)) ) + continue; + ScSubTotalFunc eFunc = static_cast<ScSubTotalFunc>(nFunc); + + if (bIgnoreError && (eFunc == SUBTOTAL_FUNC_CNT || eFunc == SUBTOTAL_FUNC_CNT2)) + nErrCode = FormulaError::NONE; + + if (nErrCode != FormulaError::NONE) + { + rFuncStr = ScGlobal::GetLongErrorString(nErrCode); + return true; + } + + TranslateId pGlobStrId; + switch (eFunc) + { + case SUBTOTAL_FUNC_AVE: pGlobStrId = STR_FUN_TEXT_AVG; break; + case SUBTOTAL_FUNC_CNT: pGlobStrId = STR_FUN_TEXT_COUNT; break; + case SUBTOTAL_FUNC_CNT2: pGlobStrId = STR_FUN_TEXT_COUNT2; break; + case SUBTOTAL_FUNC_MAX: pGlobStrId = STR_FUN_TEXT_MAX; break; + case SUBTOTAL_FUNC_MIN: pGlobStrId = STR_FUN_TEXT_MIN; break; + case SUBTOTAL_FUNC_SUM: pGlobStrId = STR_FUN_TEXT_SUM; break; + case SUBTOTAL_FUNC_SELECTION_COUNT: pGlobStrId = STR_FUN_TEXT_SELECTION_COUNT; break; + + default: + { + // added to avoid warnings + } + } + if (pGlobStrId) + { + ScDocument& rDoc = rViewData.GetDocument(); + SCCOL nPosX = rViewData.GetCurX(); + SCROW nPosY = rViewData.GetCurY(); + SCTAB nTab = rViewData.GetTabNo(); + + OUString aStr = ScResId(pGlobStrId) + ": "; + + ScAddress aCursor( nPosX, nPosY, nTab ); + double nVal; + if ( rDoc.GetSelectionFunction( eFunc, aCursor, rMark, nVal ) ) + { + if ( nVal == 0.0 ) + aStr += "0"; + else + { + // Number in the standard format, the other on the cursor position + SvNumberFormatter* pFormatter = rDoc.GetFormatTable(); + sal_uInt32 nNumFmt = 0; + if ( eFunc != SUBTOTAL_FUNC_CNT && eFunc != SUBTOTAL_FUNC_CNT2 && eFunc != SUBTOTAL_FUNC_SELECTION_COUNT) + { + // number format from attributes or formula + nNumFmt = rDoc.GetNumberFormat( nPosX, nPosY, nTab ); + // If the number format is time (without date) and the + // result is not within 24 hours, use a duration + // format. Summing date+time doesn't make much sense + // otherwise but we also don't want to display duration + // for a single date+time value. + if (nVal < 0.0 || nVal >= 1.0) + { + const SvNumberformat* pFormat = pFormatter->GetEntry(nNumFmt); + if (pFormat && (pFormat->GetType() == SvNumFormatType::TIME)) + nNumFmt = pFormatter->GetTimeFormat( nVal, pFormat->GetLanguage(), true); + } + } + + OUString aValStr; + const Color* pDummy; + pFormatter->GetOutputString( nVal, nNumFmt, aValStr, &pDummy ); + aStr += aValStr; + } + } + if ( bFirst ) + { + rFuncStr += aStr; + bFirst = false; + } + else + rFuncStr += "; " + aStr; + } + } + + return !rFuncStr.isEmpty(); +} + +// Functions that are disabled, depending on the selection +// Default: +// SID_DELETE, +// SID_DELETE_CONTENTS, +// FID_DELETE_CELL +// FID_VALIDATION + +void ScTabViewShell::GetState( SfxItemSet& rSet ) +{ + ScViewData& rViewData = GetViewData(); + ScDocument& rDoc = rViewData.GetDocument(); + ScDocShell* pDocShell = rViewData.GetDocShell(); + ScMarkData& rMark = rViewData.GetMarkData(); + SCCOL nPosX = rViewData.GetCurX(); + SCROW nPosY = rViewData.GetCurY(); + SCTAB nTab = rViewData.GetTabNo(); + + SfxViewFrame& rThisFrame = GetViewFrame(); + bool bOle = GetViewFrame().GetFrame().IsInPlace(); + + SCTAB nTabSelCount = rMark.GetSelectCount(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + + while ( nWhich ) + { + switch ( nWhich ) + { + case FID_CHG_COMMENT: + { + ScDocShell* pDocSh = GetViewData().GetDocShell(); + ScAddress aPos( nPosX, nPosY, nTab ); + if ( pDocSh->IsReadOnly() || !pDocSh->GetChangeAction(aPos) || pDocSh->IsDocShared() ) + rSet.DisableItem( nWhich ); + } + break; + + case SID_OPENDLG_EDIT_PRINTAREA: + case SID_ADD_PRINTAREA: + case SID_DEFINE_PRINTAREA: + { + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_DELETE_PRINTAREA: + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + else if (rDoc.IsPrintEntireSheet(nTab)) + rSet.DisableItem(nWhich); + break; + + case SID_STATUS_PAGESTYLE: + case SID_HFEDIT: + GetViewData().GetDocShell()->GetStatePageStyle( rSet, nTab ); + break; + + case SID_SEARCH_ITEM: + { + SvxSearchItem aItem(ScGlobal::GetSearchItem()); // make a copy. + // Search on current selection if a range is marked. + aItem.SetSelection(rMark.IsMarked()); + rSet.Put(aItem); + break; + } + + case SID_SEARCH_OPTIONS: + { + // Anything goes + SearchOptionFlags nOptions = SearchOptionFlags::ALL; + + // No replacement if ReadOnly + if (GetViewData().GetDocShell()->IsReadOnly()) + nOptions &= ~SearchOptionFlags( SearchOptionFlags::REPLACE | SearchOptionFlags::REPLACE_ALL ); + rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(nOptions) ) ); + } + break; + + case SID_CURRENTCELL: + { + ScAddress aScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), 0 ); + OUString aAddr(aScAddress.Format(ScRefFlags::ADDR_ABS, nullptr, rDoc.GetAddressConvention())); + SfxStringItem aPosItem( SID_CURRENTCELL, aAddr ); + + rSet.Put( aPosItem ); + } + break; + + case SID_CURRENTTAB: + // Table for Basic is 1-based + rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(GetViewData().GetTabNo()) + 1 ) ); + break; + + case SID_CURRENTDOC: + rSet.Put( SfxStringItem( nWhich, GetViewData().GetDocShell()->GetTitle() ) ); + break; + + case FID_TOGGLEINPUTLINE: + { + sal_uInt16 nId = ScInputWindowWrapper::GetChildWindowId(); + + if ( rThisFrame.KnowsChildWindow( nId ) ) + { + SfxChildWindow* pWnd = rThisFrame.GetChildWindow( nId ); + rSet.Put( SfxBoolItem( nWhich, pWnd != nullptr ) ); + } + else + rSet.DisableItem( nWhich ); + } + break; + + case FID_DEL_MANUALBREAKS: + if (!rDoc.HasManualBreaks(nTab)) + rSet.DisableItem( nWhich ); + break; + + case FID_RESET_PRINTZOOM: + { + // disable if already set to default + + OUString aStyleName = rDoc.GetPageStyle( nTab ); + ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, + SfxStyleFamily::Page ); + OSL_ENSURE( pStyleSheet, "PageStyle not found" ); + if ( pStyleSheet ) + { + SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); + sal_uInt16 nScale = rStyleSet.Get(ATTR_PAGE_SCALE).GetValue(); + sal_uInt16 nPages = rStyleSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue(); + if ( nScale == 100 && nPages == 0 ) + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_ZOOM_IN: + { + const Fraction& rZoomY = GetViewData().GetZoomY(); + tools::Long nZoom = tools::Long(rZoomY * 100); + if (nZoom >= MAXZOOM) + rSet.DisableItem(nWhich); + } + break; + case SID_ZOOM_OUT: + { + const Fraction& rZoomY = GetViewData().GetZoomY(); + tools::Long nZoom = tools::Long(rZoomY * 100); + if (nZoom <= MINZOOM) + rSet.DisableItem(nWhich); + } + break; + + case FID_SCALE: + case SID_ATTR_ZOOM: + if ( bOle ) + rSet.DisableItem( nWhich ); + else + { + const Fraction& rOldY = GetViewData().GetZoomY(); + sal_uInt16 nZoom = static_cast<sal_uInt16>(tools::Long( rOldY * 100 )); + rSet.Put( SvxZoomItem( SvxZoomType::PERCENT, nZoom, TypedWhichId<SvxZoomItem>(nWhich) ) ); + } + break; + + case SID_ATTR_ZOOMSLIDER: + { + if ( bOle ) + rSet.DisableItem( nWhich ); + else + { + const Fraction& rOldY = GetViewData().GetZoomY(); + sal_uInt16 nCurrentZoom = static_cast<sal_uInt16>(tools::Long( rOldY * 100 )); + + if( nCurrentZoom ) + { + SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM, SID_ATTR_ZOOMSLIDER ); + aZoomSliderItem.AddSnappingPoint( 100 ); + rSet.Put( aZoomSliderItem ); + } + } + } + break; + + case FID_FUNCTION_BOX: + { + const bool bBoxOpen = ::sfx2::sidebar::Sidebar::IsPanelVisible(u"ScFunctionsPanel", + rThisFrame.GetFrame().GetFrameInterface()); + rSet.Put(SfxBoolItem(nWhich, bBoxOpen)); + break; + } + + case FID_TOGGLESYNTAX: + rSet.Put(SfxBoolItem(nWhich, GetViewData().IsSyntaxMode())); + break; + + case FID_TOGGLECOLROWHIGHLIGHTING: + rSet.Put(SfxBoolItem( + nWhich, + officecfg::Office::Calc::Content::Display::ColumnRowHighlighting::get())); + break; + + case FID_TOGGLEHEADERS: + rSet.Put(SfxBoolItem(nWhich, GetViewData().IsHeaderMode())); + break; + + case FID_TOGGLEFORMULA: + { + const ScViewOptions& rOpts = rViewData.GetOptions(); + bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS ); + rSet.Put(SfxBoolItem(nWhich, bFormulaMode )); + } + break; + + case FID_NORMALVIEWMODE: + case FID_PAGEBREAKMODE: + // always handle both slots - they exclude each other + if ( bOle ) + { + rSet.DisableItem( FID_NORMALVIEWMODE ); + rSet.DisableItem( FID_PAGEBREAKMODE ); + } + else + { + rSet.Put(SfxBoolItem(FID_NORMALVIEWMODE, !GetViewData().IsPagebreakMode())); + rSet.Put(SfxBoolItem(FID_PAGEBREAKMODE, GetViewData().IsPagebreakMode())); + } + break; + + case FID_PROTECT_DOC: + { + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + else + { + rSet.Put( SfxBoolItem( nWhich, rDoc.IsDocProtected() ) ); + } + } + break; + + case FID_PROTECT_TABLE: + { + if ( pDocShell && pDocShell->IsDocShared() ) + { + rSet.DisableItem( nWhich ); + } + else + { + rSet.Put( SfxBoolItem( nWhich, rDoc.IsTabProtected( nTab ) ) ); + } + } + break; + + case SID_AUTO_OUTLINE: + { + if (rDoc.GetChangeTrack()!=nullptr || GetViewData().IsMultiMarked()) + { + rSet.DisableItem( nWhich ); + } + } + break; + + case SID_OUTLINE_DELETEALL: + { + SCTAB nOlTab = GetViewData().GetTabNo(); + ScOutlineTable* pOlTable = rDoc.GetOutlineTable( nOlTab ); + if (pOlTable == nullptr) + rSet.DisableItem( nWhich ); + } + break; + + case SID_WINDOW_SPLIT: + rSet.Put(SfxBoolItem(nWhich, + rViewData.GetHSplitMode() == SC_SPLIT_NORMAL || + rViewData.GetVSplitMode() == SC_SPLIT_NORMAL )); + break; + + case SID_WINDOW_FIX: + if(!comphelper::LibreOfficeKit::isActive()) + { + rSet.Put(SfxBoolItem(nWhich, + rViewData.GetHSplitMode() == SC_SPLIT_FIX || + rViewData.GetVSplitMode() == SC_SPLIT_FIX )); + } + else + { + rSet.Put(SfxBoolItem(nWhich, + rViewData.GetLOKSheetFreezeIndex(true) > 0 || + rViewData.GetLOKSheetFreezeIndex(false) > 0 )); + } + break; + + case SID_WINDOW_FIX_COL: + case SID_WINDOW_FIX_ROW: + { + Point aPos; + bool bIsCol = (nWhich == SID_WINDOW_FIX_COL); + aPos.setX(rViewData.GetLOKSheetFreezeIndex(bIsCol)); + aPos.setY(rViewData.GetTabNo()); + rSet.Put(SfxPointItem(nWhich, aPos)); + } + break; + + case FID_CHG_SHOW: + { + if ( rDoc.GetChangeTrack() == nullptr || ( pDocShell && pDocShell->IsDocShared() ) ) + rSet.DisableItem( nWhich ); + } + break; + case FID_CHG_ACCEPT: + { + if( + ( !rDoc.GetChangeTrack() && !rThisFrame.HasChildWindow(FID_CHG_ACCEPT) ) + || + ( pDocShell && pDocShell->IsDocShared() ) + ) + { + rSet.DisableItem( nWhich); + } + else + { + rSet.Put(SfxBoolItem(FID_CHG_ACCEPT, + rThisFrame.HasChildWindow(FID_CHG_ACCEPT))); + } + } + break; + + case SID_FORMATPAGE: + // in protected tables + if ( pDocShell && ( pDocShell->IsReadOnly() || pDocShell->IsDocShared() ) ) + rSet.DisableItem( nWhich ); + break; + + case SID_PRINTPREVIEW: + // Toggle slot needs a State + rSet.Put( SfxBoolItem( nWhich, false ) ); + break; + + case SID_READONLY_MODE: + rSet.Put( SfxBoolItem( nWhich, GetViewData().GetDocShell()->IsReadOnly() ) ); + break; + + case FID_TAB_DESELECTALL: + if ( nTabSelCount == 1 ) + rSet.DisableItem( nWhich ); // enabled only if several sheets are selected + break; + + case FID_TOGGLEHIDDENCOLROW: + const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig(); + rSet.Put( SfxBoolItem( nWhich, rColorCfg.GetColorValue(svtools::CALCHIDDENROWCOL).bIsVisible) ); + break; + + } // switch ( nWitch ) + nWhich = aIter.NextWhich(); + } // while ( nWitch ) +} + +void ScTabViewShell::ExecuteCellFormatDlg(SfxRequest& rReq, const OUString &rName) +{ + ScDocument& rDoc = GetViewData().GetDocument(); + + std::shared_ptr<SvxBoxItem> aLineOuter(std::make_shared<SvxBoxItem>(ATTR_BORDER)); + std::shared_ptr<SvxBoxInfoItem> aLineInner(std::make_shared<SvxBoxInfoItem>(ATTR_BORDER_INNER)); + + const ScPatternAttr* pOldAttrs = GetSelectionPattern(); + + auto pOldSet = std::make_shared<SfxItemSet>(pOldAttrs->GetItemSet()); + + pOldSet->MergeRange(XATTR_FILLSTYLE, XATTR_FILLCOLOR); + + pOldSet->MergeRange(SID_ATTR_BORDER_STYLES, SID_ATTR_BORDER_DEFAULT_WIDTH); + + // We only allow these border line types. + std::vector<sal_Int32> aBorderStyles{ + table::BorderLineStyle::SOLID, + table::BorderLineStyle::DOTTED, + table::BorderLineStyle::DASHED, + table::BorderLineStyle::FINE_DASHED, + table::BorderLineStyle::DASH_DOT, + table::BorderLineStyle::DASH_DOT_DOT, + table::BorderLineStyle::DOUBLE_THIN }; + + pOldSet->Put(SfxIntegerListItem(SID_ATTR_BORDER_STYLES, std::move(aBorderStyles))); + + // Set the default border width to 0.75 points. + SfxInt64Item aBorderWidthItem(SID_ATTR_BORDER_DEFAULT_WIDTH, 75); + pOldSet->Put(aBorderWidthItem); + + // Get border items and put them in the set: + GetSelectionFrame( aLineOuter, aLineInner ); + + //Fix border incorrect for RTL fdo#62399 + if( rDoc.IsLayoutRTL( GetViewData().GetTabNo() ) ) + { + std::unique_ptr<SvxBoxItem> aNewFrame(aLineOuter->Clone()); + std::unique_ptr<SvxBoxInfoItem> aTempInfo(aLineInner->Clone()); + + if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::LEFT) ) + aNewFrame->SetLine( aLineOuter->GetLeft(), SvxBoxItemLine::RIGHT ); + if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::RIGHT) ) + aNewFrame->SetLine( aLineOuter->GetRight(), SvxBoxItemLine::LEFT ); + + aLineInner->SetValid( SvxBoxInfoItemValidFlags::LEFT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::RIGHT)); + aLineInner->SetValid( SvxBoxInfoItemValidFlags::RIGHT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::LEFT)); + + pOldSet->Put( std::move(aNewFrame) ); + } + else + { + pOldSet->Put( *aLineOuter ); + } + + pOldSet->Put( *aLineInner ); + + // Generate NumberFormat Value from Value and Language and box it. + pOldSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT, + pOldAttrs->GetNumberFormat( rDoc.GetFormatTable() ) ) ); + + std::unique_ptr<SvxNumberInfoItem> pNumberInfoItem = MakeNumberInfoItem(rDoc, GetViewData()); + pOldSet->MergeRange( SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO ); + pOldSet->Put( std::move(pNumberInfoItem) ); + + bInFormatDialog = true; + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + + VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScAttrDlg(GetFrameWeld(), pOldSet.get())); + + if (!rName.isEmpty()) + pDlg->SetCurPageId(rName); + + auto pRequest = std::make_shared<SfxRequest>(rReq); + rReq.Ignore(); // the 'old' request is not relevant any more + + pDlg->StartExecuteAsync([pDlg, pOldSet, pRequest, this](sal_Int32 nResult){ + bInFormatDialog = false; + + if ( nResult == RET_OK ) + { + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + if(const SvxNumberInfoItem* pItem = pOutSet->GetItemIfSet(SID_ATTR_NUMBERFORMAT_INFO)) + { + UpdateNumberFormatter(*pItem); + } + + ApplyAttributes(*pOutSet, *pOldSet); + + pRequest->Done(*pOutSet); + } + + pDlg->disposeOnce(); + }); +} + +const OUString* ScTabViewShell::GetEditString() const +{ + if (mpInputHandler) + return &mpInputHandler->GetEditString(); + + return nullptr; +} + +bool ScTabViewShell::IsRefInputMode() const +{ + ScModule* pScMod = SC_MOD(); + if ( pScMod ) + { + if( pScMod->IsRefDialogOpen() ) + return pScMod->IsFormulaMode(); + if( pScMod->IsFormulaMode() ) + { + ScInputHandler* pHdl = pScMod->GetInputHdl(); + if ( pHdl ) + { + const ScViewData& rViewData = GetViewData(); + ScDocument& rDoc = rViewData.GetDocument(); + const ScAddress aPos( rViewData.GetCurPos() ); + const sal_uInt32 nIndex = rDoc.GetAttr(aPos, ATTR_VALUE_FORMAT )->GetValue(); + const SvNumFormatType nType = rDoc.GetFormatTable()->GetType(nIndex); + if (nType == SvNumFormatType::TEXT) + { + return false; + } + OUString aString = pHdl->GetEditString(); + if ( !pHdl->GetSelIsRef() && aString.getLength() > 1 && + ( aString[0] == '+' || aString[0] == '-' ) ) + { + ScCompiler aComp( rDoc, aPos, rDoc.GetGrammar() ); + aComp.SetCloseBrackets( false ); + std::unique_ptr<ScTokenArray> pArr(aComp.CompileString(aString)); + if ( pArr && pArr->MayReferenceFollow() ) + { + return true; + } + } + else + { + return true; + } + } + } + } + + return false; +} + +void ScTabViewShell::ExecuteInputDirect() +{ + if ( !IsRefInputMode() ) + { + ScModule* pScMod = SC_MOD(); + if ( pScMod ) + { + pScMod->InputEnterHandler(); + } + } +} + +void ScTabViewShell::UpdateInputHandler( bool bForce /* = sal_False */, bool bStopEditing /* = sal_True */ ) +{ + ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : SC_MOD()->GetInputHdl(); + + if ( pHdl ) + { + OUString aString; + const EditTextObject* pObject = nullptr; + ScViewData& rViewData = GetViewData(); + ScDocument& rDoc = rViewData.GetDocument(); + SCCOL nPosX = rViewData.GetCurX(); + SCROW nPosY = rViewData.GetCurY(); + SCTAB nTab = rViewData.GetTabNo(); + SCTAB nStartTab = 0; + SCTAB nEndTab = 0; + SCCOL nStartCol = 0; + SCROW nStartRow = 0; + SCCOL nEndCol = 0; + SCROW nEndRow = 0; + ScAddress aPos = rViewData.GetCurPos(); + + rViewData.GetSimpleArea( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab ); + + PutInOrder( nStartCol, nEndCol ); + PutInOrder( nStartRow, nEndRow ); + PutInOrder( nStartTab, nEndTab ); + + bool bHideFormula = false; + bool bHideAll = false; + + if (rDoc.IsTabProtected(nTab)) + { + const ScProtectionAttr* pProt = rDoc.GetAttr( nPosX,nPosY,nTab, + ATTR_PROTECTION); + bHideFormula = pProt->GetHideFormula(); + bHideAll = pProt->GetHideCell(); + } + + if (!bHideAll) + { + ScRefCellValue rCell(rDoc, aPos); + if (rCell.getType() == CELLTYPE_FORMULA) + { + if (!bHideFormula) + aString = rCell.getFormula()->GetFormula(); + } + else if (rCell.getType() == CELLTYPE_EDIT) + { + pObject = rCell.getEditText(); + } + else + { + SvNumberFormatter* pFormatter = rDoc.GetFormatTable(); + sal_uInt32 nNumFmt = rDoc.GetNumberFormat( aPos ); + + aString = ScCellFormat::GetInputString( rCell, nNumFmt, *pFormatter, rDoc ); + if (rCell.getType() == CELLTYPE_STRING) + { + // Put a ' in front if necessary, so that the string is not + // unintentionally interpreted as a number, and to show the + // user that it is a string (#35060#). + // If cell is not formatted as Text, a leading apostrophe + // needs another prepended, also '=' or '+' or '-' + // otherwise starting a formula. + // NOTE: this corresponds with + // sc/source/core/data/column3.cxx ScColumn::ParseString() + // removing one apostrophe. + // For number format Text IsNumberFormat() would never + // result in numeric anyway. + if (!pFormatter->IsTextFormat(nNumFmt) && (aString.startsWith("'") + || aString.startsWith("=") || aString.startsWith("+") || aString.startsWith("-") + || pFormatter->IsNumberFormat(aString, nNumFmt, o3tl::temporary(double())))) + aString = "'" + aString; + } + } + } + + ScInputHdlState aState( ScAddress( nPosX, nPosY, nTab ), + ScAddress( nStartCol, nStartRow, nTab ), + ScAddress( nEndCol, nEndRow, nTab ), + aString, + pObject ); + + // if using the view's local input handler, this view can always be set + // as current view inside NotifyChange. + ScTabViewShell* pSourceSh = mpInputHandler ? this : nullptr; + + pHdl->NotifyChange( &aState, bForce, pSourceSh, bStopEditing ); + } + + SfxBindings& rBindings = GetViewFrame().GetBindings(); + rBindings.Invalidate( SID_STATUS_SUM ); // always together with the input row + rBindings.Invalidate( SID_ATTR_SIZE ); + rBindings.Invalidate( SID_TABLE_CELL ); +} + +void ScTabViewShell::UpdateInputHandlerCellAdjust( SvxCellHorJustify eJust ) +{ + if( ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : SC_MOD()->GetInputHdl() ) + pHdl->UpdateCellAdjust( eJust ); +} + +void ScTabViewShell::ExecuteSave( SfxRequest& rReq ) +{ + // only SID_SAVEDOC / SID_SAVEASDOC + bool bCommitChanges = true; + const SfxItemSet* pReqArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + + if (pReqArgs && pReqArgs->HasItem(FN_PARAM_1, &pItem)) + bCommitChanges = !static_cast<const SfxBoolItem*>(pItem)->GetValue(); + + // Finish entering unless 'DontTerminateEdit' is specified, even if a formula is being processed + if (bCommitChanges) + { + bool bLOKActive = comphelper::LibreOfficeKit::isActive(); + + // Disable error dialog box when about to save in lok mode as + // this ultimately invokes SvpSalInstance::DoYield() when we want + // to save immediately without committing any erroneous input in possibly + // a cell with validation rules. After save is complete the user + // can continue editing. + SC_MOD()->InputEnterHandler(ScEnterMode::NORMAL, bLOKActive /* bBeforeSavingInLOK */); + + if (bLOKActive) + { + // Normally this isn't needed, but in Calc when editing a cell formula + // and manually saving (without changing cells or hitting enter), while + // InputEnterHandler will mark the doc as modified (when it is), because + // we will save the doc immediately afterwards, the modified state event + // is clobbered. To avoid that, we need to update SID_DOC_MODIFIED so that + // a possible state of "true" after "InputEnterHandler" will be sent + // as a notification. It is important that the notification goes through + // normal process (cache) rather than directly notifying the views. + // Otherwise, because there is a previous state of "false" in cache, the + // "false" state after saving will be ignored. + // This will work only if .uno:ModifiedStatus message will be removed from + // the mechanism that keeps in the message queue only last message of + // a particular status even if the values are different. + GetViewData().GetDocShell()->GetViewBindings()->Update(SID_DOC_MODIFIED); + } + } + + if ( GetViewData().GetDocShell()->IsDocShared() ) + { + GetViewData().GetDocShell()->SetDocumentModified(); + } + + // otherwise as normal + GetViewData().GetDocShell()->ExecuteSlot( rReq ); +} + +void ScTabViewShell::GetSaveState( SfxItemSet& rSet ) +{ + SfxShell* pDocSh = GetViewData().GetDocShell(); + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + while( nWhich ) + { + if ( nWhich != SID_SAVEDOC || !GetViewData().GetDocShell()->IsDocShared() ) + { + // get state from DocShell + pDocSh->GetSlotState( nWhich, nullptr, &rSet ); + } + nWhich = aIter.NextWhich(); + } +} + +void ScTabViewShell::ExecDrawOpt( const SfxRequest& rReq ) +{ + ScViewOptions aViewOptions = GetViewData().GetOptions(); + ScGridOptions aGridOptions = aViewOptions.GetGridOptions(); + + SfxBindings& rBindings = GetViewFrame().GetBindings(); + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + sal_uInt16 nSlotId = rReq.GetSlot(); + switch (nSlotId) + { + case SID_GRID_VISIBLE: + if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET ) + { + aGridOptions.SetGridVisible( static_cast<const SfxBoolItem*>(pItem)->GetValue() ); + aViewOptions.SetGridOptions(aGridOptions); + rBindings.Invalidate(SID_GRID_VISIBLE); + } + break; + + case SID_GRID_USE: + if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET ) + { + aGridOptions.SetUseGridSnap( static_cast<const SfxBoolItem*>(pItem)->GetValue() ); + aViewOptions.SetGridOptions(aGridOptions); + rBindings.Invalidate(SID_GRID_USE); + } + break; + + case SID_HELPLINES_MOVE: + if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET ) + { + aViewOptions.SetOption( VOPT_HELPLINES, static_cast<const SfxBoolItem*>(pItem)->GetValue() ); + rBindings.Invalidate(SID_HELPLINES_MOVE); + } + break; + } + + GetViewData().SetOptions(aViewOptions); +} + +void ScTabViewShell::GetDrawOptState( SfxItemSet& rSet ) +{ + SfxBoolItem aBool; + + const ScViewOptions& rViewOptions = GetViewData().GetOptions(); + const ScGridOptions& rGridOptions = rViewOptions.GetGridOptions(); + + aBool.SetValue(rGridOptions.GetGridVisible()); + aBool.SetWhich( SID_GRID_VISIBLE ); + rSet.Put( aBool ); + + aBool.SetValue(rGridOptions.GetUseGridSnap()); + aBool.SetWhich( SID_GRID_USE ); + rSet.Put( aBool ); + + aBool.SetValue(rViewOptions.GetOption( VOPT_HELPLINES )); + aBool.SetWhich( SID_HELPLINES_MOVE ); + rSet.Put( aBool ); +} + +void ScTabViewShell::ExecStyle( SfxRequest& rReq ) +{ + const SfxItemSet* pArgs = rReq.GetArgs(); + const sal_uInt16 nSlotId = rReq.GetSlot(); + if ( !pArgs && nSlotId != SID_STYLE_NEW_BY_EXAMPLE && nSlotId != SID_STYLE_UPDATE_BY_EXAMPLE ) + { + // in case of vertical toolbar + GetDispatcher()->Execute( SID_STYLE_DESIGNER, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD ); + return; + } + + SfxBindings& rBindings = GetViewData().GetBindings(); + const SCTAB nCurTab = GetViewData().GetTabNo(); + ScDocShell* pDocSh = GetViewData().GetDocShell(); + ScDocument& rDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData().GetMarkData(); + ScModule* pScMod = SC_MOD(); + SdrObject* pEditObject = GetDrawView()->GetTextEditObject(); + OutlinerView* pOLV = GetDrawView()->GetTextEditOutlinerView(); + ESelection aSelection = pOLV ? pOLV->GetSelection() : ESelection(); + OUString aRefName; + bool bUndo = rDoc.IsUndoEnabled(); + + SfxStyleSheetBasePool* pStylePool = rDoc.GetStyleSheetPool(); + SfxStyleSheetBase* pStyleSheet = nullptr; + + bool bStyleToMarked = false; + bool bListAction = false; + bool bAddUndo = false; // add ScUndoModifyStyle (style modified) + ScStyleSaveData aOldData; // for undo/redo + ScStyleSaveData aNewData; + + SfxStyleFamily eFamily = SfxStyleFamily::Para; + const SfxUInt16Item* pFamItem; + const SfxStringItem* pFamilyNameItem; + if ( pArgs && (pFamItem = pArgs->GetItemIfSet( SID_STYLE_FAMILY )) ) + eFamily = static_cast<SfxStyleFamily>(pFamItem->GetValue()); + else if ( pArgs && (pFamilyNameItem = pArgs->GetItemIfSet( SID_STYLE_FAMILYNAME )) ) + { + OUString sFamily = pFamilyNameItem->GetValue(); + if (sFamily == "CellStyles") + eFamily = SfxStyleFamily::Para; + else if (sFamily == "PageStyles") + eFamily = SfxStyleFamily::Page; + else if (sFamily == "GraphicStyles") + eFamily = SfxStyleFamily::Frame; + } + + OUString aStyleName; + sal_uInt16 nRetMask = 0xffff; + + switch ( nSlotId ) + { + case SID_STYLE_NEW: + { + const SfxPoolItem* pNameItem; + if (pArgs && SfxItemState::SET == pArgs->GetItemState( nSlotId, true, &pNameItem )) + aStyleName = static_cast<const SfxStringItem*>(pNameItem)->GetValue(); + + const SfxStringItem* pRefItem=nullptr; + if (pArgs && (pRefItem = pArgs->GetItemIfSet( SID_STYLE_REFERENCE ))) + { + aRefName = pRefItem->GetValue(); + } + + pStyleSheet = &(pStylePool->Make( aStyleName, eFamily, + SfxStyleSearchBits::UserDefined ) ); + + if (pStyleSheet->HasParentSupport()) + pStyleSheet->SetParent(aRefName); + } + break; + + case SID_STYLE_APPLY: + { + const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(SID_APPLY_STYLE); + const SfxStringItem* pFamilyItem = rReq.GetArg<SfxStringItem>(SID_STYLE_FAMILYNAME); + if ( pFamilyItem && pNameItem ) + { + try + { + css::uno::Reference< css::container::XNameAccess > xStyles; + css::uno::Reference< css::container::XNameAccess > xCont = pDocSh->GetModel()->getStyleFamilies(); + xCont->getByName(pFamilyItem->GetValue()) >>= xStyles; + css::uno::Reference< css::beans::XPropertySet > xInfo; + xStyles->getByName( pNameItem->GetValue() ) >>= xInfo; + OUString aUIName; + xInfo->getPropertyValue("DisplayName") >>= aUIName; + if ( !aUIName.isEmpty() ) + rReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aUIName ) ); + } + catch( css::uno::Exception& ) + { + } + } + [[fallthrough]]; + } + case SID_STYLE_EDIT: + case SID_STYLE_DELETE: + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + case SID_STYLE_NEW_BY_EXAMPLE: + { + const SfxPoolItem* pNameItem; + if (pArgs && SfxItemState::SET == pArgs->GetItemState( nSlotId, true, &pNameItem )) + aStyleName = static_cast<const SfxStringItem*>(pNameItem)->GetValue(); + else if ( nSlotId == SID_STYLE_NEW_BY_EXAMPLE ) + { + weld::Window* pDialogParent = rReq.GetFrameWeld(); + if (!pDialogParent) + pDialogParent = GetFrameWeld(); + SfxNewStyleDlg aDlg(pDialogParent, *pStylePool, eFamily); + if (aDlg.run() != RET_OK) + return; + aStyleName = aDlg.GetName(); + } + + pStyleSheet = pStylePool->Find( aStyleName, eFamily ); + + aOldData.InitFromStyle( pStyleSheet ); + } + break; + + case SID_STYLE_WATERCAN: + { + bool bWaterCan = pScMod->GetIsWaterCan(); + + if( !bWaterCan ) + { + const SfxPoolItem* pItem; + + if ( SfxItemState::SET == + pArgs->GetItemState( nSlotId, true, &pItem ) ) + { + const SfxStringItem* pStrItem = dynamic_cast< const SfxStringItem *>( pItem ); + if ( pStrItem ) + { + aStyleName = pStrItem->GetValue(); + pStyleSheet = pStylePool->Find( aStyleName, eFamily ); + + if ( pStyleSheet ) + { + static_cast<ScStyleSheetPool*>(pStylePool)-> + SetActualStyleSheet( pStyleSheet ); + rReq.Done(); + } + } + } + } + + if ( !bWaterCan && pStyleSheet ) + { + pScMod->SetWaterCan( true ); + SetActivePointer( PointerStyle::Fill ); + rReq.Done(); + } + else + { + pScMod->SetWaterCan( false ); + SetActivePointer( PointerStyle::Arrow ); + rReq.Done(); + } + } + break; + + default: + break; + } + + // set new style for paintbrush format mode + if ( nSlotId == SID_STYLE_APPLY && pScMod->GetIsWaterCan() && pStyleSheet ) + static_cast<ScStyleSheetPool*>(pStylePool)->SetActualStyleSheet( pStyleSheet ); + + switch ( eFamily ) + { + case SfxStyleFamily::Para: + { + switch ( nSlotId ) + { + case SID_STYLE_DELETE: + { + if ( pStyleSheet ) + { + RemoveStyleSheetInUse( pStyleSheet ); + pStylePool->Remove( pStyleSheet ); + InvalidateAttribs(); + nRetMask = sal_uInt16(true); + bAddUndo = true; + rReq.Done(); + } + else + nRetMask = sal_uInt16(false); + } + break; + + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + { + if ( pStyleSheet ) + { + pStyleSheet->SetHidden( nSlotId == SID_STYLE_HIDE ); + InvalidateAttribs(); + rReq.Done(); + } + else + nRetMask = sal_uInt16(false); + } + break; + + case SID_STYLE_APPLY: + { + if ( pStyleSheet && !pScMod->GetIsWaterCan() ) + { + // apply style sheet to document + SetStyleSheetToMarked( static_cast<SfxStyleSheet*>(pStyleSheet) ); + InvalidateAttribs(); + rReq.Done(); + } + } + break; + + case SID_STYLE_NEW_BY_EXAMPLE: + case SID_STYLE_UPDATE_BY_EXAMPLE: + { + // create/replace style sheet by attributes + // at cursor position: + + const ScPatternAttr* pAttrItem = nullptr; + + // The query if marked, was always wrong here, + // so now no more, and just from the cursor. + // If attributes are to be removed from the selection, still need to be + // cautious not to adopt items from templates + // (GetSelectionPattern also collects items from originals) (# 44748 #) + SCCOL nCol = GetViewData().GetCurX(); + SCROW nRow = GetViewData().GetCurY(); + pAttrItem = rDoc.GetPattern( nCol, nRow, nCurTab ); + + SfxItemSet aAttrSet = pAttrItem->GetItemSet(); + aAttrSet.ClearItem( ATTR_MERGE ); + aAttrSet.ClearItem( ATTR_MERGE_FLAG ); + + // Do not adopt conditional formatting and validity, + // because they can not be edited in the template + aAttrSet.ClearItem( ATTR_VALIDDATA ); + aAttrSet.ClearItem( ATTR_CONDITIONAL ); + + if ( SID_STYLE_NEW_BY_EXAMPLE == nSlotId ) + { + if ( bUndo ) + { + OUString aUndo = ScResId( STR_UNDO_EDITCELLSTYLE ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo, 0, GetViewShellId() ); + bListAction = true; + } + + bool bConvertBack = false; + SfxStyleSheet* pSheetInUse = const_cast<SfxStyleSheet*>(GetStyleSheetFromMarked()); + + // when a new style is present and is used in the selection, + // then the parent can not be adopted: + if ( pStyleSheet && pSheetInUse && pStyleSheet == pSheetInUse ) + pSheetInUse = nullptr; + + // if already present, first remove ... + if ( pStyleSheet ) + { + // style pointer to names before erase, + // otherwise cells will get invalid pointer + //!!! As it happens, a method that does it for a particular style + rDoc.StylesToNames(); + bConvertBack = true; + pStylePool->Remove(pStyleSheet); + } + + // ...and create new + pStyleSheet = &pStylePool->Make( aStyleName, eFamily, + SfxStyleSearchBits::UserDefined ); + + // when a style is present, then this will become + // the parent of the new style: + if ( pSheetInUse && pStyleSheet->HasParentSupport() ) + pStyleSheet->SetParent( pSheetInUse->GetName() ); + + if ( bConvertBack ) + // Name to style pointer + rDoc.UpdStlShtPtrsFrmNms(); + else + rDoc.GetPool()->CellStyleCreated( aStyleName, rDoc ); + + // Adopt attribute and use style + pStyleSheet->GetItemSet().Put( aAttrSet ); + UpdateStyleSheetInUse( pStyleSheet ); + + // call SetStyleSheetToMarked after adding the ScUndoModifyStyle + // (pStyleSheet pointer is used!) + bStyleToMarked = true; + } + else // ( nSlotId == SID_STYLE_UPDATE_BY_EXAMPLE ) + { + pStyleSheet = const_cast<SfxStyleSheet*>(GetStyleSheetFromMarked()); + + if ( pStyleSheet ) + { + aOldData.InitFromStyle( pStyleSheet ); + + if ( bUndo ) + { + OUString aUndo = ScResId( STR_UNDO_EDITCELLSTYLE ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo, 0, GetViewShellId() ); + bListAction = true; + } + + pStyleSheet->GetItemSet().Put( aAttrSet ); + UpdateStyleSheetInUse( pStyleSheet ); + + // call SetStyleSheetToMarked after adding the ScUndoModifyStyle + // (pStyleSheet pointer is used!) + bStyleToMarked = true; + } + } + + aNewData.InitFromStyle( pStyleSheet ); + bAddUndo = true; + rReq.Done(); + } + break; + + default: + break; + } + } // case SfxStyleFamily::Para: + break; + + case SfxStyleFamily::Page: + { + switch ( nSlotId ) + { + case SID_STYLE_DELETE: + { + nRetMask = sal_uInt16( nullptr != pStyleSheet ); + if ( pStyleSheet ) + { + if ( rDoc.RemovePageStyleInUse( pStyleSheet->GetName() ) ) + { + ScPrintFunc( pDocSh, GetPrinter(true), nCurTab ).UpdatePages(); + rBindings.Invalidate( SID_STATUS_PAGESTYLE ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + } + pStylePool->Remove( pStyleSheet ); + rBindings.Invalidate( SID_STYLE_FAMILY4 ); + pDocSh->SetDocumentModified(); + bAddUndo = true; + rReq.Done(); + } + } + break; + + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + { + nRetMask = sal_uInt16( nullptr != pStyleSheet ); + if ( pStyleSheet ) + { + pStyleSheet->SetHidden( nSlotId == SID_STYLE_HIDE ); + rBindings.Invalidate( SID_STYLE_FAMILY4 ); + pDocSh->SetDocumentModified(); + rReq.Done(); + } + } + break; + + case SID_STYLE_APPLY: + { + nRetMask = sal_uInt16( nullptr != pStyleSheet ); + if ( pStyleSheet && !pScMod->GetIsWaterCan() ) + { + std::unique_ptr<ScUndoApplyPageStyle> pUndoAction; + SCTAB nTabCount = rDoc.GetTableCount(); + for (const auto& rTab : rMark) + { + if (rTab >= nTabCount) + break; + OUString aOldName = rDoc.GetPageStyle( rTab ); + if ( aOldName != aStyleName ) + { + rDoc.SetPageStyle( rTab, aStyleName ); + ScPrintFunc( pDocSh, GetPrinter(true), rTab ).UpdatePages(); + if( !pUndoAction ) + pUndoAction.reset(new ScUndoApplyPageStyle( pDocSh, aStyleName )); + pUndoAction->AddSheetAction( rTab, aOldName ); + } + } + if( pUndoAction ) + { + pDocSh->GetUndoManager()->AddUndoAction( std::move(pUndoAction) ); + pDocSh->SetDocumentModified(); + rBindings.Invalidate( SID_STYLE_FAMILY4 ); + rBindings.Invalidate( SID_STATUS_PAGESTYLE ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + } + rReq.Done(); + } + } + break; + + case SID_STYLE_NEW_BY_EXAMPLE: + { + const OUString& rStrCurStyle = rDoc.GetPageStyle( nCurTab ); + + if ( rStrCurStyle != aStyleName ) + { + SfxStyleSheetBase* pCurStyle = pStylePool->Find( rStrCurStyle, eFamily ); + SfxItemSet aAttrSet = pCurStyle->GetItemSet(); + SCTAB nInTab; + bool bUsed = rDoc.IsPageStyleInUse( aStyleName, &nInTab ); + + // if already present, first remove... + if ( pStyleSheet ) + pStylePool->Remove( pStyleSheet ); + + // ...and create new + pStyleSheet = &pStylePool->Make( aStyleName, eFamily, + SfxStyleSearchBits::UserDefined ); + + // Adopt attribute + pStyleSheet->GetItemSet().Put( aAttrSet ); + pDocSh->SetDocumentModified(); + + // If being used -> Update + if ( bUsed ) + ScPrintFunc( pDocSh, GetPrinter(true), nInTab ).UpdatePages(); + + aNewData.InitFromStyle( pStyleSheet ); + bAddUndo = true; + rReq.Done(); + nRetMask = sal_uInt16(true); + } + } + break; + + default: + break; + } // switch ( nSlotId ) + } // case SfxStyleFamily::Page: + break; + + case SfxStyleFamily::Frame: + { + switch ( nSlotId ) + { + case SID_STYLE_DELETE: + { + if ( pStyleSheet ) + { + pStylePool->Remove( pStyleSheet ); + InvalidateAttribs(); + pDocSh->SetDocumentModified(); + nRetMask = sal_uInt16(true); + bAddUndo = true; + rReq.Done(); + } + else + nRetMask = sal_uInt16(false); + } + break; + + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + { + if ( pStyleSheet ) + { + pStyleSheet->SetHidden( nSlotId == SID_STYLE_HIDE ); + InvalidateAttribs(); + rReq.Done(); + } + else + nRetMask = sal_uInt16(false); + } + break; + + case SID_STYLE_APPLY: + { + if ( pStyleSheet && !pScMod->GetIsWaterCan() ) + { + GetScDrawView()->ScEndTextEdit(); + GetScDrawView()->SetStyleSheet(static_cast<SfxStyleSheet*>(pStyleSheet), false); + + GetScDrawView()->InvalidateAttribs(); + InvalidateAttribs(); + rReq.Done(); + } + } + break; + + case SID_STYLE_NEW_BY_EXAMPLE: + case SID_STYLE_UPDATE_BY_EXAMPLE: + { + if (nSlotId == SID_STYLE_NEW_BY_EXAMPLE) + { + pStyleSheet = &pStylePool->Make( aStyleName, eFamily, SfxStyleSearchBits::UserDefined ); + + // when a style is present, then this will become + // the parent of the new style: + if (SfxStyleSheet* pOldStyle = GetDrawView()->GetStyleSheet()) + pStyleSheet->SetParent(pOldStyle->GetName()); + } + else + { + pStyleSheet = GetDrawView()->GetStyleSheet(); + aOldData.InitFromStyle( pStyleSheet ); + } + + if ( bUndo ) + { + OUString aUndo = ScResId( STR_UNDO_EDITGRAPHICSTYLE ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo, 0, GetViewShellId() ); + bListAction = true; + } + + SfxItemSet aCoreSet(GetDrawView()->GetModel().GetItemPool()); + GetDrawView()->GetAttributes(aCoreSet, true); + + SfxItemSet* pStyleSet = &pStyleSheet->GetItemSet(); + pStyleSet->Put(aCoreSet); + static_cast<SfxStyleSheet*>(pStyleSheet)->Broadcast(SfxHint(SfxHintId::DataChanged)); + + aNewData.InitFromStyle( pStyleSheet ); + bAddUndo = true; + + // call SetStyleSheet after adding the ScUndoModifyStyle + // (pStyleSheet pointer is used!) + bStyleToMarked = true; + rReq.Done(); + } + break; + default: + break; + } + } + break; + default: + break; + } // switch ( eFamily ) + + // create new or process through Dialog: + if ( nSlotId == SID_STYLE_NEW || nSlotId == SID_STYLE_EDIT ) + { + if ( pStyleSheet ) + { + SfxStyleFamily eFam = pStyleSheet->GetFamily(); + ScopedVclPtr<SfxAbstractTabDialog> pDlg; + bool bPage = false; + + // Store old Items from the style + SfxItemSet aOldSet = pStyleSheet->GetItemSet(); + OUString aOldName = pStyleSheet->GetName(); + + switch ( eFam ) + { + case SfxStyleFamily::Page: + bPage = true; + break; + + case SfxStyleFamily::Para: + { + SfxItemSet& rSet = pStyleSheet->GetItemSet(); + + if ( const SfxUInt32Item* pItem = rSet.GetItemIfSet( ATTR_VALUE_FORMAT, + false ) ) + { + // Produce and format NumberFormat Value from Value and Language + sal_uLong nFormat = pItem->GetValue(); + LanguageType eLang = + rSet.Get(ATTR_LANGUAGE_FORMAT ).GetLanguage(); + sal_uLong nLangFormat = rDoc.GetFormatTable()-> + GetFormatForLanguageIfBuiltIn( nFormat, eLang ); + if ( nLangFormat != nFormat ) + { + SfxUInt32Item aNewItem( ATTR_VALUE_FORMAT, nLangFormat ); + rSet.Put( aNewItem ); + aOldSet.Put( aNewItem ); + // Also in aOldSet for comparison after the dialog, + // Otherwise might miss a language change + } + } + + std::unique_ptr<SvxNumberInfoItem> pNumberInfoItem( + ScTabViewShell::MakeNumberInfoItem(rDoc, GetViewData())); + + pDocSh->PutItem( *pNumberInfoItem ); + bPage = false; + + // Definitely a SvxBoxInfoItem with Table = sal_False in set: + // (If there is no item, the dialogue will also delete the + // BORDER_OUTER SvxBoxItem from the Template Set) + if ( rSet.GetItemState( ATTR_BORDER_INNER, false ) != SfxItemState::SET ) + { + SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER ); + aBoxInfoItem.SetTable(false); // no inner lines + aBoxInfoItem.SetDist(true); + aBoxInfoItem.SetMinDist(false); + rSet.Put( aBoxInfoItem ); + } + } + break; + + case SfxStyleFamily::Frame: + default: + break; + } + + SetInFormatDialog(true); + + SfxItemSet& rStyleSet = pStyleSheet->GetItemSet(); + rStyleSet.MergeRange( XATTR_FILL_FIRST, XATTR_FILL_LAST ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + + weld::Window* pDialogParent = rReq.GetFrameWeld(); + if (!pDialogParent) + pDialogParent = GetFrameWeld(); + + if (eFam == SfxStyleFamily::Frame) + pDlg.disposeAndReset(pFact->CreateScDrawStyleDlg(pDialogParent, *pStyleSheet, GetDrawView())); + else + pDlg.disposeAndReset(pFact->CreateScStyleDlg(pDialogParent, *pStyleSheet, bPage)); + + short nResult = pDlg->Execute(); + SetInFormatDialog(false); + + if ( nResult == RET_OK ) + { + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + + if ( pOutSet ) + { + nRetMask = sal_uInt16(pStyleSheet->GetMask()); + + // Attribute comparisons (earlier in ModifyStyleSheet) now here + // with the old values (the style is already changed) + if ( SfxStyleFamily::Para == eFam ) + { + SfxItemSet& rNewSet = pStyleSheet->GetItemSet(); + bool bNumFormatChanged; + if ( ScGlobal::CheckWidthInvalidate( + bNumFormatChanged, rNewSet, aOldSet ) ) + rDoc.InvalidateTextWidth( nullptr, nullptr, bNumFormatChanged ); + + SCTAB nTabCount = rDoc.GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + rDoc.SetStreamValid(nTab, false); + + sal_uLong nOldFormat = aOldSet.Get( ATTR_VALUE_FORMAT ).GetValue(); + sal_uLong nNewFormat = rNewSet.Get( ATTR_VALUE_FORMAT ).GetValue(); + if ( nNewFormat != nOldFormat ) + { + SvNumberFormatter* pFormatter = rDoc.GetFormatTable(); + const SvNumberformat* pOld = pFormatter->GetEntry( nOldFormat ); + const SvNumberformat* pNew = pFormatter->GetEntry( nNewFormat ); + if ( pOld && pNew && pOld->GetLanguage() != pNew->GetLanguage() ) + rNewSet.Put( SvxLanguageItem( + pNew->GetLanguage(), ATTR_LANGUAGE_FORMAT ) ); + } + + rDoc.GetPool()->CellStyleCreated( pStyleSheet->GetName(), rDoc ); + } + else if ( SfxStyleFamily::Page == eFam ) + { + //! Here also queries for Page Styles + + OUString aNewName = pStyleSheet->GetName(); + if ( aNewName != aOldName && + rDoc.RenamePageStyleInUse( aOldName, aNewName ) ) + { + rBindings.Invalidate( SID_STATUS_PAGESTYLE ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + } + + rDoc.ModifyStyleSheet( *pStyleSheet, *pOutSet ); + rBindings.Invalidate( FID_RESET_PRINTZOOM ); + } + else + { + SfxItemSet& rAttr = pStyleSheet->GetItemSet(); + sdr::properties::CleanupFillProperties(rAttr); + + // check for unique names of named items for xml + auto checkForUniqueItem = [&] (auto nWhichId) + { + if (auto pOldItem = rAttr.GetItemIfSet(nWhichId, false)) + { + if (auto pNewItem = pOldItem->checkForUniqueItem(&GetDrawView()->GetModel())) + rAttr.Put(std::move(pNewItem)); + } + }; + + checkForUniqueItem(XATTR_FILLBITMAP); + checkForUniqueItem(XATTR_LINEDASH); + checkForUniqueItem(XATTR_LINESTART); + checkForUniqueItem(XATTR_LINEEND); + checkForUniqueItem(XATTR_FILLGRADIENT); + checkForUniqueItem(XATTR_FILLFLOATTRANSPARENCE); + checkForUniqueItem(XATTR_FILLHATCH); + + static_cast<SfxStyleSheet*>(pStyleSheet)->Broadcast(SfxHint(SfxHintId::DataChanged)); + GetScDrawView()->InvalidateAttribs(); + } + + pDocSh->SetDocumentModified(); + + if ( SfxStyleFamily::Para == eFam ) + { + ScTabViewShell::UpdateNumberFormatter( + *( pDocSh->GetItem(SID_ATTR_NUMBERFORMAT_INFO) )); + + UpdateStyleSheetInUse( pStyleSheet ); + InvalidateAttribs(); + } + + aNewData.InitFromStyle( pStyleSheet ); + bAddUndo = true; + } + } + else + { + if ( nSlotId == SID_STYLE_NEW ) + pStylePool->Remove( pStyleSheet ); + else + { + // If in the meantime something was painted with the + // temporary changed item set + pDocSh->PostPaintGridAll(); + } + } + } + } + + rReq.SetReturnValue( SfxUInt16Item( nSlotId, nRetMask ) ); + + if ( bAddUndo && bUndo) + pDocSh->GetUndoManager()->AddUndoAction( + std::make_unique<ScUndoModifyStyle>( pDocSh, eFamily, aOldData, aNewData ) ); + + if ( bStyleToMarked ) + { + // call SetStyleSheetToMarked after adding the ScUndoModifyStyle, + // so redo will find the modified style + if (eFamily == SfxStyleFamily::Para) + { + SetStyleSheetToMarked( static_cast<SfxStyleSheet*>(pStyleSheet) ); + } + else if (eFamily == SfxStyleFamily::Frame) + { + GetScDrawView()->ScEndTextEdit(); + GetScDrawView()->SetStyleSheet( static_cast<SfxStyleSheet*>(pStyleSheet), false ); + } + InvalidateAttribs(); + } + + if ( bListAction ) + pDocSh->GetUndoManager()->LeaveListAction(); + + // The above call to ScEndTextEdit left us in an inconsistent state: + // Text editing isn't active, but the text edit shell still is. And we + // couldn't just deactivate it fully, because in case of editing a + // comment, that will make the comment disappear. So let's try to + // reactivate text editing instead: + auto pFuText = dynamic_cast<FuText*>(GetDrawFuncPtr()); + if (pFuText && pEditObject != GetDrawView()->GetTextEditObject()) + { + pFuText->SetInEditMode(pEditObject); + if (GetDrawView()->GetTextEditOutlinerView()) + GetDrawView()->GetTextEditOutlinerView()->SetSelection(aSelection); + } +} + +void ScTabViewShell::GetStyleState( SfxItemSet& rSet ) +{ + ScDocument& rDoc = GetViewData().GetDocument(); + SfxStyleSheetBasePool* pStylePool = rDoc.GetStyleSheetPool(); + + bool bProtected = false; + SCTAB nTabCount = rDoc.GetTableCount(); + for (SCTAB i=0; i<nTabCount && !bProtected; i++) + if (rDoc.IsTabProtected(i)) // look after protected table + bProtected = true; + + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + sal_uInt16 nSlotId = 0; + + while ( nWhich ) + { + nSlotId = SfxItemPool::IsWhich( nWhich ) + ? GetPool().GetSlotId( nWhich ) + : nWhich; + + switch ( nSlotId ) + { + case SID_STYLE_APPLY: + if ( !pStylePool ) + rSet.DisableItem( nSlotId ); + break; + + case SID_STYLE_FAMILY2: // cell style sheets + { + SfxStyleSheet* pStyleSheet = const_cast<SfxStyleSheet*>(GetStyleSheetFromMarked()); + + if ( pStyleSheet ) + rSet.Put( SfxTemplateItem( nSlotId, pStyleSheet->GetName() ) ); + else + rSet.Put( SfxTemplateItem( nSlotId, OUString() ) ); + } + break; + + case SID_STYLE_FAMILY3: // drawing style sheets + { + SfxStyleSheet* pStyleSheet = GetDrawView()->GetStyleSheet(); + + if ( pStyleSheet ) + rSet.Put( SfxTemplateItem( nSlotId, pStyleSheet->GetName() ) ); + else + rSet.Put( SfxTemplateItem( nSlotId, OUString() ) ); + } + break; + + case SID_STYLE_FAMILY4: // page style sheets + { + SCTAB nCurTab = GetViewData().GetTabNo(); + OUString aPageStyle = rDoc.GetPageStyle( nCurTab ); + SfxStyleSheet* pStyleSheet = pStylePool ? static_cast<SfxStyleSheet*>(pStylePool-> + Find( aPageStyle, SfxStyleFamily::Page )) : nullptr; + + if ( pStyleSheet ) + rSet.Put( SfxTemplateItem( nSlotId, aPageStyle ) ); + else + rSet.Put( SfxTemplateItem( nSlotId, OUString() ) ); + } + break; + + case SID_STYLE_WATERCAN: + { + rSet.Put( SfxBoolItem( nSlotId, SC_MOD()->GetIsWaterCan() ) ); + } + break; + + case SID_STYLE_UPDATE_BY_EXAMPLE: + { + std::unique_ptr<SfxUInt16Item> pFamilyItem; + GetViewFrame().GetBindings().QueryState(SID_STYLE_FAMILY, pFamilyItem); + + bool bPage = pFamilyItem && SfxStyleFamily::Page == static_cast<SfxStyleFamily>(pFamilyItem->GetValue()); + + if ( bProtected || bPage ) + rSet.DisableItem( nSlotId ); + } + break; + + case SID_STYLE_EDIT: + case SID_STYLE_DELETE: + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + { + std::unique_ptr<SfxUInt16Item> pFamilyItem; + GetViewFrame().GetBindings().QueryState(SID_STYLE_FAMILY, pFamilyItem); + bool bPage = pFamilyItem && SfxStyleFamily::Page == static_cast<SfxStyleFamily>(pFamilyItem->GetValue()); + + if ( bProtected && !bPage ) + rSet.DisableItem( nSlotId ); + } + break; + + default: + break; + } + + nWhich = aIter.NextWhich(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |