xref: /trunk/main/sw/source/ui/docvw/edtdd.cxx (revision 60822731f97e392f18f66164e20dcaceb878c33f)
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 
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 
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 
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 
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 
162 void SwEditWin::DragFinished()
163 {
164     DropCleanup();
165     aTimer.SetTimeoutHdl( LINK(this,SwEditWin, TimerHandler) );
166     bIsInDrag = sal_False;
167 }
168 
169 
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 
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)
200 void lcl_SelectShellForDrop( SwView &rView )
201 {
202     if ( !rView.GetCurShell() )
203         rView.SelectShell();
204 }
205 
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 
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 
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 
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