summaryrefslogtreecommitdiff
path: root/svtools/source
diff options
context:
space:
mode:
authorRüdiger Timm <rt@openoffice.org>2006-12-01 14:25:00 +0000
committerRüdiger Timm <rt@openoffice.org>2006-12-01 14:25:00 +0000
commit7a97b4ead07dd2a57352148c1048fa925ea548bf (patch)
treeed7287c97b74bcfd64c1c528bcc88c7bb638bfa6 /svtools/source
parenta012b098daafe9978ee1df6327ab5ffc7a5d562b (diff)
INTEGRATION: CWS swautomatic01 (1.1.2); FILE ADDED
2006/08/22 07:34:47 ama 1.1.2.8: #i65476#: Typo 2006/08/18 09:09:01 ama 1.1.2.7: #i65476#: Automatic styles 2006/08/09 08:41:12 fme 1.1.2.6: #i64576# Automatic styles 2006/06/15 15:46:59 ama 1.1.2.5: #i65476#: Automatic Styles 2006/06/02 13:20:41 ama 1.1.2.4: #i65476#: Automatic Styles 2006/05/29 13:59:04 ama 1.1.2.3: #i65476#: Automatic Styles 2006/05/24 14:29:45 ama 1.1.2.2: #i65476#: Automatic styles 2006/05/24 09:29:15 ama 1.1.2.1: #i65476# StylePool for automatic styles
Diffstat (limited to 'svtools/source')
-rw-r--r--svtools/source/items1/stylepool.cxx275
1 files changed, 275 insertions, 0 deletions
diff --git a/svtools/source/items1/stylepool.cxx b/svtools/source/items1/stylepool.cxx
new file mode 100644
index 000000000000..ca2fd2dbc255
--- /dev/null
+++ b/svtools/source/items1/stylepool.cxx
@@ -0,0 +1,275 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: stylepool.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: rt $ $Date: 2006-12-01 15:25:00 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ************************************************************************/
+
+#ifndef GCC
+#pragma hdrstop
+#endif
+
+#include <vector>
+
+#include "stylepool.hxx"
+#include "itemiter.hxx"
+#include "itempool.hxx"
+
+
+using namespace boost;
+
+namespace {
+ // A "Node" represents a subset of inserted SfxItemSets
+ // The root node represents the empty set
+ // The other nodes contain a SfxPoolItem and represents an item set which contains their
+ // pool item and the pool items of their parents.
+ class Node
+ {
+ std::vector<Node*> mChildren; // child nodes, create by findChildNode(..)
+ StylePool::SfxItemSet_Pointer_t pItemSet; // shared pointer an inserted item set or nul
+ const SfxPoolItem *pItem; // my pool item
+ Node *pUpper; // if I'm a child node that's my parent node
+ public:
+ Node() : pItem( 0 ), pUpper( 0 ) {} // root node Ctor
+ Node( const SfxPoolItem& rItem, Node* pParent ) : // child node Ctor
+ pItem( rItem.Clone() ), pUpper( pParent ){}
+ ~Node();
+ const bool hasItemSet() const { return 0 != pItemSet.get(); }
+ const StylePool::SfxItemSet_Pointer_t getItemSet() const { return pItemSet; }
+ void setItemSet( const SfxItemSet& rSet ){ pItemSet.reset( rSet.Clone() ); }
+ Node* findChildNode( const SfxPoolItem& rItem, bool bPoolable );
+ Node* nextItemSet( Node* pLast );
+ const SfxPoolItem& getPoolItem() const { return *pItem; }
+ };
+
+ Node* Node::findChildNode( const SfxPoolItem& rItem, bool bPoolable )
+ {
+ Node* pNextNode = this;
+ std::vector<Node*>::iterator aIter = mChildren.begin();
+ // Only poolable items are allowed to be reused,
+ // for non-poolable items allways newe nodes have to be created.
+ if( bPoolable )
+ {
+ while( aIter != mChildren.end() )
+ {
+ if( rItem.Which() == (*aIter)->getPoolItem().Which() &&
+ rItem == (*aIter)->getPoolItem() )
+ return *aIter;
+ ++aIter;
+ }
+ }
+ pNextNode = new Node( rItem, pNextNode );
+ mChildren.push_back( pNextNode );
+ return pNextNode;
+ }
+
+ /* 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.
+ */
+
+ Node* Node::nextItemSet( Node* pLast )
+ {
+ // Searching downstairs
+ std::vector<Node*>::iterator 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( mChildren.begin(), mChildren.end(), pLast );
+ if( aIter != mChildren.end() )
+ ++aIter;
+ }
+ Node *pNext = 0;
+ while( aIter != mChildren.end() )
+ {
+ pNext = *aIter;
+ if( pNext->hasItemSet() ) // any child with item set?
+ return pNext;
+ pNext = pNext->nextItemSet( 0 ); // 0 => downstairs only
+ if( pNext )
+ return pNext;
+ ++aIter;
+ }
+ // Searching upstairs
+ if( pLast && pUpper )
+ pNext = pUpper->nextItemSet( this );
+ return pNext;
+ }
+
+ Node::~Node()
+ {
+ std::vector<Node*>::iterator aIter = mChildren.begin();
+ while( aIter != mChildren.end() )
+ {
+ delete *aIter;
+ ++aIter;
+ }
+ delete pItem;
+ }
+
+ class Iterator : public IStylePoolIteratorAccess
+ {
+ Node* pNode;
+ bool bStart;
+ public:
+ Iterator( Node& rNode ) : pNode(&rNode), bStart(true) {}
+ virtual StylePool::SfxItemSet_Pointer_t getNext();
+ virtual ::rtl::OUString getName();
+ };
+
+ StylePool::SfxItemSet_Pointer_t Iterator::getNext()
+ {
+ StylePool::SfxItemSet_Pointer_t pReturn;
+ if( pNode )
+ {
+ if( bStart )
+ {
+ bStart = false;
+ if( pNode->hasItemSet() )
+ return pNode->getItemSet();
+ }
+ pNode = pNode->nextItemSet( pNode );
+ if( pNode )
+ pReturn = pNode->getItemSet();
+ }
+ return pReturn;
+ }
+
+ ::rtl::OUString Iterator::getName()
+ {
+ ::rtl::OUString aString;
+ if( !bStart && pNode )
+ aString = StylePool::nameOf( pNode->getItemSet() );
+ return aString;
+ }
+
+}
+
+/* This static method creates a unique name from a shared pointer to a SfxItemSet
+ The name is the memory address of the SfxItemSet itself. */
+
+::rtl::OUString StylePool::nameOf( SfxItemSet_Pointer_t pSet )
+{
+ return ::rtl::OUString::valueOf( reinterpret_cast<sal_Int32>( 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:
+ Node aRoot;
+ sal_Int32 nCount;
+public:
+ StylePoolImpl() : nCount(0) {}
+ StylePool::SfxItemSet_Pointer_t insertItemSet( const SfxItemSet& rSet );
+ IStylePoolIteratorAccess* createIterator();
+ sal_Int32 getCount() const { return nCount; }
+};
+
+StylePool::SfxItemSet_Pointer_t StylePoolImpl::insertItemSet( const SfxItemSet& rSet )
+{
+ Node* pCurNode = &aRoot;
+ SfxItemIter aIter( rSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ // Every SfxPoolItem in the SfxItemSet causes a step deeper into the tree,
+ // a complete empty SfxItemSet would stay at the root node.
+ while( pItem )
+ {
+ bool bPoolable = rSet.GetPool()->IsItemFlag(pItem->Which(), SFX_ITEM_POOLABLE );
+ pCurNode = pCurNode->findChildNode( *pItem, bPoolable );
+ // Optimization: If the last item wasn't poolable, we can stop inserting new nodes
+ // and insert our itemset directly into the last created node
+ pItem = bPoolable ? aIter.NextItem() : 0;
+ }
+ // Every leaf node represents an inserted item set, but "non-leaf" nodes represents subsets
+ // of inserted itemsets.
+ // These nodes could have but does not need to have a shared_ptr to a item set.
+ if( !pCurNode->hasItemSet() )
+ {
+ pCurNode->setItemSet( rSet );
+ ++nCount;
+ }
+#ifdef DEBUG
+ {
+ sal_Int32 nCheck = -1;
+ sal_Int32 nNo = -1;
+ IStylePoolIteratorAccess* pIter = createIterator();
+ StylePool::SfxItemSet_Pointer_t pTemp;
+ do
+ {
+ ++nCheck;
+ pTemp = pIter->getNext();
+ if( pTemp.get() == pCurNode->getItemSet().get() )
+ {
+ ::rtl::OUString aStr = pIter->getName();
+ nNo = nCheck;
+ }
+ } while( pTemp.get() );
+ DBG_ASSERT( nCount == nCheck, "Wrong counting");
+ delete pIter;
+ }
+#endif
+ return pCurNode->getItemSet();
+}
+
+IStylePoolIteratorAccess* StylePoolImpl::createIterator()
+{ return new Iterator( aRoot ); }
+
+// Ctor, Dtor and redirected methods of class StylePool, nearly inline ;-)
+
+StylePool::StylePool() : pImpl( new StylePoolImpl() ) {}
+
+StylePool::SfxItemSet_Pointer_t StylePool::insertItemSet( const SfxItemSet& rSet )
+{ return pImpl->insertItemSet( rSet ); }
+
+IStylePoolIteratorAccess* StylePool::createIterator()
+{ return pImpl->createIterator(); }
+
+sal_Int32 StylePool::getCount() const
+{ return pImpl->getCount(); }
+
+StylePool::~StylePool() { delete pImpl; }
+
+// End of class StylePool
+