1
0
Fork 0
libreoffice/sc/source/ui/view/drawvie3.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

261 lines
8.6 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 <sal/config.h>
#include <cstdlib>
#include <svx/svdograf.hxx>
#include <svx/svdoole2.hxx>
#include <svx/ImageMapInfo.hxx>
#include <sfx2/viewfrm.hxx>
#include <comphelper/lok.hxx>
#include <officecfg/Office/Common.hxx>
#include <strings.hrc>
#include <scresid.hxx>
#include <drawview.hxx>
#include <drwlayer.hxx>
#include "imapwrap.hxx"
#include <viewdata.hxx>
#include <document.hxx>
#include <userdat.hxx>
#include <tabvwsh.hxx>
#include <docsh.hxx>
ScDrawView::ScDrawView(
OutputDevice* pOut,
ScViewData* pData )
: FmFormView(*pData->GetDocument().GetDrawLayer(), pOut),
pViewData( pData ),
pDev( pOut ),
rDoc( pData->GetDocument() ),
nTab( pData->GetTabNo() ),
pDropMarkObj( nullptr ),
bInConstruct( true )
{
SetNegativeX(comphelper::LibreOfficeKit::isActive() && rDoc.IsLayoutRTL(nTab));
// #i73602# Use default from the configuration
SetBufferedOverlayAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::OverlayBuffer_Calc::get());
// #i74769#, #i75172# Use default from the configuration
SetBufferedOutputAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::PaintBuffer_Calc::get());
Construct();
}
// set anchor
void ScDrawView::SetPageAnchored()
{
const SdrMarkList& rMarkList = GetMarkedObjectList();
if( rMarkList.GetMarkCount() == 0 )
return;
const size_t nCount = rMarkList.GetMarkCount();
BegUndo(ScResId(SCSTR_UNDO_PAGE_ANCHOR));
for( size_t i=0; i<nCount; ++i )
{
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
AddUndo (std::make_unique<ScUndoAnchorData>( pObj, &rDoc, nTab ));
ScDrawLayer::SetPageAnchored( *pObj );
}
EndUndo();
if ( pViewData )
pViewData->GetDocShell()->SetDrawModified();
// Remove the anchor object.
maHdlList.RemoveAllByKind(SdrHdlKind::Anchor);
maHdlList.RemoveAllByKind(SdrHdlKind::Anchor_TR);
}
void ScDrawView::SetCellAnchored(bool bResizeWithCell)
{
const SdrMarkList& rMarkList = GetMarkedObjectList();
if( rMarkList.GetMarkCount() == 0 )
return;
const size_t nCount = rMarkList.GetMarkCount();
BegUndo(ScResId(SCSTR_UNDO_CELL_ANCHOR));
for( size_t i=0; i<nCount; ++i )
{
SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
AddUndo (std::make_unique<ScUndoAnchorData>( pObj, &rDoc, nTab ));
ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rDoc, nTab, bResizeWithCell);
}
EndUndo();
if ( pViewData )
{
pViewData->GetDocShell()->SetDrawModified();
// Set the anchor object.
AddCustomHdl();
}
}
ScAnchorType ScDrawView::GetAnchorType() const
{
bool bPage = false;
bool bCell = false;
bool bCellResize = false;
const SdrMarkList& rMarkList = GetMarkedObjectList();
if( rMarkList.GetMarkCount() != 0 )
{
const size_t nCount = rMarkList.GetMarkCount();
for( size_t i=0; i<nCount; ++i )
{
const SdrObject* pObj = rMarkList.GetMark(i)->GetMarkedSdrObj();
const ScAnchorType aAnchorType = ScDrawLayer::GetAnchorType( *pObj );
if( aAnchorType == SCA_CELL )
bCell =true;
else if (aAnchorType == SCA_CELL_RESIZE)
bCellResize = true;
else
bPage = true;
}
}
if( bPage && !bCell && !bCellResize )
return SCA_PAGE;
if( !bPage && bCell && !bCellResize )
return SCA_CELL;
if( !bPage && !bCell && bCellResize )
return SCA_CELL_RESIZE;
return SCA_DONTKNOW;
}
namespace {
bool lcl_AreRectanglesApproxEqual(const tools::Rectangle& rRectA, const tools::Rectangle& rRectB)
{
// Twips <-> Hmm conversions introduce +-1 differences although the rectangles should actually
// be equal. Therefore test with == is not appropriate in some cases.
if (std::abs(rRectA.Left() - rRectB.Left()) > 1)
return false;
if (std::abs(rRectA.Top() - rRectB.Top()) > 1)
return false;
if (std::abs(rRectA.Right() - rRectB.Right()) > 1)
return false;
if (std::abs(rRectA.Bottom() - rRectB.Bottom()) > 1)
return false;
return true;
}
/**
* Updated the anchors of any non-note object that is cell anchored which
* has been moved since the last anchors for its position was calculated.
*/
void adjustAnchoredPosition(const SdrHint& rHint, const ScDocument& rDoc, SCTAB nTab)
{
if (rHint.GetKind() != SdrHintKind::ObjectChange && rHint.GetKind() != SdrHintKind::ObjectInserted)
return;
SdrObject* pObj = const_cast<SdrObject*>(rHint.GetObject());
if (!pObj)
return;
ScDrawObjData *pAnchor = ScDrawLayer::GetObjData(pObj);
if (!pAnchor)
return;
if (pAnchor->meType == ScDrawObjData::CellNote)
return;
// SetCellAnchoredFromPosition has to be called only if shape geometry has been changed, and not
// if only shape visibility has been changed. It is not enough to test shape rect, because e.g. a
// 180deg rotation changes only the logic rect (tdf#139583).
ScDrawObjData& rNoRotatedAnchor = *ScDrawLayer::GetNonRotatedObjData(pObj, true /*bCreate*/);
if (lcl_AreRectanglesApproxEqual(pAnchor->getShapeRect(), pObj->GetSnapRect())
&& lcl_AreRectanglesApproxEqual(rNoRotatedAnchor.getShapeRect(), pObj->GetLogicRect()))
return;
if (pAnchor->maStart.Tab() != nTab)
// The object is not anchored on the current sheet. Skip it.
// TODO: In the future, we may want to adjust objects that are
// anchored on all selected sheets.
return;
ScDrawLayer::SetCellAnchoredFromPosition(*pObj, rDoc, pAnchor->maStart.Tab(), pAnchor->mbResizeWithCell);
}
}
void ScDrawView::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
{
const SdrHint* pSdrHint = static_cast<const SdrHint*>( &rHint );
adjustAnchoredPosition(*pSdrHint, rDoc, nTab);
FmFormView::Notify( rBC,rHint );
}
else if (rHint.GetId() == SfxHintId::ScTabDeleted) // Sheet has been deleted
{
auto pDeletedHint = static_cast<const ScTabDeletedHint*>(&rHint);
SCTAB nDelTab = pDeletedHint->GetTab();
if (ValidTab(nDelTab))
{
// used to be: HidePagePgNum(nDelTab) - hide only if the deleted sheet is shown here
if ( nDelTab == nTab )
HideSdrPage();
}
}
else if (rHint.GetId() == SfxHintId::ScTabSizeChanged) // Size has been changed
{
auto pChangedHint = static_cast<const ScTabSizeChangedHint*>(&rHint);
if ( nTab == pChangedHint->GetTab() )
UpdateWorkArea();
}
else
FmFormView::Notify( rBC,rHint );
}
void ScDrawView::UpdateIMap( SdrObject* pObj )
{
if ( !(pViewData &&
pViewData->GetViewShell()->GetViewFrame().HasChildWindow( ScIMapChildWindowId() ) &&
pObj && ( dynamic_cast<const SdrGrafObj*>( pObj) != nullptr || dynamic_cast<const SdrOle2Obj*>( pObj) != nullptr )) )
return;
Graphic aGraphic;
TargetList aTargetList;
SvxIMapInfo* pIMapInfo = SvxIMapInfo::GetIMapInfo( pObj );
const ImageMap* pImageMap = nullptr;
if ( pIMapInfo )
pImageMap = &pIMapInfo->GetImageMap();
// handle target list
SfxViewFrame::GetTargetList( aTargetList );
// handle graphics from object
if ( auto pGrafObj = dynamic_cast<SdrGrafObj*>( pObj) )
aGraphic = pGrafObj->GetGraphic();
else
{
const Graphic* pGraphic = static_cast<const SdrOle2Obj*>(pObj)->GetGraphic();
if ( pGraphic )
aGraphic = *pGraphic;
}
ScIMapDlgSet( aGraphic, pImageMap, &aTargetList, pObj ); // from imapwrap
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */