/* -*- 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 .
*/
// #i73602# Use default from the configuration
SetBufferedOverlayAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::OverlayBuffer_Writer::get());
// #i74769#, #i75172# Use default from the configuration
SetBufferedOutputAllowed(!comphelper::IsFuzzing() && officecfg::Office::Common::Drawinglayer::OverlayBuffer_DrawImpress::get());
}
static SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol, const SdrMarkList &rMrkList)
{ if(!nTol)
{ // the old method forced back to outer bounds test when nTol == 0, so // do not try to correct when nTol is not set (used from HelpContent)
} else
{ // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since // the SdrObject-specific CheckHit implementations are now replaced with primitives and // 'tricks' like in the old implementation (e.g. using a view from a model-data class to // detect if object is selected) are no longer valid. // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old // implementation reduced this excluding the inner bound when the object was not selected.
SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(pRetval);
if(pSwVirtFlyDrawObj)
{
SwFrame* pLower = pSwVirtFlyDrawObj->GetFlyFrame()->Lower(); if(pLower && pLower->IsNoTextFrame())
{ // the old method used IsNoTextFrame (should be for SW's own OLE and // graphic's) to accept hit only based on outer bounds; nothing to do
} else
{ // check if the object is selected in this view const size_t nMarkCount(rMrkList.GetMarkCount()); bool bSelected(false);
for(size_t a = 0; !bSelected && a < nMarkCount; ++a)
{ if(pSwVirtFlyDrawObj == rMrkList.GetMark(a)->GetMarkedSdrObj())
{
bSelected = true;
}
}
if(!bSelected)
{ // when not selected, the object is not hit when hit position is inside // inner range. Get and shrink inner range
basegfx::B2DRange aInnerBound(pSwVirtFlyDrawObj->getInnerBound());
aInnerBound.grow(-1.0 * nTol);
if(aInnerBound.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y())))
{ // exclude this hit
pRetval = nullptr;
}
}
}
}
}
if ( RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId() )
{ // #i28701# - use last character rectangle saved at object // in order to avoid a format of the anchor frame
SwAnchoredObject* pAnchoredObj = pContact->GetAnchoredObj( pObj );
// Invalidate/recalc LastCharRect which can contain invalid frame offset because // of later frame changes
pAnchoredObj->CheckCharRectAndTopOfLine(false);
SdrObject* SwDrawView::GetMaxToBtmObj(SdrObject* pObj) const
{ if ( GetUserCall(pObj) )
{ const SwFrame *pAnch = ::lcl_FindAnchor( pObj, false ); if ( pAnch )
{ //The Fly of the anchor must not be "flying under". const SwFlyFrame *pFly = pAnch->FindFlyFrame(); if ( pFly )
{
SdrObject *pRet = const_cast<SdrObject*>(static_cast<SdrObject const *>(pFly->GetVirtDrawObj())); return pRet != pObj ? pRet : nullptr;
}
}
} return nullptr;
}
/// determine maximal order number for a 'child' object of given 'parent' object
sal_uInt32 SwDrawView::GetMaxChildOrdNum( const SwFlyFrame& _rParentObj, const SdrObject* _pExclChildObj )
{
sal_uInt32 nMaxChildOrdNum = _rParentObj.GetDrawObj()->GetOrdNum();
/// method to move 'repeated' objects of the given moved object to the according level void SwDrawView::MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj, const std::vector<SdrObject*>& _rMovedChildObjs ) const
{ // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
std::vector<SwAnchoredObject*> aAnchoredObjs;
{ const SwContact* pContact = ::GetUserCall( _rMovedAnchoredObj.GetDrawObj() );
assert(pContact && "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash."); if (pContact)
pContact->GetAnchoredObjs( aAnchoredObjs );
}
// check, if 'repeated' objects exists. if ( aAnchoredObjs.size() <= 1 ) return;
SdrPage* pDrawPage = GetModel().GetPage( 0 );
// move 'repeated' ones to the same order number as the already moved one. const size_t nNewPos = _rMovedAnchoredObj.GetDrawObj()->GetOrdNum(); while ( !aAnchoredObjs.empty() )
{
SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back(); if ( pAnchoredObj != &_rMovedAnchoredObj )
{
pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
nNewPos );
pDrawPage->RecalcObjOrdNums(); // adjustments for accessibility API #if !ENABLE_WASM_STRIP_ACCESSIBILITY if ( auto pTmpFlyFrame = pAnchoredObj->DynCastFlyFrame() )
{
m_rImp.DisposeAccessibleFrame( pTmpFlyFrame );
m_rImp.AddAccessibleFrame( pTmpFlyFrame );
} else
{
m_rImp.DisposeAccessibleObj(pAnchoredObj->GetDrawObj(), true);
m_rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
} #endif
}
aAnchoredObjs.pop_back();
}
// move 'repeated' ones of 'child' objects for ( SdrObject* pChildObj : _rMovedChildObjs )
{
{ const SwContact* pContact = ::GetUserCall( pChildObj );
assert(pContact && "SwDrawView::MoveRepeatedObjs(..) - missing contact object -> crash."); if (pContact)
pContact->GetAnchoredObjs( aAnchoredObjs );
} // move 'repeated' ones to the same order number as the already moved one. const size_t nTmpNewPos = pChildObj->GetOrdNum(); while ( !aAnchoredObjs.empty() )
{
SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back(); if ( pAnchoredObj->GetDrawObj() != pChildObj )
{
pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
nTmpNewPos );
pDrawPage->RecalcObjOrdNums(); // adjustments for accessibility API #if !ENABLE_WASM_STRIP_ACCESSIBILITY if ( auto pTmpFlyFrame = pAnchoredObj->DynCastFlyFrame() )
{
m_rImp.DisposeAccessibleFrame( pTmpFlyFrame );
m_rImp.AddAccessibleFrame( pTmpFlyFrame );
} else
{
m_rImp.DisposeAccessibleObj(pAnchoredObj->GetDrawObj(), true);
m_rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
} #endif
}
aAnchoredObjs.pop_back();
}
}
}
// --> adjustment and re-factoring of method void SwDrawView::ObjOrderChanged( SdrObject* pObj, size_t nOldPos,
size_t nNewPos )
{ // nothing to do for group members if ( pObj->getParentSdrObjectFromSdrObject() )
{ return;
}
// determine drawing page and assure that the order numbers are correct.
SdrPage* pDrawPage = GetModel().GetPage( 0 ); if ( pDrawPage->IsObjOrdNumsDirty() )
pDrawPage->RecalcObjOrdNums(); const size_t nObjCount = pDrawPage->GetObjCount();
SwContact* pContact = ::GetUserCall( pObj ); if (!pContact) return;
// assure for a 'child' object, that it doesn't exceed the limits of its 'parent' if ( pParentAnchoredObj )
{ if ( bMovedForward )
{ const size_t nMaxChildOrdNumWithoutMoved =
GetMaxChildOrdNum( *pParentAnchoredObj, pMovedAnchoredObj->GetDrawObj() ); if ( nNewPos > nMaxChildOrdNumWithoutMoved+1 )
{ // set position to the top of the 'child' object group
pDrawPage->SetObjectOrdNum( nNewPos, nMaxChildOrdNumWithoutMoved+1 );
nNewPos = nMaxChildOrdNumWithoutMoved+1;
}
} else
{ const size_t nParentOrdNum = pParentAnchoredObj->GetDrawObj()->GetOrdNum(); if ( nNewPos < nParentOrdNum )
{ // set position to the bottom of the 'child' object group
pDrawPage->SetObjectOrdNum( nNewPos, nParentOrdNum );
nNewPos = nParentOrdNum;
}
} if ( pDrawPage->IsObjOrdNumsDirty() )
pDrawPage->RecalcObjOrdNums();
}
// On move forward, assure that object is moved before its own children. // Only Writer fly frames can have children. if ( pMovedAnchoredObj->DynCastFlyFrame() &&
bMovedForward && nNewPos < nObjCount - 1 )
{
sal_uInt32 nMaxChildOrdNum =
GetMaxChildOrdNum( *static_cast<const SwFlyFrame*>(pMovedAnchoredObj) ); if ( nNewPos < nMaxChildOrdNum )
{ // determine position before the object before its top 'child' object const SdrObject* pTmpObj = pDrawPage->GetObj( nMaxChildOrdNum ); if (SwContact* pContact2 = ::GetUserCall( pTmpObj ))
{
size_t nTmpNewPos = pContact2->GetMaxOrdNum() + 1; if ( nTmpNewPos >= nObjCount )
{
--nTmpNewPos;
} // assure, that determined position isn't between 'repeated' objects
pTmpObj = pDrawPage->GetObj( nTmpNewPos );
pContact2 = ::GetUserCall( pTmpObj ); if (pContact2)
{
nTmpNewPos = pContact2->GetMaxOrdNum(); // apply new position
pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
nNewPos = nTmpNewPos;
pDrawPage->RecalcObjOrdNums();
}
}
}
}
// #i7672# void SwDrawView::ModelHasChanged()
{ // The ModelHasChanged() call in DrawingLayer also updates // an eventually active text edit view (OutlinerView). This also leads // to newly setting the background color for that edit view. Thus, // this method rescues the current background color if an OutlinerView // exists and re-establishes it then. To be more safe, the OutlinerView // will be fetched again (maybe textedit has ended).
OutlinerView* pView = GetTextEditOutlinerView();
Color aBackColor; bool bColorWasSaved(false);
//In addition to the existing flags of the objects themselves, //which are evaluated by the DrawingEngine, other circumstances //lead to a protection. //Objects that are anchored in frames need to be protected //if the content of the frame is protected. //OLE-Objects may themselves wish a resize protection (StarMath)
// #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
SwDoc* pDoc = Imp().GetShell().GetDoc(); constbool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
&& RndStdIds::FLY_AS_CHAR == pFly->GetFormat()->GetAnchor().GetAnchorId()
&& pDoc->GetDocumentSettingManager().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ); if (bProtectMathPos)
m_bMoveProtect = true;
}
} elseif(pGrfNd)
{ // RotGrfFlyFrame: GraphicNode allows rotation(s). The loop ew are in stops // as soon as bMoveProtect is set, but since rotation is valid only with // a single object selected this makes no difference
bRotate = true;
}
}
}
} else
{
SwDrawContact *pC = static_cast<SwDrawContact*>(GetUserCall(pObj)); if ( pC )
pFrame = pC->GetAnchorFrame( pObj );
} if ( pFrame )
bProtect = pFrame->IsProtected(); //Frames, areas etc.
{
SwFrameFormat* pFrameFormat( ::FindFrameFormat( const_cast<SdrObject*>(pObj) ) ); if ( !pFrameFormat )
{
OSL_FAIL( " - missing frame format" );
bProtect = true;
} elseif ((RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId()) &&
rMrkList.GetMarkCount() > 1 )
{
bProtect = true;
}
}
}
m_bMoveProtect |= bProtect;
m_bResizeProtect |= bProtect || bSzProtect;
// RotGrfFlyFrame: allow rotation when SwGrfNode is selected and not size protected
m_bRotateFreeAllowed |= bRotate && !bProtect;
m_bRotate90Allowed |= m_bRotateFreeAllowed;
}
/// replace marked <SwDrawVirtObj>-objects by its reference object for delete marked objects. void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView )
{
SdrPageView* pDrawPageView = _rMarkView.GetSdrPageView(); const SdrMarkList& rMarkList = _rMarkView.GetMarkedObjectList();
if( !rMarkList.GetMarkCount() ) return;
// collect marked objects in a local data structure
std::vector<SdrObject*> aMarkedObjs; for( size_t i = 0; i < rMarkList.GetMarkCount(); ++i )
{
SdrObject* pMarkedObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
aMarkedObjs.push_back( pMarkedObj );
} // unmark all objects
_rMarkView.UnmarkAllObj(); // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its // reference object. while ( !aMarkedObjs.empty() )
{
SdrObject* pMarkObj = aMarkedObjs.back(); if ( auto pVirtObj = dynamic_cast<SwDrawVirtObj *>( pMarkObj ) )
{
SdrObject* pRefObj = &(pVirtObj->ReferencedObj()); if ( !_rMarkView.IsObjMarked( pRefObj ) )
{
_rMarkView.MarkObj( pRefObj, pDrawPageView );
}
} else
{
_rMarkView.MarkObj( pMarkObj, pDrawPageView );
}
aMarkedObjs.pop_back();
} // sort marked list in order to assure consistent state in drawing layer
_rMarkView.GetMarkedObjectList().ForceSort();
}
// Only delete these now: earlier deletion would clear the mark list as well. // Delete in reverse order, assuming that the container is sorted by anchor positions. for (int i = aTextBoxesToDelete.size() - 1; i >= 0; --i)
{
SwFrameFormat*& rpTextBox = aTextBoxesToDelete[i];
pDoc->getIDocumentLayoutAccess().DelLayoutFormat(rpTextBox);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.