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