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 | |
28 | using namespace ::cppu ; |
29 | using namespace ::osl ; |
30 | using namespace ::rtl ; |
31 | using namespace ::com::sun::star::uno ; |
32 | using namespace ::com::sun::star::lang ; |
33 | using namespace ::com::sun::star::awt ; |
34 | using namespace ::com::sun::star::container ; |
35 | |
36 | namespace unocontrols{ |
37 | |
38 | //____________________________________________________________________________________________________________ |
39 | // construct/destruct |
40 | //____________________________________________________________________________________________________________ |
41 | |
42 | BaseContainerControl::BaseContainerControl( const Reference< XComponentContext >& rxContext ) |
43 | : BaseControl ( rxContext ) |
44 | , m_aListeners ( m_aMutex ) |
45 | { |
46 | } |
47 | |
48 | BaseContainerControl::~BaseContainerControl() |
49 | { |
50 | impl_cleanMemory(); |
51 | } |
52 | |
53 | //____________________________________________________________________________________________________________ |
54 | // XInterface |
55 | //____________________________________________________________________________________________________________ |
56 | |
57 | Any 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 | |
82 | Sequence< 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 | |
114 | Any 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 | |
141 | void 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 | |
168 | sal_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 | |
178 | Reference< 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 | |
189 | void 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 | |
230 | void 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 | |
242 | void 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 | |
301 | void 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 | |
313 | void 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 | |
366 | void 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 | |
378 | void 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 | |
393 | Reference< 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 | |
421 | Sequence< 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 | |
446 | void 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 | |
472 | void 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 | |
496 | void 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 | |
504 | Sequence<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 | |
516 | void 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 | |
533 | WindowDescriptor* 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 | |
555 | void BaseContainerControl::impl_paint ( sal_Int32 /*nX*/, sal_Int32 /*nY*/, const Reference< XGraphics > & /*rGraphics*/ ) |
556 | { |
557 | } |
558 | |
559 | //____________________________________________________________________________________________________________ |
560 | // private method |
561 | //____________________________________________________________________________________________________________ |
562 | |
563 | void 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 | |
582 | void 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 | |