1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: edtdd.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
38 #include <svx/svdview.hxx>
39 #include <svx/outliner.hxx>
40 //#ifndef _SVDVMARK_HXX //autogen
41 //#include <svx/svdvmark.hxx>
43 #include <svx/svdobj.hxx>
44 #include <sot/exchange.hxx>
45 #include <sot/formats.hxx>
46 #include <sfx2/bindings.hxx>
48 #include <sfx2/viewfrm.hxx>
56 #include <viewopt.hxx>
57 #include <swdtflvr.hxx>
58 #include <swmodule.hxx>
65 using namespace ::com::sun::star
;
67 // no include "dbgoutsw.hxx" here!!!!!!
69 extern BOOL bNoInterrupt
;
71 extern BOOL bDDTimerStarted
;
73 BOOL bExecuteDrag
= FALSE
;
75 void SwEditWin::StartDDTimer()
77 aTimer
.SetTimeoutHdl(LINK(this, SwEditWin
, DDHandler
));
78 aTimer
.SetTimeout(480);
80 bDDTimerStarted
= TRUE
;
84 void SwEditWin::StopDDTimer(SwWrtShell
*pSh
, const Point
&rPt
)
87 bDDTimerStarted
= FALSE
;
88 if(!pSh
->IsSelFrmMode())
89 (pSh
->*pSh
->fnSetCrsr
)(&rPt
,FALSE
);
90 aTimer
.SetTimeoutHdl(LINK(this,SwEditWin
, TimerHandler
));
93 void SwEditWin::StartDrag( sal_Int8
/*nAction*/, const Point
& rPosPixel
)
95 SwWrtShell
&rSh
= rView
.GetWrtShell();
96 if( rSh
.GetDrawView() )
98 CommandEvent
aDragEvent( rPosPixel
, COMMAND_STARTDRAG
, TRUE
);
99 if( rSh
.GetDrawView()->Command( aDragEvent
, this ) )
101 rView
.GetViewFrame()->GetBindings().InvalidateAll(FALSE
);
102 return; // Event von der SdrView ausgewertet
106 if ( !pApplyTempl
&& !rSh
.IsDrawCreate() && !IsDrawAction())
108 BOOL bStart
= FALSE
, bDelSelect
= FALSE
;
109 SdrObject
*pObj
= NULL
;
110 Point
aDocPos( PixelToLogic( rPosPixel
) );
111 if ( !rSh
.IsInSelect() && rSh
.ChgCurrPam( aDocPos
, TRUE
, TRUE
))
112 //Wir sind nicht beim Selektieren und stehen auf einer
115 else if ( !bFrmDrag
&& rSh
.IsSelFrmMode() &&
116 rSh
.IsInsideSelectedObj( aDocPos
) )
118 //Wir sind nicht am internen Draggen und stehen auf
119 //einem Objekt (Rahmen, Zeichenobjekt)
123 else if( !bFrmDrag
&& rView
.GetDocShell()->IsReadOnly() &&
124 OBJCNT_NONE
!= rSh
.GetObjCntType( aDocPos
, pObj
))
127 if( rSh
.SelectObj( aDocPos
, 0, pObj
))
128 bStart
= bDelSelect
= TRUE
;
134 SwContentAtPos
aSwContentAtPos( SwContentAtPos::SW_INETATTR
);
135 bStart
= rSh
.GetContentAtPos( aDocPos
,
140 if ( bStart
&& !bIsInDrag
)
146 SwEditWin::nDDStartPosY
= aDocPos
.Y();
147 SwEditWin::nDDStartPosX
= aDocPos
.X();
159 void SwEditWin::StartExecuteDrag()
161 if( !bExecuteDrag
|| bIsInDrag
)
166 SwTransferable
* pTransfer
= new SwTransferable( rView
.GetWrtShell() );
168 datatransfer::XTransferable
> xRef( pTransfer
);
170 pTransfer
->StartDrag( this, aMovePos
);
173 void SwEditWin::DragFinished()
176 aTimer
.SetTimeoutHdl( LINK(this,SwEditWin
, TimerHandler
) );
181 void SwEditWin::DropCleanup()
183 SwWrtShell
&rSh
= rView
.GetWrtShell();
185 // Stati zuruecksetzen
186 bNoInterrupt
= FALSE
;
189 ((SwViewOption
*)rSh
.GetViewOptions())->SetIdle( bOldIdle
);
193 CleanupDropUserMarker();
199 void SwEditWin::CleanupDropUserMarker()
211 void lcl_SelectShellForDrop( SwView
&rView
)
213 if ( !rView
.GetCurShell() )
217 sal_Int8
SwEditWin::ExecuteDrop( const ExecuteDropEvent
& rEvt
)
219 ::lcl_SelectShellForDrop( GetView() );
221 sal_Int8 nRet
= DND_ACTION_NONE
;
223 //Ein Drop auf eine offene OutlinerView geht uns nichts an (siehe auch QueryDrop)
224 SwWrtShell
&rSh
= rView
.GetWrtShell();
225 const Point
aDocPt( PixelToLogic( rEvt
.maPosPixel
));
228 rSh
.GetObjCntType( aDocPt
, pObj
);
230 if( pObj
&& 0 != ( pOLV
= rSh
.GetDrawView()->GetTextEditOutlinerView() ))
232 Rectangle
aRect( pOLV
->GetOutputArea() );
233 aRect
.Union( pObj
->GetLogicRect() );
234 const Point aPos
= pOLV
->GetWindow()->PixelToLogic(rEvt
.maPosPixel
);
235 if ( aRect
.IsInside(aPos
) )
237 rSh
.StartAllAction();
238 //!! sal_Int8 nRet = DND_ACTION_NONE/*pOLV->ExecuteDrop( rEvt )*/;
245 // dvo 2002-05-27, #99027#: There's a special treatment for file lists with a single
246 // element, that depends on the actual content of the
247 // Transferable to be accessible. Since the transferable
248 // may only be accessed after the drop has been accepted
249 // (according to KA due to Java D&D), we'll have to
250 // reevaluate the drop action once more _with_ the
253 sal_Int8 nUserOpt
= rEvt
.mbDefault
? EXCHG_IN_ACTION_DEFAULT
255 m_nDropAction
= SotExchange::GetExchangeAction(
256 GetDataFlavorExVector(),
259 //!! rEvt.GetSourceOptions(),
260 nUserOpt
, m_nDropFormat
, nEventAction
, 0,
261 &rEvt
.maDropEvent
.Transferable
);
264 TransferableDataHelper
aData( rEvt
.maDropEvent
.Transferable
);
265 nRet
= rEvt
.mnAction
;
266 if( !SwTransferable::PasteData( aData
, rSh
, m_nDropAction
, m_nDropFormat
,
267 m_nDropDestination
, FALSE
, rEvt
.mbDefault
, &aDocPt
, nRet
))
268 //!! nRet = SFX_APP()->ExecuteDrop( rEvt );
269 nRet
= DND_ACTION_NONE
;
270 else if ( SW_MOD()->pDragDrop
)
271 //Bei internem D&D nicht mehr aufraeumen!
272 SW_MOD()->pDragDrop
->SetCleanUp( FALSE
);
278 USHORT
SwEditWin::GetDropDestination( const Point
& rPixPnt
, SdrObject
** ppObj
)
280 SwWrtShell
&rSh
= rView
.GetWrtShell();
281 const Point
aDocPt( PixelToLogic( rPixPnt
) );
282 if( rSh
.ChgCurrPam( aDocPt
) || rSh
.IsOverReadOnlyPos( aDocPt
) )
285 SdrObject
*pObj
= NULL
;
286 const ObjCntType eType
= rSh
.GetObjCntType( aDocPt
, pObj
);
288 //Drop auf OutlinerView (TextEdit im Drawing) soll diese selbst entscheiden!
291 OutlinerView
* pOLV
= rSh
.GetDrawView()->GetTextEditOutlinerView();
294 Rectangle
aRect( pOLV
->GetOutputArea() );
295 aRect
.Union( pObj
->GetLogicRect() );
296 const Point aPos
= pOLV
->GetWindow()->PixelToLogic( rPixPnt
);
297 if( aRect
.IsInside( aPos
) )
302 //Auf was wollen wir denn gerade droppen?
303 USHORT nDropDestination
= 0;
305 //Sonst etwas aus der DrawingEngine getroffen?
306 if( OBJCNT_NONE
!= eType
)
313 bIMap
= 0 != rSh
.GetFmtFromObj( aDocPt
)->GetURL().GetMap();
315 rSh
.GetGrfAtPos( aDocPt
, aDummy
, bLink
);
316 if ( bLink
&& bIMap
)
317 nDropDestination
= EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP
;
319 nDropDestination
= EXCHG_DEST_DOC_LNKD_GRAPHOBJ
;
321 nDropDestination
= EXCHG_DEST_DOC_GRAPH_W_IMAP
;
323 nDropDestination
= EXCHG_DEST_DOC_GRAPHOBJ
;
327 if( rSh
.GetView().GetDocShell()->ISA(SwWebDocShell
) )
328 nDropDestination
= EXCHG_DEST_DOC_TEXTFRAME_WEB
;
330 nDropDestination
= EXCHG_DEST_DOC_TEXTFRAME
;
332 case OBJCNT_OLE
: nDropDestination
= EXCHG_DEST_DOC_OLEOBJ
; break;
333 case OBJCNT_CONTROL
: /* no Action avail */
334 case OBJCNT_SIMPLE
: nDropDestination
= EXCHG_DEST_DOC_DRAWOBJ
; break;
335 case OBJCNT_URLBUTTON
: nDropDestination
= EXCHG_DEST_DOC_URLBUTTON
; break;
336 case OBJCNT_GROUPOBJ
: nDropDestination
= EXCHG_DEST_DOC_GROUPOBJ
; break;
338 default: ASSERT( !this, "new ObjectType?" );
341 if ( !nDropDestination
)
343 if( rSh
.GetView().GetDocShell()->ISA(SwWebDocShell
) )
344 nDropDestination
= EXCHG_DEST_SWDOC_FREE_AREA_WEB
;
346 nDropDestination
= EXCHG_DEST_SWDOC_FREE_AREA
;
350 return nDropDestination
;
353 sal_Int8
SwEditWin::AcceptDrop( const AcceptDropEvent
& rEvt
)
358 return rEvt
.mnAction
;
361 if( rView
.GetDocShell()->IsReadOnly() )
362 return DND_ACTION_NONE
;
364 SwWrtShell
&rSh
= rView
.GetWrtShell();
366 Point
aPixPt( rEvt
.maPosPixel
);
368 // If the cursor is near the inner boundary
369 // we attempt to scroll towards the desired direction.
371 Rectangle
aWin(aPoint
,GetOutputSizePixel());
372 const int nMargin
= 10;
373 aWin
.Left() += nMargin
;
374 aWin
.Top() += nMargin
;
375 aWin
.Right() -= nMargin
;
376 aWin
.Bottom() -= nMargin
;
377 if(!aWin
.IsInside(aPixPt
)) {
378 static ULONG last_tick
= 0;
379 ULONG current_tick
= Time::GetSystemTicks();
380 if((current_tick
-last_tick
) > 500) {
381 last_tick
= current_tick
;
383 bOldIdle
= rSh
.GetViewOptions()->IsIdle();
384 ((SwViewOption
*)rSh
.GetViewOptions())->SetIdle(FALSE
);
387 CleanupDropUserMarker();
388 if(aPixPt
.X() > aWin
.Right()) aPixPt
.X() += nMargin
;
389 if(aPixPt
.X() < aWin
.Left()) aPixPt
.X() -= nMargin
;
390 if(aPixPt
.Y() > aWin
.Bottom()) aPixPt
.Y() += nMargin
;
391 if(aPixPt
.Y() < aWin
.Top()) aPixPt
.Y() -= nMargin
;
392 Point
aDocPt(PixelToLogic(aPixPt
));
393 SwRect
rect(aDocPt
,Size(1,1));
394 rSh
.MakeVisible(rect
);
399 ((SwViewOption
*)rSh
.GetViewOptions())->SetIdle( bOldIdle
);
403 SdrObject
*pObj
= NULL
;
404 m_nDropDestination
= GetDropDestination( aPixPt
, &pObj
);
405 if( !m_nDropDestination
)
406 return DND_ACTION_NONE
;
409 sal_Int8 nUserOpt
= rEvt
.mbDefault
? EXCHG_IN_ACTION_DEFAULT
412 m_nDropAction
= SotExchange::GetExchangeAction(
413 GetDataFlavorExVector(),
416 //!! rEvt.GetSourceOptions(),
417 nUserOpt
, m_nDropFormat
, nEventAction
);
419 if( EXCHG_INOUT_ACTION_NONE
!= m_nDropAction
)
421 const Point
aDocPt( PixelToLogic( aPixPt
) );
423 //Bei den default Aktionen wollen wir noch ein bischen mitreden.
424 SwModule
*pMod
= SW_MOD();
425 if( pMod
->pDragDrop
)
427 BOOL bCleanup
= FALSE
;
428 //Zeichenobjekte in Kopf-/Fusszeilen sind nicht erlaubt
430 SwWrtShell
*pSrcSh
= pMod
->pDragDrop
->GetShell();
431 if( (pSrcSh
->GetSelFrmType() == FRMTYPE_DRAWOBJ
) &&
432 pSrcSh
->IsSelContainsControl() &&
433 (rSh
.GetFrmType( &aDocPt
, FALSE
) & (FRMTYPE_HEADER
|FRMTYPE_FOOTER
)) )
437 // keine positionsgeschuetzten Objecte verschieben!
438 else if( DND_ACTION_MOVE
== rEvt
.mnAction
&&
439 pSrcSh
->IsSelObjProtected( FLYPROTECT_POS
) )
443 else if( rEvt
.mbDefault
)
445 // JP 13.08.98: internes Drag&Drop: bei gleichem Doc ein Move
446 // ansonten ein Copy - Task 54974
447 nEventAction
= pSrcSh
->GetDoc() == rSh
.GetDoc()
453 CleanupDropUserMarker();
455 return DND_ACTION_NONE
;
460 //D&D von ausserhalb des SW soll per default ein Copy sein.
461 if( EXCHG_IN_ACTION_DEFAULT
== nEventAction
&&
462 DND_ACTION_MOVE
== rEvt
.mnAction
)
463 nEventAction
= DND_ACTION_COPY
;
465 if( (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE
== m_nDropFormat
&&
466 EXCHG_IN_ACTION_LINK
== m_nDropAction
) ||
467 SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE
== m_nDropFormat
)
469 SdrMarkView
* pMView
= PTR_CAST( SdrMarkView
, rSh
.GetDrawView() );
470 if( pMView
&& !pMView
->IsDesignMode() )
471 return DND_ACTION_NONE
;
475 if ( EXCHG_IN_ACTION_DEFAULT
!= nEventAction
)
476 nUserOpt
= (sal_Int8
)nEventAction
;
478 // show DropCursor or UserMarker ?
479 if( EXCHG_DEST_SWDOC_FREE_AREA_WEB
== m_nDropDestination
||
480 EXCHG_DEST_SWDOC_FREE_AREA
== m_nDropDestination
)
482 CleanupDropUserMarker();
483 SwContentAtPos
aCont( SwContentAtPos::SW_CONTENT_CHECK
);
484 if(rSh
.GetContentAtPos(aDocPt
, aCont
))
485 rSh
.SwCrsrShell::SetVisCrsr( aDocPt
);
491 if ( pUserMarkerObj
!= pObj
)
493 CleanupDropUserMarker();
494 pUserMarkerObj
= pObj
;
498 pUserMarker
= new SdrDropMarkerOverlay( *rSh
.GetDrawView(), *pUserMarkerObj
);
505 CleanupDropUserMarker();
507 //!! return SFX_APP()->AcceptDrop( rEvt );
508 return DND_ACTION_NONE
;
512 IMPL_LINK( SwEditWin
, DDHandler
, Timer
*, EMPTYARG
)
514 bDDTimerStarted
= FALSE
;
516 aTimer
.SetTimeout(240);
521 if ( rView
.GetViewFrame() && rView
.GetViewFrame()->GetFrame() )