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