xref: /trunk/main/framework/source/helper/oframes.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_________________________________________________________________________________________________________________
32 //  my own includes
33 //_________________________________________________________________________________________________________________
34 #include <helper/oframes.hxx>
35 
36 #ifndef _FRAMEWORK_THREADHELP_RESETABLEGUARD_HXX_
37 #include <threadhelp/resetableguard.hxx>
38 #endif
39 
40 //_________________________________________________________________________________________________________________
41 //  interface includes
42 //_________________________________________________________________________________________________________________
43 #include <com/sun/star/frame/XDesktop.hpp>
44 #include <com/sun/star/frame/FrameSearchFlag.hpp>
45 
46 //_________________________________________________________________________________________________________________
47 //  includes of other projects
48 //_________________________________________________________________________________________________________________
49 #include <vcl/svapp.hxx>
50 
51 //_________________________________________________________________________________________________________________
52 //  namespace
53 //_________________________________________________________________________________________________________________
54 
55 namespace framework{
56 
57 using namespace ::com::sun::star::container     ;
58 using namespace ::com::sun::star::frame         ;
59 using namespace ::com::sun::star::lang          ;
60 using namespace ::com::sun::star::uno           ;
61 using namespace ::cppu                          ;
62 using namespace ::osl                           ;
63 using namespace ::rtl                           ;
64 using namespace ::std                           ;
65 using namespace ::vos                           ;
66 
67 //_________________________________________________________________________________________________________________
68 //  non exported const
69 //_________________________________________________________________________________________________________________
70 
71 //_________________________________________________________________________________________________________________
72 //  non exported definitions
73 //_________________________________________________________________________________________________________________
74 
75 //_________________________________________________________________________________________________________________
76 //  declarations
77 //_________________________________________________________________________________________________________________
78 
79 //*****************************************************************************************************************
80 //  constructor
81 //*****************************************************************************************************************
82 OFrames::OFrames(   const   css::uno::Reference< XMultiServiceFactory >&    xFactory        ,
83                     const   css::uno::Reference< XFrame >&              xOwner          ,
84                             FrameContainer*                     pFrameContainer )
85         //  Init baseclasses first
86         :   ThreadHelpBase              ( &Application::GetSolarMutex() )
87         // Init member
88         ,   m_xFactory                  ( xFactory                      )
89         ,   m_xOwner                    ( xOwner                        )
90         ,   m_pFrameContainer           ( pFrameContainer               )
91         ,   m_bRecursiveSearchProtection( sal_False                     )
92 {
93     // Safe impossible cases
94     // Method is not defined for ALL incoming parameters!
95     LOG_ASSERT( impldbg_checkParameter_OFramesCtor( xFactory, xOwner, pFrameContainer ), "OFrames::OFrames()\nInvalid parameter detected!\n" )
96 }
97 
98 //*****************************************************************************************************************
99 //  (proteced!) destructor
100 //*****************************************************************************************************************
101 OFrames::~OFrames()
102 {
103     // Reset instance, free memory ....
104     impl_resetObject();
105 }
106 
107 //*****************************************************************************************************************
108 //  XFrames
109 //*****************************************************************************************************************
110 void SAL_CALL OFrames::append( const css::uno::Reference< XFrame >& xFrame ) throw( RuntimeException )
111 {
112     // Ready for multithreading
113     ResetableGuard aGuard( m_aLock );
114 
115     // Safe impossible cases
116     // Method is not defined for ALL incoming parameters!
117     LOG_ASSERT( impldbg_checkParameter_append( xFrame ), "OFrames::append()\nInvalid parameter detected!\n" )
118 
119     // Do the follow only, if owner instance valid!
120     // Lock owner for follow operations - make a "hard reference"!
121     css::uno::Reference< XFramesSupplier > xOwner( m_xOwner.get(), UNO_QUERY );
122     if ( xOwner.is() == sal_True )
123     {
124         // Append frame to the end of the container ...
125         m_pFrameContainer->append( xFrame );
126         // Set owner of this instance as parent of the new frame in container!
127         xFrame->setCreator( xOwner );
128     }
129     // Else; Do nothing! Ouer owner is dead.
130     LOG_ASSERT( !(xOwner.is()==sal_False), "OFrames::append()\nOuer owner is dead - you can't append any frames ...!\n" )
131 }
132 
133 //*****************************************************************************************************************
134 //  XFrames
135 //*****************************************************************************************************************
136 void SAL_CALL OFrames::remove( const css::uno::Reference< XFrame >& xFrame ) throw( RuntimeException )
137 {
138     // Ready for multithreading
139     ResetableGuard aGuard( m_aLock );
140 
141     // Safe impossible cases
142     // Method is not defined for ALL incoming parameters!
143     LOG_ASSERT( impldbg_checkParameter_remove( xFrame ), "OFrames::remove()\nInvalid parameter detected!\n" )
144 
145     // Do the follow only, if owner instance valid!
146     // Lock owner for follow operations - make a "hard reference"!
147     css::uno::Reference< XFramesSupplier > xOwner( m_xOwner.get(), UNO_QUERY );
148     if ( xOwner.is() == sal_True )
149     {
150         // Search frame and remove it from container ...
151         m_pFrameContainer->remove( xFrame );
152         // Don't reset owner-property of removed frame!
153         // This must do the caller of this method himself.
154         // See documentation of interface XFrames for further informations.
155     }
156     // Else; Do nothing! Ouer owner is dead.
157     LOG_ASSERT( !(xOwner.is()==sal_False), "OFrames::remove()\nOuer owner is dead - you can't remove any frames ...!\n" )
158 }
159 
160 //*****************************************************************************************************************
161 //  XFrames
162 //*****************************************************************************************************************
163 Sequence< css::uno::Reference< XFrame > > SAL_CALL OFrames::queryFrames( sal_Int32 nSearchFlags ) throw( RuntimeException )
164 {
165     // Ready for multithreading
166     ResetableGuard aGuard( m_aLock );
167 
168     // Safe impossible cases
169     // Method is not defined for ALL incoming parameters!
170     LOG_ASSERT( impldbg_checkParameter_queryFrames( nSearchFlags ), "OFrames::queryFrames()\nInvalid parameter detected!\n" )
171 
172     // Set default return value. (empty sequence)
173     Sequence< css::uno::Reference< XFrame > > seqFrames;
174 
175     // Do the follow only, if owner instance valid.
176     // Lock owner for follow operations - make a "hard reference"!
177     css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY );
178     if ( xOwner.is() == sal_True )
179     {
180         // Work only, if search was not started here ...!
181         if( m_bRecursiveSearchProtection == sal_False )
182         {
183             // This class is a helper for services, which must implement XFrames.
184             // His parent and childs are MY parent and childs to.
185             // All searchflags are supported by this implementation!
186             // If some flags should not be supported - don't call me with this flags!!!
187 
188             //_____________________________________________________________________________________________________________
189             // Search with AUTO-flag is not supported yet!
190             // We think about right implementation.
191             LOG_ASSERT( !(nSearchFlags & FrameSearchFlag::AUTO), "OFrames::queryFrames()\nSearch with AUTO-flag is not supported yet!\nWe think about right implementation.\n" )
192             // If searched for tasks ...
193             // Its not supported yet.
194             LOG_ASSERT( !(nSearchFlags & FrameSearchFlag::AUTO), "OFrames::queryFrames()\nSearch for tasks not supported yet!\n" )
195 
196             //_____________________________________________________________________________________________________________
197             // Search for ALL and GLOBAL is superflous!
198             // We support all necessary flags, from which these two flags are derived.
199             //      ALL     = PARENT + SELF  + CHILDREN + SIBLINGS
200             //      GLOBAL  = ALL    + TASKS
201 
202             //_____________________________________________________________________________________________________________
203             // Add parent to list ... if any exist!
204             if( nSearchFlags & FrameSearchFlag::PARENT )
205             {
206                 css::uno::Reference< XFrame > xParent( xOwner->getCreator(), UNO_QUERY );
207                 if( xParent.is() == sal_True )
208                 {
209                     Sequence< css::uno::Reference< XFrame > > seqParent( 1 );
210                     seqParent[0] = xParent;
211                     impl_appendSequence( seqFrames, seqParent );
212                 }
213             }
214 
215             //_____________________________________________________________________________________________________________
216             // Add owner to list if SELF is searched.
217             if( nSearchFlags & FrameSearchFlag::SELF )
218             {
219                 Sequence< css::uno::Reference< XFrame > > seqSelf( 1 );
220                 seqSelf[0] = xOwner;
221                 impl_appendSequence( seqFrames, seqSelf );
222             }
223 
224             //_____________________________________________________________________________________________________________
225             // Add SIBLINGS to list.
226             if( nSearchFlags & FrameSearchFlag::SIBLINGS )
227             {
228                 // Else; start a new search.
229                 // Protect this instance against recursive calls from parents.
230                 m_bRecursiveSearchProtection = sal_True;
231                 // Ask parent of my owner for frames and append results to return list.
232                 css::uno::Reference< XFramesSupplier > xParent( xOwner->getCreator(), UNO_QUERY );
233                 // If a parent exist ...
234                 if ( xParent.is() == sal_True )
235                 {
236                     // ... ask him for right frames.
237                     impl_appendSequence( seqFrames, xParent->getFrames()->queryFrames( nSearchFlags ) );
238                 }
239                 // We have all searched informations.
240                 // Reset protection-mode.
241                 m_bRecursiveSearchProtection = sal_False;
242             }
243 
244             //_____________________________________________________________________________________________________________
245             // If searched for children, step over all elements in container and collect the informations.
246             if ( nSearchFlags & FrameSearchFlag::CHILDREN )
247             {
248                 // Don't search for parents, siblings and self at childrens!
249                 // These things are supported by this instance himself.
250                 sal_Int32 nChildSearchFlags = FrameSearchFlag::SELF | FrameSearchFlag::CHILDREN;
251                 // Step over all items of container and ask childrens for frames.
252                 sal_uInt32 nCount = m_pFrameContainer->getCount();
253                 for ( sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex )
254                 {
255                     // We don't must control this conversion.
256                     // We have done this at append()!
257                     css::uno::Reference< XFramesSupplier > xItem( (*m_pFrameContainer)[nIndex], UNO_QUERY );
258                     impl_appendSequence( seqFrames, xItem->getFrames()->queryFrames( nChildSearchFlags ) );
259                 }
260             }
261         }
262     }
263     // Else; Do nothing! Ouer owner is dead.
264     LOG_ASSERT( !(xOwner.is()==sal_False), "OFrames::queryFrames()\nOuer owner is dead - you can't query for frames ...!\n" )
265 
266     // Resturn result of this operation.
267     return seqFrames;
268 }
269 
270 //*****************************************************************************************************************
271 //  XIndexAccess
272 //*****************************************************************************************************************
273 sal_Int32 SAL_CALL OFrames::getCount() throw( RuntimeException )
274 {
275     // Ready for multithreading
276     ResetableGuard aGuard( m_aLock );
277 
278     // Set default return value.
279     sal_Int32 nCount = 0;
280 
281     // Do the follow only, if owner instance valid.
282     // Lock owner for follow operations - make a "hard reference"!
283     css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY );
284     if ( xOwner.is() == sal_True )
285     {
286         // Set CURRENT size of container for return.
287         nCount = m_pFrameContainer->getCount();
288     }
289 
290     // Return result.
291     return nCount;
292 }
293 
294 //*****************************************************************************************************************
295 //  XIndexAccess
296 //*****************************************************************************************************************
297 Any SAL_CALL OFrames::getByIndex( sal_Int32 nIndex ) throw( IndexOutOfBoundsException   ,
298                                                             WrappedTargetException      ,
299                                                             RuntimeException            )
300 {
301     // Ready for multithreading
302     ResetableGuard aGuard( m_aLock );
303 
304       sal_uInt32 nCount = m_pFrameContainer->getCount();
305       if ( nIndex < 0 || ( sal::static_int_cast< sal_uInt32 >( nIndex ) >= nCount ))
306           throw IndexOutOfBoundsException( OUString::createFromAscii( "OFrames::getByIndex - Index out of bounds" ),
307                                            (OWeakObject *)this );
308 
309     // Set default return value.
310     Any aReturnValue;
311 
312     // Do the follow only, if owner instance valid.
313     // Lock owner for follow operations - make a "hard reference"!
314     css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY );
315     if ( xOwner.is() == sal_True )
316     {
317         // Get element form container.
318         // (If index not valid, FrameContainer return NULL!)
319             aReturnValue <<= (*m_pFrameContainer)[nIndex];
320     }
321 
322     // Return result of this operation.
323     return aReturnValue;
324 }
325 
326 //*****************************************************************************************************************
327 //  XElementAccess
328 //*****************************************************************************************************************
329 Type SAL_CALL OFrames::getElementType() throw( RuntimeException )
330 {
331     // This "container" support XFrame-interfaces only!
332     return ::getCppuType( (const css::uno::Reference< XFrame >*)NULL );
333 }
334 
335 //*****************************************************************************************************************
336 //  XElementAccess
337 //*****************************************************************************************************************
338 sal_Bool SAL_CALL OFrames::hasElements() throw( RuntimeException )
339 {
340     // Ready for multithreading
341     ResetableGuard aGuard( m_aLock );
342 
343     // Set default return value.
344     sal_Bool bHasElements = sal_False;
345     // Do the follow only, if owner instance valid.
346     // Lock owner for follow operations - make a "hard reference"!
347     css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY );
348     if ( xOwner.is() == sal_True )
349     {
350         // If some elements exist ...
351         if ( m_pFrameContainer->getCount() > 0 )
352         {
353             // ... change this state value!
354             bHasElements = sal_True;
355         }
356     }
357     // Return result of this operation.
358     return bHasElements;
359 }
360 
361 //*****************************************************************************************************************
362 //  proteced method
363 //*****************************************************************************************************************
364 void OFrames::impl_resetObject()
365 {
366     // Attention:
367     // Write this for multiple calls - NOT AT THE SAME TIME - but for more then one call again)!
368     // It exist two ways to call this method. From destructor and from disposing().
369     // I can't say, which one is the first. Normaly the disposing-call - but other way ....
370 
371     // This instance can't work if the weakreference to owner is invalid!
372     // Destroy this to reset this object.
373     m_xOwner = WeakReference< XFrame >();
374     // Reset pointer to shared container to!
375     m_pFrameContainer = NULL;
376 }
377 
378 //*****************************************************************************************************************
379 //  private method
380 //*****************************************************************************************************************
381 void OFrames::impl_appendSequence(          Sequence< css::uno::Reference< XFrame > >&  seqDestination  ,
382                                     const   Sequence< css::uno::Reference< XFrame > >&  seqSource       )
383 {
384     // Get some informations about the sequences.
385     sal_Int32                       nSourceCount        = seqSource.getLength();
386     sal_Int32                       nDestinationCount   = seqDestination.getLength();
387     const css::uno::Reference< XFrame >*        pSourceAccess       = seqSource.getConstArray();
388     css::uno::Reference< XFrame >*          pDestinationAccess  = seqDestination.getArray();
389 
390     // Get memory for result list.
391     Sequence< css::uno::Reference< XFrame > >   seqResult           ( nSourceCount + nDestinationCount );
392     css::uno::Reference< XFrame >*          pResultAccess       = seqResult.getArray();
393     sal_Int32                       nResultPosition     = 0;
394 
395     // Copy all items from first sequence.
396     for ( sal_Int32 nSourcePosition=0; nSourcePosition<nSourceCount; ++nSourcePosition )
397     {
398         pResultAccess[nResultPosition] = pSourceAccess[nSourcePosition];
399         ++nResultPosition;
400     }
401 
402     // Don't manipulate nResultPosition between these two loops!
403     // Its the current position in the result list.
404 
405     // Copy all items from second sequence.
406     for ( sal_Int32 nDestinationPosition=0; nDestinationPosition<nDestinationCount; ++nDestinationPosition )
407     {
408         pResultAccess[nResultPosition] = pDestinationAccess[nDestinationPosition];
409         ++nResultPosition;
410     }
411 
412     // Return result of this operation.
413     seqDestination.realloc( 0 );
414     seqDestination = seqResult;
415 }
416 
417 //_________________________________________________________________________________________________________________
418 //  debug methods
419 //_________________________________________________________________________________________________________________
420 
421 /*-----------------------------------------------------------------------------------------------------------------
422     The follow methods checks the parameter for other functions. If a parameter or his value is non valid,
423     we return "sal_False". (else sal_True) This mechanism is used to throw an ASSERT!
424 
425     ATTENTION
426 
427         If you miss a test for one of this parameters, contact the autor or add it himself !(?)
428         But ... look for right testing! See using of this methods!
429 -----------------------------------------------------------------------------------------------------------------*/
430 
431 #ifdef ENABLE_ASSERTIONS
432 
433 //*****************************************************************************************************************
434 // An instance of this class can only work with valid initialization.
435 // We share the mutex with ouer owner class, need a valid factory to instanciate new services and
436 // use the access to ouer owner for some operations.
437 sal_Bool OFrames::impldbg_checkParameter_OFramesCtor(   const   css::uno::Reference< XMultiServiceFactory >&    xFactory        ,
438                                                         const   css::uno::Reference< XFrame >&              xOwner          ,
439                                                                 FrameContainer*                     pFrameContainer )
440 {
441     // Set default return value.
442     sal_Bool bOK = sal_True;
443     // Check parameter.
444     if  (
445             ( &xFactory         ==  NULL        )   ||
446             ( &xOwner           ==  NULL        )   ||
447             ( xFactory.is()     ==  sal_False   )   ||
448             ( xOwner.is()       ==  sal_False   )   ||
449             ( pFrameContainer   ==  NULL        )
450         )
451     {
452         bOK = sal_False ;
453     }
454     // Return result of check.
455     return bOK ;
456 }
457 
458 //*****************************************************************************************************************
459 // Its only allowed to add valid references to container.
460 // AND - alle frames must support XFrames-interface!
461 sal_Bool OFrames::impldbg_checkParameter_append( const css::uno::Reference< XFrame >& xFrame )
462 {
463     // Set default return value.
464     sal_Bool bOK = sal_True;
465     // Check parameter.
466     if  (
467             ( &xFrame       ==  NULL        )   ||
468             ( xFrame.is()   ==  sal_False   )
469         )
470     {
471         bOK = sal_False ;
472     }
473     // Return result of check.
474     return bOK ;
475 }
476 
477 //*****************************************************************************************************************
478 // Its only allowed to add valid references to container...
479 // ... => You can only delete valid references!
480 sal_Bool OFrames::impldbg_checkParameter_remove( const css::uno::Reference< XFrame >& xFrame )
481 {
482     // Set default return value.
483     sal_Bool bOK = sal_True;
484     // Check parameter.
485     if  (
486             ( &xFrame       ==  NULL        )   ||
487             ( xFrame.is()   ==  sal_False   )
488         )
489     {
490         bOK = sal_False ;
491     }
492     // Return result of check.
493     return bOK ;
494 }
495 
496 //*****************************************************************************************************************
497 // A search for frames must initiate with right flags.
498 // Some one are superflous and not supported yet. But here we control only the range of incoming parameter!
499 sal_Bool OFrames::impldbg_checkParameter_queryFrames( sal_Int32 nSearchFlags )
500 {
501     // Set default return value.
502     sal_Bool bOK = sal_True;
503     // Check parameter.
504     if  (
505             (    nSearchFlags != FrameSearchFlag::AUTO        ) &&
506             ( !( nSearchFlags &  FrameSearchFlag::PARENT    ) ) &&
507             ( !( nSearchFlags &  FrameSearchFlag::SELF      ) ) &&
508             ( !( nSearchFlags &  FrameSearchFlag::CHILDREN  ) ) &&
509             ( !( nSearchFlags &  FrameSearchFlag::CREATE    ) ) &&
510             ( !( nSearchFlags &  FrameSearchFlag::SIBLINGS  ) ) &&
511             ( !( nSearchFlags &  FrameSearchFlag::TASKS     ) ) &&
512             ( !( nSearchFlags &  FrameSearchFlag::ALL       ) ) &&
513             ( !( nSearchFlags &  FrameSearchFlag::GLOBAL    ) )
514         )
515     {
516         bOK = sal_False ;
517     }
518     // Return result of check.
519     return bOK ;
520 }
521 
522 #endif  //  #ifdef ENABLE_ASSERTIONS
523 
524 }       //  namespace framework
525