xref: /trunk/main/svx/source/form/fmexch.cxx (revision f6e50924)
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_svx.hxx"
26 #include "fmexch.hxx"
27 
28 #include <sot/storage.hxx>
29 #include <svl/itempool.hxx>
30 
31 #ifndef _SVX_DBEXCH_HRC
32 #include <svx/dbexch.hrc>
33 #endif
34 #include <sot/formats.hxx>
35 #include <svtools/svtreebx.hxx>
36 #include <tools/diagnose_ex.h>
37 
38 #define _SVSTDARR_ULONGS
39 #include <svl/svstdarr.hxx>
40 
41 //........................................................................
42 namespace svxform
43 {
44 //........................................................................
45 
46 	using namespace ::com::sun::star::uno;
47 	using namespace ::com::sun::star::datatransfer;
48 
49 	//====================================================================
50 	//= OLocalExchange
51 	//====================================================================
52 	//--------------------------------------------------------------------
OLocalExchange()53 	OLocalExchange::OLocalExchange( )
54 		:m_bDragging( sal_False )
55 		,m_bClipboardOwner( sal_False )
56 	{
57 	}
58 
59 	//--------------------------------------------------------------------
copyToClipboard(Window * _pWindow,const GrantAccess &)60 	void OLocalExchange::copyToClipboard( Window* _pWindow, const GrantAccess& )
61 	{
62 		if ( m_bClipboardOwner )
63 		{	// simulate a lostOwnership to notify parties interested in
64 			if ( m_aClipboardListener.IsSet() )
65 				m_aClipboardListener.Call( this );
66 		}
67 
68 		m_bClipboardOwner = sal_True;
69 		CopyToClipboard( _pWindow );
70 	}
71 
72 	//--------------------------------------------------------------------
clear()73 	void OLocalExchange::clear()
74 	{
75 		if ( isClipboardOwner() )
76 		{
77 			try
78 			{
79 				Reference< clipboard::XClipboard > xClipBoard( getOwnClipboard() );
80 				if ( xClipBoard.is() )
81 					xClipBoard->setContents( NULL, NULL );
82 			}
83 			catch( const Exception& )
84 			{
85                 DBG_UNHANDLED_EXCEPTION();
86 			}
87 			m_bClipboardOwner = sal_False;
88 		}
89 	}
90 
91 	//--------------------------------------------------------------------
lostOwnership(const Reference<clipboard::XClipboard> & _rxClipboard,const Reference<XTransferable> & _rxTrans)92     void SAL_CALL OLocalExchange::lostOwnership( const Reference< clipboard::XClipboard >& _rxClipboard, const Reference< XTransferable >& _rxTrans ) throw(RuntimeException)
93 	{
94 		TransferableHelper::implCallOwnLostOwnership( _rxClipboard, _rxTrans );
95 		m_bClipboardOwner = sal_False;
96 
97 		if ( m_aClipboardListener.IsSet() )
98 			m_aClipboardListener.Call( this );
99 	}
100 
101 	//--------------------------------------------------------------------
startDrag(Window * _pWindow,sal_Int8 _nDragSourceActions,const GrantAccess &)102 	void OLocalExchange::startDrag( Window* _pWindow, sal_Int8 _nDragSourceActions, const GrantAccess& )
103 	{
104 		m_bDragging = sal_True;
105 		StartDrag( _pWindow, _nDragSourceActions );
106 	}
107 
108 	//--------------------------------------------------------------------
DragFinished(sal_Int8 nDropAction)109 	void OLocalExchange::DragFinished( sal_Int8 nDropAction )
110 	{
111 		TransferableHelper::DragFinished( nDropAction );
112 		m_bDragging = sal_False;
113 	}
114 
115 	//--------------------------------------------------------------------
hasFormat(const DataFlavorExVector & _rFormats,sal_uInt32 _nFormatId)116 	sal_Bool OLocalExchange::hasFormat( const DataFlavorExVector& _rFormats, sal_uInt32 _nFormatId )
117 	{
118 		DataFlavorExVector::const_iterator aSearch;
119 
120 		for	( aSearch = _rFormats.begin(); aSearch != _rFormats.end(); ++aSearch )
121 			if ( aSearch->mnSotId == _nFormatId )
122 				break;
123 
124 		return aSearch != _rFormats.end();
125 	}
126 
127 	//--------------------------------------------------------------------
GetData(const::com::sun::star::datatransfer::DataFlavor &)128 	sal_Bool OLocalExchange::GetData( const ::com::sun::star::datatransfer::DataFlavor& /*_rFlavor*/ )
129 	{
130 		return sal_False;	// do not have any formats by default
131 	}
132 
133 	//====================================================================
134 	//= OControlTransferData
135 	//====================================================================
136 	//--------------------------------------------------------------------
OControlTransferData()137 	OControlTransferData::OControlTransferData( )
138 		:m_pFocusEntry( NULL )
139 	{
140 	}
141 
142 	//--------------------------------------------------------------------
OControlTransferData(const Reference<XTransferable> & _rxTransferable)143 	OControlTransferData::OControlTransferData( const Reference< XTransferable >& _rxTransferable )
144 		:m_pFocusEntry( NULL )
145 	{
146 		TransferableDataHelper aExchangedData( _rxTransferable );
147 
148 		// try the formats we know
149 		if ( OControlExchange::hasControlPathFormat( aExchangedData.GetDataFlavorExVector() ) )
150 		{	// paths to the controls, relative to a root
151 			Sequence< Any > aControlPathData;
152 			if ( aExchangedData.GetAny( OControlExchange::getControlPathFormatId() ) >>= aControlPathData )
153 			{
154 				DBG_ASSERT( aControlPathData.getLength() >= 2, "OControlTransferData::OControlTransferData: invalid data for the control path format!" );
155 				if ( aControlPathData.getLength() >= 2 )
156 				{
157 					aControlPathData[0] >>= m_xFormsRoot;
158 					aControlPathData[1] >>= m_aControlPaths;
159 				}
160 			}
161 			else
162 			{
163 				DBG_ERROR( "OControlTransferData::OControlTransferData: invalid data for the control path format (2)!" );
164 			}
165 		}
166 		if ( OControlExchange::hasHiddenControlModelsFormat( aExchangedData.GetDataFlavorExVector() ) )
167 		{	// sequence of models of hidden controls
168 			aExchangedData.GetAny( OControlExchange::getHiddenControlModelsFormatId() ) >>= m_aHiddenControlModels;
169 		}
170 
171 		updateFormats( );
172 	}
173 
174 	//--------------------------------------------------------------------
lcl_fillDataFlavorEx(SotFormatStringId nId,DataFlavorEx & _rFlavor)175 	static sal_Bool lcl_fillDataFlavorEx( SotFormatStringId nId, DataFlavorEx& _rFlavor )
176 	{
177 		_rFlavor.mnSotId = nId;
178 		return SotExchange::GetFormatDataFlavor( _rFlavor.mnSotId, _rFlavor );
179 	}
180 
181 	//--------------------------------------------------------------------
updateFormats()182 	void OControlTransferData::updateFormats( )
183 	{
184 		m_aCurrentFormats.clear();
185 		m_aCurrentFormats.reserve( 3 );
186 
187 		DataFlavorEx aFlavor;
188 
189 		if ( m_aHiddenControlModels.getLength() )
190 		{
191 			if ( lcl_fillDataFlavorEx( OControlExchange::getHiddenControlModelsFormatId(), aFlavor ) )
192 				m_aCurrentFormats.push_back( aFlavor );
193 		}
194 
195 		if ( m_xFormsRoot.is() && m_aControlPaths.getLength() )
196 		{
197 			if ( lcl_fillDataFlavorEx( OControlExchange::getControlPathFormatId(), aFlavor ) )
198 				m_aCurrentFormats.push_back( aFlavor );
199 		}
200 
201 		if ( !m_aSelectedEntries.empty() )
202 		{
203 			if ( lcl_fillDataFlavorEx( OControlExchange::getFieldExchangeFormatId(), aFlavor ) )
204 				m_aCurrentFormats.push_back( aFlavor );
205 		}
206 	}
207 
208 	//--------------------------------------------------------------------
onEntryRemoved(SvLBoxEntry * _pEntry)209 	size_t OControlTransferData::onEntryRemoved( SvLBoxEntry* _pEntry )
210 	{
211         m_aSelectedEntries.erase( _pEntry );
212         return m_aSelectedEntries.size();
213 	}
214 
215 	//--------------------------------------------------------------------
addSelectedEntry(SvLBoxEntry * _pEntry)216 	void OControlTransferData::addSelectedEntry( SvLBoxEntry* _pEntry )
217 	{
218 		m_aSelectedEntries.insert( _pEntry );
219 	}
220 
221 	//--------------------------------------------------------------------
setFocusEntry(SvLBoxEntry * _pFocusEntry)222 	void OControlTransferData::setFocusEntry( SvLBoxEntry* _pFocusEntry )
223 	{
224 		m_pFocusEntry = _pFocusEntry;
225 	}
226 
227 	//------------------------------------------------------------------------
addHiddenControlsFormat(const::com::sun::star::uno::Sequence<::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface>> seqInterfaces)228 	void OControlTransferData::addHiddenControlsFormat(const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > seqInterfaces)
229 	{
230 		m_aHiddenControlModels = seqInterfaces;
231 	}
232 
233 	//------------------------------------------------------------------------
buildPathFormat(SvTreeListBox * pTreeBox,SvLBoxEntry * pRoot)234 	void OControlTransferData::buildPathFormat(SvTreeListBox* pTreeBox, SvLBoxEntry* pRoot)
235 	{
236 		m_aControlPaths.realloc(0);
237 
238 		sal_Int32 nEntryCount = m_aSelectedEntries.size();
239 		if (nEntryCount == 0)
240 			return;
241 
242 		m_aControlPaths.realloc(nEntryCount);
243 		::com::sun::star::uno::Sequence<sal_uInt32>* pAllPaths = m_aControlPaths.getArray();
244         for (   ListBoxEntrySet::const_iterator loop = m_aSelectedEntries.begin();
245                 loop != m_aSelectedEntries.end();
246                 ++loop, ++pAllPaths
247             )
248 		{
249 			// erst mal sammeln wir den Pfad in einem Array ein
250 			::std::vector< sal_uInt32 > aCurrentPath;
251 			SvLBoxEntry* pCurrentEntry = *loop;
252 
253 			SvLBoxEntry* pLoop = pCurrentEntry;
254 			while (pLoop != pRoot)
255 			{
256 				aCurrentPath.push_back(pLoop->GetChildListPos());
257 				pLoop = pTreeBox->GetParent(pLoop);
258 				DBG_ASSERT((pLoop != NULL) || (pRoot == 0), "OControlTransferData::buildPathFormat: invalid root or entry !");
259 					// pLoop == NULL heisst, dass ich am oberen Ende angelangt bin, dann sollte das Ganze abbrechen, was nur bei pRoot == NULL der Fall sein wird
260 			}
261 
262 			// dann koennen wir ihn in die ::com::sun::star::uno::Sequence uebertragen
263 			Sequence<sal_uInt32>& rCurrentPath = *pAllPaths;
264 			sal_Int32 nDepth = aCurrentPath.size();
265 
266 			rCurrentPath.realloc(nDepth);
267 			sal_uInt32* pSeq = rCurrentPath.getArray();
268 			sal_Int32 j,k;
269 			for (j = nDepth - 1, k = 0; k<nDepth; --j, ++k)
270 				pSeq[j] = aCurrentPath[k];
271 		}
272 	}
273 
274 	//------------------------------------------------------------------------
buildListFromPath(SvTreeListBox * pTreeBox,SvLBoxEntry * pRoot)275 	void OControlTransferData::buildListFromPath(SvTreeListBox* pTreeBox, SvLBoxEntry* pRoot)
276 	{
277         ListBoxEntrySet aEmpty;
278 		m_aSelectedEntries.swap( aEmpty );
279 
280 		sal_Int32 nControls = m_aControlPaths.getLength();
281 		const ::com::sun::star::uno::Sequence<sal_uInt32>* pPaths = m_aControlPaths.getConstArray();
282 		for (sal_Int32 i=0; i<nControls; ++i)
283 		{
284 			sal_Int32 nThisPatLength = pPaths[i].getLength();
285 			const sal_uInt32* pThisPath = pPaths[i].getConstArray();
286 			SvLBoxEntry* pSearch = pRoot;
287 			for (sal_Int32 j=0; j<nThisPatLength; ++j)
288 				pSearch = pTreeBox->GetEntry(pSearch, pThisPath[j]);
289 
290 			m_aSelectedEntries.insert( pSearch );
291 		}
292 	}
293 
294 	//====================================================================
295 	//= OControlExchange
296 	//====================================================================
297 	//--------------------------------------------------------------------
OControlExchange()298 	OControlExchange::OControlExchange( )
299 	{
300 	}
301 
302 	//--------------------------------------------------------------------
GetData(const DataFlavor & _rFlavor)303 	sal_Bool OControlExchange::GetData( const DataFlavor& _rFlavor )
304 	{
305 		const sal_uInt32 nFormatId = SotExchange::GetFormat( _rFlavor );
306 
307 		if ( getControlPathFormatId( ) == nFormatId )
308 		{
309 			// ugly. We have to pack all the info into one object
310 			Sequence< Any > aCompleteInfo( 2 );
311 			OSL_ENSURE( m_xFormsRoot.is(), "OLocalExchange::GetData: invalid forms root for this format!" );
312 			aCompleteInfo.getArray()[ 0 ] <<= m_xFormsRoot;
313 			aCompleteInfo.getArray()[ 1 ] <<= m_aControlPaths;
314 
315 			SetAny( makeAny( aCompleteInfo ), _rFlavor );
316 		}
317 		else if ( getHiddenControlModelsFormatId() == nFormatId )
318 		{
319 			// just need to transfer the models
320 			SetAny( makeAny( m_aHiddenControlModels ), _rFlavor );
321 		}
322 		else
323 			return OLocalExchange::GetData( _rFlavor );
324 
325 		return sal_True;
326 	}
327 
328 	//--------------------------------------------------------------------
AddSupportedFormats()329 	void OControlExchange::AddSupportedFormats()
330 	{
331 		if (m_pFocusEntry && !m_aSelectedEntries.empty())
332 			AddFormat(getFieldExchangeFormatId());
333 
334 		if (m_aControlPaths.getLength())
335 			AddFormat(getControlPathFormatId());
336 
337 		if (m_aHiddenControlModels.getLength())
338 			AddFormat(getHiddenControlModelsFormatId());
339 	}
340 
341 	//--------------------------------------------------------------------
getControlPathFormatId()342 	sal_uInt32 OControlExchange::getControlPathFormatId()
343 	{
344 		static sal_uInt32 s_nFormat = (sal_uInt32)-1;
345 		if ((sal_uInt32)-1 == s_nFormat)
346 		{
347 			s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"svxform.ControlPathExchange\""));
348 			DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OControlExchange::getControlPathFormatId: bad exchange id!");
349 		}
350 		return s_nFormat;
351 	}
352 
353 	//--------------------------------------------------------------------
getHiddenControlModelsFormatId()354 	sal_uInt32 OControlExchange::getHiddenControlModelsFormatId()
355 	{
356 		static sal_uInt32 s_nFormat = (sal_uInt32)-1;
357 		if ((sal_uInt32)-1 == s_nFormat)
358 		{
359 			s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"svxform.HiddenControlModelsExchange\""));
360 			DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OControlExchange::getHiddenControlModelsFormatId: bad exchange id!");
361 		}
362 		return s_nFormat;
363 	}
364 
365 	//--------------------------------------------------------------------
getFieldExchangeFormatId()366 	sal_uInt32 OControlExchange::getFieldExchangeFormatId()
367 	{
368 		static sal_uInt32 s_nFormat = (sal_uInt32)-1;
369 		if ((sal_uInt32)-1 == s_nFormat)
370 		{
371 			s_nFormat = SotExchange::RegisterFormatName(String::CreateFromAscii("application/x-openoffice;windows_formatname=\"svxform.FieldNameExchange\""));
372 			DBG_ASSERT((sal_uInt32)-1 != s_nFormat, "OControlExchange::getFieldExchangeFormatId: bad exchange id!");
373 		}
374 		return s_nFormat;
375 	}
376 
377 	//====================================================================
378 	//= OControlExchangeHelper
379 	//====================================================================
createExchange() const380 	OLocalExchange* OControlExchangeHelper::createExchange() const
381 	{
382 		return new OControlExchange;
383 	}
384 
385 	//====================================================================
386 	//= OLocalExchangeHelper
387 	//====================================================================
388 	//--------------------------------------------------------------------
OLocalExchangeHelper(Window * _pDragSource)389 	OLocalExchangeHelper::OLocalExchangeHelper(Window* _pDragSource)
390 		:m_pDragSource(_pDragSource)
391 		,m_pTransferable(NULL)
392 	{
393 	}
394 
395 	//--------------------------------------------------------------------
~OLocalExchangeHelper()396 	OLocalExchangeHelper::~OLocalExchangeHelper()
397 	{
398 		implReset();
399 	}
400 
401 	//--------------------------------------------------------------------
startDrag(sal_Int8 nDragSourceActions)402 	void OLocalExchangeHelper::startDrag( sal_Int8 nDragSourceActions )
403 	{
404 		DBG_ASSERT(m_pTransferable, "OLocalExchangeHelper::startDrag: not prepared!");
405 		m_pTransferable->startDrag( m_pDragSource, nDragSourceActions, OLocalExchange::GrantAccess() );
406 	}
407 
408 	//--------------------------------------------------------------------
copyToClipboard() const409 	void OLocalExchangeHelper::copyToClipboard( ) const
410 	{
411 		DBG_ASSERT( m_pTransferable, "OLocalExchangeHelper::copyToClipboard: not prepared!" );
412 		m_pTransferable->copyToClipboard( m_pDragSource, OLocalExchange::GrantAccess() );
413 	}
414 
415 	//--------------------------------------------------------------------
implReset()416 	void OLocalExchangeHelper::implReset()
417 	{
418 		if (m_pTransferable)
419 		{
420 			m_pTransferable->setClipboardListener( Link() );
421 			m_pTransferable->release();
422 			m_pTransferable = NULL;
423 		}
424 	}
425 
426 	//--------------------------------------------------------------------
prepareDrag()427 	void OLocalExchangeHelper::prepareDrag( )
428 	{
429 		DBG_ASSERT(!m_pTransferable || !m_pTransferable->isDragging(), "OLocalExchangeHelper::prepareDrag: recursive DnD?");
430 
431 		implReset();
432 		m_pTransferable = createExchange();
433 		m_pTransferable->acquire();
434 	}
435 
436 //........................................................................
437 }
438 //........................................................................
439 
440