xref: /AOO41X/main/svx/source/form/fmexch.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
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