xref: /aoo41x/main/svl/source/items/stylepool.cxx (revision cdf0e10c)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
28*cdf0e10cSrcweir #include "precompiled_svl.hxx"
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir #ifdef _MSC_VER
31*cdf0e10cSrcweir #pragma hdrstop
32*cdf0e10cSrcweir #endif
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir #include <vector>
35*cdf0e10cSrcweir #include <map>
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir #include <svl/stylepool.hxx>
38*cdf0e10cSrcweir #include <svl/itemiter.hxx>
39*cdf0e10cSrcweir #include <svl/itempool.hxx>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir using namespace boost;
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir namespace {
45*cdf0e10cSrcweir     // A "Node" represents a subset of inserted SfxItemSets
46*cdf0e10cSrcweir     // The root node represents the empty set
47*cdf0e10cSrcweir     // The other nodes contain a SfxPoolItem and represents an item set which contains their
48*cdf0e10cSrcweir     // pool item and the pool items of their parents.
49*cdf0e10cSrcweir     class Node
50*cdf0e10cSrcweir     {
51*cdf0e10cSrcweir         std::vector<Node*> mChildren; // child nodes, create by findChildNode(..)
52*cdf0e10cSrcweir         // container of shared pointers of inserted item sets; for non-poolable
53*cdf0e10cSrcweir         // items more than one item set is needed
54*cdf0e10cSrcweir         std::vector< StylePool::SfxItemSet_Pointer_t > maItemSet;
55*cdf0e10cSrcweir         const SfxPoolItem *mpItem;   // my pool item
56*cdf0e10cSrcweir         Node *mpUpper;               // if I'm a child node that's my parent node
57*cdf0e10cSrcweir         // --> OD 2008-03-07 #i86923#
58*cdf0e10cSrcweir         const bool mbIsItemIgnorable;
59*cdf0e10cSrcweir         // <--
60*cdf0e10cSrcweir     public:
61*cdf0e10cSrcweir         // --> OD 2008-03-07 #i86923#
62*cdf0e10cSrcweir         Node() // root node Ctor
63*cdf0e10cSrcweir             : mChildren(),
64*cdf0e10cSrcweir               maItemSet(),
65*cdf0e10cSrcweir               mpItem( 0 ),
66*cdf0e10cSrcweir               mpUpper( 0 ),
67*cdf0e10cSrcweir               mbIsItemIgnorable( false )
68*cdf0e10cSrcweir         {}
69*cdf0e10cSrcweir         Node( const SfxPoolItem& rItem, Node* pParent, const bool bIgnorable ) // child node Ctor
70*cdf0e10cSrcweir             : mChildren(),
71*cdf0e10cSrcweir               maItemSet(),
72*cdf0e10cSrcweir               mpItem( rItem.Clone() ),
73*cdf0e10cSrcweir               mpUpper( pParent ),
74*cdf0e10cSrcweir               mbIsItemIgnorable( bIgnorable )
75*cdf0e10cSrcweir         {}
76*cdf0e10cSrcweir         // <--
77*cdf0e10cSrcweir         ~Node();
78*cdf0e10cSrcweir         // --> OD 2008-03-11 #i86923#
79*cdf0e10cSrcweir         bool hasItemSet( const bool bCheckUsage ) const;
80*cdf0e10cSrcweir         // <--
81*cdf0e10cSrcweir         // --> OD 2008-04-29 #i87808#
82*cdf0e10cSrcweir //        const StylePool::SfxItemSet_Pointer_t getItemSet() const { return aItemSet[aItemSet.size()-1]; }
83*cdf0e10cSrcweir         const StylePool::SfxItemSet_Pointer_t getItemSet() const
84*cdf0e10cSrcweir         {
85*cdf0e10cSrcweir             return maItemSet.back();
86*cdf0e10cSrcweir         }
87*cdf0e10cSrcweir         const StylePool::SfxItemSet_Pointer_t getUsedOrLastAddedItemSet() const;
88*cdf0e10cSrcweir         // <--
89*cdf0e10cSrcweir         void setItemSet( const SfxItemSet& rSet ){ maItemSet.push_back( StylePool::SfxItemSet_Pointer_t( rSet.Clone() ) ); }
90*cdf0e10cSrcweir         // --> OD 2008-03-11 #i86923#
91*cdf0e10cSrcweir         Node* findChildNode( const SfxPoolItem& rItem,
92*cdf0e10cSrcweir                              const bool bIsItemIgnorable = false );
93*cdf0e10cSrcweir         Node* nextItemSet( Node* pLast,
94*cdf0e10cSrcweir                            const bool bSkipUnusedItemSet,
95*cdf0e10cSrcweir                            const bool bSkipIgnorable );
96*cdf0e10cSrcweir         // <--
97*cdf0e10cSrcweir         const SfxPoolItem& getPoolItem() const { return *mpItem; }
98*cdf0e10cSrcweir         // --> OD 2008-03-11 #i86923#
99*cdf0e10cSrcweir         bool hasIgnorableChildren( const bool bCheckUsage ) const;
100*cdf0e10cSrcweir         const StylePool::SfxItemSet_Pointer_t getItemSetOfIgnorableChild(
101*cdf0e10cSrcweir                                         const bool bSkipUnusedItemSets ) const;
102*cdf0e10cSrcweir         // <--
103*cdf0e10cSrcweir     };
104*cdf0e10cSrcweir 
105*cdf0e10cSrcweir     // --> OD 2008-04-29 #i87808#
106*cdf0e10cSrcweir     const StylePool::SfxItemSet_Pointer_t Node::getUsedOrLastAddedItemSet() const
107*cdf0e10cSrcweir     {
108*cdf0e10cSrcweir         std::vector< StylePool::SfxItemSet_Pointer_t >::const_reverse_iterator aIter;
109*cdf0e10cSrcweir 
110*cdf0e10cSrcweir         for ( aIter = maItemSet.rbegin(); aIter != maItemSet.rend(); ++aIter )
111*cdf0e10cSrcweir         {
112*cdf0e10cSrcweir             if ( (*aIter).use_count() > 1 )
113*cdf0e10cSrcweir             {
114*cdf0e10cSrcweir                 return *aIter;
115*cdf0e10cSrcweir             }
116*cdf0e10cSrcweir         }
117*cdf0e10cSrcweir 
118*cdf0e10cSrcweir         return maItemSet.back();
119*cdf0e10cSrcweir     }
120*cdf0e10cSrcweir     // <--
121*cdf0e10cSrcweir 
122*cdf0e10cSrcweir     // --> OD 2008-05-06 #i86923#
123*cdf0e10cSrcweir     bool Node::hasItemSet( const bool bCheckUsage ) const
124*cdf0e10cSrcweir     {
125*cdf0e10cSrcweir         bool bHasItemSet = false;
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir         if ( maItemSet.size() > 0 )
128*cdf0e10cSrcweir         {
129*cdf0e10cSrcweir             if ( bCheckUsage )
130*cdf0e10cSrcweir             {
131*cdf0e10cSrcweir                 std::vector< StylePool::SfxItemSet_Pointer_t >::const_reverse_iterator aIter;
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir                 for ( aIter = maItemSet.rbegin(); aIter != maItemSet.rend(); ++aIter )
134*cdf0e10cSrcweir                 {
135*cdf0e10cSrcweir                     if ( (*aIter).use_count() > 1 )
136*cdf0e10cSrcweir                     {
137*cdf0e10cSrcweir                         bHasItemSet = true;
138*cdf0e10cSrcweir                         break;
139*cdf0e10cSrcweir                     }
140*cdf0e10cSrcweir                 }
141*cdf0e10cSrcweir             }
142*cdf0e10cSrcweir             else
143*cdf0e10cSrcweir             {
144*cdf0e10cSrcweir                 bHasItemSet = true;
145*cdf0e10cSrcweir             }
146*cdf0e10cSrcweir         }
147*cdf0e10cSrcweir         return bHasItemSet;
148*cdf0e10cSrcweir     }
149*cdf0e10cSrcweir     // <--
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir     // --> OD 2008-03-07 #i86923#
152*cdf0e10cSrcweir     Node* Node::findChildNode( const SfxPoolItem& rItem,
153*cdf0e10cSrcweir                                const bool bIsItemIgnorable )
154*cdf0e10cSrcweir     // <--
155*cdf0e10cSrcweir     {
156*cdf0e10cSrcweir         Node* pNextNode = this;
157*cdf0e10cSrcweir         std::vector<Node*>::iterator aIter = mChildren.begin();
158*cdf0e10cSrcweir         while( aIter != mChildren.end() )
159*cdf0e10cSrcweir         {
160*cdf0e10cSrcweir             if( rItem.Which() == (*aIter)->getPoolItem().Which() &&
161*cdf0e10cSrcweir                 rItem == (*aIter)->getPoolItem() )
162*cdf0e10cSrcweir                 return *aIter;
163*cdf0e10cSrcweir             ++aIter;
164*cdf0e10cSrcweir         }
165*cdf0e10cSrcweir         // --> OD 2008-03-07 #i86923#
166*cdf0e10cSrcweir         pNextNode = new Node( rItem, pNextNode, bIsItemIgnorable );
167*cdf0e10cSrcweir         // <--
168*cdf0e10cSrcweir         mChildren.push_back( pNextNode );
169*cdf0e10cSrcweir         return pNextNode;
170*cdf0e10cSrcweir     }
171*cdf0e10cSrcweir 
172*cdf0e10cSrcweir     /* Find the next node which has a SfxItemSet.
173*cdf0e10cSrcweir        The input parameter pLast has a sophisticated meaning:
174*cdf0e10cSrcweir        downstairs only:
175*cdf0e10cSrcweir        pLast == 0 => scan your children and their children
176*cdf0e10cSrcweir                      but neither your parents neither your siblings
177*cdf0e10cSrcweir        downstairs and upstairs:
178*cdf0e10cSrcweir        pLast == this => scan your children, their children,
179*cdf0e10cSrcweir                         the children of your parent behind you, and so on
180*cdf0e10cSrcweir        partial downstairs and upstairs
181*cdf0e10cSrcweir        pLast != 0 && pLast != this => scan your children behind the given children,
182*cdf0e10cSrcweir                         the children of your parent behind you and so on.
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir        OD 2008-03-11 #i86923#
185*cdf0e10cSrcweir        introduce parameters <bSkipUnusedItemSets> and <bSkipIgnorable>
186*cdf0e10cSrcweir        and its handling.
187*cdf0e10cSrcweir     */
188*cdf0e10cSrcweir     Node* Node::nextItemSet( Node* pLast,
189*cdf0e10cSrcweir                              const bool bSkipUnusedItemSets,
190*cdf0e10cSrcweir                              const bool bSkipIgnorable )
191*cdf0e10cSrcweir     {
192*cdf0e10cSrcweir         // Searching downstairs
193*cdf0e10cSrcweir         std::vector<Node*>::iterator aIter = mChildren.begin();
194*cdf0e10cSrcweir         // For pLast == 0 and pLast == this all children are of interest
195*cdf0e10cSrcweir         // for another pLast the search starts behind pLast...
196*cdf0e10cSrcweir         if( pLast && pLast != this )
197*cdf0e10cSrcweir         {
198*cdf0e10cSrcweir             aIter = std::find( mChildren.begin(), mChildren.end(), pLast );
199*cdf0e10cSrcweir             if( aIter != mChildren.end() )
200*cdf0e10cSrcweir                 ++aIter;
201*cdf0e10cSrcweir         }
202*cdf0e10cSrcweir         Node *pNext = 0;
203*cdf0e10cSrcweir         while( aIter != mChildren.end() )
204*cdf0e10cSrcweir         {
205*cdf0e10cSrcweir             // --> OD 2008-03-11 #i86923#
206*cdf0e10cSrcweir             if ( bSkipIgnorable && (*aIter)->mbIsItemIgnorable )
207*cdf0e10cSrcweir             {
208*cdf0e10cSrcweir                 ++aIter;
209*cdf0e10cSrcweir                 continue;
210*cdf0e10cSrcweir             }
211*cdf0e10cSrcweir             // <--
212*cdf0e10cSrcweir             pNext = *aIter;
213*cdf0e10cSrcweir             // --> OD 2008-03-11 #i86923#
214*cdf0e10cSrcweir             if ( pNext->hasItemSet( bSkipUnusedItemSets ) )
215*cdf0e10cSrcweir             {
216*cdf0e10cSrcweir                 return pNext;
217*cdf0e10cSrcweir             }
218*cdf0e10cSrcweir             if ( bSkipIgnorable &&
219*cdf0e10cSrcweir                  pNext->hasIgnorableChildren( bSkipUnusedItemSets ) )
220*cdf0e10cSrcweir             {
221*cdf0e10cSrcweir                 return pNext;
222*cdf0e10cSrcweir             }
223*cdf0e10cSrcweir             pNext = pNext->nextItemSet( 0, bSkipUnusedItemSets, bSkipIgnorable ); // 0 => downstairs only
224*cdf0e10cSrcweir             // <--
225*cdf0e10cSrcweir             if( pNext )
226*cdf0e10cSrcweir                 return pNext;
227*cdf0e10cSrcweir             ++aIter;
228*cdf0e10cSrcweir         }
229*cdf0e10cSrcweir         // Searching upstairs
230*cdf0e10cSrcweir         if( pLast && mpUpper )
231*cdf0e10cSrcweir         {
232*cdf0e10cSrcweir             // --> OD 2008-03-11 #i86923#
233*cdf0e10cSrcweir             pNext = mpUpper->nextItemSet( this, bSkipUnusedItemSets, bSkipIgnorable );
234*cdf0e10cSrcweir             // <--
235*cdf0e10cSrcweir         }
236*cdf0e10cSrcweir         return pNext;
237*cdf0e10cSrcweir     }
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir     // --> OD 2008-03-11 #i86923#
240*cdf0e10cSrcweir     bool Node::hasIgnorableChildren( const bool bCheckUsage ) const
241*cdf0e10cSrcweir     {
242*cdf0e10cSrcweir         bool bHasIgnorableChildren( false );
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir         std::vector<Node*>::const_iterator aIter = mChildren.begin();
245*cdf0e10cSrcweir         while( aIter != mChildren.end() && !bHasIgnorableChildren )
246*cdf0e10cSrcweir         {
247*cdf0e10cSrcweir             Node* pChild = *aIter;
248*cdf0e10cSrcweir             if ( pChild->mbIsItemIgnorable )
249*cdf0e10cSrcweir             {
250*cdf0e10cSrcweir                 bHasIgnorableChildren =
251*cdf0e10cSrcweir                     !bCheckUsage ||
252*cdf0e10cSrcweir                     ( pChild->hasItemSet( bCheckUsage /* == true */ ) ||
253*cdf0e10cSrcweir                       pChild->hasIgnorableChildren( bCheckUsage /* == true */ ) );
254*cdf0e10cSrcweir             }
255*cdf0e10cSrcweir             ++aIter;
256*cdf0e10cSrcweir         }
257*cdf0e10cSrcweir 
258*cdf0e10cSrcweir         return bHasIgnorableChildren;
259*cdf0e10cSrcweir     }
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir     const StylePool::SfxItemSet_Pointer_t Node::getItemSetOfIgnorableChild(
262*cdf0e10cSrcweir                                         const bool bSkipUnusedItemSets ) const
263*cdf0e10cSrcweir     {
264*cdf0e10cSrcweir         DBG_ASSERT( hasIgnorableChildren( bSkipUnusedItemSets ),
265*cdf0e10cSrcweir                     "<Node::getItemSetOfIgnorableChild> - node has no ignorable children" );
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir         std::vector<Node*>::const_iterator aIter = mChildren.begin();
268*cdf0e10cSrcweir         while( aIter != mChildren.end() )
269*cdf0e10cSrcweir         {
270*cdf0e10cSrcweir             Node* pChild = *aIter;
271*cdf0e10cSrcweir             if ( pChild->mbIsItemIgnorable )
272*cdf0e10cSrcweir             {
273*cdf0e10cSrcweir                 if ( pChild->hasItemSet( bSkipUnusedItemSets ) )
274*cdf0e10cSrcweir                 {
275*cdf0e10cSrcweir                     return pChild->getUsedOrLastAddedItemSet();
276*cdf0e10cSrcweir                 }
277*cdf0e10cSrcweir                 else
278*cdf0e10cSrcweir                 {
279*cdf0e10cSrcweir                     pChild = pChild->nextItemSet( 0, bSkipUnusedItemSets, false );
280*cdf0e10cSrcweir                     if ( pChild )
281*cdf0e10cSrcweir                     {
282*cdf0e10cSrcweir                         return pChild->getUsedOrLastAddedItemSet();
283*cdf0e10cSrcweir                     }
284*cdf0e10cSrcweir                 }
285*cdf0e10cSrcweir             }
286*cdf0e10cSrcweir             ++aIter;
287*cdf0e10cSrcweir         }
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir         StylePool::SfxItemSet_Pointer_t pReturn;
290*cdf0e10cSrcweir         return pReturn;
291*cdf0e10cSrcweir     }
292*cdf0e10cSrcweir     // <--
293*cdf0e10cSrcweir 
294*cdf0e10cSrcweir     Node::~Node()
295*cdf0e10cSrcweir     {
296*cdf0e10cSrcweir         std::vector<Node*>::iterator aIter = mChildren.begin();
297*cdf0e10cSrcweir         while( aIter != mChildren.end() )
298*cdf0e10cSrcweir         {
299*cdf0e10cSrcweir             delete *aIter;
300*cdf0e10cSrcweir             ++aIter;
301*cdf0e10cSrcweir         }
302*cdf0e10cSrcweir         delete mpItem;
303*cdf0e10cSrcweir     }
304*cdf0e10cSrcweir 
305*cdf0e10cSrcweir     class Iterator : public IStylePoolIteratorAccess
306*cdf0e10cSrcweir     {
307*cdf0e10cSrcweir         std::map< const SfxItemSet*, Node >& mrRoot;
308*cdf0e10cSrcweir         std::map< const SfxItemSet*, Node >::iterator mpCurrNode;
309*cdf0e10cSrcweir         Node* mpNode;
310*cdf0e10cSrcweir         const bool mbSkipUnusedItemSets;
311*cdf0e10cSrcweir         const bool mbSkipIgnorable;
312*cdf0e10cSrcweir     public:
313*cdf0e10cSrcweir         // --> OD 2008-03-07 #i86923#
314*cdf0e10cSrcweir         Iterator( std::map< const SfxItemSet*, Node >& rR,
315*cdf0e10cSrcweir                   const bool bSkipUnusedItemSets,
316*cdf0e10cSrcweir                   const bool bSkipIgnorable )
317*cdf0e10cSrcweir             : mrRoot( rR ),
318*cdf0e10cSrcweir               mpCurrNode( rR.begin() ),
319*cdf0e10cSrcweir               mpNode(0),
320*cdf0e10cSrcweir               mbSkipUnusedItemSets( bSkipUnusedItemSets ),
321*cdf0e10cSrcweir               mbSkipIgnorable( bSkipIgnorable )
322*cdf0e10cSrcweir         {}
323*cdf0e10cSrcweir         // <--
324*cdf0e10cSrcweir         virtual StylePool::SfxItemSet_Pointer_t getNext();
325*cdf0e10cSrcweir         virtual ::rtl::OUString getName();
326*cdf0e10cSrcweir     };
327*cdf0e10cSrcweir 
328*cdf0e10cSrcweir     StylePool::SfxItemSet_Pointer_t Iterator::getNext()
329*cdf0e10cSrcweir     {
330*cdf0e10cSrcweir         StylePool::SfxItemSet_Pointer_t pReturn;
331*cdf0e10cSrcweir         while( mpNode || mpCurrNode != mrRoot.end() )
332*cdf0e10cSrcweir         {
333*cdf0e10cSrcweir             if( !mpNode )
334*cdf0e10cSrcweir             {
335*cdf0e10cSrcweir                 mpNode = &mpCurrNode->second;
336*cdf0e10cSrcweir                 ++mpCurrNode;
337*cdf0e10cSrcweir                 // --> OD 2008-03-11 #i86923#
338*cdf0e10cSrcweir                 if ( mpNode->hasItemSet( mbSkipUnusedItemSets ) )
339*cdf0e10cSrcweir                 {
340*cdf0e10cSrcweir                     // --> OD 2008-04-30 #i87808#
341*cdf0e10cSrcweir //                    return pNode->getItemSet();
342*cdf0e10cSrcweir                     return mpNode->getUsedOrLastAddedItemSet();
343*cdf0e10cSrcweir                     // <--
344*cdf0e10cSrcweir                 }
345*cdf0e10cSrcweir                 // <--
346*cdf0e10cSrcweir             }
347*cdf0e10cSrcweir             // --> OD 2008-03-11 #i86923#
348*cdf0e10cSrcweir             mpNode = mpNode->nextItemSet( mpNode, mbSkipUnusedItemSets, mbSkipIgnorable );
349*cdf0e10cSrcweir             if ( mpNode && mpNode->hasItemSet( mbSkipUnusedItemSets ) )
350*cdf0e10cSrcweir             {
351*cdf0e10cSrcweir                 // --> OD 2008-04-30 #i87808#
352*cdf0e10cSrcweir //                return pNode->getItemSet();
353*cdf0e10cSrcweir                 return mpNode->getUsedOrLastAddedItemSet();
354*cdf0e10cSrcweir                 // <--
355*cdf0e10cSrcweir             }
356*cdf0e10cSrcweir             if ( mbSkipIgnorable &&
357*cdf0e10cSrcweir                  mpNode && mpNode->hasIgnorableChildren( mbSkipUnusedItemSets ) )
358*cdf0e10cSrcweir             {
359*cdf0e10cSrcweir                 return mpNode->getItemSetOfIgnorableChild( mbSkipUnusedItemSets );
360*cdf0e10cSrcweir             }
361*cdf0e10cSrcweir             // <--
362*cdf0e10cSrcweir         }
363*cdf0e10cSrcweir         return pReturn;
364*cdf0e10cSrcweir     }
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir     ::rtl::OUString Iterator::getName()
367*cdf0e10cSrcweir     {
368*cdf0e10cSrcweir         ::rtl::OUString aString;
369*cdf0e10cSrcweir         if( mpNode && mpNode->hasItemSet( false ) )
370*cdf0e10cSrcweir         {
371*cdf0e10cSrcweir             // --> OD 2008-04-30 #i87808#
372*cdf0e10cSrcweir //            aString = StylePool::nameOf( pNode->getItemSet() );
373*cdf0e10cSrcweir             aString = StylePool::nameOf( mpNode->getUsedOrLastAddedItemSet() );
374*cdf0e10cSrcweir             // <--
375*cdf0e10cSrcweir         }
376*cdf0e10cSrcweir         return aString;
377*cdf0e10cSrcweir     }
378*cdf0e10cSrcweir 
379*cdf0e10cSrcweir }
380*cdf0e10cSrcweir 
381*cdf0e10cSrcweir /* This static method creates a unique name from a shared pointer to a SfxItemSet
382*cdf0e10cSrcweir    The name is the memory address of the SfxItemSet itself. */
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir ::rtl::OUString StylePool::nameOf( SfxItemSet_Pointer_t pSet )
385*cdf0e10cSrcweir {
386*cdf0e10cSrcweir     return ::rtl::OUString::valueOf( reinterpret_cast<sal_IntPtr>( pSet.get() ), 16 );
387*cdf0e10cSrcweir }
388*cdf0e10cSrcweir 
389*cdf0e10cSrcweir // class StylePoolImpl organized a tree-structure where every node represents a SfxItemSet.
390*cdf0e10cSrcweir // The insertItemSet method adds a SfxItemSet into the tree if necessary and returns a shared_ptr
391*cdf0e10cSrcweir // to a copy of the SfxItemSet.
392*cdf0e10cSrcweir // The aRoot-Node represents an empty SfxItemSet.
393*cdf0e10cSrcweir 
394*cdf0e10cSrcweir class StylePoolImpl
395*cdf0e10cSrcweir {
396*cdf0e10cSrcweir private:
397*cdf0e10cSrcweir     std::map< const SfxItemSet*, Node > maRoot;
398*cdf0e10cSrcweir     sal_Int32 mnCount;
399*cdf0e10cSrcweir     // --> OD 2008-03-07 #i86923#
400*cdf0e10cSrcweir     SfxItemSet* mpIgnorableItems;
401*cdf0e10cSrcweir     // <--
402*cdf0e10cSrcweir public:
403*cdf0e10cSrcweir     // --> OD 2008-03-07 #i86923#
404*cdf0e10cSrcweir     explicit StylePoolImpl( SfxItemSet* pIgnorableItems = 0 )
405*cdf0e10cSrcweir         : maRoot(),
406*cdf0e10cSrcweir           mnCount(0),
407*cdf0e10cSrcweir           mpIgnorableItems( pIgnorableItems != 0
408*cdf0e10cSrcweir                             ? pIgnorableItems->Clone( sal_False )
409*cdf0e10cSrcweir                             : 0 )
410*cdf0e10cSrcweir     {
411*cdf0e10cSrcweir         DBG_ASSERT( !pIgnorableItems || !pIgnorableItems->Count(),
412*cdf0e10cSrcweir                     "<StylePoolImpl::StylePoolImpl(..)> - misusage: item set for ignorable item should be empty. Please correct usage." );
413*cdf0e10cSrcweir         DBG_ASSERT( !mpIgnorableItems || !mpIgnorableItems->Count(),
414*cdf0e10cSrcweir                     "<StylePoolImpl::StylePoolImpl(..)> - <SfxItemSet::Clone( sal_False )> does not work as excepted - <mpIgnorableItems> is not empty. Please inform OD." );
415*cdf0e10cSrcweir     }
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir     ~StylePoolImpl()
418*cdf0e10cSrcweir     {
419*cdf0e10cSrcweir         delete mpIgnorableItems;
420*cdf0e10cSrcweir     }
421*cdf0e10cSrcweir     // <--
422*cdf0e10cSrcweir 
423*cdf0e10cSrcweir     StylePool::SfxItemSet_Pointer_t insertItemSet( const SfxItemSet& rSet );
424*cdf0e10cSrcweir 
425*cdf0e10cSrcweir     // --> OD 2008-03-07 #i86923#
426*cdf0e10cSrcweir     IStylePoolIteratorAccess* createIterator( bool bSkipUnusedItemSets = false,
427*cdf0e10cSrcweir                                               bool bSkipIgnorableItems = false );
428*cdf0e10cSrcweir     // <--
429*cdf0e10cSrcweir     sal_Int32 getCount() const { return mnCount; }
430*cdf0e10cSrcweir };
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir StylePool::SfxItemSet_Pointer_t StylePoolImpl::insertItemSet( const SfxItemSet& rSet )
433*cdf0e10cSrcweir {
434*cdf0e10cSrcweir     bool bNonPoolable = false;
435*cdf0e10cSrcweir     Node* pCurNode = &maRoot[ rSet.GetParent() ];
436*cdf0e10cSrcweir     SfxItemIter aIter( rSet );
437*cdf0e10cSrcweir     const SfxPoolItem* pItem = aIter.GetCurItem();
438*cdf0e10cSrcweir     // Every SfxPoolItem in the SfxItemSet causes a step deeper into the tree,
439*cdf0e10cSrcweir     // a complete empty SfxItemSet would stay at the root node.
440*cdf0e10cSrcweir     // --> OD 2008-03-07 #i86923#
441*cdf0e10cSrcweir     // insert ignorable items to the tree leaves.
442*cdf0e10cSrcweir     std::auto_ptr<SfxItemSet> pFoundIgnorableItems;
443*cdf0e10cSrcweir     if ( mpIgnorableItems )
444*cdf0e10cSrcweir     {
445*cdf0e10cSrcweir         pFoundIgnorableItems.reset( new SfxItemSet( *mpIgnorableItems ) );
446*cdf0e10cSrcweir     }
447*cdf0e10cSrcweir     while( pItem )
448*cdf0e10cSrcweir     {
449*cdf0e10cSrcweir         if( !rSet.GetPool()->IsItemFlag(pItem->Which(), SFX_ITEM_POOLABLE ) )
450*cdf0e10cSrcweir             bNonPoolable = true;
451*cdf0e10cSrcweir         if ( !pFoundIgnorableItems.get() ||
452*cdf0e10cSrcweir              ( pFoundIgnorableItems.get() &&
453*cdf0e10cSrcweir                pFoundIgnorableItems->Put( *pItem ) == 0 ) )
454*cdf0e10cSrcweir         {
455*cdf0e10cSrcweir             pCurNode = pCurNode->findChildNode( *pItem );
456*cdf0e10cSrcweir         }
457*cdf0e10cSrcweir 		pItem = aIter.NextItem();
458*cdf0e10cSrcweir     }
459*cdf0e10cSrcweir     if ( pFoundIgnorableItems.get() &&
460*cdf0e10cSrcweir          pFoundIgnorableItems->Count() > 0 )
461*cdf0e10cSrcweir     {
462*cdf0e10cSrcweir         SfxItemIter aIgnorableItemsIter( *pFoundIgnorableItems );
463*cdf0e10cSrcweir         pItem = aIgnorableItemsIter.GetCurItem();
464*cdf0e10cSrcweir         while( pItem )
465*cdf0e10cSrcweir         {
466*cdf0e10cSrcweir             if( !rSet.GetPool()->IsItemFlag(pItem->Which(), SFX_ITEM_POOLABLE ) )
467*cdf0e10cSrcweir                 bNonPoolable = true;
468*cdf0e10cSrcweir             pCurNode = pCurNode->findChildNode( *pItem, true );
469*cdf0e10cSrcweir             pItem = aIgnorableItemsIter.NextItem();
470*cdf0e10cSrcweir         }
471*cdf0e10cSrcweir     }
472*cdf0e10cSrcweir     // <--
473*cdf0e10cSrcweir     // Every leaf node represents an inserted item set, but "non-leaf" nodes represents subsets
474*cdf0e10cSrcweir     // of inserted itemsets.
475*cdf0e10cSrcweir     // These nodes could have but does not need to have a shared_ptr to a item set.
476*cdf0e10cSrcweir     if( !pCurNode->hasItemSet( false ) )
477*cdf0e10cSrcweir     {
478*cdf0e10cSrcweir         pCurNode->setItemSet( rSet );
479*cdf0e10cSrcweir         bNonPoolable = false; // to avoid a double insertion
480*cdf0e10cSrcweir         ++mnCount;
481*cdf0e10cSrcweir     }
482*cdf0e10cSrcweir     // If rSet contains at least one non poolable item, a new itemset has to be inserted
483*cdf0e10cSrcweir     if( bNonPoolable )
484*cdf0e10cSrcweir         pCurNode->setItemSet( rSet );
485*cdf0e10cSrcweir #ifdef DEBUG
486*cdf0e10cSrcweir     {
487*cdf0e10cSrcweir         sal_Int32 nCheck = -1;
488*cdf0e10cSrcweir         sal_Int32 nNo = -1;
489*cdf0e10cSrcweir         IStylePoolIteratorAccess* pIter = createIterator();
490*cdf0e10cSrcweir         StylePool::SfxItemSet_Pointer_t pTemp;
491*cdf0e10cSrcweir         do
492*cdf0e10cSrcweir         {
493*cdf0e10cSrcweir             ++nCheck;
494*cdf0e10cSrcweir             pTemp = pIter->getNext();
495*cdf0e10cSrcweir             if( pCurNode->hasItemSet( false ) && pTemp.get() == pCurNode->getItemSet().get() )
496*cdf0e10cSrcweir             {
497*cdf0e10cSrcweir                 ::rtl::OUString aStr = StylePool::nameOf( pTemp );
498*cdf0e10cSrcweir                 nNo = nCheck;
499*cdf0e10cSrcweir             }
500*cdf0e10cSrcweir         } while( pTemp.get() );
501*cdf0e10cSrcweir         DBG_ASSERT( mnCount == nCheck, "Wrong counting");
502*cdf0e10cSrcweir         delete pIter;
503*cdf0e10cSrcweir     }
504*cdf0e10cSrcweir #endif
505*cdf0e10cSrcweir     return pCurNode->getItemSet();
506*cdf0e10cSrcweir }
507*cdf0e10cSrcweir 
508*cdf0e10cSrcweir // --> OD 2008-03-07 #i86923#
509*cdf0e10cSrcweir IStylePoolIteratorAccess* StylePoolImpl::createIterator( bool bSkipUnusedItemSets,
510*cdf0e10cSrcweir                                                          bool bSkipIgnorableItems )
511*cdf0e10cSrcweir {
512*cdf0e10cSrcweir     return new Iterator( maRoot, bSkipUnusedItemSets, bSkipIgnorableItems );
513*cdf0e10cSrcweir }
514*cdf0e10cSrcweir // <--
515*cdf0e10cSrcweir 
516*cdf0e10cSrcweir // Ctor, Dtor and redirected methods of class StylePool, nearly inline ;-)
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir // --> OD 2008-03-07 #i86923#
519*cdf0e10cSrcweir StylePool::StylePool( SfxItemSet* pIgnorableItems )
520*cdf0e10cSrcweir     : pImpl( new StylePoolImpl( pIgnorableItems ) )
521*cdf0e10cSrcweir {}
522*cdf0e10cSrcweir // <--
523*cdf0e10cSrcweir 
524*cdf0e10cSrcweir StylePool::SfxItemSet_Pointer_t StylePool::insertItemSet( const SfxItemSet& rSet )
525*cdf0e10cSrcweir { return pImpl->insertItemSet( rSet ); }
526*cdf0e10cSrcweir 
527*cdf0e10cSrcweir // --> OD 2008-03-11 #i86923#
528*cdf0e10cSrcweir IStylePoolIteratorAccess* StylePool::createIterator( const bool bSkipUnusedItemSets,
529*cdf0e10cSrcweir                                                      const bool bSkipIgnorableItems )
530*cdf0e10cSrcweir {
531*cdf0e10cSrcweir     return pImpl->createIterator( bSkipUnusedItemSets, bSkipIgnorableItems );
532*cdf0e10cSrcweir }
533*cdf0e10cSrcweir // <--
534*cdf0e10cSrcweir 
535*cdf0e10cSrcweir sal_Int32 StylePool::getCount() const
536*cdf0e10cSrcweir { return pImpl->getCount(); }
537*cdf0e10cSrcweir 
538*cdf0e10cSrcweir StylePool::~StylePool() { delete pImpl; }
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir // End of class StylePool
541*cdf0e10cSrcweir 
542