/* -*- 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 .
*/
/** * Find the next node which has a SfxItemSet. * The input parameter pLast has a sophisticated meaning: * downstairs only: * pLast == 0 => scan your children and their children * but neither your parents neither your siblings * downstairs and upstairs: * pLast == this => scan your children, their children, * the children of your parent behind you, and so on * partial downstairs and upstairs * pLast != 0 && pLast != this => scan your children behind the given children, * the children of your parent behind you and so on. * * OD 2008-03-11 #i86923# * introduce parameters <bSkipUnusedItemSets> and <bSkipIgnorable> * and its handling.
*/
Node* Node::nextItemSet( Node const * pLast, constbool bSkipUnusedItemSets, constbool bSkipIgnorable )
{ // Searching downstairs auto aIter = mChildren.begin(); // For pLast == 0 and pLast == this all children are of interest // for another pLast the search starts behind pLast... if( pLast && pLast != this )
{
aIter = std::find_if( mChildren.begin(), mChildren.end(),
[&] (std::unique_ptr<Node> const &p) { return p.get() == pLast; }); if( aIter != mChildren.end() )
++aIter;
}
Node *pNext = nullptr; while( aIter != mChildren.end() )
{ // #i86923# if ( bSkipIgnorable && (*aIter)->mbIsItemIgnorable )
{
++aIter; continue;
}
pNext = aIter->get(); // #i86923# if ( pNext->hasItemSet( bSkipUnusedItemSets ) )
{ return pNext;
} if ( bSkipIgnorable &&
pNext->hasIgnorableChildren( bSkipUnusedItemSets ) )
{ return pNext;
}
pNext = pNext->nextItemSet( nullptr, bSkipUnusedItemSets, bSkipIgnorable ); // 0 => downstairs only if( pNext ) return pNext;
++aIter;
} // Searching upstairs if( pLast && mpUpper )
{ // #i86923#
pNext = mpUpper->nextItemSet( this, bSkipUnusedItemSets, bSkipIgnorable );
} return pNext;
}
class Iterator
{
std::map< const SfxItemSet*, Node >& mrRoot;
std::map< const SfxItemSet*, Node >::iterator mpCurrNode;
Node* mpNode; constbool mbSkipUnusedItemSets; constbool mbSkipIgnorable; /// List of item set parents, ordered by their name.
std::vector<const SfxItemSet*> maParents; /// The iterator's current position.
std::vector<const SfxItemSet*>::iterator mpCurrParent; public: // #i86923#
Iterator( std::map< const SfxItemSet*, Node >& rR, constbool bSkipUnusedItemSets, constbool bSkipIgnorable, const std::map< const SfxItemSet*, OUString>& rParentNames )
: mrRoot( rR ),
mpNode(nullptr),
mbSkipUnusedItemSets( bSkipUnusedItemSets ),
mbSkipIgnorable( bSkipIgnorable )
{ // Collect the parent pointers into a vector we can sort. for (constauto& rParent : mrRoot)
maParents.push_back(rParent.first);
// Sort the parents using their name, if they have one. if (!rParentNames.empty())
{
std::stable_sort(maParents.begin(), maParents.end(),
[&rParentNames](const SfxItemSet* pA, const SfxItemSet* pB) {
OUString aA;
OUString aB; auto it = rParentNames.find(pA); if (it != rParentNames.end())
aA = it->second;
it = rParentNames.find(pB); if (it != rParentNames.end())
aB = it->second; return aA < aB;
});
}
// Start the iteration.
mpCurrParent = maParents.begin(); if (mpCurrParent != maParents.end())
mpCurrNode = mrRoot.find(*mpCurrParent);
}
std::shared_ptr<SfxItemSet> getNext();
};
/** * This static method creates a unique name from a shared pointer to a SfxItemSet * The name is the memory address of the SfxItemSet itself.
*/
OUString StylePool::nameOf( const std::shared_ptr<SfxItemSet>& pSet )
{ return OUString::number( reinterpret_cast<sal_IntPtr>( pSet.get() ), 16 );
}
/** * class StylePoolImpl organized a tree-structure where every node represents a SfxItemSet. * The insertItemSet method adds a SfxItemSet into the tree if necessary and returns a shared_ptr * to a copy of the SfxItemSet. * The aRoot-Node represents an empty SfxItemSet.
*/ class StylePoolImpl
{ private:
std::map< const SfxItemSet*, Node > maRoot; /// Names of maRoot keys.
std::map< const SfxItemSet*, OUString> maParentNames; // #i86923#
std::unique_ptr<SfxItemSet> mpIgnorableItems; #if OSL_DEBUG_LEVEL >= 2
sal_Int32 mnCount; #endif public: // #i86923# explicit StylePoolImpl( SfxItemSet const * pIgnorableItems )
: #if OSL_DEBUG_LEVEL >= 2
mnCount(0), #endif
mpIgnorableItems( pIgnorableItems != nullptr
? pIgnorableItems->Clone( false )
: nullptr )
{
DBG_ASSERT( !pIgnorableItems || !pIgnorableItems->Count(), " - misusage: item set for ignorable item should be empty. Please correct usage." );
DBG_ASSERT( !mpIgnorableItems || !mpIgnorableItems->Count(), " - does not work as expected - is not empty." );
}
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.