/* -*- 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 .
*/
ScModule::ScModule( SfxObjectFactory* pFact ) :
SfxModule("sc"_ostr, {pFact}),
m_aIdleTimer("sc ScModule IdleTimer"),
m_pDragData(new ScDragData),
m_pSelTransfer( nullptr ),
m_pRefInputHandler( nullptr ),
m_nCurRefDlgId( 0 ),
m_bIsWaterCan( false ),
m_bIsInEditCommand( false ),
m_bIsInExecuteDrop( false ),
m_bIsInSharedDocLoading( false ),
m_bIsInSharedDocSaving( false )
{ // The ResManager (DLL data) is not yet initialized in the ctor!
SetName(u"StarCalc"_ustr); // for Basic
ResetDragObject();
// InputHandler does not need to be created
// Create ErrorHandler - was in Init() // Between OfficeApplication::Init and ScGlobal::Init
SvxErrorHandler::ensure();
m_pErrorHdl.reset( new SfxErrorHandler(RID_ERRHDLSC,
ErrCodeArea::Sc,
ErrCodeArea::Sc,
GetResLocale()) );
m_pMessagePool = new ScMessagePool;
SetPool( m_pMessagePool.get() );
ScGlobal::InitTextHeight( *m_pMessagePool );
StartListening( *SfxGetpApp() ); // for SfxHintId::Deinitializing
// Initialize the color config
GetColorConfig();
}
ScModule::~ScModule()
{
OSL_ENSURE( !m_pSelTransfer, "Selection Transfer object not deleted" );
// InputHandler does not need to be deleted (there's none in the App anymore)
m_pMessagePool.clear();
m_pDragData.reset();
m_pErrorHdl.reset();
ScGlobal::Clear(); // Also calls ScDocumentPool::DeleteVersionMaps();
ScInterpreterContextPool::ModuleExiting();
DeleteCfg(); // Called from Exit()
}
void ScModule::ConfigurationChanged(utl::ConfigurationBroadcaster* p, ConfigurationHints eHints)
{ if ( p == m_pColorConfig.get() )
{ // Test if detective objects have to be updated with new colors // (if the detective colors haven't been used yet, there's nothing to update) if ( ScDetectiveFunc::IsColorsInitialized() )
{ const svtools::ColorConfig& rColors = GetColorConfig(); bool bArrows =
( ScDetectiveFunc::GetArrowColor() != rColors.GetColorValue(svtools::CALCDETECTIVE).nColor ||
ScDetectiveFunc::GetErrorColor() != rColors.GetColorValue(svtools::CALCDETECTIVEERROR).nColor ); bool bComments =
( ScDetectiveFunc::GetCommentColor() != rColors.GetColorValue(svtools::CALCNOTESBACKGROUND).nColor ); if ( bArrows || bComments )
{
ScDetectiveFunc::InitializeColors(); // get the new colors
// update detective objects in all open documents
SfxObjectShell* pObjSh = SfxObjectShell::GetFirst(); while ( pObjSh )
{ if ( auto pDocSh = dynamic_cast<ScDocShell * >(pObjSh) )
{ if ( bArrows )
ScDetectiveFunc( pDocSh->GetDocument(), 0 ).UpdateAllArrowColors(); if ( bComments )
ScDetectiveFunc::UpdateAllComments( pDocSh->GetDocument() );
}
pObjSh = SfxObjectShell::GetNext( *pObjSh );
}
}
}
//invalidate only the current view in tiled rendering mode, or all views otherwise
SfxViewShell* pViewShell = bKit ? SfxViewShell::Current() : SfxViewShell::GetFirst(); while (pViewShell)
{ if (ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(pViewShell))
{
ScViewRenderingOptions aViewRenderingOptions(pViewSh->GetViewRenderingData());
Color aFillColor(m_pColorConfig->GetColorValue(svtools::DOCCOLOR).nColor);
aViewRenderingOptions.SetDocColor(aFillColor);
aViewRenderingOptions.SetColorSchemeName(svtools::ColorConfig::GetCurrentSchemeName()); constbool bUnchanged(aViewRenderingOptions == pViewSh->GetViewRenderingData()); if (!bUnchanged)
pViewSh->SetViewRenderingData(aViewRenderingOptions);
if (SfxObjectShell* pKitCurrentObjSh = bKit ? SfxObjectShell::Current() : nullptr)
{
ScModelObj* pScModelObj = comphelper::getFromUnoTunnel<ScModelObj>(pKitCurrentObjSh->GetModel());
SfxLokHelper::notifyViewRenderState(pViewSh, pScModelObj); // In Online, the document color is the one used for the background, contrary to // Writer and Draw that use the application background color.
pViewSh->libreOfficeKitViewCallback(LOK_CALLBACK_APPLICATION_BACKGROUND_COLOR,
aFillColor.AsRGBHexString().toUtf8());
}
// if nothing changed, and the hint was OnlyCurrentDocumentColorScheme we can skip invalidate constbool bSkipInvalidate = bKit ||(bUnchanged && eHints == ConfigurationHints::OnlyCurrentDocumentColorScheme); if (!bSkipInvalidate)
{
pViewSh->PaintGrid();
pViewSh->PaintTop();
pViewSh->PaintLeft();
pViewSh->PaintExtras();
}
ScInputHandler* pHdl = pViewSh->GetInputHandler(); if ( pHdl )
pHdl->ForgetLastPattern(); // EditEngine BackgroundColor may change
} elseif ( dynamic_cast<const ScPreviewShell*>( pViewShell) != nullptr )
{
vcl::Window* pWin = pViewShell->GetWindow(); if (pWin)
pWin->Invalidate();
} if (bKit) break;
pViewShell = SfxViewShell::GetNext( *pViewShell );
}
} elseif ( p == m_pCTLOptions.get() )
{ // for all documents: set digit language for printer, recalc output factor, update row heights
SfxObjectShell* pObjSh = SfxObjectShell::GetFirst(); while ( pObjSh )
{ if ( auto pDocSh = dynamic_cast<ScDocShell *>(pObjSh) )
{
OutputDevice* pPrinter = pDocSh->GetPrinter(); if ( pPrinter )
pPrinter->SetDigitLanguage( GetOptDigitLanguage() );
// for all views (table and preview): update digit language
SfxViewShell* pSh = SfxViewShell::GetFirst(); while ( pSh )
{ if (ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>(pSh))
{ // set ref-device for EditEngine (re-evaluates digit settings)
ScInputHandler* pHdl = GetInputHdl(pViewSh); if (pHdl)
pHdl->UpdateRefDevice();
case SID_ATTR_METRIC:
{ const SfxPoolItem* pItem; if ( pReqArgs && SfxItemState::SET == pReqArgs->GetItemState( nSlot, true, &pItem ) )
{
FieldUnit eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); switch( eUnit )
{ case FieldUnit::MM: // Just the units that are also in the dialog case FieldUnit::CM: case FieldUnit::INCH: case FieldUnit::PICA: case FieldUnit::POINT:
{
PutItem( *pItem );
ScAppOptions aNewOpts( GetAppOptions() );
aNewOpts.SetAppMetric( eUnit );
SetAppOptions( aNewOpts );
rReq.Done();
} break; default:
{ // added to avoid warnings
}
}
}
} break;
SfxWhichIter aIter(rSet); for (sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich())
{ if (!pTabViewShell)
{ // Not in the normal calc view shell (most likely in preview shell). Disable all actions.
rSet.DisableItem(nWhich); continue;
}
const ScTransferObj* pObj = ScTransferObj::GetOwnClipboard(xTransferable); if (pObj)
{
ScDocument* pDoc = pObj->GetDocument();
assert((!pDoc || pDoc->IsClipboard()) && "Document is not clipboard, how can that be?"); return pDoc;
}
sal_uInt16 aIdxList[LRU_MAX];
sal_uInt16 n = 0; bool bFound = false;
while ((n < LRU_MAX) && n<nLRUFuncCount) // Iterate through old list
{ if (!bFound && (pLRUListIds[n]== nFIndex))
bFound = true; // First hit! elseif (bFound)
aIdxList[n ] = pLRUListIds[n]; // Copy after hit elseif ((n+1) < LRU_MAX)
aIdxList[n+1] = pLRUListIds[n]; // Move before hit
n++;
} if (!bFound && (n < LRU_MAX)) // Entry not found?
n++; // One more
aIdxList[0] = nFIndex; // Current on Top
ScAppOptions aNewOpts(rAppOpt); // Let App know
aNewOpts.SetLRUFuncList(aIdxList, n);
SetAppOptions(aNewOpts);
}
if (!m_pFormulaCfg || (*m_pFormulaCfg != rOpt)) // Formula options have changed. Repaint the column headers.
bRepaint = true;
if (m_pFormulaCfg && m_pFormulaCfg->GetUseEnglishFuncName() != rOpt.GetUseEnglishFuncName())
{ // Re-compile formula cells with error as the error may have been // caused by unresolved function names.
bCompileErrorCells = true;
}
// Recalc for interpreter options changes. if (m_pFormulaCfg && m_pFormulaCfg->GetCalcConfig() != rOpt.GetCalcConfig())
bCalcAll = true;
if ( pDocSh )
{
pDocSh->SetFormulaOptions( rOpt );
pDocSh->SetDocumentModified();
}
// ScDocShell::SetFormulaOptions() may check for changed settings, so // set the new options here after that has been called. if (!bCalcAll || rOpt.GetWriteCalcConfig())
{ // CalcConfig is new, didn't change or is global, simply set all.
SetFormulaOptions( rOpt );
} else
{ // If "only for current document" was checked, reset those affected // by that setting to previous values.
ScFormulaOptions aNewOpt( rOpt);
aNewOpt.GetCalcConfig().MergeDocumentSpecific( m_pFormulaCfg->GetCalcConfig());
SetFormulaOptions( aNewOpt);
}
}
if ( rOldOpt != rNewOpt )
{
rViewData.SetOptions( rNewOpt ); // Changes rOldOpt
rViewData.GetDocument().SetViewOptions( rNewOpt ); if (pDocSh)
pDocSh->SetDocumentModified();
bRepaint = true;
} if ( bAnchorList )
pViewSh->UpdateAnchorHandles();
}
SetViewOptions( rNewOpt ); if (pBindings)
{
pBindings->Invalidate(SID_HELPLINES_MOVE);
}
}
// GridOptions // Evaluate after ViewOptions, as GridOptions is a member of ViewOptions if ( const SvxGridItem* pItem = rOptSet.GetItemIfSet(SID_ATTR_GRID_OPTIONS) )
{
ScGridOptions aNewGridOpt( *pItem );
// AutoSpell after the DocOptions (due to being a member) if ( const SfxBoolItem* pItem = rOptSet.GetItemIfSet(SID_AUTOSPELL_CHECK) ) // At DocOptions
{ bool bDoAutoSpell = pItem->GetValue();
if (pViewSh)
{ if (pViewSh->IsAutoSpell() != bDoAutoSpell)
{
pViewSh->EnableAutoSpell(bDoAutoSpell);
bRepaint = true; // Because HideAutoSpell might be invalid //TODO: Paint all Views?
}
}
if ( bOldAutoSpell != bDoAutoSpell )
SetAutoSpellProperty( bDoAutoSpell ); if ( pDocSh )
pDocSh->PostPaintGridAll(); // Due to marks
ScInputHandler* pInputHandler = GetInputHdl(); if ( pInputHandler )
pInputHandler->UpdateSpellSettings(); // EditEngine flags if ( pViewSh )
pViewSh->UpdateDrawTextOutliner(); // EditEngine flags
if (pBindings)
pBindings->Invalidate( SID_AUTOSPELL_CHECK );
}
// broadcast causes all previews to recalc page numbers
SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScPrintOptions ) );
}
if ( bSaveAppOptions )
m_pAppCfg->SetOptions(aAppOptions);
if ( bSaveInputOptions )
m_pInputCfg->SetOptions(aInputOptions);
// Kick off recalculation? if (pDoc && bCompileErrorCells)
{ // Re-compile cells with name error, and recalc if at least one cell // has been re-compiled. In the future we may want to find a way to // recalc only those that are affected. if (pDoc->CompileErrorCells(FormulaError::NoName))
bCalcAll = true;
}
ScInputHandler* pHdl = nullptr; if ( !pViewSh )
{ // in case a UIActive embedded object has no ViewShell (UNO component) // the own calc view shell will be set as current, but no handling should happen
ScTabViewShell* pCurViewSh = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() ); if ( pCurViewSh && !pCurViewSh->GetUIActiveClient() )
pViewSh = pCurViewSh;
}
if ( pViewSh )
pHdl = pViewSh->GetInputHandler(); // Viewshell always has one, from now on
// If no ViewShell passed or active, we can get NULL
OSL_ENSURE( pHdl || !pViewSh, "GetInputHdl: no InputHandler found!" ); return pHdl;
}
ScInputWindow* pWin = pHdl->GetInputWindow(); if ( pStrFormula )
{ // Take over formula if ( pWin )
{
pWin->SetFuncString( *pStrFormula, false ); // SetSumAssignMode due to sal_False not necessary
}
ScEnterMode nMode = bMatrix ? ScEnterMode::MATRIX : ScEnterMode::NORMAL;
pHdl->EnterHandler( nMode );
// Without Invalidate the selection remains active, if the formula has not changed if (pWin)
pWin->TextInvalidate();
} else
{ // Cancel if ( pWin )
{
pWin->SetFuncString( OUString(), false ); // SetSumAssignMode due to sal_False no necessary
}
pHdl->CancelHandler();
}
}
/** * Reference dialogs
*/ void ScModule::SetRefDialog( sal_uInt16 nId, bool bVis, SfxViewFrame* pViewFrm )
{ //TODO: Move reference dialog handling to view // Just keep function autopilot here for references to other documents if ( !(m_nCurRefDlgId == 0 || ( nId == m_nCurRefDlgId && !bVis )
|| ( comphelper::LibreOfficeKit::isActive() )) ) return;
if ( !pViewFrm )
pViewFrm = SfxViewFrame::Current();
// bindings update causes problems with update of stylist if // current style family has changed //if ( pViewFrm ) // pViewFrm->GetBindings().Update(); // to avoid trouble in LockDispatcher
// before SetChildWindow if ( comphelper::LibreOfficeKit::isActive() )
{ if ( bVis )
m_nCurRefDlgId = nId;
} else
{
m_nCurRefDlgId = bVis ? nId : 0;
}
if ( pViewFrm )
{ // store the dialog id also in the view shell
SfxViewShell* pViewSh = pViewFrm->GetViewShell(); if (ScTabViewShell* pTabViewSh = dynamic_cast<ScTabViewShell*>(pViewSh))
pTabViewSh->SetCurRefDlgId(m_nCurRefDlgId); else
{ // no ScTabViewShell - possible for example from a Basic macro
bVis = false;
m_nCurRefDlgId = 0; // don't set nCurRefDlgId if no dialog is created
}
// #i46999# current view frame can be null (for example, when closing help) return pViewFrm ? pViewFrm->GetChildWindow( nId ) : nullptr;
}
static SfxChildWindow* lcl_GetChildWinFromAnyView( sal_uInt16 nId )
{ // First, try the current view
SfxChildWindow* pChildWnd = lcl_GetChildWinFromCurrentView( nId ); if ( pChildWnd ) return pChildWnd; // found in the current view
// if not found there, get the child window from any open view // it can be open only in one view because nCurRefDlgId is global
SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst(); while ( pViewFrm )
{
pChildWnd = pViewFrm->GetChildWindow( nId ); if ( pChildWnd ) return pChildWnd; // found in any view
pViewFrm = SfxViewFrame::GetNext( *pViewFrm );
}
return nullptr; // none found
}
bool ScModule::IsModalMode(SfxObjectShell* pDocSh)
{ //TODO: Move reference dialog handling to view // Just keep function autopilot here for references to other documents bool bIsModal = false;
if ( m_nCurRefDlgId )
{
SfxChildWindow* pChildWnd = lcl_GetChildWinFromCurrentView( m_nCurRefDlgId ); if ( pChildWnd )
{ if (pChildWnd->GetController())
{
IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
assert(pRefDlg);
bIsModal = pChildWnd->IsVisible() && pRefDlg &&
!( pRefDlg->IsRefInputMode() && pRefDlg->IsDocAllowed(pDocSh) );
}
} elseif ( pDocSh && comphelper::LibreOfficeKit::isActive() )
{ // m_nCurRefDlgId is not deglobalized so it can be set by other view // in LOK case when no ChildWindow for this view was detected -> fallback
ScInputHandler* pHdl = GetInputHdl(); if ( pHdl )
bIsModal = pHdl->IsModalMode(*pDocSh);
}
} elseif (pDocSh)
{
ScInputHandler* pHdl = GetInputHdl(); if ( pHdl )
bIsModal = pHdl->IsModalMode(*pDocSh);
}
return bIsModal;
}
bool ScModule::IsTableLocked()
{ //TODO: Move reference dialog handling to view // Just keep function autopilot here for references to other documents bool bLocked = false;
// Up until now just for ScAnyRefDlg if ( m_nCurRefDlgId )
{
SfxChildWindow* pChildWnd = lcl_GetChildWinFromAnyView( m_nCurRefDlgId ); if ( pChildWnd )
{ if (pChildWnd->GetController())
{
IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
assert(pRefDlg); if (pRefDlg)
bLocked = pRefDlg->IsTableLocked();
}
} elseif (!comphelper::LibreOfficeKit::isActive())
bLocked = true; // for other views, see IsModalMode
}
// We can't stop LOK clients from switching part, and getting out of sync.
assert(!bLocked || !comphelper::LibreOfficeKit::isActive());
return bLocked;
}
bool ScModule::IsRefDialogOpen()
{ //TODO: Move reference dialog handling to view // Just keep function autopilot here for references to other documents bool bIsOpen = false;
if ( m_nCurRefDlgId )
{
SfxChildWindow* pChildWnd = lcl_GetChildWinFromCurrentView( m_nCurRefDlgId ); if ( pChildWnd )
bIsOpen = pChildWnd->IsVisible();
}
return bIsOpen;
}
bool ScModule::IsFormulaMode()
{ //TODO: Move reference dialog handling to view // Just keep function autopilot here for references to other documents bool bIsFormula = false;
if ( m_nCurRefDlgId )
{
SfxChildWindow* pChildWnd = nullptr;
if ( pChildWnd )
{ if (pChildWnd->GetController())
{
IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
assert(pRefDlg);
bIsFormula = pChildWnd->IsVisible() && pRefDlg && pRefDlg->IsRefInputMode();
}
} elseif ( comphelper::LibreOfficeKit::isActive() )
{ // m_nCurRefDlgId is not deglobalized so it can be set by other view // in LOK case when no ChildWindow for this view was detected -> fallback
ScInputHandler* pHdl = GetInputHdl(); if ( pHdl )
bIsFormula = pHdl->IsFormulaMode();
}
} else
{
ScInputHandler* pHdl = GetInputHdl(); if ( pHdl )
bIsFormula = pHdl->IsFormulaMode();
}
void ScModule::SetReference( const ScRange& rRef, ScDocument& rDoc, const ScMarkData* pMarkData )
{ //TODO: Move reference dialog handling to view // Just keep function autopilot here for references to other documents
// In RefDialogs we also trigger the ZoomIn, if the Ref's Start and End are different
ScRange aNew = rRef;
aNew.PutInOrder(); // Always in the right direction
if (pChildWnd->GetController())
{
IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
assert(pRefDlg); if(pRefDlg)
{ // hide the (color) selection now instead of later from LoseFocus, // don't abort the ref input that causes this call (bDoneRefMode = sal_False)
pRefDlg->HideReference( false );
pRefDlg->SetReference( aNew, rDoc );
}
}
} elseif ( comphelper::LibreOfficeKit::isActive() )
{ // m_nCurRefDlgId is not deglobalized so it can be set by other view // in LOK case when no ChildWindow for this view was detected -> fallback
ScInputHandler* pHdl = GetInputHdl(); if (pHdl)
pHdl->SetReference( aNew, rDoc );
}
} else
{
ScInputHandler* pHdl = GetInputHdl(); if (pHdl)
pHdl->SetReference( aNew, rDoc ); else
{
OSL_FAIL("SetReference without receiver");
}
}
}
/** * Multiple selection
*/ void ScModule::AddRefEntry()
{ //TODO: Move reference dialog handling to view // Just keep function autopilot here for references to other documents if ( m_nCurRefDlgId )
{
SfxChildWindow* pChildWnd = lcl_GetChildWinFromAnyView( m_nCurRefDlgId );
OSL_ENSURE( pChildWnd, "NoChildWin" ); if ( pChildWnd )
{ if (pChildWnd->GetController())
{
IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetController().get());
assert(pRefDlg); if (pRefDlg)
{
pRefDlg->AddRefEntry();
}
}
}
} else
{
ScInputHandler* pHdl = GetInputHdl(); if (pHdl)
pHdl->AddRefEntry();
}
}
void ScModule::EndReference()
{ //TODO: Move reference dialog handling to view // Just keep function autopilot here for references to other documents
// We also annul the ZoomIn again in RefDialogs
//FIXME: ShowRefFrame at InputHdl, if the Function AutoPilot is open? if ( !m_nCurRefDlgId ) return;
bMore = bLinks || bWidth; // Still something at all?
// While calculating a Basic formula, a paint event may have occurred, // so check the bNeedsRepaint flags for this document's views if (bWidth)
lcl_CheckNeedsRepaint( pDocSh );
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.