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