1
0
Fork 0
libreoffice/sc/source/core/data/stlsheet.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

347 lines
13 KiB
C++

/* -*- 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 <document.hxx>
#include <stlsheet.hxx>
#include <stlpool.hxx>
#include <scitems.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/lrspitem.hxx>
#include <svx/pageitem.hxx>
#include <svx/svddef.hxx>
#include <svx/svdpool.hxx>
#include <svx/xdef.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/paperinf.hxx>
#include <editeng/shaditem.hxx>
#include <editeng/sizeitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/xmlcnitm.hxx>
#include <svl/itempool.hxx>
#include <svl/itemset.hxx>
#include <svl/numformat.hxx>
#include <svl/hint.hxx>
#include <o3tl/unit_conversion.hxx>
#include <attrib.hxx>
#include <globstr.hrc>
#include <scresid.hxx>
#include <sc.hrc>
constexpr auto TWO_CM = o3tl::convert(2, o3tl::Length::cm, o3tl::Length::twip); // 1134
constexpr auto HFDIST_CM = o3tl::convert(250, o3tl::Length::mm100, o3tl::Length::twip); // 142
ScStyleSheet::ScStyleSheet( const OUString& rName,
const ScStyleSheetPool& rPoolP,
SfxStyleFamily eFamily,
SfxStyleSearchBits nMaskP,
const OUString& rParentStyleSheetName)
: SfxStyleSheet ( rName, rPoolP, eFamily, nMaskP, rParentStyleSheetName )
, eUsage( Usage::UNKNOWN )
{
}
ScStyleSheet::ScStyleSheet( const ScStyleSheet& rStyle )
: SfxStyleSheet ( rStyle )
, eUsage( Usage::UNKNOWN )
{
}
ScStyleSheet::~ScStyleSheet()
{
}
bool ScStyleSheet::HasFollowSupport() const
{
return false;
}
bool ScStyleSheet::HasParentSupport () const
{
bool bHasParentSupport = false;
switch ( GetFamily() )
{
case SfxStyleFamily::Para: bHasParentSupport = true; break;
case SfxStyleFamily::Frame: bHasParentSupport = true; break;
case SfxStyleFamily::Page: bHasParentSupport = false; break;
default:
{
// added to avoid warnings
}
}
return bHasParentSupport;
}
bool ScStyleSheet::SetParent( const OUString& rParentName )
{
bool bResult = false;
OUString aEffName = rParentName;
SfxStyleSheetBase* pStyle = m_pPool->Find( aEffName, nFamily );
if (!pStyle)
{
std::unique_ptr<SfxStyleSheetIterator> pIter = m_pPool->CreateIterator(nFamily);
pStyle = pIter->First();
if (pStyle)
aEffName = pStyle->GetName();
}
if ( pStyle && aEffName != GetName() )
{
bResult = SfxStyleSheet::SetParent( aEffName );
if (bResult)
{
SfxItemSet& rParentSet = pStyle->GetItemSet();
GetItemSet().SetParent( &rParentSet );
// #i113491# Drag&Drop in the stylist's hierarchical view doesn't execute a slot,
// so the repaint has to come from here (after modifying the ItemSet).
// RepaintRange checks the document's IsVisible flag and locked repaints.
ScDocument* pDoc = static_cast<ScStyleSheetPool*>(GetPool())->GetDocument();
if (pDoc)
pDoc->RepaintRange( ScRange( 0,0,0, pDoc->MaxCol(),pDoc->MaxRow(),MAXTAB ) );
}
}
return bResult;
}
void ScStyleSheet::ResetParent()
{
GetItemSet().SetParent(nullptr);
}
SfxItemSet& ScStyleSheet::GetItemSet()
{
if ( !pSet )
{
switch ( GetFamily() )
{
case SfxStyleFamily::Page:
{
// Page templates should not be derivable,
// therefore suitable values are set at this point.
// (== Standard page template)
SfxItemPool& rItemPool = GetPool()->GetPool();
pSet = new SfxItemSetFixed<
ATTR_USERDEF, ATTR_USERDEF,
ATTR_WRITINGDIR, ATTR_WRITINGDIR,
ATTR_BACKGROUND, ATTR_BACKGROUND,
ATTR_BORDER, ATTR_SHADOW,
ATTR_LRSPACE, ATTR_PAGE_SCALETO>(rItemPool);
// If being loaded also the set is then filled in from the file,
// so the defaults do not need to be set.
// GetPrinter would then also create a new printer,
// because the stored Printer is not loaded yet!
ScDocument* pDoc = static_cast<ScStyleSheetPool*>(GetPool())->GetDocument();
if ( pDoc )
{
// Setting reasonable default values:
SvxPageItem aPageItem( ATTR_PAGE );
SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetDefaultPaperSize() );
SvxSetItem aHFSetItem(
rItemPool.GetUserOrPoolDefaultItem(ATTR_PAGE_HEADERSET) );
SfxItemSet& rHFSet = aHFSetItem.GetItemSet();
SvxSizeItem aHFSizeItem( // 0,5 cm + distance
ATTR_PAGE_SIZE,
Size( 0, o3tl::convert(500, o3tl::Length::mm100, o3tl::Length::twip) + HFDIST_CM ) );
SvxULSpaceItem aHFDistItem ( HFDIST_CM,// nUp
HFDIST_CM,// nLow
ATTR_ULSPACE );
SvxLRSpaceItem aLRSpaceItem(SvxIndentValue::twips(TWO_CM), // nLeft
SvxIndentValue::twips(TWO_CM), // nRight
SvxIndentValue::zero(), // nFirstLineOffset
ATTR_LRSPACE);
SvxULSpaceItem aULSpaceItem( TWO_CM, // nUp
TWO_CM, // nLow
ATTR_ULSPACE );
SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER );
aBoxInfoItem.SetTable( false );
aBoxInfoItem.SetDist( true );
aBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::DISTANCE );
aPageItem.SetLandscape( false );
rHFSet.Put( aBoxInfoItem );
rHFSet.Put( aHFSizeItem );
rHFSet.Put( aHFDistItem );
rHFSet.Put(SvxLRSpaceItem(SvxIndentValue::zero(), SvxIndentValue::zero(),
SvxIndentValue::zero(),
ATTR_LRSPACE)); // Set border to Null
aHFSetItem.SetWhich(ATTR_PAGE_HEADERSET);
pSet->Put( aHFSetItem );
aHFSetItem.SetWhich(ATTR_PAGE_FOOTERSET);
pSet->Put( aHFSetItem );
pSet->Put( aBoxInfoItem ); // Do not overwrite PoolDefault
// due to format templates
// Writing direction: not as pool default because the default for cells
// must remain SvxFrameDirection::Environment, and each page style's setting is
// supposed to be saved in the file format.
// The page default depends on the system language.
SvxFrameDirection eDirection = ScGlobal::IsSystemRTL() ?
SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB;
pSet->Put( SvxFrameDirectionItem( eDirection, ATTR_WRITINGDIR ) );
rItemPool.SetUserDefaultItem( aPageItem );
rItemPool.SetUserDefaultItem( aPaperSizeItem );
rItemPool.SetUserDefaultItem( aLRSpaceItem );
rItemPool.SetUserDefaultItem( aULSpaceItem );
rItemPool.SetUserDefaultItem( SfxUInt16Item( ATTR_PAGE_SCALE, 100 ) );
ScPageScaleToItem aScaleToItem;
rItemPool.SetUserDefaultItem( aScaleToItem );
rItemPool.SetUserDefaultItem( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, 0 ) );
}
}
break;
case SfxStyleFamily::Frame:
{
SfxItemPool* pItemPool = &GetPool()->GetPool();
assert(pItemPool);
if (dynamic_cast<SdrItemPool*>(pItemPool) == nullptr)
pItemPool = pItemPool->GetSecondaryPool();
assert(pItemPool);
pSet = new SfxItemSetFixed<
XATTR_LINE_FIRST, XATTR_LINE_LAST,
XATTR_FILL_FIRST, XATTR_FILL_LAST,
SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST,
SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_WORDWRAP,
SDRATTR_EDGE_FIRST, SDRATTR_MEASURE_LAST,
SDRATTR_3D_FIRST, SDRATTR_3D_LAST,
EE_PARA_START, EE_CHAR_END>(*pItemPool);
}
break;
case SfxStyleFamily::Para:
default:
pSet = new SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END>( GetPool()->GetPool() );
break;
}
bMySet = true;
}
if ( nHelpId == HID_SC_SHEET_CELL_ERG1 )
{
if ( !pSet->Count() )
{
// Hack to work around that when this code is called from
// ~ScStyleSheetPool -> ~SfxStyleSheetPool, GetPool() is no longer
// an ScStyleSheetPool:
ScStyleSheetPool * pool = dynamic_cast<ScStyleSheetPool *>(
GetPool());
if (pool != nullptr) {
ScDocument* pDoc = pool->GetDocument();
if ( pDoc )
{
sal_uInt32 nNumFmt = pDoc->GetFormatTable()->GetStandardFormat( SvNumFormatType::CURRENCY,ScGlobal::eLnge );
pSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumFmt ) );
}
}
}
}
return *pSet;
}
bool ScStyleSheet::IsUsed() const
{
switch (GetFamily())
{
case SfxStyleFamily::Para:
{
// Always query the document to let it decide if a rescan is necessary,
// and store the state.
ScDocument* pDoc = static_cast<ScStyleSheetPool*>(m_pPool)->GetDocument();
if ( pDoc && pDoc->IsStyleSheetUsed( *this ) )
eUsage = Usage::USED;
else
eUsage = Usage::NOTUSED;
return eUsage == Usage::USED;
}
case SfxStyleFamily::Page:
{
// tdf#108188 - verify that the page style is actually used
ScDocument* pDoc = static_cast<ScStyleSheetPool*>(m_pPool)->GetDocument();
if (pDoc && pDoc->IsPageStyleInUse(GetName(), nullptr))
eUsage = Usage::USED;
else
eUsage = Usage::NOTUSED;
return eUsage == Usage::USED;
}
case SfxStyleFamily::Frame:
{
ForAllListeners([this] (SfxListener* pListener)
{
auto pUser(dynamic_cast<svl::StyleSheetUser*>(pListener));
if (pUser && pUser->isUsedByModel())
{
eUsage = Usage::USED;
return true; // break loop
}
else
eUsage = Usage::NOTUSED;
return false;
});
return eUsage == Usage::USED;
}
default:
return true;
}
}
void ScStyleSheet::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
if ( rHint.GetId() == SfxHintId::Dying )
GetItemSet().SetParent( nullptr );
if (GetFamily() == SfxStyleFamily::Frame)
SfxStyleSheet::Notify(rBC, rHint);
}
// Avoid creating a Style "Standard" if this is not the Standard-Name;
// otherwise two styles would have the same name when storing.
// (on loading the style is created directly per Make with the name; making this query
// not applicable)
//TODO: If at any time during loading SetName is called, a flag has to be set/checked for loading
//TODO: The whole check has to be removed if for a new file version the name transformation is dropped.
bool ScStyleSheet::SetName(const OUString& rNew, bool bReindexNow)
{
OUString aFileStdName = STRING_STANDARD;
if ( rNew == aFileStdName && aFileStdName != ScResId(STR_STYLENAME_STANDARD) )
return false;
else
return SfxStyleSheet::SetName(rNew, bReindexNow);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */