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