Files
libreoffice/sw/source/core/layout/anchoreddrawobject.cxx

854 lines
28 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
re-base on ALv2 code. Includes: Patches contributed by Oliver-Rainer Wittmann sw34bf06: #i117783# - Writer's implementation of XPagePrintable - apply print settings to new printing routines http://svn.apache.org/viewvc?view=revision&revision=1172115 sw34bf06: #o12311627# use <rtl_random> methods to create unique ids for list styles and list ids http://svn.apache.org/viewvc?view=revision&revision=1172112 sw34bf06 #i114725#,#i115828# - method <SwDoc::ClearDoc()> - clear list structures completely http://svn.apache.org/viewvc?view=revision&revision=1172122 i#118572 - remove ui string and help content regarding usage of Java Mail in Writer's Mail Merge as Java Mail is not used. http://svn.apache.org/viewvc?view=revision&revision=1197035 Patches contributed by Mathias Bauer cws mba34issues01: #i117718#: provide filter name in case storage of medium does not allow to detect one http://svn.apache.org/viewvc?view=revision&revision=1172350 cws mba34issues01: #i117721#: directly provide parameters retrieved from SfxMedium http://svn.apache.org/viewvc?view=revision&revision=1172353 gnumake4 work variously http://svn.apache.org/viewvc?view=revision&revision=1394707 http://svn.apache.org/viewvc?view=revision&revision=1394326 http://svn.apache.org/viewvc?view=revision&revision=1396797 http://svn.apache.org/viewvc?view=revision&revision=1397315 cws mba34issues01: #i117723#: convert assertion into trace http://svn.apache.org/viewvc?view=revision&revision=1172355 cws mba34issues01: #i117699#: keep layout alive until swdoc dies http://svn.apache.org/viewvc?view=revision&revision=1172362 cws mba34issues01: #i117943#: missing color attributes in RTF clipboard http://svn.apache.org/viewvc?view=revision&revision=1172363 Patch contributed by Henning Brinkmann imported patch i#103878 http://svn.apache.org/viewvc?view=revision&revision=1172109 Patches contributed by Michael Stahl sw34bf06: #i117955#: WW8 export: disable storing of section breaks in endnotes http://svn.apache.org/viewvc?view=revision&revision=1172119 Patch contributed by imacat Fixed the Asian language work count. http://svn.apache.org/viewvc?view=revision&revision=1241345 Patch contributed by Pedro Giffuni i#20878 - Add comment with BZ issue for reference. http://svn.apache.org/viewvc?view=revision&revision=1244517 Patch contributed by Andre Fischer Do not add targets for junit tests when junit is disabled. http://svn.apache.org/viewvc?view=revision&revision=1241508 add writerperfect dependency.
2011-03-31 10:05:04 +02:00
/*
* 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 <dcontact.hxx>
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <tocntntanchoredobjectposition.hxx>
#include <tolayoutanchoredobjectposition.hxx>
#include <frmtool.hxx>
#include <fmtornt.hxx>
2011-02-05 18:00:33 +01:00
// --> #i32795#
#include <txtfrm.hxx>
2011-02-05 18:00:33 +01:00
// --> #i32795#
// template class <std::vector>
#include <vector>
using namespace ::com::sun::star;
// ============================================================================
// helper class for correct notification due to the positioning of
// the anchored drawing object
// ============================================================================
class SwPosNotify
{
private:
SwAnchoredDrawObject* mpAnchoredDrawObj;
SwRect maOldObjRect;
SwPageFrm* mpOldPageFrm;
public:
SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj );
~SwPosNotify();
// #i32795#
Point LastObjPos() const;
};
SwPosNotify::SwPosNotify( SwAnchoredDrawObject* _pAnchoredDrawObj ) :
mpAnchoredDrawObj( _pAnchoredDrawObj )
{
maOldObjRect = mpAnchoredDrawObj->GetObjRect();
2011-02-05 18:00:33 +01:00
// --> #i35640# - determine correct page frame
mpOldPageFrm = mpAnchoredDrawObj->GetPageFrm();
}
SwPosNotify::~SwPosNotify()
{
if ( maOldObjRect != mpAnchoredDrawObj->GetObjRect() )
{
if( maOldObjRect.HasArea() && mpOldPageFrm )
{
mpAnchoredDrawObj->NotifyBackground( mpOldPageFrm, maOldObjRect,
PREP_FLY_LEAVE );
}
SwRect aNewObjRect( mpAnchoredDrawObj->GetObjRect() );
if( aNewObjRect.HasArea() )
{
2011-02-05 18:00:33 +01:00
// --> #i35640# - determine correct page frame
SwPageFrm* pNewPageFrm = mpAnchoredDrawObj->GetPageFrm();
if( pNewPageFrm )
mpAnchoredDrawObj->NotifyBackground( pNewPageFrm, aNewObjRect,
PREP_FLY_ARRIVE );
}
::ClrContourCache( mpAnchoredDrawObj->GetDrawObj() );
2011-02-05 18:00:33 +01:00
// --> #i35640# - additional notify anchor text frame
// Needed for negative positioned drawing objects
2011-02-05 18:00:33 +01:00
// --> #i43255# - refine condition to avoid unneeded
// invalidations: anchored object had to be on the page of its anchor
// text frame.
if ( mpAnchoredDrawObj->GetAnchorFrm()->IsTxtFrm() &&
mpOldPageFrm == mpAnchoredDrawObj->GetAnchorFrm()->FindPageFrm() )
{
mpAnchoredDrawObj->AnchorFrm()->Prepare( PREP_FLY_LEAVE );
}
// 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->GetPageFrm(),
mpAnchoredDrawObj->GetObjRectWithSpaces(),
PREP_FLY_ARRIVE );
// 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->AnchorFrm()->InvalidatePos();
}
}
}
2011-02-05 18:00:33 +01:00
// --> #i32795#
Point SwPosNotify::LastObjPos() const
{
return maOldObjRect.Pos();
}
// ============================================================================
2011-02-05 18:00:33 +01:00
// #i32795#
// helper class for oscillation control on object positioning
// ============================================================================
class SwObjPosOscillationControl
{
private:
sal_uInt8 mnPosStackSize;
const SwAnchoredDrawObject* mpAnchoredDrawObj;
std::vector<Point*> maObjPositions;
public:
SwObjPosOscillationControl( const SwAnchoredDrawObject& _rAnchoredDrawObj );
~SwObjPosOscillationControl();
bool OscillationDetected();
};
SwObjPosOscillationControl::SwObjPosOscillationControl(
const SwAnchoredDrawObject& _rAnchoredDrawObj )
: mnPosStackSize( 20 ),
mpAnchoredDrawObj( &_rAnchoredDrawObj )
{
}
SwObjPosOscillationControl::~SwObjPosOscillationControl()
{
while ( !maObjPositions.empty() )
{
Point* pPos = maObjPositions.back();
delete pPos;
maObjPositions.pop_back();
}
}
bool SwObjPosOscillationControl::OscillationDetected()
{
bool bOscillationDetected = false;
if ( maObjPositions.size() == mnPosStackSize )
{
// position stack is full -> oscillation
bOscillationDetected = true;
}
else
{
Point* pNewObjPos = new Point( mpAnchoredDrawObj->GetObjRect().Pos() );
for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin();
aObjPosIter != maObjPositions.end();
++aObjPosIter )
{
if ( *(pNewObjPos) == *(*aObjPosIter) )
{
2010-12-04 14:11:36 +09:00
// position already occurred -> oscillation
bOscillationDetected = true;
delete pNewObjPos;
break;
}
}
if ( !bOscillationDetected )
{
maObjPositions.push_back( pNewObjPos );
}
}
return bOscillationDetected;
}
// ============================================================================
// implementation of class <SwAnchoredDrawObject>
// ============================================================================
TYPEINIT1(SwAnchoredDrawObject,SwAnchoredObject);
SwAnchoredDrawObject::SwAnchoredDrawObject() :
SwAnchoredObject(),
mbValidPos( false ),
2011-02-05 18:00:33 +01:00
// --> #i34748#
mpLastObjRect( 0L ),
mbNotYetAttachedToAnchorFrame( true ),
2011-02-05 18:00:33 +01:00
// --> #i28749#
mbNotYetPositioned( true ),
2011-02-05 18:00:33 +01:00
// --> #i62875#
mbCaptureAfterLayoutDirChange( false )
{
}
SwAnchoredDrawObject::~SwAnchoredDrawObject()
{
// #i34748#
delete mpLastObjRect;
}
2011-02-05 18:00:33 +01:00
// --> #i62875#
void SwAnchoredDrawObject::UpdateLayoutDir()
{
SwFrmFmt::tLayoutDir nOldLayoutDir( GetFrmFmt().GetLayoutDir() );
SwAnchoredObject::UpdateLayoutDir();
if ( !NotYetPositioned() &&
GetFrmFmt().GetLayoutDir() != nOldLayoutDir &&
GetFrmFmt().GetDoc()->get(IDocumentSettingAccess::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) &&
!IsOutsidePage() )
{
mbCaptureAfterLayoutDirChange = true;
}
}
2011-02-05 18:00:33 +01:00
// --> #i62875#
2008-10-10 13:02:43 +00:00
bool SwAnchoredDrawObject::IsOutsidePage() const
{
bool bOutsidePage( false );
if ( !NotYetPositioned() && GetPageFrm() )
{
SwRect aTmpRect( GetObjRect() );
bOutsidePage =
( aTmpRect.Intersection( GetPageFrm()->Frm() ) != GetObjRect() );
}
return bOutsidePage;
}
// =============================================================================
2011-02-05 18:00:33 +01:00
// #i26791# - implementation of pure virtual method declared in
// base class <SwAnchoredObject>
// =============================================================================
void SwAnchoredDrawObject::MakeObjPos()
{
if ( IsPositioningInProgress() )
{
// nothind to do - positioning already in progress
return;
}
if ( mbValidPos )
{
// nothing to do - position is valid
return;
}
2011-02-05 18:00:33 +01:00
// --> #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() ));
2011-02-05 18:00:33 +01:00
// --> #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.
2011-02-05 18:00:33 +01:00
// --> #i36010# - Note: horizontal left-to-right layout is made
// the default layout direction for <SwDrawFrmFmt> instances. Thus, it has
// to be adjusted manually, if no adjustment of the positioning attributes
// have to be performed here.
2011-02-05 18:00:33 +01:00
// --> #i35635# - additionally move drawing object to the visible layer.
if ( mbNotYetPositioned )
{
2011-02-05 18:00:33 +01:00
// --> #i35635#
pDrawContact->MoveObjToVisibleLayer( DrawObj() );
2011-02-05 18:00:33 +01:00
// --> perform conversion of positioning
// attributes only for 'master' drawing objects
// #i44334#, #i44681# - check, if positioning
// attributes already have been set.
if ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
!static_cast<SwDrawFrmFmt&>(GetFrmFmt()).IsPosAttrSet() )
{
_SetPositioningAttr();
}
2011-02-05 18:00:33 +01:00
// -->
// - 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 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 FLY_AT_PARA:
case FLY_AT_CHAR:
{
2011-02-05 18:00:33 +01:00
// --> #i32795# - move intrinsic positioning to
// helper method <_MakeObjPosAnchoredAtPara()>
_MakeObjPosAnchoredAtPara();
}
break;
case FLY_AT_PAGE:
case FLY_AT_FLY:
{
2011-02-05 18:00:33 +01:00
// --> #i32795# - move intrinsic positioning to
// helper method <_MakeObjPosAnchoredAtLayout()>
_MakeObjPosAnchoredAtLayout();
}
break;
default:
{
OSL_FAIL( "<SwAnchoredDrawObject::MakeObjPos()> - unknown anchor type - please inform OD." );
}
}
// keep, current object rectangle
2011-02-05 18:00:33 +01:00
// --> #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 ( !GetDrawObj()->ISA(SwDrawVirtObj) &&
!pDrawContact->ObjAnchoredAsChar() &&
GetAnchorFrm()->IsValid() )
{
pDrawContact->ChkPage();
}
}
2011-02-05 18:00:33 +01:00
// --> #i62875#
if ( mbCaptureAfterLayoutDirChange &&
GetPageFrm() )
{
SwRect aPageRect( GetPageFrm()->Frm() );
SwRect aObjRect( GetObjRect() );
if ( aObjRect.Right() >= aPageRect.Right() + 10 )
{
Size aSize( aPageRect.Right() - aObjRect.Right(), 0 );
DrawObj()->Move( aSize );
aObjRect = GetObjRect();
}
if ( aObjRect.Left() + 10 <= aPageRect.Left() )
{
Size aSize( aPageRect.Left() - aObjRect.Left(), 0 );
DrawObj()->Move( aSize );
}
mbCaptureAfterLayoutDirChange = false;
}
}
/** method for the intrinsic positioning of a at-paragraph|at-character
anchored drawing object
2011-02-05 18:00:33 +01:00
#i32795# - helper method for method <MakeObjPos>
@author OD
*/
void SwAnchoredDrawObject::_MakeObjPosAnchoredAtPara()
{
2011-02-05 18:00:33 +01:00
// --> #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.
2011-02-05 18:00:33 +01:00
// --> #i43255# - refine condition: anchor frame format not
// allowed, if another anchored object, has to be consider its wrap influence
2011-02-05 18:00:33 +01:00
// --> #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.
const bool bFormatAnchor =
!static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() &&
!ConsiderObjWrapInfluenceOnObjPos() &&
!ConsiderObjWrapInfluenceOfOtherObjs();
if ( bFormatAnchor )
{
2011-02-05 18:00:33 +01:00
// --> #i50356#
GetAnchorFrmContainingAnchPos()->Calc();
}
bool bOscillationDetected = false;
SwObjPosOscillationControl aObjPosOscCtrl( *this );
2011-02-05 18:00:33 +01:00
// --> #i3317# - boolean, to apply temporarly 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;
2011-02-05 18:00:33 +01:00
// --> #i35640# - correct scope for <SwPosNotify> instance
{
// create instance of <SwPosNotify> for correct notification
SwPosNotify aPosNotify( this );
// determine and set position
objectpositioning::SwToCntntAnchoredObjectPosition
aObjPositioning( *DrawObj() );
aObjPositioning.CalcPosition();
// get further needed results of the positioning algorithm
SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() );
_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 )
{
2011-02-05 18:00:33 +01:00
// --> #i50356#
GetAnchorFrmContainingAnchPos()->Calc();
}
2011-02-05 18:00:33 +01:00
// --> #i3317#
if ( !ConsiderObjWrapInfluenceOnObjPos() &&
OverlapsPrevColumn() )
{
bConsiderWrapInfluenceDueToOverlapPrevCol = true;
}
} while ( !mbValidPos && !bOscillationDetected &&
!bConsiderWrapInfluenceDueToOverlapPrevCol );
2011-02-05 18:00:33 +01:00
// --> #i3317# - consider a detected oscillation and overlapping
// with previous column.
// temporarly consider the anchored objects wrapping style influence
if ( bOscillationDetected || bConsiderWrapInfluenceDueToOverlapPrevCol )
{
SetTmpConsiderWrapInfluence( true );
SetRestartLayoutProcess( true );
}
}
/** method for the intrinsic positioning of a at-page|at-frame anchored
drawing object
2011-02-05 18:00:33 +01:00
#i32795# - helper method for method <MakeObjPos>
@author OD
*/
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
2011-02-05 18:00:33 +01:00
// --> #i31698#
// --> #i34995# - setting anchor position needed for filters,
// especially for the xml-filter to the OpenOffice.org file format
{
const Point aNewAnchorPos =
GetAnchorFrm()->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
DrawObj()->SetAnchorPos( aNewAnchorPos );
2011-02-05 18:00:33 +01:00
// --> #i70122# - missing invalidation
InvalidateObjRectWithSpaces();
}
SetCurrRelPos( aObjPositioning.GetRelPos() );
const SwFrm* pAnchorFrm = GetAnchorFrm();
SWRECTFN( pAnchorFrm );
const Point aAnchPos( (pAnchorFrm->Frm().*fnRect->fnGetPos)() );
SetObjLeft( aAnchPos.X() + GetCurrRelPos().X() );
SetObjTop( aAnchPos.Y() + GetCurrRelPos().Y() );
}
void SwAnchoredDrawObject::_SetDrawObjAnchor()
{
// new anchor position
2011-02-05 18:00:33 +01:00
// --> #i31698# -
Point aNewAnchorPos =
GetAnchorFrm()->GetFrmAnchorPos( ::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 );
2011-02-05 18:00:33 +01:00
// --> #i70122# - missing invalidation
InvalidateObjRectWithSpaces();
}
}
/** method to invalidate the given page frame
2011-02-05 18:00:33 +01:00
#i28701#
@author OD
*/
void SwAnchoredDrawObject::_InvalidatePage( SwPageFrm* _pPageFrm )
{
if ( _pPageFrm && !_pPageFrm->GetFmt()->GetDoc()->IsInDtor() )
{
if ( _pPageFrm->GetUpper() )
{
2011-02-05 18:00:33 +01:00
// --> #i35007# - correct invalidation for as-character
// anchored objects.
if ( GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR )
{
_pPageFrm->InvalidateFlyInCnt();
}
else
{
_pPageFrm->InvalidateFlyLayout();
}
SwRootFrm* pRootFrm = static_cast<SwRootFrm*>(_pPageFrm->GetUpper());
pRootFrm->DisallowTurbo();
if ( pRootFrm->GetTurbo() )
{
const SwCntntFrm* pTmpFrm = pRootFrm->GetTurbo();
pRootFrm->ResetTurbo();
pTmpFrm->InvalidatePage();
}
pRootFrm->SetIdleFlags();
}
}
}
void SwAnchoredDrawObject::InvalidateObjPos()
{
2011-02-05 18:00:33 +01:00
// --> #i28701# - check, if invalidation is allowed
if ( mbValidPos &&
InvalidationOfPosAllowed() )
{
mbValidPos = false;
2011-02-05 18:00:33 +01:00
// --> #i68520#
InvalidateObjRectWithSpaces();
2011-02-05 18:00:33 +01:00
// --> #i44339# - check, if anchor frame exists.
if ( GetAnchorFrm() )
{
2011-02-05 18:00:33 +01:00
// --> #118547# - notify anchor frame of as-character
// anchored object, because its positioned by the format of its anchor frame.
2011-02-05 18:00:33 +01:00
// --> #i44559# - assure, that text hint is already
// existing in the text frame
if ( GetAnchorFrm()->ISA(SwTxtFrm) &&
(GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
{
SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) );
if ( pAnchorTxtFrm->GetTxtNode()->GetpSwpHints() &&
pAnchorTxtFrm->CalcFlyPos( &GetFrmFmt() ) != STRING_LEN )
{
AnchorFrm()->Prepare( PREP_FLY_ATTR_CHG, &GetFrmFmt() );
}
}
SwPageFrm* pPageFrm = AnchorFrm()->FindPageFrm();
_InvalidatePage( pPageFrm );
2011-02-05 18:00:33 +01:00
// --> #i32270# - also invalidate page frame, at which the
// drawing object is registered at.
SwPageFrm* pPageFrmRegisteredAt = GetPageFrm();
if ( pPageFrmRegisteredAt &&
pPageFrmRegisteredAt != pPageFrm )
{
_InvalidatePage( pPageFrmRegisteredAt );
}
// #i33751#, #i34060# - method <GetPageFrmOfAnchor()>
// is replaced by method <FindPageFrmOfAnchor()>. It's return value
// have to be checked.
SwPageFrm* pPageFrmOfAnchor = FindPageFrmOfAnchor();
if ( pPageFrmOfAnchor &&
pPageFrmOfAnchor != pPageFrm &&
pPageFrmOfAnchor != pPageFrmRegisteredAt )
{
_InvalidatePage( pPageFrmOfAnchor );
}
}
}
}
SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt()
{
OSL_ENSURE( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
"<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
}
const SwFrmFmt& SwAnchoredDrawObject::GetFrmFmt() const
{
OSL_ENSURE( static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt(),
"<SwAnchoredDrawObject::GetFrmFmt()> - missing frame format -> crash." );
return *(static_cast<SwDrawContact*>(GetUserCall(GetDrawObj()))->GetFmt());
}
const SwRect SwAnchoredDrawObject::GetObjRect() const
{
// use geometry of drawing object
//return GetDrawObj()->GetCurrentBoundRect();
return GetDrawObj()->GetSnapRect();
}
2011-02-05 18:00:33 +01:00
// --> #i70122#
const SwRect SwAnchoredDrawObject::GetObjBoundRect() const
{
// Resize objects with relative width or height
if ( GetDrawObj( )->GetRelativeWidth( ) || GetDrawObj()->GetRelativeHeight( ) )
{
Rectangle aPageRect = GetPageFrm( )->GetBoundRect( ).SVRect();
Rectangle aCurrObjRect = GetDrawObj()->GetCurrentBoundRect();
long nTargetWidth = aCurrObjRect.GetWidth( );
if ( GetDrawObj( )->GetRelativeWidth( ) )
nTargetWidth = aPageRect.GetWidth( ) * GetDrawObj( )->GetRelativeWidth( ).get( );
long nTargetHeight = aCurrObjRect.GetHeight( );
if ( GetDrawObj( )->GetRelativeHeight( ) )
nTargetHeight = aPageRect.GetHeight( ) * GetDrawObj( )->GetRelativeHeight( ).get( );
if ( nTargetWidth != aCurrObjRect.GetWidth( ) || nTargetHeight != aCurrObjRect.GetHeight( ) )
{
const_cast< SdrObject* >( GetDrawObj() )->Resize( aCurrObjRect.TopLeft(),
Fraction( nTargetWidth, aCurrObjRect.GetWidth() ),
Fraction( nTargetHeight, aCurrObjRect.GetHeight() ), false );
}
}
return GetDrawObj()->GetCurrentBoundRect();
}
2011-02-05 18:00:33 +01:00
// --> #i68520#
2008-10-10 13:02:43 +00:00
bool SwAnchoredDrawObject::_SetObjTop( const SwTwips _nTop )
{
SwTwips nDiff = _nTop - GetObjRect().Top();
DrawObj()->Move( Size( 0, nDiff ) );
return nDiff != 0;
}
2008-10-10 13:02:43 +00:00
bool SwAnchoredDrawObject::_SetObjLeft( const SwTwips _nLeft )
{
SwTwips nDiff = _nLeft - GetObjRect().Left();
DrawObj()->Move( Size( nDiff, 0 ) );
return nDiff != 0;
}
/** adjust positioning and alignment attributes for new anchor frame
2011-02-05 18:00:33 +01:00
#i33313# - add second optional parameter <_pNewObjRect>
@author OD
*/
void SwAnchoredDrawObject::AdjustPositioningAttr( const SwFrm* _pNewAnchorFrm,
const SwRect* _pNewObjRect )
{
SwTwips nHoriRelPos = 0;
SwTwips nVertRelPos = 0;
const Point aAnchorPos = _pNewAnchorFrm->GetFrmAnchorPos( ::HasWrap( GetDrawObj() ) );
2011-02-05 18:00:33 +01:00
// --> #i33313#
const SwRect aObjRect( _pNewObjRect ? *_pNewObjRect : GetObjRect() );
const bool bVert = _pNewAnchorFrm->IsVertical();
const bool bR2L = _pNewAnchorFrm->IsRightToLeft();
if ( bVert )
{
nHoriRelPos = aObjRect.Top() - aAnchorPos.Y();
nVertRelPos = aAnchorPos.X() - aObjRect.Right();
}
else if ( bR2L )
{
nHoriRelPos = aAnchorPos.X() - aObjRect.Right();
nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
}
else
{
nHoriRelPos = aObjRect.Left() - aAnchorPos.X();
nVertRelPos = aObjRect.Top() - aAnchorPos.Y();
}
GetFrmFmt().SetFmtAttr( SwFmtHoriOrient( nHoriRelPos, text::HoriOrientation::NONE, text::RelOrientation::FRAME ) );
GetFrmFmt().SetFmtAttr( SwFmtVertOrient( nVertRelPos, text::VertOrientation::NONE, text::RelOrientation::FRAME ) );
}
2011-02-05 18:00:33 +01:00
// --> #i34748# - change return type
const Rectangle* SwAnchoredDrawObject::GetLastObjRect() const
{
return mpLastObjRect;
}
2011-02-05 18:00:33 +01:00
// --> #i34748# - change return type.
// If member <mpLastObjRect> is NULL, create one.
void SwAnchoredDrawObject::SetLastObjRect( const Rectangle& _rNewLastRect )
{
if ( !mpLastObjRect )
{
mpLastObjRect = new Rectangle;
}
*(mpLastObjRect) = _rNewLastRect;
}
void SwAnchoredDrawObject::ObjectAttachedToAnchorFrame()
{
2011-02-05 18:00:33 +01:00
// --> #i31698#
SwAnchoredObject::ObjectAttachedToAnchorFrame();
if ( mbNotYetAttachedToAnchorFrame )
{
mbNotYetAttachedToAnchorFrame = false;
}
}
/** method to set positioning attributes
2011-02-05 18:00:33 +01:00
#i35798#
During load the positioning attributes aren't set.
Thus, the positioning attributes are set by the current object geometry.
This method is also used for the conversion for drawing objects
(not anchored as-character) imported from OpenOffice.org file format
once and directly before the first positioning.
@author OD
*/
void SwAnchoredDrawObject::_SetPositioningAttr()
{
SwDrawContact* pDrawContact =
static_cast<SwDrawContact*>(GetUserCall( GetDrawObj() ));
if ( !pDrawContact->ObjAnchoredAsChar() )
{
SwRect aObjRect( GetObjRect() );
SwTwips nHoriPos = aObjRect.Left();
SwTwips nVertPos = aObjRect.Top();
// #i44334#, #i44681#
// perform conversion only if position is in horizontal-left-to-right-layout.
if ( GetFrmFmt().GetPositionLayoutDir() ==
text::PositionLayoutDir::PositionInHoriL2R )
{
SwFrmFmt::tLayoutDir eLayoutDir = GetFrmFmt().GetLayoutDir();
switch ( eLayoutDir )
{
case SwFrmFmt::HORI_L2R:
{
// nothing to do
}
break;
case SwFrmFmt::HORI_R2L:
{
nHoriPos = -aObjRect.Left() - aObjRect.Width();
}
break;
case SwFrmFmt::VERT_R2L:
{
nHoriPos = aObjRect.Top();
nVertPos = -aObjRect.Left() - aObjRect.Width();
}
break;
default:
{
OSL_FAIL( "<SwAnchoredDrawObject::_SetPositioningAttr()> - unsupported layout direction" );
}
}
}
2011-02-05 18:00:33 +01:00
// --> #i71182#
// only change position - do not lose other attributes
SwFmtHoriOrient aHori( GetFrmFmt().GetHoriOrient() );
aHori.SetPos( nHoriPos );
GetFrmFmt().SetFmtAttr( aHori );
SwFmtVertOrient aVert( GetFrmFmt().GetVertOrient() );
2010-11-16 06:31:40 +01:00
aVert.SetPos( nVertPos );
GetFrmFmt().SetFmtAttr( aVert );
2011-02-05 18:00:33 +01:00
// --> #i36010# - set layout direction of the position
GetFrmFmt().SetPositionLayoutDir(
text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
}
2011-02-05 18:00:33 +01:00
// --> #i65798# - also for as-character anchored objects
// --> #i45952# - indicate that position
// attributes are set now.
static_cast<SwDrawFrmFmt&>(GetFrmFmt()).PosAttrSet();
}
void SwAnchoredDrawObject::NotifyBackground( SwPageFrm* _pPageFrm,
const SwRect& _rRect,
PrepareHint _eHint )
{
::Notify_Background( GetDrawObj(), _pPageFrm, _rRect, _eHint, sal_True );
}
/** method to assure that anchored object is registered at the correct
page frame
2011-02-05 18:00:33 +01:00
#i28701#
@author OD
*/
void SwAnchoredDrawObject::RegisterAtCorrectPage()
{
SwPageFrm* pPageFrm( 0L );
if ( GetVertPosOrientFrm() )
{
pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm());
}
if ( pPageFrm && GetPageFrm() != pPageFrm )
{
if ( GetPageFrm() )
GetPageFrm()->RemoveDrawObjFromPage( *this );
pPageFrm->AppendDrawObjToPage( *this );
}
}
// =============================================================================
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */