/* -*- 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 <hintids.hxx>
#include <comphelper/lok.hxx>
#include <svx/svdview.hxx>
#include <svx/svdobj.hxx>
#include <svl/ptitem.hxx>
#include <editeng/sizeitem.hxx>
#include <sfx2/request.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/viewfrm.hxx>
#include <fmtclds.hxx>
#include <frmfmt.hxx>
#include <cmdid.h>
#include <view.hxx>
#include <wrtsh.hxx>
#include <drawbase.hxx>
#include <edtwin.hxx>
#include <swmodule.hxx>
#include <swundo.hxx>
#include <SwCapObjType.hxx>
#include <SwRewriter.hxx>
#include <strings.hrc>
using namespace ::com::sun::star;
SwDrawBase::SwDrawBase(SwWrtShell* pSwWrtShell, SwEditWin* pWindow, SwView* pSwView) :
m_pView(pSwView),
m_pSh(pSwWrtShell),
m_pWin(pWindow),
m_nSlotId(USHRT_MAX),
m_bCreateObj(true),
m_bInsForm(false)
{
if ( !m_pSh->HasDrawView() )
m_pSh->MakeDrawView();
}
SwDrawBase::~SwDrawBase()
{
if (m_pView->GetWrtShellPtr()) // In the view-dtor could the wrtsh already been deleted...
m_pSh->GetDrawView()->SetEditMode();
}
bool SwDrawBase::MouseButtonDown(const MouseEvent& rMEvt)
{
bool bReturn = false;
SdrView *pSdrView = m_pSh->GetDrawView();
// #i33136#
pSdrView->SetOrtho(doConstructOrthogonal() ? !rMEvt.IsShift() : rMEvt.IsShift());
pSdrView->SetAngleSnapEnabled(rMEvt.IsShift());
if (rMEvt.IsMod2())
{
pSdrView->SetCreate1stPointAsCenter(true);
pSdrView->SetResizeAtCenter(true);
}
else
{
pSdrView->SetCreate1stPointAsCenter(false);
pSdrView->SetResizeAtCenter(false);
}
SdrViewEvent aVEvt;
SdrHitKind eHit = pSdrView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
// Only new object, if not in the basic mode (or pure selection mode).
if (rMEvt.IsLeft() && !m_pWin->IsDrawAction())
{
if (IsCreateObj() && (eHit == SdrHitKind::UnmarkedObject || eHit == SdrHitKind::NONE || m_pSh->IsDrawCreate()))
{
g_bNoInterrupt = true;
m_pWin->CaptureMouse();
m_aStartPos = m_pWin->PixelToLogic(rMEvt.GetPosPixel());
bReturn = m_pSh->BeginCreate(m_pWin->GetSdrDrawMode(), m_aStartPos);
SetDrawPointer();
if ( bReturn )
m_pWin->SetDrawAction(true);
}
else if (!pSdrView->IsAction())
{
// BEZIER-EDITOR
m_pWin->CaptureMouse();
m_aStartPos = m_pWin->PixelToLogic(rMEvt.GetPosPixel());
sal_uInt16 nEditMode = m_pWin->GetBezierMode();
if (eHit == SdrHitKind::Handle && aVEvt.mpHdl->GetKind() == SdrHdlKind::BezierWeight)
{
// Drag handle
g_bNoInterrupt = true;
bReturn = pSdrView->BegDragObj(m_aStartPos, nullptr, aVEvt.mpHdl);
m_pWin->SetDrawAction(true);
}
else if (eHit == SdrHitKind::MarkedObject && nEditMode == SID_BEZIER_INSERT)
{
// Insert gluepoint
g_bNoInterrupt = true;
bReturn = pSdrView->BegInsObjPoint(m_aStartPos, rMEvt.IsMod1());
m_pWin->SetDrawAction(true);
}
else if (eHit == SdrHitKind::MarkedObject && rMEvt.IsMod1())
{
// Select gluepoint
if (!rMEvt.IsShift())
pSdrView->UnmarkAllPoints();
bReturn = pSdrView->BegMarkPoints(m_aStartPos);
m_pWin->SetDrawAction(true);
}
else if (eHit == SdrHitKind::MarkedObject && !rMEvt.IsShift() && !rMEvt.IsMod2())
{
// Move object
return false;
}
else if (eHit == SdrHitKind::Handle)
{
// Select gluepoint
if (pSdrView->HasMarkablePoints() && (!pSdrView->IsPointMarked(*aVEvt.mpHdl) || rMEvt.IsShift()))
{
SdrHdl* pHdl = nullptr;
if (!rMEvt.IsShift())
{
pSdrView->UnmarkAllPoints();
pHdl = pSdrView->PickHandle(m_aStartPos);
}
else
{
if (pSdrView->IsPointMarked(*aVEvt.mpHdl))
{
bReturn = pSdrView->UnmarkPoint(*aVEvt.mpHdl);
pHdl = nullptr;
}
else
{
pHdl = pSdrView->PickHandle(m_aStartPos);
}
}
if (pHdl)
{
g_bNoInterrupt = true;
pSdrView->MarkPoint(*pHdl);
}
}
}
else
{
// Select or drag object
if (m_pSh->IsObjSelectable(m_aStartPos) && eHit == SdrHitKind::UnmarkedObject)
{
if (pSdrView->HasMarkablePoints())
pSdrView->UnmarkAllPoints();
g_bNoInterrupt = false;
// Use drag in edtwin
return false;
}
g_bNoInterrupt = true;
if (m_pSh->IsObjSelected())
{
if (!rMEvt.IsShift())
{
if (!pSdrView->HasMarkablePoints())
{
bool bUnlockView = !m_pSh->IsViewLocked();
m_pSh->LockView( true ); //lock visible section
m_pSh->SelectObj(Point(LONG_MAX, LONG_MAX)); // deselect all
if( bUnlockView )
m_pSh->LockView( false );
}
else
pSdrView->UnmarkAllPoints();
}
}
if (!m_pSh->IsSelFrameMode())
m_pSh->EnterSelFrameMode();
bReturn = m_pSh->BeginMark(m_aStartPos);
if( bReturn )
m_pWin->SetDrawAction(true);
SetDrawPointer();
}
}
}
return bReturn;
}
bool SwDrawBase::MouseMove(const MouseEvent& rMEvt)
{
SdrView *pSdrView = m_pSh->GetDrawView();
Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel()));
bool bRet = false;
if (IsCreateObj() && !m_pWin->IsDrawSelMode() && pSdrView->IsCreateObj())
{
// #i33136#
pSdrView->SetOrtho(doConstructOrthogonal() ? !rMEvt.IsShift() : rMEvt.IsShift());
pSdrView->SetAngleSnapEnabled(rMEvt.IsShift());
m_pSh->MoveCreate(aPnt);
bRet = true;
}
else if (pSdrView->IsAction() || pSdrView->IsInsObjPoint() || pSdrView->IsMarkPoints())
{
m_pSh->MoveMark(aPnt);
bRet = true;
}
return bRet;
}
bool SwDrawBase::MouseButtonUp(const MouseEvent& rMEvt)
{
bool bReturn = false;
bool bCheckShell = false;
bool bAutoCap = false;
Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel()));
if (IsCreateObj() && m_pSh->IsDrawCreate() && !m_pWin->IsDrawSelMode())
{
const SdrObjKind nDrawMode = m_pWin->GetSdrDrawMode();
//objects with multiple point may end at the start position
bool bMultiPoint = SdrObjKind::PolyLine == nDrawMode ||
SdrObjKind::Polygon == nDrawMode ||
SdrObjKind::PathLine == nDrawMode ||
SdrObjKind::PathFill == nDrawMode ||
SdrObjKind::FreehandLine == nDrawMode ||
SdrObjKind::FreehandFill == nDrawMode;
if(rMEvt.IsRight())
{
m_pSh->BreakCreate();
m_pView->LeaveDrawCreate();
}
else
{
if (SdrObjKind::NewFrame == nDrawMode)
{
SwRewriter aRewriter;
aRewriter.AddRule(UndoArg1, SwResId(STR_FRAME));
m_pSh->StartUndo(SwUndoId::INSERT, &aRewriter);
}
bool didCreate = m_pSh->EndCreate(SdrCreateCmd::ForceEnd);
if(!didCreate && !bMultiPoint)
{
CreateDefaultObjectAtPosWithSize(aPnt, Size(1000, 1000));
}
if (SdrObjKind::NewFrame == nDrawMode) // Text border inserted
{
uno::Reference< frame::XDispatchRecorder > xRecorder =
m_pSh->GetView().GetViewFrame().GetBindings().GetRecorder();
if ( xRecorder.is() )
{
SfxRequest aReq(m_pSh->GetView().GetViewFrame(), FN_INSERT_FRAME);
aReq .AppendItem(SfxUInt16Item( FN_INSERT_FRAME,
static_cast<sal_uInt16>(RndStdIds::FLY_AT_PARA) ));
aReq.AppendItem(SfxPointItem( FN_PARAM_1, m_pSh->GetAnchorObjDiff()));
aReq.AppendItem(SvxSizeItem( FN_PARAM_2, m_pSh->GetObjSize()));
aReq.Done();
}
bAutoCap = true;
if(m_pWin->GetFrameColCount() > 1)
{
SfxItemSetFixed<RES_COL,RES_COL> aSet(m_pView->GetPool());
SwFormatCol aCol(aSet.Get(RES_COL));
aCol.Init(m_pWin->GetFrameColCount(), aCol.GetGutterWidth(), aCol.GetWishWidth());
aSet.Put(aCol);
// Template AutoUpdate
SwFrameFormat* pFormat = m_pSh->GetSelectedFrameFormat();
if(pFormat && pFormat->IsAutoUpdateOnDirectFormat())
m_pSh->AutoUpdateFrame(pFormat, aSet);
else
m_pSh->SetFlyFrameAttr( aSet );
}
}
if (m_pWin->GetSdrDrawMode() == SdrObjKind::NewFrame)
{
m_pSh->EndUndo();
}
}
bReturn = true;
EnterSelectMode(rMEvt);
}
else
{
SdrView *pSdrView = m_pSh->GetDrawView();
if (!pSdrView->HasMarkablePoints())
{
// NO BEZIER_EDITOR
if ((m_pSh->GetDrawView()->IsMarkObj() || m_pSh->GetDrawView()->IsMarkPoints())
&& rMEvt.IsLeft())
{
bReturn = m_pSh->EndMark();
m_pWin->SetDrawAction(false);
if (aPnt == m_aStartPos && m_pSh->IsObjSelectable(aPnt))
{
m_pSh->SelectObj(aPnt, ( rMEvt.IsShift() &&
m_pSh->IsSelFrameMode()) ? SW_ADD_SELECT : 0);
if (!m_pSh->IsObjSelected())
{
m_pView->LeaveDrawCreate(); // Switch to selection mode
m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
if (m_pSh->IsSelFrameMode())
m_pSh->LeaveSelFrameMode();
}
m_pView->NoRotate();
bCheckShell = true; // if necessary turn on BezierShell
}
else if (!m_pSh->IsObjSelected() && !m_pWin->IsDrawAction())
{
if (m_pSh->IsObjSelectable(aPnt))
m_pSh->SelectObj(aPnt, ( rMEvt.IsShift() &&
m_pSh->IsSelFrameMode() ) ? SW_ADD_SELECT : 0 );
else
{
m_pView->LeaveDrawCreate();
if (m_pSh->IsSelFrameMode())
m_pSh->LeaveSelFrameMode();
}
m_pView->NoRotate();
bReturn = true;
}
}
}
else
{
// BEZIER_EDITOR
if ( pSdrView->IsAction() )
{
if ( pSdrView->IsInsObjPoint() )
bReturn = pSdrView->EndInsObjPoint(SdrCreateCmd::ForceEnd);
else if (pSdrView->IsMarkPoints() )
bReturn = pSdrView->EndMarkPoints();
else
{
pSdrView->EndAction();
bReturn = true;
}
m_pWin->SetDrawAction(false);
if (aPnt == m_aStartPos)
{
if (!m_pSh->IsObjSelectable(aPnt))
m_pSh->SelectObj(Point(LONG_MAX, LONG_MAX));
else if (!bReturn)
{
if (!rMEvt.IsShift())
pSdrView->UnmarkAllPoints();
m_pSh->SelectObj(aPnt, (rMEvt.IsShift() &&
m_pSh->IsSelFrameMode()) ? SW_ADD_SELECT :0);
}
if (!m_pSh->IsObjSelected())
{
m_pView->LeaveDrawCreate(); // Switch to selection mode
m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
if (m_pSh->IsSelFrameMode())
m_pSh->LeaveSelFrameMode();
}
m_pView->NoRotate();
bCheckShell = true; // if necessary turn on BezierShell
}
}
SetDrawPointer();
if (!m_pSh->IsObjSelected() && !m_pWin->IsDrawAction())
{
m_pView->LeaveDrawCreate();
if (m_pSh->IsSelFrameMode())
m_pSh->LeaveSelFrameMode();
m_pView->NoRotate();
bReturn = true;
}
}
}
if (bCheckShell)
m_pView->AttrChangedNotify(nullptr); // if necessary turn on BezierShell
//!!!!!!!!!! Attention suicide !!!!!!!!!!! Everything should be renewed once
if ( bAutoCap )
m_pView->AutoCaption(FRAME_CAP); //Can currently only be FRAME, otherwise convert
// to enums
return bReturn;
}
void SwDrawBase::Activate(const sal_uInt16 nSlot)
{
SetSlotId(nSlot);
SdrView *pSdrView = m_pSh->GetDrawView();
pSdrView->SetCurrentObj(m_pWin->GetSdrDrawMode());
pSdrView->SetEditMode(false);
SetDrawPointer();
m_pSh->NoEdit();
}
void SwDrawBase::Deactivate()
{
SdrView *pSdrView = m_pSh->GetDrawView();
pSdrView->SetOrtho(false);
pSdrView->SetAngleSnapEnabled(false);
if (m_pWin->IsDrawAction() && m_pSh->IsDrawCreate())
m_pSh->BreakCreate();
m_pWin->SetDrawAction(false);
if (m_pWin->IsMouseCaptured())
m_pWin->ReleaseMouse();
g_bNoInterrupt = false;
if (m_pWin->GetApplyTemplate())
m_pWin->SetApplyTemplate(SwApplyTemplate());
m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
}
// Process keyboard events
// If a KeyEvent is processed then the return value is true, otherwise
// false.
void SwDrawBase::BreakCreate()
{
m_pSh->BreakCreate();
m_pWin->SetDrawAction(false);
m_pWin->ReleaseMouse();
Deactivate();
}
void SwDrawBase::SetDrawPointer()
{
SdrView *pSdrView = m_pSh->GetDrawView();
Point aPnt(m_pWin->OutputToScreenPixel(m_pWin->GetPointerPosPixel()));
aPnt = m_pWin->PixelToLogic(m_pWin->ScreenToOutputPixel(aPnt));
PointerStyle aPointTyp = pSdrView->GetPreferredPointer(aPnt, m_pSh->GetOut());
m_pWin->SetPointer(aPointTyp);
}
// If necessary switch into selection mode
void SwDrawBase::EnterSelectMode(const MouseEvent& rMEvt)
{
m_pWin->SetDrawAction(false);
if (m_pSh->IsObjSelected() || m_pWin->IsDrawAction())
return;
Point aPnt(m_pWin->PixelToLogic(rMEvt.GetPosPixel()));
if (m_pSh->IsObjSelectable(aPnt))
{
m_pSh->SelectObj(aPnt);
if (rMEvt.GetModifier() == KEY_SHIFT || !m_pSh->IsObjSelected())
{
m_pView->LeaveDrawCreate(); // Switch to selection mode
m_pSh->GetView().GetViewFrame().GetBindings().Invalidate(SID_INSERT_DRAW);
}
}
else
{
m_pView->LeaveDrawCreate();
if (m_pSh->IsSelFrameMode())
m_pSh->LeaveSelFrameMode();
}
m_pView->NoRotate();
}
void SwDrawBase::CreateDefaultObject()
{
constexpr tools::Long constTwips_3cm = o3tl::toTwips(3, o3tl::Length::cm);
Point aStartPos = GetDefaultCenterPos();
Point aEndPos(aStartPos);
aStartPos.AdjustX(-constTwips_3cm);
aStartPos.AdjustY(-constTwips_3cm);
aEndPos.AdjustX(constTwips_3cm);
aEndPos.AdjustY(constTwips_3cm);
tools::Rectangle aRect(aStartPos, aEndPos);
m_pSh->CreateDefaultShape(m_pWin->GetSdrDrawMode(), aRect, m_nSlotId);
}
void SwDrawBase::CreateDefaultObjectAtPosWithSize(Point aPos, Size aSize)
{
aPos.AdjustX(-sal_Int32(aSize.getWidth() / 2));
aPos.AdjustY(-sal_Int32(aSize.getHeight() / 2));
SdrView* sdrView = m_pView->GetDrawView();
SdrPageView *pPV = sdrView->GetSdrPageView();
if(sdrView->IsSnapEnabled())
aPos = sdrView->GetSnapPos(aPos, pPV);
::tools::Rectangle aNewObjectRectangle(aPos, aSize);
m_pSh->CreateDefaultShape(m_pWin->GetSdrDrawMode(), aNewObjectRectangle, m_nSlotId);
}
Point SwDrawBase::GetDefaultCenterPos() const
{
Size aDocSz(m_pSh->GetDocSize());
SwRect aVisArea(m_pSh->VisArea());
if (comphelper::LibreOfficeKit::isActive())
{
aVisArea = SwRect(m_pSh->getLOKVisibleArea());
aVisArea.Intersection(SwRect(Point(), aDocSz));
}
Point aCenter = aVisArea.Center();
// To increase the chance that aCenter actually falls somewhere on a page (rather than on the
// background between pages), keep it centered horizontally for the "Single-page view"
// (GetViewLayoutColumns() == 1) and "Book view" (GetViewLayoutColumns() == 2) cases that
// display the pages centered on the background:
if (aVisArea.Width() > aDocSz.Width() && m_pSh->GetViewOptions()->GetViewLayoutColumns() == 0)
aCenter.setX(aDocSz.Width() / 2 + aVisArea.Left());
if (aVisArea.Height() > aDocSz.Height())
aCenter.setY(aDocSz.Height() / 2 + aVisArea.Top());
return aCenter;
}
// #i33136#
bool SwDrawBase::doConstructOrthogonal() const
{
return ( m_nSlotId == SID_DRAW_XPOLYGON || m_nSlotId == SID_DRAW_XPOLYGON_NOFILL || m_nSlotId == SID_DRAW_XLINE );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'Intersection' is required to be utilized.