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 ) || rSh.IsOverReadOnlyPos( aDocPt ) ) 276 return 0; 277 278 SdrObject *pObj = NULL; 279 const ObjCntType eType = rSh.GetObjCntType( aDocPt, pObj ); 280 281 //Drop auf OutlinerView (TextEdit im Drawing) soll diese selbst entscheiden! 282 if( pObj ) 283 { 284 OutlinerView* pOLV = rSh.GetDrawView()->GetTextEditOutlinerView(); 285 if ( pOLV ) 286 { 287 Rectangle aRect( pOLV->GetOutputArea() ); 288 aRect.Union( pObj->GetLogicRect() ); 289 const Point aPos = pOLV->GetWindow()->PixelToLogic( rPixPnt ); 290 if( aRect.IsInside( aPos ) ) 291 return 0; 292 } 293 } 294 295 //Auf was wollen wir denn gerade droppen? 296 sal_uInt16 nDropDestination = 0; 297 298 //Sonst etwas aus der DrawingEngine getroffen? 299 if( OBJCNT_NONE != eType ) 300 { 301 switch ( eType ) 302 { 303 case OBJCNT_GRF: 304 { 305 sal_Bool bLink, 306 bIMap = 0 != rSh.GetFmtFromObj( aDocPt )->GetURL().GetMap(); 307 String aDummy; 308 rSh.GetGrfAtPos( aDocPt, aDummy, bLink ); 309 if ( bLink && bIMap ) 310 nDropDestination = EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP; 311 else if ( bLink ) 312 nDropDestination = EXCHG_DEST_DOC_LNKD_GRAPHOBJ; 313 else if ( bIMap ) 314 nDropDestination = EXCHG_DEST_DOC_GRAPH_W_IMAP; 315 else 316 nDropDestination = EXCHG_DEST_DOC_GRAPHOBJ; 317 } 318 break; 319 case OBJCNT_FLY: 320 if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) 321 nDropDestination = EXCHG_DEST_DOC_TEXTFRAME_WEB; 322 else 323 nDropDestination = EXCHG_DEST_DOC_TEXTFRAME; 324 break; 325 case OBJCNT_OLE: nDropDestination = EXCHG_DEST_DOC_OLEOBJ; break; 326 case OBJCNT_CONTROL: /* no Action avail */ 327 case OBJCNT_SIMPLE: nDropDestination = EXCHG_DEST_DOC_DRAWOBJ; break; 328 case OBJCNT_URLBUTTON: nDropDestination = EXCHG_DEST_DOC_URLBUTTON; break; 329 case OBJCNT_GROUPOBJ: nDropDestination = EXCHG_DEST_DOC_GROUPOBJ; break; 330 331 default: ASSERT( !this, "new ObjectType?" ); 332 } 333 } 334 if ( !nDropDestination ) 335 { 336 if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) 337 nDropDestination = EXCHG_DEST_SWDOC_FREE_AREA_WEB; 338 else 339 nDropDestination = EXCHG_DEST_SWDOC_FREE_AREA; 340 } 341 if( ppObj ) 342 *ppObj = pObj; 343 return nDropDestination; 344 } 345 346 sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt ) 347 { 348 if( rEvt.mbLeaving ) 349 { 350 DropCleanup(); 351 return rEvt.mnAction; 352 } 353 354 if( rView.GetDocShell()->IsReadOnly() ) 355 return DND_ACTION_NONE; 356 357 SwWrtShell &rSh = rView.GetWrtShell(); 358 359 Point aPixPt( rEvt.maPosPixel ); 360 361 // If the cursor is near the inner boundary 362 // we attempt to scroll towards the desired direction. 363 Point aPoint; 364 Rectangle aWin(aPoint,GetOutputSizePixel()); 365 const int nMargin = 10; 366 aWin.Left() += nMargin; 367 aWin.Top() += nMargin; 368 aWin.Right() -= nMargin; 369 aWin.Bottom() -= nMargin; 370 if(!aWin.IsInside(aPixPt)) { 371 static sal_uLong last_tick = 0; 372 sal_uLong current_tick = Time::GetSystemTicks(); 373 if((current_tick-last_tick) > 500) { 374 last_tick = current_tick; 375 if(!bOldIdleSet) { 376 bOldIdle = rSh.GetViewOptions()->IsIdle(); 377 ((SwViewOption *)rSh.GetViewOptions())->SetIdle(sal_False); 378 bOldIdleSet = sal_True; 379 } 380 CleanupDropUserMarker(); 381 if(aPixPt.X() > aWin.Right()) aPixPt.X() += nMargin; 382 if(aPixPt.X() < aWin.Left()) aPixPt.X() -= nMargin; 383 if(aPixPt.Y() > aWin.Bottom()) aPixPt.Y() += nMargin; 384 if(aPixPt.Y() < aWin.Top()) aPixPt.Y() -= nMargin; 385 Point aDocPt(PixelToLogic(aPixPt)); 386 SwRect rect(aDocPt,Size(1,1)); 387 rSh.MakeVisible(rect); 388 } 389 } 390 391 if(bOldIdleSet) { 392 ((SwViewOption *)rSh.GetViewOptions())->SetIdle( bOldIdle ); 393 bOldIdleSet = sal_False; 394 } 395 396 SdrObject *pObj = NULL; 397 m_nDropDestination = GetDropDestination( aPixPt, &pObj ); 398 if( !m_nDropDestination ) 399 return DND_ACTION_NONE; 400 401 sal_uInt16 nEventAction; 402 sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT 403 : rEvt.mnAction; 404 405 m_nDropAction = SotExchange::GetExchangeAction( 406 GetDataFlavorExVector(), 407 m_nDropDestination, 408 rEvt.mnAction, 409 //!! rEvt.GetSourceOptions(), 410 nUserOpt, m_nDropFormat, nEventAction ); 411 412 if( EXCHG_INOUT_ACTION_NONE != m_nDropAction ) 413 { 414 const Point aDocPt( PixelToLogic( aPixPt ) ); 415 416 //Bei den default Aktionen wollen wir noch ein bischen mitreden. 417 SwModule *pMod = SW_MOD(); 418 if( pMod->pDragDrop ) 419 { 420 sal_Bool bCleanup = sal_False; 421 //Zeichenobjekte in Kopf-/Fusszeilen sind nicht erlaubt 422 423 SwWrtShell *pSrcSh = pMod->pDragDrop->GetShell(); 424 if( (pSrcSh->GetSelFrmType() == FRMTYPE_DRAWOBJ) && 425 pSrcSh->IsSelContainsControl() && 426 (rSh.GetFrmType( &aDocPt, sal_False ) & (FRMTYPE_HEADER|FRMTYPE_FOOTER)) ) 427 { 428 bCleanup = sal_True; 429 } 430 // keine positionsgeschuetzten Objecte verschieben! 431 else if( DND_ACTION_MOVE == rEvt.mnAction && 432 pSrcSh->IsSelObjProtected( FLYPROTECT_POS ) ) 433 { 434 bCleanup = sal_True; 435 } 436 else if( rEvt.mbDefault ) 437 { 438 // JP 13.08.98: internes Drag&Drop: bei gleichem Doc ein Move 439 // ansonten ein Copy - Task 54974 440 nEventAction = pSrcSh->GetDoc() == rSh.GetDoc() 441 ? DND_ACTION_MOVE 442 : DND_ACTION_COPY; 443 } 444 if ( bCleanup ) 445 { 446 CleanupDropUserMarker(); 447 rSh.UnSetVisCrsr(); 448 return DND_ACTION_NONE; 449 } 450 } 451 else 452 { 453 //D&D von ausserhalb des SW soll per default ein Copy sein. 454 if( EXCHG_IN_ACTION_DEFAULT == nEventAction && 455 DND_ACTION_MOVE == rEvt.mnAction ) 456 nEventAction = DND_ACTION_COPY; 457 458 if( (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE == m_nDropFormat && 459 EXCHG_IN_ACTION_LINK == m_nDropAction) || 460 SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE == m_nDropFormat ) 461 { 462 SdrMarkView* pMView = PTR_CAST( SdrMarkView, rSh.GetDrawView() ); 463 if( pMView && !pMView->IsDesignMode() ) 464 return DND_ACTION_NONE; 465 } 466 } 467 468 if ( EXCHG_IN_ACTION_DEFAULT != nEventAction ) 469 nUserOpt = (sal_Int8)nEventAction; 470 471 // show DropCursor or UserMarker ? 472 if( EXCHG_DEST_SWDOC_FREE_AREA_WEB == m_nDropDestination || 473 EXCHG_DEST_SWDOC_FREE_AREA == m_nDropDestination ) 474 { 475 CleanupDropUserMarker(); 476 SwContentAtPos aCont( SwContentAtPos::SW_CONTENT_CHECK ); 477 if(rSh.GetContentAtPos(aDocPt, aCont)) 478 rSh.SwCrsrShell::SetVisCrsr( aDocPt ); 479 } 480 else 481 { 482 rSh.UnSetVisCrsr(); 483 484 if ( pUserMarkerObj != pObj ) 485 { 486 CleanupDropUserMarker(); 487 pUserMarkerObj = pObj; 488 489 if(pUserMarkerObj) 490 { 491 pUserMarker = new SdrDropMarkerOverlay( *rSh.GetDrawView(), *pUserMarkerObj ); 492 } 493 } 494 } 495 return nUserOpt; 496 } 497 498 CleanupDropUserMarker(); 499 rSh.UnSetVisCrsr(); 500 //!! return SFX_APP()->AcceptDrop( rEvt ); 501 return DND_ACTION_NONE; 502 } 503 504 505 IMPL_LINK( SwEditWin, DDHandler, Timer *, EMPTYARG ) 506 { 507 bDDTimerStarted = sal_False; 508 aTimer.Stop(); 509 aTimer.SetTimeout(240); 510 bMBPressed = sal_False; 511 ReleaseMouse(); 512 bFrmDrag = sal_False; 513 514 if ( rView.GetViewFrame() ) 515 { 516 bExecuteDrag = sal_True; 517 StartExecuteDrag(); 518 } 519 return 0; 520 } 521 522 523 524