xref: /AOO41X/main/sw/source/ui/docvw/edtdd.cxx (revision 69a743679e823ad8f875be547552acb607b8ada5)
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( !this, "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