xref: /trunk/main/sw/source/ui/docvw/edtdd.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #include <hintids.hxx>
33 
34 
35 #include <svx/svdview.hxx>
36 #include <editeng/outliner.hxx>
37 //#ifndef _SVDVMARK_HXX //autogen
38 //#include <svx/svdvmark.hxx>
39 //#endif
40 #include <svx/svdobj.hxx>
41 #include <sot/exchange.hxx>
42 #include <sot/formats.hxx>
43 #include <sfx2/bindings.hxx>
44 
45 #include <sfx2/viewfrm.hxx>
46 #include <fmturl.hxx>
47 #include <frmfmt.hxx>
48 #include <wrtsh.hxx>
49 #include <edtwin.hxx>
50 #ifndef _VIEW_HXX
51 #include <view.hxx>
52 #endif
53 #include <viewopt.hxx>
54 #include <swdtflvr.hxx>
55 #include <swmodule.hxx>
56 #ifndef _DOCSH_HXX
57 #include <docsh.hxx>
58 #endif
59 #include <wdocsh.hxx>
60 #include <swundo.hxx>
61 
62 using namespace ::com::sun::star;
63 
64 // no include "dbgoutsw.hxx" here!!!!!!
65 
66 extern sal_Bool bNoInterrupt;
67 extern sal_Bool bFrmDrag;
68 extern sal_Bool bDDTimerStarted;
69 
70 sal_Bool bExecuteDrag = sal_False;
71 
72 void SwEditWin::StartDDTimer()
73 {
74     aTimer.SetTimeoutHdl(LINK(this, SwEditWin, DDHandler));
75     aTimer.SetTimeout(480);
76     aTimer.Start();
77     bDDTimerStarted = sal_True;
78 }
79 
80 
81 void SwEditWin::StopDDTimer(SwWrtShell *pSh, const Point &rPt)
82 {
83     aTimer.Stop();
84     bDDTimerStarted = sal_False;
85     if(!pSh->IsSelFrmMode())
86         (pSh->*pSh->fnSetCrsr)(&rPt,sal_False);
87     aTimer.SetTimeoutHdl(LINK(this,SwEditWin, TimerHandler));
88 }
89 
90 void SwEditWin::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel )
91 {
92     SwWrtShell &rSh = rView.GetWrtShell();
93     if( rSh.GetDrawView() )
94     {
95         CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True );
96         if( rSh.GetDrawView()->Command( aDragEvent, this ) )
97         {
98             rView.GetViewFrame()->GetBindings().InvalidateAll(sal_False);
99             return; // Event von der SdrView ausgewertet
100         }
101     }
102 
103     if ( !pApplyTempl && !rSh.IsDrawCreate() && !IsDrawAction())
104     {
105         sal_Bool bStart = sal_False, bDelSelect = sal_False;
106         SdrObject *pObj = NULL;
107         Point aDocPos( PixelToLogic( rPosPixel ) );
108         if ( !rSh.IsInSelect() && rSh.ChgCurrPam( aDocPos, sal_True, sal_True))
109             //Wir sind nicht beim Selektieren und stehen auf einer
110             //Selektion
111             bStart = sal_True;
112         else if ( !bFrmDrag && rSh.IsSelFrmMode() &&
113                     rSh.IsInsideSelectedObj( aDocPos ) )
114         {
115             //Wir sind nicht am internen Draggen und stehen auf
116             //einem Objekt (Rahmen, Zeichenobjekt)
117 
118             bStart = sal_True;
119         }
120         else if( !bFrmDrag && rView.GetDocShell()->IsReadOnly() &&
121                 OBJCNT_NONE != rSh.GetObjCntType( aDocPos, pObj ))
122         {
123             rSh.LockPaint();
124             if( rSh.SelectObj( aDocPos, 0, pObj ))
125                 bStart = bDelSelect = sal_True;
126             else
127                 rSh.UnlockPaint();
128         }
129         else
130         {
131             SwContentAtPos aSwContentAtPos( SwContentAtPos::SW_INETATTR );
132             bStart = rSh.GetContentAtPos( aDocPos,
133                         aSwContentAtPos,
134                         sal_False );
135         }
136 
137         if ( bStart && !bIsInDrag )
138         {
139             bMBPressed = sal_False;
140             ReleaseMouse();
141             bFrmDrag = sal_False;
142             bExecuteDrag = sal_True;
143             SwEditWin::nDDStartPosY = aDocPos.Y();
144             SwEditWin::nDDStartPosX = aDocPos.X();
145             aMovePos = aDocPos;
146             StartExecuteDrag();
147             if( bDelSelect )
148             {
149                 rSh.UnSelectFrm();
150                 rSh.UnlockPaint();
151             }
152         }
153     }
154 }
155 
156 void SwEditWin::StartExecuteDrag()
157 {
158     if( !bExecuteDrag || bIsInDrag )
159         return;
160 
161     bIsInDrag = sal_True;
162 
163     SwTransferable* pTransfer = new SwTransferable( rView.GetWrtShell() );
164     uno::Reference<
165         datatransfer::XTransferable > xRef( pTransfer );
166 
167     pTransfer->StartDrag( this, aMovePos );
168 }
169 
170 void SwEditWin::DragFinished()
171 {
172     DropCleanup();
173     aTimer.SetTimeoutHdl( LINK(this,SwEditWin, TimerHandler) );
174     bIsInDrag = sal_False;
175 }
176 
177 
178 void SwEditWin::DropCleanup()
179 {
180     SwWrtShell &rSh =  rView.GetWrtShell();
181 
182     // Stati zuruecksetzen
183     bNoInterrupt = sal_False;
184     if ( bOldIdleSet )
185     {
186         ((SwViewOption*)rSh.GetViewOptions())->SetIdle( bOldIdle );
187         bOldIdleSet = sal_False;
188     }
189     if ( pUserMarker )
190         CleanupDropUserMarker();
191     else
192         rSh.UnSetVisCrsr();
193 
194 }
195 
196 void SwEditWin::CleanupDropUserMarker()
197 {
198     if ( pUserMarker )
199     {
200         delete pUserMarker;
201         pUserMarker = 0;
202         pUserMarkerObj = 0;
203     }
204 }
205 
206 
207 //Messehack (MA,MBA)
208 void lcl_SelectShellForDrop( SwView &rView )
209 {
210     if ( !rView.GetCurShell() )
211         rView.SelectShell();
212 }
213 
214 sal_Int8 SwEditWin::ExecuteDrop( const ExecuteDropEvent& rEvt )
215 {
216     ::lcl_SelectShellForDrop( GetView() );
217     DropCleanup();
218     sal_Int8 nRet = DND_ACTION_NONE;
219 
220     //Ein Drop auf eine offene OutlinerView geht uns nichts an (siehe auch QueryDrop)
221     SwWrtShell &rSh = rView.GetWrtShell();
222     const Point aDocPt( PixelToLogic( rEvt.maPosPixel ));
223     SdrObject *pObj = 0;
224     OutlinerView* pOLV;
225     rSh.GetObjCntType( aDocPt, pObj );
226 
227     if( pObj && 0 != ( pOLV = rSh.GetDrawView()->GetTextEditOutlinerView() ))
228     {
229         Rectangle aRect( pOLV->GetOutputArea() );
230         aRect.Union( pObj->GetLogicRect() );
231         const Point aPos = pOLV->GetWindow()->PixelToLogic(rEvt.maPosPixel);
232         if ( aRect.IsInside(aPos) )
233         {
234             rSh.StartAllAction();
235 //!!            sal_Int8 nRet = DND_ACTION_NONE/*pOLV->ExecuteDrop( rEvt )*/;
236             rSh.EndAllAction();
237             return nRet;
238         }
239     }
240 
241 
242     // dvo 2002-05-27, #99027#: There's a special treatment for file lists with a single
243     //                          element, that depends on the actual content of the
244     //                          Transferable to be accessible. Since the transferable
245     //                          may only be accessed after the drop has been accepted
246     //                          (according to KA due to Java D&D), we'll have to
247     //                          reevaluate the drop action once more _with_ the
248     //                          Transferable.
249     sal_uInt16 nEventAction;
250     sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT
251                                        : rEvt.mnAction;
252     m_nDropAction = SotExchange::GetExchangeAction(
253                                 GetDataFlavorExVector(),
254                                 m_nDropDestination,
255                                 rEvt.mnAction,
256 //!!                                rEvt.GetSourceOptions(),
257                                 nUserOpt, m_nDropFormat, nEventAction, 0,
258                                 &rEvt.maDropEvent.Transferable );
259 
260 
261     TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
262     nRet = rEvt.mnAction;
263     if( !SwTransferable::PasteData( aData, rSh, m_nDropAction, m_nDropFormat,
264                                 m_nDropDestination, sal_False, rEvt.mbDefault, &aDocPt, nRet))
265 //!!    nRet = SFX_APP()->ExecuteDrop( rEvt );
266         nRet = DND_ACTION_NONE;
267     else if ( SW_MOD()->pDragDrop )
268         //Bei internem D&D nicht mehr aufraeumen!
269         SW_MOD()->pDragDrop->SetCleanUp( sal_False );
270 
271     return nRet;
272 }
273 
274 
275 sal_uInt16 SwEditWin::GetDropDestination( const Point& rPixPnt, SdrObject ** ppObj )
276 {
277     SwWrtShell &rSh = rView.GetWrtShell();
278     const Point aDocPt( PixelToLogic( rPixPnt ) );
279     if( rSh.ChgCurrPam( aDocPt ) || rSh.IsOverReadOnlyPos( aDocPt ) )
280         return 0;
281 
282     SdrObject *pObj = NULL;
283     const ObjCntType eType = rSh.GetObjCntType( aDocPt, pObj );
284 
285     //Drop auf OutlinerView (TextEdit im Drawing) soll diese selbst entscheiden!
286     if( pObj )
287     {
288         OutlinerView* pOLV = rSh.GetDrawView()->GetTextEditOutlinerView();
289         if ( pOLV )
290         {
291             Rectangle aRect( pOLV->GetOutputArea() );
292             aRect.Union( pObj->GetLogicRect() );
293             const Point aPos = pOLV->GetWindow()->PixelToLogic( rPixPnt );
294             if( aRect.IsInside( aPos ) )
295                 return 0;
296         }
297     }
298 
299     //Auf was wollen wir denn gerade droppen?
300     sal_uInt16 nDropDestination = 0;
301 
302     //Sonst etwas aus der DrawingEngine getroffen?
303     if( OBJCNT_NONE != eType )
304     {
305         switch ( eType )
306         {
307         case OBJCNT_GRF:
308             {
309                 sal_Bool bLink,
310                     bIMap = 0 != rSh.GetFmtFromObj( aDocPt )->GetURL().GetMap();
311                 String aDummy;
312                 rSh.GetGrfAtPos( aDocPt, aDummy, bLink );
313                 if ( bLink && bIMap )
314                     nDropDestination = EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP;
315                 else if ( bLink )
316                     nDropDestination = EXCHG_DEST_DOC_LNKD_GRAPHOBJ;
317                 else if ( bIMap )
318                     nDropDestination = EXCHG_DEST_DOC_GRAPH_W_IMAP;
319                 else
320                     nDropDestination = EXCHG_DEST_DOC_GRAPHOBJ;
321             }
322             break;
323         case OBJCNT_FLY:
324             if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) )
325                 nDropDestination = EXCHG_DEST_DOC_TEXTFRAME_WEB;
326             else
327                 nDropDestination = EXCHG_DEST_DOC_TEXTFRAME;
328             break;
329         case OBJCNT_OLE:        nDropDestination = EXCHG_DEST_DOC_OLEOBJ; break;
330         case OBJCNT_CONTROL:    /* no Action avail */
331         case OBJCNT_SIMPLE:     nDropDestination = EXCHG_DEST_DOC_DRAWOBJ; break;
332         case OBJCNT_URLBUTTON:  nDropDestination = EXCHG_DEST_DOC_URLBUTTON; break;
333         case OBJCNT_GROUPOBJ:   nDropDestination = EXCHG_DEST_DOC_GROUPOBJ;     break;
334 
335         default: ASSERT( !this, "new ObjectType?" );
336         }
337     }
338     if ( !nDropDestination )
339     {
340         if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) )
341             nDropDestination = EXCHG_DEST_SWDOC_FREE_AREA_WEB;
342         else
343             nDropDestination = EXCHG_DEST_SWDOC_FREE_AREA;
344     }
345     if( ppObj )
346         *ppObj = pObj;
347     return nDropDestination;
348 }
349 
350 sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt )
351 {
352     if( rEvt.mbLeaving )
353     {
354         DropCleanup();
355         return rEvt.mnAction;
356     }
357 
358     if( rView.GetDocShell()->IsReadOnly() )
359         return DND_ACTION_NONE;
360 
361     SwWrtShell &rSh = rView.GetWrtShell();
362 
363     Point aPixPt( rEvt.maPosPixel );
364 
365     // If the cursor is near the inner boundary
366     // we attempt to scroll towards the desired direction.
367     Point aPoint;
368     Rectangle aWin(aPoint,GetOutputSizePixel());
369     const int nMargin = 10;
370     aWin.Left() += nMargin;
371     aWin.Top() += nMargin;
372     aWin.Right() -= nMargin;
373     aWin.Bottom() -= nMargin;
374     if(!aWin.IsInside(aPixPt)) {
375         static sal_uLong last_tick = 0;
376         sal_uLong current_tick = Time::GetSystemTicks();
377         if((current_tick-last_tick) > 500) {
378             last_tick = current_tick;
379             if(!bOldIdleSet) {
380                 bOldIdle = rSh.GetViewOptions()->IsIdle();
381                 ((SwViewOption *)rSh.GetViewOptions())->SetIdle(sal_False);
382                 bOldIdleSet = sal_True;
383             }
384             CleanupDropUserMarker();
385             if(aPixPt.X() > aWin.Right()) aPixPt.X() += nMargin;
386             if(aPixPt.X() < aWin.Left()) aPixPt.X() -= nMargin;
387             if(aPixPt.Y() > aWin.Bottom()) aPixPt.Y() += nMargin;
388             if(aPixPt.Y() < aWin.Top()) aPixPt.Y() -= nMargin;
389             Point aDocPt(PixelToLogic(aPixPt));
390             SwRect rect(aDocPt,Size(1,1));
391             rSh.MakeVisible(rect);
392         }
393     }
394 
395     if(bOldIdleSet) {
396         ((SwViewOption *)rSh.GetViewOptions())->SetIdle( bOldIdle );
397         bOldIdleSet = sal_False;
398     }
399 
400     SdrObject *pObj = NULL;
401     m_nDropDestination = GetDropDestination( aPixPt, &pObj );
402     if( !m_nDropDestination )
403         return DND_ACTION_NONE;
404 
405     sal_uInt16 nEventAction;
406     sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT
407                                        : rEvt.mnAction;
408 
409     m_nDropAction = SotExchange::GetExchangeAction(
410                                 GetDataFlavorExVector(),
411                                 m_nDropDestination,
412                                 rEvt.mnAction,
413 //!!                                rEvt.GetSourceOptions(),
414                                 nUserOpt, m_nDropFormat, nEventAction );
415 
416     if( EXCHG_INOUT_ACTION_NONE != m_nDropAction )
417     {
418         const Point aDocPt( PixelToLogic( aPixPt ) );
419 
420         //Bei den default Aktionen wollen wir noch ein bischen mitreden.
421         SwModule *pMod = SW_MOD();
422         if( pMod->pDragDrop )
423         {
424             sal_Bool bCleanup = sal_False;
425             //Zeichenobjekte in Kopf-/Fusszeilen sind nicht erlaubt
426 
427             SwWrtShell *pSrcSh = pMod->pDragDrop->GetShell();
428             if( (pSrcSh->GetSelFrmType() == FRMTYPE_DRAWOBJ) &&
429                 pSrcSh->IsSelContainsControl() &&
430                  (rSh.GetFrmType( &aDocPt, sal_False ) & (FRMTYPE_HEADER|FRMTYPE_FOOTER)) )
431             {
432                 bCleanup = sal_True;
433             }
434             // keine positionsgeschuetzten Objecte verschieben!
435             else if( DND_ACTION_MOVE == rEvt.mnAction &&
436                      pSrcSh->IsSelObjProtected( FLYPROTECT_POS ) )
437             {
438                 bCleanup = sal_True;
439             }
440             else if( rEvt.mbDefault )
441             {
442                 // JP 13.08.98: internes Drag&Drop: bei gleichem Doc ein Move
443                 //              ansonten ein Copy - Task 54974
444                 nEventAction = pSrcSh->GetDoc() == rSh.GetDoc()
445                                     ? DND_ACTION_MOVE
446                                     : DND_ACTION_COPY;
447             }
448             if ( bCleanup )
449             {
450                 CleanupDropUserMarker();
451                 rSh.UnSetVisCrsr();
452                 return DND_ACTION_NONE;
453             }
454         }
455         else
456         {
457             //D&D von ausserhalb des SW soll per default ein Copy sein.
458             if( EXCHG_IN_ACTION_DEFAULT == nEventAction &&
459                 DND_ACTION_MOVE == rEvt.mnAction )
460                 nEventAction = DND_ACTION_COPY;
461 
462             if( (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE == m_nDropFormat &&
463                  EXCHG_IN_ACTION_LINK == m_nDropAction) ||
464                  SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE == m_nDropFormat  )
465             {
466                 SdrMarkView* pMView = PTR_CAST( SdrMarkView, rSh.GetDrawView() );
467                 if( pMView && !pMView->IsDesignMode() )
468                     return DND_ACTION_NONE;
469             }
470         }
471 
472         if ( EXCHG_IN_ACTION_DEFAULT != nEventAction )
473             nUserOpt = (sal_Int8)nEventAction;
474 
475         // show DropCursor or UserMarker ?
476         if( EXCHG_DEST_SWDOC_FREE_AREA_WEB == m_nDropDestination ||
477             EXCHG_DEST_SWDOC_FREE_AREA == m_nDropDestination )
478         {
479             CleanupDropUserMarker();
480             SwContentAtPos aCont( SwContentAtPos::SW_CONTENT_CHECK );
481             if(rSh.GetContentAtPos(aDocPt, aCont))
482                 rSh.SwCrsrShell::SetVisCrsr( aDocPt );
483         }
484         else
485         {
486             rSh.UnSetVisCrsr();
487 
488             if ( pUserMarkerObj != pObj )
489             {
490                 CleanupDropUserMarker();
491                 pUserMarkerObj = pObj;
492 
493                 if(pUserMarkerObj)
494                 {
495                     pUserMarker = new SdrDropMarkerOverlay( *rSh.GetDrawView(), *pUserMarkerObj );
496                 }
497             }
498         }
499         return nUserOpt;
500     }
501 
502     CleanupDropUserMarker();
503     rSh.UnSetVisCrsr();
504 //!!    return SFX_APP()->AcceptDrop( rEvt );
505     return DND_ACTION_NONE;
506 }
507 
508 
509 IMPL_LINK( SwEditWin, DDHandler, Timer *, EMPTYARG )
510 {
511     bDDTimerStarted = sal_False;
512     aTimer.Stop();
513     aTimer.SetTimeout(240);
514     bMBPressed = sal_False;
515     ReleaseMouse();
516     bFrmDrag = sal_False;
517 
518     if ( rView.GetViewFrame() )
519     {
520         bExecuteDrag = sal_True;
521         StartExecuteDrag();
522     }
523     return 0;
524 }
525 
526 
527 
528