blob: 8efe74bb894aa0c4f3d24df2c41be8e1cb4dded4 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
// INCLUDE ---------------------------------------------------------------
#include <com/sun/star/embed/EmbedStates.hpp>
#include <editeng/eeitem.hxx>
#include <editeng/flditem.hxx>
#include <svx/svdoole2.hxx>
#include <svx/svdotext.hxx>
#include <sfx2/dispatch.hxx>
#include <svtools/imapobj.hxx>
#include <svx/svdouno.hxx>
#include <svx/svdomedia.hxx>
#include <svx/svdpagv.hxx>
#include <editeng/outlobj.hxx>
#include <svx/svdocapt.hxx>
#include <sfx2/app.hxx>
#include "fusel.hxx"
#include "sc.hrc"
#include "fudraw.hxx"
#include "futext.hxx"
#include "drawview.hxx"
#include "tabvwsh.hxx"
#include "drawpage.hxx"
#include "globstr.hrc"
#include "drwlayer.hxx"
#include "userdat.hxx"
#include "scmod.hxx"
#include "client.hxx"
#include "charthelper.hxx"
#include "docuno.hxx"
#include "docsh.hxx"
// -----------------------------------------------------------------------
// Maximal erlaubte Mausbewegung um noch Drag&Drop zu starten
//! fusel,fuconstr,futext - zusammenfassen!
#define SC_MAXDRAGMOVE 3
// -----------------------------------------------------------------------
#ifdef _MSC_VER
#pragma optimize ( "", off )
#endif
using namespace com::sun::star;
/*************************************************************************
|*
|* Konstruktor
|*
\************************************************************************/
FuSelection::FuSelection(ScTabViewShell* pViewSh, Window* pWin, ScDrawView* pViewP,
SdrModel* pDoc, SfxRequest& rReq ) :
FuDraw(pViewSh, pWin, pViewP, pDoc, rReq),
bVCAction(sal_False)
{
}
/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/
FuSelection::~FuSelection()
{
}
sal_uInt8 FuSelection::Command(const CommandEvent& rCEvt)
{
// special code for non-VCL OS2/UNX removed
return FuDraw::Command( rCEvt );
}
/*************************************************************************
|*
|* MouseButtonDown-event
|*
\************************************************************************/
sal_Bool __EXPORT FuSelection::MouseButtonDown(const MouseEvent& rMEvt)
{
// #95491# remember button state for creation of own MouseEvents
SetMouseButtonCode(rMEvt.GetButtons());
const bool bSelectionOnly = rMEvt.IsRight();
if ( pView->IsAction() )
{
if ( bSelectionOnly )
pView->BckAction();
return sal_True;
}
bVCAction = sal_False;
bIsInDragMode = sal_False; // irgendwo muss es ja zurueckgesetzt werden (#50033#)
sal_Bool bReturn = FuDraw::MouseButtonDown(rMEvt);
aMDPos = pWindow->PixelToLogic( rMEvt.GetPosPixel() );
if ( rMEvt.IsLeft() )
{
SdrHdl* pHdl = pView->PickHandle(aMDPos);
SdrObject* pObj;
SdrPageView* pPV;
if ( pHdl!=NULL || pView->IsMarkedHit(aMDPos) )
{
// Determine if this is the tail of a SdrCaptionObj i.e.
// we need to disable the drag option on the tail of a note
// object. Also, disable the ability to use the circular
// drag of a note object.
bool bDrag = false;
const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
if( rMarkList.GetMarkCount() == 1 )
{
SdrObject* pMarkedObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
if( ScDrawLayer::IsNoteCaption( pMarkedObj ) )
{
// move using the valid caption handles for note text box.
if(pHdl && (pHdl->GetKind() != HDL_POLY && pHdl->GetKind() != HDL_CIRC))
bDrag = true;
// move the complete note box.
else if(!pHdl)
bDrag = true;
}
else
bDrag = true; // different object
}
else
bDrag = true; // several objects
if ( bDrag )
{
aDragTimer.Start();
pView->BegDragObj(aMDPos, (OutputDevice*) NULL, pHdl);
bReturn = sal_True;
}
}
else
{
sal_Bool bAlt = rMEvt.IsMod2();
if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMACRO) )
{
pView->BegMacroObj(aMDPos, pObj, pPV, pWindow);
bReturn = sal_True;
}
else
{
String sURL, sTarget;
if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER))
{
// Support for imported Excel docs
// Excel is of course not consistent and allows
// a hyperlink to be assigned for an object group
// and even though the hyperlink is exported in the Escher layer
// its never used, when dealing with a group object the link
// associated with the clicked object is used only
// additionally you can also select a macro in Excel for a grouped
// objects and this results in the macro being set for the elements
// in the group and no macro is exported for the group
// if a macro and hlink are defined favour the hlink
// If a group object has no hyperlink use the hyperlink of the
// object clicked
if ( pObj->IsGroupObject() )
{
SdrObject* pHit = NULL;
if ( pView->PickObj(aMDPos, pView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) )
pObj = pHit;
}
ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pObj, sal_True );
#ifdef ISSUE66550_HLINK_FOR_SHAPES
// For interoperability favour links over macros if both are defined
if ( pInfo->GetHlink().getLength() > 0 )
{
OSL_TRACE("** Got URL");
sURL = pInfo->GetHlink();
}
else if ( pInfo->GetMacro().getLength() > 0 )
#else
if ( pInfo->GetMacro().getLength() > 0 )
#endif
{
SfxObjectShell* pObjSh = SfxObjectShell::Current();
if ( pObjSh && SfxApplication::IsXScriptURL( pInfo->GetMacro() ) )
{
uno::Any aRet;
uno::Sequence< sal_Int16 > aOutArgsIndex;
uno::Sequence< uno::Any > aOutArgs;
uno::Sequence< uno::Any >* pInArgs =
new uno::Sequence< uno::Any >(0);
pObjSh->CallXScript( pInfo->GetMacro(),
*pInArgs, aRet, aOutArgsIndex, aOutArgs);
pViewShell->FakeButtonUp( pViewShell->GetViewData()->GetActivePart() );
return sal_True; // kein CaptureMouse etc.
}
}
}
// URL / ImageMap
SdrViewEvent aVEvt;
if ( !bAlt &&
pView->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt ) != SDRHIT_NONE &&
aVEvt.pObj != NULL )
{
if ( ScDrawLayer::GetIMapInfo( aVEvt.pObj ) ) // ImageMap
{
const IMapObject* pIMapObj =
ScDrawLayer::GetHitIMapObject( aVEvt.pObj, aMDPos, *pWindow );
if ( pIMapObj && pIMapObj->GetURL().Len() )
{
sURL = pIMapObj->GetURL();
sTarget = pIMapObj->GetTarget();
}
}
if ( aVEvt.eEvent == SDREVENT_EXECUTEURL && aVEvt.pURLField ) // URL
{
sURL = aVEvt.pURLField->GetURL();
sTarget = aVEvt.pURLField->GetTargetFrame();
}
}
// open hyperlink, if found at object or in object's text
if ( sURL.Len() > 0 )
{
ScGlobal::OpenURL( sURL, sTarget );
pViewShell->FakeButtonUp( pViewShell->GetViewData()->GetActivePart() );
return sal_True; // kein CaptureMouse etc.
}
// Is another object being edited in this view?
// (Editing is ended in MarkListHasChanged - test before UnmarkAll)
SfxInPlaceClient* pClient = pViewShell->GetIPClient();
sal_Bool bWasOleActive = ( pClient && pClient->IsObjectInPlaceActive() );
// Markieren
// do not allow multiselection with note caption
bool bCaptionClicked = IsNoteCaptionClicked( aMDPos );
if ( !rMEvt.IsShift() || bCaptionClicked || IsNoteCaptionMarked() )
pView->UnmarkAll();
/* Unlock internal layer, if a note caption is clicked. The
layer will be relocked in ScDrawView::MarkListHasChanged(). */
if( bCaptionClicked )
pView->UnlockInternalLayer();
// try to select the clicked object
if ( pView->MarkObj( aMDPos, -2, sal_False, rMEvt.IsMod1() ) )
{
//*********************************************************
//Objekt verschieben
//********************************************************
if (pView->IsMarkedHit(aMDPos))
{
// #95834# Don't start drag timer if inplace editing of an OLE object
// was just ended with this mouse click - the view will be moved
// (different tool bars) and the object that was clicked on would
// be moved unintentionally.
if ( !bWasOleActive )
aDragTimer.Start();
pHdl=pView->PickHandle(aMDPos);
pView->BegDragObj(aMDPos, (OutputDevice*) NULL, pHdl);
bReturn = sal_True;
}
else // Objekt am Rand getroffen
if (pViewShell->IsDrawSelMode())
bReturn = sal_True;
}
else
{
// nichts getroffen
if (pViewShell->IsDrawSelMode())
{
//*********************************************************
//Objekt selektieren
//********************************************************
pView->BegMarkObj(aMDPos);
bReturn = sal_True;
}
}
}
}
}
if (!bIsInDragMode)
{
if (!bVCAction) // VC rufen selber CaptureMouse
pWindow->CaptureMouse();
ForcePointer(&rMEvt);
}
return bReturn;
}
/*************************************************************************
|*
|* MouseMove-event
|*
\************************************************************************/
sal_Bool __EXPORT FuSelection::MouseMove(const MouseEvent& rMEvt)
{
sal_Bool bReturn = FuDraw::MouseMove(rMEvt);
if (aDragTimer.IsActive() )
{
Point aOldPixel = pWindow->LogicToPixel( aMDPos );
Point aNewPixel = rMEvt.GetPosPixel();
if ( Abs( aOldPixel.X() - aNewPixel.X() ) > SC_MAXDRAGMOVE ||
Abs( aOldPixel.Y() - aNewPixel.Y() ) > SC_MAXDRAGMOVE )
aDragTimer.Stop();
}
if ( pView->IsAction() )
{
Point aPix(rMEvt.GetPosPixel());
Point aPnt(pWindow->PixelToLogic(aPix));
ForceScroll(aPix);
pView->MovAction(aPnt);
bReturn = sal_True;
}
// Ein VCControl ist aktiv
// Event an den Manager weiterleiten
if( bVCAction )
{
// GetSbxForm gibts nicht mehr - Basic-Controls sind tot
//SdrPageView* pPgView = pView->GetPageViewByIndex(0);
//ScDrawPage* pPage = (ScDrawPage*)pPgView->GetPage();
//VCSbxForm* pForm = (VCSbxForm*)(SbxObject*)(pPage->GetSbxForm());
//((VCManager*)(pForm->GetVCContainer()))->
// MouseMove( pWindow, rMEvt );
bReturn = sal_True;
}
ForcePointer(&rMEvt);
return (bReturn);
}
/*************************************************************************
|*
|* MouseButtonUp-event
|*
\************************************************************************/
sal_Bool __EXPORT FuSelection::MouseButtonUp(const MouseEvent& rMEvt)
{
// #95491# remember button state for creation of own MouseEvents
SetMouseButtonCode(rMEvt.GetButtons());
sal_Bool bReturn = FuDraw::MouseButtonUp(rMEvt);
// sal_Bool bOle = pViewShell->GetViewData()->IsOle();
sal_Bool bOle = pViewShell->GetViewFrame()->GetFrame().IsInPlace();
if (aDragTimer.IsActive() )
{
aDragTimer.Stop();
}
Point aPnt( pWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
bool bCopy = false;
ScViewData* pViewData = ( pViewShell ? pViewShell->GetViewData() : NULL );
ScDocument* pDocument = ( pViewData ? pViewData->GetDocument() : NULL );
SdrPageView* pPageView = ( pView ? pView->GetSdrPageView() : NULL );
SdrPage* pPage = ( pPageView ? pPageView->GetPage() : NULL );
::std::vector< ::rtl::OUString > aExcludedChartNames;
ScRangeListVector aProtectedChartRangesVector;
if ( rMEvt.IsLeft() )
{
if ( pView->IsDragObj() )
{
/******************************************************************
* Objekt wurde verschoben
******************************************************************/
if ( rMEvt.IsMod1() )
{
if ( pPage )
{
ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
}
if ( pView && pDocument )
{
const SdrMarkList& rSdrMarkList = pView->GetMarkedObjectList();
sal_uLong nMarkCount = rSdrMarkList.GetMarkCount();
for ( sal_uLong i = 0; i < nMarkCount; ++i )
{
SdrMark* pMark = rSdrMarkList.GetMark( i );
SdrObject* pObj = ( pMark ? pMark->GetMarkedSdrObj() : NULL );
if ( pObj )
{
ScChartHelper::AddRangesIfProtectedChart( aProtectedChartRangesVector, pDocument, pObj );
}
}
}
bCopy = true;
}
pView->EndDragObj( rMEvt.IsMod1() );
pView->ForceMarkedToAnotherPage();
const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
if (rMarkList.GetMarkCount() == 1)
{
SdrMark* pMark = rMarkList.GetMark(0);
SdrObject* pObj = pMark->GetMarkedSdrObj();
FuPoor* pPoor = pViewShell->GetViewData()->GetView()->GetDrawFuncPtr();
FuText* pText = static_cast<FuText*>(pPoor);
pText->StopDragMode(pObj );
}
bReturn = sal_True;
}
else if (pView->IsAction() )
{
// unlock internal layer to include note captions
pView->UnlockInternalLayer();
pView->EndAction();
if ( pView->AreObjectsMarked() )
{
bReturn = sal_True;
/* if multi-selection contains a note caption object, remove
all other objects from selection. */
const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
sal_uLong nCount = rMarkList.GetMarkCount();
if( nCount > 1 )
{
bool bFound = false;
for( sal_uLong nIdx = 0; !bFound && (nIdx < nCount); ++nIdx )
{
SdrObject* pObj = rMarkList.GetMark( nIdx )->GetMarkedSdrObj();
bFound = ScDrawLayer::IsNoteCaption( pObj );
if( bFound )
{
pView->UnMarkAll();
pView->MarkObj( pObj, pView->GetSdrPageView() );
}
}
}
}
}
}
/*
if ( pView->IsObjEdit() )
{
sal_Bool bShowCursor = sal_True;
//! pOutlinerView = pView->GetOutlinerView(pWindow, bShowCursor);
bReturn = sal_True;
}
*/
/**************************************************************************
* Ggf. OLE-Objekt beruecksichtigen
**************************************************************************/
SfxInPlaceClient* pIPClient = pViewShell->GetIPClient();
if (pIPClient)
{
ScModule* pScMod = SC_MOD();
bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF;
if ( pIPClient->IsObjectInPlaceActive() && !bUnoRefDialog )
pIPClient->DeactivateObject();
}
sal_uInt16 nClicks = rMEvt.GetClicks();
if ( nClicks == 2 && rMEvt.IsLeft() )
{
if ( pView->AreObjectsMarked() )
{
const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
if (rMarkList.GetMarkCount() == 1)
{
SdrMark* pMark = rMarkList.GetMark(0);
SdrObject* pObj = pMark->GetMarkedSdrObj();
// #43984# aktivieren nur, wenn die Maus auch (noch) ueber dem
// selektierten Objekt steht
SdrViewEvent aVEvt;
SdrHitKind eHit = pView->PickAnything( rMEvt, SDRMOUSEBUTTONDOWN, aVEvt );
if ( eHit != SDRHIT_NONE && aVEvt.pObj == pObj )
{
sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier();
//
// OLE: aktivieren
//
if (nSdrObjKind == OBJ_OLE2)
{
if (!bOle)
{
if (((SdrOle2Obj*) pObj)->GetObjRef().is())
{
//HMHpView->HideMarkHdl();
pViewShell->ActivateObject( (SdrOle2Obj*) pObj, 0 );
}
}
}
//
// Edit text
// #49458# not in UNO controls
// #i32352# not in media objects
//
else if ( pObj->ISA(SdrTextObj) && !pObj->ISA(SdrUnoObj) && !pObj->ISA(SdrMediaObj) )
{
OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject();
sal_Bool bVertical = ( pOPO && pOPO->IsVertical() );
sal_uInt16 nTextSlotId = bVertical ? SID_DRAW_TEXT_VERTICAL : SID_DRAW_TEXT;
pViewShell->GetViewData()->GetDispatcher().
Execute(nTextSlotId, SFX_CALLMODE_SYNCHRON | SFX_CALLMODE_RECORD);
// jetzt den erzeugten FuText holen und in den EditModus setzen
FuPoor* pPoor = pViewShell->GetViewData()->GetView()->GetDrawFuncPtr();
if ( pPoor && pPoor->GetSlotID() == nTextSlotId ) // hat keine RTTI
{
FuText* pText = (FuText*)pPoor;
Point aMousePixel = rMEvt.GetPosPixel();
pText->SetInEditMode( pObj, &aMousePixel );
}
bReturn = sal_True;
}
}
}
}
else if ( TestDetective( pView->GetSdrPageView(), aPnt ) )
bReturn = sal_True;
}
// Ein VCControl ist aktiv
// Event an den Manager weiterleiten
if( bVCAction )
{
// GetSbxForm gibts nicht mehr - Basic-Controls sind tot
//SdrPageView* pPgView = pView->GetPageViewByIndex(0);
//ScDrawPage* pPage = (ScDrawPage*)pPgView->GetPage();
//VCSbxForm* pForm = (VCSbxForm*)(SbxObject*)(pPage->GetSbxForm());
//((VCManager*)(pForm->GetVCContainer()))->
// MouseButtonUp( pWindow, rMEvt );
//HMHpView->ShowMarkHdl();
bVCAction = sal_False;
bReturn = sal_True;
}
ForcePointer(&rMEvt);
pWindow->ReleaseMouse();
// Command-Handler fuer Kontext-Menue kommt erst nach MouseButtonUp,
// darum hier die harte IsLeft-Abfrage
if ( !bReturn && rMEvt.IsLeft() )
if (pViewShell->IsDrawSelMode())
pViewShell->GetViewData()->GetDispatcher().
Execute(SID_OBJECT_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD);
if ( bCopy && pViewData && pDocument && pPage )
{
ScDocShell* pDocShell = pViewData->GetDocShell();
ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL );
if ( pModelObj )
{
SCTAB nTab = pViewData->GetTabNo();
ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pPage, pModelObj, nTab,
aProtectedChartRangesVector, aExcludedChartNames );
}
}
return (bReturn);
}
/*************************************************************************
|*
|* Tastaturereignisse bearbeiten
|*
|* Wird ein KeyEvent bearbeitet, so ist der Return-Wert sal_True, andernfalls
|* FALSE.
|*
\************************************************************************/
sal_Bool FuSelection::KeyInput(const KeyEvent& rKEvt)
{
sal_Bool bReturn = sal_False;
if (!bReturn)
{
bReturn = FuDraw::KeyInput(rKEvt);
}
return(bReturn);
}
/*************************************************************************
|*
|* Function aktivieren
|*
\************************************************************************/
void FuSelection::Activate()
{
/*
SdrDragMode eMode;
switch (aSfxRequest.GetSlot() )
{
case SID_OBJECT_SELECT:
eMode = SDRDRAG_MOVE;
break;
case SID_OBJECT_ROTATE:
eMode = SDRDRAG_ROTATE;
break;
case SID_OBJECT_MIRROR:
eMode = SDRDRAG_MIRROR;
break;
}
pView->SetDragMode(eMode);
*/
FuDraw::Activate();
}
/*************************************************************************
|*
|* Function deaktivieren
|*
\************************************************************************/
void FuSelection::Deactivate()
{
/**************************************************************************
* Hide Cursor
**************************************************************************/
// sal_Bool bShowCursor = sal_False;
//! pOutlinerView = pView->GetOutlinerView(pWindow, bShowCursor);
// pView->SetDragMode(SDRDRAG_MOVE);
FuDraw::Deactivate();
}
#ifdef _MSC_VER
#pragma optimize ( "", on )
#endif