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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_toolkit.hxx" 30 31 #include <vcl/svapp.hxx> 32 #include <vcl/window.hxx> 33 #include <vcl/wall.hxx> 34 #include <vos/mutex.hxx> 35 #include <toolkit/controls/dialogcontrol.hxx> 36 #include <toolkit/helper/property.hxx> 37 #include <toolkit/helper/unopropertyarrayhelper.hxx> 38 #include <toolkit/controls/stdtabcontroller.hxx> 39 #include <com/sun/star/awt/PosSize.hpp> 40 #include <com/sun/star/awt/WindowAttribute.hpp> 41 #include <com/sun/star/resource/XStringResourceResolver.hpp> 42 #include <com/sun/star/graphic/XGraphicProvider.hpp> 43 #include <tools/list.hxx> 44 #include <cppuhelper/typeprovider.hxx> 45 #include <tools/debug.hxx> 46 #include <tools/diagnose_ex.h> 47 #include <comphelper/sequence.hxx> 48 #include <vcl/svapp.hxx> 49 #include <vcl/outdev.hxx> 50 51 #include <toolkit/helper/vclunohelper.hxx> 52 #include <unotools/ucbstreamhelper.hxx> 53 #include <vcl/graph.hxx> 54 #include <vcl/image.hxx> 55 #include <map> 56 #include <algorithm> 57 #include <functional> 58 #include "tools/urlobj.hxx" 59 #include "osl/file.hxx" 60 61 using namespace ::com::sun::star; 62 using namespace ::com::sun::star::uno; 63 using namespace ::com::sun::star::awt; 64 using namespace ::com::sun::star::lang; 65 using namespace ::com::sun::star::container; 66 using namespace ::com::sun::star::beans; 67 using namespace ::com::sun::star::util; 68 69 #define PROPERTY_DIALOGSOURCEURL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DialogSourceURL" )) 70 #define PROPERTY_IMAGEURL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ImageURL" )) 71 #define PROPERTY_GRAPHIC ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" )) 72 // 73 ////HELPER 74 ::rtl::OUString getPhysicalLocation( const ::com::sun::star::uno::Any& rbase, const ::com::sun::star::uno::Any& rUrl ); 75 76 // ---------------------------------------------------- 77 // class UnoControlDialogModel 78 // ---------------------------------------------------- 79 UnoControlDialogModel::UnoControlDialogModel( const Reference< XMultiServiceFactory >& i_factory ) 80 :ControlModelContainerBase( i_factory ) 81 { 82 ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR ); 83 // ImplRegisterProperty( BASEPROPERTY_BORDER ); 84 ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL ); 85 ImplRegisterProperty( BASEPROPERTY_ENABLED ); 86 ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR ); 87 // ImplRegisterProperty( BASEPROPERTY_PRINTABLE ); 88 ImplRegisterProperty( BASEPROPERTY_HELPTEXT ); 89 ImplRegisterProperty( BASEPROPERTY_HELPURL ); 90 ImplRegisterProperty( BASEPROPERTY_TITLE ); 91 ImplRegisterProperty( BASEPROPERTY_SIZEABLE ); 92 ImplRegisterProperty( BASEPROPERTY_DESKTOP_AS_PARENT ); 93 ImplRegisterProperty( BASEPROPERTY_DECORATION ); 94 ImplRegisterProperty( BASEPROPERTY_DIALOGSOURCEURL ); 95 ImplRegisterProperty( BASEPROPERTY_GRAPHIC ); 96 ImplRegisterProperty( BASEPROPERTY_IMAGEURL ); 97 98 Any aBool; 99 aBool <<= (sal_Bool) sal_True; 100 ImplRegisterProperty( BASEPROPERTY_MOVEABLE, aBool ); 101 ImplRegisterProperty( BASEPROPERTY_CLOSEABLE, aBool ); 102 } 103 104 UnoControlDialogModel::UnoControlDialogModel( const UnoControlDialogModel& rModel ) 105 : ControlModelContainerBase( rModel ) 106 { 107 } 108 109 UnoControlDialogModel::~UnoControlDialogModel() 110 { 111 } 112 113 UnoControlModel* UnoControlDialogModel::Clone() const 114 { 115 // clone the container itself 116 UnoControlDialogModel* pClone = new UnoControlDialogModel( *this ); 117 118 Clone_Impl(*pClone); 119 120 return pClone; 121 } 122 123 124 ::rtl::OUString UnoControlDialogModel::getServiceName( ) throw(RuntimeException) 125 { 126 return ::rtl::OUString::createFromAscii( szServiceName_UnoControlDialogModel ); 127 } 128 129 Any UnoControlDialogModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const 130 { 131 Any aAny; 132 133 switch ( nPropId ) 134 { 135 case BASEPROPERTY_DEFAULTCONTROL: 136 aAny <<= ::rtl::OUString::createFromAscii( szServiceName_UnoControlDialog ); 137 break; 138 default: 139 aAny = UnoControlModel::ImplGetDefaultValue( nPropId ); 140 } 141 142 return aAny; 143 } 144 145 ::cppu::IPropertyArrayHelper& UnoControlDialogModel::getInfoHelper() 146 { 147 static UnoPropertyArrayHelper* pHelper = NULL; 148 if ( !pHelper ) 149 { 150 Sequence<sal_Int32> aIDs = ImplGetPropertyIds(); 151 pHelper = new UnoPropertyArrayHelper( aIDs ); 152 } 153 return *pHelper; 154 } 155 156 // XMultiPropertySet 157 Reference< XPropertySetInfo > UnoControlDialogModel::getPropertySetInfo( ) throw(RuntimeException) 158 { 159 static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); 160 return xInfo; 161 } 162 163 // ============================================================================ 164 // = class UnoDialogControl 165 // ============================================================================ 166 167 UnoDialogControl::UnoDialogControl( const uno::Reference< lang::XMultiServiceFactory >& i_factory ) 168 :UnoDialogControl_Base( i_factory ) 169 ,maTopWindowListeners( *this ) 170 ,mbWindowListener(false) 171 { 172 maComponentInfos.nWidth = 300; 173 maComponentInfos.nHeight = 450; 174 } 175 176 UnoDialogControl::~UnoDialogControl() 177 { 178 } 179 180 ::rtl::OUString UnoDialogControl::GetComponentServiceName() 181 { 182 183 sal_Bool bDecoration( sal_True ); 184 ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DECORATION )) >>= bDecoration; 185 if ( bDecoration ) 186 return ::rtl::OUString::createFromAscii( "Dialog" ); 187 else 188 return ::rtl::OUString::createFromAscii( "TabPage" ); 189 } 190 191 void UnoDialogControl::dispose() throw(RuntimeException) 192 { 193 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 194 195 EventObject aEvt; 196 aEvt.Source = static_cast< ::cppu::OWeakObject* >( this ); 197 maTopWindowListeners.disposeAndClear( aEvt ); 198 ControlContainerBase::dispose(); 199 } 200 201 void SAL_CALL UnoDialogControl::disposing( 202 const EventObject& Source ) 203 throw(RuntimeException) 204 { 205 ControlContainerBase::disposing( Source ); 206 } 207 208 sal_Bool UnoDialogControl::setModel( const Reference< XControlModel >& rxModel ) throw(RuntimeException) 209 { 210 // #Can we move all the Resource stuff to the ControlContainerBase ? 211 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 212 sal_Bool bRet = ControlContainerBase::setModel( rxModel ); 213 ImplStartListingForResourceEvents(); 214 return bRet; 215 } 216 217 void UnoDialogControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) throw(RuntimeException) 218 { 219 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 220 221 UnoControlContainer::createPeer( rxToolkit, rParentPeer ); 222 223 Reference < XTopWindow > xTW( getPeer(), UNO_QUERY ); 224 if ( xTW.is() ) 225 { 226 xTW->setMenuBar( mxMenuBar ); 227 228 if ( !mbWindowListener ) 229 { 230 Reference< XWindowListener > xWL( static_cast< cppu::OWeakObject*>( this ), UNO_QUERY ); 231 addWindowListener( xWL ); 232 mbWindowListener = true; 233 } 234 235 if ( maTopWindowListeners.getLength() ) 236 xTW->addTopWindowListener( &maTopWindowListeners ); 237 } 238 } 239 240 void UnoDialogControl::PrepareWindowDescriptor( ::com::sun::star::awt::WindowDescriptor& rDesc ) 241 { 242 sal_Bool bDecoration( sal_True ); 243 ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DECORATION )) >>= bDecoration; 244 if ( !bDecoration ) 245 { 246 // Now we have to manipulate the WindowDescriptor 247 rDesc.WindowAttributes = rDesc.WindowAttributes | ::com::sun::star::awt::WindowAttribute::NODECORATION; 248 } 249 250 // We have to set the graphic property before the peer 251 // will be created. Otherwise the properties will be copied 252 // into the peer via propertiesChangeEvents. As the order of 253 // can lead to overwrites we have to set the graphic property 254 // before the propertiesChangeEvents are sent! 255 ::rtl::OUString aImageURL; 256 Reference< graphic::XGraphic > xGraphic; 257 if (( ImplGetPropertyValue( PROPERTY_IMAGEURL ) >>= aImageURL ) && 258 ( aImageURL.getLength() > 0 )) 259 { 260 ::rtl::OUString absoluteUrl = 261 getPhysicalLocation( ImplGetPropertyValue( PROPERTY_DIALOGSOURCEURL ), 262 ImplGetPropertyValue( PROPERTY_IMAGEURL )); 263 264 xGraphic = ControlContainerBase::Impl_getGraphicFromURL_nothrow( absoluteUrl ); 265 ImplSetPropertyValue( PROPERTY_GRAPHIC, uno::makeAny( xGraphic ), sal_True ); 266 } 267 } 268 269 void UnoDialogControl::addTopWindowListener( const Reference< XTopWindowListener >& rxListener ) throw (RuntimeException) 270 { 271 maTopWindowListeners.addInterface( rxListener ); 272 if( getPeer().is() && maTopWindowListeners.getLength() == 1 ) 273 { 274 Reference < XTopWindow > xTW( getPeer(), UNO_QUERY ); 275 xTW->addTopWindowListener( &maTopWindowListeners ); 276 } 277 } 278 279 void UnoDialogControl::removeTopWindowListener( const Reference< XTopWindowListener >& rxListener ) throw (RuntimeException) 280 { 281 if( getPeer().is() && maTopWindowListeners.getLength() == 1 ) 282 { 283 Reference < XTopWindow > xTW( getPeer(), UNO_QUERY ); 284 xTW->removeTopWindowListener( &maTopWindowListeners ); 285 } 286 maTopWindowListeners.removeInterface( rxListener ); 287 } 288 289 void UnoDialogControl::toFront( ) throw (RuntimeException) 290 { 291 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 292 if ( getPeer().is() ) 293 { 294 Reference< XTopWindow > xTW( getPeer(), UNO_QUERY ); 295 if( xTW.is() ) 296 xTW->toFront(); 297 } 298 } 299 300 void UnoDialogControl::toBack( ) throw (RuntimeException) 301 { 302 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 303 if ( getPeer().is() ) 304 { 305 Reference< XTopWindow > xTW( getPeer(), UNO_QUERY ); 306 if( xTW.is() ) 307 xTW->toBack(); 308 } 309 } 310 311 void UnoDialogControl::setMenuBar( const Reference< XMenuBar >& rxMenuBar ) throw (RuntimeException) 312 { 313 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 314 mxMenuBar = rxMenuBar; 315 if ( getPeer().is() ) 316 { 317 Reference< XTopWindow > xTW( getPeer(), UNO_QUERY ); 318 if( xTW.is() ) 319 xTW->setMenuBar( mxMenuBar ); 320 } 321 } 322 static ::Size ImplMapPixelToAppFont( OutputDevice* pOutDev, const ::Size& aSize ) 323 { 324 ::Size aTmp = pOutDev->PixelToLogic( aSize, MAP_APPFONT ); 325 return aTmp; 326 } 327 // ::com::sun::star::awt::XWindowListener 328 void SAL_CALL UnoDialogControl::windowResized( const ::com::sun::star::awt::WindowEvent& e ) 329 throw (::com::sun::star::uno::RuntimeException) 330 { 331 OutputDevice*pOutDev = Application::GetDefaultDevice(); 332 DBG_ASSERT( pOutDev, "Missing Default Device!" ); 333 if ( pOutDev && !mbSizeModified ) 334 { 335 // Currentley we are simply using MAP_APPFONT 336 ::Size aAppFontSize( e.Width, e.Height ); 337 338 Reference< XControl > xDialogControl( *this, UNO_QUERY_THROW ); 339 Reference< XDevice > xDialogDevice( xDialogControl->getPeer(), UNO_QUERY ); 340 OSL_ENSURE( xDialogDevice.is(), "UnoDialogControl::windowResized: no peer, but a windowResized event?" ); 341 342 // #i87592 In design mode the drawing layer works with sizes with decoration. 343 // Therefore we have to substract them before writing back to the properties (model). 344 if ( xDialogDevice.is() && mbDesignMode ) 345 { 346 DeviceInfo aDeviceInfo( xDialogDevice->getInfo() ); 347 aAppFontSize.Width() -= aDeviceInfo.LeftInset + aDeviceInfo.RightInset; 348 aAppFontSize.Height() -= aDeviceInfo.TopInset + aDeviceInfo.BottomInset; 349 } 350 351 aAppFontSize = ImplMapPixelToAppFont( pOutDev, aAppFontSize ); 352 353 // Remember that changes have been done by listener. No need to 354 // update the position because of property change event. 355 mbSizeModified = true; 356 Sequence< rtl::OUString > aProps( 2 ); 357 Sequence< Any > aValues( 2 ); 358 // Properties in a sequence must be sorted! 359 aProps[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Height" )); 360 aProps[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Width" )); 361 aValues[0] <<= aAppFontSize.Height(); 362 aValues[1] <<= aAppFontSize.Width(); 363 364 ImplSetPropertyValues( aProps, aValues, true ); 365 mbSizeModified = false; 366 } 367 } 368 369 void SAL_CALL UnoDialogControl::windowMoved( const ::com::sun::star::awt::WindowEvent& e ) 370 throw (::com::sun::star::uno::RuntimeException) 371 { 372 OutputDevice*pOutDev = Application::GetDefaultDevice(); 373 DBG_ASSERT( pOutDev, "Missing Default Device!" ); 374 if ( pOutDev && !mbPosModified ) 375 { 376 // Currentley we are simply using MAP_APPFONT 377 Any aAny; 378 ::Size aTmp( e.X, e.Y ); 379 aTmp = ImplMapPixelToAppFont( pOutDev, aTmp ); 380 381 // Remember that changes have been done by listener. No need to 382 // update the position because of property change event. 383 mbPosModified = true; 384 Sequence< rtl::OUString > aProps( 2 ); 385 Sequence< Any > aValues( 2 ); 386 aProps[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PositionX" )); 387 aProps[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PositionY" )); 388 aValues[0] <<= aTmp.Width(); 389 aValues[1] <<= aTmp.Height(); 390 391 ImplSetPropertyValues( aProps, aValues, true ); 392 mbPosModified = false; 393 } 394 } 395 396 void SAL_CALL UnoDialogControl::windowShown( const EventObject& e ) throw (RuntimeException) 397 { 398 (void)e; 399 } 400 401 void SAL_CALL UnoDialogControl::windowHidden( const EventObject& e ) throw (RuntimeException) 402 { 403 (void)e; 404 } 405 406 void SAL_CALL UnoDialogControl::endDialog( ::sal_Int32 i_result ) throw (RuntimeException) 407 { 408 Reference< XDialog2 > xPeerDialog( getPeer(), UNO_QUERY ); 409 if ( xPeerDialog.is() ) 410 xPeerDialog->endDialog( i_result ); 411 } 412 413 void SAL_CALL UnoDialogControl::setHelpId( const rtl::OUString& i_id ) throw (RuntimeException) 414 { 415 Reference< XDialog2 > xPeerDialog( getPeer(), UNO_QUERY ); 416 if ( xPeerDialog.is() ) 417 xPeerDialog->setHelpId( i_id ); 418 } 419 420 void UnoDialogControl::setTitle( const ::rtl::OUString& Title ) throw(RuntimeException) 421 { 422 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 423 Any aAny; 424 aAny <<= Title; 425 ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TITLE ), aAny, sal_True ); 426 } 427 428 ::rtl::OUString UnoDialogControl::getTitle() throw(RuntimeException) 429 { 430 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 431 return ImplGetPropertyValue_UString( BASEPROPERTY_TITLE ); 432 } 433 434 sal_Int16 UnoDialogControl::execute() throw(RuntimeException) 435 { 436 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 437 sal_Int16 nDone = -1; 438 if ( getPeer().is() ) 439 { 440 Reference< XDialog > xDlg( getPeer(), UNO_QUERY ); 441 if( xDlg.is() ) 442 { 443 GetComponentInfos().bVisible = sal_True; 444 nDone = xDlg->execute(); 445 GetComponentInfos().bVisible = sal_False; 446 } 447 } 448 return nDone; 449 } 450 451 void UnoDialogControl::endExecute() throw(RuntimeException) 452 { 453 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 454 if ( getPeer().is() ) 455 { 456 Reference< XDialog > xDlg( getPeer(), UNO_QUERY ); 457 if( xDlg.is() ) 458 { 459 xDlg->endExecute(); 460 GetComponentInfos().bVisible = sal_False; 461 } 462 } 463 } 464 465 // XModifyListener 466 void SAL_CALL UnoDialogControl::modified( 467 const lang::EventObject& /*rEvent*/ ) 468 throw (RuntimeException) 469 { 470 ImplUpdateResourceResolver(); 471 } 472 473 void UnoDialogControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents ) throw(RuntimeException) 474 { 475 sal_Int32 nLen = rEvents.getLength(); 476 for( sal_Int32 i = 0; i < nLen; i++ ) 477 { 478 const PropertyChangeEvent& rEvt = rEvents.getConstArray()[i]; 479 Reference< XControlModel > xModel( rEvt.Source, UNO_QUERY ); 480 sal_Bool bOwnModel = (XControlModel*)xModel.get() == (XControlModel*)getModel().get(); 481 if ( bOwnModel && rEvt.PropertyName.equalsAsciiL( "ImageURL", 8 )) 482 { 483 ::rtl::OUString aImageURL; 484 Reference< graphic::XGraphic > xGraphic; 485 if (( ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_IMAGEURL ) ) >>= aImageURL ) && 486 ( aImageURL.getLength() > 0 )) 487 { 488 ::rtl::OUString absoluteUrl = 489 getPhysicalLocation( ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DIALOGSOURCEURL )), 490 uno::makeAny(aImageURL)); 491 492 xGraphic = Impl_getGraphicFromURL_nothrow( absoluteUrl ); 493 } 494 ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_GRAPHIC), uno::makeAny( xGraphic ), sal_True ); 495 break; 496 } 497 } 498 ControlContainerBase::ImplModelPropertiesChanged(rEvents); 499 } 500