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