xref: /trunk/main/sw/source/ui/docvw/edtdd.cxx (revision 870262e3)
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 
StartDDTimer()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 
StopDDTimer(SwWrtShell * pSh,const Point & rPt)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 
StartDrag(sal_Int8,const Point & rPosPixel)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 
StartExecuteDrag()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 
DragFinished()166 void SwEditWin::DragFinished()
167 {
168 	DropCleanup();
169 	aTimer.SetTimeoutHdl( LINK(this,SwEditWin, TimerHandler) );
170 	bIsInDrag = sal_False;
171 }
172 
173 
DropCleanup()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 
CleanupDropUserMarker()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)
lcl_SelectShellForDrop(SwView & rView)204 void lcl_SelectShellForDrop( SwView &rView )
205 {
206 	if ( !rView.GetCurShell() )
207 		rView.SelectShell();
208 }
209 
ExecuteDrop(const ExecuteDropEvent & rEvt)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 
GetDropDestination(const Point & rPixPnt,SdrObject ** ppObj)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( sal_False, "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 
AcceptDrop(const AcceptDropEvent & rEvt)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 
IMPL_LINK(SwEditWin,DDHandler,Timer *,EMPTYARG)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