docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / sw / source / uibase / docvw / edtdd.cxx
blob89f93144919d2ce4a2c47f58b90da86ddc074783
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svx/svdview.hxx>
21 #include <editeng/outliner.hxx>
22 #include <svx/svdobj.hxx>
23 #include <sot/exchange.hxx>
24 #include <sot/formats.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <vcl/commandevent.hxx>
27 #include <osl/diagnose.h>
29 #include <sfx2/viewfrm.hxx>
30 #include <fmturl.hxx>
31 #include <frmfmt.hxx>
32 #include <wrtsh.hxx>
33 #include <edtdd.hxx>
34 #include <edtwin.hxx>
35 #include <view.hxx>
36 #include <viewopt.hxx>
37 #include <swdtflvr.hxx>
38 #include <swmodule.hxx>
39 #include <docsh.hxx>
40 #include <wdocsh.hxx>
42 using namespace ::com::sun::star;
44 // no include "dbgoutsw.hxx" here!!!!!!
46 bool g_bExecuteDrag = false;
48 void SwEditWin::StartDDTimer()
50 m_aTimer.SetInvokeHandler(LINK(this, SwEditWin, DDHandler));
51 m_aTimer.SetTimeout(480);
52 m_aTimer.Start();
53 g_bDDTimerStarted = true;
56 void SwEditWin::StopDDTimer(SwWrtShell *pSh, const Point &rPt)
58 m_aTimer.Stop();
59 g_bDDTimerStarted = false;
60 if(!pSh->IsSelFrameMode())
61 pSh->CallSetCursor(&rPt, false);
62 m_aTimer.SetInvokeHandler(LINK(this,SwEditWin, TimerHandler));
65 void SwEditWin::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel )
67 if (m_rView.GetObjectShell()->isContentExtractionLocked())
68 return;
70 SwWrtShell &rSh = m_rView.GetWrtShell();
71 if( rSh.GetDrawView() )
73 CommandEvent aDragEvent( rPosPixel, CommandEventId::StartDrag, true );
74 if( rSh.GetDrawView()->Command( aDragEvent, this ) )
76 m_rView.GetViewFrame().GetBindings().InvalidateAll(false);
77 return; // Event evaluated by SdrView
81 if ( m_pApplyTempl || rSh.IsDrawCreate() || IsDrawAction())
82 return;
84 bool bStart = false, bDelSelect = false;
85 SdrObject *pObj = nullptr;
86 Point aDocPos( PixelToLogic( rPosPixel ) );
87 const bool bInSelect = rSh.IsInSelect();
88 if (!bInSelect && rSh.TestCurrPam(aDocPos, true))
89 //We are not selecting and aren't at a selection
90 bStart = true;
91 else if ( !g_bFrameDrag && rSh.IsSelFrameMode() &&
92 rSh.IsInsideSelectedObj( aDocPos ) &&
93 nullptr == m_pAnchorMarker)
95 //We are not dragging internally and are not at an
96 //object (frame, draw object)
98 // #i106131# *and* AnchorDrag is *not* active: When active,
99 // entering global drag mode will destroy the AnchorHdl but
100 // keep the now invalid ptr in place, next access will crash.
101 // It is indeed wrong to enter drag mode when AnchorDrag is
102 // already active
103 bStart = true;
105 else if( !g_bFrameDrag && m_rView.GetDocShell()->IsReadOnly() &&
106 OBJCNT_NONE != rSh.GetObjCntType( aDocPos, pObj ))
108 rSh.LockPaint(LockPaintReason::StartDrag);
109 if( rSh.SelectObj( aDocPos, 0, pObj ))
110 bStart = bDelSelect = true;
111 else
112 rSh.UnlockPaint();
114 else if (!bInSelect)// tdf#116384 only drag hyperlink if user's not currently setting the selection
116 SwContentAtPos aSwContentAtPos( IsAttrAtPos::InetAttr );
117 bStart = rSh.GetContentAtPos( aDocPos,
118 aSwContentAtPos );
121 if ( !bStart || m_bIsInDrag )
122 return;
124 // If the add selection mode has been pushed in the MouseButtonDown handler it needs to be
125 // popped or it will remain active and noticeable in the statusbar selection control until the
126 // next MouseButtonUp event after the DnD, since a MouseButtonUp event is not received by the
127 // edit window when DnD is done.
128 if (g_bModePushed)
130 rSh.PopMode();
131 g_bModePushed = false;
134 m_bMBPressed = false;
135 ReleaseMouse();
136 g_bFrameDrag = false;
137 g_bExecuteDrag = true;
138 SwEditWin::s_nDDStartPosY = aDocPos.Y();
139 SwEditWin::s_nDDStartPosX = aDocPos.X();
140 m_aMovePos = aDocPos;
141 StartExecuteDrag();
142 if( bDelSelect )
144 rSh.UnSelectFrame();
145 rSh.UnlockPaint();
149 void SwEditWin::StartExecuteDrag()
151 if( !g_bExecuteDrag || m_bIsInDrag )
152 return;
154 m_bIsInDrag = true;
156 rtl::Reference<SwTransferable> pTransfer = new SwTransferable( m_rView.GetWrtShell() );
158 pTransfer->StartDrag( this, m_aMovePos );
161 void SwEditWin::DragFinished()
163 DropCleanup();
164 m_aTimer.SetInvokeHandler( LINK(this,SwEditWin, TimerHandler) );
165 m_bIsInDrag = false;
168 void SwEditWin::DropCleanup()
170 SwWrtShell &rSh = m_rView.GetWrtShell();
172 // reset statuses
173 g_bNoInterrupt = false;
174 if ( m_bOldIdleSet )
176 rSh.GetViewOptions()->SetIdle( m_bOldIdle );
177 m_bOldIdleSet = false;
179 if ( m_pUserMarker )
180 CleanupDropUserMarker();
181 else
182 rSh.UnSetVisibleCursor();
186 void SwEditWin::CleanupDropUserMarker()
188 if ( m_pUserMarker )
190 m_pUserMarker.reset();
191 m_pUserMarkerObj = nullptr;
195 //exhibition hack (MA,MBA)
196 void SwView::SelectShellForDrop()
198 if ( !GetCurShell() )
199 SelectShell();
202 sal_Int8 SwEditWin::ExecuteDrop( const ExecuteDropEvent& rEvt )
204 GetView().SelectShellForDrop();
205 DropCleanup();
206 sal_Int8 nRet = DND_ACTION_NONE;
208 //A Drop to an open OutlinerView doesn't concern us (also see QueryDrop)
209 SwWrtShell &rSh = m_rView.GetWrtShell();
210 const Point aDocPt( PixelToLogic( rEvt.maPosPixel ));
211 SdrObject *pObj = nullptr;
212 OutlinerView* pOLV;
213 rSh.GetObjCntType( aDocPt, pObj );
215 if( pObj && nullptr != ( pOLV = rSh.GetDrawView()->GetTextEditOutlinerView() ))
217 tools::Rectangle aRect( pOLV->GetOutputArea() );
218 aRect.Union( pObj->GetLogicRect() );
219 const Point aPos = pOLV->GetWindow()->PixelToLogic(rEvt.maPosPixel);
220 if ( aRect.Contains(aPos) )
222 rSh.StartAllAction();
223 rSh.EndAllAction();
224 return nRet;
228 // There's a special treatment for file lists with a single
229 // element, that depends on the actual content of the
230 // Transferable to be accessible. Since the transferable
231 // may only be accessed after the drop has been accepted
232 // (according to KA due to Java D&D), we'll have to
233 // reevaluate the drop action once more _with_ the
234 // Transferable.
235 sal_uInt8 nEventAction;
236 sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT
237 : rEvt.mnAction;
238 SotExchangeActionFlags nActionFlags;
239 m_nDropAction = SotExchange::GetExchangeAction(
240 GetDataFlavorExVector(),
241 m_nDropDestination,
242 rEvt.mnAction,
243 nUserOpt, m_nDropFormat, nEventAction, SotClipboardFormatId::NONE,
244 &rEvt.maDropEvent.Transferable,
245 &nActionFlags );
247 TransferableDataHelper aData( rEvt.maDropEvent.Transferable );
248 nRet = rEvt.mnAction;
249 if( !SwTransferable::PasteData( aData, rSh, m_nDropAction, nActionFlags, m_nDropFormat,
250 m_nDropDestination, false, rEvt.mbDefault, &aDocPt, nRet))
251 nRet = DND_ACTION_NONE;
252 else if (SwModule* mod = SwModule::get(); mod->m_pDragDrop)
253 //Don't clean up anymore at internal D&D!
254 mod->m_pDragDrop->SetCleanUp(false);
256 return nRet;
259 SotExchangeDest SwEditWin::GetDropDestination( const Point& rPixPnt, SdrObject ** ppObj )
261 SwWrtShell &rSh = m_rView.GetWrtShell();
262 const Point aDocPt( PixelToLogic( rPixPnt ) );
263 if (rSh.IsOverReadOnlyPos(aDocPt) || rSh.DocPtInsideInputField(aDocPt))
264 return SotExchangeDest::NONE;
266 SdrObject *pObj = nullptr;
267 const ObjCntType eType = rSh.GetObjCntType( aDocPt, pObj );
269 //Drop to OutlinerView (TextEdit in Drawing) should decide it on its own!
270 if( pObj )
272 OutlinerView* pOLV = rSh.GetDrawView()->GetTextEditOutlinerView();
273 if ( pOLV )
275 tools::Rectangle aRect( pOLV->GetOutputArea() );
276 aRect.Union( pObj->GetLogicRect() );
277 const Point aPos = pOLV->GetWindow()->PixelToLogic( rPixPnt );
278 if( aRect.Contains( aPos ) )
279 return SotExchangeDest::NONE;
283 //What do we want to drop on now?
284 SotExchangeDest nDropDestination = SotExchangeDest::NONE;
286 //Did anything else arrive from the DrawingEngine?
287 if( OBJCNT_NONE != eType )
289 switch ( eType )
291 case OBJCNT_GRF:
293 bool bLink,
294 bIMap = nullptr != rSh.GetFormatFromObj( aDocPt )->GetURL().GetMap();
295 OUString aDummy;
296 rSh.GetGrfAtPos( aDocPt, aDummy, bLink );
297 if ( bLink && bIMap )
298 nDropDestination = SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP;
299 else if ( bLink )
300 nDropDestination = SotExchangeDest::DOC_LNKD_GRAPHOBJ;
301 else if ( bIMap )
302 nDropDestination = SotExchangeDest::DOC_GRAPH_W_IMAP;
303 else
304 nDropDestination = SotExchangeDest::DOC_GRAPHOBJ;
306 break;
307 case OBJCNT_FLY:
308 if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
309 nDropDestination = SotExchangeDest::DOC_TEXTFRAME_WEB;
310 else
311 nDropDestination = SotExchangeDest::DOC_TEXTFRAME;
312 break;
313 case OBJCNT_OLE: nDropDestination = SotExchangeDest::DOC_OLEOBJ; break;
314 case OBJCNT_CONTROL: /* no Action avail */
315 case OBJCNT_SIMPLE: nDropDestination = SotExchangeDest::DOC_DRAWOBJ; break;
316 case OBJCNT_URLBUTTON: nDropDestination = SotExchangeDest::DOC_URLBUTTON; break;
317 case OBJCNT_GROUPOBJ: nDropDestination = SotExchangeDest::DOC_GROUPOBJ; break;
319 default: OSL_ENSURE( false, "new ObjectType?" );
322 if ( nDropDestination == SotExchangeDest::NONE )
324 if( dynamic_cast< const SwWebDocShell *>( rSh.GetView().GetDocShell() ) != nullptr )
325 nDropDestination = SotExchangeDest::SWDOC_FREE_AREA_WEB;
326 else
327 nDropDestination = SotExchangeDest::SWDOC_FREE_AREA;
329 if( ppObj )
330 *ppObj = pObj;
331 return nDropDestination;
334 sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt )
336 if( rEvt.mbLeaving )
338 DropCleanup();
339 return rEvt.mnAction;
342 if( m_rView.GetDocShell()->IsReadOnly() )
343 return DND_ACTION_NONE;
345 SwWrtShell &rSh = m_rView.GetWrtShell();
347 Point aPixPt( rEvt.maPosPixel );
349 // If the cursor is near the inner boundary
350 // we attempt to scroll towards the desired direction.
351 tools::Rectangle aWin(Point(), GetOutputSizePixel());
352 const int nMargin = 10;
353 aWin.AdjustLeft(nMargin );
354 aWin.AdjustTop(nMargin );
355 aWin.AdjustRight( -nMargin );
356 aWin.AdjustBottom( -nMargin );
357 if(!aWin.Contains(aPixPt)) {
358 static sal_uInt64 last_tick = 0;
359 sal_uInt64 current_tick = tools::Time::GetSystemTicks();
360 if((current_tick-last_tick) > 500) {
361 last_tick = current_tick;
362 if(!m_bOldIdleSet) {
363 m_bOldIdle = rSh.GetViewOptions()->IsIdle();
364 rSh.GetViewOptions()->SetIdle(false);
365 m_bOldIdleSet = true;
367 CleanupDropUserMarker();
368 if(aPixPt.X() > aWin.Right()) aPixPt.AdjustX(nMargin );
369 if(aPixPt.X() < aWin.Left()) aPixPt.AdjustX( -nMargin );
370 if(aPixPt.Y() > aWin.Bottom()) aPixPt.AdjustY(nMargin );
371 if(aPixPt.Y() < aWin.Top()) aPixPt.AdjustY( -nMargin );
372 Point aDocPt(PixelToLogic(aPixPt));
373 SwRect rect(aDocPt,Size(1,1));
374 rSh.MakeVisible(rect, ScrollSizeMode::ScrollSizeTimer2);
378 if(m_bOldIdleSet) {
379 rSh.GetViewOptions()->SetIdle( m_bOldIdle );
380 m_bOldIdleSet = false;
383 SdrObject *pObj = nullptr;
384 m_nDropDestination = GetDropDestination( aPixPt, &pObj );
385 if( m_nDropDestination == SotExchangeDest::NONE )
386 return DND_ACTION_NONE;
388 sal_uInt8 nEventAction;
389 sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT
390 : rEvt.mnAction;
392 m_nDropAction = SotExchange::GetExchangeAction(
393 GetDataFlavorExVector(),
394 m_nDropDestination,
395 rEvt.mnAction,
396 nUserOpt, m_nDropFormat, nEventAction );
398 if( EXCHG_INOUT_ACTION_NONE != m_nDropAction )
400 const Point aDocPt( PixelToLogic( aPixPt ) );
402 //With the default action we still want to have a say.
403 SwModule* pMod = SwModule::get();
404 if( pMod->m_pDragDrop )
406 bool bCleanup = false;
407 //Drawing objects in Headers/Footers are not allowed
409 SwWrtShell *pSrcSh = pMod->m_pDragDrop->GetShell();
410 if( (pSrcSh->GetSelFrameType() == FrameTypeFlags::DRAWOBJ) &&
411 pSrcSh->IsSelContainsControl() &&
412 (rSh.GetFrameType( &aDocPt, false ) & (FrameTypeFlags::HEADER|FrameTypeFlags::FOOTER)) )
414 bCleanup = true;
416 // don't more position protected objects!
417 else if( DND_ACTION_MOVE == rEvt.mnAction &&
418 pSrcSh->IsSelObjProtected( FlyProtectFlags::Pos ) != FlyProtectFlags::NONE )
420 bCleanup = true;
422 else if( rEvt.mbDefault )
424 // internal Drag&Drop: within same Doc a Move
425 // otherwise a Copy - Task 54974
426 nEventAction = pSrcSh->GetDoc() == rSh.GetDoc()
427 ? DND_ACTION_MOVE
428 : DND_ACTION_COPY;
430 if ( bCleanup )
432 CleanupDropUserMarker();
433 rSh.UnSetVisibleCursor();
434 return DND_ACTION_NONE;
437 else
439 //D&D from outside of SW should be a Copy per default.
440 if( EXCHG_IN_ACTION_DEFAULT == nEventAction &&
441 DND_ACTION_MOVE == rEvt.mnAction )
442 nEventAction = DND_ACTION_COPY;
444 if( (SotClipboardFormatId::SBA_FIELDDATAEXCHANGE == m_nDropFormat &&
445 EXCHG_IN_ACTION_LINK == m_nDropAction) ||
446 SotClipboardFormatId::SBA_CTRLDATAEXCHANGE == m_nDropFormat )
448 SdrMarkView* pMView = rSh.GetDrawView();
449 if( pMView && !pMView->IsDesignMode() )
450 return DND_ACTION_NONE;
454 if ( EXCHG_IN_ACTION_DEFAULT != nEventAction )
455 nUserOpt = static_cast<sal_Int8>(nEventAction);
457 // show DropCursor or UserMarker ?
458 if( SotExchangeDest::SWDOC_FREE_AREA_WEB == m_nDropDestination ||
459 SotExchangeDest::SWDOC_FREE_AREA == m_nDropDestination )
461 CleanupDropUserMarker();
462 SwContentAtPos aCont( IsAttrAtPos::ContentCheck );
463 if(rSh.GetContentAtPos(aDocPt, aCont))
464 rSh.SwCursorShell::SetVisibleCursor( aDocPt, ScrollSizeMode::ScrollSizeMouseSelection );
466 else
468 rSh.UnSetVisibleCursor();
470 if ( m_pUserMarkerObj != pObj )
472 CleanupDropUserMarker();
473 m_pUserMarkerObj = pObj;
475 if(m_pUserMarkerObj)
477 m_pUserMarker.reset(new SdrDropMarkerOverlay( *rSh.GetDrawView(), *m_pUserMarkerObj ));
481 return nUserOpt;
484 CleanupDropUserMarker();
485 rSh.UnSetVisibleCursor();
486 return DND_ACTION_NONE;
489 IMPL_LINK_NOARG(SwEditWin, DDHandler, Timer *, void)
491 g_bDDTimerStarted = false;
492 m_aTimer.Stop();
493 m_aTimer.SetTimeout(240);
494 m_bMBPressed = false;
495 ReleaseMouse();
496 g_bFrameDrag = false;
497 g_bExecuteDrag = true;
498 StartExecuteDrag();
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */