xref: /AOO41X/main/UnoControls/source/base/basecontainercontrol.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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