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 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svtools.hxx" 26 27 #include <svtools/embedhlp.hxx> 28 #include <svtools/filter.hxx> 29 #include <svtools/svtools.hrc> 30 #include <svtools/svtdata.hxx> 31 32 #include <comphelper/embeddedobjectcontainer.hxx> 33 #include <comphelper/seqstream.hxx> 34 #include <toolkit/helper/vclunohelper.hxx> 35 #include <unotools/ucbstreamhelper.hxx> 36 #include <unotools/streamwrap.hxx> 37 #include <com/sun/star/chart2/XChartDocument.hpp> 38 #include <com/sun/star/chart2/XCoordinateSystem.hpp> 39 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> 40 #include <com/sun/star/chart2/XDiagram.hpp> 41 #include <com/sun/star/chart2/XChartTypeContainer.hpp> 42 #include <com/sun/star/chart2/XChartType.hpp> 43 #include <tools/globname.hxx> 44 #include <sot/clsids.hxx> 45 #include <com/sun/star/util/XModifyListener.hpp> 46 #ifndef _COM_SUN_STAR_UTIL_XMODIFYiBLE_HPP_ 47 #include <com/sun/star/util/XModifiable.hpp> 48 #endif 49 #include <com/sun/star/embed/EmbedStates.hpp> 50 #include <com/sun/star/embed/EmbedMisc.hpp> 51 #include <com/sun/star/embed/XStateChangeListener.hpp> 52 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 53 #include <com/sun/star/util/XModifiable.hpp> 54 #include <com/sun/star/datatransfer/XTransferable.hpp> 55 #include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp> 56 #include <cppuhelper/implbase4.hxx> 57 #include "vcl/svapp.hxx" 58 #include <rtl/logfile.hxx> 59 #include <vos/mutex.hxx> 60 61 using namespace com::sun::star; 62 63 namespace svt 64 { 65 66 class EmbedEventListener_Impl : public ::cppu::WeakImplHelper4 < embed::XStateChangeListener, 67 document::XEventListener, 68 util::XModifyListener, 69 util::XCloseListener > 70 { 71 public: 72 EmbeddedObjectRef* pObject; 73 sal_Int32 nState; 74 75 EmbedEventListener_Impl( EmbeddedObjectRef* p ) : 76 pObject(p) 77 , nState(-1) 78 {} 79 80 static EmbedEventListener_Impl* Create( EmbeddedObjectRef* ); 81 82 virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) 83 throw (embed::WrongStateException, uno::RuntimeException); 84 virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) 85 throw (uno::RuntimeException); 86 virtual void SAL_CALL queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership ) 87 throw (util::CloseVetoException, uno::RuntimeException); 88 virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException); 89 virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ); 90 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ); 91 virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); 92 }; 93 94 EmbedEventListener_Impl* EmbedEventListener_Impl::Create( EmbeddedObjectRef* p ) 95 { 96 EmbedEventListener_Impl* xRet = new EmbedEventListener_Impl( p ); 97 xRet->acquire(); 98 99 if ( p->GetObject().is() ) 100 { 101 p->GetObject()->addStateChangeListener( xRet ); 102 103 uno::Reference < util::XCloseable > xClose( p->GetObject(), uno::UNO_QUERY ); 104 DBG_ASSERT( xClose.is(), "Object does not support XCloseable!" ); 105 if ( xClose.is() ) 106 xClose->addCloseListener( xRet ); 107 108 uno::Reference < document::XEventBroadcaster > xBrd( p->GetObject(), uno::UNO_QUERY ); 109 if ( xBrd.is() ) 110 xBrd->addEventListener( xRet ); 111 112 xRet->nState = p->GetObject()->getCurrentState(); 113 if ( xRet->nState == embed::EmbedStates::RUNNING ) 114 { 115 uno::Reference < util::XModifiable > xMod( p->GetObject()->getComponent(), uno::UNO_QUERY ); 116 if ( xMod.is() ) 117 // listen for changes in running state (update replacements in case of changes) 118 xMod->addModifyListener( xRet ); 119 } 120 } 121 122 return xRet; 123 } 124 125 void SAL_CALL EmbedEventListener_Impl::changingState( const lang::EventObject&, 126 ::sal_Int32, 127 ::sal_Int32 ) 128 throw ( embed::WrongStateException, 129 uno::RuntimeException ) 130 { 131 } 132 133 void SAL_CALL EmbedEventListener_Impl::stateChanged( const lang::EventObject&, 134 ::sal_Int32 nOldState, 135 ::sal_Int32 nNewState ) 136 throw ( uno::RuntimeException ) 137 { 138 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 139 nState = nNewState; 140 if ( !pObject ) 141 return; 142 143 uno::Reference < util::XModifiable > xMod( pObject->GetObject()->getComponent(), uno::UNO_QUERY ); 144 if ( nNewState == embed::EmbedStates::RUNNING ) 145 { 146 // TODO/LATER: container must be set before! 147 // When is this event created? Who sets the new container when it changed? 148 if( ( pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) && nOldState != embed::EmbedStates::LOADED && !pObject->IsChart() ) 149 // get new replacement after deactivation 150 pObject->UpdateReplacement(); 151 152 if( pObject->IsChart() && nOldState == embed::EmbedStates::UI_ACTIVE ) 153 { 154 //create a new metafile replacement when leaving the edit mode 155 //for buggy documents where the old image looks different from the correct one 156 if( xMod.is() && !xMod->isModified() )//in case of modification a new replacement will be requested anyhow 157 pObject->UpdateReplacementOnDemand(); 158 } 159 160 if ( xMod.is() && nOldState == embed::EmbedStates::LOADED ) 161 // listen for changes (update replacements in case of changes) 162 xMod->addModifyListener( this ); 163 } 164 else if ( nNewState == embed::EmbedStates::LOADED ) 165 { 166 // in loaded state we can't listen 167 if ( xMod.is() ) 168 xMod->removeModifyListener( this ); 169 } 170 } 171 172 void SAL_CALL EmbedEventListener_Impl::modified( const lang::EventObject& ) throw (uno::RuntimeException) 173 { 174 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 175 if ( pObject && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON ) 176 { 177 if ( nState == embed::EmbedStates::RUNNING ) 178 { 179 // updates only necessary in non-active states 180 if( pObject->IsChart() ) 181 pObject->UpdateReplacementOnDemand(); 182 else 183 pObject->UpdateReplacement(); 184 } 185 else if ( nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::INPLACE_ACTIVE ) 186 { 187 // in case the object is inplace or UI active the replacement image should be updated on demand 188 pObject->UpdateReplacementOnDemand(); 189 } 190 } 191 } 192 193 void SAL_CALL EmbedEventListener_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ) 194 { 195 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 196 197 #if 0 198 if ( pObject && aEvent.EventName.equalsAscii("OnSaveDone") || aEvent.EventName.equalsAscii("OnSaveAsDone") ) 199 { 200 // TODO/LATER: container must be set before! 201 // When is this event created? Who sets the new container when it changed? 202 pObject->UpdateReplacement(); 203 } 204 else 205 #endif 206 if ( pObject && aEvent.EventName.equalsAscii("OnVisAreaChanged") && pObject->GetViewAspect() != embed::Aspects::MSOLE_ICON && !pObject->IsChart() ) 207 { 208 pObject->UpdateReplacement(); 209 } 210 } 211 212 void SAL_CALL EmbedEventListener_Impl::queryClosing( const lang::EventObject& Source, ::sal_Bool ) 213 throw ( util::CloseVetoException, uno::RuntimeException) 214 { 215 // An embedded object can be shared between several objects (f.e. for undo purposes) 216 // the object will not be closed before the last "customer" is destroyed 217 // Now the EmbeddedObjectRef helper class works like a "lock" on the object 218 if ( pObject && pObject->IsLocked() && Source.Source == pObject->GetObject() ) 219 throw util::CloseVetoException(); 220 } 221 222 void SAL_CALL EmbedEventListener_Impl::notifyClosing( const lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException) 223 { 224 if ( pObject && Source.Source == pObject->GetObject() ) 225 { 226 pObject->Clear(); 227 pObject = 0; 228 } 229 } 230 231 void SAL_CALL EmbedEventListener_Impl::disposing( const lang::EventObject& aEvent ) throw( uno::RuntimeException ) 232 { 233 if ( pObject && aEvent.Source == pObject->GetObject() ) 234 { 235 pObject->Clear(); 236 pObject = 0; 237 } 238 } 239 240 struct EmbeddedObjectRef_Impl 241 { 242 EmbedEventListener_Impl* xListener; 243 ::rtl::OUString aPersistName; 244 ::rtl::OUString aMediaType; 245 comphelper::EmbeddedObjectContainer* pContainer; 246 Graphic* pGraphic; 247 Graphic* pHCGraphic; 248 sal_Int64 nViewAspect; 249 sal_Bool bIsLocked; 250 sal_Bool bNeedUpdate; 251 252 // #i104867# 253 sal_uInt32 mnGraphicVersion; 254 awt::Size aDefaultSizeForChart_In_100TH_MM;//#i103460# charts do not necessaryly have an own size within ODF files, in this case they need to use the size settings from the surrounding frame, which is made available with this member 255 }; 256 257 void EmbeddedObjectRef::Construct_Impl() 258 { 259 mpImp = new EmbeddedObjectRef_Impl; 260 mpImp->pContainer = 0; 261 mpImp->pGraphic = 0; 262 mpImp->pHCGraphic = 0; 263 mpImp->nViewAspect = embed::Aspects::MSOLE_CONTENT; 264 mpImp->bIsLocked = sal_False; 265 mpImp->bNeedUpdate = sal_False; 266 mpImp->mnGraphicVersion = 0; 267 mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size(8000,7000); 268 } 269 270 EmbeddedObjectRef::EmbeddedObjectRef() 271 { 272 Construct_Impl(); 273 } 274 275 EmbeddedObjectRef::EmbeddedObjectRef( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect ) 276 { 277 Construct_Impl(); 278 mpImp->nViewAspect = nAspect; 279 mxObj = xObj; 280 mpImp->xListener = EmbedEventListener_Impl::Create( this ); 281 } 282 283 EmbeddedObjectRef::EmbeddedObjectRef( const EmbeddedObjectRef& rObj ) 284 { 285 mpImp = new EmbeddedObjectRef_Impl; 286 mpImp->pContainer = rObj.mpImp->pContainer; 287 mpImp->nViewAspect = rObj.mpImp->nViewAspect; 288 mpImp->bIsLocked = rObj.mpImp->bIsLocked; 289 mxObj = rObj.mxObj; 290 mpImp->xListener = EmbedEventListener_Impl::Create( this ); 291 mpImp->aPersistName = rObj.mpImp->aPersistName; 292 mpImp->aMediaType = rObj.mpImp->aMediaType; 293 mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate; 294 mpImp->aDefaultSizeForChart_In_100TH_MM = rObj.mpImp->aDefaultSizeForChart_In_100TH_MM; 295 296 if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate ) 297 mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic ); 298 else 299 mpImp->pGraphic = 0; 300 301 mpImp->pHCGraphic = 0; 302 mpImp->mnGraphicVersion = 0; 303 } 304 305 EmbeddedObjectRef::~EmbeddedObjectRef() 306 { 307 delete mpImp->pGraphic; 308 if ( mpImp->pHCGraphic ) 309 DELETEZ( mpImp->pHCGraphic ); 310 Clear(); 311 delete mpImp; 312 } 313 /* 314 EmbeddedObjectRef& EmbeddedObjectRef::operator = ( const EmbeddedObjectRef& rObj ) 315 { 316 DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" ); 317 318 delete mpImp->pGraphic; 319 if ( mpImp->pHCGraphic ) DELETEZ( mpImp->pHCGraphic ); 320 Clear(); 321 322 mpImp->nViewAspect = rObj.mpImp->nViewAspect; 323 mpImp->bIsLocked = rObj.mpImp->bIsLocked; 324 mxObj = rObj.mxObj; 325 mpImp->xListener = EmbedEventListener_Impl::Create( this ); 326 mpImp->pContainer = rObj.mpImp->pContainer; 327 mpImp->aPersistName = rObj.mpImp->aPersistName; 328 mpImp->aMediaType = rObj.mpImp->aMediaType; 329 mpImp->bNeedUpdate = rObj.mpImp->bNeedUpdate; 330 331 if ( rObj.mpImp->pGraphic && !rObj.mpImp->bNeedUpdate ) 332 mpImp->pGraphic = new Graphic( *rObj.mpImp->pGraphic ); 333 else 334 mpImp->pGraphic = 0; 335 return *this; 336 } 337 */ 338 void EmbeddedObjectRef::Assign( const NS_UNO::Reference < NS_EMBED::XEmbeddedObject >& xObj, sal_Int64 nAspect ) 339 { 340 DBG_ASSERT( !mxObj.is(), "Never assign an already assigned object!" ); 341 342 Clear(); 343 mpImp->nViewAspect = nAspect; 344 mxObj = xObj; 345 mpImp->xListener = EmbedEventListener_Impl::Create( this ); 346 347 //#i103460# 348 if ( IsChart() ) 349 { 350 ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( xObj, uno::UNO_QUERY ); 351 DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" ); 352 if( xSizeTransmitter.is() ) 353 xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM ); 354 } 355 } 356 357 void EmbeddedObjectRef::Clear() 358 { 359 if ( mxObj.is() && mpImp->xListener ) 360 { 361 mxObj->removeStateChangeListener( mpImp->xListener ); 362 363 uno::Reference < util::XCloseable > xClose( mxObj, uno::UNO_QUERY ); 364 if ( xClose.is() ) 365 xClose->removeCloseListener( mpImp->xListener ); 366 367 uno::Reference < document::XEventBroadcaster > xBrd( mxObj, uno::UNO_QUERY ); 368 if ( xBrd.is() ) 369 xBrd->removeEventListener( mpImp->xListener ); 370 371 if ( mpImp->bIsLocked ) 372 { 373 if ( xClose.is() ) 374 { 375 try 376 { 377 mxObj->changeState( embed::EmbedStates::LOADED ); 378 xClose->close( sal_True ); 379 } 380 catch ( util::CloseVetoException& ) 381 { 382 // there's still someone who needs the object! 383 } 384 catch ( uno::Exception& ) 385 { 386 OSL_ENSURE( sal_False, "Error on switching of the object to loaded state and closing!\n" ); 387 } 388 } 389 } 390 391 if ( mpImp->xListener ) 392 { 393 mpImp->xListener->pObject = 0; 394 mpImp->xListener->release(); 395 mpImp->xListener = 0; 396 } 397 398 mxObj = 0; 399 mpImp->bNeedUpdate = sal_False; 400 } 401 402 mpImp->pContainer = 0; 403 mpImp->bIsLocked = sal_False; 404 mpImp->bNeedUpdate = sal_False; 405 } 406 407 void EmbeddedObjectRef::AssignToContainer( comphelper::EmbeddedObjectContainer* pContainer, const ::rtl::OUString& rPersistName ) 408 { 409 mpImp->pContainer = pContainer; 410 mpImp->aPersistName = rPersistName; 411 412 if ( mpImp->pGraphic && !mpImp->bNeedUpdate && pContainer ) 413 SetGraphicToContainer( *mpImp->pGraphic, *pContainer, mpImp->aPersistName, ::rtl::OUString() ); 414 } 415 416 comphelper::EmbeddedObjectContainer* EmbeddedObjectRef::GetContainer() const 417 { 418 return mpImp->pContainer; 419 } 420 421 ::rtl::OUString EmbeddedObjectRef::GetPersistName() const 422 { 423 return mpImp->aPersistName; 424 } 425 426 MapUnit EmbeddedObjectRef::GetMapUnit() const 427 { 428 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT ) 429 return VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) ); 430 else 431 // TODO/LATER: currently only CONTENT aspect requires communication with the object 432 return MAP_100TH_MM; 433 } 434 435 sal_Int64 EmbeddedObjectRef::GetViewAspect() const 436 { 437 return mpImp->nViewAspect; 438 } 439 440 void EmbeddedObjectRef::SetViewAspect( sal_Int64 nAspect ) 441 { 442 mpImp->nViewAspect = nAspect; 443 } 444 445 void EmbeddedObjectRef::Lock( sal_Bool bLock ) 446 { 447 mpImp->bIsLocked = bLock; 448 } 449 450 sal_Bool EmbeddedObjectRef::IsLocked() const 451 { 452 return mpImp->bIsLocked; 453 } 454 455 void EmbeddedObjectRef::GetReplacement( sal_Bool bUpdate ) 456 { 457 if ( bUpdate ) 458 { 459 DELETEZ( mpImp->pGraphic ); 460 mpImp->aMediaType = ::rtl::OUString(); 461 mpImp->pGraphic = new Graphic; 462 if ( mpImp->pHCGraphic ) 463 DELETEZ( mpImp->pHCGraphic ); 464 mpImp->mnGraphicVersion++; 465 } 466 else if ( !mpImp->pGraphic ) 467 { 468 mpImp->pGraphic = new Graphic; 469 mpImp->mnGraphicVersion++; 470 } 471 else 472 { 473 DBG_ERROR("No update, but replacement exists already!"); 474 return; 475 } 476 477 SvStream* pGraphicStream = GetGraphicStream( bUpdate ); 478 if ( pGraphicStream ) 479 { 480 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); 481 if( mpImp->pGraphic ) 482 pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ); 483 mpImp->mnGraphicVersion++; 484 delete pGraphicStream; 485 } 486 } 487 488 Graphic* EmbeddedObjectRef::GetGraphic( ::rtl::OUString* pMediaType ) const 489 { 490 try 491 { 492 if ( mpImp->bNeedUpdate ) 493 // bNeedUpdate will be set to false while retrieving new replacement 494 const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_True ); 495 else if ( !mpImp->pGraphic ) 496 const_cast < EmbeddedObjectRef* >(this)->GetReplacement( sal_False ); 497 } 498 catch( uno::Exception& ) 499 { 500 OSL_ENSURE( sal_False, "Something went wrong on getting the graphic!" ); 501 } 502 503 if ( mpImp->pGraphic && pMediaType ) 504 *pMediaType = mpImp->aMediaType; 505 return mpImp->pGraphic; 506 } 507 508 Size EmbeddedObjectRef::GetSize( MapMode* pTargetMapMode ) const 509 { 510 MapMode aSourceMapMode( MAP_100TH_MM ); 511 Size aResult; 512 513 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_ICON ) 514 { 515 Graphic* pGraphic = GetGraphic(); 516 if ( pGraphic ) 517 { 518 aSourceMapMode = pGraphic->GetPrefMapMode(); 519 aResult = pGraphic->GetPrefSize(); 520 } 521 else 522 aResult = Size( 2500, 2500 ); 523 } 524 else 525 { 526 awt::Size aSize; 527 528 if ( mxObj.is() ) 529 { 530 try 531 { 532 aSize = mxObj->getVisualAreaSize( mpImp->nViewAspect ); 533 } 534 catch( embed::NoVisualAreaSizeException& ) 535 { 536 } 537 catch( uno::Exception& ) 538 { 539 OSL_ENSURE( sal_False, "Something went wrong on getting of the size of the object!" ); 540 } 541 542 try 543 { 544 aSourceMapMode = VCLUnoHelper::UnoEmbed2VCLMapUnit( mxObj->getMapUnit( mpImp->nViewAspect ) ); 545 } 546 catch( uno::Exception ) 547 { 548 OSL_ENSURE( sal_False, "Can not get the map mode!" ); 549 } 550 } 551 552 if ( !aSize.Height && !aSize.Width ) 553 { 554 aSize.Width = 5000; 555 aSize.Height = 5000; 556 } 557 558 aResult = Size( aSize.Width, aSize.Height ); 559 } 560 561 if ( pTargetMapMode ) 562 aResult = OutputDevice::LogicToLogic( aResult, aSourceMapMode, *pTargetMapMode ); 563 564 return aResult; 565 } 566 567 Graphic* EmbeddedObjectRef::GetHCGraphic() const 568 { 569 if ( !mpImp->pHCGraphic ) 570 { 571 uno::Reference< io::XInputStream > xInStream; 572 try 573 { 574 // if the object needs size on load, that means that it is not our object 575 // currently the HC mode is supported only for OOo own objects so the following 576 // check is used as an optimization 577 // TODO/LATER: shouldn't there be a special status flag to detect alien implementation? 578 if ( mpImp->nViewAspect == embed::Aspects::MSOLE_CONTENT 579 && mxObj.is() && !( mxObj->getStatus( mpImp->nViewAspect ) & embed::EmbedMisc::EMBED_NEEDSSIZEONLOAD ) ) 580 { 581 // TODO/LATER: optimization, it makes no sence to do it for OLE objects 582 if ( mxObj->getCurrentState() == embed::EmbedStates::LOADED ) 583 mxObj->changeState( embed::EmbedStates::RUNNING ); 584 585 // TODO: return for the aspect of the document 586 embed::VisualRepresentation aVisualRepresentation; 587 uno::Reference< datatransfer::XTransferable > xTransferable( mxObj->getComponent(), uno::UNO_QUERY ); 588 if ( !xTransferable.is() ) 589 throw uno::RuntimeException(); 590 591 datatransfer::DataFlavor aDataFlavor( 592 ::rtl::OUString::createFromAscii( 593 "application/x-openoffice-highcontrast-gdimetafile;windows_formatname=\"GDIMetaFile\"" ), 594 ::rtl::OUString::createFromAscii( "GDIMetaFile" ), 595 ::getCppuType( (const uno::Sequence< sal_Int8 >*) NULL ) ); 596 597 uno::Sequence < sal_Int8 > aSeq; 598 if ( ( xTransferable->getTransferData( aDataFlavor ) >>= aSeq ) && aSeq.getLength() ) 599 xInStream = new ::comphelper::SequenceInputStream( aSeq ); 600 } 601 } 602 catch ( uno::Exception& ) 603 { 604 OSL_ENSURE( sal_False, "Something went wrong on getting the high contrast graphic!" ); 605 } 606 607 if ( xInStream.is() ) 608 { 609 SvStream* pStream = NULL; 610 pStream = ::utl::UcbStreamHelper::CreateStream( xInStream ); 611 if ( pStream ) 612 { 613 if ( !pStream->GetError() ) 614 { 615 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); 616 Graphic* pGraphic = new Graphic(); 617 if ( pGF->ImportGraphic( *pGraphic, String(), *pStream, GRFILTER_FORMAT_DONTKNOW ) == 0 ) 618 mpImp->pHCGraphic = pGraphic; 619 else 620 delete pGraphic; 621 mpImp->mnGraphicVersion++; 622 } 623 624 delete pStream; 625 } 626 } 627 } 628 629 return mpImp->pHCGraphic; 630 } 631 632 void EmbeddedObjectRef::SetGraphicStream( const uno::Reference< io::XInputStream >& xInGrStream, 633 const ::rtl::OUString& rMediaType ) 634 { 635 if ( mpImp->pGraphic ) 636 delete mpImp->pGraphic; 637 mpImp->pGraphic = new Graphic(); 638 mpImp->aMediaType = rMediaType; 639 if ( mpImp->pHCGraphic ) 640 DELETEZ( mpImp->pHCGraphic ); 641 mpImp->mnGraphicVersion++; 642 643 SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( xInGrStream ); 644 645 if ( pGraphicStream ) 646 { 647 GraphicFilter* pGF = GraphicFilter::GetGraphicFilter(); 648 pGF->ImportGraphic( *mpImp->pGraphic, String(), *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ); 649 mpImp->mnGraphicVersion++; 650 651 if ( mpImp->pContainer ) 652 { 653 pGraphicStream->Seek( 0 ); 654 uno::Reference< io::XInputStream > xInSeekGrStream = new ::utl::OSeekableInputStreamWrapper( pGraphicStream ); 655 656 mpImp->pContainer->InsertGraphicStream( xInSeekGrStream, mpImp->aPersistName, rMediaType ); 657 } 658 659 delete pGraphicStream; 660 } 661 662 mpImp->bNeedUpdate = sal_False; 663 664 } 665 666 void EmbeddedObjectRef::SetGraphic( const Graphic& rGraphic, const ::rtl::OUString& rMediaType ) 667 { 668 if ( mpImp->pGraphic ) 669 delete mpImp->pGraphic; 670 mpImp->pGraphic = new Graphic( rGraphic ); 671 mpImp->aMediaType = rMediaType; 672 if ( mpImp->pHCGraphic ) 673 DELETEZ( mpImp->pHCGraphic ); 674 mpImp->mnGraphicVersion++; 675 676 if ( mpImp->pContainer ) 677 SetGraphicToContainer( rGraphic, *mpImp->pContainer, mpImp->aPersistName, rMediaType ); 678 679 mpImp->bNeedUpdate = sal_False; 680 } 681 682 SvStream* EmbeddedObjectRef::GetGraphicStream( sal_Bool bUpdate ) const 683 { 684 RTL_LOGFILE_CONTEXT( aLog, "svtools (mv76033) svt::EmbeddedObjectRef::GetGraphicStream" ); 685 DBG_ASSERT( bUpdate || mpImp->pContainer, "Can't retrieve current graphic!" ); 686 uno::Reference < io::XInputStream > xStream; 687 if ( mpImp->pContainer && !bUpdate ) 688 { 689 RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from container" ); 690 // try to get graphic stream from container storage 691 xStream = mpImp->pContainer->GetGraphicStream( mxObj, &mpImp->aMediaType ); 692 if ( xStream.is() ) 693 { 694 const sal_Int32 nConstBufferSize = 32000; 695 SvStream *pStream = new SvMemoryStream( 32000, 32000 ); 696 sal_Int32 nRead=0; 697 uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize ); 698 do 699 { 700 nRead = xStream->readBytes ( aSequence, nConstBufferSize ); 701 pStream->Write( aSequence.getConstArray(), nRead ); 702 } 703 while ( nRead == nConstBufferSize ); 704 pStream->Seek(0); 705 return pStream; 706 } 707 } 708 709 if ( !xStream.is() ) 710 { 711 RTL_LOGFILE_CONTEXT_TRACE( aLog, "getting stream from object" ); 712 // update wanted or no stream in container storage available 713 xStream = GetGraphicReplacementStream( mpImp->nViewAspect, mxObj, &mpImp->aMediaType ); 714 715 if ( xStream.is() ) 716 { 717 if ( mpImp->pContainer ) 718 mpImp->pContainer->InsertGraphicStream( xStream, mpImp->aPersistName, mpImp->aMediaType ); 719 720 SvStream* pResult = ::utl::UcbStreamHelper::CreateStream( xStream ); 721 if ( pResult && bUpdate ) 722 mpImp->bNeedUpdate = sal_False; 723 724 return pResult; 725 } 726 } 727 728 return NULL; 729 } 730 731 void EmbeddedObjectRef::DrawPaintReplacement( const Rectangle &rRect, const String &rText, OutputDevice *pOut ) 732 { 733 MapMode aMM( MAP_APPFONT ); 734 Size aAppFontSz = pOut->LogicToLogic( Size( 0, 8 ), &aMM, NULL ); 735 Font aFnt( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Helvetica" ) ), aAppFontSz ); 736 aFnt.SetTransparent( sal_True ); 737 aFnt.SetColor( Color( COL_LIGHTRED ) ); 738 aFnt.SetWeight( WEIGHT_BOLD ); 739 aFnt.SetFamily( FAMILY_SWISS ); 740 741 pOut->Push(); 742 pOut->SetBackground(); 743 pOut->SetFont( aFnt ); 744 745 Point aPt; 746 // Nun den Text so skalieren, dass er in das Rect passt. 747 // Wir fangen mit der Defaultsize an und gehen 1-AppFont runter 748 for( sal_uInt16 i = 8; i > 2; i-- ) 749 { 750 aPt.X() = (rRect.GetWidth() - pOut->GetTextWidth( rText )) / 2; 751 aPt.Y() = (rRect.GetHeight() - pOut->GetTextHeight()) / 2; 752 753 sal_Bool bTiny = sal_False; 754 if( aPt.X() < 0 ) bTiny = sal_True, aPt.X() = 0; 755 if( aPt.Y() < 0 ) bTiny = sal_True, aPt.Y() = 0; 756 if( bTiny ) 757 { 758 // heruntergehen bei kleinen Bildern 759 aFnt.SetSize( Size( 0, aAppFontSz.Height() * i / 8 ) ); 760 pOut->SetFont( aFnt ); 761 } 762 else 763 break; 764 } 765 766 Bitmap aBmp( SvtResId( BMP_PLUGIN ) ); 767 long nHeight = rRect.GetHeight() - pOut->GetTextHeight(); 768 long nWidth = rRect.GetWidth(); 769 if( nHeight > 0 ) 770 { 771 aPt.Y() = nHeight; 772 Point aP = rRect.TopLeft(); 773 Size aBmpSize = aBmp.GetSizePixel(); 774 // Bitmap einpassen 775 if( nHeight * 10 / nWidth 776 > aBmpSize.Height() * 10 / aBmpSize.Width() ) 777 { 778 // nach der Breite ausrichten 779 // Proportion beibehalten 780 long nH = nWidth * aBmpSize.Height() / aBmpSize.Width(); 781 // zentrieren 782 aP.Y() += (nHeight - nH) / 2; 783 nHeight = nH; 784 } 785 else 786 { 787 // nach der H"ohe ausrichten 788 // Proportion beibehalten 789 long nW = nHeight * aBmpSize.Width() / aBmpSize.Height(); 790 // zentrieren 791 aP.X() += (nWidth - nW) / 2; 792 nWidth = nW; 793 } 794 795 pOut->DrawBitmap( aP, Size( nWidth, nHeight ), aBmp ); 796 } 797 798 pOut->IntersectClipRegion( rRect ); 799 aPt += rRect.TopLeft(); 800 pOut->DrawText( aPt, rText ); 801 pOut->Pop(); 802 } 803 804 void EmbeddedObjectRef::DrawShading( const Rectangle &rRect, OutputDevice *pOut ) 805 { 806 GDIMetaFile * pMtf = pOut->GetConnectMetaFile(); 807 if( pMtf && pMtf->IsRecord() ) 808 return; 809 810 pOut->Push(); 811 pOut->SetLineColor( Color( COL_BLACK ) ); 812 813 Size aPixSize = pOut->LogicToPixel( rRect.GetSize() ); 814 aPixSize.Width() -= 1; 815 aPixSize.Height() -= 1; 816 Point aPixViewPos = pOut->LogicToPixel( rRect.TopLeft() ); 817 sal_Int32 nMax = aPixSize.Width() + aPixSize.Height(); 818 for( sal_Int32 i = 5; i < nMax; i += 5 ) 819 { 820 Point a1( aPixViewPos ), a2( aPixViewPos ); 821 if( i > aPixSize.Width() ) 822 a1 += Point( aPixSize.Width(), i - aPixSize.Width() ); 823 else 824 a1 += Point( i, 0 ); 825 if( i > aPixSize.Height() ) 826 a2 += Point( i - aPixSize.Height(), aPixSize.Height() ); 827 else 828 a2 += Point( 0, i ); 829 830 pOut->DrawLine( pOut->PixelToLogic( a1 ), pOut->PixelToLogic( a2 ) ); 831 } 832 833 pOut->Pop(); 834 835 } 836 837 sal_Bool EmbeddedObjectRef::TryRunningState() 838 { 839 return TryRunningState( mxObj ); 840 } 841 842 sal_Bool EmbeddedObjectRef::TryRunningState( const uno::Reference < embed::XEmbeddedObject >& xEmbObj ) 843 { 844 if ( !xEmbObj.is() ) 845 return sal_False; 846 847 try 848 { 849 if ( xEmbObj->getCurrentState() == embed::EmbedStates::LOADED ) 850 xEmbObj->changeState( embed::EmbedStates::RUNNING ); 851 } 852 catch ( uno::Exception& ) 853 { 854 return sal_False; 855 } 856 857 return sal_True; 858 } 859 860 void EmbeddedObjectRef::SetGraphicToContainer( const Graphic& rGraphic, 861 comphelper::EmbeddedObjectContainer& aContainer, 862 const ::rtl::OUString& aName, 863 const ::rtl::OUString& aMediaType ) 864 { 865 SvMemoryStream aStream; 866 aStream.SetVersion( SOFFICE_FILEFORMAT_CURRENT ); 867 if ( rGraphic.ExportNative( aStream ) ) 868 { 869 aStream.Seek( 0 ); 870 871 uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aStream ); 872 aContainer.InsertGraphicStream( xStream, aName, aMediaType ); 873 } 874 else 875 OSL_ENSURE( sal_False, "Export of graphic is failed!\n" ); 876 } 877 878 sal_Bool EmbeddedObjectRef::ObjectIsModified( const uno::Reference< embed::XEmbeddedObject >& xObj ) 879 throw( uno::Exception ) 880 { 881 sal_Bool bResult = sal_False; 882 883 sal_Int32 nState = xObj->getCurrentState(); 884 if ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING ) 885 { 886 // the object is active so if the model is modified the replacement 887 // should be retrieved from the object 888 uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY ); 889 if ( xModifiable.is() ) 890 bResult = xModifiable->isModified(); 891 } 892 893 return bResult; 894 } 895 896 uno::Reference< io::XInputStream > EmbeddedObjectRef::GetGraphicReplacementStream( 897 sal_Int64 nViewAspect, 898 const uno::Reference< embed::XEmbeddedObject >& xObj, 899 ::rtl::OUString* pMediaType ) 900 throw() 901 { 902 return ::comphelper::EmbeddedObjectContainer::GetGraphicReplacementStream(nViewAspect,xObj,pMediaType); 903 } 904 905 void EmbeddedObjectRef::UpdateReplacementOnDemand() 906 { 907 DELETEZ( mpImp->pGraphic ); 908 mpImp->bNeedUpdate = sal_True; 909 if ( mpImp->pHCGraphic ) 910 DELETEZ( mpImp->pHCGraphic ); 911 mpImp->mnGraphicVersion++; 912 913 if( mpImp->pContainer ) 914 { 915 //remove graphic from container thus a new up to date one is requested on save 916 mpImp->pContainer->RemoveGraphicStream( mpImp->aPersistName ); 917 } 918 } 919 920 sal_Bool EmbeddedObjectRef::IsChart() const 921 { 922 //todo maybe for 3.0: 923 //if the changes work good for chart 924 //we should apply them for all own ole objects 925 926 //#i83708# #i81857# #i79578# request an ole replacement image only if really necessary 927 //as this call can be very expensive and does block the user interface as long at it takes 928 929 if ( !mxObj.is() ) 930 return false; 931 932 SvGlobalName aObjClsId( mxObj->getClassID() ); 933 if( 934 SvGlobalName(SO3_SCH_CLASSID_30) == aObjClsId 935 || SvGlobalName(SO3_SCH_CLASSID_40) == aObjClsId 936 || SvGlobalName(SO3_SCH_CLASSID_50) == aObjClsId 937 || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId) 938 { 939 return sal_True; 940 } 941 942 return sal_False; 943 } 944 945 // MT: Only used for getting accessible attributes, which are not localized 946 rtl::OUString EmbeddedObjectRef::GetChartType() 947 { 948 rtl::OUString Style; 949 if ( mxObj.is() ) 950 { 951 if ( IsChart() ) 952 { 953 if ( svt::EmbeddedObjectRef::TryRunningState( mxObj ) ) 954 { 955 uno::Reference< chart2::XChartDocument > xChart( mxObj->getComponent(), uno::UNO_QUERY ); 956 if (xChart.is()) 957 { 958 uno::Reference< chart2::XDiagram > xDiagram( xChart->getFirstDiagram()); 959 if( ! xDiagram.is()) 960 return String(); 961 uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); 962 uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); 963 // IA2 CWS. Unused: int nCoordinateCount = aCooSysSeq.getLength(); 964 sal_Bool bGetChartType = sal_False; 965 for( sal_Int32 nCooSysIdx=0; nCooSysIdx<aCooSysSeq.getLength(); ++nCooSysIdx ) 966 { 967 uno::Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); 968 uno::Sequence< uno::Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes()); 969 int nDimesionCount = aCooSysSeq[nCooSysIdx]->getDimension(); 970 if( nDimesionCount == 3 ) 971 Style += rtl::OUString::createFromAscii("3D "); 972 else 973 Style += rtl::OUString::createFromAscii("2D "); 974 for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx ) 975 { 976 rtl::OUString strChartType = aChartTypes[nCTIdx]->getChartType(); 977 if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.AreaChartType"))) 978 { 979 Style += rtl::OUString::createFromAscii("Areas"); 980 bGetChartType = sal_True; 981 } 982 else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.BarChartType"))) 983 { 984 Style += rtl::OUString::createFromAscii("Bars"); 985 bGetChartType = sal_True; 986 } 987 else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.ColumnChartType"))) 988 { 989 uno::Reference< beans::XPropertySet > xProp( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY ); 990 if( xProp.is()) 991 { 992 bool bCurrent = false; 993 if( xProp->getPropertyValue( rtl::OUString::createFromAscii("SwapXAndYAxis") ) >>= bCurrent ) 994 { 995 if (bCurrent) 996 Style += rtl::OUString::createFromAscii("Bars"); 997 else 998 Style += rtl::OUString::createFromAscii("Columns"); 999 bGetChartType = sal_True; 1000 } 1001 } 1002 } 1003 else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.LineChartType"))) 1004 { 1005 Style += rtl::OUString::createFromAscii("Lines"); 1006 bGetChartType = sal_True; 1007 } 1008 else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.ScatterChartType"))) 1009 { 1010 Style += rtl::OUString::createFromAscii("XY Chart"); 1011 bGetChartType = sal_True; 1012 } 1013 else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.PieChartType"))) 1014 { 1015 Style += rtl::OUString::createFromAscii("Pies"); 1016 bGetChartType = sal_True; 1017 } 1018 else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.NetChartType"))) 1019 { 1020 Style += rtl::OUString::createFromAscii("Radar"); 1021 bGetChartType = sal_True; 1022 } 1023 else if (strChartType.equals(::rtl::OUString::createFromAscii("com.sun.star.chart2.CandleStickChartType"))) 1024 { 1025 Style += rtl::OUString::createFromAscii("Candle Stick Chart"); 1026 bGetChartType = sal_True; 1027 } 1028 if (bGetChartType) 1029 return Style; 1030 } 1031 } 1032 } 1033 } 1034 } 1035 } 1036 return Style; 1037 } 1038 1039 // #i104867# 1040 sal_uInt32 EmbeddedObjectRef::getGraphicVersion() const 1041 { 1042 return mpImp->mnGraphicVersion; 1043 } 1044 1045 void EmbeddedObjectRef::SetDefaultSizeForChart( const Size& rSizeIn_100TH_MM ) 1046 { 1047 //#i103460# charts do not necessaryly have an own size within ODF files, 1048 //for this case they need to use the size settings from the surrounding frame, 1049 //which is made available with this method 1050 1051 mpImp->aDefaultSizeForChart_In_100TH_MM = awt::Size( rSizeIn_100TH_MM.getWidth(), rSizeIn_100TH_MM.getHeight() ); 1052 1053 ::com::sun::star::uno::Reference < ::com::sun::star::chart2::XDefaultSizeTransmitter > xSizeTransmitter( mxObj, uno::UNO_QUERY ); 1054 DBG_ASSERT( xSizeTransmitter.is(), "Object does not support XDefaultSizeTransmitter -> will cause #i103460#!" ); 1055 if( xSizeTransmitter.is() ) 1056 xSizeTransmitter->setDefaultSize( mpImp->aDefaultSizeForChart_In_100TH_MM ); 1057 } 1058 1059 } // namespace svt 1060 1061