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