1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svtools.hxx" 30 #include <com/sun/star/embed/XComponentSupplier.hpp> 31 #include <com/sun/star/embed/EmbedStates.hpp> 32 #include <com/sun/star/embed/XVisualObject.hpp> 33 #include <com/sun/star/embed/XEmbedPersist.hpp> 34 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 35 #include <com/sun/star/datatransfer/XTransferable.hpp> 36 #include <com/sun/star/embed/Aspects.hpp> 37 38 #include <svtools/embedtransfer.hxx> 39 #include <tools/mapunit.hxx> 40 #include <vcl/outdev.hxx> 41 #include <comphelper/storagehelper.hxx> 42 #include <unotools/ucbstreamhelper.hxx> 43 #include <unotools/streamwrap.hxx> 44 #include <unotools/tempfile.hxx> 45 #include <toolkit/helper/vclunohelper.hxx> 46 47 #include <svtools/embedhlp.hxx> 48 49 using namespace ::com::sun::star; 50 51 SvEmbedTransferHelper::SvEmbedTransferHelper( const uno::Reference< embed::XEmbeddedObject >& xObj, 52 Graphic* pGraphic, 53 sal_Int64 nAspect ) 54 : m_xObj( xObj ) 55 , m_pGraphic( pGraphic ? new Graphic( *pGraphic ) : NULL ) 56 , m_nAspect( nAspect ) 57 { 58 if( xObj.is() ) 59 { 60 TransferableObjectDescriptor aObjDesc; 61 62 FillTransferableObjectDescriptor( aObjDesc, m_xObj, NULL, m_nAspect ); 63 PrepareOLE( aObjDesc ); 64 } 65 } 66 67 // ----------------------------------------------------------------------------- 68 69 SvEmbedTransferHelper::~SvEmbedTransferHelper() 70 { 71 if ( m_pGraphic ) 72 { 73 delete m_pGraphic; 74 m_pGraphic = NULL; 75 } 76 } 77 78 // ----------------------------------------------------------------------------- 79 80 void SvEmbedTransferHelper::AddSupportedFormats() 81 { 82 AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ); 83 AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ); 84 AddFormat( FORMAT_GDIMETAFILE ); 85 } 86 87 // ----------------------------------------------------------------------------- 88 89 sal_Bool SvEmbedTransferHelper::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor ) 90 { 91 sal_Bool bRet = sal_False; 92 93 if( m_xObj.is() ) 94 { 95 try 96 { 97 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor ); 98 if( HasFormat( nFormat ) ) 99 { 100 if( nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) 101 { 102 TransferableObjectDescriptor aDesc; 103 FillTransferableObjectDescriptor( aDesc, m_xObj, m_pGraphic, m_nAspect ); 104 bRet = SetTransferableObjectDescriptor( aDesc, rFlavor ); 105 } 106 else if( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE ) 107 { 108 try 109 { 110 // TODO/LATER: Propbably the graphic should be copied here as well 111 // currently it is handled by the applications 112 utl::TempFile aTmp; 113 aTmp.EnableKillingFile( sal_True ); 114 uno::Reference < embed::XEmbedPersist > xPers( m_xObj, uno::UNO_QUERY ); 115 if ( xPers.is() ) 116 { 117 uno::Reference < embed::XStorage > xStg = comphelper::OStorageHelper::GetTemporaryStorage(); 118 ::rtl::OUString aName = ::rtl::OUString::createFromAscii("Dummy"); 119 SvStream* pStream = NULL; 120 sal_Bool bDeleteStream = sal_False; 121 uno::Sequence < beans::PropertyValue > aEmpty; 122 xPers->storeToEntry( xStg, aName, aEmpty, aEmpty ); 123 if ( xStg->isStreamElement( aName ) ) 124 { 125 uno::Reference < io::XStream > xStm = xStg->cloneStreamElement( aName ); 126 pStream = utl::UcbStreamHelper::CreateStream( xStm ); 127 bDeleteStream = sal_True; 128 } 129 else 130 { 131 pStream = aTmp.GetStream( STREAM_STD_READWRITE ); 132 uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper( *pStream ) ); 133 xStg->openStorageElement( aName, embed::ElementModes::READ )->copyToStorage( xStor ); 134 } 135 136 ::com::sun::star::uno::Any aAny; 137 const sal_uInt32 nLen = pStream->Seek( STREAM_SEEK_TO_END ); 138 ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( nLen ); 139 140 pStream->Seek( STREAM_SEEK_TO_BEGIN ); 141 pStream->Read( aSeq.getArray(), nLen ); 142 if ( bDeleteStream ) 143 delete pStream; 144 145 if( ( bRet = ( aSeq.getLength() > 0 ) ) == sal_True ) 146 { 147 aAny <<= aSeq; 148 SetAny( aAny, rFlavor ); 149 } 150 } 151 else 152 { 153 //TODO/LATER: how to handle objects without persistance?! 154 } 155 } 156 catch ( uno::Exception& ) 157 { 158 } 159 } 160 else if ( nFormat == FORMAT_GDIMETAFILE && m_pGraphic ) 161 { 162 SvMemoryStream aMemStm( 65535, 65535 ); 163 aMemStm.SetVersion( SOFFICE_FILEFORMAT_CURRENT ); 164 165 const GDIMetaFile& aMetaFile = m_pGraphic->GetGDIMetaFile(); 166 ((GDIMetaFile*)(&aMetaFile))->Write( aMemStm ); 167 uno::Any aAny; 168 aAny <<= uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), 169 aMemStm.Seek( STREAM_SEEK_TO_END ) ); 170 SetAny( aAny, rFlavor ); 171 bRet = sal_True; 172 } 173 else if ( m_xObj.is() && :: svt::EmbeddedObjectRef::TryRunningState( m_xObj ) ) 174 { 175 uno::Reference< datatransfer::XTransferable > xTransferable( m_xObj->getComponent(), uno::UNO_QUERY ); 176 if ( xTransferable.is() ) 177 { 178 uno::Any aAny = xTransferable->getTransferData( rFlavor ); 179 SetAny( aAny, rFlavor ); 180 bRet = sal_True; 181 } 182 } 183 } 184 } 185 catch( uno::Exception& ) 186 { 187 // Error handling? 188 } 189 } 190 191 return bRet; 192 } 193 194 // ----------------------------------------------------------------------------- 195 196 void SvEmbedTransferHelper::ObjectReleased() 197 { 198 m_xObj = uno::Reference< embed::XEmbeddedObject >(); 199 } 200 201 void SvEmbedTransferHelper::FillTransferableObjectDescriptor( TransferableObjectDescriptor& rDesc, 202 const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XEmbeddedObject >& xObj, 203 Graphic* pGraphic, 204 sal_Int64 nAspect ) 205 { 206 //TODO/LATER: need TypeName to fill it into the Descriptor (will be shown in listbox) 207 ::com::sun::star::datatransfer::DataFlavor aFlavor; 208 SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aFlavor ); 209 210 rDesc.maClassName = SvGlobalName( xObj->getClassID() ); 211 rDesc.maTypeName = aFlavor.HumanPresentableName; 212 213 //TODO/LATER: the aspect size in the descriptor is wrong, unfortunately the stream 214 // representation of the descriptor allows only 4 bytes for the aspect 215 // so for internal transport something different should be found 216 rDesc.mnViewAspect = sal::static_int_cast<sal_uInt16>( nAspect ); 217 218 //TODO/LATER: status needs to become sal_Int64 219 rDesc.mnOle2Misc = sal::static_int_cast<sal_Int32>(xObj->getStatus( rDesc.mnViewAspect )); 220 221 Size aSize; 222 MapMode aMapMode( MAP_100TH_MM ); 223 if ( nAspect == embed::Aspects::MSOLE_ICON ) 224 { 225 if ( pGraphic ) 226 { 227 aMapMode = pGraphic->GetPrefMapMode(); 228 aSize = pGraphic->GetPrefSize(); 229 } 230 else 231 aSize = Size( 2500, 2500 ); 232 } 233 else 234 { 235 try 236 { 237 awt::Size aSz; 238 aSz = xObj->getVisualAreaSize( rDesc.mnViewAspect ); 239 aSize = Size( aSz.Width, aSz.Height ); 240 } 241 catch( embed::NoVisualAreaSizeException& ) 242 { 243 OSL_ENSURE( sal_False, "Can not get visual area size!\n" ); 244 aSize = Size( 5000, 5000 ); 245 } 246 247 // TODO/LEAN: getMapUnit can switch object to running state 248 aMapMode = MapMode( VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( rDesc.mnViewAspect ) ) ); 249 } 250 251 rDesc.maSize = OutputDevice::LogicToLogic( aSize, aMapMode, MapMode( MAP_100TH_MM ) ); 252 rDesc.maDragStartPos = Point(); 253 rDesc.maDisplayName = String(); 254 rDesc.mbCanLink = sal_False; 255 } 256 257