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