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