Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <hintids.hxx>
21 :
22 : #include <svx/svdview.hxx>
23 : #include <editeng/outliner.hxx>
24 : #include <svx/svdobj.hxx>
25 : #include <sot/exchange.hxx>
26 : #include <sot/formats.hxx>
27 : #include <sfx2/bindings.hxx>
28 :
29 : #include <sfx2/viewfrm.hxx>
30 : #include <fmturl.hxx>
31 : #include <frmfmt.hxx>
32 : #include <wrtsh.hxx>
33 : #include <edtwin.hxx>
34 : #include <view.hxx>
35 : #include <viewopt.hxx>
36 : #include <swdtflvr.hxx>
37 : #include <swmodule.hxx>
38 : #include <docsh.hxx>
39 : #include <wdocsh.hxx>
40 : #include <swundo.hxx>
41 :
42 : using namespace ::com::sun::star;
43 :
44 : // no include "dbgoutsw.hxx" here!!!!!!
45 :
46 : extern bool g_bNoInterrupt;
47 : extern bool g_bFrmDrag;
48 : extern bool g_bDDTimerStarted;
49 :
50 : bool g_bExecuteDrag = false;
51 :
52 0 : void SwEditWin::StartDDTimer()
53 : {
54 0 : m_aTimer.SetTimeoutHdl(LINK(this, SwEditWin, DDHandler));
55 0 : m_aTimer.SetTimeout(480);
56 0 : m_aTimer.Start();
57 0 : g_bDDTimerStarted = true;
58 0 : }
59 :
60 0 : void SwEditWin::StopDDTimer(SwWrtShell *pSh, const Point &rPt)
61 : {
62 0 : m_aTimer.Stop();
63 0 : g_bDDTimerStarted = false;
64 0 : if(!pSh->IsSelFrmMode())
65 0 : pSh->SetCursor(&rPt, false);
66 0 : m_aTimer.SetTimeoutHdl(LINK(this,SwEditWin, TimerHandler));
67 0 : }
68 :
69 0 : void SwEditWin::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel )
70 : {
71 0 : SwWrtShell &rSh = m_rView.GetWrtShell();
72 0 : if( rSh.GetDrawView() )
73 : {
74 0 : CommandEvent aDragEvent( rPosPixel, CommandEventId::StartDrag, true );
75 0 : if( rSh.GetDrawView()->Command( aDragEvent, this ) )
76 : {
77 0 : m_rView.GetViewFrame()->GetBindings().InvalidateAll(false);
78 0 : return; // Event evaluated by SdrView
79 : }
80 : }
81 :
82 0 : if ( !m_pApplyTempl && !rSh.IsDrawCreate() && !IsDrawAction())
83 : {
84 0 : bool bStart = false, bDelSelect = false;
85 0 : SdrObject *pObj = NULL;
86 0 : Point aDocPos( PixelToLogic( rPosPixel ) );
87 0 : if ( !rSh.IsInSelect() && rSh.ChgCurrPam( aDocPos, true, true))
88 : //We are not selecting and aren't at a selection
89 0 : bStart = true;
90 0 : else if ( !g_bFrmDrag && rSh.IsSelFrmMode() &&
91 0 : rSh.IsInsideSelectedObj( aDocPos ) )
92 : {
93 : //We are not dragging internally and are not at an
94 : //object (frame, draw object)
95 :
96 0 : bStart = true;
97 : }
98 0 : else if( !g_bFrmDrag && m_rView.GetDocShell()->IsReadOnly() &&
99 0 : OBJCNT_NONE != rSh.GetObjCntType( aDocPos, pObj ))
100 : {
101 0 : rSh.LockPaint();
102 0 : if( rSh.SelectObj( aDocPos, 0, pObj ))
103 0 : bStart = bDelSelect = true;
104 : else
105 0 : rSh.UnlockPaint();
106 : }
107 : else
108 : {
109 0 : SwContentAtPos aSwContentAtPos( SwContentAtPos::SW_INETATTR );
110 : bStart = rSh.GetContentAtPos( aDocPos,
111 : aSwContentAtPos,
112 0 : false );
113 : }
114 :
115 0 : if ( bStart && !m_bIsInDrag )
116 : {
117 0 : m_bMBPressed = false;
118 0 : ReleaseMouse();
119 0 : g_bFrmDrag = false;
120 0 : g_bExecuteDrag = true;
121 0 : SwEditWin::m_nDDStartPosY = aDocPos.Y();
122 0 : SwEditWin::m_nDDStartPosX = aDocPos.X();
123 0 : m_aMovePos = aDocPos;
124 0 : StartExecuteDrag();
125 0 : if( bDelSelect )
126 : {
127 0 : rSh.UnSelectFrm();
128 0 : rSh.UnlockPaint();
129 : }
130 : }
131 : }
132 : }
133 :
134 0 : void SwEditWin::StartExecuteDrag()
135 : {
136 0 : if( !g_bExecuteDrag || m_bIsInDrag )
137 0 : return;
138 :
139 0 : m_bIsInDrag = true;
140 :
141 0 : SwTransferable* pTransfer = new SwTransferable( m_rView.GetWrtShell() );
142 : uno::Reference<
143 0 : datatransfer::XTransferable > xRef( pTransfer );
144 :
145 0 : pTransfer->StartDrag( this, m_aMovePos );
146 : }
147 :
148 0 : void SwEditWin::DragFinished()
149 : {
150 0 : DropCleanup();
151 0 : m_aTimer.SetTimeoutHdl( LINK(this,SwEditWin, TimerHandler) );
152 0 : m_bIsInDrag = false;
153 0 : }
154 :
155 0 : void SwEditWin::DropCleanup()
156 : {
157 0 : SwWrtShell &rSh = m_rView.GetWrtShell();
158 :
159 : // reset statuses
160 0 : g_bNoInterrupt = false;
161 0 : if ( m_bOldIdleSet )
162 : {
163 0 : rSh.GetViewOptions()->SetIdle( m_bOldIdle );
164 0 : m_bOldIdleSet = false;
165 : }
166 0 : if ( m_pUserMarker )
167 0 : CleanupDropUserMarker();
168 : else
169 0 : rSh.UnSetVisCrsr();
170 :
171 0 : }
172 :
173 0 : void SwEditWin::CleanupDropUserMarker()
174 : {
175 0 : if ( m_pUserMarker )
176 : {
177 0 : delete m_pUserMarker;
178 0 : m_pUserMarker = 0;
179 0 : m_pUserMarkerObj = 0;
180 : }
181 0 : }
182 :
183 : //exhibition hack (MA,MBA)
184 2 : void SwView::SelectShellForDrop()
185 : {
186 2 : if ( !GetCurShell() )
187 0 : SelectShell();
188 2 : }
189 :
190 0 : sal_Int8 SwEditWin::ExecuteDrop( const ExecuteDropEvent& rEvt )
191 : {
192 0 : GetView().SelectShellForDrop();
193 0 : DropCleanup();
194 0 : sal_Int8 nRet = DND_ACTION_NONE;
195 :
196 : //A Drop to an open OutlinerView doesn't concern us (also see QueryDrop)
197 0 : SwWrtShell &rSh = m_rView.GetWrtShell();
198 0 : const Point aDocPt( PixelToLogic( rEvt.maPosPixel ));
199 0 : SdrObject *pObj = 0;
200 : OutlinerView* pOLV;
201 0 : rSh.GetObjCntType( aDocPt, pObj );
202 :
203 0 : if( pObj && 0 != ( pOLV = rSh.GetDrawView()->GetTextEditOutlinerView() ))
204 : {
205 0 : Rectangle aRect( pOLV->GetOutputArea() );
206 0 : aRect.Union( pObj->GetLogicRect() );
207 0 : const Point aPos = pOLV->GetWindow()->PixelToLogic(rEvt.maPosPixel);
208 0 : if ( aRect.IsInside(aPos) )
209 : {
210 0 : rSh.StartAllAction();
211 0 : rSh.EndAllAction();
212 0 : return nRet;
213 : }
214 : }
215 :
216 : // There's a special treatment for file lists with a single
217 : // element, that depends on the actual content of the
218 : // Transferable to be accessible. Since the transferable
219 : // may only be accessed after the drop has been accepted
220 : // (according to KA due to Java D&D), we'll have to
221 : // reevaluate the drop action once more _with_ the
222 : // Transferable.
223 : sal_uInt16 nEventAction;
224 : sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT
225 0 : : rEvt.mnAction;
226 : m_nDropAction = SotExchange::GetExchangeAction(
227 0 : GetDataFlavorExVector(),
228 : m_nDropDestination,
229 : rEvt.mnAction,
230 : nUserOpt, m_nDropFormat, nEventAction, SotClipboardFormatId::NONE,
231 0 : &rEvt.maDropEvent.Transferable );
232 :
233 0 : TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
234 0 : nRet = rEvt.mnAction;
235 0 : if( !SwTransferable::PasteData( aData, rSh, m_nDropAction, m_nDropFormat,
236 0 : m_nDropDestination, false, rEvt.mbDefault, &aDocPt, nRet))
237 0 : nRet = DND_ACTION_NONE;
238 0 : else if ( SW_MOD()->pDragDrop )
239 : //Don't clean up anymore at internal D&D!
240 0 : SW_MOD()->pDragDrop->SetCleanUp( false );
241 :
242 0 : return nRet;
243 : }
244 :
245 0 : SotExchangeDest SwEditWin::GetDropDestination( const Point& rPixPnt, SdrObject ** ppObj )
246 : {
247 0 : SwWrtShell &rSh = m_rView.GetWrtShell();
248 0 : const Point aDocPt( PixelToLogic( rPixPnt ) );
249 0 : if( rSh.ChgCurrPam( aDocPt )
250 0 : || rSh.IsOverReadOnlyPos( aDocPt )
251 0 : || rSh.DocPtInsideInputField( aDocPt ) )
252 0 : return SotExchangeDest::NONE;
253 :
254 0 : SdrObject *pObj = NULL;
255 0 : const ObjCntType eType = rSh.GetObjCntType( aDocPt, pObj );
256 :
257 : //Drop to OutlinerView (TextEdit in Drawing) should decide it on its own!
258 0 : if( pObj )
259 : {
260 0 : OutlinerView* pOLV = rSh.GetDrawView()->GetTextEditOutlinerView();
261 0 : if ( pOLV )
262 : {
263 0 : Rectangle aRect( pOLV->GetOutputArea() );
264 0 : aRect.Union( pObj->GetLogicRect() );
265 0 : const Point aPos = pOLV->GetWindow()->PixelToLogic( rPixPnt );
266 0 : if( aRect.IsInside( aPos ) )
267 0 : return SotExchangeDest::NONE;
268 : }
269 : }
270 :
271 : //What do we want to drop on now?
272 0 : SotExchangeDest nDropDestination = SotExchangeDest::NONE;
273 :
274 : //Did anything else arrive from the DrawingEngine?
275 0 : if( OBJCNT_NONE != eType )
276 : {
277 0 : switch ( eType )
278 : {
279 : case OBJCNT_GRF:
280 : {
281 : bool bLink,
282 0 : bIMap = 0 != rSh.GetFormatFromObj( aDocPt )->GetURL().GetMap();
283 0 : OUString aDummy;
284 0 : rSh.GetGrfAtPos( aDocPt, aDummy, bLink );
285 0 : if ( bLink && bIMap )
286 0 : nDropDestination = SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP;
287 0 : else if ( bLink )
288 0 : nDropDestination = SotExchangeDest::DOC_LNKD_GRAPHOBJ;
289 0 : else if ( bIMap )
290 0 : nDropDestination = SotExchangeDest::DOC_GRAPH_W_IMAP;
291 : else
292 0 : nDropDestination = SotExchangeDest::DOC_GRAPHOBJ;
293 : }
294 0 : break;
295 : case OBJCNT_FLY:
296 0 : if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) )
297 0 : nDropDestination = SotExchangeDest::DOC_TEXTFRAME_WEB;
298 : else
299 0 : nDropDestination = SotExchangeDest::DOC_TEXTFRAME;
300 0 : break;
301 0 : case OBJCNT_OLE: nDropDestination = SotExchangeDest::DOC_OLEOBJ; break;
302 : case OBJCNT_CONTROL: /* no Action avail */
303 0 : case OBJCNT_SIMPLE: nDropDestination = SotExchangeDest::DOC_DRAWOBJ; break;
304 0 : case OBJCNT_URLBUTTON: nDropDestination = SotExchangeDest::DOC_URLBUTTON; break;
305 0 : case OBJCNT_GROUPOBJ: nDropDestination = SotExchangeDest::DOC_GROUPOBJ; break;
306 :
307 : default: OSL_ENSURE( false, "new ObjectType?" );
308 : }
309 : }
310 0 : if ( !bool(nDropDestination) )
311 : {
312 0 : if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) )
313 0 : nDropDestination = SotExchangeDest::SWDOC_FREE_AREA_WEB;
314 : else
315 0 : nDropDestination = SotExchangeDest::SWDOC_FREE_AREA;
316 : }
317 0 : if( ppObj )
318 0 : *ppObj = pObj;
319 0 : return nDropDestination;
320 : }
321 :
322 0 : sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt )
323 : {
324 0 : if( rEvt.mbLeaving )
325 : {
326 0 : DropCleanup();
327 0 : return rEvt.mnAction;
328 : }
329 :
330 0 : if( m_rView.GetDocShell()->IsReadOnly() )
331 0 : return DND_ACTION_NONE;
332 :
333 0 : SwWrtShell &rSh = m_rView.GetWrtShell();
334 :
335 0 : Point aPixPt( rEvt.maPosPixel );
336 :
337 : // If the cursor is near the inner boundary
338 : // we attempt to scroll towards the desired direction.
339 0 : Point aPoint;
340 0 : Rectangle aWin(aPoint,GetOutputSizePixel());
341 0 : const int nMargin = 10;
342 0 : aWin.Left() += nMargin;
343 0 : aWin.Top() += nMargin;
344 0 : aWin.Right() -= nMargin;
345 0 : aWin.Bottom() -= nMargin;
346 0 : if(!aWin.IsInside(aPixPt)) {
347 : static sal_uInt64 last_tick = 0;
348 0 : sal_uInt64 current_tick = tools::Time::GetSystemTicks();
349 0 : if((current_tick-last_tick) > 500) {
350 0 : last_tick = current_tick;
351 0 : if(!m_bOldIdleSet) {
352 0 : m_bOldIdle = rSh.GetViewOptions()->IsIdle();
353 0 : rSh.GetViewOptions()->SetIdle(false);
354 0 : m_bOldIdleSet = true;
355 : }
356 0 : CleanupDropUserMarker();
357 0 : if(aPixPt.X() > aWin.Right()) aPixPt.X() += nMargin;
358 0 : if(aPixPt.X() < aWin.Left()) aPixPt.X() -= nMargin;
359 0 : if(aPixPt.Y() > aWin.Bottom()) aPixPt.Y() += nMargin;
360 0 : if(aPixPt.Y() < aWin.Top()) aPixPt.Y() -= nMargin;
361 0 : Point aDocPt(PixelToLogic(aPixPt));
362 0 : SwRect rect(aDocPt,Size(1,1));
363 0 : rSh.MakeVisible(rect);
364 : }
365 : }
366 :
367 0 : if(m_bOldIdleSet) {
368 0 : rSh.GetViewOptions()->SetIdle( m_bOldIdle );
369 0 : m_bOldIdleSet = false;
370 : }
371 :
372 0 : SdrObject *pObj = NULL;
373 0 : m_nDropDestination = GetDropDestination( aPixPt, &pObj );
374 0 : if( !bool(m_nDropDestination) )
375 0 : return DND_ACTION_NONE;
376 :
377 : sal_uInt16 nEventAction;
378 : sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT
379 0 : : rEvt.mnAction;
380 :
381 : m_nDropAction = SotExchange::GetExchangeAction(
382 0 : GetDataFlavorExVector(),
383 : m_nDropDestination,
384 : rEvt.mnAction,
385 0 : nUserOpt, m_nDropFormat, nEventAction );
386 :
387 0 : if( EXCHG_INOUT_ACTION_NONE != m_nDropAction )
388 : {
389 0 : const Point aDocPt( PixelToLogic( aPixPt ) );
390 :
391 : //With the default action we still want to have a say.
392 0 : SwModule *pMod = SW_MOD();
393 0 : if( pMod->pDragDrop )
394 : {
395 0 : bool bCleanup = false;
396 : //Drawing objects in Headers/Footers are not allowed
397 :
398 0 : SwWrtShell *pSrcSh = pMod->pDragDrop->GetShell();
399 0 : if( (pSrcSh->GetSelFrmType() == FrmTypeFlags::DRAWOBJ) &&
400 0 : pSrcSh->IsSelContainsControl() &&
401 0 : (rSh.GetFrmType( &aDocPt, false ) & (FrmTypeFlags::HEADER|FrmTypeFlags::FOOTER)) )
402 : {
403 0 : bCleanup = true;
404 : }
405 : // don't more position protected objects!
406 0 : else if( DND_ACTION_MOVE == rEvt.mnAction &&
407 0 : pSrcSh->IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
408 : {
409 0 : bCleanup = true;
410 : }
411 0 : else if( rEvt.mbDefault )
412 : {
413 : // internal Drag&Drop: within same Doc a Move
414 : // otherwise a Copy - Task 54974
415 0 : nEventAction = pSrcSh->GetDoc() == rSh.GetDoc()
416 : ? DND_ACTION_MOVE
417 0 : : DND_ACTION_COPY;
418 : }
419 0 : if ( bCleanup )
420 : {
421 0 : CleanupDropUserMarker();
422 0 : rSh.UnSetVisCrsr();
423 0 : return DND_ACTION_NONE;
424 : }
425 : }
426 : else
427 : {
428 : //D&D from outside of SW should be a Copy per default.
429 0 : if( EXCHG_IN_ACTION_DEFAULT == nEventAction &&
430 0 : DND_ACTION_MOVE == rEvt.mnAction )
431 0 : nEventAction = DND_ACTION_COPY;
432 :
433 0 : if( (SotClipboardFormatId::SBA_FIELDDATAEXCHANGE == m_nDropFormat &&
434 0 : EXCHG_IN_ACTION_LINK == m_nDropAction) ||
435 0 : SotClipboardFormatId::SBA_CTRLDATAEXCHANGE == m_nDropFormat )
436 : {
437 0 : SdrMarkView* pMView = rSh.GetDrawView();
438 0 : if( pMView && !pMView->IsDesignMode() )
439 0 : return DND_ACTION_NONE;
440 : }
441 : }
442 :
443 0 : if ( EXCHG_IN_ACTION_DEFAULT != nEventAction )
444 0 : nUserOpt = (sal_Int8)nEventAction;
445 :
446 : // show DropCursor or UserMarker ?
447 0 : if( SotExchangeDest::SWDOC_FREE_AREA_WEB == m_nDropDestination ||
448 0 : SotExchangeDest::SWDOC_FREE_AREA == m_nDropDestination )
449 : {
450 0 : CleanupDropUserMarker();
451 0 : SwContentAtPos aCont( SwContentAtPos::SW_CONTENT_CHECK );
452 0 : if(rSh.GetContentAtPos(aDocPt, aCont))
453 0 : rSh.SwCrsrShell::SetVisCrsr( aDocPt );
454 : }
455 : else
456 : {
457 0 : rSh.UnSetVisCrsr();
458 :
459 0 : if ( m_pUserMarkerObj != pObj )
460 : {
461 0 : CleanupDropUserMarker();
462 0 : m_pUserMarkerObj = pObj;
463 :
464 0 : if(m_pUserMarkerObj)
465 : {
466 0 : m_pUserMarker = new SdrDropMarkerOverlay( *rSh.GetDrawView(), *m_pUserMarkerObj );
467 : }
468 : }
469 : }
470 0 : return nUserOpt;
471 : }
472 :
473 0 : CleanupDropUserMarker();
474 0 : rSh.UnSetVisCrsr();
475 0 : return DND_ACTION_NONE;
476 : }
477 :
478 0 : IMPL_LINK_NOARG_TYPED(SwEditWin, DDHandler, Timer *, void)
479 : {
480 0 : g_bDDTimerStarted = false;
481 0 : m_aTimer.Stop();
482 0 : m_aTimer.SetTimeout(240);
483 0 : m_bMBPressed = false;
484 0 : ReleaseMouse();
485 0 : g_bFrmDrag = false;
486 :
487 0 : if ( m_rView.GetViewFrame() )
488 : {
489 0 : g_bExecuteDrag = true;
490 0 : StartExecuteDrag();
491 : }
492 177 : }
493 :
494 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|