/// helper class for correct notification due to the positioning of /// the anchored drawing object class SwPosNotify
{ private:
SwAnchoredDrawObject* mpAnchoredDrawObj;
SwRect maOldObjRect;
SwPageFrame* mpOldPageFrame;
// --> #i35640# - additional notify anchor text frame // Needed for negative positioned drawing objects // --> #i43255# - refine condition to avoid unneeded // invalidations: anchored object had to be on the page of its anchor // text frame. if ( mpAnchoredDrawObj->GetAnchorFrame()->IsTextFrame() &&
mpOldPageFrame == mpAnchoredDrawObj->GetAnchorFrame()->FindPageFrame() )
{
mpAnchoredDrawObj->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave );
}
// indicate a restart of the layout process
mpAnchoredDrawObj->SetRestartLayoutProcess( true );
} else
{ // lock position
mpAnchoredDrawObj->LockPosition();
if ( !mpAnchoredDrawObj->ConsiderForTextWrap() )
{ // indicate that object has to be considered for text wrap
mpAnchoredDrawObj->SetConsiderForTextWrap( true ); // invalidate 'background' in order to allow its 'background' // to wrap around it.
mpAnchoredDrawObj->NotifyBackground( mpAnchoredDrawObj->GetPageFrame(),
mpAnchoredDrawObj->GetObjRectWithSpaces(),
PrepareHint::FlyFrameArrive ); // invalidate position of anchor frame in order to force // a re-format of the anchor frame, which also causes a // re-format of the invalid previous frames of the anchor frame.
mpAnchoredDrawObj->AnchorFrame()->InvalidatePos();
}
} // tdf#101464 notify SwAccessibleMap about new drawing object position #if !ENABLE_WASM_STRIP_ACCESSIBILITY if (mpOldPageFrame && mpOldPageFrame->getRootFrame()->IsAnyShellAccessible())
{
mpOldPageFrame->getRootFrame()->GetCurrShell()->Imp()->MoveAccessible(
nullptr, mpAnchoredDrawObj->GetDrawObj(), maOldObjRect);
} #endif
}
// #i32795# /// helper class for oscillation control on object positioning class SwObjPosOscillationControl
{ private: const SwAnchoredDrawObject* mpAnchoredDrawObj;
void SwAnchoredDrawObject::MakeObjPos()
{ if ( IsPositioningInProgress() )
{ // nothing to do - positioning already in progress return;
}
if ( mbValidPos )
{ // nothing to do - position is valid return;
}
// --> #i28749# - anchored drawing object has to be attached // to anchor frame if ( mbNotYetAttachedToAnchorFrame )
{
OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos() - drawing object not yet attached to anchor frame -> no positioning" ); return;
}
SwDrawContact* pDrawContact = static_cast<SwDrawContact*>(::GetUserCall( GetDrawObj() )); if (!pDrawContact) return;
// --> #i28749# - if anchored drawing object hasn't been yet // positioned, convert its positioning attributes, if its positioning // attributes are given in horizontal left-to-right layout. // --> #i36010# - Note: horizontal left-to-right layout is made // the default layout direction for <SwDrawFrameFormat> instances. Thus, it has // to be adjusted manually, if no adjustment of the positioning attributes // have to be performed here. // --> #i35635# - additionally move drawing object to the visible layer. if ( mbNotYetPositioned )
{ // --> #i35635#
pDrawContact->MoveObjToVisibleLayer( DrawObj() ); // --> perform conversion of positioning // attributes only for 'master' drawing objects // #i44334#, #i44681# - check, if positioning // attributes already have been set. if ( dynamic_cast< const SwDrawVirtObj* >(GetDrawObj()) == nullptr &&
!static_cast<SwDrawFrameFormat*>(GetFrameFormat())->IsPosAttrSet() )
{
SetPositioningAttr();
} // --> // - reset internal flag after all needed actions are performed to // avoid callbacks from drawing layer
mbNotYetPositioned = false;
}
// indicate that positioning is in progress
{
SwObjPositioningInProgress aObjPosInProgress( *this );
// determine relative position of drawing object and set it switch ( pDrawContact->GetAnchorId() )
{ case RndStdIds::FLY_AS_CHAR:
{ // indicate that position will be valid after positioning is performed
mbValidPos = true; // nothing to do, because as-character anchored objects are positioned // during the format of its anchor frame - see <SwFlyCntPortion::SetBase(..)>
} break; case RndStdIds::FLY_AT_PARA: case RndStdIds::FLY_AT_CHAR:
{ // --> #i32795# - move intrinsic positioning to // helper method <MakeObjPosAnchoredAtPara()>
MakeObjPosAnchoredAtPara();
} break; case RndStdIds::FLY_AT_PAGE: case RndStdIds::FLY_AT_FLY:
{ // --> #i32795# - move intrinsic positioning to // helper method <MakeObjPosAnchoredAtLayout()>
MakeObjPosAnchoredAtLayout();
} break; default:
{
assert(!"<SwAnchoredDrawObject::MakeObjPos()> - unknown anchor type.");
}
}
// keep, current object rectangle // --> #i34748# - use new method <SetLastObjRect(..)>
SetLastObjRect( GetObjRect().SVRect() );
// Assure for 'master' drawing object, that it's registered at the correct page. // Perform check not for as-character anchored drawing objects and only if // the anchor frame is valid. if ( dynamic_cast< const SwDrawVirtObj* >(GetDrawObj()) == nullptr &&
!pDrawContact->ObjAnchoredAsChar() &&
GetAnchorFrame()->isFrameAreaDefinitionValid() )
{
pDrawContact->ChkPage();
}
}
// --> #i62875# if ( !(mbCaptureAfterLayoutDirChange &&
GetPageFrame()) ) return;
/** method for the intrinsic positioning of an at-paragraph|at-character anchoreddrawingobject
#i32795#-helpermethodformethod<MakeObjPos>
*/ void SwAnchoredDrawObject::MakeObjPosAnchoredAtPara()
{ // --> #i32795# - adopt positioning algorithm from Writer // fly frames, which are anchored at paragraph|at character
// Determine, if anchor frame can/has to be formatted. // If yes, after each object positioning the anchor frame is formatted. // If after the anchor frame format the object position isn't valid, the // object is positioned again. // --> #i43255# - refine condition: anchor frame format not // allowed, if another anchored object, has to be consider its wrap influence // --> #i50356# - format anchor frame containing the anchor // position. E.g., for at-character anchored object this can be the follow // frame of the anchor frame, which contains the anchor character. bool bJoinLocked
= static_cast<const SwTextFrame*>(GetAnchorFrameContainingAnchPos())->IsAnyJoinLocked(); constbool bFormatAnchor = !bJoinLocked && !ConsiderObjWrapInfluenceOnObjPos()
&& !ConsiderObjWrapInfluenceOfOtherObjs();
// Format of anchor is needed for (vertical) fly offsets, otherwise the // lack of fly portions will result in an incorrect 0 offset. bool bAddVerticalFlyOffsets = GetFrameFormat()->getIDocumentSettingAccess().get(
DocumentSettingId::ADD_VERTICAL_FLY_OFFSETS); bool bFormatAnchorOnce = !bJoinLocked && bAddVerticalFlyOffsets;
if (bFormatAnchor || bFormatAnchorOnce)
{ // --> #i50356#
GetAnchorFrameContainingAnchPos()->Calc(GetAnchorFrameContainingAnchPos()->getRootFrame()->GetCurrShell()->GetOut());
}
bool bOscillationDetected = false;
SwObjPosOscillationControl aObjPosOscCtrl( *this ); // --> #i3317# - boolean, to apply temporarily the // 'straightforward positioning process' for the frame due to its // overlapping with a previous column. bool bConsiderWrapInfluenceDueToOverlapPrevCol( false ); do { // indicate that position will be valid after positioning is performed
mbValidPos = true;
// --> #i35640# - correct scope for <SwPosNotify> instance
{ // create instance of <SwPosNotify> for correct notification
SwPosNotify aPosNotify( this );
// determine and set position
objectpositioning::SwToContentAnchoredObjectPosition
aObjPositioning( *DrawObj() );
aObjPositioning.CalcPosition();
// get further needed results of the positioning algorithm
SetVertPosOrientFrame ( aObjPositioning.GetVertPosOrientFrame() );
SetDrawObjAnchor();
// check for object position oscillation, if position has changed. if ( GetObjRect().Pos() != aPosNotify.LastObjPos() )
{
bOscillationDetected = aObjPosOscCtrl.OscillationDetected();
}
} // format anchor frame, if requested. // Note: the format of the anchor frame can cause the object position // to be invalid. if ( bFormatAnchor )
{ // --> #i50356#
GetAnchorFrameContainingAnchPos()->Calc(GetAnchorFrameContainingAnchPos()->getRootFrame()->GetCurrShell()->GetOut());
}
// --> #i3317# - consider a detected oscillation and overlapping // with previous column. // temporarily consider the anchored objects wrapping style influence if ( bOscillationDetected || bConsiderWrapInfluenceDueToOverlapPrevCol )
{
SetTmpConsiderWrapInfluence( true );
SetRestartLayoutProcess( true );
}
}
/** method for the intrinsic positioning of an at-page|at-frame anchored drawingobject
#i32795#-helpermethodformethod<MakeObjPos>
*/ void SwAnchoredDrawObject::MakeObjPosAnchoredAtLayout()
{ // indicate that position will be valid after positioning is performed
mbValidPos = true;
// create instance of <SwPosNotify> for correct notification
SwPosNotify aPosNotify( this );
// determine position
objectpositioning::SwToLayoutAnchoredObjectPosition
aObjPositioning( *DrawObj() );
aObjPositioning.CalcPosition();
// set position
// --> #i31698# // --> #i34995# - setting anchor position needed for filters, // especially for the xml-filter to the OpenOffice.org file format
{ const Point aNewAnchorPos =
GetAnchorFrame()->GetFrameAnchorPos( ::HasWrap( GetDrawObj() ) );
DrawObj()->SetAnchorPos( aNewAnchorPos ); // --> #i70122# - missing invalidation
InvalidateObjRectWithSpaces();
}
SetCurrRelPos( aObjPositioning.GetRelPos() ); const SwFrame* pAnchorFrame = GetAnchorFrame();
SwRectFnSet aRectFnSet(pAnchorFrame); const Point aAnchPos( aRectFnSet.GetPos(pAnchorFrame->getFrameArea()) );
SetObjLeft( aAnchPos.X() + GetCurrRelPos().X() );
SetObjTop( aAnchPos.Y() + GetCurrRelPos().Y() );
}
void SwAnchoredDrawObject::SetDrawObjAnchor()
{ // new anchor position // --> #i31698# -
Point aNewAnchorPos =
GetAnchorFrame()->GetFrameAnchorPos( ::HasWrap( GetDrawObj() ) );
Point aCurrAnchorPos = GetDrawObj()->GetAnchorPos(); if ( aNewAnchorPos != aCurrAnchorPos )
{ // determine movement to be applied after setting the new anchor position
Size aMove( aCurrAnchorPos.getX() - aNewAnchorPos.getX(),
aCurrAnchorPos.getY() - aNewAnchorPos.getY() ); // set new anchor position
DrawObj()->SetAnchorPos( aNewAnchorPos ); // correct object position, caused by setting new anchor position
DrawObj()->Move( aMove ); // Sync textbox if it wasn't done at move
SwFrameFormat* pObjFormat = GetFrameFormat(); if ( SwTextBoxHelper::isTextBox(pObjFormat, RES_DRAWFRMFMT) &&
pObjFormat->GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell() &&
pObjFormat->GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell()->IsInConstructor())
{
SwTextBoxHelper::changeAnchor(pObjFormat, pObjFormat->FindRealSdrObject());
} // --> #i70122# - missing invalidation
InvalidateObjRectWithSpaces();
}
}
// --> #i44339# - check, if anchor frame exists. if ( !GetAnchorFrame() ) return;
// --> #118547# - notify anchor frame of as-character // anchored object, because its positioned by the format of its anchor frame. // --> #i44559# - assure, that text hint is already // existing in the text frame const SwFrameFormat* pObjFormat = GetFrameFormat(); if ( GetAnchorFrame()->DynCastTextFrame() != nullptr &&
(pObjFormat->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR) )
{
SwTextFrame* pAnchorTextFrame( static_cast<SwTextFrame*>(AnchorFrame()) ); if (pAnchorTextFrame->CalcFlyPos(pObjFormat) != TextFrameIndex(COMPLETE_STRING))
{
AnchorFrame()->Prepare(PrepareHint::FlyFrameAttributesChanged, pObjFormat);
}
}
SwRect SwAnchoredDrawObject::GetObjRect() const
{ // use geometry of drawing object //return GetDrawObj()->GetCurrentBoundRect(); return SwRect(GetDrawObj()->GetSnapRect());
}
namespace
{ // Imagine an open book, inside margin is the one that is at the inner side of the pages, at the center of the book, // outside margin is at the two opposite edges of the book. // outside --text-- inside | inside --text-- outside // With mirrored margins, when relating the size of an object from the inside margin for example, on the // first page we calculate the new size of the object using the size of the right margin, // on second page the left margin, third page right margin, etc.
tools::Long getInsideOutsideRelativeWidth(bool isOutside, const SwPageFrame* const pPageFrame)
{ // Alternating between the only two possible cases: inside and outside. // Inside = false, Outside = true. auto nPageNum = pPageFrame->GetPhyPageNum(); if (nPageNum % 2 == (isOutside ? 0 : 1)) return pPageFrame->GetRightMargin(); else return pPageFrame->GetLeftMargin();
}
}
tools::Long nTargetWidth = aCurrObjRect.GetWidth( ); if ( GetDrawObj( )->GetRelativeWidth( ) )
{
tools::Long nWidth = 0; if (GetDrawObj()->GetRelativeWidthRelation() == text::RelOrientation::FRAME) // Exclude margins.
nWidth = GetPageFrame()->getFramePrintArea().SVRect().GetWidth(); // Here we handle the relative size of the width of some shape. // The size of the shape's width is going to be relative to the size of the left margin. // E.g.: (left margin = 8 && relative size = 150%) -> width of some shape = 12. elseif (GetDrawObj()->GetRelativeWidthRelation() == text::RelOrientation::PAGE_LEFT)
{ if (GetPageFrame()->GetPageDesc()->GetUseOn() == UseOnPage::Mirror) // We want to get the width of whatever is going through here using the size of the // outside margin.
nWidth = getInsideOutsideRelativeWidth(true, GetPageFrame()); else
nWidth = GetPageFrame()->GetLeftMargin();
} // Same as the left margin above. elseif (GetDrawObj()->GetRelativeWidthRelation() == text::RelOrientation::PAGE_RIGHT) if (GetPageFrame()->GetPageDesc()->GetUseOn() == UseOnPage::Mirror) // We want to get the width of whatever is going through here using the size of the // inside margin.
nWidth = getInsideOutsideRelativeWidth(false, GetPageFrame()); else
nWidth = GetPageFrame()->GetRightMargin(); else
nWidth = GetPageFrame( )->GetBoundRect( GetPageFrame()->getRootFrame()->GetCurrShell()->GetOut() ).SVRect().GetWidth();
nTargetWidth = nWidth * (*GetDrawObj( )->GetRelativeWidth());
}
bool bCheck = GetDrawObj()->GetRelativeHeight(); if (bCheck)
{ auto pObjCustomShape = dynamic_cast<const SdrObjCustomShape*>(GetDrawObj());
bCheck = !pObjCustomShape || !pObjCustomShape->IsAutoGrowHeight();
}
if (SwFrameFormat* pFrameFormat = FindFrameFormat(pObject))
{ if (SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT))
{ // Shape has relative size and also a textbox, update its text area as well.
uno::Reference<drawing::XShape> xShape(pObject->getUnoShape(), uno::UNO_QUERY);
SwTextBoxHelper::syncProperty(pFrameFormat, RES_FRM_SIZE, MID_FRMSIZE_SIZE,
uno::Any(xShape->getSize()));
}
}
// --> #i36010# - set layout direction of the position
pObjFormat->SetPositionLayoutDir(
text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
} // --> #i65798# - also for as-character anchored objects // --> #i45952# - indicate that position // attributes are set now. static_cast<SwDrawFrameFormat*>(pObjFormat)->PosAttrSet();
}
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.