Line data Source code
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 : // namespaces
25 :
26 : using namespace ::cppu;
27 : using namespace ::osl;
28 : using namespace ::rtl;
29 : using namespace ::com::sun::star::uno;
30 : using namespace ::com::sun::star::lang;
31 : using namespace ::com::sun::star::awt;
32 : using namespace ::com::sun::star::container;
33 :
34 : namespace unocontrols{
35 :
36 : // construct/destruct
37 :
38 0 : BaseContainerControl::BaseContainerControl( const Reference< XComponentContext >& rxContext )
39 : : BaseControl ( rxContext )
40 0 : , m_aListeners ( m_aMutex )
41 : {
42 0 : }
43 :
44 0 : BaseContainerControl::~BaseContainerControl()
45 : {
46 0 : impl_cleanMemory();
47 0 : }
48 :
49 : // XInterface
50 :
51 0 : Any SAL_CALL BaseContainerControl::queryInterface( const Type& rType ) throw( RuntimeException, std::exception )
52 : {
53 : // Attention:
54 : // Don't use mutex or guard in this method!!! Is a method of XInterface.
55 0 : Any aReturn;
56 0 : Reference< XInterface > xDel = BaseControl::impl_getDelegator();
57 0 : if ( xDel.is() )
58 : {
59 : // If an delegator exist, forward question to his queryInterface.
60 : // Delegator will ask his own queryAggregation!
61 0 : aReturn = xDel->queryInterface( rType );
62 : }
63 : else
64 : {
65 : // If an delegator unknown, forward question to own queryAggregation.
66 0 : aReturn = queryAggregation( rType );
67 : }
68 :
69 0 : return aReturn;
70 : }
71 :
72 : // XTypeProvider
73 :
74 0 : Sequence< Type > SAL_CALL BaseContainerControl::getTypes() throw( RuntimeException, std::exception )
75 : {
76 : // Optimize this method !
77 : // We initialize a static variable only one time. And we don't must use a mutex at every call!
78 : // For the first call; pTypeCollection is NULL - for the second call pTypeCollection is different from NULL!
79 : static OTypeCollection* pTypeCollection = NULL;
80 :
81 0 : if ( pTypeCollection == NULL )
82 : {
83 : // Ready for multithreading; get global mutex for first call of this method only! see before
84 0 : MutexGuard aGuard( Mutex::getGlobalMutex() );
85 :
86 : // Control these pointer again ... it can be, that another instance will be faster then these!
87 0 : if ( pTypeCollection == NULL )
88 : {
89 : // Create a static typecollection ...
90 0 : static OTypeCollection aTypeCollection ( ::getCppuType(( const Reference< XControlModel >*)NULL ) ,
91 0 : ::getCppuType(( const Reference< XControlContainer >*)NULL ) ,
92 : BaseControl::getTypes()
93 0 : );
94 : // ... and set his address to static pointer!
95 0 : pTypeCollection = &aTypeCollection;
96 0 : }
97 : }
98 :
99 0 : return pTypeCollection->getTypes();
100 : }
101 :
102 : // XAggregation
103 :
104 0 : Any SAL_CALL BaseContainerControl::queryAggregation( const Type& aType ) throw( RuntimeException, std::exception )
105 : {
106 : // Ask for my own supported interfaces ...
107 : // Attention: XTypeProvider and XInterface are supported by OComponentHelper!
108 : Any aReturn ( ::cppu::queryInterface( aType ,
109 : static_cast< XControlModel* > ( this ) ,
110 : static_cast< XControlContainer* > ( this )
111 : )
112 0 : );
113 :
114 : // If searched interface supported by this class ...
115 0 : if ( aReturn.hasValue() )
116 : {
117 : // ... return this information.
118 0 : return aReturn;
119 : }
120 : else
121 : {
122 : // Else; ... ask baseclass for interfaces!
123 0 : return BaseControl::queryAggregation( aType );
124 0 : }
125 : }
126 :
127 : // XControl
128 :
129 0 : void SAL_CALL BaseContainerControl::createPeer( const Reference< XToolkit >& xToolkit ,
130 : const Reference< XWindowPeer >& xParent ) throw( RuntimeException, std::exception )
131 : {
132 0 : if ( !getPeer().is() )
133 : {
134 : // create own peer
135 0 : BaseControl::createPeer( xToolkit, xParent );
136 :
137 : // create peers at all children
138 0 : Sequence< Reference< XControl > > seqControlList = getControls();
139 0 : sal_uInt32 nControls = seqControlList.getLength();
140 :
141 0 : for ( sal_uInt32 n=0; n<nControls; n++ )
142 : {
143 0 : seqControlList.getArray()[n]->createPeer( xToolkit, getPeer() );
144 : }
145 :
146 : // activate new tab order
147 0 : impl_activateTabControllers();
148 :
149 : }
150 0 : }
151 :
152 : // XControl
153 :
154 0 : sal_Bool SAL_CALL BaseContainerControl::setModel( const Reference< XControlModel >& ) throw( RuntimeException, std::exception )
155 : {
156 : // This object has NO model.
157 0 : return sal_False;
158 : }
159 :
160 : // XControl
161 :
162 0 : Reference< XControlModel > SAL_CALL BaseContainerControl::getModel() throw( RuntimeException, std::exception )
163 : {
164 : // This object has NO model.
165 : // return (XControlModel*)this;
166 0 : return Reference< XControlModel >();
167 : }
168 :
169 : // XComponent
170 :
171 0 : void SAL_CALL BaseContainerControl::dispose() throw( RuntimeException, std::exception )
172 : {
173 : // Tell everything that this container is now gone.
174 : // It's faster if you listen to both the control and the container.
175 :
176 : // Ready for multithreading
177 0 : MutexGuard aGuard( m_aMutex );
178 :
179 : // remove listeners
180 0 : EventObject aObject;
181 :
182 0 : aObject.Source = Reference< XComponent > ( (XControlContainer*)this, UNO_QUERY );
183 0 : m_aListeners.disposeAndClear( aObject );
184 :
185 : // remove controls
186 0 : Sequence< Reference< XControl > > seqCtrls = getControls();
187 0 : Reference< XControl > * pCtrls = seqCtrls.getArray();
188 0 : sal_uInt32 nCtrls = seqCtrls.getLength();
189 0 : size_t nMaxCount = maControlInfoList.size();
190 0 : size_t nCount = 0;
191 :
192 0 : for ( nCount = 0; nCount < nMaxCount; ++nCount )
193 : {
194 0 : delete maControlInfoList[ nCount ];
195 : }
196 0 : maControlInfoList.clear();
197 :
198 0 : for ( nCount = 0; nCount < nCtrls; ++nCount )
199 : {
200 0 : pCtrls [ nCount ] -> removeEventListener ( static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) ) );
201 0 : pCtrls [ nCount ] -> dispose ( );
202 : }
203 :
204 : // call baseclass
205 0 : BaseControl::dispose();
206 0 : }
207 :
208 : // XEventListener
209 :
210 0 : void SAL_CALL BaseContainerControl::disposing( const EventObject& rEvent ) throw( RuntimeException, std::exception )
211 : {
212 0 : Reference< XControl > xControl( rEvent.Source, UNO_QUERY );
213 :
214 : // "removeControl" remove only, when control is an active control
215 0 : removeControl( xControl );
216 0 : }
217 :
218 : // XControlContainer
219 :
220 0 : void SAL_CALL BaseContainerControl::addControl ( const OUString& rName, const Reference< XControl > & rControl ) throw( RuntimeException, std::exception )
221 : {
222 0 : if ( !rControl.is () )
223 0 : return;
224 :
225 : // take memory for new item
226 0 : IMPL_ControlInfo* pNewControl = new IMPL_ControlInfo;
227 :
228 0 : if (pNewControl!=(IMPL_ControlInfo*)0)
229 : {
230 : // Ready for multithreading
231 0 : MutexGuard aGuard (m_aMutex);
232 :
233 : // set control
234 0 : pNewControl->sName = rName;
235 0 : pNewControl->xControl = rControl;
236 :
237 : // and insert in list
238 0 : maControlInfoList.push_back( pNewControl );
239 :
240 : // initialize new control
241 0 : pNewControl->xControl->setContext ( (OWeakObject*)this );
242 0 : pNewControl->xControl->addEventListener ( static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) ) );
243 :
244 : // when container has a peer ...
245 0 : if (getPeer().is())
246 : {
247 : // .. then create a peer on child
248 0 : pNewControl->xControl->createPeer ( getPeer()->getToolkit(), getPeer() );
249 0 : impl_activateTabControllers ();
250 : }
251 :
252 : // Send message to all listener
253 0 : OInterfaceContainerHelper* pInterfaceContainer = m_aListeners.getContainer( ::getCppuType((const Reference< XContainerListener >*)0) );
254 :
255 0 : if (pInterfaceContainer)
256 : {
257 : // Build event
258 0 : ContainerEvent aEvent;
259 :
260 0 : aEvent.Source = *this;
261 0 : aEvent.Element <<= rControl;
262 :
263 : // Get all listener
264 0 : OInterfaceIteratorHelper aIterator (*pInterfaceContainer);
265 :
266 : // Send event
267 0 : while ( aIterator.hasMoreElements() )
268 : {
269 0 : ((XContainerListener*)aIterator.next())->elementInserted (aEvent);
270 0 : }
271 0 : }
272 : }
273 : }
274 :
275 : // XControlContainer
276 :
277 0 : void SAL_CALL BaseContainerControl::removeControl ( const Reference< XControl > & rControl ) throw( RuntimeException, std::exception )
278 : {
279 0 : if ( rControl.is() )
280 : {
281 : // Ready for multithreading
282 0 : MutexGuard aGuard (m_aMutex);
283 :
284 0 : size_t nControls = maControlInfoList.size();
285 :
286 0 : for ( size_t n = 0; n < nControls; n++ )
287 : {
288 : // Search for right control
289 0 : IMPL_ControlInfo* pControl = maControlInfoList[ n ];
290 0 : if ( rControl == pControl->xControl )
291 : {
292 : //.is it found ... remove listener from control
293 0 : pControl->xControl->removeEventListener (static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) ));
294 0 : pControl->xControl->setContext ( Reference< XInterface > () );
295 :
296 : // ... free memory
297 0 : delete pControl;
298 0 : ::std::vector<IMPL_ControlInfo*>::iterator itr = maControlInfoList.begin();
299 0 : ::std::advance(itr, n);
300 0 : maControlInfoList.erase(itr);
301 :
302 : // Send message to all other listener
303 0 : OInterfaceContainerHelper * pInterfaceContainer = m_aListeners.getContainer( ::getCppuType((const Reference< XContainerListener >*)0) );
304 :
305 0 : if (pInterfaceContainer)
306 : {
307 0 : ContainerEvent aEvent;
308 :
309 0 : aEvent.Source = *this;
310 0 : aEvent.Element <<= rControl;
311 :
312 0 : OInterfaceIteratorHelper aIterator (*pInterfaceContainer);
313 :
314 0 : while ( aIterator.hasMoreElements() )
315 : {
316 0 : ((XContainerListener*)aIterator.next())->elementRemoved (aEvent);
317 0 : }
318 : }
319 : // Break "for" !
320 0 : break;
321 : }
322 0 : }
323 : }
324 0 : }
325 :
326 : // XControlContainer
327 :
328 0 : void SAL_CALL BaseContainerControl::setStatusText ( const OUString& rStatusText ) throw( RuntimeException, std::exception )
329 : {
330 : // go down to each parent
331 0 : Reference< XControlContainer > xContainer ( getContext(), UNO_QUERY );
332 :
333 0 : if ( xContainer.is () )
334 : {
335 0 : xContainer->setStatusText ( rStatusText );
336 0 : }
337 0 : }
338 :
339 : // XControlContainer
340 :
341 0 : Reference< XControl > SAL_CALL BaseContainerControl::getControl ( const OUString& rName ) throw( RuntimeException, std::exception )
342 : {
343 : // Ready for multithreading
344 0 : MutexGuard aGuard ( Mutex::getGlobalMutex() );
345 :
346 0 : size_t nControls = maControlInfoList.size();
347 :
348 : // Search for right control
349 0 : for( size_t nCount = 0; nCount < nControls; ++nCount )
350 : {
351 0 : IMPL_ControlInfo* pSearchControl = maControlInfoList[ nCount ];
352 :
353 0 : if ( pSearchControl->sName == rName )
354 : {
355 : // We have found it ...
356 : // Break operation and return.
357 0 : return pSearchControl->xControl;
358 : }
359 : }
360 :
361 : // We have not found it ... return NULL.
362 0 : return Reference< XControl > ();
363 : }
364 :
365 : // XControlContainer
366 :
367 0 : Sequence< Reference< XControl > > SAL_CALL BaseContainerControl::getControls () throw( RuntimeException, std::exception )
368 : {
369 : // Ready for multithreading
370 0 : MutexGuard aGuard ( Mutex::getGlobalMutex() );
371 :
372 0 : size_t nControls = maControlInfoList.size();
373 0 : size_t nCount = 0;
374 0 : Sequence< Reference< XControl > > aDescriptor ( nControls );
375 0 : Reference< XControl > * pDestination = aDescriptor.getArray ();
376 :
377 : // Copy controls to sequence
378 0 : for( nCount = 0; nCount < nControls; ++nCount )
379 : {
380 0 : IMPL_ControlInfo* pCopyControl = maControlInfoList[ nCount ];
381 0 : pDestination [ nCount ] = pCopyControl->xControl;
382 : }
383 :
384 : // Return sequence
385 0 : return aDescriptor;
386 : }
387 :
388 : // XWindow
389 :
390 0 : void SAL_CALL BaseContainerControl::setVisible ( sal_Bool bVisible ) throw( RuntimeException, std::exception )
391 : {
392 : // override baseclass definition
393 0 : BaseControl::setVisible ( bVisible );
394 :
395 : // is it a top window ?
396 0 : if ( !getContext().is() && bVisible )
397 : {
398 : // then show it automaticly
399 0 : createPeer ( Reference< XToolkit > (), Reference< XWindowPeer > () );
400 : }
401 0 : }
402 :
403 : // protected method
404 :
405 0 : WindowDescriptor* BaseContainerControl::impl_getWindowDescriptor ( const Reference< XWindowPeer > & rParentPeer )
406 : {
407 : // - used from "createPeer()" to set the values of an WindowDescriptor !!!
408 : // - if you will change the descriptor-values, you must override thid virtuell function
409 : // - the caller must release the memory for this dynamical descriptor !!!
410 :
411 0 : WindowDescriptor * aDescriptor = new WindowDescriptor;
412 :
413 0 : aDescriptor->Type = WindowClass_CONTAINER;
414 0 : aDescriptor->WindowServiceName = "window";
415 0 : aDescriptor->ParentIndex = -1;
416 0 : aDescriptor->Parent = rParentPeer;
417 0 : aDescriptor->Bounds = getPosSize ();
418 0 : aDescriptor->WindowAttributes = 0;
419 :
420 0 : return aDescriptor;
421 : }
422 :
423 : // protected method
424 :
425 0 : void BaseContainerControl::impl_paint ( sal_Int32 /*nX*/, sal_Int32 /*nY*/, const Reference< XGraphics > & /*rGraphics*/ )
426 : {
427 0 : }
428 :
429 : // private method
430 :
431 0 : void BaseContainerControl::impl_activateTabControllers ()
432 : {
433 : // Ready for multithreading
434 0 : MutexGuard aGuard (m_aMutex);
435 :
436 0 : sal_uInt32 nMaxCount = m_xTabControllerList.getLength ();
437 0 : sal_uInt32 nCount = 0;
438 :
439 0 : for ( nCount = 0; nCount < nMaxCount; ++nCount )
440 : {
441 0 : m_xTabControllerList.getArray () [nCount]->setContainer ( this );
442 0 : m_xTabControllerList.getArray () [nCount]->activateTabOrder ( );
443 0 : }
444 0 : }
445 :
446 : // private method
447 :
448 0 : void BaseContainerControl::impl_cleanMemory ()
449 : {
450 : // Get count of listitems.
451 0 : size_t nMaxCount = maControlInfoList.size();
452 0 : size_t nCount = 0;
453 :
454 : // Delete all items.
455 0 : for ( nCount = 0; nCount < nMaxCount; ++nCount )
456 : {
457 : // Delete everytime first element of list!
458 : // We count from 0 to MAX, where "MAX=count of items" BEFORE we delete some elements!
459 : // If we use "GetObject ( nCount )" ... it can be, that we have an index greater then count of current elements!
460 :
461 0 : IMPL_ControlInfo* pSearchControl = maControlInfoList[ nCount ];
462 0 : delete pSearchControl;
463 : }
464 :
465 : // Delete list himself.
466 0 : maControlInfoList.clear ();
467 0 : }
468 :
469 : } // namespace unocontrols
470 :
471 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|