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_sw.hxx" 30 31 32 #include <hintids.hxx> 33 34 35 #include <svx/svdview.hxx> 36 #include <editeng/outliner.hxx> 37 //#ifndef _SVDVMARK_HXX //autogen 38 //#include <svx/svdvmark.hxx> 39 //#endif 40 #include <svx/svdobj.hxx> 41 #include <sot/exchange.hxx> 42 #include <sot/formats.hxx> 43 #include <sfx2/bindings.hxx> 44 45 #include <sfx2/viewfrm.hxx> 46 #include <fmturl.hxx> 47 #include <frmfmt.hxx> 48 #include <wrtsh.hxx> 49 #include <edtwin.hxx> 50 #ifndef _VIEW_HXX 51 #include <view.hxx> 52 #endif 53 #include <viewopt.hxx> 54 #include <swdtflvr.hxx> 55 #include <swmodule.hxx> 56 #ifndef _DOCSH_HXX 57 #include <docsh.hxx> 58 #endif 59 #include <wdocsh.hxx> 60 #include <swundo.hxx> 61 62 using namespace ::com::sun::star; 63 64 // no include "dbgoutsw.hxx" here!!!!!! 65 66 extern sal_Bool bNoInterrupt; 67 extern sal_Bool bFrmDrag; 68 extern sal_Bool bDDTimerStarted; 69 70 sal_Bool bExecuteDrag = sal_False; 71 72 void SwEditWin::StartDDTimer() 73 { 74 aTimer.SetTimeoutHdl(LINK(this, SwEditWin, DDHandler)); 75 aTimer.SetTimeout(480); 76 aTimer.Start(); 77 bDDTimerStarted = sal_True; 78 } 79 80 81 void SwEditWin::StopDDTimer(SwWrtShell *pSh, const Point &rPt) 82 { 83 aTimer.Stop(); 84 bDDTimerStarted = sal_False; 85 if(!pSh->IsSelFrmMode()) 86 (pSh->*pSh->fnSetCrsr)(&rPt,sal_False); 87 aTimer.SetTimeoutHdl(LINK(this,SwEditWin, TimerHandler)); 88 } 89 90 void SwEditWin::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel ) 91 { 92 SwWrtShell &rSh = rView.GetWrtShell(); 93 if( rSh.GetDrawView() ) 94 { 95 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True ); 96 if( rSh.GetDrawView()->Command( aDragEvent, this ) ) 97 { 98 rView.GetViewFrame()->GetBindings().InvalidateAll(sal_False); 99 return; // Event von der SdrView ausgewertet 100 } 101 } 102 103 if ( !pApplyTempl && !rSh.IsDrawCreate() && !IsDrawAction()) 104 { 105 sal_Bool bStart = sal_False, bDelSelect = sal_False; 106 SdrObject *pObj = NULL; 107 Point aDocPos( PixelToLogic( rPosPixel ) ); 108 if ( !rSh.IsInSelect() && rSh.ChgCurrPam( aDocPos, sal_True, sal_True)) 109 //Wir sind nicht beim Selektieren und stehen auf einer 110 //Selektion 111 bStart = sal_True; 112 else if ( !bFrmDrag && rSh.IsSelFrmMode() && 113 rSh.IsInsideSelectedObj( aDocPos ) ) 114 { 115 //Wir sind nicht am internen Draggen und stehen auf 116 //einem Objekt (Rahmen, Zeichenobjekt) 117 118 bStart = sal_True; 119 } 120 else if( !bFrmDrag && rView.GetDocShell()->IsReadOnly() && 121 OBJCNT_NONE != rSh.GetObjCntType( aDocPos, pObj )) 122 { 123 rSh.LockPaint(); 124 if( rSh.SelectObj( aDocPos, 0, pObj )) 125 bStart = bDelSelect = sal_True; 126 else 127 rSh.UnlockPaint(); 128 } 129 else 130 { 131 SwContentAtPos aSwContentAtPos( SwContentAtPos::SW_INETATTR ); 132 bStart = rSh.GetContentAtPos( aDocPos, 133 aSwContentAtPos, 134 sal_False ); 135 } 136 137 if ( bStart && !bIsInDrag ) 138 { 139 bMBPressed = sal_False; 140 ReleaseMouse(); 141 bFrmDrag = sal_False; 142 bExecuteDrag = sal_True; 143 SwEditWin::nDDStartPosY = aDocPos.Y(); 144 SwEditWin::nDDStartPosX = aDocPos.X(); 145 aMovePos = aDocPos; 146 StartExecuteDrag(); 147 if( bDelSelect ) 148 { 149 rSh.UnSelectFrm(); 150 rSh.UnlockPaint(); 151 } 152 } 153 } 154 } 155 156 void SwEditWin::StartExecuteDrag() 157 { 158 if( !bExecuteDrag || bIsInDrag ) 159 return; 160 161 bIsInDrag = sal_True; 162 163 SwTransferable* pTransfer = new SwTransferable( rView.GetWrtShell() ); 164 uno::Reference< 165 datatransfer::XTransferable > xRef( pTransfer ); 166 167 pTransfer->StartDrag( this, aMovePos ); 168 } 169 170 void SwEditWin::DragFinished() 171 { 172 DropCleanup(); 173 aTimer.SetTimeoutHdl( LINK(this,SwEditWin, TimerHandler) ); 174 bIsInDrag = sal_False; 175 } 176 177 178 void SwEditWin::DropCleanup() 179 { 180 SwWrtShell &rSh = rView.GetWrtShell(); 181 182 // Stati zuruecksetzen 183 bNoInterrupt = sal_False; 184 if ( bOldIdleSet ) 185 { 186 ((SwViewOption*)rSh.GetViewOptions())->SetIdle( bOldIdle ); 187 bOldIdleSet = sal_False; 188 } 189 if ( pUserMarker ) 190 CleanupDropUserMarker(); 191 else 192 rSh.UnSetVisCrsr(); 193 194 } 195 196 void SwEditWin::CleanupDropUserMarker() 197 { 198 if ( pUserMarker ) 199 { 200 delete pUserMarker; 201 pUserMarker = 0; 202 pUserMarkerObj = 0; 203 } 204 } 205 206 207 //Messehack (MA,MBA) 208 void lcl_SelectShellForDrop( SwView &rView ) 209 { 210 if ( !rView.GetCurShell() ) 211 rView.SelectShell(); 212 } 213 214 sal_Int8 SwEditWin::ExecuteDrop( const ExecuteDropEvent& rEvt ) 215 { 216 ::lcl_SelectShellForDrop( GetView() ); 217 DropCleanup(); 218 sal_Int8 nRet = DND_ACTION_NONE; 219 220 //Ein Drop auf eine offene OutlinerView geht uns nichts an (siehe auch QueryDrop) 221 SwWrtShell &rSh = rView.GetWrtShell(); 222 const Point aDocPt( PixelToLogic( rEvt.maPosPixel )); 223 SdrObject *pObj = 0; 224 OutlinerView* pOLV; 225 rSh.GetObjCntType( aDocPt, pObj ); 226 227 if( pObj && 0 != ( pOLV = rSh.GetDrawView()->GetTextEditOutlinerView() )) 228 { 229 Rectangle aRect( pOLV->GetOutputArea() ); 230 aRect.Union( pObj->GetLogicRect() ); 231 const Point aPos = pOLV->GetWindow()->PixelToLogic(rEvt.maPosPixel); 232 if ( aRect.IsInside(aPos) ) 233 { 234 rSh.StartAllAction(); 235 //!! sal_Int8 nRet = DND_ACTION_NONE/*pOLV->ExecuteDrop( rEvt )*/; 236 rSh.EndAllAction(); 237 return nRet; 238 } 239 } 240 241 242 // dvo 2002-05-27, #99027#: There's a special treatment for file lists with a single 243 // element, that depends on the actual content of the 244 // Transferable to be accessible. Since the transferable 245 // may only be accessed after the drop has been accepted 246 // (according to KA due to Java D&D), we'll have to 247 // reevaluate the drop action once more _with_ the 248 // Transferable. 249 sal_uInt16 nEventAction; 250 sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT 251 : rEvt.mnAction; 252 m_nDropAction = SotExchange::GetExchangeAction( 253 GetDataFlavorExVector(), 254 m_nDropDestination, 255 rEvt.mnAction, 256 //!! rEvt.GetSourceOptions(), 257 nUserOpt, m_nDropFormat, nEventAction, 0, 258 &rEvt.maDropEvent.Transferable ); 259 260 261 TransferableDataHelper aData( rEvt.maDropEvent.Transferable ); 262 nRet = rEvt.mnAction; 263 if( !SwTransferable::PasteData( aData, rSh, m_nDropAction, m_nDropFormat, 264 m_nDropDestination, sal_False, rEvt.mbDefault, &aDocPt, nRet)) 265 //!! nRet = SFX_APP()->ExecuteDrop( rEvt ); 266 nRet = DND_ACTION_NONE; 267 else if ( SW_MOD()->pDragDrop ) 268 //Bei internem D&D nicht mehr aufraeumen! 269 SW_MOD()->pDragDrop->SetCleanUp( sal_False ); 270 271 return nRet; 272 } 273 274 275 sal_uInt16 SwEditWin::GetDropDestination( const Point& rPixPnt, SdrObject ** ppObj ) 276 { 277 SwWrtShell &rSh = rView.GetWrtShell(); 278 const Point aDocPt( PixelToLogic( rPixPnt ) ); 279 if( rSh.ChgCurrPam( aDocPt ) || rSh.IsOverReadOnlyPos( aDocPt ) ) 280 return 0; 281 282 SdrObject *pObj = NULL; 283 const ObjCntType eType = rSh.GetObjCntType( aDocPt, pObj ); 284 285 //Drop auf OutlinerView (TextEdit im Drawing) soll diese selbst entscheiden! 286 if( pObj ) 287 { 288 OutlinerView* pOLV = rSh.GetDrawView()->GetTextEditOutlinerView(); 289 if ( pOLV ) 290 { 291 Rectangle aRect( pOLV->GetOutputArea() ); 292 aRect.Union( pObj->GetLogicRect() ); 293 const Point aPos = pOLV->GetWindow()->PixelToLogic( rPixPnt ); 294 if( aRect.IsInside( aPos ) ) 295 return 0; 296 } 297 } 298 299 //Auf was wollen wir denn gerade droppen? 300 sal_uInt16 nDropDestination = 0; 301 302 //Sonst etwas aus der DrawingEngine getroffen? 303 if( OBJCNT_NONE != eType ) 304 { 305 switch ( eType ) 306 { 307 case OBJCNT_GRF: 308 { 309 sal_Bool bLink, 310 bIMap = 0 != rSh.GetFmtFromObj( aDocPt )->GetURL().GetMap(); 311 String aDummy; 312 rSh.GetGrfAtPos( aDocPt, aDummy, bLink ); 313 if ( bLink && bIMap ) 314 nDropDestination = EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP; 315 else if ( bLink ) 316 nDropDestination = EXCHG_DEST_DOC_LNKD_GRAPHOBJ; 317 else if ( bIMap ) 318 nDropDestination = EXCHG_DEST_DOC_GRAPH_W_IMAP; 319 else 320 nDropDestination = EXCHG_DEST_DOC_GRAPHOBJ; 321 } 322 break; 323 case OBJCNT_FLY: 324 if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) 325 nDropDestination = EXCHG_DEST_DOC_TEXTFRAME_WEB; 326 else 327 nDropDestination = EXCHG_DEST_DOC_TEXTFRAME; 328 break; 329 case OBJCNT_OLE: nDropDestination = EXCHG_DEST_DOC_OLEOBJ; break; 330 case OBJCNT_CONTROL: /* no Action avail */ 331 case OBJCNT_SIMPLE: nDropDestination = EXCHG_DEST_DOC_DRAWOBJ; break; 332 case OBJCNT_URLBUTTON: nDropDestination = EXCHG_DEST_DOC_URLBUTTON; break; 333 case OBJCNT_GROUPOBJ: nDropDestination = EXCHG_DEST_DOC_GROUPOBJ; break; 334 335 default: ASSERT( !this, "new ObjectType?" ); 336 } 337 } 338 if ( !nDropDestination ) 339 { 340 if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) 341 nDropDestination = EXCHG_DEST_SWDOC_FREE_AREA_WEB; 342 else 343 nDropDestination = EXCHG_DEST_SWDOC_FREE_AREA; 344 } 345 if( ppObj ) 346 *ppObj = pObj; 347 return nDropDestination; 348 } 349 350 sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt ) 351 { 352 if( rEvt.mbLeaving ) 353 { 354 DropCleanup(); 355 return rEvt.mnAction; 356 } 357 358 if( rView.GetDocShell()->IsReadOnly() ) 359 return DND_ACTION_NONE; 360 361 SwWrtShell &rSh = rView.GetWrtShell(); 362 363 Point aPixPt( rEvt.maPosPixel ); 364 365 // If the cursor is near the inner boundary 366 // we attempt to scroll towards the desired direction. 367 Point aPoint; 368 Rectangle aWin(aPoint,GetOutputSizePixel()); 369 const int nMargin = 10; 370 aWin.Left() += nMargin; 371 aWin.Top() += nMargin; 372 aWin.Right() -= nMargin; 373 aWin.Bottom() -= nMargin; 374 if(!aWin.IsInside(aPixPt)) { 375 static sal_uLong last_tick = 0; 376 sal_uLong current_tick = Time::GetSystemTicks(); 377 if((current_tick-last_tick) > 500) { 378 last_tick = current_tick; 379 if(!bOldIdleSet) { 380 bOldIdle = rSh.GetViewOptions()->IsIdle(); 381 ((SwViewOption *)rSh.GetViewOptions())->SetIdle(sal_False); 382 bOldIdleSet = sal_True; 383 } 384 CleanupDropUserMarker(); 385 if(aPixPt.X() > aWin.Right()) aPixPt.X() += nMargin; 386 if(aPixPt.X() < aWin.Left()) aPixPt.X() -= nMargin; 387 if(aPixPt.Y() > aWin.Bottom()) aPixPt.Y() += nMargin; 388 if(aPixPt.Y() < aWin.Top()) aPixPt.Y() -= nMargin; 389 Point aDocPt(PixelToLogic(aPixPt)); 390 SwRect rect(aDocPt,Size(1,1)); 391 rSh.MakeVisible(rect); 392 } 393 } 394 395 if(bOldIdleSet) { 396 ((SwViewOption *)rSh.GetViewOptions())->SetIdle( bOldIdle ); 397 bOldIdleSet = sal_False; 398 } 399 400 SdrObject *pObj = NULL; 401 m_nDropDestination = GetDropDestination( aPixPt, &pObj ); 402 if( !m_nDropDestination ) 403 return DND_ACTION_NONE; 404 405 sal_uInt16 nEventAction; 406 sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT 407 : rEvt.mnAction; 408 409 m_nDropAction = SotExchange::GetExchangeAction( 410 GetDataFlavorExVector(), 411 m_nDropDestination, 412 rEvt.mnAction, 413 //!! rEvt.GetSourceOptions(), 414 nUserOpt, m_nDropFormat, nEventAction ); 415 416 if( EXCHG_INOUT_ACTION_NONE != m_nDropAction ) 417 { 418 const Point aDocPt( PixelToLogic( aPixPt ) ); 419 420 //Bei den default Aktionen wollen wir noch ein bischen mitreden. 421 SwModule *pMod = SW_MOD(); 422 if( pMod->pDragDrop ) 423 { 424 sal_Bool bCleanup = sal_False; 425 //Zeichenobjekte in Kopf-/Fusszeilen sind nicht erlaubt 426 427 SwWrtShell *pSrcSh = pMod->pDragDrop->GetShell(); 428 if( (pSrcSh->GetSelFrmType() == FRMTYPE_DRAWOBJ) && 429 pSrcSh->IsSelContainsControl() && 430 (rSh.GetFrmType( &aDocPt, sal_False ) & (FRMTYPE_HEADER|FRMTYPE_FOOTER)) ) 431 { 432 bCleanup = sal_True; 433 } 434 // keine positionsgeschuetzten Objecte verschieben! 435 else if( DND_ACTION_MOVE == rEvt.mnAction && 436 pSrcSh->IsSelObjProtected( FLYPROTECT_POS ) ) 437 { 438 bCleanup = sal_True; 439 } 440 else if( rEvt.mbDefault ) 441 { 442 // JP 13.08.98: internes Drag&Drop: bei gleichem Doc ein Move 443 // ansonten ein Copy - Task 54974 444 nEventAction = pSrcSh->GetDoc() == rSh.GetDoc() 445 ? DND_ACTION_MOVE 446 : DND_ACTION_COPY; 447 } 448 if ( bCleanup ) 449 { 450 CleanupDropUserMarker(); 451 rSh.UnSetVisCrsr(); 452 return DND_ACTION_NONE; 453 } 454 } 455 else 456 { 457 //D&D von ausserhalb des SW soll per default ein Copy sein. 458 if( EXCHG_IN_ACTION_DEFAULT == nEventAction && 459 DND_ACTION_MOVE == rEvt.mnAction ) 460 nEventAction = DND_ACTION_COPY; 461 462 if( (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE == m_nDropFormat && 463 EXCHG_IN_ACTION_LINK == m_nDropAction) || 464 SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE == m_nDropFormat ) 465 { 466 SdrMarkView* pMView = PTR_CAST( SdrMarkView, rSh.GetDrawView() ); 467 if( pMView && !pMView->IsDesignMode() ) 468 return DND_ACTION_NONE; 469 } 470 } 471 472 if ( EXCHG_IN_ACTION_DEFAULT != nEventAction ) 473 nUserOpt = (sal_Int8)nEventAction; 474 475 // show DropCursor or UserMarker ? 476 if( EXCHG_DEST_SWDOC_FREE_AREA_WEB == m_nDropDestination || 477 EXCHG_DEST_SWDOC_FREE_AREA == m_nDropDestination ) 478 { 479 CleanupDropUserMarker(); 480 SwContentAtPos aCont( SwContentAtPos::SW_CONTENT_CHECK ); 481 if(rSh.GetContentAtPos(aDocPt, aCont)) 482 rSh.SwCrsrShell::SetVisCrsr( aDocPt ); 483 } 484 else 485 { 486 rSh.UnSetVisCrsr(); 487 488 if ( pUserMarkerObj != pObj ) 489 { 490 CleanupDropUserMarker(); 491 pUserMarkerObj = pObj; 492 493 if(pUserMarkerObj) 494 { 495 pUserMarker = new SdrDropMarkerOverlay( *rSh.GetDrawView(), *pUserMarkerObj ); 496 } 497 } 498 } 499 return nUserOpt; 500 } 501 502 CleanupDropUserMarker(); 503 rSh.UnSetVisCrsr(); 504 //!! return SFX_APP()->AcceptDrop( rEvt ); 505 return DND_ACTION_NONE; 506 } 507 508 509 IMPL_LINK( SwEditWin, DDHandler, Timer *, EMPTYARG ) 510 { 511 bDDTimerStarted = sal_False; 512 aTimer.Stop(); 513 aTimer.SetTimeout(240); 514 bMBPressed = sal_False; 515 ReleaseMouse(); 516 bFrmDrag = sal_False; 517 518 if ( rView.GetViewFrame() ) 519 { 520 bExecuteDrag = sal_True; 521 StartExecuteDrag(); 522 } 523 return 0; 524 } 525 526 527 528