tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / drawfunc / fusel.cxx
blob6bb680cd49a246afe5b8913d7753b1bd8eb76b0f
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 <com/sun/star/embed/EmbedVerbs.hpp>
21 #include <editeng/flditem.hxx>
22 #include <svx/svddrgmt.hxx>
23 #include <svx/svdoole2.hxx>
24 #include <sfx2/dispatch.hxx>
25 #include <vcl/imapobj.hxx>
26 #include <svx/svdouno.hxx>
27 #include <svx/svdomedia.hxx>
28 #include <svx/svdpagv.hxx>
29 #include <svx/ImageMapInfo.hxx>
30 #include <editeng/outlobj.hxx>
31 #include <sfx2/app.hxx>
32 #include <sfx2/ipclient.hxx>
33 #include <sfx2/viewfrm.hxx>
34 #include <comphelper/lok.hxx>
36 #include <fusel.hxx>
37 #include <sc.hrc>
38 #include <fudraw.hxx>
39 #include <futext.hxx>
40 #include <drawview.hxx>
41 #include <tabvwsh.hxx>
42 #include <drwlayer.hxx>
43 #include <userdat.hxx>
44 #include <scmod.hxx>
45 #include <charthelper.hxx>
46 #include <docuno.hxx>
47 #include <docsh.hxx>
48 #include <stlpool.hxx>
50 // maximal permitted mouse movement to start Drag&Drop
51 //! fusel,fuconstr,futext - combine them!
52 #define SC_MAXDRAGMOVE 3
53 // Min necessary mouse motion for normal dragging
54 #define SC_MINDRAGMOVE 2
56 using namespace com::sun::star;
58 FuSelection::FuSelection(ScTabViewShell& rViewSh, vcl::Window* pWin, ScDrawView* pViewP,
59 SdrModel* pDoc, const SfxRequest& rReq)
60 : FuDraw(rViewSh, pWin, pViewP, pDoc, rReq)
64 FuSelection::~FuSelection()
68 bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
70 // remember button state for creation of own MouseEvents
71 SetMouseButtonCode(rMEvt.GetButtons());
72 const bool bSelectionOnly = rMEvt.IsRight();
73 if ( pView->IsAction() )
75 if ( bSelectionOnly )
76 pView->BckAction();
77 return true;
80 bIsInDragMode = false; // somewhere it has to be reset (#50033#)
82 bool bReturn = FuDraw::MouseButtonDown(rMEvt);
83 auto aLogicPosition = rMEvt.getLogicPosition();
84 if (aLogicPosition)
85 aMDPos = *aLogicPosition;
86 else
87 aMDPos = pWindow->PixelToLogic(rMEvt.GetPosPixel());
89 if (comphelper::LibreOfficeKit::isActive())
91 ScViewData& rViewData = rViewShell.GetViewData();
92 ScDocument& rDocument = rViewData.GetDocument();
93 if (rDocument.IsNegativePage(rViewData.GetTabNo()))
94 aMDPos.setX(-aMDPos.X());
97 if ( rMEvt.IsLeft() )
99 SdrHdl* pHdl = pView->PickHandle(aMDPos);
101 if ( pHdl!=nullptr || pView->IsMarkedHit(aMDPos) )
103 // Determine if this is the tail of a SdrCaptionObj i.e.
104 // we need to disable the drag option on the tail of a note
105 // object. Also, disable the ability to use the circular
106 // drag of a note object.
107 bool bDrag = false;
108 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
109 if( rMarkList.GetMarkCount() == 1 )
111 SdrObject* pMarkedObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
112 if( ScDrawLayer::IsNoteCaption( pMarkedObj ) )
114 // move using the valid caption handles for note text box.
115 if(pHdl && (pHdl->GetKind() != SdrHdlKind::Poly && pHdl->GetKind() != SdrHdlKind::Circle))
116 bDrag = true;
117 // move the complete note box.
118 else if(!pHdl)
119 bDrag = true;
121 else
122 bDrag = true; // different object
124 else
125 bDrag = true; // several objects
127 if ( bDrag )
129 aDragTimer.Start();
130 if (pView->BegDragObj(aMDPos, nullptr, pHdl))
131 pView->GetDragMethod()->SetShiftPressed( rMEvt.IsShift() );
132 bReturn = true;
135 else
137 SdrPageView* pPV = nullptr;
138 bool bAlt = rMEvt.IsMod2();
139 SdrObject* pObj = !bAlt ? pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::PICKMACRO) : nullptr;
140 if (pObj)
142 pView->BegMacroObj(aMDPos, pObj, pPV, pWindow);
143 bReturn = true;
145 else
147 OUString sURL, sTarget;
148 pObj = !bAlt ? pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER) : nullptr;
149 if (pObj)
151 // Support for imported Excel docs
152 // Excel is of course not consistent and allows
153 // a hyperlink to be assigned for an object group
154 // and even though the hyperlink is exported in the Escher layer
155 // its never used, when dealing with a group object the link
156 // associated with the clicked object is used only
158 // additionally you can also select a macro in Excel for a grouped
159 // objects and this *usually* results in the macro being set
160 // for the elements in the group and no macro is exported
161 // for the group itself ( this however is not always true )
162 // if a macro and hlink are defined favour the hlink
163 // If a group object has no hyperlink use the hyperlink of the
164 // object clicked
166 if ( pObj->IsGroupObject() )
168 ScMacroInfo* pTmpInfo = ScDrawLayer::GetMacroInfo( pObj );
169 if ( !pTmpInfo || pTmpInfo->GetMacro().isEmpty() )
171 SdrObject* pHit = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::DEEP);
172 if (pHit)
173 pObj = pHit;
177 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj, true );
178 // For interoperability favour links over macros if both are defined
179 if ( !pObj->getHyperlink().isEmpty() )
181 sURL = pObj->getHyperlink();
183 else if ( !pInfo->GetMacro().isEmpty() )
185 SfxObjectShell* pObjSh = SfxObjectShell::Current();
186 if ( pObjSh && SfxApplication::IsXScriptURL( pInfo->GetMacro() ) )
188 uno::Reference< beans::XPropertySet > xProps( pObj->getUnoShape(), uno::UNO_QUERY );
189 uno::Any aCaller;
190 if ( xProps.is() )
194 aCaller = xProps->getPropertyValue(u"Name"_ustr);
196 catch( uno::Exception& ) {}
198 uno::Any aRet;
199 uno::Sequence< sal_Int16 > aOutArgsIndex;
200 uno::Sequence< uno::Any > aOutArgs;
201 uno::Sequence< uno::Any > aInArgs;
202 pObjSh->CallXScript( pInfo->GetMacro(),
203 aInArgs, aRet, aOutArgsIndex, aOutArgs, true, &aCaller );
204 rViewShell.FakeButtonUp( rViewShell.GetViewData().GetActivePart() );
205 return true; // no CaptureMouse etc.
210 // URL / ImageMap
212 SdrViewEvent aVEvt;
213 if ( !bAlt &&
214 pView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ) != SdrHitKind::NONE &&
215 aVEvt.mpObj != nullptr )
217 if ( SvxIMapInfo::GetIMapInfo( aVEvt.mpObj ) ) // ImageMap
219 const IMapObject* pIMapObj =
220 SvxIMapInfo::GetHitIMapObject( aVEvt.mpObj, aMDPos, pWindow->GetOutDev() );
221 if ( pIMapObj && !pIMapObj->GetURL().isEmpty() )
223 sURL = pIMapObj->GetURL();
224 sTarget = pIMapObj->GetTarget();
227 if ( aVEvt.meEvent == SdrEventKind::ExecuteUrl && aVEvt.mpURLField ) // URL
229 sURL = aVEvt.mpURLField->GetURL();
230 sTarget = aVEvt.mpURLField->GetTargetFrame();
234 // open hyperlink, if found at object or in object's text
235 // Fragments pointing into the current document should be always opened.
236 if ( !sURL.isEmpty() && (ScGlobal::ShouldOpenURL() || sURL.startsWith("#")) )
238 ScGlobal::OpenURL( sURL, sTarget );
239 rViewShell.FakeButtonUp( rViewShell.GetViewData().GetActivePart() );
240 return true; // no CaptureMouse etc.
243 // Is another object being edited in this view?
244 // (Editing is ended in MarkListHasChanged - test before UnmarkAll)
245 SfxInPlaceClient* pClient = rViewShell.GetIPClient();
246 bool bWasOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
248 // Selection
250 // do not allow multiselection with note caption
251 bool bCaptionClicked = IsNoteCaptionClicked( aMDPos );
252 if ( !rMEvt.IsShift() || bCaptionClicked || IsNoteCaptionMarked() )
253 pView->UnmarkAll();
255 /* Unlock internal layer, if a note caption is clicked. The
256 layer will be relocked in ScDrawView::MarkListHasChanged(). */
257 if( bCaptionClicked )
258 pView->UnlockInternalLayer();
260 // try to select the clicked object
261 if ( pView->MarkObj( aMDPos, -2, false, rMEvt.IsMod1() ) )
264 // move object
266 if (pView->IsMarkedHit(aMDPos))
268 // Don't start drag timer if inplace editing of an OLE object
269 // was just ended with this mouse click - the view will be moved
270 // (different tool bars) and the object that was clicked on would
271 // be moved unintentionally.
272 if ( !bWasOleActive )
273 aDragTimer.Start();
275 pHdl=pView->PickHandle(aMDPos);
276 pView->BegDragObj(aMDPos, nullptr, pHdl);
277 bReturn = true;
279 else // object at the edge
280 if (rViewShell.IsDrawSelMode())
281 bReturn = true;
283 else
285 if (rViewShell.IsDrawSelMode())
288 // select object
290 pView->BegMarkObj(aMDPos);
291 bReturn = true;
299 if (!bIsInDragMode)
301 // VC calls CaptureMouse itself
302 pWindow->CaptureMouse();
303 ForcePointer(&rMEvt);
306 return bReturn;
309 bool FuSelection::MouseMove(const MouseEvent& rMEvt)
311 bool bReturn = FuDraw::MouseMove(rMEvt);
313 if (aDragTimer.IsActive() )
315 Point aOldPixel = pWindow->LogicToPixel( aMDPos );
316 Point aNewPixel = rMEvt.GetPosPixel();
317 if ( std::abs( aOldPixel.X() - aNewPixel.X() ) > SC_MAXDRAGMOVE ||
318 std::abs( aOldPixel.Y() - aNewPixel.Y() ) > SC_MAXDRAGMOVE )
319 aDragTimer.Stop();
322 if ( pView->IsAction() )
324 Point aPix(rMEvt.GetPosPixel());
325 Point aPnt(pWindow->PixelToLogic(aPix));
327 ForceScroll(aPix);
328 pView->MovAction(aPnt);
329 bReturn = true;
332 ForcePointer(&rMEvt);
334 return bReturn;
337 bool FuSelection::MouseButtonUp(const MouseEvent& rMEvt)
339 // remember button state for creation of own MouseEvents
340 SetMouseButtonCode(rMEvt.GetButtons());
342 bool bReturn = FuDraw::MouseButtonUp(rMEvt);
343 bool bOle = rViewShell.GetViewFrame().GetFrame().IsInPlace();
345 SdrObject* pObj = nullptr;
346 if (aDragTimer.IsActive() )
348 aDragTimer.Stop();
351 sal_uInt16 nDrgLog = sal_uInt16 ( pWindow->PixelToLogic(Size(SC_MINDRAGMOVE,0)).Width() );
352 auto aLogicPosition = rMEvt.getLogicPosition();
353 Point aPnt(aLogicPosition ? *aLogicPosition : pWindow->PixelToLogic(rMEvt.GetPosPixel()));
355 bool bCopy = false;
356 ScViewData& rViewData = rViewShell.GetViewData();
357 ScDocument& rDocument = rViewData.GetDocument();
358 SdrPageView* pPageView = ( pView ? pView->GetSdrPageView() : nullptr );
359 SdrPage* pPage = ( pPageView ? pPageView->GetPage() : nullptr );
360 ::std::vector< OUString > aExcludedChartNames;
361 ScRangeListVector aProtectedChartRangesVector;
363 if (comphelper::LibreOfficeKit::isActive() && rDocument.IsNegativePage(rViewData.GetTabNo()))
364 aPnt.setX(-aPnt.X());
366 if (pView && rMEvt.IsLeft())
368 if ( pView->IsDragObj() )
370 // object was moved
371 if ( rMEvt.IsMod1() )
373 if ( pPage )
375 ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
377 if ( pView )
379 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
380 const size_t nMarkCount = rMarkList.GetMarkCount();
381 for ( size_t i = 0; i < nMarkCount; ++i )
383 SdrMark* pMark = rMarkList.GetMark( i );
384 pObj = ( pMark ? pMark->GetMarkedSdrObj() : nullptr );
385 if ( pObj )
387 ScChartHelper::AddRangesIfProtectedChart( aProtectedChartRangesVector, rDocument, pObj );
391 bCopy = true;
394 if (!rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() &&
395 std::abs(aPnt.X() - aMDPos.X()) < nDrgLog &&
396 std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog)
398 /* If a user wants to click on an object in front of a marked
399 one, he releases the mouse button immediately */
400 SdrPageView* pPV = nullptr;
401 pObj = pView->PickObj(aMDPos, pView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK);
402 if (pObj)
404 pView->UnmarkAllObj();
405 pView->MarkObj(pObj,pPV);
406 return true;
409 pView->EndDragObj( rMEvt.IsMod1() );
410 pView->ForceMarkedToAnotherPage();
412 bReturn = true;
414 else if (pView->IsAction() )
416 // unlock internal layer to include note captions
417 pView->UnlockInternalLayer();
418 pView->EndAction();
419 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
420 if ( rMarkList.GetMarkCount() != 0 )
422 bReturn = true;
424 /* if multi-selection contains a note caption object, remove
425 all other objects from selection. */
426 const size_t nCount = rMarkList.GetMarkCount();
427 if( nCount > 1 )
429 bool bFound = false;
430 for( size_t nIdx = 0; !bFound && (nIdx < nCount); ++nIdx )
432 pObj = rMarkList.GetMark( nIdx )->GetMarkedSdrObj();
433 bFound = ScDrawLayer::IsNoteCaption( pObj );
434 if( bFound )
436 pView->UnMarkAll();
437 pView->MarkObj( pObj, pView->GetSdrPageView() );
444 if (ScModule::get()->GetIsWaterCan())
446 auto pStyleSheet = rViewData.GetDocument().GetStyleSheetPool()->GetActualStyleSheet();
447 if (pStyleSheet && pStyleSheet->GetFamily() == SfxStyleFamily::Frame)
448 pView->SetStyleSheet(static_cast<SfxStyleSheet*>(pStyleSheet), false);
452 // maybe consider OLE object
453 SfxInPlaceClient* pIPClient = rViewShell.GetIPClient();
455 if (pIPClient)
457 ScModule* pScMod = ScModule::get();
458 bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF;
460 if ( pIPClient->IsObjectInPlaceActive() && !bUnoRefDialog )
461 pIPClient->DeactivateObject();
464 sal_uInt16 nClicks = rMEvt.GetClicks();
465 if (pView && nClicks == 2 && rMEvt.IsLeft())
467 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
468 if ( rMarkList.GetMarkCount() != 0 )
470 if (rMarkList.GetMarkCount() == 1)
472 SdrMark* pMark = rMarkList.GetMark(0);
473 pObj = pMark->GetMarkedSdrObj();
475 // only activate, when the mouse also is over the selected object
477 SdrViewEvent aVEvt;
478 SdrHitKind eHit = pView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
479 if (eHit != SdrHitKind::NONE && aVEvt.mpObj == pObj)
481 assert(pObj);
483 SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
485 // OLE: activate
487 if (nSdrObjKind == SdrObjKind::OLE2)
489 if (!bOle)
491 if (static_cast<SdrOle2Obj*>(pObj)->GetObjRef().is())
493 // release so if ActivateObject launches a warning dialog, then that dialog
494 // can get mouse events
495 if (pWindow->IsMouseCaptured())
496 pWindow->ReleaseMouse();
497 rViewShell.ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
502 // Edit text
503 // not in UNO controls
504 // #i32352# not in media objects
506 else if ( DynCastSdrTextObj( pObj) != nullptr && dynamic_cast<const SdrUnoObj*>( pObj) == nullptr && dynamic_cast<const SdrMediaObj*>( pObj) == nullptr )
508 OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
509 bool bVertical = ( pOPO && pOPO->IsEffectivelyVertical() );
510 sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
512 rViewShell.GetViewData().GetDispatcher().
513 Execute(nTextSlotId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
515 // Get the created FuText now and change into EditMode
516 FuPoor* pPoor = rViewShell.GetViewData().GetView()->GetDrawFuncPtr();
517 if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // has no RTTI
519 FuText* pText = static_cast<FuText*>(pPoor);
520 Point aMousePixel = rMEvt.GetPosPixel();
521 pText->SetInEditMode( pObj, &aMousePixel );
523 bReturn = true;
528 else if ( TestDetective( pView->GetSdrPageView(), aPnt ) )
529 bReturn = true;
532 ForcePointer(&rMEvt);
534 if (pWindow->IsMouseCaptured())
535 pWindow->ReleaseMouse();
537 // command handler for context menu follows after MouseButtonUp,
538 // therefore here the hard IsLeft call
539 if ( !bReturn && rMEvt.IsLeft() )
540 if (rViewShell.IsDrawSelMode())
541 rViewShell.GetViewData().GetDispatcher().
542 Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
544 if ( bCopy && pPage )
546 ScDocShell* pDocShell = rViewData.GetDocShell();
547 ScModelObj* pModelObj = ( pDocShell ? pDocShell->GetModel() : nullptr );
548 if ( pModelObj )
550 SCTAB nTab = rViewData.GetTabNo();
551 ScChartHelper::CreateProtectedChartListenersAndNotify( rDocument, pPage, pModelObj, nTab,
552 aProtectedChartRangesVector, aExcludedChartNames );
556 return bReturn;
559 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */