fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / drawfunc / fusel.cxx
bloba51363d91865782a76c352ab695bae6491c319aa
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/svddrgmt.hxx>
25 #include <svx/svdoole2.hxx>
26 #include <svx/svdotext.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <svtools/imapobj.hxx>
29 #include <svx/svdouno.hxx>
30 #include <svx/svdomedia.hxx>
31 #include <svx/svdpagv.hxx>
32 #include <editeng/outlobj.hxx>
33 #include <svx/svdocapt.hxx>
34 #include <sfx2/app.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 "drawpage.hxx"
43 #include "globstr.hrc"
44 #include "drwlayer.hxx"
45 #include "userdat.hxx"
46 #include "scmod.hxx"
47 #include "client.hxx"
48 #include "charthelper.hxx"
49 #include "docuno.hxx"
50 #include "docsh.hxx"
52 // Maximal erlaubte Mausbewegung um noch Drag&Drop zu starten
53 //! fusel,fuconstr,futext - zusammenfassen!
54 #define SC_MAXDRAGMOVE 3
55 // Min necessary mouse motion for normal dragging
56 #define SC_MINDRAGMOVE 2
58 using namespace com::sun::star;
60 /*************************************************************************
62 |* Konstruktor
64 \************************************************************************/
66 FuSelection::FuSelection(ScTabViewShell* pViewSh, vcl::Window* pWin, ScDrawView* pViewP,
67 SdrModel* pDoc, SfxRequest& rReq ) :
68 FuDraw(pViewSh, pWin, pViewP, pDoc, rReq),
69 bVCAction(false)
73 /*************************************************************************
75 |* Destruktor
77 \************************************************************************/
79 FuSelection::~FuSelection()
83 sal_uInt8 FuSelection::Command(const CommandEvent& rCEvt)
85 return FuDraw::Command( rCEvt );
88 /*************************************************************************
90 |* MouseButtonDown-event
92 \************************************************************************/
94 bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
96 // remember button state for creation of own MouseEvents
97 SetMouseButtonCode(rMEvt.GetButtons());
98 const bool bSelectionOnly = rMEvt.IsRight();
99 if ( pView->IsAction() )
101 if ( bSelectionOnly )
102 pView->BckAction();
103 return true;
106 bVCAction = false;
107 bIsInDragMode = false; // irgendwo muss es ja zurueckgesetzt werden (#50033#)
109 bool bReturn = FuDraw::MouseButtonDown(rMEvt);
111 aMDPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
113 if ( rMEvt.IsLeft() )
115 SdrHdl* pHdl = pView->PickHandle(aMDPos);
117 if ( pHdl!=NULL || pView->IsMarkedHit(aMDPos) )
119 // Determine if this is the tail of a SdrCaptionObj i.e.
120 // we need to disable the drag option on the tail of a note
121 // object. Also, disable the ability to use the circular
122 // drag of a note object.
123 bool bDrag = false;
124 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
125 if( rMarkList.GetMarkCount() == 1 )
127 SdrObject* pMarkedObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
128 if( ScDrawLayer::IsNoteCaption( pMarkedObj ) )
130 // move using the valid caption handles for note text box.
131 if(pHdl && (pHdl->GetKind() != HDL_POLY && pHdl->GetKind() != HDL_CIRC))
132 bDrag = true;
133 // move the complete note box.
134 else if(!pHdl)
135 bDrag = true;
137 else
138 bDrag = true; // different object
140 else
141 bDrag = true; // several objects
143 if ( bDrag )
145 aDragTimer.Start();
146 if (pView->BegDragObj(aMDPos, (OutputDevice*) NULL, pHdl))
147 pView->GetDragMethod()->SetShiftPressed( rMEvt.IsShift() );
148 bReturn = true;
151 else
153 SdrObject* pObj;
154 SdrPageView* pPV;
155 bool bAlt = rMEvt.IsMod2();
156 if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SdrSearchOptions::PICKMACRO) )
158 pView->BegMacroObj(aMDPos, pObj, pPV, pWindow);
159 bReturn = true;
161 else
163 OUString sURL, sTarget;
164 if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SdrSearchOptions::ALSOONMASTER))
166 // Support for imported Excel docs
167 // Excel is of course not consistent and allows
168 // a hyperlink to be assigned for an object group
169 // and even though the hyperlink is exported in the Escher layer
170 // its never used, when dealing with a group object the link
171 // associated with the clicked object is used only
173 // additionally you can also select a macro in Excel for a grouped
174 // objects and this *usually* results in the macro being set
175 // for the elements in the group and no macro is exported
176 // for the group itself ( this however is not always true )
177 // if a macro and hlink are defined favour the hlink
178 // If a group object has no hyperlink use the hyperlink of the
179 // object clicked
181 if ( pObj->IsGroupObject() )
183 ScMacroInfo* pTmpInfo = ScDrawLayer::GetMacroInfo( pObj );
184 if ( !pTmpInfo || pTmpInfo->GetMacro().isEmpty() )
186 SdrObject* pHit = NULL;
187 if ( pView->PickObj(aMDPos, pView->getHitTolLog(), pHit, pPV, SdrSearchOptions::DEEP ) )
188 pObj = pHit;
192 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj, true );
193 // For interoperability favour links over macros if both are defined
194 if ( !pInfo->GetHlink().isEmpty() )
196 OSL_TRACE("** Got URL");
197 sURL = pInfo->GetHlink();
199 else if ( !pInfo->GetMacro().isEmpty() )
201 SfxObjectShell* pObjSh = SfxObjectShell::Current();
202 if ( pObjSh && SfxApplication::IsXScriptURL( pInfo->GetMacro() ) )
204 uno::Reference< beans::XPropertySet > xProps( pObj->getUnoShape(), uno::UNO_QUERY );
205 uno::Any aCaller;
206 if ( xProps.is() )
210 aCaller = xProps->getPropertyValue("Name");
212 catch( uno::Exception& ) {}
214 uno::Any aRet;
215 uno::Sequence< sal_Int16 > aOutArgsIndex;
216 uno::Sequence< uno::Any > aOutArgs;
217 uno::Sequence< uno::Any >* pInArgs =
218 new uno::Sequence< uno::Any >(0);
219 pObjSh->CallXScript( pInfo->GetMacro(),
220 *pInArgs, aRet, aOutArgsIndex, aOutArgs, true, &aCaller );
221 pViewShell->FakeButtonUp( pViewShell->GetViewData().GetActivePart() );
222 return true; // kein CaptureMouse etc.
227 // URL / ImageMap
229 SdrViewEvent aVEvt;
230 if ( !bAlt &&
231 pView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt ) != SDRHIT_NONE &&
232 aVEvt.pObj != NULL )
234 if ( ScDrawLayer::GetIMapInfo( aVEvt.pObj ) ) // ImageMap
236 const IMapObject* pIMapObj =
237 ScDrawLayer::GetHitIMapObject( aVEvt.pObj, aMDPos, *pWindow );
238 if ( pIMapObj && !pIMapObj->GetURL().isEmpty() )
240 sURL = pIMapObj->GetURL();
241 sTarget = pIMapObj->GetTarget();
244 if ( aVEvt.eEvent == SDREVENT_EXECUTEURL && aVEvt.pURLField ) // URL
246 sURL = aVEvt.pURLField->GetURL();
247 sTarget = aVEvt.pURLField->GetTargetFrame();
251 // open hyperlink, if found at object or in object's text
252 if ( !sURL.isEmpty() )
254 ScGlobal::OpenURL( sURL, sTarget );
255 pViewShell->FakeButtonUp( pViewShell->GetViewData().GetActivePart() );
256 return true; // kein CaptureMouse etc.
259 // Is another object being edited in this view?
260 // (Editing is ended in MarkListHasChanged - test before UnmarkAll)
261 SfxInPlaceClient* pClient = pViewShell->GetIPClient();
262 bool bWasOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
264 // Markieren
266 // do not allow multiselection with note caption
267 bool bCaptionClicked = IsNoteCaptionClicked( aMDPos );
268 if ( !rMEvt.IsShift() || bCaptionClicked || IsNoteCaptionMarked() )
269 pView->UnmarkAll();
271 /* Unlock internal layer, if a note caption is clicked. The
272 layer will be relocked in ScDrawView::MarkListHasChanged(). */
273 if( bCaptionClicked )
274 pView->UnlockInternalLayer();
276 // try to select the clicked object
277 if ( pView->MarkObj( aMDPos, -2, false, rMEvt.IsMod1() ) )
280 //Objekt verschieben
282 if (pView->IsMarkedHit(aMDPos))
284 // Don't start drag timer if inplace editing of an OLE object
285 // was just ended with this mouse click - the view will be moved
286 // (different tool bars) and the object that was clicked on would
287 // be moved unintentionally.
288 if ( !bWasOleActive )
289 aDragTimer.Start();
291 pHdl=pView->PickHandle(aMDPos);
292 pView->BegDragObj(aMDPos, (OutputDevice*) NULL, pHdl);
293 bReturn = true;
295 else // Objekt am Rand getroffen
296 if (pViewShell->IsDrawSelMode())
297 bReturn = true;
299 else
301 // nichts getroffen
303 if (pViewShell->IsDrawSelMode())
306 //Objekt selektieren
308 pView->BegMarkObj(aMDPos);
309 bReturn = true;
317 if (!bIsInDragMode)
319 if (!bVCAction) // VC rufen selber CaptureMouse
320 pWindow->CaptureMouse();
321 ForcePointer(&rMEvt);
324 return bReturn;
327 /*************************************************************************
329 |* MouseMove-event
331 \************************************************************************/
333 bool FuSelection::MouseMove(const MouseEvent& rMEvt)
335 bool bReturn = FuDraw::MouseMove(rMEvt);
337 if (aDragTimer.IsActive() )
339 Point aOldPixel = pWindow->LogicToPixel( aMDPos );
340 Point aNewPixel = rMEvt.GetPosPixel();
341 if ( std::abs( aOldPixel.X() - aNewPixel.X() ) > SC_MAXDRAGMOVE ||
342 std::abs( aOldPixel.Y() - aNewPixel.Y() ) > SC_MAXDRAGMOVE )
343 aDragTimer.Stop();
346 if ( pView->IsAction() )
348 Point aPix(rMEvt.GetPosPixel());
349 Point aPnt(pWindow->PixelToLogic(aPix));
351 ForceScroll(aPix);
352 pView->MovAction(aPnt);
353 bReturn = true;
356 // Ein VCControl ist aktiv
357 // Event an den Manager weiterleiten
358 if( bVCAction )
360 bReturn = true;
363 ForcePointer(&rMEvt);
365 return bReturn;
368 /*************************************************************************
370 |* MouseButtonUp-event
372 \************************************************************************/
374 bool FuSelection::MouseButtonUp(const MouseEvent& rMEvt)
376 // remember button state for creation of own MouseEvents
377 SetMouseButtonCode(rMEvt.GetButtons());
379 bool bReturn = FuDraw::MouseButtonUp(rMEvt);
380 bool bOle = pViewShell && pViewShell->GetViewFrame()->GetFrame().IsInPlace();
382 SdrObject* pObj = NULL;
383 if (aDragTimer.IsActive() )
385 aDragTimer.Stop();
388 sal_uInt16 nDrgLog = sal_uInt16 ( pWindow->PixelToLogic(Size(SC_MINDRAGMOVE,0)).Width() );
389 Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
391 bool bCopy = false;
392 ScViewData* pViewData = ( pViewShell ? &pViewShell->GetViewData() : NULL );
393 ScDocument* pDocument = ( pViewData ? pViewData->GetDocument() : NULL );
394 SdrPageView* pPageView = ( pView ? pView->GetSdrPageView() : NULL );
395 SdrPage* pPage = ( pPageView ? pPageView->GetPage() : NULL );
396 ::std::vector< OUString > aExcludedChartNames;
397 ScRangeListVector aProtectedChartRangesVector;
399 if (pView && rMEvt.IsLeft())
401 if ( pView->IsDragObj() )
403 /******************************************************************
404 * Objekt wurde verschoben
405 ******************************************************************/
406 if ( rMEvt.IsMod1() )
408 if ( pPage )
410 ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
412 if ( pView && pDocument )
414 const SdrMarkList& rSdrMarkList = pView->GetMarkedObjectList();
415 const size_t nMarkCount = rSdrMarkList.GetMarkCount();
416 for ( size_t i = 0; i < nMarkCount; ++i )
418 SdrMark* pMark = rSdrMarkList.GetMark( i );
419 pObj = ( pMark ? pMark->GetMarkedSdrObj() : NULL );
420 if ( pObj )
422 ScChartHelper::AddRangesIfProtectedChart( aProtectedChartRangesVector, pDocument, pObj );
426 bCopy = true;
429 if (!rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() &&
430 std::abs(aPnt.X() - aMDPos.X()) < nDrgLog &&
431 std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog)
433 /*************************************************************
434 * If a user wants to click on an object in front of a marked
435 * one, he releases the mouse button immediately
436 **************************************************************/
437 SdrPageView* pPV = NULL;
438 if (pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK))
440 pView->UnmarkAllObj();
441 pView->MarkObj(pObj,pPV,false,false);
442 return true;
445 pView->EndDragObj( rMEvt.IsMod1() );
446 pView->ForceMarkedToAnotherPage();
448 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
449 if (rMarkList.GetMarkCount() == 1)
451 SdrMark* pMark = rMarkList.GetMark(0);
452 pObj = pMark->GetMarkedSdrObj();
454 bReturn = true;
456 else if (pView->IsAction() )
458 // unlock internal layer to include note captions
459 pView->UnlockInternalLayer();
460 pView->EndAction();
461 if ( pView->AreObjectsMarked() )
463 bReturn = true;
465 /* if multi-selection contains a note caption object, remove
466 all other objects from selection. */
467 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
468 const size_t nCount = rMarkList.GetMarkCount();
469 if( nCount > 1 )
471 bool bFound = false;
472 for( size_t nIdx = 0; !bFound && (nIdx < nCount); ++nIdx )
474 pObj = rMarkList.GetMark( nIdx )->GetMarkedSdrObj();
475 bFound = ScDrawLayer::IsNoteCaption( pObj );
476 if( bFound )
478 pView->UnMarkAll();
479 pView->MarkObj( pObj, pView->GetSdrPageView() );
487 /**************************************************************************
488 * Ggf. OLE-Objekt beruecksichtigen
489 **************************************************************************/
490 SfxInPlaceClient* pIPClient = pViewShell ? pViewShell->GetIPClient() : NULL;
492 if (pIPClient)
494 ScModule* pScMod = SC_MOD();
495 bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF;
497 if ( pIPClient->IsObjectInPlaceActive() && !bUnoRefDialog )
498 pIPClient->DeactivateObject();
501 sal_uInt16 nClicks = rMEvt.GetClicks();
502 if (pView && nClicks == 2 && rMEvt.IsLeft())
504 if ( pView->AreObjectsMarked() )
506 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
507 if (rMarkList.GetMarkCount() == 1)
509 SdrMark* pMark = rMarkList.GetMark(0);
510 pObj = pMark->GetMarkedSdrObj();
512 // aktivieren nur, wenn die Maus auch (noch) ueber dem
513 // selektierten Objekt steht
515 SdrViewEvent aVEvt;
516 SdrHitKind eHit = pView->PickAnything( rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt );
517 if (eHit != SDRHIT_NONE && aVEvt.pObj == pObj && pViewShell)
519 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
521 // OLE: aktivieren
523 if (nSdrObjKind == OBJ_OLE2)
525 if (!bOle)
527 if (static_cast<SdrOle2Obj*>(pObj)->GetObjRef().is())
529 pViewShell->ActivateObject( static_cast<SdrOle2Obj*>(pObj), 0 );
534 // Edit text
535 // not in UNO controls
536 // #i32352# not in media objects
538 else if ( pObj->ISA(SdrTextObj) && !pObj->ISA(SdrUnoObj) && !pObj->ISA(SdrMediaObj) )
540 OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
541 bool bVertical = ( pOPO && pOPO->IsVertical() );
542 sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
544 pViewShell->GetViewData().GetDispatcher().
545 Execute(nTextSlotId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
547 // jetzt den erzeugten FuText holen und in den EditModus setzen
548 FuPoor* pPoor = pViewShell->GetViewData().GetView()->GetDrawFuncPtr();
549 if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // hat keine RTTI
551 FuText* pText = static_cast<FuText*>(pPoor);
552 Point aMousePixel = rMEvt.GetPosPixel();
553 pText->SetInEditMode( pObj, &aMousePixel );
555 bReturn = true;
560 else if ( TestDetective( pView->GetSdrPageView(), aPnt ) )
561 bReturn = true;
564 // Ein VCControl ist aktiv
565 // Event an den Manager weiterleiten
566 if( bVCAction )
568 bVCAction = false;
569 bReturn = true;
572 ForcePointer(&rMEvt);
574 pWindow->ReleaseMouse();
576 // Command-Handler fuer Kontext-Menue kommt erst nach MouseButtonUp,
577 // darum hier die harte IsLeft-Abfrage
578 if ( !bReturn && rMEvt.IsLeft() )
579 if (pViewShell->IsDrawSelMode())
580 pViewShell->GetViewData().GetDispatcher().
581 Execute(SID_OBJECT_SELECT, SfxCallMode::SLOT | SfxCallMode::RECORD);
583 if ( bCopy && pViewData && pDocument && pPage )
585 ScDocShell* pDocShell = pViewData->GetDocShell();
586 ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL );
587 if ( pModelObj )
589 SCTAB nTab = pViewData->GetTabNo();
590 ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pPage, pModelObj, nTab,
591 aProtectedChartRangesVector, aExcludedChartNames );
595 return bReturn;
598 /*************************************************************************
600 |* Tastaturereignisse bearbeiten
602 |* Wird ein KeyEvent bearbeitet, so ist der Return-Wert sal_True, andernfalls
603 |* FALSE.
605 \************************************************************************/
607 bool FuSelection::KeyInput(const KeyEvent& rKEvt)
609 return FuDraw::KeyInput(rKEvt);
612 /*************************************************************************
614 |* Function aktivieren
616 \************************************************************************/
618 void FuSelection::Activate()
620 FuDraw::Activate();
623 /*************************************************************************
625 |* Function deaktivieren
627 \************************************************************************/
629 void FuSelection::Deactivate()
631 /**************************************************************************
632 * Hide Cursor
633 **************************************************************************/
634 FuDraw::Deactivate();
637 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */