xref: /AOO41X/main/sw/source/ui/docvw/edtdd.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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