1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_svx.hxx" 24 25 #include <svx/svdoole2.hxx> 26 #include <com/sun/star/util/XModifyBroadcaster.hpp> 27 #include <com/sun/star/util/XModifiable.hpp> 28 #include <com/sun/star/embed/EmbedStates.hpp> 29 #include <com/sun/star/embed/ElementModes.hpp> 30 #include <com/sun/star/embed/EmbedMisc.hpp> 31 #include <com/sun/star/embed/Aspects.hpp> 32 #include <com/sun/star/embed/XInplaceClient.hpp> 33 #include <com/sun/star/embed/XInplaceObject.hpp> 34 #include <com/sun/star/embed/XLinkageSupport.hpp> 35 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 36 #include <com/sun/star/embed/XWindowSupplier.hpp> 37 #include <com/sun/star/document/XEventListener.hpp> 38 #include <com/sun/star/container/XChild.hpp> 39 #include "com/sun/star/document/XStorageBasedDocument.hpp" 40 41 #include <comphelper/processfactory.hxx> 42 #include <cppuhelper/exc_hlp.hxx> 43 #include <unotools/ucbstreamhelper.hxx> 44 45 #include <toolkit/helper/vclunohelper.hxx> 46 #include <toolkit/awt/vclxwindow.hxx> 47 #include <toolkit/helper/convert.hxx> 48 49 #include <svtools/filter.hxx> 50 #include <svtools/embedhlp.hxx> 51 52 #include <sfx2/objsh.hxx> 53 #include <sfx2/ipclient.hxx> 54 #include <sfx2/lnkbase.hxx> 55 #include <tools/stream.hxx> 56 #include <comphelper/anytostring.hxx> 57 #include <svx/svdpagv.hxx> 58 #include <tools/globname.hxx> 59 #include <vcl/jobset.hxx> 60 #include <sot/clsids.hxx> 61 62 #include <sot/formats.hxx> 63 #include <sfx2/linkmgr.hxx> 64 #include <svtools/transfer.hxx> 65 #include <cppuhelper/implbase5.hxx> 66 67 #include <svl/solar.hrc> 68 #include <svl/urihelper.hxx> 69 #include <vos/mutex.hxx> 70 #include <vcl/svapp.hxx> 71 72 #include <svx/svdpagv.hxx> 73 #include <svx/svdmodel.hxx> 74 #include "svx/svdglob.hxx" // Stringcache 75 #include "svx/svdstr.hrc" // Objectname 76 #include <svx/svdetc.hxx> 77 #include <svx/svdview.hxx> 78 #include "unomlstr.hxx" 79 #include <svx/charthelper.hxx> 80 #include <svx/sdr/contact/viewcontactofsdrole2obj.hxx> 81 #include <svx/svdograf.hxx> 82 #include <svx/sdr/properties/oleproperties.hxx> 83 84 // #i100710# 85 #include <svx/xlnclit.hxx> 86 #include <svx/xbtmpit.hxx> 87 #include <svx/xflbmtit.hxx> 88 #include <svx/xflbstit.hxx> 89 90 // #i118485# 91 #include <basegfx/matrix/b2dhommatrix.hxx> 92 #include <basegfx/polygon/b2dpolypolygon.hxx> 93 #include <editeng/outlobj.hxx> 94 95 #include <svx/svdpage.hxx> 96 97 using namespace ::rtl; 98 using namespace ::com::sun::star; 99 100 uno::Reference < beans::XPropertySet > lcl_getFrame_throw(const SdrOle2Obj* _pObject) 101 { 102 uno::Reference < beans::XPropertySet > xFrame; 103 if ( _pObject ) 104 { 105 uno::Reference< frame::XController> xController = _pObject->GetParentXModel()->getCurrentController(); 106 if ( xController.is() ) 107 { 108 xFrame.set( xController->getFrame(),uno::UNO_QUERY_THROW); 109 } 110 } // if ( _pObject ) 111 return xFrame; 112 } 113 114 class SdrLightEmbeddedClient_Impl : public ::cppu::WeakImplHelper5 115 < embed::XStateChangeListener 116 , document::XEventListener 117 , embed::XInplaceClient 118 , embed::XEmbeddedClient 119 , embed::XWindowSupplier 120 > 121 { 122 uno::Reference< awt::XWindow > m_xWindow; 123 SdrOle2Obj* mpObj; 124 125 Fraction m_aScaleWidth; 126 Fraction m_aScaleHeight; 127 128 129 public: 130 SdrLightEmbeddedClient_Impl( SdrOle2Obj* pObj ); 131 void Release(); 132 133 void SetSizeScale( const Fraction& aScaleWidth, const Fraction& aScaleHeight ) 134 { 135 m_aScaleWidth = aScaleWidth; 136 m_aScaleHeight = aScaleHeight; 137 } 138 139 Fraction GetScaleWidth() const { return m_aScaleWidth; } 140 Fraction GetScaleHeight() const { return m_aScaleHeight; } 141 142 void setWindow(const uno::Reference< awt::XWindow >& _xWindow); 143 144 private: 145 Rectangle impl_getScaledRect_nothrow() const; 146 // XStateChangeListener 147 virtual void SAL_CALL changingState( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::embed::WrongStateException, ::com::sun::star::uno::RuntimeException); 148 virtual void SAL_CALL stateChanged( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::uno::RuntimeException); 149 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); 150 151 // document::XEventListener 152 virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ); 153 154 // XEmbeddedClient 155 virtual void SAL_CALL saveObject() throw ( embed::ObjectSaveVetoException, uno::Exception, uno::RuntimeException ); 156 virtual void SAL_CALL visibilityChanged( sal_Bool bVisible ) throw ( embed::WrongStateException, uno::RuntimeException ); 157 158 // XComponentSupplier 159 virtual uno::Reference< util::XCloseable > SAL_CALL getComponent() throw ( uno::RuntimeException ); 160 161 // XInplaceClient 162 virtual sal_Bool SAL_CALL canInplaceActivate() throw ( uno::RuntimeException ); 163 virtual void SAL_CALL activatingInplace() throw ( embed::WrongStateException, uno::RuntimeException ); 164 virtual void SAL_CALL activatingUI() throw ( embed::WrongStateException, uno::RuntimeException ); 165 virtual void SAL_CALL deactivatedInplace() throw ( embed::WrongStateException, uno::RuntimeException ); 166 virtual void SAL_CALL deactivatedUI() throw ( embed::WrongStateException, uno::RuntimeException ); 167 virtual uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL getLayoutManager() throw ( embed::WrongStateException, uno::RuntimeException ); 168 virtual uno::Reference< frame::XDispatchProvider > SAL_CALL getInplaceDispatchProvider() throw ( embed::WrongStateException, uno::RuntimeException ); 169 virtual awt::Rectangle SAL_CALL getPlacement() throw ( embed::WrongStateException, uno::RuntimeException ); 170 virtual awt::Rectangle SAL_CALL getClipRectangle() throw ( embed::WrongStateException, uno::RuntimeException ); 171 virtual void SAL_CALL translateAccelerators( const uno::Sequence< awt::KeyEvent >& aKeys ) throw ( embed::WrongStateException, uno::RuntimeException ); 172 virtual void SAL_CALL scrollObject( const awt::Size& aOffset ) throw ( embed::WrongStateException, uno::RuntimeException ); 173 virtual void SAL_CALL changedPlacement( const awt::Rectangle& aPosRect ) throw ( embed::WrongStateException, uno::Exception, uno::RuntimeException ); 174 175 // XWindowSupplier 176 virtual uno::Reference< awt::XWindow > SAL_CALL getWindow() throw ( uno::RuntimeException ); 177 }; 178 179 //-------------------------------------------------------------------- 180 SdrLightEmbeddedClient_Impl::SdrLightEmbeddedClient_Impl( SdrOle2Obj* pObj ) 181 : mpObj( pObj ) 182 { 183 } 184 Rectangle SdrLightEmbeddedClient_Impl::impl_getScaledRect_nothrow() const 185 { 186 MapUnit aContainerMapUnit( MAP_100TH_MM ); 187 uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); 188 if ( xParentVis.is() ) 189 aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) ); 190 Rectangle aLogicRect( mpObj->GetLogicRect() ); 191 // apply scaling to object area and convert to pixels 192 aLogicRect.SetSize( Size( Fraction( aLogicRect.GetWidth() ) * m_aScaleWidth, 193 Fraction( aLogicRect.GetHeight() ) * m_aScaleHeight ) ); 194 return aLogicRect; 195 } 196 //-------------------------------------------------------------------- 197 void SAL_CALL SdrLightEmbeddedClient_Impl::changingState( const ::com::sun::star::lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ ) throw (::com::sun::star::embed::WrongStateException, ::com::sun::star::uno::RuntimeException) 198 { 199 } 200 201 //-------------------------------------------------------------------- 202 void SdrLightEmbeddedClient_Impl::Release() 203 { 204 { 205 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 206 mpObj = NULL; 207 } 208 209 release(); 210 } 211 212 //-------------------------------------------------------------------- 213 void SAL_CALL SdrLightEmbeddedClient_Impl::stateChanged( const ::com::sun::star::lang::EventObject& /*aEvent*/, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::uno::RuntimeException) 214 { 215 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 216 217 if ( mpObj && nOldState == embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING ) 218 { 219 mpObj->ObjectLoaded(); 220 GetSdrGlobalData().GetOLEObjCache().InsertObj(mpObj); 221 } 222 else if ( mpObj && nNewState == embed::EmbedStates::LOADED && nOldState == embed::EmbedStates::RUNNING ) 223 { 224 GetSdrGlobalData().GetOLEObjCache().RemoveObj(mpObj); 225 } 226 } 227 228 //-------------------------------------------------------------------- 229 void SAL_CALL SdrLightEmbeddedClient_Impl::disposing( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::RuntimeException) 230 { 231 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 232 233 GetSdrGlobalData().GetOLEObjCache().RemoveObj(mpObj); 234 } 235 236 //-------------------------------------------------------------------- 237 void SAL_CALL SdrLightEmbeddedClient_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ) 238 { 239 // TODO/LATER: when Writer uses this implementation the code could be shared with SfxInPlaceClient_Impl 240 241 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 242 243 // the code currently makes sense only in case there is no other client 244 if ( mpObj && mpObj->GetAspect() != embed::Aspects::MSOLE_ICON && aEvent.EventName.equalsAscii("OnVisAreaChanged") 245 && mpObj->GetObjRef().is() && mpObj->GetObjRef()->getClientSite() == uno::Reference< embed::XEmbeddedClient >( this ) ) 246 { 247 try 248 { 249 MapUnit aContainerMapUnit( MAP_100TH_MM ); 250 uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); 251 if ( xParentVis.is() ) 252 aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) ); 253 254 MapUnit aObjMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpObj->GetObjRef()->getMapUnit( mpObj->GetAspect() ) ); 255 256 Rectangle aVisArea; 257 awt::Size aSz; 258 try 259 { 260 aSz = mpObj->GetObjRef()->getVisualAreaSize( mpObj->GetAspect() ); 261 } 262 catch( embed::NoVisualAreaSizeException& ) 263 { 264 OSL_ENSURE( sal_False, "No visual area size!\n" ); 265 aSz.Width = 5000; 266 aSz.Height = 5000; 267 } 268 catch( uno::Exception& ) 269 { 270 OSL_ENSURE( sal_False, "Unexpected exception!\n" ); 271 aSz.Width = 5000; 272 aSz.Height = 5000; 273 } 274 275 aVisArea.SetSize( Size( aSz.Width, aSz.Height ) ); 276 aVisArea = OutputDevice::LogicToLogic( aVisArea, aObjMapUnit, aContainerMapUnit ); 277 Size aScaledSize( static_cast< long >( m_aScaleWidth * Fraction( aVisArea.GetWidth() ) ), 278 static_cast< long >( m_aScaleHeight * Fraction( aVisArea.GetHeight() ) ) ); 279 Rectangle aLogicRect( mpObj->GetLogicRect() ); 280 281 // react to the change if the difference is bigger than one pixel 282 Size aPixelDiff = 283 Application::GetDefaultDevice()->LogicToPixel( 284 Size( aLogicRect.GetWidth() - aScaledSize.Width(), 285 aLogicRect.GetHeight() - aScaledSize.Height() ), 286 aContainerMapUnit ); 287 if( aPixelDiff.Width() || aPixelDiff.Height() ) 288 { 289 mpObj->SetLogicRect( Rectangle( aLogicRect.TopLeft(), aScaledSize ) ); 290 mpObj->BroadcastObjectChange(); 291 } 292 else 293 mpObj->ActionChanged(); 294 } 295 catch( uno::Exception& ) 296 { 297 OSL_ENSURE( sal_False, "Unexpected exception!\n" ); 298 } 299 } 300 } 301 302 //-------------------------------------------------------------------- 303 void SAL_CALL SdrLightEmbeddedClient_Impl::saveObject() 304 throw ( embed::ObjectSaveVetoException, 305 uno::Exception, 306 uno::RuntimeException ) 307 { 308 // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl 309 uno::Reference< embed::XCommonEmbedPersist > xPersist; 310 uno::Reference< util::XModifiable > xModifiable; 311 312 { 313 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 314 315 if ( !mpObj ) 316 throw embed::ObjectSaveVetoException(); 317 318 // the common persistence is supported by objects and links 319 xPersist = uno::Reference< embed::XCommonEmbedPersist >( mpObj->GetObjRef(), uno::UNO_QUERY_THROW ); 320 xModifiable = uno::Reference< util::XModifiable >( mpObj->GetParentXModel(), uno::UNO_QUERY ); 321 } 322 323 xPersist->storeOwn(); 324 325 if ( xModifiable.is() ) 326 xModifiable->setModified( sal_True ); 327 } 328 329 //-------------------------------------------------------------------- 330 void SAL_CALL SdrLightEmbeddedClient_Impl::visibilityChanged( sal_Bool /*bVisible*/ ) 331 throw ( embed::WrongStateException, 332 uno::RuntimeException ) 333 { 334 // nothing to do currently 335 // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl 336 if ( mpObj ) 337 { 338 Rectangle aLogicRect( mpObj->GetLogicRect() ); 339 Size aLogicSize( aLogicRect.GetWidth(), aLogicRect.GetHeight() ); 340 341 if( mpObj->IsChart() ) 342 { 343 // charts never should be stretched see #i84323# for example 344 mpObj->SetLogicRect( Rectangle( aLogicRect.TopLeft(), aLogicSize ) ); 345 mpObj->BroadcastObjectChange(); 346 } // if( mpObj->IsChart() ) 347 } 348 } 349 350 //-------------------------------------------------------------------- 351 uno::Reference< util::XCloseable > SAL_CALL SdrLightEmbeddedClient_Impl::getComponent() 352 throw ( uno::RuntimeException ) 353 { 354 uno::Reference< util::XCloseable > xResult; 355 356 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 357 if ( mpObj ) 358 xResult = uno::Reference< util::XCloseable >( mpObj->GetParentXModel(), uno::UNO_QUERY ); 359 360 return xResult; 361 } 362 // XInplaceClient 363 //-------------------------------------------------------------------- 364 sal_Bool SAL_CALL SdrLightEmbeddedClient_Impl::canInplaceActivate() 365 throw ( uno::RuntimeException ) 366 { 367 sal_Bool bRet = sal_False; 368 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 369 if ( mpObj ) 370 { 371 uno::Reference< embed::XEmbeddedObject > xObject = mpObj->GetObjRef(); 372 if ( !xObject.is() ) 373 throw uno::RuntimeException(); 374 // we don't want to switch directly from outplace to inplace mode 375 bRet = !( xObject->getCurrentState() == embed::EmbedStates::ACTIVE || mpObj->GetAspect() == embed::Aspects::MSOLE_ICON ); 376 } // if ( mpObj ) 377 return bRet; 378 } 379 380 //-------------------------------------------------------------------- 381 void SAL_CALL SdrLightEmbeddedClient_Impl::activatingInplace() 382 throw ( embed::WrongStateException, 383 uno::RuntimeException ) 384 { 385 } 386 387 //-------------------------------------------------------------------- 388 void SAL_CALL SdrLightEmbeddedClient_Impl::activatingUI() 389 throw ( embed::WrongStateException, 390 uno::RuntimeException ) 391 { 392 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 393 394 uno::Reference < beans::XPropertySet > xFrame( lcl_getFrame_throw(mpObj)); 395 uno::Reference < frame::XFrame > xOwnFrame( xFrame,uno::UNO_QUERY); 396 uno::Reference < frame::XFramesSupplier > xParentFrame( xOwnFrame->getCreator(), uno::UNO_QUERY ); 397 if ( xParentFrame.is() ) 398 xParentFrame->setActiveFrame( xOwnFrame ); 399 400 OLEObjCache& rObjCache = GetSdrGlobalData().GetOLEObjCache(); 401 const sal_uIntPtr nCount = rObjCache.Count(); 402 for(sal_Int32 i = nCount-1 ; i >= 0;--i) 403 { 404 SdrOle2Obj* pObj = reinterpret_cast<SdrOle2Obj*>(rObjCache.GetObject(i)); 405 if ( pObj != mpObj ) 406 { 407 // only deactivate ole objects which belongs to the same frame 408 if ( xFrame == lcl_getFrame_throw(pObj) ) 409 { 410 uno::Reference< embed::XEmbeddedObject > xObject = pObj->GetObjRef(); 411 try 412 { 413 if ( xObject->getStatus( pObj->GetAspect() ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE ) 414 xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE ); 415 else 416 { 417 // the links should not stay in running state for long time because of locking 418 uno::Reference< embed::XLinkageSupport > xLink( xObject, uno::UNO_QUERY ); 419 if ( xLink.is() && xLink->isLink() ) 420 xObject->changeState( embed::EmbedStates::LOADED ); 421 else 422 xObject->changeState( embed::EmbedStates::RUNNING ); 423 } 424 } 425 catch (com::sun::star::uno::Exception& ) 426 {} 427 } 428 } 429 } // for(sal_Int32 i = nCount-1 ; i >= 0;--i) 430 431 //m_pClient->GetViewShell()->UIActivating( m_pClient ); 432 } 433 434 //-------------------------------------------------------------------- 435 void SAL_CALL SdrLightEmbeddedClient_Impl::deactivatedInplace() 436 throw ( embed::WrongStateException, 437 uno::RuntimeException ) 438 { 439 } 440 441 //-------------------------------------------------------------------- 442 void SAL_CALL SdrLightEmbeddedClient_Impl::deactivatedUI() 443 throw ( embed::WrongStateException, 444 uno::RuntimeException ) 445 { 446 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 447 com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager(getLayoutManager()); 448 if ( xLayoutManager.is() ) 449 { 450 const static rtl::OUString aMenuBarURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )); 451 if ( !xLayoutManager->isElementVisible( aMenuBarURL ) ) 452 xLayoutManager->createElement( aMenuBarURL ); 453 } 454 } 455 456 //-------------------------------------------------------------------- 457 uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL SdrLightEmbeddedClient_Impl::getLayoutManager() 458 throw ( embed::WrongStateException, 459 uno::RuntimeException ) 460 { 461 uno::Reference< ::com::sun::star::frame::XLayoutManager > xMan; 462 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 463 uno::Reference < beans::XPropertySet > xFrame( lcl_getFrame_throw(mpObj)); 464 try 465 { 466 xMan.set(xFrame->getPropertyValue( ::rtl::OUString::createFromAscii("LayoutManager") ),uno::UNO_QUERY); 467 } 468 catch ( uno::Exception& ) 469 { 470 throw uno::RuntimeException(); 471 } 472 473 return xMan; 474 } 475 476 //-------------------------------------------------------------------- 477 uno::Reference< frame::XDispatchProvider > SAL_CALL SdrLightEmbeddedClient_Impl::getInplaceDispatchProvider() 478 throw ( embed::WrongStateException, 479 uno::RuntimeException ) 480 { 481 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 482 return uno::Reference < frame::XDispatchProvider >( lcl_getFrame_throw(mpObj), uno::UNO_QUERY_THROW ); 483 } 484 485 //-------------------------------------------------------------------- 486 awt::Rectangle SAL_CALL SdrLightEmbeddedClient_Impl::getPlacement() 487 throw ( embed::WrongStateException, 488 uno::RuntimeException ) 489 { 490 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 491 if ( !mpObj ) 492 throw uno::RuntimeException(); 493 494 Rectangle aLogicRect = impl_getScaledRect_nothrow(); 495 MapUnit aContainerMapUnit( MAP_100TH_MM ); 496 uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); 497 if ( xParentVis.is() ) 498 aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) ); 499 500 aLogicRect = Application::GetDefaultDevice()->LogicToPixel(aLogicRect,aContainerMapUnit); 501 return AWTRectangle( aLogicRect ); 502 } 503 504 //-------------------------------------------------------------------- 505 awt::Rectangle SAL_CALL SdrLightEmbeddedClient_Impl::getClipRectangle() 506 throw ( embed::WrongStateException, 507 uno::RuntimeException ) 508 { 509 return getPlacement(); 510 } 511 512 //-------------------------------------------------------------------- 513 void SAL_CALL SdrLightEmbeddedClient_Impl::translateAccelerators( const uno::Sequence< awt::KeyEvent >& /*aKeys*/ ) 514 throw ( embed::WrongStateException, 515 uno::RuntimeException ) 516 { 517 } 518 519 //-------------------------------------------------------------------- 520 void SAL_CALL SdrLightEmbeddedClient_Impl::scrollObject( const awt::Size& /*aOffset*/ ) 521 throw ( embed::WrongStateException, 522 uno::RuntimeException ) 523 { 524 } 525 526 //-------------------------------------------------------------------- 527 void SAL_CALL SdrLightEmbeddedClient_Impl::changedPlacement( const awt::Rectangle& aPosRect ) 528 throw ( embed::WrongStateException, 529 uno::Exception, 530 uno::RuntimeException ) 531 { 532 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 533 if ( !mpObj ) 534 throw uno::RuntimeException(); 535 536 uno::Reference< embed::XInplaceObject > xInplace( mpObj->GetObjRef(), uno::UNO_QUERY ); 537 if ( !xInplace.is() ) 538 throw uno::RuntimeException(); 539 540 // check if the change is at least one pixel in size 541 awt::Rectangle aOldRect = getPlacement(); 542 Rectangle aNewPixelRect = VCLRectangle( aPosRect ); 543 Rectangle aOldPixelRect = VCLRectangle( aOldRect ); 544 if ( aOldPixelRect == aNewPixelRect ) 545 // nothing has changed 546 return; 547 548 // new scaled object area 549 MapUnit aContainerMapUnit( MAP_100TH_MM ); 550 uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); 551 if ( xParentVis.is() ) 552 aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) ); 553 554 Rectangle aNewLogicRect = Application::GetDefaultDevice()->PixelToLogic(aNewPixelRect,aContainerMapUnit); 555 Rectangle aLogicRect = impl_getScaledRect_nothrow(); 556 557 if ( aNewLogicRect != aLogicRect ) 558 { 559 // the calculation of the object area has not changed the object size 560 // it should be done here then 561 //SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True ); 562 563 // new size of the object area without scaling 564 Size aNewObjSize( Fraction( aNewLogicRect.GetWidth() ) / m_aScaleWidth, 565 Fraction( aNewLogicRect.GetHeight() ) / m_aScaleHeight ); 566 567 // now remove scaling from new placement and keep this a the new object area 568 aNewLogicRect.SetSize( aNewObjSize ); 569 // react to the change if the difference is bigger than one pixel 570 Size aPixelDiff = 571 Application::GetDefaultDevice()->LogicToPixel( 572 Size( aLogicRect.GetWidth() - aNewObjSize.Width(), 573 aLogicRect.GetHeight() - aNewObjSize.Height() ), 574 aContainerMapUnit ); 575 if( aPixelDiff.Width() || aPixelDiff.Height() ) 576 { 577 mpObj->SetLogicRect( Rectangle( aLogicRect.TopLeft(), aNewObjSize ) ); 578 mpObj->BroadcastObjectChange(); 579 } 580 else 581 mpObj->ActionChanged(); 582 583 // let the window size be recalculated 584 //SizeHasChanged(); // TODO: OJ 585 } 586 } 587 // XWindowSupplier 588 //-------------------------------------------------------------------- 589 uno::Reference< awt::XWindow > SAL_CALL SdrLightEmbeddedClient_Impl::getWindow() 590 throw ( uno::RuntimeException ) 591 { 592 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 593 uno::Reference< awt::XWindow > xCurrent = m_xWindow; 594 if ( !xCurrent.is() ) 595 { 596 if ( !mpObj ) 597 throw uno::RuntimeException(); 598 uno::Reference< frame::XFrame> xFrame(lcl_getFrame_throw(mpObj),uno::UNO_QUERY_THROW); 599 xCurrent = xFrame->getComponentWindow(); 600 } // if ( !xCurrent.is() ) 601 return xCurrent; 602 } 603 void SdrLightEmbeddedClient_Impl::setWindow(const uno::Reference< awt::XWindow >& _xWindow) 604 { 605 m_xWindow = _xWindow; 606 } 607 608 //////////////////////////////////////////////////////////////////////////////////////////////////// 609 610 class SdrEmbedObjectLink : public sfx2::SvBaseLink 611 { 612 SdrOle2Obj* pObj; 613 614 public: 615 SdrEmbedObjectLink(SdrOle2Obj* pObj); 616 virtual ~SdrEmbedObjectLink(); 617 618 virtual void Closed(); 619 virtual void DataChanged( const String& rMimeType, 620 const ::com::sun::star::uno::Any & rValue ); 621 622 sal_Bool Connect() { return GetRealObject() != NULL; } 623 }; 624 625 // ----------------------------------------------------------------------------- 626 627 SdrEmbedObjectLink::SdrEmbedObjectLink(SdrOle2Obj* pObject): 628 ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL, SOT_FORMATSTR_ID_SVXB ), 629 pObj(pObject) 630 { 631 SetSynchron( sal_False ); 632 } 633 634 // ----------------------------------------------------------------------------- 635 636 SdrEmbedObjectLink::~SdrEmbedObjectLink() 637 { 638 } 639 640 // ----------------------------------------------------------------------------- 641 642 void SdrEmbedObjectLink::DataChanged( const String& /*rMimeType*/, 643 const ::com::sun::star::uno::Any & /*rValue*/ ) 644 { 645 if ( !pObj->UpdateLinkURL_Impl() ) 646 { 647 // the link URL was not changed 648 uno::Reference< embed::XEmbeddedObject > xObject = pObj->GetObjRef(); 649 OSL_ENSURE( xObject.is(), "The object must exist always!\n" ); 650 if ( xObject.is() ) 651 { 652 // let the object reload the link 653 // TODO/LATER: reload call could be used for this case 654 655 try 656 { 657 sal_Int32 nState = xObject->getCurrentState(); 658 if ( nState != embed::EmbedStates::LOADED ) 659 { 660 // in some cases the linked file probably is not locked so it could be changed 661 xObject->changeState( embed::EmbedStates::LOADED ); 662 xObject->changeState( nState ); 663 } 664 } 665 catch ( uno::Exception& ) 666 { 667 } 668 } 669 } 670 671 pObj->GetNewReplacement(); 672 pObj->SetChanged(); 673 } 674 675 // ----------------------------------------------------------------------------- 676 677 void SdrEmbedObjectLink::Closed() 678 { 679 pObj->BreakFileLink_Impl(); 680 SvBaseLink::Closed(); 681 } 682 683 //////////////////////////////////////////////////////////////////////////////////////////////////// 684 685 class SdrOle2ObjImpl 686 { 687 public: 688 // TODO/LATER: do we really need this pointer? 689 GraphicObject* pGraphicObject; 690 String aPersistName; // name of object in persist 691 SdrLightEmbeddedClient_Impl* pLightClient; // must be registered as client only using AddOwnLightClient() call 692 693 // #107645# 694 // New local var to avoid repeated loading if load of OLE2 fails 695 sal_Bool mbLoadingOLEObjectFailed; 696 sal_Bool mbConnected; 697 698 SdrEmbedObjectLink* mpObjectLink; 699 String maLinkURL; 700 701 SdrOle2ObjImpl() 702 : pGraphicObject( NULL ) 703 // #107645# 704 // init to start situation, loading did not fail 705 , mbLoadingOLEObjectFailed( sal_False ) 706 , mbConnected( sal_False ) 707 , mpObjectLink( NULL ) 708 { 709 } 710 }; 711 712 //////////////////////////////////////////////////////////////////////////////////////////////////// 713 714 // Predicate determining whether the given OLE is an internal math 715 // object 716 static bool ImplIsMathObj( const uno::Reference < embed::XEmbeddedObject >& rObjRef ) 717 { 718 if ( !rObjRef.is() ) 719 return false; 720 721 SvGlobalName aClassName( rObjRef->getClassID() ); 722 if( aClassName == SvGlobalName(SO3_SM_CLASSID_30) || 723 aClassName == SvGlobalName(SO3_SM_CLASSID_40) || 724 aClassName == SvGlobalName(SO3_SM_CLASSID_50) || 725 aClassName == SvGlobalName(SO3_SM_CLASSID_60) || 726 aClassName == SvGlobalName(SO3_SM_CLASSID) ) 727 { 728 return true; 729 } 730 else 731 { 732 return false; 733 } 734 } 735 736 ////////////////////////////////////////////////////////////////////////////// 737 // BaseProperties section 738 739 sdr::properties::BaseProperties* SdrOle2Obj::CreateObjectSpecificProperties() 740 { 741 return new sdr::properties::OleProperties(*this); 742 } 743 744 ////////////////////////////////////////////////////////////////////////////// 745 // DrawContact section 746 747 sdr::contact::ViewContact* SdrOle2Obj::CreateObjectSpecificViewContact() 748 { 749 return new sdr::contact::ViewContactOfSdrOle2Obj(*this); 750 } 751 752 // ----------------------------------------------------------------------------- 753 754 TYPEINIT1(SdrOle2Obj,SdrRectObj); 755 DBG_NAME(SdrOle2Obj) 756 SdrOle2Obj::SdrOle2Obj(FASTBOOL bFrame_) : m_bTypeAsked(false) 757 ,m_bChart(false) 758 { 759 DBG_CTOR( SdrOle2Obj,NULL); 760 bInDestruction = sal_False; 761 mbSuppressSetVisAreaSize = false; 762 Init(); 763 bFrame=bFrame_; 764 } 765 766 // ----------------------------------------------------------------------------- 767 SdrOle2Obj::SdrOle2Obj( const svt::EmbeddedObjectRef& rNewObjRef, FASTBOOL bFrame_) 768 : xObjRef( rNewObjRef ) 769 , m_bTypeAsked(false) 770 , m_bChart(false) 771 { 772 DBG_CTOR( SdrOle2Obj,NULL); 773 bInDestruction = sal_False; 774 mbSuppressSetVisAreaSize = false; 775 Init(); 776 777 bFrame=bFrame_; 778 779 if ( xObjRef.is() && (xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) ) 780 SetResizeProtect(sal_True); 781 782 // #108759# For math objects, set closed state to transparent 783 SetClosedObj(!ImplIsMathObj( xObjRef.GetObject() )); 784 } 785 786 // ----------------------------------------------------------------------------- 787 788 SdrOle2Obj::SdrOle2Obj( const svt::EmbeddedObjectRef& rNewObjRef, const XubString& rNewObjName, FASTBOOL bFrame_) 789 : xObjRef( rNewObjRef ) 790 , m_bTypeAsked(false) 791 , m_bChart(false) 792 { 793 DBG_CTOR( SdrOle2Obj,NULL); 794 bInDestruction = sal_False; 795 mbSuppressSetVisAreaSize = false; 796 Init(); 797 798 mpImpl->aPersistName = rNewObjName; 799 bFrame=bFrame_; 800 801 if ( xObjRef.is() && (xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) ) 802 SetResizeProtect(sal_True); 803 804 // #108759# For math objects, set closed state to transparent 805 SetClosedObj(!ImplIsMathObj( xObjRef.GetObject() )); 806 } 807 808 // ----------------------------------------------------------------------------- 809 810 SdrOle2Obj::SdrOle2Obj( const svt::EmbeddedObjectRef& rNewObjRef, const XubString& rNewObjName, const Rectangle& rNewRect, FASTBOOL bFrame_) 811 : SdrRectObj(rNewRect) 812 , xObjRef( rNewObjRef ) 813 , m_bTypeAsked(false) 814 , m_bChart(false) 815 { 816 DBG_CTOR( SdrOle2Obj,NULL); 817 bInDestruction = sal_False; 818 mbSuppressSetVisAreaSize = false; 819 Init(); 820 821 mpImpl->aPersistName = rNewObjName; 822 bFrame=bFrame_; 823 824 if ( xObjRef.is() && (xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) ) 825 SetResizeProtect(sal_True); 826 827 // #108759# For math objects, set closed state to transparent 828 SetClosedObj(!ImplIsMathObj( xObjRef.GetObject() )); 829 } 830 831 // ----------------------------------------------------------------------------- 832 833 void SdrOle2Obj::Init() 834 { 835 mpImpl = new SdrOle2ObjImpl; 836 pModifyListener = NULL; 837 pGraphic=NULL; 838 mpImpl->pGraphicObject=NULL; 839 mpImpl->pLightClient = 0; 840 841 xObjRef.Lock( sal_True ); 842 } 843 844 // ----------------------------------------------------------------------------- 845 String SdrOle2Obj::GetStyleString() 846 { 847 String strStyle; 848 if( xObjRef.is() && xObjRef.IsChart() ) 849 { 850 strStyle = xObjRef.GetChartType(); 851 } 852 return strStyle; 853 } 854 855 // ----------------------------------------------------------------------------- 856 SdrOle2Obj::~SdrOle2Obj() 857 { 858 DBG_DTOR( SdrOle2Obj,NULL); 859 bInDestruction = sal_True; 860 861 if ( mpImpl->mbConnected ) 862 Disconnect(); 863 864 if( pGraphic!=NULL ) 865 delete pGraphic; 866 867 if(mpImpl->pGraphicObject!=NULL) 868 delete mpImpl->pGraphicObject; 869 870 if(pModifyListener) 871 { 872 pModifyListener->invalidate(); 873 pModifyListener->release(); 874 } 875 876 DisconnectFileLink_Impl(); 877 878 if ( mpImpl->pLightClient ) 879 { 880 mpImpl->pLightClient->Release(); 881 mpImpl->pLightClient = NULL; 882 } 883 884 delete mpImpl; 885 } 886 887 // ----------------------------------------------------------------------------- 888 void SdrOle2Obj::SetAspect( sal_Int64 nAspect ) 889 { 890 xObjRef.SetViewAspect( nAspect ); 891 } 892 893 // ----------------------------------------------------------------------------- 894 bool SdrOle2Obj::isInplaceActive() const 895 { 896 return xObjRef.is() && embed::EmbedStates::INPLACE_ACTIVE == xObjRef->getCurrentState(); 897 } 898 899 // ----------------------------------------------------------------------------- 900 bool SdrOle2Obj::isUiActive() const 901 { 902 return xObjRef.is() && embed::EmbedStates::UI_ACTIVE == xObjRef->getCurrentState(); 903 } 904 905 // ----------------------------------------------------------------------------- 906 907 void SdrOle2Obj::SetGraphic_Impl(const Graphic* pGrf) 908 { 909 if ( pGraphic ) 910 { 911 delete pGraphic; 912 pGraphic = NULL; 913 delete mpImpl->pGraphicObject; 914 mpImpl->pGraphicObject = NULL; 915 } 916 917 if (pGrf!=NULL) 918 { 919 pGraphic = new Graphic(*pGrf); 920 mpImpl->pGraphicObject = new GraphicObject( *pGraphic ); 921 } 922 923 SetChanged(); 924 BroadcastObjectChange(); 925 926 //if ( ppObjRef->Is() && pGrf ) 927 // BroadcastObjectChange(); 928 } 929 930 void SdrOle2Obj::SetGraphic(const Graphic* pGrf) 931 { 932 // only for setting a preview graphic 933 SetGraphic_Impl( pGrf ); 934 } 935 936 // ----------------------------------------------------------------------------- 937 938 FASTBOOL SdrOle2Obj::IsEmpty() const 939 { 940 return !(xObjRef.is()); 941 } 942 943 // ----------------------------------------------------------------------------- 944 945 void SdrOle2Obj::Connect() 946 { 947 if( IsEmptyPresObj() ) 948 return; 949 950 if( mpImpl->mbConnected ) 951 { 952 // mba: currently there are situations where it seems to be unavoidable to have multiple connects 953 // changing this would need a larger code rewrite, so for now I remove the assertion 954 // DBG_ERROR("Connect() called on connected object!"); 955 return; 956 } 957 958 Connect_Impl(); 959 AddListeners_Impl(); 960 } 961 962 // ----------------------------------------------------------------------------- 963 964 sal_Bool SdrOle2Obj::UpdateLinkURL_Impl() 965 { 966 sal_Bool bResult = sal_False; 967 968 if ( mpImpl->mpObjectLink ) 969 { 970 sfx2::LinkManager* pLinkManager = pModel ? pModel->GetLinkManager() : NULL; 971 if ( pLinkManager ) 972 { 973 String aNewLinkURL; 974 pLinkManager->GetDisplayNames( mpImpl->mpObjectLink, 0, &aNewLinkURL, 0, 0 ); 975 if ( !aNewLinkURL.EqualsIgnoreCaseAscii( mpImpl->maLinkURL ) ) 976 { 977 const_cast<SdrOle2Obj*>(this)->GetObjRef_Impl(); 978 uno::Reference< embed::XCommonEmbedPersist > xPersObj( xObjRef.GetObject(), uno::UNO_QUERY ); 979 OSL_ENSURE( xPersObj.is(), "The object must exist!\n" ); 980 if ( xPersObj.is() ) 981 { 982 try 983 { 984 sal_Int32 nCurState = xObjRef->getCurrentState(); 985 if ( nCurState != embed::EmbedStates::LOADED ) 986 xObjRef->changeState( embed::EmbedStates::LOADED ); 987 988 // TODO/LATER: there should be possible to get current mediadescriptor settings from the object 989 uno::Sequence< beans::PropertyValue > aArgs( 1 ); 990 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); 991 aArgs[0].Value <<= ::rtl::OUString( aNewLinkURL ); 992 xPersObj->reload( aArgs, uno::Sequence< beans::PropertyValue >() ); 993 994 mpImpl->maLinkURL = aNewLinkURL; 995 bResult = sal_True; 996 997 if ( nCurState != embed::EmbedStates::LOADED ) 998 xObjRef->changeState( nCurState ); 999 } 1000 catch( ::com::sun::star::uno::Exception& e ) 1001 { 1002 (void)e; 1003 DBG_ERROR( 1004 (OString("SdrOle2Obj::UpdateLinkURL_Impl(), " 1005 "exception caught: ") + 1006 rtl::OUStringToOString( 1007 comphelper::anyToString( cppu::getCaughtException() ), 1008 RTL_TEXTENCODING_UTF8 )).getStr() ); 1009 } 1010 } 1011 1012 if ( !bResult ) 1013 { 1014 // TODO/LATER: return the old name to the link manager, is it possible? 1015 } 1016 } 1017 } 1018 } 1019 1020 return bResult; 1021 } 1022 1023 // ----------------------------------------------------------------------------- 1024 1025 void SdrOle2Obj::BreakFileLink_Impl() 1026 { 1027 uno::Reference<document::XStorageBasedDocument> xDoc; 1028 if ( pModel ) 1029 xDoc.set( pModel->getUnoModel(),uno::UNO_QUERY); 1030 1031 if ( xDoc.is() ) 1032 { 1033 uno::Reference< embed::XStorage > xStorage = xDoc->getDocumentStorage(); 1034 if ( xStorage.is() ) 1035 { 1036 try 1037 { 1038 uno::Reference< embed::XLinkageSupport > xLinkSupport( xObjRef.GetObject(), uno::UNO_QUERY_THROW ); 1039 xLinkSupport->breakLink( xStorage, mpImpl->aPersistName ); 1040 DisconnectFileLink_Impl(); 1041 mpImpl->maLinkURL = String(); 1042 } 1043 catch( ::com::sun::star::uno::Exception& e ) 1044 { 1045 (void)e; 1046 DBG_ERROR( 1047 (OString("SdrOle2Obj::BreakFileLink_Impl(), " 1048 "exception caught: ") + 1049 rtl::OUStringToOString( 1050 comphelper::anyToString( cppu::getCaughtException() ), 1051 RTL_TEXTENCODING_UTF8 )).getStr() ); 1052 } 1053 } 1054 } 1055 } 1056 1057 // ----------------------------------------------------------------------------- 1058 1059 void SdrOle2Obj::DisconnectFileLink_Impl() 1060 { 1061 sfx2::LinkManager* pLinkManager = pModel ? pModel->GetLinkManager() : NULL; 1062 if ( pLinkManager && mpImpl->mpObjectLink ) 1063 { 1064 pLinkManager->Remove( mpImpl->mpObjectLink ); 1065 mpImpl->mpObjectLink = NULL; 1066 } 1067 } 1068 1069 // ----------------------------------------------------------------------------- 1070 1071 void SdrOle2Obj::CheckFileLink_Impl() 1072 { 1073 if ( pModel && xObjRef.GetObject().is() && !mpImpl->mpObjectLink ) 1074 { 1075 try 1076 { 1077 uno::Reference< embed::XLinkageSupport > xLinkSupport( xObjRef.GetObject(), uno::UNO_QUERY ); 1078 if ( xLinkSupport.is() && xLinkSupport->isLink() ) 1079 { 1080 String aLinkURL = xLinkSupport->getLinkURL(); 1081 if ( aLinkURL.Len() ) 1082 { 1083 // this is a file link so the model link manager should handle it 1084 sfx2::LinkManager* pLinkManager = pModel->GetLinkManager(); 1085 if ( pLinkManager ) 1086 { 1087 mpImpl->mpObjectLink = new SdrEmbedObjectLink( this ); 1088 mpImpl->maLinkURL = aLinkURL; 1089 pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL, NULL, NULL ); 1090 mpImpl->mpObjectLink->Connect(); 1091 } 1092 } 1093 } 1094 } 1095 catch( ::com::sun::star::uno::Exception& e ) 1096 { 1097 (void)e; 1098 DBG_ERROR( 1099 (OString("SdrOle2Obj::CheckFileLink_Impl(), " 1100 "exception caught: ") + 1101 rtl::OUStringToOString( 1102 comphelper::anyToString( cppu::getCaughtException() ), 1103 RTL_TEXTENCODING_UTF8 )).getStr() ); 1104 } 1105 } 1106 } 1107 1108 // ----------------------------------------------------------------------------- 1109 1110 void SdrOle2Obj::Reconnect_Impl() 1111 { 1112 DBG_ASSERT( mpImpl->mbConnected, "Assigned unconnected object?!" ); 1113 Connect_Impl(); 1114 } 1115 1116 void SdrOle2Obj::Connect_Impl() 1117 { 1118 if( pModel && mpImpl->aPersistName.Len() ) 1119 { 1120 try 1121 { 1122 ::comphelper::IEmbeddedHelper* pPers = pModel->GetPersist(); 1123 if ( pPers ) 1124 { 1125 comphelper::EmbeddedObjectContainer& rContainer = pPers->getEmbeddedObjectContainer(); 1126 if ( !rContainer.HasEmbeddedObject( mpImpl->aPersistName ) 1127 || ( xObjRef.is() && !rContainer.HasEmbeddedObject( xObjRef.GetObject() ) ) ) 1128 { 1129 // object not known to container document 1130 // No object -> disaster! 1131 DBG_ASSERT( xObjRef.is(), "No object in connect!"); 1132 if ( xObjRef.is() ) 1133 { 1134 // object came from the outside, now add it to the container 1135 ::rtl::OUString aTmp; 1136 rContainer.InsertEmbeddedObject( xObjRef.GetObject(), aTmp ); 1137 mpImpl->aPersistName = aTmp; 1138 } 1139 } 1140 else if ( !xObjRef.is() ) 1141 { 1142 xObjRef.Assign( rContainer.GetEmbeddedObject( mpImpl->aPersistName ), xObjRef.GetViewAspect() ); 1143 m_bTypeAsked = false; 1144 } 1145 1146 if ( xObjRef.GetObject().is() ) 1147 { 1148 xObjRef.AssignToContainer( &rContainer, mpImpl->aPersistName ); 1149 mpImpl->mbConnected = true; 1150 xObjRef.Lock( sal_True ); 1151 } 1152 } 1153 1154 if ( xObjRef.is() ) 1155 { 1156 if ( !mpImpl->pLightClient ) 1157 { 1158 mpImpl->pLightClient = new SdrLightEmbeddedClient_Impl( this ); 1159 mpImpl->pLightClient->acquire(); 1160 } 1161 1162 xObjRef->addStateChangeListener( mpImpl->pLightClient ); 1163 xObjRef->addEventListener( uno::Reference< document::XEventListener >( mpImpl->pLightClient ) ); 1164 1165 if ( xObjRef->getCurrentState() != embed::EmbedStates::LOADED ) 1166 GetSdrGlobalData().GetOLEObjCache().InsertObj(this); 1167 1168 CheckFileLink_Impl(); 1169 1170 uno::Reference< container::XChild > xChild( xObjRef.GetObject(), uno::UNO_QUERY ); 1171 if( xChild.is() ) 1172 { 1173 uno::Reference< uno::XInterface > xParent( pModel->getUnoModel()); 1174 if( xParent.is()) 1175 xChild->setParent( pModel->getUnoModel() ); 1176 } 1177 1178 } 1179 } 1180 catch( ::com::sun::star::uno::Exception& e ) 1181 { 1182 (void)e; 1183 DBG_ERROR( 1184 (OString("SdrOle2Obj::Connect_Impl(), " 1185 "exception caught: ") + 1186 rtl::OUStringToOString( 1187 comphelper::anyToString( cppu::getCaughtException() ), 1188 RTL_TEXTENCODING_UTF8 )).getStr() ); 1189 } 1190 } 1191 1192 //TODO/LATER: wait for definition of MiscStatus RESIZEONPRINTERCHANGE 1193 //if ( xObjRef.is() && (*ppObjRef)->GetMiscStatus() & SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE ) 1194 { 1195 //TODO/LATER: needs a new handling for OnPrinterChanged 1196 /* 1197 if (pModel && pModel->GetRefDevice() && 1198 pModel->GetRefDevice()->GetOutDevType() == OUTDEV_PRINTER) 1199 { 1200 // Kein RefDevice oder RefDevice kein Printer 1201 sal_Bool bModified = (*ppObjRef)->IsModified(); 1202 Printer* pPrinter = (Printer*) pModel->GetRefDevice(); 1203 (*ppObjRef)->OnDocumentPrinterChanged( pPrinter ); 1204 (*ppObjRef)->SetModified( bModified ); 1205 }*/ 1206 } 1207 } 1208 1209 void SdrOle2Obj::ObjectLoaded() 1210 { 1211 AddListeners_Impl(); 1212 } 1213 1214 void SdrOle2Obj::AddListeners_Impl() 1215 { 1216 if( xObjRef.is() && xObjRef->getCurrentState() != embed::EmbedStates::LOADED ) 1217 { 1218 // register modify listener 1219 if( !pModifyListener ) 1220 { 1221 ((SdrOle2Obj*)this)->pModifyListener = new SvxUnoShapeModifyListener( (SdrOle2Obj*)this ); 1222 pModifyListener->acquire(); 1223 } 1224 1225 uno::Reference< util::XModifyBroadcaster > xBC( getXModel(), uno::UNO_QUERY ); 1226 if( xBC.is() && pModifyListener ) 1227 { 1228 uno::Reference< util::XModifyListener > xListener( pModifyListener ); 1229 xBC->addModifyListener( xListener ); 1230 } 1231 } 1232 } 1233 1234 // ----------------------------------------------------------------------------- 1235 1236 void SdrOle2Obj::Disconnect() 1237 { 1238 if( IsEmptyPresObj() ) 1239 return; 1240 1241 if( !mpImpl->mbConnected ) 1242 { 1243 DBG_ERROR("Disconnect() called on disconnected object!"); 1244 return; 1245 } 1246 1247 RemoveListeners_Impl(); 1248 Disconnect_Impl(); 1249 } 1250 1251 void SdrOle2Obj::RemoveListeners_Impl() 1252 { 1253 if( xObjRef.is() && mpImpl->aPersistName.Len() ) 1254 { 1255 try 1256 { 1257 sal_Int32 nState = xObjRef->getCurrentState(); 1258 if ( nState != embed::EmbedStates::LOADED ) 1259 { 1260 uno::Reference< util::XModifyBroadcaster > xBC( getXModel(), uno::UNO_QUERY ); 1261 if( xBC.is() && pModifyListener ) 1262 { 1263 uno::Reference< util::XModifyListener > xListener( pModifyListener ); 1264 xBC->removeModifyListener( xListener ); 1265 } 1266 } 1267 } 1268 catch( ::com::sun::star::uno::Exception& e ) 1269 { 1270 (void)e; 1271 DBG_ERROR( 1272 (OString("SdrOle2Obj::RemoveListeners_Impl(), " 1273 "exception caught: ") + 1274 rtl::OUStringToOString( 1275 comphelper::anyToString( cppu::getCaughtException() ), 1276 RTL_TEXTENCODING_UTF8 )).getStr() ); 1277 } 1278 } 1279 } 1280 1281 void SdrOle2Obj::Disconnect_Impl() 1282 { 1283 try 1284 { 1285 if ( pModel && mpImpl->aPersistName.Len() ) 1286 { 1287 if( pModel->IsInDestruction() ) 1288 { 1289 // TODO/LATER: here we must assume that the destruction of the model is enough to make clear that we will not 1290 // remove the object from the container, even if the DrawingObject itself is not destroyed (unfortunately this 1291 // There is no real need to do the following removing of the object from the container 1292 // in case the model has correct persistence, but in case of problems such a removing 1293 // would make the behavior of the office more stable 1294 1295 comphelper::EmbeddedObjectContainer* pContainer = xObjRef.GetContainer(); 1296 if ( pContainer ) 1297 { 1298 pContainer->CloseEmbeddedObject( xObjRef.GetObject() ); 1299 xObjRef.AssignToContainer( NULL, mpImpl->aPersistName ); 1300 } 1301 1302 // happens later than the destruction of the model, so we can't assert that). 1303 //DBG_ASSERT( bInDestruction, "Model is destroyed, but not me?!" ); 1304 // TODO/LATER: should be make sure that the ObjectShell also forgets the object, because we will close it soon? 1305 /* 1306 uno::Reference < util::XCloseable > xClose( xObjRef, uno::UNO_QUERY ); 1307 if ( xClose.is() ) 1308 { 1309 try 1310 { 1311 xClose->close( sal_True ); 1312 } 1313 catch ( util::CloseVetoException& ) 1314 { 1315 // there's still someone who needs the object! 1316 } 1317 } 1318 1319 xObjRef = NULL;*/ 1320 } 1321 else if ( xObjRef.is() ) 1322 { 1323 if ( pModel->getUnoModel().is() ) 1324 { 1325 // remove object, but don't close it (that's up to someone else) 1326 comphelper::EmbeddedObjectContainer* pContainer = xObjRef.GetContainer(); 1327 if ( pContainer ) 1328 { 1329 pContainer->RemoveEmbeddedObject( xObjRef.GetObject(), sal_False); 1330 1331 // TODO/LATER: mpImpl->aPersistName contains outdated information, to have it uptodate 1332 // it should be returned from RemoveEmbeddedObject call. Currently it is no problem, 1333 // since no container is adjusted, actually the empty string could be provided as a name here 1334 xObjRef.AssignToContainer( NULL, mpImpl->aPersistName ); 1335 } 1336 1337 DisconnectFileLink_Impl(); 1338 } 1339 } 1340 } 1341 1342 if ( xObjRef.is() && mpImpl->pLightClient ) 1343 { 1344 xObjRef->removeStateChangeListener ( mpImpl->pLightClient ); 1345 xObjRef->removeEventListener( uno::Reference< document::XEventListener >( mpImpl->pLightClient ) ); 1346 xObjRef->setClientSite( NULL ); 1347 1348 GetSdrGlobalData().GetOLEObjCache().RemoveObj(this); 1349 } 1350 } 1351 catch( ::com::sun::star::uno::Exception& e ) 1352 { 1353 (void)e; 1354 DBG_ERROR( 1355 (OString("SdrOle2Obj::Disconnect_Impl(), " 1356 "exception caught: ") + 1357 rtl::OUStringToOString( 1358 comphelper::anyToString( cppu::getCaughtException() ), 1359 RTL_TEXTENCODING_UTF8 )).getStr() ); 1360 } 1361 1362 mpImpl->mbConnected = false; 1363 } 1364 1365 // ----------------------------------------------------------------------------- 1366 1367 SdrObject* SdrOle2Obj::createSdrGrafObjReplacement(bool bAddText, bool bUseHCGraphic) const 1368 { 1369 Graphic* pOLEGraphic = GetGraphic(); 1370 1371 if(bUseHCGraphic && Application::GetSettings().GetStyleSettings().GetHighContrastMode()) 1372 { 1373 pOLEGraphic = getEmbeddedObjectRef().GetHCGraphic(); 1374 } 1375 1376 if(pOLEGraphic) 1377 { 1378 // #i118485# allow creating a SdrGrafObj representation 1379 SdrGrafObj* pClone = new SdrGrafObj(*pOLEGraphic); 1380 pClone->SetModel(GetModel()); 1381 1382 // copy transformation 1383 basegfx::B2DHomMatrix aMatrix; 1384 basegfx::B2DPolyPolygon aPolyPolygon; 1385 1386 TRGetBaseGeometry(aMatrix, aPolyPolygon); 1387 pClone->TRSetBaseGeometry(aMatrix, aPolyPolygon); 1388 1389 // copy all attributes to support graphic styles for OLEs 1390 pClone->SetStyleSheet(GetStyleSheet(), false); 1391 pClone->SetMergedItemSet(GetMergedItemSet()); 1392 1393 if(bAddText) 1394 { 1395 // #i118485# copy text (Caution! Model needed, as guaranteed in aw080) 1396 OutlinerParaObject* pOPO = GetOutlinerParaObject(); 1397 1398 if(pOPO && GetModel()) 1399 { 1400 pClone->NbcSetOutlinerParaObject(new OutlinerParaObject(*pOPO)); 1401 } 1402 } 1403 1404 return pClone; 1405 } 1406 else 1407 { 1408 // #i100710# pOLEGraphic may be zero (no visualization available), 1409 // so we need to use the OLE replacement graphic 1410 SdrRectObj* pClone = new SdrRectObj(GetSnapRect()); 1411 pClone->SetModel(GetModel()); 1412 1413 // gray outline 1414 pClone->SetMergedItem(XLineStyleItem(XLINE_SOLID)); 1415 const svtools::ColorConfig aColorConfig; 1416 const svtools::ColorConfigValue aColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES)); 1417 pClone->SetMergedItem(XLineColorItem(String(), aColor.nColor)); 1418 1419 // bitmap fill 1420 pClone->SetMergedItem(XFillStyleItem(XFILL_BITMAP)); 1421 pClone->SetMergedItem(XFillBitmapItem(String(), Graphic(GetEmptyOLEReplacementBitmap()))); 1422 pClone->SetMergedItem(XFillBmpTileItem(false)); 1423 pClone->SetMergedItem(XFillBmpStretchItem(false)); 1424 1425 return pClone; 1426 } 1427 } 1428 1429 SdrObject* SdrOle2Obj::DoConvertToPolyObj(sal_Bool bBezier, bool bAddText) const 1430 { 1431 // #i118485# missing converter added 1432 if(GetModel()) 1433 { 1434 SdrObject* pRetval = createSdrGrafObjReplacement(true, false); 1435 1436 if(pRetval) 1437 { 1438 SdrObject* pRetval2 = pRetval->DoConvertToPolyObj(bBezier, bAddText); 1439 SdrObject::Free(pRetval); 1440 1441 return pRetval2; 1442 } 1443 } 1444 1445 return 0; 1446 } 1447 1448 // ----------------------------------------------------------------------------- 1449 1450 void SdrOle2Obj::SetModel(SdrModel* pNewModel) 1451 { 1452 ::comphelper::IEmbeddedHelper* pDestPers = pNewModel ? pNewModel->GetPersist() : 0; 1453 ::comphelper::IEmbeddedHelper* pSrcPers = pModel ? pModel->GetPersist() : 0; 1454 1455 if ( pNewModel == pModel ) 1456 { 1457 // don't know if this is necessary or if it will ever happen, but who know?! 1458 SdrRectObj::SetModel( pNewModel ); 1459 return; 1460 } 1461 1462 // assignment to model has changed 1463 DBG_ASSERT( pSrcPers || !mpImpl->mbConnected, "Connected object without a model?!" ); 1464 1465 DBG_ASSERT( pDestPers, "The destination model must have a persistence! Please submit an issue!" ); 1466 DBG_ASSERT( pDestPers != pSrcPers, "The source and the destination models should have different persistences! Problems are possible!" ); 1467 1468 // this is a bug if the target model has no persistence 1469 // no error handling is possible so just do nothing in this method 1470 if ( !pDestPers ) 1471 return; 1472 1473 RemoveListeners_Impl(); 1474 1475 if( pDestPers && pSrcPers && !IsEmptyPresObj() ) 1476 { 1477 try 1478 { 1479 // move the objects' storage; ObjectRef remains the same, but PersistName may change 1480 ::rtl::OUString aTmp; 1481 comphelper::EmbeddedObjectContainer& rContainer = pSrcPers->getEmbeddedObjectContainer(); 1482 uno::Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( mpImpl->aPersistName ); 1483 DBG_ASSERT( !xObjRef.is() || xObjRef.GetObject() == xObj, "Wrong object identity!" ); 1484 if ( xObj.is() ) 1485 { 1486 pDestPers->getEmbeddedObjectContainer().MoveEmbeddedObject( rContainer, xObj, aTmp ); 1487 mpImpl->aPersistName = aTmp; 1488 xObjRef.AssignToContainer( &pDestPers->getEmbeddedObjectContainer(), aTmp ); 1489 } 1490 DBG_ASSERT( aTmp.getLength(), "Copying embedded object failed!" ); 1491 } 1492 catch( ::com::sun::star::uno::Exception& e ) 1493 { 1494 (void)e; 1495 DBG_ERROR( 1496 (OString("SdrOle2Obj::SetModel(), " 1497 "exception caught: ") + 1498 rtl::OUStringToOString( 1499 comphelper::anyToString( cppu::getCaughtException() ), 1500 RTL_TEXTENCODING_UTF8 )).getStr() ); 1501 } 1502 } 1503 1504 SdrRectObj::SetModel( pNewModel ); 1505 1506 // #i43086# 1507 // #i85304 redo the change for charts for the above bugfix, as #i43086# does not occur anymore 1508 //so maybe the ImpSetVisAreaSize call can be removed here completely 1509 //Nevertheless I leave it in for other objects as I am not sure about the side effects when removing now 1510 if( pModel && !pModel->isLocked() && !IsChart() ) 1511 ImpSetVisAreaSize(); 1512 1513 if( pDestPers && !IsEmptyPresObj() ) 1514 { 1515 if ( !pSrcPers || IsEmptyPresObj() ) 1516 // object wasn't connected, now it should 1517 Connect_Impl(); 1518 else 1519 Reconnect_Impl(); 1520 } 1521 1522 AddListeners_Impl(); 1523 } 1524 1525 // ----------------------------------------------------------------------------- 1526 1527 void SdrOle2Obj::SetPage(SdrPage* pNewPage) 1528 { 1529 FASTBOOL bRemove=pNewPage==NULL && pPage!=NULL; 1530 FASTBOOL bInsert=pNewPage!=NULL && pPage==NULL; 1531 1532 if (bRemove && mpImpl->mbConnected ) 1533 Disconnect(); 1534 1535 if(!pModel && !GetStyleSheet() && pNewPage->GetModel()) 1536 { 1537 // #119287# Set default StyleSheet for SdrGrafObj here, it is different from 'Default'. This 1538 // needs to be done before the style 'Default' is set from the :SetModel() call which is triggered 1539 // from the following :SetPage(). 1540 // TTTT: Needs to be moved in branch aw080 due to having a SdrModel from the beginning, is at this 1541 // place for convenience currently (works in both versions, is not in the way) 1542 SfxStyleSheet* pSheet = pNewPage->GetModel()->GetDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj(); 1543 1544 if(pSheet) 1545 { 1546 SetStyleSheet(pSheet, false); 1547 } 1548 else 1549 { 1550 SetMergedItem(XFillStyleItem(XFILL_NONE)); 1551 SetMergedItem(XLineStyleItem(XLINE_NONE)); 1552 } 1553 } 1554 1555 SdrRectObj::SetPage(pNewPage); 1556 1557 if (bInsert && !mpImpl->mbConnected ) 1558 Connect(); 1559 } 1560 1561 // ----------------------------------------------------------------------------- 1562 1563 void SdrOle2Obj::SetObjRef( const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >& rNewObjRef ) 1564 { 1565 DBG_ASSERT( !rNewObjRef.is() || !xObjRef.GetObject().is(), "SetObjRef called on already initialized object!"); 1566 if( rNewObjRef == xObjRef.GetObject() ) 1567 return; 1568 1569 // MBA: the caller of the method is responsible to control the old object, it will not be closed here 1570 // Otherwise WW8 import crashes because it transfers control to OLENode by this method 1571 if ( xObjRef.GetObject().is() ) 1572 xObjRef.Lock( sal_False ); 1573 1574 // MBA: avoid removal of object in Disconnect! It is definitely a HACK to call SetObjRef(0)! 1575 // This call will try to close the objects; so if anybody else wants to keep it, it must be locked by a CloseListener 1576 xObjRef.Clear(); 1577 1578 if ( mpImpl->mbConnected ) 1579 Disconnect(); 1580 1581 xObjRef.Assign( rNewObjRef, GetAspect() ); 1582 m_bTypeAsked = false; 1583 1584 if ( xObjRef.is() ) 1585 { 1586 DELETEZ( pGraphic ); 1587 1588 if ( (xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) ) 1589 SetResizeProtect(sal_True); 1590 1591 // #108759# For math objects, set closed state to transparent 1592 SetClosedObj(!ImplIsMathObj( rNewObjRef )); 1593 1594 Connect(); 1595 } 1596 1597 SetChanged(); 1598 BroadcastObjectChange(); 1599 } 1600 1601 // ----------------------------------------------------------------------------- 1602 1603 void SdrOle2Obj::SetClosedObj( bool bIsClosed ) 1604 { 1605 // TODO/LATER: do we still need this hack? 1606 // #108759# Allow changes to the closed state of OLE objects 1607 bClosedObj = bIsClosed; 1608 } 1609 1610 // ----------------------------------------------------------------------------- 1611 1612 SdrObject* SdrOle2Obj::getFullDragClone() const 1613 { 1614 // special handling for OLE. The default handling works, but is too 1615 // slow when the whole OLE needs to be cloned. Get the Metafile and 1616 // create a graphic object with it 1617 1618 // #i118485# use central replacement generator 1619 return createSdrGrafObjReplacement(false, true); 1620 } 1621 1622 // ----------------------------------------------------------------------------- 1623 1624 void SdrOle2Obj::SetPersistName( const String& rPersistName ) 1625 { 1626 DBG_ASSERT( !mpImpl->aPersistName.Len(), "Persist name changed!"); 1627 1628 mpImpl->aPersistName = rPersistName; 1629 mpImpl->mbLoadingOLEObjectFailed = false; 1630 1631 Connect(); 1632 SetChanged(); 1633 } 1634 1635 void SdrOle2Obj::AbandonObject() 1636 { 1637 mpImpl->aPersistName.Erase(); 1638 mpImpl->mbLoadingOLEObjectFailed = false; 1639 SetObjRef(0); 1640 } 1641 1642 // ----------------------------------------------------------------------------- 1643 1644 String SdrOle2Obj::GetPersistName() const 1645 { 1646 return mpImpl->aPersistName; 1647 } 1648 1649 // ----------------------------------------------------------------------------- 1650 1651 void SdrOle2Obj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const 1652 { 1653 // #i118485# Allowing much more attributes for OLEs 1654 rInfo.bRotateFreeAllowed = true; 1655 rInfo.bRotate90Allowed = true; 1656 rInfo.bMirrorFreeAllowed = true; 1657 rInfo.bMirror45Allowed = true; 1658 rInfo.bMirror90Allowed = true; 1659 rInfo.bTransparenceAllowed = true; 1660 rInfo.bGradientAllowed = true; 1661 rInfo.bShearAllowed = true; 1662 rInfo.bEdgeRadiusAllowed = false; 1663 rInfo.bNoOrthoDesired = false; 1664 rInfo.bCanConvToPath = true; 1665 rInfo.bCanConvToPoly = true; 1666 rInfo.bCanConvToPathLineToArea = false; 1667 rInfo.bCanConvToPolyLineToArea = false; 1668 rInfo.bCanConvToContour = true; 1669 } 1670 1671 // ----------------------------------------------------------------------------- 1672 1673 sal_uInt16 SdrOle2Obj::GetObjIdentifier() const 1674 { 1675 return bFrame ? sal_uInt16(OBJ_FRAME) : sal_uInt16(OBJ_OLE2); 1676 } 1677 1678 // ----------------------------------------------------------------------------- 1679 1680 void SdrOle2Obj::TakeObjNameSingul(XubString& rName) const 1681 { 1682 rName = ImpGetResStr(bFrame ? STR_ObjNameSingulFrame : STR_ObjNameSingulOLE2); 1683 1684 const String aName(GetName()); 1685 1686 if( aName.Len() ) 1687 { 1688 rName.AppendAscii(" '"); 1689 rName += aName; 1690 rName += sal_Unicode('\''); 1691 } 1692 } 1693 1694 // ----------------------------------------------------------------------------- 1695 1696 void SdrOle2Obj::TakeObjNamePlural(XubString& rName) const 1697 { 1698 rName=ImpGetResStr(bFrame ? STR_ObjNamePluralFrame : STR_ObjNamePluralOLE2); 1699 } 1700 1701 // ----------------------------------------------------------------------------- 1702 1703 void SdrOle2Obj::operator=(const SdrObject& rObj) 1704 { 1705 //TODO/LATER: who takes over control of my old object?! 1706 if( &rObj != this ) 1707 { 1708 // #116235# 1709 // ImpAssign( rObj ); 1710 const SdrOle2Obj& rOle2Obj = static_cast< const SdrOle2Obj& >( rObj ); 1711 1712 uno::Reference < util::XCloseable > xClose( xObjRef.GetObject(), uno::UNO_QUERY ); 1713 1714 if( pModel && mpImpl->mbConnected ) 1715 Disconnect(); 1716 1717 SdrRectObj::operator=( rObj ); 1718 1719 // #108867# Manually copying bClosedObj attribute 1720 SetClosedObj( rObj.IsClosedObj() ); 1721 1722 mpImpl->aPersistName = rOle2Obj.mpImpl->aPersistName; 1723 aProgName = rOle2Obj.aProgName; 1724 bFrame = rOle2Obj.bFrame; 1725 1726 if( rOle2Obj.pGraphic ) 1727 { 1728 if( pGraphic ) 1729 { 1730 delete pGraphic; 1731 delete mpImpl->pGraphicObject; 1732 } 1733 1734 pGraphic = new Graphic( *rOle2Obj.pGraphic ); 1735 mpImpl->pGraphicObject = new GraphicObject( *pGraphic ); 1736 } 1737 1738 if( pModel && rObj.GetModel() && !IsEmptyPresObj() ) 1739 { 1740 ::comphelper::IEmbeddedHelper* pDestPers = pModel->GetPersist(); 1741 ::comphelper::IEmbeddedHelper* pSrcPers = rObj.GetModel()->GetPersist(); 1742 if( pDestPers && pSrcPers ) 1743 { 1744 DBG_ASSERT( !xObjRef.is(), "Object already existing!" ); 1745 comphelper::EmbeddedObjectContainer& rContainer = pSrcPers->getEmbeddedObjectContainer(); 1746 uno::Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( mpImpl->aPersistName ); 1747 if ( xObj.is() ) 1748 { 1749 ::rtl::OUString aTmp; 1750 xObjRef.Assign( pDestPers->getEmbeddedObjectContainer().CopyAndGetEmbeddedObject( rContainer, xObj, aTmp ), rOle2Obj.GetAspect() ); 1751 m_bTypeAsked = false; 1752 mpImpl->aPersistName = aTmp; 1753 CheckFileLink_Impl(); 1754 } 1755 1756 Connect(); 1757 1758 /* only needed for MSOLE-Objects, now handled inside implementation of Object 1759 if ( xObjRef.is() && rOle2Obj.xObjRef.is() && rOle2Obj.GetAspect() != embed::Aspects::MSOLE_ICON ) 1760 { 1761 try 1762 { 1763 awt::Size aVisSize = rOle2Obj.xObjRef->getVisualAreaSize( rOle2Obj.GetAspect() ); 1764 if( rOle2Obj.xObjRef->getMapUnit( rOle2Obj.GetAspect() ) == xObjRef->getMapUnit( GetAspect() ) ) 1765 xObjRef->setVisualAreaSize( GetAspect(), aVisSize ); 1766 } 1767 catch ( embed::WrongStateException& ) 1768 { 1769 // setting of VisArea not necessary for objects that don't cache it in loaded state 1770 } 1771 catch( embed::NoVisualAreaSizeException& ) 1772 { 1773 // objects my not have visual areas 1774 } 1775 catch( uno::Exception& e ) 1776 { 1777 (void)e; 1778 DBG_ERROR( "SdrOle2Obj::operator=(), unexpected exception caught!" ); 1779 } 1780 } */ 1781 } 1782 } 1783 } 1784 } 1785 1786 // ----------------------------------------------------------------------------- 1787 1788 void SdrOle2Obj::ImpSetVisAreaSize() 1789 { 1790 // #i118524# do not again set VisAreaSize when the call comes from OLE client (e.g. ObjectAreaChanged) 1791 if(mbSuppressSetVisAreaSize) 1792 return; 1793 1794 // currently there is no need to recalculate scaling for iconified objects 1795 // TODO/LATER: it might be needed in future when it is possible to change the icon 1796 if ( GetAspect() == embed::Aspects::MSOLE_ICON ) 1797 return; 1798 1799 // the object area of an embedded object was changed, e.g. by user interaction an a selected object 1800 GetObjRef(); 1801 if ( xObjRef.is() ) 1802 { 1803 OSL_ASSERT( pModel ); 1804 sal_Int64 nMiscStatus = xObjRef->getStatus( GetAspect() ); 1805 1806 // the client is required to get access to scaling 1807 SfxInPlaceClient* pClient = SfxInPlaceClient::GetClient( dynamic_cast<SfxObjectShell*>(pModel->GetPersist()), xObjRef.GetObject() ); 1808 sal_Bool bHasOwnClient = 1809 ( mpImpl->pLightClient 1810 && xObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->pLightClient ) ); 1811 1812 if ( pClient || bHasOwnClient ) 1813 { 1814 // TODO/LATER: IMHO we need to do similar things when object is UIActive or OutplaceActive?! (MBA) 1815 if ( ((nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) && 1816 svt::EmbeddedObjectRef::TryRunningState( xObjRef.GetObject() )) 1817 || xObjRef->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE 1818 ) 1819 { 1820 Fraction aScaleWidth; 1821 Fraction aScaleHeight; 1822 if ( pClient ) 1823 { 1824 aScaleWidth = pClient->GetScaleWidth(); 1825 aScaleHeight = pClient->GetScaleHeight(); 1826 } 1827 else 1828 { 1829 aScaleWidth = mpImpl->pLightClient->GetScaleWidth(); 1830 aScaleHeight = mpImpl->pLightClient->GetScaleHeight(); 1831 } 1832 1833 // The object wants to resize itself (f.e. Chart wants to recalculate the layout) 1834 // or object is inplace active and so has a window that must be resized also 1835 // In these cases the change in the object area size will be reflected in a change of the 1836 // objects' visual area. The scaling will not change, but it might exist already and must 1837 // be used in calculations 1838 MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObjRef->getMapUnit( GetAspect() ) ); 1839 Size aVisSize( (long)( Fraction( aRect.GetWidth() ) / aScaleWidth ), 1840 (long)( Fraction( aRect.GetHeight() ) / aScaleHeight ) ); 1841 1842 aVisSize = OutputDevice::LogicToLogic( aVisSize, pModel->GetScaleUnit(), aMapUnit); 1843 awt::Size aSz; 1844 aSz.Width = aVisSize.Width(); 1845 aSz.Height = aVisSize.Height(); 1846 xObjRef->setVisualAreaSize( GetAspect(), aSz ); 1847 1848 try 1849 { 1850 aSz = xObjRef->getVisualAreaSize( GetAspect() ); 1851 } 1852 catch( embed::NoVisualAreaSizeException& ) 1853 {} 1854 1855 Rectangle aAcceptedVisArea; 1856 aAcceptedVisArea.SetSize( Size( (long)( Fraction( long( aSz.Width ) ) * aScaleWidth ), 1857 (long)( Fraction( long( aSz.Height ) ) * aScaleHeight ) ) ); 1858 if (aVisSize != aAcceptedVisArea.GetSize()) 1859 { 1860 // server changed VisArea to its liking and the VisArea is different than the suggested one 1861 // store the new value as given by the object 1862 MapUnit aNewMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObjRef->getMapUnit( GetAspect() ) ); 1863 aRect.SetSize(OutputDevice::LogicToLogic( aAcceptedVisArea.GetSize(), aNewMapUnit, pModel->GetScaleUnit())); 1864 } 1865 1866 // make the new object area known to the client 1867 // compared to the "else" branch aRect might have been changed by the object and no additional scaling was applied 1868 // OJ: WHY this -> OSL_ASSERT( pClient ); 1869 if( pClient ) 1870 pClient->SetObjArea(aRect); 1871 1872 // we need a new replacement image as the object has resized itself 1873 1874 // #i79578# don't request a new replacement image for charts to often 1875 // a chart sends a modified call to the framework if it was changed 1876 // thus the replacement update is already handled there 1877 if( !IsChart() ) 1878 xObjRef.UpdateReplacement(); 1879 } 1880 else 1881 { 1882 // The object isn't active and does not want to resize itself so the changed object area size 1883 // will be reflected in a changed object scaling 1884 Fraction aScaleWidth; 1885 Fraction aScaleHeight; 1886 Size aObjAreaSize; 1887 if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) ) 1888 { 1889 if ( pClient ) 1890 { 1891 Rectangle aScaleRect(aRect.TopLeft(), aObjAreaSize); 1892 pClient->SetObjAreaAndScale( aScaleRect, aScaleWidth, aScaleHeight); 1893 } 1894 else 1895 { 1896 mpImpl->pLightClient->SetSizeScale( aScaleWidth, aScaleHeight ); 1897 } 1898 } 1899 } 1900 } 1901 else if( (nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) && 1902 svt::EmbeddedObjectRef::TryRunningState( xObjRef.GetObject() ) ) 1903 { 1904 // also handle not sfx based ole objects e.g. charts 1905 // #i83860# resizing charts in Impress distorts fonts 1906 uno::Reference< embed::XVisualObject > xVisualObject( this->getXModel(), uno::UNO_QUERY ); 1907 if( xVisualObject.is() ) 1908 { 1909 MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObjRef->getMapUnit( GetAspect() ) ); 1910 Point aTL( aRect.TopLeft() ); 1911 Point aBR( aRect.BottomRight() ); 1912 Point aTL2( OutputDevice::LogicToLogic( aTL, pModel->GetScaleUnit(), aMapUnit) ); 1913 Point aBR2( OutputDevice::LogicToLogic( aBR, pModel->GetScaleUnit(), aMapUnit) ); 1914 Rectangle aNewRect( aTL2, aBR2 ); 1915 xVisualObject->setVisualAreaSize( GetAspect(), awt::Size( aNewRect.GetWidth(), aNewRect.GetHeight() ) ); 1916 } 1917 } 1918 } 1919 } 1920 1921 // ----------------------------------------------------------------------------- 1922 1923 void SdrOle2Obj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) 1924 { 1925 if( pModel && !pModel->isLocked() ) 1926 { 1927 GetObjRef(); 1928 if ( xObjRef.is() && ( xObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) ) 1929 { 1930 // if the object needs recompose on resize 1931 // the client site should be created before the resize will take place 1932 // check whether there is no client site and create it if necessary 1933 AddOwnLightClient(); 1934 } 1935 } 1936 1937 SdrRectObj::NbcResize(rRef,xFact,yFact); 1938 1939 if( pModel && !pModel->isLocked() ) 1940 ImpSetVisAreaSize(); 1941 } 1942 1943 // ----------------------------------------------------------------------------- 1944 1945 void SdrOle2Obj::SetGeoData(const SdrObjGeoData& rGeo) 1946 { 1947 SdrRectObj::SetGeoData(rGeo); 1948 1949 if( pModel && !pModel->isLocked() ) 1950 ImpSetVisAreaSize(); 1951 } 1952 1953 // ----------------------------------------------------------------------------- 1954 1955 void SdrOle2Obj::NbcSetSnapRect(const Rectangle& rRect) 1956 { 1957 SdrRectObj::NbcSetSnapRect(rRect); 1958 1959 if( pModel && !pModel->isLocked() ) 1960 ImpSetVisAreaSize(); 1961 1962 if ( xObjRef.is() && IsChart() ) 1963 { 1964 //#i103460# charts do not necessarily have an own size within ODF files, 1965 //for this case they need to use the size settings from the surrounding frame, 1966 //which is made available with this method as there is no other way 1967 xObjRef.SetDefaultSizeForChart( Size( rRect.GetWidth(), rRect.GetHeight() ) ); 1968 } 1969 } 1970 1971 // ----------------------------------------------------------------------------- 1972 1973 void SdrOle2Obj::NbcSetLogicRect(const Rectangle& rRect) 1974 { 1975 SdrRectObj::NbcSetLogicRect(rRect); 1976 1977 if( pModel && !pModel->isLocked() ) 1978 ImpSetVisAreaSize(); 1979 } 1980 1981 Graphic* SdrOle2Obj::GetGraphic() const 1982 { 1983 if ( xObjRef.is() ) 1984 return xObjRef.GetGraphic(); 1985 return pGraphic; 1986 } 1987 1988 void SdrOle2Obj::GetNewReplacement() 1989 { 1990 if ( xObjRef.is() ) 1991 xObjRef.UpdateReplacement(); 1992 } 1993 1994 // ----------------------------------------------------------------------------- 1995 1996 Size SdrOle2Obj::GetOrigObjSize( MapMode* pTargetMapMode ) const 1997 { 1998 return xObjRef.GetSize( pTargetMapMode ); 1999 } 2000 2001 // ----------------------------------------------------------------------------- 2002 2003 void SdrOle2Obj::NbcMove(const Size& rSize) 2004 { 2005 SdrRectObj::NbcMove(rSize); 2006 2007 if( pModel && !pModel->isLocked() ) 2008 ImpSetVisAreaSize(); 2009 } 2010 2011 // ----------------------------------------------------------------------------- 2012 2013 sal_Bool SdrOle2Obj::CanUnloadRunningObj( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect ) 2014 { 2015 sal_Bool bResult = sal_False; 2016 2017 sal_Int32 nState = xObj->getCurrentState(); 2018 if ( nState == embed::EmbedStates::LOADED ) 2019 { 2020 // the object is already unloaded 2021 bResult = sal_True; 2022 } 2023 else 2024 { 2025 uno::Reference < util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); 2026 if ( !xModifiable.is() ) 2027 bResult = sal_True; 2028 else 2029 { 2030 sal_Int64 nMiscStatus = xObj->getStatus( nAspect ); 2031 2032 if ( embed::EmbedMisc::MS_EMBED_ALWAYSRUN != ( nMiscStatus & embed::EmbedMisc::MS_EMBED_ALWAYSRUN ) && 2033 embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY != ( nMiscStatus & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) && 2034 !( xModifiable.is() && xModifiable->isModified() ) && 2035 !( nState == embed::EmbedStates::INPLACE_ACTIVE || nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::ACTIVE ) ) 2036 { 2037 bResult = sal_True; 2038 } 2039 } 2040 } 2041 2042 return bResult; 2043 } 2044 2045 // ----------------------------------------------------------------------------- 2046 2047 sal_Bool SdrOle2Obj::Unload( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect ) 2048 { 2049 sal_Bool bResult = sal_False; 2050 2051 if ( CanUnloadRunningObj( xObj, nAspect ) ) 2052 { 2053 try 2054 { 2055 xObj->changeState( embed::EmbedStates::LOADED ); 2056 bResult = sal_True; 2057 } 2058 catch( ::com::sun::star::uno::Exception& e ) 2059 { 2060 (void)e; 2061 DBG_ERROR( 2062 (OString("SdrOle2Obj::Unload=(), " 2063 "exception caught: ") + 2064 rtl::OUStringToOString( 2065 comphelper::anyToString( cppu::getCaughtException() ), 2066 RTL_TEXTENCODING_UTF8 )).getStr() ); 2067 } 2068 } 2069 2070 return bResult; 2071 } 2072 2073 // ----------------------------------------------------------------------------- 2074 2075 sal_Bool SdrOle2Obj::Unload() 2076 { 2077 sal_Bool bUnloaded = sal_False; 2078 2079 if( xObjRef.is() ) 2080 { 2081 //TODO/LATER: no refcounting tricks anymore! 2082 //"customers" must register as state change listeners 2083 //Nicht notwendig im Doc DTor (MM) 2084 //sal_uIntPtr nRefCount = (*ppObjRef)->GetRefCount(); 2085 // prevent Unload if there are external references 2086 //if( nRefCount > 2 ) 2087 // return sal_False; 2088 //DBG_ASSERT( nRefCount == 2, "Wrong RefCount for unload" ); 2089 } 2090 else 2091 bUnloaded = sal_True; 2092 2093 if ( pModel && xObjRef.is() ) 2094 { 2095 bUnloaded = Unload( xObjRef.GetObject(), GetAspect() ); 2096 } 2097 2098 return bUnloaded; 2099 } 2100 2101 // ----------------------------------------------------------------------------- 2102 2103 void SdrOle2Obj::GetObjRef_Impl() 2104 { 2105 if ( !xObjRef.is() && mpImpl->aPersistName.Len() && pModel && pModel->GetPersist() ) 2106 { 2107 // #107645# 2108 // Only try loading if it did not went wrong up to now 2109 if(!mpImpl->mbLoadingOLEObjectFailed) 2110 { 2111 xObjRef.Assign( pModel->GetPersist()->getEmbeddedObjectContainer().GetEmbeddedObject( mpImpl->aPersistName ), GetAspect() ); 2112 m_bTypeAsked = false; 2113 CheckFileLink_Impl(); 2114 2115 // #107645# 2116 // If loading of OLE object failed, remember that to not invoke a endless 2117 // loop trying to load it again and again. 2118 if( xObjRef.is() ) 2119 { 2120 mpImpl->mbLoadingOLEObjectFailed = sal_True; 2121 } 2122 2123 // #108759# For math objects, set closed state to transparent 2124 SetClosedObj(!ImplIsMathObj( xObjRef.GetObject() )); 2125 } 2126 2127 if ( xObjRef.is() ) 2128 { 2129 if( !IsEmptyPresObj() ) 2130 { 2131 // #75637# remember modified status of model 2132 const sal_Bool bWasChanged(pModel ? pModel->IsChanged() : sal_False); 2133 2134 // perhaps preview not valid anymore 2135 // #75637# This line changes the modified state of the model 2136 SetGraphic_Impl( NULL ); 2137 2138 // #75637# if status was not set before, force it back 2139 // to not set, so that SetGraphic(0L) above does not 2140 // set the modified state of the model. 2141 if(!bWasChanged && pModel && pModel->IsChanged()) 2142 { 2143 pModel->SetChanged( sal_False ); 2144 } 2145 } 2146 2147 sal_Int64 nMiscStatus = xObjRef->getStatus( GetAspect() ); 2148 (void)nMiscStatus; 2149 // TODO/LATER: wait until ResizeOnPrinterChange is defined 2150 //if ( nMiscStatus & SVOBJ_MISCSTATUS_RESIZEONPRINTERCHANGE ) 2151 { 2152 if (pModel && pModel->GetRefDevice() && 2153 pModel->GetRefDevice()->GetOutDevType() == OUTDEV_PRINTER) 2154 { 2155 if(!bInDestruction) 2156 { 2157 // TODO/LATER: printerchange notification 2158 /* 2159 // prevent SetModified (don't want no update here) 2160 sal_Bool bWasEnabled = (*ppObjRef)->IsEnableSetModified(); 2161 if ( bWasEnabled ) 2162 (*ppObjRef)->EnableSetModified( sal_False ); 2163 2164 // Kein RefDevice oder RefDevice kein Printer 2165 Printer* pPrinter = (Printer*) pModel->GetRefDevice(); 2166 (*ppObjRef)->OnDocumentPrinterChanged( pPrinter ); 2167 2168 // reset state 2169 (*ppObjRef)->EnableSetModified( bWasEnabled );*/ 2170 } 2171 } 2172 } 2173 } 2174 2175 if ( xObjRef.is() ) 2176 Connect(); 2177 } 2178 2179 if ( mpImpl->mbConnected ) 2180 // move object to first position in cache 2181 GetSdrGlobalData().GetOLEObjCache().InsertObj(this); 2182 } 2183 2184 uno::Reference < embed::XEmbeddedObject > SdrOle2Obj::GetObjRef() const 2185 { 2186 const_cast<SdrOle2Obj*>(this)->GetObjRef_Impl(); 2187 return xObjRef.GetObject(); 2188 } 2189 2190 uno::Reference < embed::XEmbeddedObject > SdrOle2Obj::GetObjRef_NoInit() const 2191 { 2192 return xObjRef.GetObject(); 2193 } 2194 2195 // ----------------------------------------------------------------------------- 2196 2197 uno::Reference< frame::XModel > SdrOle2Obj::getXModel() const 2198 { 2199 GetObjRef(); 2200 if ( svt::EmbeddedObjectRef::TryRunningState(xObjRef.GetObject()) ) 2201 return uno::Reference< frame::XModel >( xObjRef->getComponent(), uno::UNO_QUERY ); 2202 else 2203 return uno::Reference< frame::XModel >(); 2204 } 2205 2206 // ----------------------------------------------------------------------------- 2207 2208 // #109985# 2209 sal_Bool SdrOle2Obj::IsChart() const 2210 { 2211 if ( !m_bTypeAsked ) 2212 { 2213 m_bChart = ChartHelper::IsChart(xObjRef); 2214 m_bTypeAsked = true; 2215 } 2216 return m_bChart; 2217 } 2218 2219 // ----------------------------------------------------------------------------- 2220 void SdrOle2Obj::SetGraphicToObj( const Graphic& aGraphic, const ::rtl::OUString& aMediaType ) 2221 { 2222 xObjRef.SetGraphic( aGraphic, aMediaType ); 2223 } 2224 2225 // ----------------------------------------------------------------------------- 2226 void SdrOle2Obj::SetGraphicToObj( const uno::Reference< io::XInputStream >& xGrStream, const ::rtl::OUString& aMediaType ) 2227 { 2228 xObjRef.SetGraphicStream( xGrStream, aMediaType ); 2229 } 2230 2231 // ----------------------------------------------------------------------------- 2232 sal_Bool SdrOle2Obj::IsCalc() const 2233 { 2234 if ( !xObjRef.is() ) 2235 return false; 2236 2237 SvGlobalName aObjClsId( xObjRef->getClassID() ); 2238 if( SvGlobalName(SO3_SC_CLASSID_30) == aObjClsId 2239 || SvGlobalName(SO3_SC_CLASSID_40) == aObjClsId 2240 || SvGlobalName(SO3_SC_CLASSID_50) == aObjClsId 2241 || SvGlobalName(SO3_SC_CLASSID_60) == aObjClsId 2242 || SvGlobalName(SO3_SC_OLE_EMBED_CLASSID_60) == aObjClsId 2243 || SvGlobalName(SO3_SC_OLE_EMBED_CLASSID_8) == aObjClsId 2244 || SvGlobalName(SO3_SC_CLASSID) == aObjClsId ) 2245 { 2246 return sal_True; 2247 } 2248 2249 return sal_False; 2250 } 2251 2252 // ----------------------------------------------------------------------------- 2253 uno::Reference< frame::XModel > SdrOle2Obj::GetParentXModel() const 2254 { 2255 uno::Reference< frame::XModel > xDoc; 2256 if ( pModel ) 2257 xDoc.set( pModel->getUnoModel(),uno::UNO_QUERY); 2258 return xDoc; 2259 } 2260 2261 // ----------------------------------------------------------------------------- 2262 sal_Bool SdrOle2Obj::CalculateNewScaling( Fraction& aScaleWidth, Fraction& aScaleHeight, Size& aObjAreaSize ) 2263 { 2264 // TODO/LEAN: to avoid rounding errors scaling always uses the VisArea. 2265 // If we don't cache it for own objects also we must load the object here 2266 if ( !xObjRef.is() || !pModel ) 2267 return sal_False; 2268 2269 MapMode aMapMode( pModel->GetScaleUnit() ); 2270 aObjAreaSize = xObjRef.GetSize( &aMapMode ); 2271 2272 Size aSize = aRect.GetSize(); 2273 aScaleWidth = Fraction(aSize.Width(), aObjAreaSize.Width() ); 2274 aScaleHeight = Fraction(aSize.Height(), aObjAreaSize.Height() ); 2275 2276 // reduce to 10 binary digits 2277 aScaleHeight.ReduceInaccurate(10); 2278 aScaleWidth.ReduceInaccurate(10); 2279 2280 return sal_True; 2281 } 2282 2283 // ----------------------------------------------------------------------------- 2284 sal_Bool SdrOle2Obj::AddOwnLightClient() 2285 { 2286 // The Own Light Client must be registered in object only using this method! 2287 if ( !SfxInPlaceClient::GetClient( dynamic_cast<SfxObjectShell*>(pModel->GetPersist()), xObjRef.GetObject() ) 2288 && !( mpImpl->pLightClient && xObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->pLightClient ) ) ) 2289 { 2290 Connect(); 2291 2292 if ( xObjRef.is() && mpImpl->pLightClient ) 2293 { 2294 Fraction aScaleWidth; 2295 Fraction aScaleHeight; 2296 Size aObjAreaSize; 2297 if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) ) 2298 { 2299 mpImpl->pLightClient->SetSizeScale( aScaleWidth, aScaleHeight ); 2300 try { 2301 xObjRef->setClientSite( mpImpl->pLightClient ); 2302 return sal_True; 2303 } catch( uno::Exception& ) 2304 {} 2305 } 2306 2307 } 2308 2309 return sal_False; 2310 } 2311 2312 return sal_True; 2313 } 2314 2315 ////////////////////////////////////////////////////////////////////////////// 2316 2317 Bitmap SdrOle2Obj::GetEmptyOLEReplacementBitmap() 2318 { 2319 return Bitmap(ResId(BMP_SVXOLEOBJ, *ImpGetResMgr())); 2320 } 2321 2322 ////////////////////////////////////////////////////////////////////////////// 2323 2324 void SdrOle2Obj::SetWindow(const com::sun::star::uno::Reference < com::sun::star::awt::XWindow >& _xWindow) 2325 { 2326 if ( xObjRef.is() && mpImpl->pLightClient ) 2327 { 2328 mpImpl->pLightClient->setWindow(_xWindow); 2329 } 2330 } 2331 2332 /* vim: set noet sw=4 ts=4: */ 2333