Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / sc / source / ui / drawfunc / fusel.cxx
blob402cb4ac1331638cef5eee2be01c40f60fe530b4
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 // Maximal erlaubte Mausbewegung um noch Drag&Drop zu starten
52 //! fusel,fuconstr,futext - zusammenfassen!
53 #define SC_MAXDRAGMOVE 3
54 // Min necessary mouse motion for normal dragging
55 #define SC_MINDRAGMOVE 2
57 using namespace com::sun::star;
59 /*************************************************************************
61 |* Konstruktor
63 \************************************************************************/
65 FuSelection::FuSelection(ScTabViewShell* pViewSh, Window* pWin, ScDrawView* pViewP,
66 SdrModel* pDoc, SfxRequest& rReq ) :
67 FuDraw(pViewSh, pWin, pViewP, pDoc, rReq),
68 bVCAction(false)
72 /*************************************************************************
74 |* Destruktor
76 \************************************************************************/
78 FuSelection::~FuSelection()
82 sal_uInt8 FuSelection::Command(const CommandEvent& rCEvt)
84 return FuDraw::Command( rCEvt );
87 /*************************************************************************
89 |* MouseButtonDown-event
91 \************************************************************************/
93 bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
95 // remember button state for creation of own MouseEvents
96 SetMouseButtonCode(rMEvt.GetButtons());
97 const bool bSelectionOnly = rMEvt.IsRight();
98 if ( pView->IsAction() )
100 if ( bSelectionOnly )
101 pView->BckAction();
102 return true;
105 bVCAction = false;
106 bIsInDragMode = false; // irgendwo muss es ja zurueckgesetzt werden (#50033#)
108 bool bReturn = FuDraw::MouseButtonDown(rMEvt);
110 aMDPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
112 if ( rMEvt.IsLeft() )
114 SdrHdl* pHdl = pView->PickHandle(aMDPos);
116 if ( pHdl!=NULL || pView->IsMarkedHit(aMDPos) )
118 // Determine if this is the tail of a SdrCaptionObj i.e.
119 // we need to disable the drag option on the tail of a note
120 // object. Also, disable the ability to use the circular
121 // drag of a note object.
122 bool bDrag = false;
123 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
124 if( rMarkList.GetMarkCount() == 1 )
126 SdrObject* pMarkedObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
127 if( ScDrawLayer::IsNoteCaption( pMarkedObj ) )
129 // move using the valid caption handles for note text box.
130 if(pHdl && (pHdl->GetKind() != HDL_POLY && pHdl->GetKind() != HDL_CIRC))
131 bDrag = true;
132 // move the complete note box.
133 else if(!pHdl)
134 bDrag = true;
136 else
137 bDrag = true; // different object
139 else
140 bDrag = true; // several objects
142 if ( bDrag )
144 aDragTimer.Start();
145 pView->BegDragObj(aMDPos, (OutputDevice*) NULL, pHdl);
146 bReturn = true;
149 else
151 SdrObject* pObj;
152 SdrPageView* pPV;
153 bool bAlt = rMEvt.IsMod2();
154 if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMACRO) )
156 pView->BegMacroObj(aMDPos, pObj, pPV, pWindow);
157 bReturn = true;
159 else
161 OUString sURL, sTarget;
162 if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER))
164 // Support for imported Excel docs
165 // Excel is of course not consistent and allows
166 // a hyperlink to be assigned for an object group
167 // and even though the hyperlink is exported in the Escher layer
168 // its never used, when dealing with a group object the link
169 // associated with the clicked object is used only
171 // additionally you can also select a macro in Excel for a grouped
172 // objects and this *usually* results in the macro being set
173 // for the elements in the group and no macro is exported
174 // for the group itself ( this however is not always true )
175 // if a macro and hlink are defined favour the hlink
176 // If a group object has no hyperlink use the hyperlink of the
177 // object clicked
179 if ( pObj->IsGroupObject() )
181 ScMacroInfo* pTmpInfo = ScDrawLayer::GetMacroInfo( pObj );
182 if ( !pTmpInfo || pTmpInfo->GetMacro().isEmpty() )
184 SdrObject* pHit = NULL;
185 if ( pView->PickObj(aMDPos, pView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) )
186 pObj = pHit;
190 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj, true );
191 // For interoperability favour links over macros if both are defined
192 if ( !pInfo->GetHlink().isEmpty() )
194 OSL_TRACE("** Got URL");
195 sURL = pInfo->GetHlink();
197 else if ( !pInfo->GetMacro().isEmpty() )
199 SfxObjectShell* pObjSh = SfxObjectShell::Current();
200 if ( pObjSh && SfxApplication::IsXScriptURL( pInfo->GetMacro() ) )
202 uno::Reference< beans::XPropertySet > xProps( pObj->getUnoShape(), uno::UNO_QUERY );
203 uno::Any aCaller;
204 if ( xProps.is() )
208 aCaller = xProps->getPropertyValue("Name");
210 catch( uno::Exception& ) {}
212 uno::Any aRet;
213 uno::Sequence< sal_Int16 > aOutArgsIndex;
214 uno::Sequence< uno::Any > aOutArgs;
215 uno::Sequence< uno::Any >* pInArgs =
216 new uno::Sequence< uno::Any >(0);
217 pObjSh->CallXScript( pInfo->GetMacro(),
218 *pInArgs, aRet, aOutArgsIndex, aOutArgs, true, &aCaller );
219 pViewShell->FakeButtonUp( pViewShell->GetViewData()->GetActivePart() );
220 return true; // kein CaptureMouse etc.
225 // URL / ImageMap
227 SdrViewEvent aVEvt;
228 if ( !bAlt &&
229 pView->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt ) != SDRHIT_NONE &&
230 aVEvt.pObj != NULL )
232 if ( ScDrawLayer::GetIMapInfo( aVEvt.pObj ) ) // ImageMap
234 const IMapObject* pIMapObj =
235 ScDrawLayer::GetHitIMapObject( aVEvt.pObj, aMDPos, *pWindow );
236 if ( pIMapObj && !pIMapObj->GetURL().isEmpty() )
238 sURL = pIMapObj->GetURL();
239 sTarget = pIMapObj->GetTarget();
242 if ( aVEvt.eEvent == SDREVENT_EXECUTEURL && aVEvt.pURLField ) // URL
244 sURL = aVEvt.pURLField->GetURL();
245 sTarget = aVEvt.pURLField->GetTargetFrame();
249 // open hyperlink, if found at object or in object's text
250 if ( !sURL.isEmpty() )
252 ScGlobal::OpenURL( sURL, sTarget );
253 pViewShell->FakeButtonUp( pViewShell->GetViewData()->GetActivePart() );
254 return true; // kein CaptureMouse etc.
257 // Is another object being edited in this view?
258 // (Editing is ended in MarkListHasChanged - test before UnmarkAll)
259 SfxInPlaceClient* pClient = pViewShell->GetIPClient();
260 bool bWasOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
262 // Markieren
264 // do not allow multiselection with note caption
265 bool bCaptionClicked = IsNoteCaptionClicked( aMDPos );
266 if ( !rMEvt.IsShift() || bCaptionClicked || IsNoteCaptionMarked() )
267 pView->UnmarkAll();
269 /* Unlock internal layer, if a note caption is clicked. The
270 layer will be relocked in ScDrawView::MarkListHasChanged(). */
271 if( bCaptionClicked )
272 pView->UnlockInternalLayer();
274 // try to select the clicked object
275 if ( pView->MarkObj( aMDPos, -2, false, rMEvt.IsMod1() ) )
278 //Objekt verschieben
280 if (pView->IsMarkedHit(aMDPos))
282 // Don't start drag timer if inplace editing of an OLE object
283 // was just ended with this mouse click - the view will be moved
284 // (different tool bars) and the object that was clicked on would
285 // be moved unintentionally.
286 if ( !bWasOleActive )
287 aDragTimer.Start();
289 pHdl=pView->PickHandle(aMDPos);
290 pView->BegDragObj(aMDPos, (OutputDevice*) NULL, pHdl);
291 bReturn = true;
293 else // Objekt am Rand getroffen
294 if (pViewShell->IsDrawSelMode())
295 bReturn = true;
297 else
299 // nichts getroffen
301 if (pViewShell->IsDrawSelMode())
304 //Objekt selektieren
306 pView->BegMarkObj(aMDPos);
307 bReturn = true;
315 if (!bIsInDragMode)
317 if (!bVCAction) // VC rufen selber CaptureMouse
318 pWindow->CaptureMouse();
319 ForcePointer(&rMEvt);
322 return bReturn;
325 /*************************************************************************
327 |* MouseMove-event
329 \************************************************************************/
331 bool FuSelection::MouseMove(const MouseEvent& rMEvt)
333 bool bReturn = FuDraw::MouseMove(rMEvt);
335 if (aDragTimer.IsActive() )
337 Point aOldPixel = pWindow->LogicToPixel( aMDPos );
338 Point aNewPixel = rMEvt.GetPosPixel();
339 if ( std::abs( aOldPixel.X() - aNewPixel.X() ) > SC_MAXDRAGMOVE ||
340 std::abs( aOldPixel.Y() - aNewPixel.Y() ) > SC_MAXDRAGMOVE )
341 aDragTimer.Stop();
344 if ( pView->IsAction() )
346 Point aPix(rMEvt.GetPosPixel());
347 Point aPnt(pWindow->PixelToLogic(aPix));
349 ForceScroll(aPix);
350 pView->MovAction(aPnt);
351 bReturn = true;
354 // Ein VCControl ist aktiv
355 // Event an den Manager weiterleiten
356 if( bVCAction )
358 bReturn = true;
361 ForcePointer(&rMEvt);
363 return bReturn;
366 /*************************************************************************
368 |* MouseButtonUp-event
370 \************************************************************************/
372 bool FuSelection::MouseButtonUp(const MouseEvent& rMEvt)
374 // remember button state for creation of own MouseEvents
375 SetMouseButtonCode(rMEvt.GetButtons());
377 bool bReturn = FuDraw::MouseButtonUp(rMEvt);
378 bool bOle = pViewShell && pViewShell->GetViewFrame()->GetFrame().IsInPlace();
380 SdrObject* pObj = NULL;
381 SdrPageView* pPV = NULL;
382 if (aDragTimer.IsActive() )
384 aDragTimer.Stop();
387 sal_uInt16 nDrgLog = sal_uInt16 ( pWindow->PixelToLogic(Size(SC_MINDRAGMOVE,0)).Width() );
388 Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
390 bool bCopy = false;
391 ScViewData* pViewData = ( pViewShell ? pViewShell->GetViewData() : NULL );
392 ScDocument* pDocument = ( pViewData ? pViewData->GetDocument() : NULL );
393 SdrPageView* pPageView = ( pView ? pView->GetSdrPageView() : NULL );
394 SdrPage* pPage = ( pPageView ? pPageView->GetPage() : NULL );
395 ::std::vector< OUString > aExcludedChartNames;
396 ScRangeListVector aProtectedChartRangesVector;
398 if (pView && rMEvt.IsLeft())
400 if ( pView->IsDragObj() )
402 /******************************************************************
403 * Objekt wurde verschoben
404 ******************************************************************/
405 if ( rMEvt.IsMod1() )
407 if ( pPage )
409 ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
411 if ( pView && pDocument )
413 const SdrMarkList& rSdrMarkList = pView->GetMarkedObjectList();
414 sal_uLong nMarkCount = rSdrMarkList.GetMarkCount();
415 for ( sal_uLong i = 0; i < nMarkCount; ++i )
417 SdrMark* pMark = rSdrMarkList.GetMark( i );
418 pObj = ( pMark ? pMark->GetMarkedSdrObj() : NULL );
419 if ( pObj )
421 ScChartHelper::AddRangesIfProtectedChart( aProtectedChartRangesVector, pDocument, pObj );
425 bCopy = true;
428 if (!rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() &&
429 std::abs(aPnt.X() - aMDPos.X()) < nDrgLog &&
430 std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog)
432 /*************************************************************
433 * If a user wants to click on an object in front of a marked
434 * one, he releases the mouse button immediately
435 **************************************************************/
436 if (pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER | SDRSEARCH_BEFOREMARK))
438 pView->UnmarkAllObj();
439 pView->MarkObj(pObj,pPV,false,false);
440 return true;
443 pView->EndDragObj( rMEvt.IsMod1() );
444 pView->ForceMarkedToAnotherPage();
446 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
447 if (rMarkList.GetMarkCount() == 1)
449 SdrMark* pMark = rMarkList.GetMark(0);
450 pObj = pMark->GetMarkedSdrObj();
451 FuPoor* pPoor = pViewShell->GetViewData()->GetView()->GetDrawFuncPtr();
452 FuText* pText = static_cast<FuText*>(pPoor);
453 pText->StopDragMode(pObj );
455 bReturn = true;
457 else if (pView->IsAction() )
459 // unlock internal layer to include note captions
460 pView->UnlockInternalLayer();
461 pView->EndAction();
462 if ( pView->AreObjectsMarked() )
464 bReturn = true;
466 /* if multi-selection contains a note caption object, remove
467 all other objects from selection. */
468 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
469 sal_uLong nCount = rMarkList.GetMarkCount();
470 if( nCount > 1 )
472 bool bFound = false;
473 for( sal_uLong nIdx = 0; !bFound && (nIdx < nCount); ++nIdx )
475 pObj = rMarkList.GetMark( nIdx )->GetMarkedSdrObj();
476 bFound = ScDrawLayer::IsNoteCaption( pObj );
477 if( bFound )
479 pView->UnMarkAll();
480 pView->MarkObj( pObj, pView->GetSdrPageView() );
488 /**************************************************************************
489 * Ggf. OLE-Objekt beruecksichtigen
490 **************************************************************************/
491 SfxInPlaceClient* pIPClient = pViewShell ? pViewShell->GetIPClient() : NULL;
493 if (pIPClient)
495 ScModule* pScMod = SC_MOD();
496 bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF;
498 if ( pIPClient->IsObjectInPlaceActive() && !bUnoRefDialog )
499 pIPClient->DeactivateObject();
502 sal_uInt16 nClicks = rMEvt.GetClicks();
503 if (pView && nClicks == 2 && rMEvt.IsLeft())
505 if ( pView->AreObjectsMarked() )
507 const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
508 if (rMarkList.GetMarkCount() == 1)
510 SdrMark* pMark = rMarkList.GetMark(0);
511 pObj = pMark->GetMarkedSdrObj();
513 // aktivieren nur, wenn die Maus auch (noch) ueber dem
514 // selektierten Objekt steht
516 SdrViewEvent aVEvt;
517 SdrHitKind eHit = pView->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt );
518 if ( eHit != SDRHIT_NONE && aVEvt.pObj == pObj )
520 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
523 // OLE: aktivieren
526 if (nSdrObjKind == OBJ_OLE2)
528 if (!bOle)
530 if (((SdrOle2Obj*) pObj)->GetObjRef().is())
532 pViewShell->ActivateObject( (SdrOle2Obj*) pObj, 0 );
538 // Edit text
539 // not in UNO controls
540 // #i32352# not in media objects
542 else if ( pObj->ISA(SdrTextObj) && !pObj->ISA(SdrUnoObj) && !pObj->ISA(SdrMediaObj) )
544 OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
545 bool bVertical = ( pOPO && pOPO->IsVertical() );
546 sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
548 pViewShell->GetViewData()->GetDispatcher().
549 Execute(nTextSlotId, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD);
551 // jetzt den erzeugten FuText holen und in den EditModus setzen
552 FuPoor* pPoor = pViewShell->GetViewData()->GetView()->GetDrawFuncPtr();
553 if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // hat keine RTTI
555 FuText* pText = (FuText*)pPoor;
556 Point aMousePixel = rMEvt.GetPosPixel();
557 pText->SetInEditMode( pObj, &aMousePixel );
559 bReturn = true;
564 else if ( TestDetective( pView->GetSdrPageView(), aPnt ) )
565 bReturn = true;
568 // Ein VCControl ist aktiv
569 // Event an den Manager weiterleiten
570 if( bVCAction )
572 bVCAction = false;
573 bReturn = true;
576 ForcePointer(&rMEvt);
578 pWindow->ReleaseMouse();
580 // Command-Handler fuer Kontext-Menue kommt erst nach MouseButtonUp,
581 // darum hier die harte IsLeft-Abfrage
582 if ( !bReturn && rMEvt.IsLeft() )
583 if (pViewShell->IsDrawSelMode())
584 pViewShell->GetViewData()->GetDispatcher().
585 Execute(SID_OBJECT_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
587 if ( bCopy && pViewData && pDocument && pPage )
589 ScDocShell* pDocShell = pViewData->GetDocShell();
590 ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL );
591 if ( pModelObj )
593 SCTAB nTab = pViewData->GetTabNo();
594 ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pPage, pModelObj, nTab,
595 aProtectedChartRangesVector, aExcludedChartNames );
599 return bReturn;
602 /*************************************************************************
604 |* Tastaturereignisse bearbeiten
606 |* Wird ein KeyEvent bearbeitet, so ist der Return-Wert sal_True, andernfalls
607 |* FALSE.
609 \************************************************************************/
611 bool FuSelection::KeyInput(const KeyEvent& rKEvt)
613 return FuDraw::KeyInput(rKEvt);
617 /*************************************************************************
619 |* Function aktivieren
621 \************************************************************************/
623 void FuSelection::Activate()
625 FuDraw::Activate();
628 /*************************************************************************
630 |* Function deaktivieren
632 \************************************************************************/
634 void FuSelection::Deactivate()
636 /**************************************************************************
637 * Hide Cursor
638 **************************************************************************/
639 FuDraw::Deactivate();
642 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */