5da4acd481
From 211 to 129 Change-Id: I2ccb4261f5f842e7f1514bc0c8eab2591ead173e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168256 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
1138 lines
37 KiB
C++
1138 lines
37 KiB
C++
/* -*- 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 <fupoor.hxx>
|
|
|
|
#include <svx/svxids.hrc>
|
|
#include <svx/svdpagv.hxx>
|
|
#include <svx/svdoole2.hxx>
|
|
#include <svx/svdograf.hxx>
|
|
#include <vcl/seleng.hxx>
|
|
#include <sfx2/dispatch.hxx>
|
|
#include <sfx2/bindings.hxx>
|
|
#include <sfx2/request.hxx>
|
|
#include <svl/stritem.hxx>
|
|
|
|
#include <app.hrc>
|
|
#include <fusel.hxx>
|
|
#include <sdpage.hxx>
|
|
#include <DrawViewShell.hxx>
|
|
#include <Window.hxx>
|
|
#include <drawdoc.hxx>
|
|
#include <DrawDocShell.hxx>
|
|
#include <zoomlist.hxx>
|
|
#include <slideshow.hxx>
|
|
#include <LayerTabBar.hxx>
|
|
|
|
#include <com/sun/star/embed/EmbedVerbs.hpp>
|
|
|
|
#include <sfx2/viewfrm.hxx>
|
|
|
|
#include <svx/svditer.hxx>
|
|
|
|
#include <editeng/editeng.hxx>
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
namespace sd {
|
|
|
|
|
|
FuPoor::FuPoor (
|
|
ViewShell* pViewSh,
|
|
::sd::Window* pWin,
|
|
::sd::View* pView,
|
|
SdDrawDocument* pDrDoc,
|
|
SfxRequest& rReq)
|
|
: mpView(pView),
|
|
mpViewShell(pViewSh),
|
|
mpWindow(pWin),
|
|
mpDocSh( pDrDoc->GetDocSh() ),
|
|
mpDoc(pDrDoc),
|
|
nSlotId( rReq.GetSlot() ),
|
|
aScrollTimer("sd FuPoor aScrollTimer"),
|
|
aDragTimer("sd FuPoor aDragTimer"),
|
|
bIsInDragMode(false),
|
|
bNoScrollUntilInside (true),
|
|
aDelayToScrollTimer("sd FuPoor aDelayToScrollTimer"),
|
|
bScrollable (false),
|
|
bDelayActive (false),
|
|
bFirstMouseMove (false),
|
|
// remember MouseButton state
|
|
mnCode(0)
|
|
{
|
|
ReceiveRequest(rReq);
|
|
|
|
aScrollTimer.SetInvokeHandler( LINK(this, FuPoor, ScrollHdl) );
|
|
aScrollTimer.SetTimeout(SELENG_AUTOREPEAT_INTERVAL);
|
|
|
|
aDragTimer.SetInvokeHandler( LINK(this, FuPoor, DragHdl) );
|
|
aDragTimer.SetTimeout(SELENG_DRAGDROP_TIMEOUT);
|
|
|
|
aDelayToScrollTimer.SetInvokeHandler( LINK(this, FuPoor, DelayHdl) );
|
|
aDelayToScrollTimer.SetTimeout(2000);
|
|
}
|
|
|
|
FuPoor::~FuPoor()
|
|
{
|
|
aDragTimer.Stop();
|
|
aScrollTimer.Stop();
|
|
aDelayToScrollTimer.Stop();
|
|
}
|
|
|
|
void FuPoor::Activate()
|
|
{
|
|
}
|
|
|
|
void FuPoor::Deactivate()
|
|
{
|
|
aDragTimer.Stop();
|
|
aScrollTimer.Stop();
|
|
aDelayToScrollTimer.Stop ();
|
|
bScrollable = bDelayActive = false;
|
|
|
|
if (mpWindow && mpWindow->IsMouseCaptured())
|
|
mpWindow->ReleaseMouse();
|
|
}
|
|
|
|
void FuPoor::SetWindow(::sd::Window* pWin)
|
|
{
|
|
mpWindow = pWin;
|
|
}
|
|
|
|
/**
|
|
* scroll when approached the border of the window; is called by MouseMove
|
|
*/
|
|
void FuPoor::ForceScroll(const Point& aPixPos)
|
|
{
|
|
aScrollTimer.Stop();
|
|
|
|
if ( mpView->IsDragHelpLine() || mpView->IsSetPageOrg() ||
|
|
(SlideShow::IsRunning( mpViewShell->GetViewShellBase() )
|
|
&& !SlideShow::IsInteractiveSlideshow( &mpViewShell->GetViewShellBase() )) ) // IASS
|
|
return;
|
|
|
|
Point aPos = mpWindow->OutputToScreenPixel(aPixPos);
|
|
const ::tools::Rectangle& rRect = mpViewShell->GetAllWindowRect();
|
|
|
|
if ( bNoScrollUntilInside )
|
|
{
|
|
if ( rRect.Contains(aPos) )
|
|
bNoScrollUntilInside = false;
|
|
}
|
|
else
|
|
{
|
|
short dx = 0, dy = 0;
|
|
|
|
if ( aPos.X() <= rRect.Left() ) dx = -1;
|
|
if ( aPos.X() >= rRect.Right() ) dx = 1;
|
|
if ( aPos.Y() <= rRect.Top() ) dy = -1;
|
|
if ( aPos.Y() >= rRect.Bottom() ) dy = 1;
|
|
|
|
if ( dx != 0 || dy != 0 )
|
|
{
|
|
if (bScrollable)
|
|
{
|
|
// scroll action in derived class
|
|
mpViewShell->ScrollLines(dx, dy);
|
|
aScrollTimer.Start();
|
|
}
|
|
else if (! bDelayActive) StartDelayToScrollTimer ();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* timer handler for window scrolling
|
|
*/
|
|
IMPL_LINK_NOARG(FuPoor, ScrollHdl, Timer *, void)
|
|
{
|
|
Point aPnt(mpWindow->GetPointerPosPixel());
|
|
|
|
// use remembered MouseButton state to create correct
|
|
// MouseEvents for this artificial MouseMove.
|
|
MouseMove(MouseEvent(aPnt, 1, MouseEventModifiers::NONE, GetMouseButtonCode()));
|
|
}
|
|
|
|
/**
|
|
* handle keyboard events
|
|
* @returns sal_True if the event was handled, sal_False otherwise
|
|
*/
|
|
bool FuPoor::KeyInput(const KeyEvent& rKEvt)
|
|
{
|
|
sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
|
|
bool bReturn = false;
|
|
bool bSlideShow = SlideShow::IsRunning( mpViewShell->GetViewShellBase() )
|
|
&& !SlideShow::IsInteractiveSlideshow( &mpViewShell->GetViewShellBase() ); // IASS
|
|
|
|
switch (nCode)
|
|
{
|
|
case KEY_RETURN:
|
|
{
|
|
if(rKEvt.GetKeyCode().IsMod1())
|
|
{
|
|
if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ))
|
|
{
|
|
SdPage* pActualPage = pDrawViewShell->GetActualPage();
|
|
SdrTextObj* pCandidate = nullptr;
|
|
|
|
if(pActualPage)
|
|
{
|
|
SdrObjListIter aIter(pActualPage, SdrIterMode::DeepNoGroups);
|
|
|
|
while(aIter.IsMore() && !pCandidate)
|
|
{
|
|
SdrObject* pObj = aIter.Next();
|
|
|
|
if(auto pTextObj = DynCastSdrTextObj( pObj ))
|
|
{
|
|
SdrInventor nInv(pObj->GetObjInventor());
|
|
SdrObjKind nKnd(pObj->GetObjIdentifier());
|
|
|
|
if(SdrInventor::Default == nInv &&
|
|
(SdrObjKind::TitleText == nKnd || SdrObjKind::OutlineText == nKnd || SdrObjKind::Text == nKnd))
|
|
{
|
|
pCandidate = pTextObj;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pCandidate)
|
|
{
|
|
mpView->UnMarkAll();
|
|
mpView->MarkObj(pCandidate, mpView->GetSdrPageView());
|
|
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
|
|
SID_ATTR_CHAR, SfxCallMode::ASYNCHRON);
|
|
}
|
|
else
|
|
{
|
|
// insert a new page with the same page layout
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->Execute(
|
|
SID_INSERTPAGE_QUICK, SfxCallMode::ASYNCHRON);
|
|
}
|
|
|
|
// consumed
|
|
bReturn = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// activate OLE object on RETURN for selected object
|
|
// activate text edit on RETURN for selected object
|
|
const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
|
|
|
|
if( !mpView->IsTextEdit() && 1 == rMarkList.GetMarkCount() )
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark( 0 )->GetMarkedSdrObj();
|
|
|
|
if( dynamic_cast< const SdrOle2Obj* >( pObj ) && !mpDocSh->IsUIActive() )
|
|
{
|
|
//HMHmpView->HideMarkHdl();
|
|
mpViewShell->ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
|
|
}
|
|
else if( pObj && pObj->IsEmptyPresObj() && dynamic_cast< const SdrGrafObj *>( pObj ) != nullptr )
|
|
{
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_INSERT_GRAPHIC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
|
|
}
|
|
else
|
|
{
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->Execute( SID_ATTR_CHAR, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
|
|
}
|
|
|
|
// consumed
|
|
bReturn = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_TAB:
|
|
{
|
|
// handle Mod1 and Mod2 to get travelling running on different systems
|
|
if(rKEvt.GetKeyCode().IsMod1() || rKEvt.GetKeyCode().IsMod2())
|
|
{
|
|
// do something with a selected handle?
|
|
const SdrHdlList& rHdlList = mpView->GetHdlList();
|
|
bool bForward(!rKEvt.GetKeyCode().IsShift());
|
|
|
|
const_cast<SdrHdlList&>(rHdlList).TravelFocusHdl(bForward);
|
|
|
|
// guarantee visibility of focused handle
|
|
SdrHdl* pHdl = rHdlList.GetFocusHdl();
|
|
|
|
if(pHdl)
|
|
{
|
|
Point aHdlPosition(pHdl->GetPos());
|
|
::tools::Rectangle aVisRect(aHdlPosition - Point(100, 100), Size(200, 200));
|
|
mpView->MakeVisible(aVisRect, *mpWindow);
|
|
}
|
|
|
|
// consumed
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_ESCAPE:
|
|
{
|
|
bReturn = FuPoor::cancel();
|
|
}
|
|
break;
|
|
|
|
case KEY_ADD:
|
|
{
|
|
if (!mpView->IsTextEdit() && !bSlideShow && !mpDocSh->IsUIActive())
|
|
{
|
|
// increase zoom
|
|
mpViewShell->SetZoom(mpWindow->GetZoom() * 3 / 2);
|
|
|
|
if( auto pViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ))
|
|
pViewShell->SetZoomOnPage(false);
|
|
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_SUBTRACT:
|
|
{
|
|
if (!mpView->IsTextEdit() && !bSlideShow && !mpDocSh->IsUIActive())
|
|
{
|
|
// decrease zoom
|
|
mpViewShell->SetZoom(mpWindow->GetZoom() * 2 / 3);
|
|
|
|
if( auto pViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ))
|
|
pViewShell->SetZoomOnPage(false);
|
|
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_MULTIPLY:
|
|
{
|
|
if (!mpView->IsTextEdit() && !bSlideShow)
|
|
{
|
|
// zoom to page
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->
|
|
Execute(SID_SIZE_PAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_DIVIDE:
|
|
{
|
|
if (!mpView->IsTextEdit() && !bSlideShow)
|
|
{
|
|
// zoom to selected objects
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->
|
|
Execute(SID_SIZE_OPTIMAL, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_POINT:
|
|
{
|
|
ZoomList* pZoomList = mpViewShell->GetZoomList();
|
|
|
|
if (!mpView->IsTextEdit() && pZoomList->IsNextPossible() && !bSlideShow && !mpDocSh->IsUIActive())
|
|
{
|
|
// use next ZoomRect
|
|
mpViewShell->SetZoomRect(pZoomList->GetNextZoomRect());
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_COMMA:
|
|
{
|
|
ZoomList* pZoomList = mpViewShell->GetZoomList();
|
|
|
|
if (!mpView->IsTextEdit() && pZoomList->IsPreviousPossible() && !bSlideShow && !mpDocSh->IsUIActive())
|
|
{
|
|
// use previous ZoomRect
|
|
mpViewShell->SetZoomRect(pZoomList->GetPreviousZoomRect());
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_HOME:
|
|
{
|
|
if (!mpView->IsTextEdit() && !bSlideShow)
|
|
if (auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ))
|
|
{
|
|
// jump to first page
|
|
pDrawViewShell->SwitchPage(0);
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_END:
|
|
{
|
|
if (!mpView->IsTextEdit() && !bSlideShow)
|
|
if (auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ))
|
|
{
|
|
// jump to last page
|
|
SdPage* pPage = pDrawViewShell->GetActualPage();
|
|
pDrawViewShell->SwitchPage(mpDoc->GetSdPageCount(
|
|
pPage->GetPageKind()) - 1);
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_PAGEUP:
|
|
{
|
|
if( rKEvt.GetKeyCode().IsMod1() && rKEvt.GetKeyCode().IsMod2() )
|
|
break;
|
|
if( bSlideShow)
|
|
break;
|
|
|
|
if( auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell ) )
|
|
{
|
|
// The page-up key switches layers or pages depending on the
|
|
// modifier key.
|
|
if ( ! rKEvt.GetKeyCode().GetModifier())
|
|
{
|
|
// With no modifier pressed we move to the previous
|
|
// slide.
|
|
mpView->SdrEndTextEdit();
|
|
|
|
// Previous page.
|
|
bReturn = true;
|
|
SdPage* pPage = pDrawViewShell->GetActualPage();
|
|
sal_uInt16 nSdPage = (pPage->GetPageNum() - 1) / 2;
|
|
|
|
if (nSdPage > 0)
|
|
{
|
|
// Switch the page and send events regarding
|
|
// deactivation the old page and activating the new
|
|
// one.
|
|
TabControl& rPageTabControl =
|
|
pDrawViewShell->GetPageTabControl();
|
|
if (rPageTabControl.IsReallyShown())
|
|
rPageTabControl.SendDeactivatePageEvent ();
|
|
pDrawViewShell->SwitchPage(nSdPage - 1);
|
|
if (rPageTabControl.IsReallyShown())
|
|
rPageTabControl.SendActivatePageEvent ();
|
|
}
|
|
}
|
|
else if (rKEvt.GetKeyCode().IsMod1())
|
|
{
|
|
// With the CONTROL modifier we switch layers.
|
|
if (pDrawViewShell->IsLayerModeActive())
|
|
{
|
|
// Moves to the previous layer.
|
|
SwitchLayer (-1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_PAGEDOWN:
|
|
{
|
|
if( rKEvt.GetKeyCode().IsMod1() && rKEvt.GetKeyCode().IsMod2() )
|
|
break;
|
|
if(dynamic_cast< const DrawViewShell *>( mpViewShell ) != nullptr && !bSlideShow)
|
|
{
|
|
// The page-down key switches layers or pages depending on the
|
|
// modifier key.
|
|
if ( ! rKEvt.GetKeyCode().GetModifier())
|
|
{
|
|
// With no modifier pressed we move to the next slide.
|
|
mpView->SdrEndTextEdit();
|
|
|
|
// Next page.
|
|
bReturn = true;
|
|
SdPage* pPage = static_cast<DrawViewShell*>(mpViewShell)->GetActualPage();
|
|
sal_uInt16 nSdPage = (pPage->GetPageNum() - 1) / 2;
|
|
|
|
if (nSdPage < mpDoc->GetSdPageCount(pPage->GetPageKind()) - 1)
|
|
{
|
|
// Switch the page and send events regarding
|
|
// deactivation the old page and activating the new
|
|
// one.
|
|
TabControl& rPageTabControl =
|
|
static_cast<DrawViewShell*>(mpViewShell)->GetPageTabControl();
|
|
if (rPageTabControl.IsReallyShown())
|
|
rPageTabControl.SendDeactivatePageEvent ();
|
|
static_cast<DrawViewShell*>(mpViewShell)->SwitchPage(nSdPage + 1);
|
|
if (rPageTabControl.IsReallyShown())
|
|
rPageTabControl.SendActivatePageEvent ();
|
|
}
|
|
}
|
|
else if (rKEvt.GetKeyCode().IsMod1())
|
|
{
|
|
// With the CONTROL modifier we switch layers.
|
|
if (static_cast<DrawViewShell*>(mpViewShell)->IsLayerModeActive())
|
|
{
|
|
// With the layer mode active pressing page-down
|
|
// moves to the next layer.
|
|
SwitchLayer (+1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// change select state when focus is on poly point
|
|
case KEY_SPACE:
|
|
{
|
|
const SdrHdlList& rHdlList = mpView->GetHdlList();
|
|
SdrHdl* pHdl = rHdlList.GetFocusHdl();
|
|
|
|
if(pHdl)
|
|
{
|
|
if(pHdl->GetKind() == SdrHdlKind::Poly)
|
|
{
|
|
// rescue ID of point with focus
|
|
sal_uInt32 nPol(pHdl->GetPolyNum());
|
|
sal_uInt32 nPnt(pHdl->GetPointNum());
|
|
|
|
if(mpView->IsPointMarked(*pHdl))
|
|
{
|
|
if(rKEvt.GetKeyCode().IsShift())
|
|
{
|
|
mpView->UnmarkPoint(*pHdl);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!rKEvt.GetKeyCode().IsShift())
|
|
{
|
|
mpView->UnmarkAllPoints();
|
|
}
|
|
|
|
mpView->MarkPoint(*pHdl);
|
|
}
|
|
|
|
if(nullptr == rHdlList.GetFocusHdl())
|
|
{
|
|
// restore point with focus
|
|
SdrHdl* pNewOne = nullptr;
|
|
|
|
for(size_t a = 0; !pNewOne && a < rHdlList.GetHdlCount(); ++a)
|
|
{
|
|
SdrHdl* pAct = rHdlList.GetHdl(a);
|
|
|
|
if(pAct
|
|
&& pAct->GetKind() == SdrHdlKind::Poly
|
|
&& pAct->GetPolyNum() == nPol
|
|
&& pAct->GetPointNum() == nPnt)
|
|
{
|
|
pNewOne = pAct;
|
|
}
|
|
}
|
|
|
|
if(pNewOne)
|
|
{
|
|
const_cast<SdrHdlList&>(rHdlList).SetFocusHdl(pNewOne);
|
|
}
|
|
}
|
|
|
|
bReturn = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case KEY_UP:
|
|
case KEY_DOWN:
|
|
case KEY_LEFT:
|
|
case KEY_RIGHT:
|
|
{
|
|
if (!mpView->IsTextEdit() && !bSlideShow)
|
|
{
|
|
::tools::Long nX = 0;
|
|
::tools::Long nY = 0;
|
|
|
|
if (nCode == KEY_UP)
|
|
{
|
|
// scroll up
|
|
nX = 0;
|
|
nY =-1;
|
|
}
|
|
else if (nCode == KEY_DOWN)
|
|
{
|
|
// scroll down
|
|
nX = 0;
|
|
nY = 1;
|
|
}
|
|
else if (nCode == KEY_LEFT)
|
|
{
|
|
// scroll left
|
|
nX =-1;
|
|
nY = 0;
|
|
}
|
|
else if (nCode == KEY_RIGHT)
|
|
{
|
|
// scroll right
|
|
nX = 1;
|
|
nY = 0;
|
|
}
|
|
|
|
const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
|
|
if (rMarkList.GetMarkCount() != 0 && !rKEvt.GetKeyCode().IsMod1() &&
|
|
!mpDocSh->IsReadOnly())
|
|
{
|
|
const SdrHdlList& rHdlList = mpView->GetHdlList();
|
|
SdrHdl* pHdl = rHdlList.GetFocusHdl();
|
|
|
|
bool bIsMoveOfConnectedHandle(false);
|
|
bool bOldSuppress = false;
|
|
SdrEdgeObj* pEdgeObj = nullptr;
|
|
if(pHdl)
|
|
pEdgeObj = dynamic_cast<SdrEdgeObj *>( pHdl->GetObj() );
|
|
|
|
if(pEdgeObj && 0 == pHdl->GetPolyNum())
|
|
{
|
|
if(0 == pHdl->GetPointNum())
|
|
{
|
|
if(pEdgeObj->GetConnection(true).GetSdrObject())
|
|
{
|
|
bIsMoveOfConnectedHandle = true;
|
|
}
|
|
}
|
|
if(1 == pHdl->GetPointNum())
|
|
{
|
|
if(pEdgeObj->GetConnection(false).GetSdrObject())
|
|
{
|
|
bIsMoveOfConnectedHandle = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pEdgeObj)
|
|
{
|
|
// Suppress default connects to inside object and object center
|
|
bOldSuppress = pEdgeObj->GetSuppressDefaultConnect();
|
|
pEdgeObj->SetSuppressDefaultConnect(true);
|
|
}
|
|
|
|
if(bIsMoveOfConnectedHandle)
|
|
{
|
|
sal_uInt16 nMarkHdSiz(mpView->GetMarkHdlSizePixel());
|
|
Size aHalfConSiz(nMarkHdSiz + 1, nMarkHdSiz + 1);
|
|
aHalfConSiz = mpWindow->PixelToLogic(aHalfConSiz);
|
|
|
|
if(100 < aHalfConSiz.Width())
|
|
nX *= aHalfConSiz.Width();
|
|
else
|
|
nX *= 100;
|
|
|
|
if(100 < aHalfConSiz.Height())
|
|
nY *= aHalfConSiz.Height();
|
|
else
|
|
nY *= 100;
|
|
}
|
|
else if(rKEvt.GetKeyCode().IsMod2())
|
|
{
|
|
// move in 1 pixel distance
|
|
Size aLogicSizeOnePixel = mpWindow->PixelToLogic(Size(1,1));
|
|
nX *= aLogicSizeOnePixel.Width();
|
|
nY *= aLogicSizeOnePixel.Height();
|
|
}
|
|
else if(rKEvt.GetKeyCode().IsShift())
|
|
{
|
|
nX *= 1000;
|
|
nY *= 1000;
|
|
}
|
|
else
|
|
{
|
|
// old, fixed move distance
|
|
nX *= 100;
|
|
nY *= 100;
|
|
}
|
|
|
|
if(nullptr == pHdl)
|
|
{
|
|
// only take action when move is allowed
|
|
if(mpView->IsMoveAllowed())
|
|
{
|
|
// restrict movement to WorkArea
|
|
const ::tools::Rectangle& rWorkArea = mpView->GetWorkArea();
|
|
|
|
if(!rWorkArea.IsEmpty())
|
|
{
|
|
::tools::Rectangle aMarkRect(mpView->GetMarkedObjRect());
|
|
aMarkRect.Move(nX, nY);
|
|
|
|
if(!aMarkRect.Contains(rWorkArea))
|
|
{
|
|
if(aMarkRect.Left() < rWorkArea.Left())
|
|
{
|
|
nX += rWorkArea.Left() - aMarkRect.Left();
|
|
}
|
|
|
|
if(aMarkRect.Right() > rWorkArea.Right())
|
|
{
|
|
nX -= aMarkRect.Right() - rWorkArea.Right();
|
|
}
|
|
|
|
if(aMarkRect.Top() < rWorkArea.Top())
|
|
{
|
|
nY += rWorkArea.Top() - aMarkRect.Top();
|
|
}
|
|
|
|
if(aMarkRect.Bottom() > rWorkArea.Bottom())
|
|
{
|
|
nY -= aMarkRect.Bottom() - rWorkArea.Bottom();
|
|
}
|
|
}
|
|
}
|
|
|
|
// no handle selected
|
|
if(0 != nX || 0 != nY)
|
|
{
|
|
mpView->MoveAllMarked(Size(nX, nY));
|
|
|
|
mpView->MakeVisible(mpView->GetAllMarkedRect(), *mpWindow);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// move handle with index nHandleIndex
|
|
if (nX || nY)
|
|
{
|
|
// now move the Handle (nX, nY)
|
|
Point aStartPoint(pHdl->GetPos());
|
|
Point aEndPoint(pHdl->GetPos() + Point(nX, nY));
|
|
const SdrDragStat& rDragStat = mpView->GetDragStat();
|
|
|
|
// start dragging
|
|
mpView->BegDragObj(aStartPoint, nullptr, pHdl, 0);
|
|
|
|
if(mpView->IsDragObj())
|
|
{
|
|
bool bWasNoSnap = rDragStat.IsNoSnap();
|
|
bool bWasSnapEnabled = mpView->IsSnapEnabled();
|
|
|
|
// switch snapping off
|
|
if(!bWasNoSnap)
|
|
const_cast<SdrDragStat&>(rDragStat).SetNoSnap();
|
|
if(bWasSnapEnabled)
|
|
mpView->SetSnapEnabled(false);
|
|
|
|
mpView->MovAction(aEndPoint);
|
|
mpView->EndDragObj();
|
|
|
|
// restore snap
|
|
if(!bWasNoSnap)
|
|
const_cast<SdrDragStat&>(rDragStat).SetNoSnap(bWasNoSnap);
|
|
if(bWasSnapEnabled)
|
|
mpView->SetSnapEnabled(bWasSnapEnabled);
|
|
}
|
|
|
|
// make moved handle visible
|
|
::tools::Rectangle aVisRect(aEndPoint - Point(100, 100), Size(200, 200));
|
|
mpView->MakeVisible(aVisRect, *mpWindow);
|
|
}
|
|
}
|
|
|
|
if(pEdgeObj)
|
|
{
|
|
// Restore original suppress value
|
|
pEdgeObj->SetSuppressDefaultConnect(bOldSuppress);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// scroll page
|
|
mpViewShell->ScrollLines(nX, nY);
|
|
}
|
|
|
|
bReturn = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (bReturn)
|
|
{
|
|
mpWindow->ReleaseMouse();
|
|
}
|
|
|
|
// when a text-editable object is selected and the
|
|
// input character is printable, activate text edit on that object
|
|
// and feed character to object
|
|
if(!bReturn && !mpDocSh->IsReadOnly())
|
|
{
|
|
if (!mpView->IsTextEdit())
|
|
{
|
|
const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
|
|
|
|
if(1 == rMarkList.GetMarkCount())
|
|
{
|
|
SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
|
|
|
|
// #i118485# allow TextInput for OLEs, too
|
|
if( DynCastSdrTextObj( pObj ) != nullptr && pObj->HasTextEdit())
|
|
{
|
|
// use common IsSimpleCharInput from the EditEngine.
|
|
bool bPrintable(EditEngine::IsSimpleCharInput(rKEvt));
|
|
|
|
if(bPrintable)
|
|
{
|
|
// try to activate textedit mode for the selected object
|
|
SfxStringItem aInputString(SID_ATTR_CHAR, OUString(rKEvt.GetCharCode()));
|
|
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(
|
|
SID_ATTR_CHAR,
|
|
SfxCallMode::ASYNCHRON,
|
|
{ &aInputString });
|
|
|
|
// consumed
|
|
bReturn = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// test if there is a title object there. If yes, try to
|
|
// set it to edit mode and start typing...
|
|
DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(mpViewShell);
|
|
if (pDrawViewShell && EditEngine::IsSimpleCharInput(rKEvt))
|
|
{
|
|
SdPage* pActualPage = pDrawViewShell->GetActualPage();
|
|
SdrTextObj* pCandidate = nullptr;
|
|
|
|
if(pActualPage)
|
|
{
|
|
SdrObjListIter aIter(pActualPage, SdrIterMode::DeepNoGroups);
|
|
|
|
while(aIter.IsMore() && !pCandidate)
|
|
{
|
|
SdrObject* pObj = aIter.Next();
|
|
|
|
if(auto pTextObj = DynCastSdrTextObj( pObj ))
|
|
{
|
|
SdrInventor nInv(pObj->GetObjInventor());
|
|
SdrObjKind nKnd(pObj->GetObjIdentifier());
|
|
|
|
if(SdrInventor::Default == nInv && SdrObjKind::TitleText == nKnd)
|
|
{
|
|
pCandidate = pTextObj;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// when candidate found and candidate is untouched, start editing text...
|
|
if(pCandidate && pCandidate->IsEmptyPresObj())
|
|
{
|
|
mpView->UnMarkAll();
|
|
mpView->MarkObj(pCandidate, mpView->GetSdrPageView());
|
|
SfxStringItem aInputString(SID_ATTR_CHAR, OUString(rKEvt.GetCharCode()));
|
|
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->ExecuteList(
|
|
SID_ATTR_CHAR,
|
|
SfxCallMode::ASYNCHRON,
|
|
{ &aInputString });
|
|
|
|
// consumed
|
|
bReturn = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
bool FuPoor::MouseMove(const MouseEvent& )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void FuPoor::SelectionHasChanged()
|
|
{
|
|
const SdrHdlList& rHdlList = mpView->GetHdlList();
|
|
const_cast<SdrHdlList&>(rHdlList).ResetFocusHdl();
|
|
}
|
|
|
|
/**
|
|
* Cut object to clipboard
|
|
*/
|
|
void FuPoor::DoCut()
|
|
{
|
|
if (mpView)
|
|
{
|
|
mpView->DoCut();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Copy object to clipboard
|
|
*/
|
|
void FuPoor::DoCopy()
|
|
{
|
|
if (mpView)
|
|
{
|
|
mpView->DoCopy();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Paste object from clipboard
|
|
*/
|
|
void FuPoor::DoPaste()
|
|
{
|
|
if (mpView)
|
|
{
|
|
mpView->DoPaste(mpWindow);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Paste unformatted text from clipboard
|
|
*/
|
|
void FuPoor::DoPasteUnformatted()
|
|
{
|
|
if (mpView)
|
|
{
|
|
TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( mpViewShell->GetActiveWindow() ) );
|
|
if (aDataHelper.GetTransferable().is())
|
|
{
|
|
sal_Int8 nAction = DND_ACTION_COPY;
|
|
mpView->InsertData( aDataHelper,
|
|
mpWindow->PixelToLogic( ::tools::Rectangle( Point(), mpWindow->GetOutputSizePixel() ).Center() ),
|
|
nAction, false, SotClipboardFormatId::STRING);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Timer handler for Drag&Drop
|
|
*/
|
|
IMPL_LINK_NOARG(FuPoor, DragHdl, Timer *, void)
|
|
{
|
|
if( !mpView )
|
|
return;
|
|
|
|
sal_uInt16 nHitLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(HITPIX,0)).Width() );
|
|
SdrHdl* pHdl = mpView->PickHandle(aMDPos);
|
|
|
|
if ( pHdl==nullptr && mpView->IsMarkedHit(aMDPos, nHitLog)
|
|
&& !mpView->IsPresObjSelected(false) )
|
|
{
|
|
mpWindow->ReleaseMouse();
|
|
bIsInDragMode = true;
|
|
mpView->StartDrag( aMDPos, mpWindow );
|
|
}
|
|
}
|
|
|
|
bool FuPoor::Command(const CommandEvent& rCEvt)
|
|
{
|
|
return mpView->Command(rCEvt,mpWindow);
|
|
}
|
|
|
|
/**
|
|
* Timer handler for window scrolling
|
|
*/
|
|
IMPL_LINK_NOARG(FuPoor, DelayHdl, Timer *, void)
|
|
{
|
|
aDelayToScrollTimer.Stop ();
|
|
bScrollable = true;
|
|
|
|
Point aPnt(mpWindow->GetPointerPosPixel());
|
|
|
|
// use remembered MouseButton state to create correct
|
|
// MouseEvents for this artificial MouseMove.
|
|
MouseMove(MouseEvent(aPnt, 1, MouseEventModifiers::NONE, GetMouseButtonCode()));
|
|
}
|
|
|
|
bool FuPoor::MouseButtonUp (const MouseEvent& rMEvt)
|
|
{
|
|
// remember button state for creation of own MouseEvents
|
|
SetMouseButtonCode(rMEvt.GetButtons());
|
|
|
|
aDelayToScrollTimer.Stop ();
|
|
bScrollable = bDelayActive = false;
|
|
return bScrollable;
|
|
}
|
|
|
|
bool FuPoor::MouseButtonDown(const MouseEvent& rMEvt)
|
|
{
|
|
// remember button state for creation of own MouseEvents
|
|
SetMouseButtonCode(rMEvt.GetButtons());
|
|
|
|
return false;
|
|
}
|
|
|
|
void FuPoor::StartDelayToScrollTimer ()
|
|
{
|
|
bDelayActive = true;
|
|
aDelayToScrollTimer.Start ();
|
|
}
|
|
|
|
bool FuPoor::RequestHelp(const HelpEvent& rHEvt)
|
|
{
|
|
bool bReturn = false;
|
|
|
|
SdrPageView* pPV = mpView->GetSdrPageView();
|
|
|
|
if (pPV)
|
|
{
|
|
SdPage* pPage = static_cast<SdPage*>( pPV->GetPage() );
|
|
|
|
if (pPage)
|
|
{
|
|
bReturn = FmFormPage::RequestHelp(mpWindow, mpView, rHEvt);
|
|
}
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
void FuPoor::ReceiveRequest(SfxRequest& /*rReq*/)
|
|
{
|
|
}
|
|
|
|
rtl::Reference<SdrObject> FuPoor::CreateDefaultObject(const sal_uInt16, const ::tools::Rectangle& )
|
|
{
|
|
// empty base implementation
|
|
return nullptr;
|
|
}
|
|
|
|
void FuPoor::ImpForceQuadratic(::tools::Rectangle& rRect)
|
|
{
|
|
if(rRect.GetWidth() > rRect.GetHeight())
|
|
{
|
|
rRect = ::tools::Rectangle(
|
|
Point(rRect.Left() + ((rRect.GetWidth() - rRect.GetHeight()) / 2), rRect.Top()),
|
|
Size(rRect.GetHeight(), rRect.GetHeight()));
|
|
}
|
|
else
|
|
{
|
|
rRect = ::tools::Rectangle(
|
|
Point(rRect.Left(), rRect.Top() + ((rRect.GetHeight() - rRect.GetWidth()) / 2)),
|
|
Size(rRect.GetWidth(), rRect.GetWidth()));
|
|
}
|
|
}
|
|
|
|
void FuPoor::SwitchLayer (sal_Int32 nOffset)
|
|
{
|
|
auto pDrawViewShell = dynamic_cast<DrawViewShell *>( mpViewShell );
|
|
if(!pDrawViewShell)
|
|
return;
|
|
|
|
// Calculate the new index.
|
|
sal_Int32 nIndex = pDrawViewShell->GetActiveTabLayerIndex() + nOffset;
|
|
|
|
// Make sure the new index lies inside the range of valid indices.
|
|
if (nIndex < 0)
|
|
nIndex = 0;
|
|
else if (nIndex >= pDrawViewShell->GetTabLayerCount ())
|
|
nIndex = pDrawViewShell->GetTabLayerCount() - 1;
|
|
|
|
// Set the new active layer.
|
|
if (nIndex != pDrawViewShell->GetActiveTabLayerIndex ())
|
|
{
|
|
LayerTabBar* pLayerTabControl =
|
|
static_cast<DrawViewShell*>(mpViewShell)->GetLayerTabControl();
|
|
if (pLayerTabControl != nullptr)
|
|
pLayerTabControl->SendDeactivatePageEvent ();
|
|
|
|
pDrawViewShell->SetActiveTabLayerIndex (nIndex);
|
|
|
|
if (pLayerTabControl != nullptr)
|
|
pLayerTabControl->SendActivatePageEvent ();
|
|
}
|
|
}
|
|
|
|
/** is called when the current function should be aborted. <p>
|
|
This is used when a function gets a KEY_ESCAPE but can also
|
|
be called directly.
|
|
|
|
@returns true if an active function was aborted
|
|
*/
|
|
bool FuPoor::cancel()
|
|
{
|
|
if ( dynamic_cast< const FuSelection *>( this ) == nullptr )
|
|
{
|
|
mpViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// #i33136#
|
|
bool FuPoor::doConstructOrthogonal() const
|
|
{
|
|
// Check whether a media object is selected
|
|
bool bResizeKeepRatio = false;
|
|
const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
|
|
// tdf#89758 Avoid interactive crop preview from being proportionally scaled by default.
|
|
if (rMarkList.GetMarkCount() != 0 && mpView->GetDragMode() != SdrDragMode::Crop)
|
|
{
|
|
if (rMarkList.GetMarkCount() == 1)
|
|
{
|
|
SdrObjKind aObjIdentifier = rMarkList.GetMark(0)->GetMarkedSdrObj()->GetObjIdentifier();
|
|
bResizeKeepRatio = aObjIdentifier == SdrObjKind::Graphic ||
|
|
aObjIdentifier == SdrObjKind::Media ||
|
|
aObjIdentifier == SdrObjKind::OLE2;
|
|
}
|
|
}
|
|
SdrHdl* pHdl = mpView->PickHandle(aMDPos);
|
|
// Resize proportionally when media is selected and the user drags on a corner
|
|
if (pHdl)
|
|
bResizeKeepRatio = bResizeKeepRatio && pHdl->IsCornerHdl();
|
|
|
|
return (
|
|
bResizeKeepRatio ||
|
|
SID_DRAW_XLINE == nSlotId ||
|
|
SID_DRAW_CIRCLEARC == nSlotId ||
|
|
SID_DRAW_SQUARE == nSlotId ||
|
|
SID_DRAW_SQUARE_NOFILL == nSlotId ||
|
|
SID_DRAW_SQUARE_ROUND == nSlotId ||
|
|
SID_DRAW_SQUARE_ROUND_NOFILL == nSlotId ||
|
|
SID_DRAW_CIRCLE == nSlotId ||
|
|
SID_DRAW_CIRCLE_NOFILL == nSlotId ||
|
|
SID_DRAW_CIRCLEPIE == nSlotId ||
|
|
SID_DRAW_CIRCLEPIE_NOFILL == nSlotId ||
|
|
SID_DRAW_CIRCLECUT == nSlotId ||
|
|
SID_DRAW_CIRCLECUT_NOFILL == nSlotId ||
|
|
SID_DRAW_XPOLYGON == nSlotId ||
|
|
SID_DRAW_XPOLYGON_NOFILL == nSlotId ||
|
|
SID_3D_CUBE == nSlotId ||
|
|
SID_3D_SPHERE == nSlotId ||
|
|
SID_3D_SHELL == nSlotId ||
|
|
SID_3D_HALF_SPHERE == nSlotId ||
|
|
SID_3D_TORUS == nSlotId ||
|
|
SID_3D_CYLINDER == nSlotId ||
|
|
SID_3D_CONE == nSlotId ||
|
|
SID_3D_PYRAMID == nSlotId);
|
|
}
|
|
|
|
void FuPoor::DoExecute( SfxRequest& )
|
|
{
|
|
}
|
|
|
|
} // end of namespace sd
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|