xref: /trunk/main/UnoControls/source/base/basecontainercontrol.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 //____________________________________________________________________________________________________________
29 //  my own includes
30 //____________________________________________________________________________________________________________
31 
32 #include "basecontainercontrol.hxx"
33 
34 //____________________________________________________________________________________________________________
35 //  includes of other projects
36 //____________________________________________________________________________________________________________
37 #include <cppuhelper/typeprovider.hxx>
38 
39 //____________________________________________________________________________________________________________
40 //  includes of my own project
41 //____________________________________________________________________________________________________________
42 
43 //____________________________________________________________________________________________________________
44 //  namespaces
45 //____________________________________________________________________________________________________________
46 
47 using namespace ::cppu                      ;
48 using namespace ::osl                       ;
49 using namespace ::rtl                       ;
50 using namespace ::com::sun::star::uno       ;
51 using namespace ::com::sun::star::lang      ;
52 using namespace ::com::sun::star::awt       ;
53 using namespace ::com::sun::star::container ;
54 
55 namespace unocontrols{
56 
57 //____________________________________________________________________________________________________________
58 //  construct/destruct
59 //____________________________________________________________________________________________________________
60 
61 BaseContainerControl::BaseContainerControl( const Reference< XMultiServiceFactory >& xFactory )
62     : BaseControl   ( xFactory  )
63     , m_aListeners  ( m_aMutex  )
64 {
65     // initialize info list for controls
66     m_pControlInfoList = new IMPL_ControlInfoList ;
67 }
68 
69 BaseContainerControl::~BaseContainerControl()
70 {
71     impl_cleanMemory();
72 }
73 
74 //____________________________________________________________________________________________________________
75 //  XInterface
76 //____________________________________________________________________________________________________________
77 
78 Any SAL_CALL BaseContainerControl::queryInterface( const Type& rType ) throw( RuntimeException )
79 {
80     // Attention:
81     //  Don't use mutex or guard in this method!!! Is a method of XInterface.
82     Any aReturn ;
83     Reference< XInterface > xDel = BaseControl::impl_getDelegator();
84     if ( xDel.is() == sal_True )
85     {
86         // If an delegator exist, forward question to his queryInterface.
87         // Delegator will ask his own queryAggregation!
88         aReturn = xDel->queryInterface( rType );
89     }
90     else
91     {
92         // If an delegator unknown, forward question to own queryAggregation.
93         aReturn = queryAggregation( rType );
94     }
95 
96     return aReturn ;
97 }
98 
99 //____________________________________________________________________________________________________________
100 //  XTypeProvider
101 //____________________________________________________________________________________________________________
102 
103 Sequence< Type > SAL_CALL BaseContainerControl::getTypes() throw( RuntimeException )
104 {
105     // Optimize this method !
106     // We initialize a static variable only one time. And we don't must use a mutex at every call!
107     // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL!
108     static OTypeCollection* pTypeCollection = NULL ;
109 
110     if ( pTypeCollection == NULL )
111     {
112         // Ready for multithreading; get global mutex for first call of this method only! see before
113         MutexGuard aGuard( Mutex::getGlobalMutex() );
114 
115         // Control these pointer again ... it can be, that another instance will be faster then these!
116         if ( pTypeCollection == NULL )
117         {
118             // Create a static typecollection ...
119             static OTypeCollection aTypeCollection  (   ::getCppuType(( const Reference< XControlModel      >*)NULL )   ,
120                                                         ::getCppuType(( const Reference< XControlContainer  >*)NULL )   ,
121                                                         BaseControl::getTypes()
122                                                     );
123             // ... and set his address to static pointer!
124             pTypeCollection = &aTypeCollection ;
125         }
126     }
127 
128     return pTypeCollection->getTypes();
129 }
130 
131 //____________________________________________________________________________________________________________
132 //  XAggregation
133 //____________________________________________________________________________________________________________
134 
135 Any SAL_CALL BaseContainerControl::queryAggregation( const Type& aType ) throw( RuntimeException )
136 {
137     // Ask for my own supported interfaces ...
138     // Attention: XTypeProvider and XInterface are supported by OComponentHelper!
139     Any aReturn ( ::cppu::queryInterface(   aType                                       ,
140                                             static_cast< XControlModel*     > ( this )  ,
141                                             static_cast< XControlContainer* > ( this )
142                                         )
143                 );
144 
145     // If searched interface supported by this class ...
146     if ( aReturn.hasValue() == sal_True )
147     {
148         // ... return this information.
149         return aReturn ;
150     }
151     else
152     {
153         // Else; ... ask baseclass for interfaces!
154         return BaseControl::queryAggregation( aType );
155     }
156 }
157 
158 //____________________________________________________________________________________________________________
159 //  XControl
160 //____________________________________________________________________________________________________________
161 
162 void SAL_CALL BaseContainerControl::createPeer( const   Reference< XToolkit >&      xToolkit    ,
163                                                 const   Reference< XWindowPeer >&   xParent     ) throw( RuntimeException )
164 {
165     if ( getPeer().is() == sal_False )
166     {
167         // create own peer
168         BaseControl::createPeer( xToolkit, xParent );
169 
170         // create peers at all childs
171         Sequence< Reference< XControl > >   seqControlList  = getControls();
172         sal_uInt32                          nControls       = seqControlList.getLength();
173 
174         for ( sal_uInt32 n=0; n<nControls; n++ )
175         {
176             seqControlList.getArray()[n]->createPeer( xToolkit, getPeer() );
177         }
178 
179         // activate new tab order
180         impl_activateTabControllers();
181 
182 /*
183         Reference< XVclContainerPeer > xC;
184         mxPeer->queryInterface( ::getCppuType((const Reference< XVclContainerPeer >*)0), xC );
185         xC->enableDialogControl( sal_True );
186 */
187 
188     }
189 }
190 
191 //____________________________________________________________________________________________________________
192 //  XControl
193 //____________________________________________________________________________________________________________
194 
195 sal_Bool SAL_CALL BaseContainerControl::setModel( const Reference< XControlModel >& ) throw( RuntimeException )
196 {
197     // This object has NO model.
198     return sal_False ;
199 }
200 
201 //____________________________________________________________________________________________________________
202 //  XControl
203 //____________________________________________________________________________________________________________
204 
205 Reference< XControlModel > SAL_CALL BaseContainerControl::getModel() throw( RuntimeException )
206 {
207     // This object has NO model.
208     // return (XControlModel*)this ;
209     return Reference< XControlModel >();
210 }
211 
212 //____________________________________________________________________________________________________________
213 //  XComponent
214 //____________________________________________________________________________________________________________
215 
216 void SAL_CALL BaseContainerControl::dispose() throw( RuntimeException )
217 {
218     // Zuerst der Welt mitteilen, da� der Container wegfliegt. Dieses ist um einiges
219     // schneller wenn die Welt sowohl an den Controls als auch am Container horcht
220 
221     // Ready for multithreading
222     MutexGuard aGuard( m_aMutex );
223 
224     // remove listeners
225     EventObject aObject ;
226 
227     aObject.Source = Reference< XComponent > ( (XControlContainer*)this, UNO_QUERY );
228     m_aListeners.disposeAndClear( aObject );
229 
230     // remove controls
231     Sequence< Reference< XControl > >   seqCtrls    =   getControls();
232     Reference< XControl > *             pCtrls      =   seqCtrls.getArray();
233     sal_uInt32                          nCtrls      =   seqCtrls.getLength();
234     sal_uInt32                          nMaxCount   =   m_pControlInfoList->Count();
235     sal_uInt32                          nCount      =   0;
236 
237     for ( nCount = 0; nCount < nMaxCount; ++nCount )
238     {
239         delete m_pControlInfoList->GetObject( 0 );
240     }
241     m_pControlInfoList->Clear();
242 
243 
244     for ( nCount = 0; nCount < nCtrls; ++nCount )
245     {
246         pCtrls [ nCount ] -> removeEventListener    ( static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) ) ) ;
247         pCtrls [ nCount ] -> dispose                (       ) ;
248     }
249 
250     // call baseclass
251     BaseControl::dispose();
252 }
253 
254 //____________________________________________________________________________________________________________
255 //  XEventListener
256 //____________________________________________________________________________________________________________
257 
258 void SAL_CALL BaseContainerControl::disposing( const EventObject& rEvent ) throw( RuntimeException )
259 {
260     Reference< XControl > xControl( rEvent.Source, UNO_QUERY );
261 
262     // "removeControl" remove only, when control is an active control
263     removeControl( xControl );
264 }
265 
266 //____________________________________________________________________________________________________________
267 //  XControlContainer
268 //____________________________________________________________________________________________________________
269 
270 void SAL_CALL BaseContainerControl::addControl ( const OUString& rName, const Reference< XControl > & rControl ) throw( RuntimeException )
271 {
272     if ( !rControl.is () )
273         return;
274 
275     // take memory for new item
276     IMPL_ControlInfo* pNewControl = new IMPL_ControlInfo ;
277 
278     if (pNewControl!=(IMPL_ControlInfo*)0)
279     {
280         // Ready for multithreading
281         MutexGuard aGuard (m_aMutex) ;
282 
283         // set control
284         pNewControl->sName      = rName     ;
285         pNewControl->xControl   = rControl  ;
286 
287         // and insert in list
288         m_pControlInfoList->Insert ( pNewControl, LIST_APPEND ) ;
289 
290         // initialize new control
291         pNewControl->xControl->setContext       ( (OWeakObject*)this    ) ;
292         pNewControl->xControl->addEventListener ( static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) ) ) ;
293 
294         // when container has a peer ...
295         if (getPeer().is())
296         {
297             // .. then create a peer on child
298             pNewControl->xControl->createPeer ( getPeer()->getToolkit(), getPeer() ) ;
299             impl_activateTabControllers () ;
300         }
301 
302         // Send message to all listener
303         OInterfaceContainerHelper* pInterfaceContainer = m_aListeners.getContainer( ::getCppuType((const Reference< XContainerListener >*)0) ) ;
304 
305         if (pInterfaceContainer)
306         {
307             // Build event
308             ContainerEvent  aEvent ;
309 
310             aEvent.Source   = *this     ;
311             aEvent.Element <<= rControl ;
312 
313             // Get all listener
314             OInterfaceIteratorHelper    aIterator (*pInterfaceContainer) ;
315 
316             // Send event
317             while ( aIterator.hasMoreElements() )
318             {
319                 ((XContainerListener*)aIterator.next())->elementInserted (aEvent) ;
320             }
321         }
322     }
323 }
324 
325 //____________________________________________________________________________________________________________
326 //  XControlContainer
327 //____________________________________________________________________________________________________________
328 
329 void SAL_CALL BaseContainerControl::addContainerListener ( const Reference< XContainerListener > & rListener ) throw( RuntimeException )
330 {
331     // Ready for multithreading
332     MutexGuard aGuard ( m_aMutex ) ;
333 
334     m_aListeners.addInterface ( ::getCppuType((const Reference< XContainerListener >*)0), rListener ) ;
335 }
336 
337 //____________________________________________________________________________________________________________
338 //  XControlContainer
339 //____________________________________________________________________________________________________________
340 
341 void SAL_CALL BaseContainerControl::removeControl ( const Reference< XControl > & rControl ) throw( RuntimeException )
342 {
343     if ( rControl.is() )
344     {
345         // Ready for multithreading
346         MutexGuard aGuard (m_aMutex) ;
347 
348         sal_uInt32 nControls = m_pControlInfoList->Count () ;
349 
350         for ( sal_uInt32 n=0; n<nControls; n++ )
351         {
352             // Search for right control
353             IMPL_ControlInfo* pControl = m_pControlInfoList->GetObject (n) ;
354             if ( rControl == pControl->xControl )
355             {
356                 //.is it found ... remove listener from control
357                 pControl->xControl->removeEventListener (static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) )) ;
358                 pControl->xControl->setContext          ( Reference< XInterface >  ()   ) ;
359 
360                 // ... free memory
361                 delete pControl ;
362                 m_pControlInfoList->Remove (n) ;
363 
364                 // Send message to all other listener
365                 OInterfaceContainerHelper * pInterfaceContainer = m_aListeners.getContainer( ::getCppuType((const Reference< XContainerListener >*)0) ) ;
366 
367                 if (pInterfaceContainer)
368                 {
369                     ContainerEvent  aEvent ;
370 
371                     aEvent.Source    = *this    ;
372                     aEvent.Element <<= rControl ;
373 
374                     OInterfaceIteratorHelper    aIterator (*pInterfaceContainer) ;
375 
376                     while ( aIterator.hasMoreElements() )
377                     {
378                         ((XContainerListener*)aIterator.next())->elementRemoved (aEvent) ;
379                     }
380                 }
381                 // Break "for" !
382                 break ;
383             }
384         }
385     }
386 }
387 
388 //____________________________________________________________________________________________________________
389 //  XControlContainer
390 //____________________________________________________________________________________________________________
391 
392 void SAL_CALL BaseContainerControl::removeContainerListener ( const Reference< XContainerListener > & rListener ) throw( RuntimeException )
393 {
394     // Ready for multithreading
395     MutexGuard aGuard ( m_aMutex ) ;
396 
397     m_aListeners.removeInterface ( ::getCppuType((const Reference< XContainerListener >*)0), rListener ) ;
398 }
399 
400 //____________________________________________________________________________________________________________
401 //  XControlContainer
402 //____________________________________________________________________________________________________________
403 
404 void SAL_CALL BaseContainerControl::setStatusText ( const OUString& rStatusText ) throw( RuntimeException )
405 {
406     // go down to each parent
407     Reference< XControlContainer >  xContainer ( getContext(), UNO_QUERY ) ;
408 
409     if ( xContainer.is () )
410     {
411         xContainer->setStatusText ( rStatusText ) ;
412     }
413 }
414 
415 //____________________________________________________________________________________________________________
416 //  XControlContainer
417 //____________________________________________________________________________________________________________
418 
419 Reference< XControl > SAL_CALL BaseContainerControl::getControl ( const OUString& rName ) throw( RuntimeException )
420 {
421     // Ready for multithreading
422     MutexGuard  aGuard ( Mutex::getGlobalMutex() ) ;
423 
424     Reference< XControl >  xRetControl  =   Reference< XControl >       () ;
425     sal_uInt32              nControls   =   m_pControlInfoList->Count   () ;
426 
427     // Search for right control
428     for( sal_uInt32 nCount = 0; nCount < nControls; ++nCount )
429     {
430         IMPL_ControlInfo* pSearchControl = m_pControlInfoList->GetObject ( nCount ) ;
431 
432         if ( pSearchControl->sName == rName )
433         {
434             // We have found it ...
435             // Break operation and return.
436             return pSearchControl->xControl ;
437         }
438     }
439 
440     // We have not found it ... return NULL.
441     return Reference< XControl >  () ;
442 }
443 
444 //____________________________________________________________________________________________________________
445 //  XControlContainer
446 //____________________________________________________________________________________________________________
447 
448 Sequence< Reference< XControl > > SAL_CALL BaseContainerControl::getControls () throw( RuntimeException )
449 {
450     // Ready for multithreading
451     MutexGuard  aGuard ( Mutex::getGlobalMutex() ) ;
452 
453     sal_uInt32                          nControls       = m_pControlInfoList->Count ()  ;
454     Sequence< Reference< XControl > >   aDescriptor     ( nControls )                   ;
455     Reference< XControl > *             pDestination    = aDescriptor.getArray ()       ;
456     sal_uInt32                          nCount          = 0                             ;
457 
458     // Copy controls to sequence
459     for( nCount = 0; nCount < nControls; ++nCount )
460     {
461         IMPL_ControlInfo* pCopyControl = m_pControlInfoList->GetObject ( nCount ) ;
462         pDestination [ nCount ] = pCopyControl->xControl ;
463     }
464 
465     // Return sequence
466     return aDescriptor ;
467 }
468 
469 //____________________________________________________________________________________________________________
470 //  XUnoControlContainer
471 //____________________________________________________________________________________________________________
472 
473 void SAL_CALL BaseContainerControl::addTabController ( const Reference< XTabController > & rTabController ) throw( RuntimeException )
474 {
475     // Ready for multithreading
476     MutexGuard aGuard (m_aMutex) ;
477 
478     sal_uInt32                                  nOldCount   = m_xTabControllerList.getLength () ;
479     Sequence< Reference< XTabController >  >    aNewList    ( nOldCount + 1 )                   ;
480     sal_uInt32                                  nCount      = 0                                 ;
481 
482     // Copy old elements of sequence to new list.
483     for ( nCount = 0; nCount < nOldCount; ++nCount )
484     {
485         aNewList.getArray () [nCount] = m_xTabControllerList.getConstArray () [nCount] ;
486     }
487 
488     // Add new controller
489     aNewList.getArray () [nOldCount] = rTabController ;
490 
491     // change old and new list
492     m_xTabControllerList = aNewList ;
493 }
494 
495 //____________________________________________________________________________________________________________
496 //  XUnoControlContainer
497 //____________________________________________________________________________________________________________
498 
499 void SAL_CALL BaseContainerControl::removeTabController ( const Reference< XTabController > & rTabController ) throw( RuntimeException )
500 {
501     // Ready for multithreading
502     MutexGuard aGuard (m_aMutex) ;
503 
504     sal_uInt32  nMaxCount   = m_xTabControllerList.getLength () ;
505     sal_uInt32  nCount      = 0                                 ;
506 
507     // Search right tabcontroller ...
508     for ( nCount = 0; nCount < nMaxCount; ++nCount )
509     {
510         if ( m_xTabControllerList.getConstArray () [nCount] == rTabController )
511         {
512             // ... if is it found ... remove it from list.
513             m_xTabControllerList.getArray()[ nCount ] = Reference< XTabController >() ;
514             break ;
515         }
516     }
517 }
518 
519 //____________________________________________________________________________________________________________
520 //  XUnoControlContainer
521 //____________________________________________________________________________________________________________
522 
523 void SAL_CALL BaseContainerControl::setTabControllers ( const Sequence< Reference< XTabController >  >& rTabControllers ) throw( RuntimeException )
524 {
525     // Ready for multithreading
526     MutexGuard aGuard (m_aMutex) ;
527 
528     m_xTabControllerList = rTabControllers ;
529 }
530 
531 Sequence<Reference< XTabController > > SAL_CALL BaseContainerControl::getTabControllers () throw( RuntimeException )
532 {
533     // Ready for multithreading
534     MutexGuard aGuard (m_aMutex) ;
535 
536     return m_xTabControllerList ;
537 }
538 
539 //____________________________________________________________________________________________________________
540 //  XWindow
541 //____________________________________________________________________________________________________________
542 
543 void SAL_CALL BaseContainerControl::setVisible ( sal_Bool bVisible ) throw( RuntimeException )
544 {
545     // override baseclass definition
546     BaseControl::setVisible ( bVisible ) ;
547 
548     // is it a top window ?
549     if ( !getContext().is() && bVisible )
550     {
551         // then show it automaticly
552         createPeer ( Reference< XToolkit > (), Reference< XWindowPeer > () ) ;
553     }
554 }
555 
556 //____________________________________________________________________________________________________________
557 //  protected method
558 //____________________________________________________________________________________________________________
559 
560 WindowDescriptor* BaseContainerControl::impl_getWindowDescriptor ( const Reference< XWindowPeer > & rParentPeer )
561 {
562     // - used from "createPeer()" to set the values of an WindowDescriptor !!!
563     // - if you will change the descriptor-values, you must override thid virtuell function
564     // - the caller must release the memory for this dynamical descriptor !!!
565 
566     WindowDescriptor    *   aDescriptor = new WindowDescriptor ;
567 
568     aDescriptor->Type               = WindowClass_CONTAINER                             ;
569     aDescriptor->WindowServiceName  = OUString(RTL_CONSTASCII_USTRINGPARAM("window"))   ;
570     aDescriptor->ParentIndex        = -1                                                ;
571     aDescriptor->Parent             = rParentPeer                                       ;
572     aDescriptor->Bounds             = getPosSize ()                                     ;
573     aDescriptor->WindowAttributes   = 0                                                 ;
574 
575     return aDescriptor ;
576 }
577 
578 //____________________________________________________________________________________________________________
579 //  protected method
580 //____________________________________________________________________________________________________________
581 
582 void BaseContainerControl::impl_paint ( sal_Int32 /*nX*/, sal_Int32 /*nY*/, const Reference< XGraphics > & /*rGraphics*/ )
583 {
584 /*
585     if (rGraphics.is())
586     {
587         for ( sal_uInt32 n=m_pControlInfoList->Count(); n; )
588         {
589             ControlInfo* pSearchControl = m_pControlInfoList->GetObject (--n) ;
590 
591             pSearchControl->xControl->paint ( nX, nY, rGraphics ) ;
592         }
593     }
594 */
595 }
596 
597 //____________________________________________________________________________________________________________
598 //  private method
599 //____________________________________________________________________________________________________________
600 
601 void BaseContainerControl::impl_activateTabControllers ()
602 {
603     // Ready for multithreading
604     MutexGuard aGuard (m_aMutex) ;
605 
606     sal_uInt32  nMaxCount   =   m_xTabControllerList.getLength ()   ;
607     sal_uInt32  nCount      =   0                                   ;
608 
609     for ( nCount = 0; nCount < nMaxCount; ++nCount )
610     {
611         m_xTabControllerList.getArray () [nCount]->setContainer     ( this  ) ;
612         m_xTabControllerList.getArray () [nCount]->activateTabOrder (       ) ;
613     }
614 }
615 
616 //____________________________________________________________________________________________________________
617 //  private method
618 //____________________________________________________________________________________________________________
619 
620 void BaseContainerControl::impl_cleanMemory ()
621 {
622     // Get count of listitems.
623     sal_uInt32  nMaxCount   =   m_pControlInfoList->Count ()    ;
624     sal_uInt32  nCount      =   0                               ;
625 
626     // Delete all items.
627     for ( nCount = 0; nCount < nMaxCount; ++nCount )
628     {
629         // Delete everytime first element of list!
630         // We count from 0 to MAX, where "MAX=count of items" BEFORE we delete some elements!
631         // If we use "GetObject ( nCount )" ... it can be, that we have an index greater then count of current elements!
632 
633         IMPL_ControlInfo* pSearchControl = m_pControlInfoList->GetObject ( 0 ) ;
634         delete pSearchControl ;
635     }
636 
637     // Delete list himself.
638     m_pControlInfoList->Clear () ;
639     delete m_pControlInfoList ;
640 }
641 
642 } // namespace unocontrols
643