Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / drawfunc / fusel.cxx
blob13e1d30534c4d3d8907a5173c3a46f8e9bd90a22
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/EmbedStates.hpp>
22 #include <editeng/eeitem.hxx>
23 #include <editeng/flditem.hxx>
24 #include <svx/svdoole2.hxx>
25 #include <svx/svdotext.hxx>
26 #include <sfx2/dispatch.hxx>
27 #include <svtools/imapobj.hxx>
28 #include <svx/svdouno.hxx>
29 #include <svx/svdomedia.hxx>
30 #include <svx/svdpagv.hxx>
31 #include <editeng/outlobj.hxx>
32 #include <svx/svdocapt.hxx>
33 #include <sfx2/app.hxx>
35 #include "fusel.hxx"
36 #include "sc.hrc"
37 #include "fudraw.hxx"
38 #include "futext.hxx"
39 #include "drawview.hxx"
40 #include "tabvwsh.hxx"
41 #include "drawpage.hxx"
42 #include "globstr.hrc"
43 #include "drwlayer.hxx"
44 #include "userdat.hxx"
45 #include "scmod.hxx"
46 #include "client.hxx"
47 #include "charthelper.hxx"
48 #include "docuno.hxx"
49 #include "docsh.hxx"
51 // -----------------------------------------------------------------------
53 // Maximal erlaubte Mausbewegung um noch Drag&Drop zu starten
54 //! fusel,fuconstr,futext - zusammenfassen!
55 #define SC_MAXDRAGMOVE 3
56 // Min necessary mouse motion for normal dragging
57 #define SC_MINDRAGMOVE 2
59 // -----------------------------------------------------------------------
61 using namespace com::sun::star;
63 /*************************************************************************
65 |* Konstruktor
67 \************************************************************************/
69 FuSelection::FuSelection(ScTabViewShell* pViewSh, Window* pWin, ScDrawView* pViewP,
70 SdrModel* pDoc, SfxRequest& rReq ) :
71 FuDraw(pViewSh, pWin, pViewP, pDoc, rReq),
72 bVCAction(false)
76 /*************************************************************************
78 |* Destruktor
80 \************************************************************************/
82 FuSelection::~FuSelection()
86 sal_uInt8 FuSelection::Command(const CommandEvent& rCEvt)
88 return FuDraw::Command( rCEvt );
91 /*************************************************************************
93 |* MouseButtonDown-event
95 \************************************************************************/
97 sal_Bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
99 // remember button state for creation of own MouseEvents
100 SetMouseButtonCode(rMEvt.GetButtons());
101 const bool bSelectionOnly = rMEvt.IsRight();
102 if ( pView->IsAction() )
104 if ( bSelectionOnly )
105 pView->BckAction();
106 return sal_True;
109 bVCAction = false;
110 bIsInDragMode = false; // irgendwo muss es ja zurueckgesetzt werden (#50033#)
112 sal_Bool bReturn = FuDraw::MouseButtonDown(rMEvt);
114 aMDPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
116 if ( rMEvt.IsLeft() )
118 SdrHdl* pHdl = pView->PickHandle(aMDPos);
120 if ( pHdl!=NULL || pView->IsMarkedHit(aMDPos) )
122 // Determine if this is the tail of a SdrCaptionObj i.e.
123 // we need to disable the drag option on the tail of a note
124 // object. Also, disable the ability to use the circular
125 // drag of a note object.
126 bool bDrag = false;
127 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
128 if( rMarkList.GetMarkCount() == 1 )
130 SdrObject* pMarkedObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
131 if( ScDrawLayer::IsNoteCaption( pMarkedObj ) )
133 // move using the valid caption handles for note text box.
134 if(pHdl && (pHdl->GetKind() != HDL_POLY && pHdl->GetKind() != HDL_CIRC))
135 bDrag = true;
136 // move the complete note box.
137 else if(!pHdl)
138 bDrag = true;
140 else
141 bDrag = true; // different object
143 else
144 bDrag = true; // several objects
146 if ( bDrag )
148 aDragTimer.Start();
149 pView->BegDragObj(aMDPos, (OutputDevice*) NULL, pHdl);
150 bReturn = sal_True;
153 else
155 SdrObject* pObj;
156 SdrPageView* pPV;
157 sal_Bool bAlt = rMEvt.IsMod2();
158 if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMACRO) )
160 pView->BegMacroObj(aMDPos, pObj, pPV, pWindow);
161 bReturn = sal_True;
163 else
165 OUString sURL, sTarget;
166 if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER))
168 // Support for imported Excel docs
169 // Excel is of course not consistent and allows
170 // a hyperlink to be assigned for an object group
171 // and even though the hyperlink is exported in the Escher layer
172 // its never used, when dealing with a group object the link
173 // associated with the clicked object is used only
175 // additionally you can also select a macro in Excel for a grouped
176 // objects and this *usually* results in the macro being set
177 // for the elements in the group and no macro is exported
178 // for the group itself ( this however is not always true )
179 // if a macro and hlink are defined favour the hlink
180 // If a group object has no hyperlink use the hyperlink of the
181 // object clicked
183 if ( pObj->IsGroupObject() )
185 ScMacroInfo* pTmpInfo = ScDrawLayer::GetMacroInfo( pObj );
186 if ( !pTmpInfo || pTmpInfo->GetMacro().isEmpty() )
188 SdrObject* pHit = NULL;
189 if ( pView->PickObj(aMDPos, pView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) )
190 pObj = pHit;
194 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj, true );
195 // For interoperability favour links over macros if both are defined
196 if ( !pInfo->GetHlink().isEmpty() )
198 OSL_TRACE("** Got URL");
199 sURL = pInfo->GetHlink();
201 else if ( !pInfo->GetMacro().isEmpty() )
203 SfxObjectShell* pObjSh = SfxObjectShell::Current();
204 if ( pObjSh && SfxApplication::IsXScriptURL( pInfo->GetMacro() ) )
206 uno::Reference< beans::XPropertySet > xProps( pObj->getUnoShape(), uno::UNO_QUERY );
207 uno::Any aCaller;
208 if ( xProps.is() )
212 aCaller = xProps->getPropertyValue("Name");
214 catch( uno::Exception& ) {}
216 uno::Any aRet;
217 uno::Sequence< sal_Int16 > aOutArgsIndex;
218 uno::Sequence< uno::Any > aOutArgs;
219 uno::Sequence< uno::Any >* pInArgs =
220 new uno::Sequence< uno::Any >(0);
221 pObjSh->CallXScript( pInfo->GetMacro(),
222 *pInArgs, aRet, aOutArgsIndex, aOutArgs, true, &aCaller );
223 pViewShell->FakeButtonUp( pViewShell->GetViewData()->GetActivePart() );
224 return sal_True; // kein CaptureMouse etc.
229 // URL / ImageMap
231 SdrViewEvent aVEvt;
232 if ( !bAlt &&
233 pView->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt ) != SDRHIT_NONE &&
234 aVEvt.pObj != NULL )
236 if ( ScDrawLayer::GetIMapInfo( aVEvt.pObj ) ) // ImageMap
238 const IMapObject* pIMapObj =
239 ScDrawLayer::GetHitIMapObject( aVEvt.pObj, aMDPos, *pWindow );
240 if ( pIMapObj && !pIMapObj->GetURL().isEmpty() )
242 sURL = pIMapObj->GetURL();
243 sTarget = pIMapObj->GetTarget();
246 if ( aVEvt.eEvent == SDREVENT_EXECUTEURL && aVEvt.pURLField ) // URL
248 sURL = aVEvt.pURLField->GetURL();
249 sTarget = aVEvt.pURLField->GetTargetFrame();
253 // open hyperlink, if found at object or in object's text
254 if ( !sURL.isEmpty() )
256 ScGlobal::OpenURL( sURL, sTarget );
257 pViewShell->FakeButtonUp( pViewShell->GetViewData()->GetActivePart() );
258 return sal_True; // kein CaptureMouse etc.
261 // Is another object being edited in this view?
262 // (Editing is ended in MarkListHasChanged - test before UnmarkAll)
263 SfxInPlaceClient* pClient = pViewShell->GetIPClient();
264 sal_Bool bWasOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
266 // Markieren
268 // do not allow multiselection with note caption
269 bool bCaptionClicked = IsNoteCaptionClicked( aMDPos );
270 if ( !rMEvt.IsShift() || bCaptionClicked || IsNoteCaptionMarked() )
271 pView->UnmarkAll();
273 /* Unlock internal layer, if a note caption is clicked. The
274 layer will be relocked in ScDrawView::MarkListHasChanged(). */
275 if( bCaptionClicked )
276 pView->UnlockInternalLayer();
278 // try to select the clicked object
279 if ( pView->MarkObj( aMDPos, -2, false, rMEvt.IsMod1() ) )
281 //*********************************************************
282 //Objekt verschieben
283 //********************************************************
284 if (pView->IsMarkedHit(aMDPos))
286 // Don't start drag timer if inplace editing of an OLE object
287 // was just ended with this mouse click - the view will be moved
288 // (different tool bars) and the object that was clicked on would
289 // be moved unintentionally.
290 if ( !bWasOleActive )
291 aDragTimer.Start();
293 pHdl=pView->PickHandle(aMDPos);
294 pView->BegDragObj(aMDPos, (OutputDevice*) NULL, pHdl);
295 bReturn = sal_True;
297 else // Objekt am Rand getroffen
298 if (pViewShell->IsDrawSelMode())
299 bReturn = sal_True;
301 else
303 // nichts getroffen
305 if (pViewShell->IsDrawSelMode())
307 //*********************************************************
308 //Objekt selektieren
309 //********************************************************
310 pView->BegMarkObj(aMDPos);
311 bReturn = sal_True;
319 if (!bIsInDragMode)
321 if (!bVCAction) // VC rufen selber CaptureMouse
322 pWindow->CaptureMouse();
323 ForcePointer(&rMEvt);
326 return bReturn;
329 /*************************************************************************
331 |* MouseMove-event
333 \************************************************************************/
335 sal_Bool FuSelection::MouseMove(const MouseEvent& rMEvt)
337 sal_Bool bReturn = FuDraw::MouseMove(rMEvt);
339 if (aDragTimer.IsActive() )
341 Point aOldPixel = pWindow->LogicToPixel( aMDPos );
342 Point aNewPixel = rMEvt.GetPosPixel();
343 if ( std::abs( aOldPixel.X() - aNewPixel.X() ) > SC_MAXDRAGMOVE ||
344 std::abs( aOldPixel.Y() - aNewPixel.Y() ) > SC_MAXDRAGMOVE )
345 aDragTimer.Stop();
348 if ( pView->IsAction() )
350 Point aPix(rMEvt.GetPosPixel());
351 Point aPnt(pWindow->PixelToLogic(aPix));
353 ForceScroll(aPix);
354 pView->MovAction(aPnt);
355 bReturn = sal_True;
358 // Ein VCControl ist aktiv
359 // Event an den Manager weiterleiten
360 if( bVCAction )
362 bReturn = true;
365 ForcePointer(&rMEvt);
367 return (bReturn);
370 /*************************************************************************
372 |* MouseButtonUp-event
374 \************************************************************************/
376 sal_Bool FuSelection::MouseButtonUp(const MouseEvent& rMEvt)
378 // remember button state for creation of own MouseEvents
379 SetMouseButtonCode(rMEvt.GetButtons());
381 sal_Bool bReturn = FuDraw::MouseButtonUp(rMEvt);
382 sal_Bool bOle = pViewShell->GetViewFrame()->GetFrame().IsInPlace();
384 SdrObject* pObj = NULL;
385 SdrPageView* pPV = NULL;
386 if (aDragTimer.IsActive() )
388 aDragTimer.Stop();
391 sal_uInt16 nDrgLog = sal_uInt16 ( pWindow->PixelToLogic(Size(SC_MINDRAGMOVE,0)).Width() );
392 Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
394 bool bCopy = false;
395 ScViewData* pViewData = ( pViewShell ? pViewShell->GetViewData() : NULL );
396 ScDocument* pDocument = ( pViewData ? pViewData->GetDocument() : NULL );
397 SdrPageView* pPageView = ( pView ? pView->GetSdrPageView() : NULL );
398 SdrPage* pPage = ( pPageView ? pPageView->GetPage() : NULL );
399 ::std::vector< OUString > aExcludedChartNames;
400 ScRangeListVector aProtectedChartRangesVector;
402 if ( rMEvt.IsLeft() )
404 if ( pView->IsDragObj() )
406 /******************************************************************
407 * Objekt wurde verschoben
408 ******************************************************************/
409 if ( rMEvt.IsMod1() )
411 if ( pPage )
413 ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
415 if ( pView && pDocument )
417 const SdrMarkList& rSdrMarkList = pView->GetMarkedObjectList();
418 sal_uLong nMarkCount = rSdrMarkList.GetMarkCount();
419 for ( sal_uLong i = 0; i < nMarkCount; ++i )
421 SdrMark* pMark = rSdrMarkList.GetMark( i );
422 pObj = ( pMark ? pMark->GetMarkedSdrObj() : NULL );
423 if ( pObj )
425 ScChartHelper::AddRangesIfProtectedChart( aProtectedChartRangesVector, pDocument, pObj );
429 bCopy = true;
432 if (!rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() &&
433 std::abs(aPnt.X() - aMDPos.X()) < nDrgLog &&
434 std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog)
436 /*************************************************************
437 * If a user wants to click on an object in front of a marked
438 * one, he releases the mouse button immediately
439 **************************************************************/
440 if (pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER | SDRSEARCH_BEFOREMARK))
442 pView->UnmarkAllObj();
443 pView->MarkObj(pObj,pPV,false,false);
444 return (sal_True);
447 pView->EndDragObj( rMEvt.IsMod1() );
448 pView->ForceMarkedToAnotherPage();
450 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
451 if (rMarkList.GetMarkCount() == 1)
453 SdrMark* pMark = rMarkList.GetMark(0);
454 pObj = pMark->GetMarkedSdrObj();
455 FuPoor* pPoor = pViewShell->GetViewData()->GetView()->GetDrawFuncPtr();
456 FuText* pText = static_cast<FuText*>(pPoor);
457 pText->StopDragMode(pObj );
459 bReturn = sal_True;
461 else if (pView->IsAction() )
463 // unlock internal layer to include note captions
464 pView->UnlockInternalLayer();
465 pView->EndAction();
466 if ( pView->AreObjectsMarked() )
468 bReturn = sal_True;
470 /* if multi-selection contains a note caption object, remove
471 all other objects from selection. */
472 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
473 sal_uLong nCount = rMarkList.GetMarkCount();
474 if( nCount > 1 )
476 bool bFound = false;
477 for( sal_uLong nIdx = 0; !bFound && (nIdx < nCount); ++nIdx )
479 pObj = rMarkList.GetMark( nIdx )->GetMarkedSdrObj();
480 bFound = ScDrawLayer::IsNoteCaption( pObj );
481 if( bFound )
483 pView->UnMarkAll();
484 pView->MarkObj( pObj, pView->GetSdrPageView() );
492 /**************************************************************************
493 * Ggf. OLE-Objekt beruecksichtigen
494 **************************************************************************/
495 SfxInPlaceClient* pIPClient = pViewShell->GetIPClient();
497 if (pIPClient)
499 ScModule* pScMod = SC_MOD();
500 bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF;
502 if ( pIPClient->IsObjectInPlaceActive() && !bUnoRefDialog )
503 pIPClient->DeactivateObject();
506 sal_uInt16 nClicks = rMEvt.GetClicks();
507 if ( nClicks == 2 && rMEvt.IsLeft() )
509 if ( pView->AreObjectsMarked() )
511 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
512 if (rMarkList.GetMarkCount() == 1)
514 SdrMark* pMark = rMarkList.GetMark(0);
515 pObj = pMark->GetMarkedSdrObj();
517 // aktivieren nur, wenn die Maus auch (noch) ueber dem
518 // selektierten Objekt steht
520 SdrViewEvent aVEvt;
521 SdrHitKind eHit = pView->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt );
522 if ( eHit != SDRHIT_NONE && aVEvt.pObj == pObj )
524 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
527 // OLE: aktivieren
530 if (nSdrObjKind == OBJ_OLE2)
532 if (!bOle)
534 if (((SdrOle2Obj*) pObj)->GetObjRef().is())
536 pViewShell->ActivateObject( (SdrOle2Obj*) pObj, 0 );
542 // Edit text
543 // not in UNO controls
544 // #i32352# not in media objects
546 else if ( pObj->ISA(SdrTextObj) && !pObj->ISA(SdrUnoObj) && !pObj->ISA(SdrMediaObj) )
548 OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
549 sal_Bool bVertical = ( pOPO && pOPO->IsVertical() );
550 sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
552 pViewShell->GetViewData()->GetDispatcher().
553 Execute(nTextSlotId, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD);
555 // jetzt den erzeugten FuText holen und in den EditModus setzen
556 FuPoor* pPoor = pViewShell->GetViewData()->GetView()->GetDrawFuncPtr();
557 if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // hat keine RTTI
559 FuText* pText = (FuText*)pPoor;
560 Point aMousePixel = rMEvt.GetPosPixel();
561 pText->SetInEditMode( pObj, &aMousePixel );
563 bReturn = sal_True;
568 else if ( TestDetective( pView->GetSdrPageView(), aPnt ) )
569 bReturn = sal_True;
572 // Ein VCControl ist aktiv
573 // Event an den Manager weiterleiten
574 if( bVCAction )
576 bVCAction = false;
577 bReturn = true;
580 ForcePointer(&rMEvt);
582 pWindow->ReleaseMouse();
584 // Command-Handler fuer Kontext-Menue kommt erst nach MouseButtonUp,
585 // darum hier die harte IsLeft-Abfrage
586 if ( !bReturn && rMEvt.IsLeft() )
587 if (pViewShell->IsDrawSelMode())
588 pViewShell->GetViewData()->GetDispatcher().
589 Execute(SID_OBJECT_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
591 if ( bCopy && pViewData && pDocument && pPage )
593 ScDocShell* pDocShell = pViewData->GetDocShell();
594 ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL );
595 if ( pModelObj )
597 SCTAB nTab = pViewData->GetTabNo();
598 ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pPage, pModelObj, nTab,
599 aProtectedChartRangesVector, aExcludedChartNames );
603 return (bReturn);
606 /*************************************************************************
608 |* Tastaturereignisse bearbeiten
610 |* Wird ein KeyEvent bearbeitet, so ist der Return-Wert sal_True, andernfalls
611 |* FALSE.
613 \************************************************************************/
615 sal_Bool FuSelection::KeyInput(const KeyEvent& rKEvt)
617 sal_Bool bReturn = false;
619 if (!bReturn)
621 bReturn = FuDraw::KeyInput(rKEvt);
624 return(bReturn);
628 /*************************************************************************
630 |* Function aktivieren
632 \************************************************************************/
634 void FuSelection::Activate()
636 FuDraw::Activate();
639 /*************************************************************************
641 |* Function deaktivieren
643 \************************************************************************/
645 void FuSelection::Deactivate()
647 /**************************************************************************
648 * Hide Cursor
649 **************************************************************************/
650 FuDraw::Deactivate();
653 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */