xref: /trunk/main/sw/source/ui/docvw/edtdd.cxx (revision 30b58845)
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 
StartDDTimer()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 
StopDDTimer(SwWrtShell * pSh,const Point & rPt)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 
StartDrag(sal_Int8,const Point & rPosPixel)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 
StartExecuteDrag()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 
DragFinished()162 void SwEditWin::DragFinished()
163 {
164 	DropCleanup();
165 	aTimer.SetTimeoutHdl( LINK(this,SwEditWin, TimerHandler) );
166 	bIsInDrag = sal_False;
167 }
168 
169 
DropCleanup()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 
CleanupDropUserMarker()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)
lcl_SelectShellForDrop(SwView & rView)200 void lcl_SelectShellForDrop( SwView &rView )
201 {
202 	if ( !rView.GetCurShell() )
203 		rView.SelectShell();
204 }
205 
ExecuteDrop(const ExecuteDropEvent & rEvt)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 
GetDropDestination(const Point & rPixPnt,SdrObject ** ppObj)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 
AcceptDrop(const AcceptDropEvent & rEvt)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 
IMPL_LINK(SwEditWin,DDHandler,Timer *,EMPTYARG)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