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