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