/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ #include "fusel.hxx" #include #include #include #include #include #include "drawview.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "app.hrc" #include "strings.hrc" #include "res_bmp.hrc" #include "GraphicDocShell.hxx" #include "sdmod.hxx" #include "DrawDocShell.hxx" #include "stlpool.hxx" #include "anminfo.hxx" #include "fudraw.hxx" #include "ViewShell.hxx" #include "ViewShellBase.hxx" #include "FrameView.hxx" #include "View.hxx" #include "Window.hxx" #include "drawdoc.hxx" #include "sdpage.hxx" #include "DrawViewShell.hxx" #include "ToolBarManager.hxx" #include "pgjump.hxx" #include #include "Client.hxx" #include "slideshow.hxx" #include #include #include #include using namespace ::com::sun::star; namespace sd { TYPEINIT1( FuSelection, FuDraw ); FuSelection::FuSelection ( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq) : FuDraw(pViewSh, pWin, pView, pDoc, rReq), bTempRotation(false), bSelectionChanged(false), bHideAndAnimate(false), pHdl(NULL), bSuppressChangesOfSelection(false), bMirrorSide0(false), nEditMode(SID_BEZIER_MOVE), pWaterCanCandidate(NULL) //Add Shift+UP/DOWN/LEFT/RIGHT key to move the position of insert point, //and SHIFT+ENTER key to decide the position and draw the new insert point ,bBeginInsertPoint(false), oldPoint(0,0) ,bMovedToCenterPoint(false) { } rtl::Reference FuSelection::Create( ViewShell* pViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument* pDoc, SfxRequest& rReq ) { rtl::Reference xFunc( new FuSelection( pViewSh, pWin, pView, pDoc, rReq ) ); xFunc->DoExecute(rReq); return xFunc; } void FuSelection::DoExecute( SfxRequest& rReq ) { FuDraw::DoExecute( rReq ); // Select object bar SelectionHasChanged(); } FuSelection::~FuSelection() { mpView->UnmarkAllPoints(); mpView->ResetCreationActive(); if ( mpView->GetDragMode() != SDRDRAG_MOVE ) { mpView->SetDragMode(SDRDRAG_MOVE); } } bool FuSelection::MouseButtonDown(const MouseEvent& rMEvt) { // Hack for #?????# bHideAndAnimate = false; pHdl = NULL; bool bReturn = FuDraw::MouseButtonDown(rMEvt); bool bWaterCan = SD_MOD()->GetWaterCan(); const bool bReadOnly = mpDocSh->IsReadOnly(); // When the right mouse button is pressed then only select objects // (and deselect others) as a preparation for showing the context // menu. const bool bSelectionOnly = rMEvt.IsRight(); bMBDown = true; bSelectionChanged = false; if ( mpView->IsAction() ) { if ( rMEvt.IsRight() ) mpView->BckAction(); return true; } sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); if (mpDoc->isTiledRendering()) { // When tiled rendering, we always work in logic units, use the non-pixel constants. nDrgLog = DRGLOG; nHitLog = HITLOG; } // The following code is executed for right clicks as well as for left // clicks in order to modify the selection for the right button as a // preparation for the context menu. The functions BegMarkObject() and // BegDragObject(), however, are not called for right clicks because a) // it makes no sense and b) to have IsAction() return sal_False when called // from Command() which is a prerequisite for the context menu. if ((rMEvt.IsLeft() || rMEvt.IsRight()) && !mpView->IsAction() && (mpView->IsFrameDragSingles() || !mpView->HasMarkablePoints())) { /****************************************************************** * NO BEZIER_EDITOR ******************************************************************/ mpWindow->CaptureMouse(); pHdl = mpView->PickHandle(aMDPos); SdrObject* pObj; SdrPageView* pPV; long nAngle0 = GetAngle(aMDPos - mpView->GetRef1()); nAngle0 -= 27000; nAngle0 = NormAngle360(nAngle0); bMirrorSide0 = nAngle0 < 18000L; if (!pHdl && mpView->Is3DRotationCreationActive()) { /****************************************************************** * If 3D-rotation bodies are about to be created, * end creation now. ******************************************************************/ bSuppressChangesOfSelection = true; mpWindow->EnterWait(); mpView->End3DCreation(); bSuppressChangesOfSelection = false; mpView->ResetCreationActive(); mpWindow->LeaveWait(); } bool bTextEdit = false; SdrViewEvent aVEvt; SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); if ( eHit == SDRHIT_TEXTEDITOBJ && ( mpViewShell->GetFrameView()->IsQuickEdit() || dynamic_cast< sdr::table::SdrTableObj* >( aVEvt.pObj ) != NULL ) ) { bTextEdit = true; } if(!bTextEdit && !mpDocSh->IsReadOnly() && ((mpView->IsMarkedHit(aMDPos, nHitLog) && !rMEvt.IsShift() && !rMEvt.IsMod2()) || pHdl != NULL) && (rMEvt.GetClicks() != 2) ) { if (!pHdl && mpView->Is3DRotationCreationActive()) { // Switch between 3D-rotation body -> selection mpView->ResetCreationActive(); } else if (bWaterCan) { // Remember the selected object for proper handling in // MouseButtonUp(). pWaterCanCandidate = pickObject (aMDPos); } else { // hit handle or marked object bFirstMouseMove = true; aDragTimer.Start(); } if ( ! rMEvt.IsRight()) if (mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog)) mpView->GetDragMethod()->SetShiftPressed( rMEvt.IsShift() ); bReturn = true; } else { if (!rMEvt.IsMod2() && mpView->PickObj(aMDPos, mpView->getHitTolLog(), pObj, pPV, SdrSearchOptions::PICKMACRO)) { mpView->BegMacroObj(aMDPos, nHitLog, pObj, pPV, mpWindow); bReturn = true; } else if ( bTextEdit ) { sal_uInt16 nSdrObjKind = aVEvt.pObj->GetObjIdentifier(); if (aVEvt.pObj->GetObjInventor() == SdrInventor && (nSdrObjKind == OBJ_TEXT || nSdrObjKind == OBJ_TITLETEXT || nSdrObjKind == OBJ_OUTLINETEXT || !aVEvt.pObj->IsEmptyPresObj())) { // Seamless Editing: branch to text input if (!rMEvt.IsShift()) mpView->UnmarkAll(); SfxUInt16Item aItem(SID_TEXTEDIT, 1); mpViewShell->GetViewFrame()->GetDispatcher()-> Execute(SID_TEXTEDIT, SfxCallMode::SYNCHRON | SfxCallMode::RECORD, &aItem, 0L); return bReturn; // CAUTION, due to the synchronous slot the object is deleted now } } else if ( !rMEvt.IsMod2() && rMEvt.GetClicks() == 1 && aVEvt.eEvent == SDREVENT_EXECUTEURL ) { mpWindow->ReleaseMouse(); SfxStringItem aStrItem(SID_FILE_NAME, aVEvt.pURLField->GetURL()); SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName()); SfxBoolItem aBrowseItem( SID_BROWSE, true ); SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); mpWindow->ReleaseMouse(); // If tiled rendering, let client handles URL execution and early returns. if (mpDoc->isTiledRendering()) { mpDoc->libreOfficeKitCallback(LOK_CALLBACK_HYPERLINK_CLICKED, aVEvt.pURLField->GetURL().toUtf8().getStr()); return true; } if (rMEvt.IsMod1()) { // Open in new frame pFrame->GetDispatcher()->Execute(SID_OPENDOC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, &aStrItem, &aBrowseItem, &aReferer, 0L); } else { // Open in current frame SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame); pFrame->GetDispatcher()->Execute(SID_OPENDOC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, &aStrItem, &aFrameItem, &aBrowseItem, &aReferer, 0L); } bReturn = true; } else if(!rMEvt.IsMod2() && mpViewShell->ISA(DrawViewShell) ) { if(mpView->PickObj(aMDPos, mpView->getHitTolLog(), pObj, pPV, SdrSearchOptions::ALSOONMASTER)) { // Animate object when not just selecting. if ( ! bSelectionOnly) bReturn = AnimateObj(pObj, aMDPos); if (!bReturn && (pObj->ISA(SdrObjGroup) || pObj->ISA(E3dPolyScene))) { if(rMEvt.GetClicks() == 1) { // Look into the group if (mpView->PickObj(aMDPos, mpView->getHitTolLog(), pObj, pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::DEEP)) bReturn = AnimateObj(pObj, aMDPos); } else if( !bReadOnly && rMEvt.GetClicks() == 2) { // New: double click on selected Group object // enter group if ( ! bSelectionOnly && pObj->GetPage() == pPV->GetPage()) bReturn = pPV->EnterGroup(pObj); } } } // #i71727# replaced else here with two possibilities, once the original else (!pObj) // and also ignoring the found object when it's on a masterpage if(!pObj || (pObj->GetPage() && pObj->GetPage()->IsMasterPage())) { if(mpView->IsGroupEntered() && 2 == rMEvt.GetClicks()) { // New: double click on empty space/on obj on MasterPage, leave group mpView->LeaveOneGroup(); bReturn = true; } } } if (!bReturn) { if (bWaterCan) { if ( ! (rMEvt.IsShift() || rMEvt.IsMod2())) { // Find the object under the current mouse position // and store it for the MouseButtonUp() method to // evaluate. pWaterCanCandidate = pickObject (aMDPos); } } else { bReturn = true; bool bDeactivateOLE = false; if ( !rMEvt.IsShift() && !rMEvt.IsMod2() ) { OSL_ASSERT (mpViewShell->GetViewShell()!=NULL); Client* pIPClient = static_cast( mpViewShell->GetViewShell()->GetIPClient()); if (pIPClient && pIPClient->IsObjectInPlaceActive()) { // OLE-Objekt gets deactivated in subsequent UnmarkAll() bDeactivateOLE = true; } mpView->UnmarkAll(); } bool bMarked = false; if ( !rMEvt.IsMod1() && !bDeactivateOLE) { if ( rMEvt.IsMod2() ) { bMarked = mpView->MarkNextObj(aMDPos, nHitLog, rMEvt.IsShift() ); } else { bool bToggle = false; if (rMEvt.IsShift() && mpView->GetMarkedObjectList().GetMarkCount() > 1) { // No Toggle on single selection bToggle = true; } bMarked = mpView->MarkObj(aMDPos, nHitLog, bToggle); } } if( !bDeactivateOLE ) { if ( !bReadOnly && bMarked && (!rMEvt.IsShift() || mpView->IsMarkedHit(aMDPos, nHitLog))) { /********************************************************** * Move object **********************************************************/ aDragTimer.Start(); pHdl=mpView->PickHandle(aMDPos); if ( ! rMEvt.IsRight()) mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); } else { /********************************************************** * Select object **********************************************************/ if ( ! rMEvt.IsRight()) mpView->BegMarkObj(aMDPos); } } if( bMarked && bTempRotation && (nSlotId == SID_OBJECT_ROTATE) && !rMEvt.IsShift() && (rMEvt.GetClicks() != 2) ) { nSlotId = SID_OBJECT_SELECT; Activate(); } } } } } else if ( !bReadOnly && (rMEvt.IsLeft() || rMEvt.IsRight()) && !mpView->IsAction()) { /********************************************************************** * BEZIER-EDITOR **********************************************************************/ mpWindow->CaptureMouse(); SdrViewEvent aVEvt; SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); if (eHit == SDRHIT_HANDLE && aVEvt.pHdl->GetKind() == HDL_BWGT) { /****************************************************************** * Drag Handle ******************************************************************/ if ( ! rMEvt.IsRight()) mpView->BegDragObj(aMDPos, nullptr, aVEvt.pHdl, nDrgLog); } else if (eHit == SDRHIT_MARKEDOBJECT && nEditMode == SID_BEZIER_INSERT) { /****************************************************************** * Insert glue point ******************************************************************/ mpView->BegInsObjPoint(aMDPos, rMEvt.IsMod1()); } else if (eHit == SDRHIT_MARKEDOBJECT && rMEvt.IsMod1()) { /****************************************************************** * Select glue point ******************************************************************/ if (!rMEvt.IsShift()) mpView->UnmarkAllPoints(); if ( ! rMEvt.IsRight()) mpView->BegMarkPoints(aMDPos); } else if (eHit == SDRHIT_MARKEDOBJECT && !rMEvt.IsShift() && !rMEvt.IsMod2()) { /****************************************************************** * Move object ******************************************************************/ if ( ! rMEvt.IsRight()) mpView->BegDragObj(aMDPos, nullptr, NULL, nDrgLog); } else if (eHit == SDRHIT_HANDLE) { /****************************************************************** * Select glue point ******************************************************************/ if (!mpView->IsPointMarked(*aVEvt.pHdl) || rMEvt.IsShift()) { if (!rMEvt.IsShift()) { mpView->UnmarkAllPoints(); pHdl = mpView->PickHandle(aMDPos); } else { if (mpView->IsPointMarked(*aVEvt.pHdl)) { mpView->UnmarkPoint(*aVEvt.pHdl); pHdl = NULL; } else { pHdl = mpView->PickHandle(aMDPos); } } if (pHdl) { mpView->MarkPoint(*pHdl); if ( ! rMEvt.IsRight()) mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); } } else { // Point IS marked and NO shift is pressed. Start // dragging of selected point(s) pHdl = mpView->PickHandle(aMDPos); if(pHdl) if ( ! rMEvt.IsRight()) mpView->BegDragObj(aMDPos, nullptr, pHdl, nDrgLog); } } else { /****************************************************************** * Select or drag object ******************************************************************/ if (!rMEvt.IsShift() && !rMEvt.IsMod2() && eHit == SDRHIT_UNMARKEDOBJECT) { mpView->UnmarkAllObj(); } bool bMarked = false; if (!rMEvt.IsMod1()) { if (rMEvt.IsMod2()) { bMarked = mpView->MarkNextObj(aMDPos, nHitLog, rMEvt.IsShift()); } else { bMarked = mpView->MarkObj(aMDPos, nHitLog, rMEvt.IsShift()); } } if (bMarked && (!rMEvt.IsShift() || eHit == SDRHIT_MARKEDOBJECT)) { // Move object if ( ! rMEvt.IsRight()) mpView->BegDragObj(aMDPos, nullptr, aVEvt.pHdl, nDrgLog); } else if (mpView->AreObjectsMarked()) { /************************************************************** * Select glue point **************************************************************/ if (!rMEvt.IsShift()) mpView->UnmarkAllPoints(); if ( ! rMEvt.IsRight()) mpView->BegMarkPoints(aMDPos); } else { /************************************************************** * Select object **************************************************************/ if ( ! rMEvt.IsRight()) mpView->BegMarkObj(aMDPos); } ForcePointer(&rMEvt); } } if (!bIsInDragMode) { ForcePointer(&rMEvt); } return bReturn; } bool FuSelection::MouseMove(const MouseEvent& rMEvt) { bool bReturn = FuDraw::MouseMove(rMEvt); if (aDragTimer.IsActive()) { if(bFirstMouseMove) { bFirstMouseMove = false; } else { aDragTimer.Stop(); } } if (mpView->IsAction()) { Point aPix(rMEvt.GetPosPixel()); Point aPnt(mpWindow->PixelToLogic(aPix)); ForceScroll(aPix); if (mpView->IsInsObjPoint()) { mpView->MovInsObjPoint(aPnt); } else { mpView->MovAction(aPnt); } } ForcePointer(&rMEvt); return bReturn; } bool FuSelection::MouseButtonUp(const MouseEvent& rMEvt) { bool bReturn = false; // When the right mouse button is pressed then only select objects // (and deselect others) as a preparation for showing the context // menu. const bool bSelectionOnly = rMEvt.IsRight(); SdrObject* pObj; SdrPageView* pPV; if (bHideAndAnimate) { // Animation is still running -> return immediately bHideAndAnimate = false; pHdl = NULL; mpWindow->ReleaseMouse(); return true; } if (aDragTimer.IsActive() ) { aDragTimer.Stop(); bIsInDragMode = false; } if( !mpView ) return false; Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) ); sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); if (mpView->IsFrameDragSingles() || !mpView->HasMarkablePoints()) { /********************************************************************** * NO BEZIER_EDITOR **********************************************************************/ if ( mpView->IsDragObj() ) { /****************************************************************** * Object was moved ******************************************************************/ FrameView* pFrameView = mpViewShell->GetFrameView(); bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); if (bDragWithCopy) { bDragWithCopy = !mpView->IsPresObjSelected(false, true); } mpView->SetDragWithCopy(bDragWithCopy); mpView->EndDragObj( mpView->IsDragWithCopy() ); mpView->ForceMarkedToAnotherPage(); if (!rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() && !bSelectionChanged && std::abs(aPnt.X() - aMDPos.X()) < nDrgLog && std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) { /************************************************************* * If a user wants to click on an object in front of a marked * one, he releases the mouse button immediately **************************************************************/ if (mpView->PickObj(aMDPos, mpView->getHitTolLog(), pObj, pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK)) { if (pPV->IsObjSelectable(pObj)) { mpView->UnmarkAllObj(); mpView->MarkObj(pObj,pPV,false); return true; } } /************************************************************** * Toggle between selection and rotation **************************************************************/ SdrObject* pSingleObj = NULL; if (mpView->GetMarkedObjectList().GetMarkCount()==1) { pSingleObj = mpView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); } if (nSlotId == SID_OBJECT_SELECT && mpView->IsRotateAllowed() && (rMEvt.GetClicks() != 2) && (mpViewShell->GetFrameView()->IsClickChangeRotation() || (pSingleObj && pSingleObj->GetObjInventor()==E3dInventor)) && ! bSelectionOnly) { bTempRotation = true; nSlotId = SID_OBJECT_ROTATE; Activate(); } else if (nSlotId == SID_OBJECT_ROTATE) { nSlotId = SID_OBJECT_SELECT; Activate(); } } else if (nSlotId == SID_CONVERT_TO_3D_LATHE) { if (!pHdl) { bSuppressChangesOfSelection = true; mpView->Start3DCreation(); bSuppressChangesOfSelection = false; } else if (pHdl->GetKind() != HDL_MIRX && pHdl->GetKind() != HDL_REF1 && pHdl->GetKind() != HDL_REF2 && mpView->Is3DRotationCreationActive()) { /********************************************************* * If 3D-rotation bodies are about to be created, * end creation now **********************************************************/ long nAngle1 = GetAngle(aPnt - mpView->GetRef1()); nAngle1 -= 27000; nAngle1 = NormAngle360(nAngle1); bool bMirrorSide1 = nAngle1 < 18000L; if (bMirrorSide0 != bMirrorSide1) { bSuppressChangesOfSelection = true; mpWindow->EnterWait(); mpView->End3DCreation(); bSuppressChangesOfSelection = false; nSlotId = SID_OBJECT_SELECT; mpWindow->LeaveWait(); Activate(); } } } } else if (rMEvt.IsMod1() && !rMEvt.IsMod2() && std::abs(aPnt.X() - aMDPos.X()) < nDrgLog && std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) { // Enter group mpView->MarkObj(aPnt, nHitLog, rMEvt.IsShift(), rMEvt.IsMod1()); } if (mpView->IsAction() ) { mpView->EndAction(); } if( SD_MOD()->GetWaterCan() ) { if( rMEvt.IsRight() ) { // In watering-can mode, on press onto right mouse button, a undo is executed mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_UNDO, SfxCallMode::ASYNCHRON ); } else if (pWaterCanCandidate != NULL) { // Is the candidate object still under the mouse? if (pickObject (aPnt) == pWaterCanCandidate) { SdStyleSheetPool* pPool = static_cast( mpDocSh->GetStyleSheetPool()); if (pPool != NULL) { SfxStyleSheet* pStyleSheet = static_cast( pPool->GetActualStyleSheet()); if (pStyleSheet != NULL && mpView->IsUndoEnabled() ) { // Added UNDOs for the WaterCan mode. This was never done in // the past, thus it was missing all the time. SdrUndoAction* pUndoAttr = mpDoc->GetSdrUndoFactory().CreateUndoAttrObject(*pWaterCanCandidate, true, true); mpView->BegUndo(pUndoAttr->GetComment()); mpView->AddUndo(mpDoc->GetSdrUndoFactory().CreateUndoGeoObject(*pWaterCanCandidate)); mpView->AddUndo(pUndoAttr); pWaterCanCandidate->SetStyleSheet (pStyleSheet, false); mpView->EndUndo(); } } } } // else when there has been no object under the mouse when the // button was pressed then nothing happens even when there is // one now. } sal_uInt16 nClicks = rMEvt.GetClicks(); if (nClicks == 2 && rMEvt.IsLeft() && bMBDown && !rMEvt.IsMod1() && !rMEvt.IsShift() ) { DoubleClick(rMEvt); } bMBDown = false; ForcePointer(&rMEvt); pHdl = NULL; mpWindow->ReleaseMouse(); SdrObject* pSingleObj = NULL; const size_t nMarkCount = mpView->GetMarkedObjectList().GetMarkCount(); if (nMarkCount==1) { pSingleObj = mpView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); } if ( (nSlotId != SID_OBJECT_SELECT && nMarkCount==0) || ( mpView->GetDragMode() == SDRDRAG_CROOK && !mpView->IsCrookAllowed( mpView->IsCrookNoContortion() ) ) || ( mpView->GetDragMode() == SDRDRAG_SHEAR && !mpView->IsShearAllowed() && !mpView->IsDistortAllowed() ) || ( nSlotId==SID_CONVERT_TO_3D_LATHE && pSingleObj && (pSingleObj->GetObjInventor() != SdrInventor || pSingleObj->GetObjIdentifier() == OBJ_MEASURE) ) ) { bReturn = true; ForcePointer(&rMEvt); pHdl = NULL; mpWindow->ReleaseMouse(); FuDraw::MouseButtonUp(rMEvt); mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::SYNCHRON); return bReturn; // CAUTION, due to the synchronous slot, the object is deleted now. } FuDraw::MouseButtonUp(rMEvt); } else { /********************************************************************** * BEZIER_EDITOR **********************************************************************/ if ( mpView->IsAction() ) { if ( mpView->IsInsObjPoint() ) { mpView->EndInsObjPoint(SDRCREATE_FORCEEND); } else if ( mpView->IsDragObj() ) { FrameView* pFrameView = mpViewShell->GetFrameView(); bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy()); if (bDragWithCopy) { bDragWithCopy = !mpView->IsPresObjSelected(false, true); } mpView->SetDragWithCopy(bDragWithCopy); mpView->EndDragObj( mpView->IsDragWithCopy() ); } else { mpView->EndAction(); sal_uInt16 nDrgLog2 = sal_uInt16 ( mpWindow->PixelToLogic(Size(DRGPIX,0)).Width() ); Point aPos = mpWindow->PixelToLogic( rMEvt.GetPosPixel() ); if (std::abs(aMDPos.X() - aPos.X()) < nDrgLog2 && std::abs(aMDPos.Y() - aPos.Y()) < nDrgLog2 && !rMEvt.IsShift() && !rMEvt.IsMod2()) { SdrViewEvent aVEvt; SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt); if (eHit == SDRHIT_NONE) { // Click on the same place - unselect mpView->UnmarkAllObj(); } } } } else if (!rMEvt.IsShift() && rMEvt.IsMod1() && !rMEvt.IsMod2() && std::abs(aPnt.X() - aMDPos.X()) < nDrgLog && std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog) { // Enter group mpView->MarkObj(aPnt, nHitLog, false, rMEvt.IsMod1()); } ForcePointer(&rMEvt); pHdl = NULL; mpWindow->ReleaseMouse(); FuDraw::MouseButtonUp(rMEvt); } return bReturn; } /** * Process keyboard input * @returns sal_True if a KeyEvent is being processed, sal_False otherwise */ bool FuSelection::KeyInput(const KeyEvent& rKEvt) { bool bReturn = false; switch (rKEvt.GetKeyCode().GetCode()) { case KEY_ESCAPE: { bReturn = FuSelection::cancel(); } break; //add keyboard operation for insert points in drawing curve case KEY_UP: case KEY_DOWN: case KEY_LEFT: case KEY_RIGHT: { if(rKEvt.GetKeyCode().IsShift()&&(nEditMode == SID_BEZIER_INSERT)){ long nX = 0; long nY = 0; sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); if (nCode == KEY_UP) { // Scroll nach oben nX = 0; nY =-1; } else if (nCode == KEY_DOWN) { // Scroll nach unten nX = 0; nY = 1; } else if (nCode == KEY_LEFT) { // Scroll nach links nX =-1; nY = 0; } else if (nCode == KEY_RIGHT) { // Scroll nach rechts nX = 1; nY = 0; } Point centerPoint; Rectangle rect = mpView->GetMarkedObjRect(); centerPoint = mpWindow->LogicToPixel(rect.Center()); Point aPoint = bMovedToCenterPoint? oldPoint:centerPoint; Point ePoint = aPoint + Point(nX,nY); mpWindow->SetPointerPosPixel(ePoint); //simulate mouse move action MouseEvent eMevt(ePoint, 1, MouseEventModifiers::DRAGMOVE, MOUSE_LEFT, 0); MouseMove(eMevt); oldPoint = ePoint; bMovedToCenterPoint = true; bReturn = true; } } break; case KEY_RETURN: if(rKEvt.GetKeyCode().IsShift()&&(nEditMode == SID_BEZIER_INSERT)) { if(!bBeginInsertPoint) { //simulate mouse button down action MouseEvent aMevt(oldPoint, 1, MouseEventModifiers::SIMPLEMOVE | MouseEventModifiers::DRAGMOVE, MOUSE_LEFT, KEY_SHIFT); MouseButtonDown(aMevt); mpWindow->CaptureMouse(); bBeginInsertPoint = true; } else { //simulate mouse button up action MouseEvent rMEvt(oldPoint, 1, MouseEventModifiers::SIMPLEMOVE | MouseEventModifiers::ENTERWINDOW, MOUSE_LEFT, KEY_SHIFT); MouseButtonUp(rMEvt); bBeginInsertPoint = false; } bReturn= true; } break; } if (!bReturn) { bReturn = FuDraw::KeyInput(rKEvt); if(mpView->GetMarkedObjectList().GetMarkCount() == 0) { mpView->ResetCreationActive(); mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); } } return bReturn; } void FuSelection::Activate() { SdrDragMode eMode; mpView->ResetCreationActive(); mpView->SetEditMode(SDREDITMODE_EDIT); switch( nSlotId ) { case SID_OBJECT_ROTATE: { eMode = SDRDRAG_ROTATE; if ( mpView->GetDragMode() != eMode ) mpView->SetDragMode(eMode); } break; case SID_OBJECT_MIRROR: { eMode = SDRDRAG_MIRROR; if ( mpView->GetDragMode() != eMode ) mpView->SetDragMode(eMode); } break; case SID_OBJECT_CROP: { eMode = SDRDRAG_CROP; if ( mpView->GetDragMode() != eMode ) mpView->SetDragMode(eMode); } break; case SID_OBJECT_TRANSPARENCE: { eMode = SDRDRAG_TRANSPARENCE; if ( mpView->GetDragMode() != eMode ) mpView->SetDragMode(eMode); } break; case SID_OBJECT_GRADIENT: { eMode = SDRDRAG_GRADIENT; if ( mpView->GetDragMode() != eMode ) mpView->SetDragMode(eMode); } break; case SID_OBJECT_SHEAR: { eMode = SDRDRAG_SHEAR; if ( mpView->GetDragMode() != eMode ) mpView->SetDragMode(eMode); } break; case SID_OBJECT_CROOK_ROTATE: { eMode = SDRDRAG_CROOK; if ( mpView->GetDragMode() != eMode ) { mpView->SetDragMode(eMode); mpView->SetCrookMode(SDRCROOK_ROTATE); } } break; case SID_OBJECT_CROOK_SLANT: { eMode = SDRDRAG_CROOK; if ( mpView->GetDragMode() != eMode ) { mpView->SetDragMode(eMode); mpView->SetCrookMode(SDRCROOK_SLANT); } } break; case SID_OBJECT_CROOK_STRETCH: { eMode = SDRDRAG_CROOK; if ( mpView->GetDragMode() != eMode ) { mpView->SetDragMode(eMode); mpView->SetCrookMode(SDRCROOK_STRETCH); } } break; case SID_CONVERT_TO_3D_LATHE: { eMode = SDRDRAG_MIRROR; bSuppressChangesOfSelection = true; if ( mpView->GetDragMode() != eMode ) mpView->SetDragMode(eMode); if (!mpView->Is3DRotationCreationActive()) mpView->Start3DCreation(); bSuppressChangesOfSelection = false; } break; default: { eMode = SDRDRAG_MOVE; if ( mpView->GetDragMode() != eMode ) mpView->SetDragMode(eMode); } break; } if (nSlotId != SID_OBJECT_ROTATE) { bTempRotation = false; } FuDraw::Activate(); } void FuSelection::Deactivate() { FuDraw::Deactivate(); } void FuSelection::SelectionHasChanged() { bSelectionChanged = true; FuDraw::SelectionHasChanged(); if ((mpView->Is3DRotationCreationActive() && !bSuppressChangesOfSelection)) { // Switch rotation body -> selection mpView->ResetCreationActive(); nSlotId = SID_OBJECT_SELECT; Activate(); } // Activate the right tool bar for the current context of the view. mpViewShell->GetViewShellBase().GetToolBarManager()->SelectionHasChanged(*mpViewShell, *mpView); } /** * Set current bezier edit mode */ void FuSelection::SetEditMode(sal_uInt16 nMode) { nEditMode = nMode; if (nEditMode == SID_BEZIER_INSERT) { mpView->SetInsObjPointMode(true); } else { mpView->SetInsObjPointMode(false); } ForcePointer(); SfxBindings& rBindings = mpViewShell->GetViewFrame()->GetBindings(); rBindings.Invalidate(SID_BEZIER_MOVE); rBindings.Invalidate(SID_BEZIER_INSERT); } /** * Execute animation or interaction */ bool FuSelection::AnimateObj(SdrObject* pObj, const Point& rPos) { bool bAnimated = false; bool bClosed = pObj->IsClosedObj(); bool bFilled = false; if (bClosed) { SfxItemSet aSet(mpDoc->GetPool()); aSet.Put(pObj->GetMergedItemSet()); const XFillStyleItem& rFillStyle = static_cast( aSet.Get(XATTR_FILLSTYLE) ); bFilled = rFillStyle.GetValue() != drawing::FillStyle_NONE; } const SetOfByte* pVisiLayer = &mpView->GetSdrPageView()->GetVisibleLayers(); sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() ); const long n2HitLog = nHitLog * 2; Point aHitPosR(rPos); Point aHitPosL(rPos); Point aHitPosT(rPos); Point aHitPosB(rPos); aHitPosR.X() += n2HitLog; aHitPosL.X() -= n2HitLog; aHitPosT.Y() += n2HitLog; aHitPosB.Y() -= n2HitLog; if ( !bClosed || !bFilled || (SdrObjectPrimitiveHit(*pObj, aHitPosR, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, false) && SdrObjectPrimitiveHit(*pObj, aHitPosL, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, false) && SdrObjectPrimitiveHit(*pObj, aHitPosT, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, false) && SdrObjectPrimitiveHit(*pObj, aHitPosB, nHitLog, *mpView->GetSdrPageView(), pVisiLayer, false) ) ) { if ( mpDoc->GetIMapInfo( pObj ) ) { const IMapObject* pIMapObj = mpDoc->GetHitIMapObject( pObj, rPos, *mpWindow ); if ( pIMapObj && !pIMapObj->GetURL().isEmpty() ) { // Jump to Document mpWindow->ReleaseMouse(); SfxStringItem aStrItem(SID_FILE_NAME, pIMapObj->GetURL()); SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName()); SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame); SfxBoolItem aBrowseItem( SID_BROWSE, true ); mpWindow->ReleaseMouse(); pFrame->GetDispatcher()-> Execute(SID_OPENDOC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, &aStrItem, &aFrameItem, &aBrowseItem, &aReferer, 0L); bAnimated = true; } } else if (!mpDocSh->ISA(GraphicDocShell) && mpView->ISA(DrawView) && mpDoc->GetAnimationInfo(pObj)) { /********************************************************** * Animation-object hit in the middle -> interaction **********************************************************/ SdAnimationInfo* pInfo = mpDoc->GetAnimationInfo(pObj); DrawViewShell* pDrViewSh = static_cast(mpViewShell); mpWindow->ReleaseMouse(); switch (pInfo->meClickAction) { case presentation::ClickAction_BOOKMARK: { // Jump to Bookmark (Page or Object) SfxStringItem aItem(SID_NAVIGATOR_OBJECT, pInfo->GetBookmark()); mpViewShell->GetViewFrame()->GetDispatcher()-> Execute(SID_NAVIGATOR_OBJECT, SfxCallMode::SLOT | SfxCallMode::RECORD, &aItem, 0L); bAnimated = true; } break; case presentation::ClickAction_DOCUMENT: { OUString sBookmark( pInfo->GetBookmark() ); // Jump to document if (!sBookmark.isEmpty()) { SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName()); SfxStringItem aStrItem(SID_FILE_NAME, sBookmark); SfxViewFrame* pFrame = mpViewShell->GetViewFrame(); SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame); SfxBoolItem aBrowseItem( SID_BROWSE, true ); pFrame->GetDispatcher()-> Execute(SID_OPENDOC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, &aStrItem, &aFrameItem, &aBrowseItem, &aReferer, 0L); } bAnimated = true; } break; case presentation::ClickAction_PREVPAGE: { // Jump to the previous page SfxUInt16Item aItem(SID_NAVIGATOR_PAGE, PAGE_PREVIOUS); mpViewShell->GetViewFrame()->GetDispatcher()-> Execute(SID_NAVIGATOR_PAGE, SfxCallMode::SLOT | SfxCallMode::RECORD, &aItem, 0L); bAnimated = true; } break; case presentation::ClickAction_NEXTPAGE: { // Jump to the next page SfxUInt16Item aItem(SID_NAVIGATOR_PAGE, PAGE_NEXT); mpViewShell->GetViewFrame()->GetDispatcher()-> Execute(SID_NAVIGATOR_PAGE, SfxCallMode::SLOT | SfxCallMode::RECORD, &aItem, 0L); bAnimated = true; } break; case presentation::ClickAction_FIRSTPAGE: { // Jump to the first page SfxUInt16Item aItem(SID_NAVIGATOR_PAGE, PAGE_FIRST); mpViewShell->GetViewFrame()->GetDispatcher()-> Execute(SID_NAVIGATOR_PAGE, SfxCallMode::SLOT | SfxCallMode::RECORD, &aItem, 0L); bAnimated = true; } break; case presentation::ClickAction_LASTPAGE: { // Jump to the last page SfxUInt16Item aItem(SID_NAVIGATOR_PAGE, PAGE_LAST); mpViewShell->GetViewFrame()->GetDispatcher()-> Execute(SID_NAVIGATOR_PAGE, SfxCallMode::SLOT | SfxCallMode::RECORD, &aItem, 0L); bAnimated = true; } break; case presentation::ClickAction_SOUND: { try { mxPlayer.set( avmedia::MediaWindow::createPlayer( pInfo->GetBookmark(), ""/*TODO?*/), uno::UNO_QUERY_THROW ); mxPlayer->start(); } catch( uno::Exception& ) { } bAnimated = true; } break; case presentation::ClickAction_VERB: { // Assign verb mpView->UnmarkAll(); mpView->MarkObj(pObj, mpView->GetSdrPageView(), false); pDrViewSh->DoVerb((sal_Int16)pInfo->mnVerb); bAnimated = true; } break; case presentation::ClickAction_PROGRAM: { OUString aBaseURL = GetDocSh()->GetMedium()->GetBaseURL(); INetURLObject aURL( ::URIHelper::SmartRel2Abs( INetURLObject(aBaseURL), pInfo->GetBookmark(), URIHelper::GetMaybeFileHdl(), true, false, INetURLObject::WAS_ENCODED, INetURLObject::DECODE_UNAMBIGUOUS ) ); if( INetProtocol::File == aURL.GetProtocol() ) { SfxStringItem aUrl( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::NO_DECODE ) ); SfxBoolItem aBrowsing( SID_BROWSE, true ); SfxViewFrame* pViewFrm = SfxViewFrame::Current(); if (pViewFrm) pViewFrm->GetDispatcher()->Execute( SID_OPENDOC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, &aUrl, &aBrowsing, 0L ); } bAnimated = true; } break; case presentation::ClickAction_MACRO: { // Execute macro OUString aMacro = pInfo->GetBookmark(); if ( SfxApplication::IsXScriptURL( aMacro ) ) { uno::Any aRet; uno::Sequence< sal_Int16 > aOutArgsIndex; uno::Sequence< uno::Any > aOutArgs; uno::Sequence< uno::Any >* pInArgs = new uno::Sequence< uno::Any >(0); ErrCode eErr = mpDocSh->CallXScript( aMacro, *pInArgs, aRet, aOutArgsIndex, aOutArgs); // Check the return value from the script bool bTmp = false; if ( eErr == ERRCODE_NONE && aRet.getValueType() == cppu::UnoType::get() && ( aRet >>= bTmp ) && bTmp ) { bAnimated = true; } else { bAnimated = false; } } else { // aMacro has got following format: // "Macroname.Modulname.Libname.Documentname" or // "Macroname.Modulname.Libname.Applicationname" OUString aMacroName = aMacro.getToken(0, '.'); OUString aModulName = aMacro.getToken(1, '.'); // In this moment the Call-method only // resolves modulename+macroname OUString aExecMacro(aModulName + "." + aMacroName); bAnimated = mpDocSh->GetBasic()->Call(aExecMacro); } } break; default: { bAnimated = false; } break; } } if (!bAnimated && mpView->ISA(DrawView) && !mpDocSh->ISA(GraphicDocShell) && SlideShow::IsRunning( mpViewShell->GetViewShellBase() ) && mpDoc->GetAnimationInfo(pObj)) { /********************************************************** * Effect-Object hit in the middle -> Play effect **********************************************************/ SdAnimationInfo* pInfo = mpDoc->GetAnimationInfo(pObj); switch (pInfo->meClickAction) { case presentation::ClickAction_VANISH: case presentation::ClickAction_INVISIBLE: break; default: bAnimated = false; break; } } } return bAnimated; } /** is called when the current function should be aborted.

This is used when a function gets a KEY_ESCAPE but can also be called directly. @returns true if a active function was aborted */ bool FuSelection::cancel() { if (mpView->Is3DRotationCreationActive()) { mpView->ResetCreationActive(); mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); return true; } else { return false; } } SdrObject* FuSelection::pickObject (const Point& rTestPoint) { SdrObject* pObject = NULL; SdrPageView* pPageView; sal_uInt16 nHitLog = sal_uInt16 (mpWindow->PixelToLogic(Size(HITPIX,0)).Width()); mpView->PickObj (rTestPoint, nHitLog, pObject, pPageView, SdrSearchOptions::PICKMARKABLE); return pObject; } void FuSelection::ForcePointer(const MouseEvent* pMEvt) { if(bMovedToCenterPoint && !bBeginInsertPoint && pMEvt) { MouseEvent aMEvt(pMEvt->GetPosPixel(), pMEvt->GetClicks(), pMEvt->GetMode(), pMEvt->GetButtons(), pMEvt->GetModifier() & ~KEY_SHIFT); FuDraw::ForcePointer(&aMEvt); } else { FuDraw::ForcePointer(pMEvt); } } } // end of namespace sd /* vim:set shiftwidth=4 softtabstop=4 expandtab: */