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