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