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