blob: 18a49d8d876d5d74088bb5f9e7701978b334c82e [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include "hintids.hxx"
#include <svx/svdtrans.hxx>
#include <editeng/protitem.hxx>
#include <editeng/opaqitem.hxx>
#include <svx/svdpage.hxx>
#include <fmtclds.hxx>
#include <fmtornt.hxx>
#include <fmtfsize.hxx>
#include <fmturl.hxx>
#include "viewsh.hxx"
#include "viewimp.hxx"
#include "cntfrm.hxx"
#include "frmatr.hxx"
#include "doc.hxx"
#include <IDocumentUndoRedo.hxx>
#include "dview.hxx"
#include "dflyobj.hxx"
#include "flyfrm.hxx"
#include "frmfmt.hxx"
#include "viewopt.hxx"
#include "frmtool.hxx"
#include "flyfrms.hxx"
#include "ndnotxt.hxx"
#include "grfatr.hxx"
#include "pagefrm.hxx"
#include "rootfrm.hxx"
using namespace ::com::sun::star;
// --> OD 2004-11-22 #117958#
#include <svx/sdr/properties/defaultproperties.hxx>
// <--
#include <basegfx/range/b2drange.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
// AW: For VCOfDrawVirtObj and stuff
#include <svx/sdr/contact/viewcontactofvirtobj.hxx>
#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
#include <sw_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
using namespace ::com::sun::star;
static sal_Bool bInResize = sal_False;
TYPEINIT1( SwFlyDrawObj, SdrObject )
TYPEINIT1( SwVirtFlyDrawObj, SdrVirtObj )
/*************************************************************************
|*
|* SwFlyDrawObj::Ctor
|*
|* Ersterstellung MA 18. Apr. 95
|* Letzte Aenderung MA 28. May. 96
|*
*************************************************************************/
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace sdr
{
namespace contact
{
// #i95264# currently needed since createViewIndependentPrimitive2DSequence()
// is called when RecalcBoundRect() is used. There should currently no VOCs being
// constructed since it gets not visualized (instead the corresponding SwVirtFlyDrawObj's
// referencing this one are visualized).
class VCOfSwFlyDrawObj : public ViewContactOfSdrObj
{
protected:
// This method is responsible for creating the graphical visualisation data
// ONLY based on model data
virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const;
public:
// basic constructor, used from SdrObject.
VCOfSwFlyDrawObj(SwFlyDrawObj& rObj)
: ViewContactOfSdrObj(rObj)
{
}
virtual ~VCOfSwFlyDrawObj();
};
drawinglayer::primitive2d::Primitive2DSequence VCOfSwFlyDrawObj::createViewIndependentPrimitive2DSequence() const
{
// currently gets not visualized, return empty sequence
return drawinglayer::primitive2d::Primitive2DSequence();
}
VCOfSwFlyDrawObj::~VCOfSwFlyDrawObj()
{
}
} // end of namespace contact
} // end of namespace sdr
////////////////////////////////////////////////////////////////////////////////////////////////////
sdr::properties::BaseProperties* SwFlyDrawObj::CreateObjectSpecificProperties()
{
// --> OD 2004-11-22 #117958# - create default properties
return new sdr::properties::DefaultProperties(*this);
// <--
}
sdr::contact::ViewContact* SwFlyDrawObj::CreateObjectSpecificViewContact()
{
// #i95264# needs an own VC since createViewIndependentPrimitive2DSequence()
// is called when RecalcBoundRect() is used
return new sdr::contact::VCOfSwFlyDrawObj(*this);
}
SwFlyDrawObj::SwFlyDrawObj()
{
}
SwFlyDrawObj::~SwFlyDrawObj()
{
}
/*************************************************************************
|*
|* SwFlyDrawObj::Factory-Methoden
|*
|* Ersterstellung MA 23. Feb. 95
|* Letzte Aenderung MA 23. Feb. 95
|*
*************************************************************************/
sal_uInt32 __EXPORT SwFlyDrawObj::GetObjInventor() const
{
return SWGInventor;
}
sal_uInt16 __EXPORT SwFlyDrawObj::GetObjIdentifier() const
{
return SwFlyDrawObjIdentifier;
}
sal_uInt16 __EXPORT SwFlyDrawObj::GetObjVersion() const
{
return SwDrawFirst;
}
/*************************************************************************
|*
|* SwVirtFlyDrawObj::CToren, Dtor
|*
|* Ersterstellung MA 08. Dec. 94
|* Letzte Aenderung MA 28. May. 96
|*
*************************************************************************/
//////////////////////////////////////////////////////////////////////////////////////
// AW: Need own primitive to get the FlyFrame paint working
namespace drawinglayer
{
namespace primitive2d
{
class SwVirtFlyDrawObjPrimitive : public BufferedDecompositionPrimitive2D
{
private:
const SwVirtFlyDrawObj& mrSwVirtFlyDrawObj;
const basegfx::B2DRange maOuterRange;
protected:
// method which is to be used to implement the local decomposition of a 2D primitive
virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
public:
SwVirtFlyDrawObjPrimitive(
const SwVirtFlyDrawObj& rSwVirtFlyDrawObj,
const basegfx::B2DRange &rOuterRange)
: BufferedDecompositionPrimitive2D(),
mrSwVirtFlyDrawObj(rSwVirtFlyDrawObj),
maOuterRange(rOuterRange)
{
}
// compare operator
virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
// get range
virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const;
// overloaded to allow callbacks to wrap_DoPaintObject
virtual Primitive2DSequence get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
// data read access
const SwVirtFlyDrawObj& getSwVirtFlyDrawObj() const { return mrSwVirtFlyDrawObj; }
const basegfx::B2DRange& getOuterRange() const { return maOuterRange; }
// provide unique ID
DeclPrimitrive2DIDBlock()
};
} // end of namespace primitive2d
} // end of namespace drawinglayer
namespace drawinglayer
{
namespace primitive2d
{
Primitive2DSequence SwVirtFlyDrawObjPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
Primitive2DSequence aRetval;
if(!getOuterRange().isEmpty())
{
// currently this SW object has no primitive representation. As long as this is the case,
// create invisible geometry to allow corfect HitTest and BoundRect calculations for the
// object. Use a filled primitive to get 'inside' as default object hit. The special cases from
// the old SwVirtFlyDrawObj::CheckHit implementation are handled now in SwDrawView::PickObj;
// this removed the 'hack' to get a view from inside model data or to react on null-tolerance
// as it was done in the old implementation
const Primitive2DReference aHitTestReference(
createHiddenGeometryPrimitives2D(
true,
getOuterRange()));
aRetval = Primitive2DSequence(&aHitTestReference, 1);
}
return aRetval;
}
bool SwVirtFlyDrawObjPrimitive::operator==(const BasePrimitive2D& rPrimitive) const
{
if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
{
const SwVirtFlyDrawObjPrimitive& rCompare = (SwVirtFlyDrawObjPrimitive&)rPrimitive;
return (&getSwVirtFlyDrawObj() == &rCompare.getSwVirtFlyDrawObj()
&& getOuterRange() == rCompare.getOuterRange());
}
return false;
}
basegfx::B2DRange SwVirtFlyDrawObjPrimitive::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
{
return getOuterRange();
}
Primitive2DSequence SwVirtFlyDrawObjPrimitive::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
// This is the callback to keep the FlyFrame painting in SW alive as long as it
// is not changed to primitives. This is the method which will be called by the processors
// when they do not know this primitive (and they do not). Inside wrap_DoPaintObject
// there needs to be a test that paint is only done during SW repaints (see there).
// Using this mechanism guarantees the correct Z-Order of the VirtualObject-based FlyFrames.
getSwVirtFlyDrawObj().wrap_DoPaintObject();
// call parent
return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
}
// provide unique ID
ImplPrimitrive2DIDBlock(SwVirtFlyDrawObjPrimitive, PRIMITIVE2D_ID_SWVIRTFLYDRAWOBJPRIMITIVE2D)
} // end of namespace primitive2d
} // end of namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////////////
// AW: own sdr::contact::ViewContact (VC) sdr::contact::ViewObjectContact (VOC) needed
// since offset is defined different from SdrVirtObj's sdr::contact::ViewContactOfVirtObj.
// For paint, that offset is used by setting at the OutputDevice; for primitives this is
// not possible since we have no OutputDevice, but define the geometry itself.
namespace sdr
{
namespace contact
{
class VCOfSwVirtFlyDrawObj : public ViewContactOfVirtObj
{
protected:
// This method is responsible for creating the graphical visualisation data
// ONLY based on model data
virtual drawinglayer::primitive2d::Primitive2DSequence createViewIndependentPrimitive2DSequence() const;
public:
// basic constructor, used from SdrObject.
VCOfSwVirtFlyDrawObj(SwVirtFlyDrawObj& rObj)
: ViewContactOfVirtObj(rObj)
{
}
virtual ~VCOfSwVirtFlyDrawObj();
// access to SwVirtFlyDrawObj
SwVirtFlyDrawObj& GetSwVirtFlyDrawObj() const
{
return (SwVirtFlyDrawObj&)mrObject;
}
};
} // end of namespace contact
} // end of namespace sdr
namespace sdr
{
namespace contact
{
drawinglayer::primitive2d::Primitive2DSequence VCOfSwVirtFlyDrawObj::createViewIndependentPrimitive2DSequence() const
{
drawinglayer::primitive2d::Primitive2DSequence xRetval;
const SdrObject& rReferencedObject = GetSwVirtFlyDrawObj().GetReferencedObj();
if(rReferencedObject.ISA(SwFlyDrawObj))
{
// create an own specialized primitive which is used as repaint callpoint and HitTest
// for HitTest processor (see primitive implementation above)
const basegfx::B2DRange aOuterRange(GetSwVirtFlyDrawObj().getOuterBound());
if(!aOuterRange.isEmpty())
{
const drawinglayer::primitive2d::Primitive2DReference xPrimitive(
new drawinglayer::primitive2d::SwVirtFlyDrawObjPrimitive(
GetSwVirtFlyDrawObj(),
aOuterRange));
xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xPrimitive, 1);
}
}
return xRetval;
}
VCOfSwVirtFlyDrawObj::~VCOfSwVirtFlyDrawObj()
{
}
} // end of namespace contact
} // end of namespace sdr
//////////////////////////////////////////////////////////////////////////////////////
basegfx::B2DRange SwVirtFlyDrawObj::getOuterBound() const
{
basegfx::B2DRange aOuterRange;
const SdrObject& rReferencedObject = GetReferencedObj();
if(rReferencedObject.ISA(SwFlyDrawObj))
{
const SwFlyFrm* pFlyFrame = GetFlyFrm();
if(pFlyFrame)
{
const Rectangle aOuterRectangle(pFlyFrame->Frm().Pos(), pFlyFrame->Frm().SSize());
if(!aOuterRectangle.IsEmpty()
&& RECT_EMPTY != aOuterRectangle.Right()
&& RECT_EMPTY != aOuterRectangle.Bottom())
{
aOuterRange.expand(basegfx::B2DTuple(aOuterRectangle.Left(), aOuterRectangle.Top()));
aOuterRange.expand(basegfx::B2DTuple(aOuterRectangle.Right(), aOuterRectangle.Bottom()));
}
}
}
return aOuterRange;
}
basegfx::B2DRange SwVirtFlyDrawObj::getInnerBound() const
{
basegfx::B2DRange aInnerRange;
const SdrObject& rReferencedObject = GetReferencedObj();
if(rReferencedObject.ISA(SwFlyDrawObj))
{
const SwFlyFrm* pFlyFrame = GetFlyFrm();
if(pFlyFrame)
{
const Rectangle aInnerRectangle(pFlyFrame->Frm().Pos() + pFlyFrame->Prt().Pos(), pFlyFrame->Prt().SSize());
if(!aInnerRectangle.IsEmpty()
&& RECT_EMPTY != aInnerRectangle.Right()
&& RECT_EMPTY != aInnerRectangle.Bottom())
{
aInnerRange.expand(basegfx::B2DTuple(aInnerRectangle.Left(), aInnerRectangle.Top()));
aInnerRange.expand(basegfx::B2DTuple(aInnerRectangle.Right(), aInnerRectangle.Bottom()));
}
}
}
return aInnerRange;
}
sdr::contact::ViewContact* SwVirtFlyDrawObj::CreateObjectSpecificViewContact()
{
// need an own ViewContact (VC) to allow creation of a specialized primitive
// for being able to visualize the FlyFrames in primitive renderers
return new sdr::contact::VCOfSwVirtFlyDrawObj(*this);
}
SwVirtFlyDrawObj::SwVirtFlyDrawObj(SdrObject& rNew, SwFlyFrm* pFly) :
SdrVirtObj( rNew ),
pFlyFrm( pFly )
{
//#110094#-1
// bNotPersistent = bNeedColorRestore = bWriterFlyFrame = sal_True;
const SvxProtectItem &rP = pFlyFrm->GetFmt()->GetProtect();
bMovProt = rP.IsPosProtected();
bSizProt = rP.IsSizeProtected();
}
__EXPORT SwVirtFlyDrawObj::~SwVirtFlyDrawObj()
{
if ( GetPage() ) //Der SdrPage die Verantwortung entziehen.
GetPage()->RemoveObject( GetOrdNum() );
}
/*************************************************************************
|*
|* SwVirtFlyDrawObj::GetFmt()
|*
|* Ersterstellung MA 08. Dec. 94
|* Letzte Aenderung MA 08. Dec. 94
|*
*************************************************************************/
const SwFrmFmt *SwVirtFlyDrawObj::GetFmt() const
{
return GetFlyFrm()->GetFmt();
}
SwFrmFmt *SwVirtFlyDrawObj::GetFmt()
{
return GetFlyFrm()->GetFmt();
}
/*************************************************************************
|*
|* SwVirtFlyDrawObj::Paint()
|*
|* Ersterstellung MA 20. Dec. 94
|* Letzte Aenderung MA 18. Dec. 95
|*
*************************************************************************/
// --> OD #i102707#
namespace
{
class RestoreMapMode
{
public:
explicit RestoreMapMode( ViewShell* pViewShell )
: mbMapModeRestored( false )
, mpOutDev( pViewShell->GetOut() )
{
if ( pViewShell->getPrePostMapMode() != mpOutDev->GetMapMode() )
{
mpOutDev->Push(PUSH_MAPMODE);
GDIMetaFile* pMetaFile = mpOutDev->GetConnectMetaFile();
if ( pMetaFile &&
pMetaFile->IsRecord() && !pMetaFile->IsPause() )
{
ASSERT( false,
"MapMode restoration during meta file creation is somehow suspect - using <SetRelativeMapMode(..)>, but not sure, if correct." )
mpOutDev->SetRelativeMapMode( pViewShell->getPrePostMapMode() );
}
else
{
mpOutDev->SetMapMode( pViewShell->getPrePostMapMode() );
}
mbMapModeRestored = true;
}
};
~RestoreMapMode()
{
if ( mbMapModeRestored )
{
mpOutDev->Pop();
}
};
private:
bool mbMapModeRestored;
OutputDevice* mpOutDev;
};
}
// <--
void SwVirtFlyDrawObj::wrap_DoPaintObject() const
{
ViewShell* pShell = pFlyFrm->getRootFrm()->GetCurrShell();
// Only paint when we have a current shell and a DrawingLayer paint is in progress.
// This avcoids evtl. problems with renderers which do processing stuff,
// but no paints. IsPaintInProgress() depends on SW repaint, so, as long
// as SW paints self and calls DrawLayer() for Heaven and Hell, this will
// be correct
if ( pShell && pShell->IsDrawingLayerPaintInProgress() )
{
sal_Bool bDrawObject(sal_True);
if ( !SwFlyFrm::IsPaint( (SdrObject*)this, pShell ) )
{
bDrawObject = sal_False;
}
if ( bDrawObject )
{
if ( !pFlyFrm->IsFlyInCntFrm() )
{
// it is also necessary to restore the VCL MapMode from ViewInformation since e.g.
// the VCL PixelRenderer resets it at the used OutputDevice. Unfortunately, this
// excludes shears and rotates which are not expressable in MapMode.
// OD #i102707#
// new helper class to restore MapMode - restoration, only if
// needed and consideration of paint for meta file creation .
RestoreMapMode aRestoreMapModeIfNeeded( pShell );
// paint the FlyFrame (use standard VCL-Paint)
pFlyFrm->Paint( GetFlyFrm()->Frm() );
}
}
}
}
/*************************************************************************
|*
|* SwVirtFlyDrawObj::TakeObjInfo()
|*
|* Ersterstellung MA 03. May. 95
|* Letzte Aenderung MA 03. May. 95
|*
*************************************************************************/
void __EXPORT SwVirtFlyDrawObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
{
rInfo.bSelectAllowed = rInfo.bMoveAllowed =
rInfo.bResizeFreeAllowed = rInfo.bResizePropAllowed = sal_True;
rInfo.bRotateFreeAllowed = rInfo.bRotate90Allowed =
rInfo.bMirrorFreeAllowed = rInfo.bMirror45Allowed =
rInfo.bMirror90Allowed = rInfo.bShearAllowed =
rInfo.bCanConvToPath = rInfo.bCanConvToPoly =
rInfo.bCanConvToPathLineToArea = rInfo.bCanConvToPolyLineToArea = sal_False;
}
/*************************************************************************
|*
|* SwVirtFlyDrawObj::Groessenermittlung
|*
|* Ersterstellung MA 12. Jan. 95
|* Letzte Aenderung MA 10. Nov. 95
|*
*************************************************************************/
void SwVirtFlyDrawObj::SetRect() const
{
if ( GetFlyFrm()->Frm().HasArea() )
((SwVirtFlyDrawObj*)this)->aOutRect = GetFlyFrm()->Frm().SVRect();
else
((SwVirtFlyDrawObj*)this)->aOutRect = Rectangle();
}
const Rectangle& __EXPORT SwVirtFlyDrawObj::GetCurrentBoundRect() const
{
SetRect();
return aOutRect;
}
const Rectangle& __EXPORT SwVirtFlyDrawObj::GetLastBoundRect() const
{
return GetCurrentBoundRect();
}
void __EXPORT SwVirtFlyDrawObj::RecalcBoundRect()
{
SetRect();
}
void __EXPORT SwVirtFlyDrawObj::RecalcSnapRect()
{
SetRect();
}
const Rectangle& __EXPORT SwVirtFlyDrawObj::GetSnapRect() const
{
SetRect();
return aOutRect;
}
void __EXPORT SwVirtFlyDrawObj::SetSnapRect(const Rectangle& )
{
Rectangle aTmp( GetLastBoundRect() );
SetRect();
SetChanged();
BroadcastObjectChange();
if (pUserCall!=NULL)
pUserCall->Changed(*this, SDRUSERCALL_RESIZE, aTmp);
}
void __EXPORT SwVirtFlyDrawObj::NbcSetSnapRect(const Rectangle& )
{
SetRect();
}
const Rectangle& __EXPORT SwVirtFlyDrawObj::GetLogicRect() const
{
SetRect();
return aOutRect;
}
void __EXPORT SwVirtFlyDrawObj::SetLogicRect(const Rectangle& )
{
Rectangle aTmp( GetLastBoundRect() );
SetRect();
SetChanged();
BroadcastObjectChange();
if (pUserCall!=NULL)
pUserCall->Changed(*this, SDRUSERCALL_RESIZE, aTmp);
}
void __EXPORT SwVirtFlyDrawObj::NbcSetLogicRect(const Rectangle& )
{
SetRect();
}
::basegfx::B2DPolyPolygon SwVirtFlyDrawObj::TakeXorPoly() const
{
const Rectangle aSourceRectangle(GetFlyFrm()->Frm().SVRect());
const ::basegfx::B2DRange aSourceRange(aSourceRectangle.Left(), aSourceRectangle.Top(), aSourceRectangle.Right(), aSourceRectangle.Bottom());
::basegfx::B2DPolyPolygon aRetval;
aRetval.append(::basegfx::tools::createPolygonFromRect(aSourceRange));
return aRetval;
}
/*************************************************************************
|*
|* SwVirtFlyDrawObj::Move() und Resize()
|*
|* Ersterstellung MA 12. Jan. 95
|* Letzte Aenderung MA 26. Jul. 96
|*
*************************************************************************/
void __EXPORT SwVirtFlyDrawObj::NbcMove(const Size& rSiz)
{
MoveRect( aOutRect, rSiz );
const Point aOldPos( GetFlyFrm()->Frm().Pos() );
const Point aNewPos( aOutRect.TopLeft() );
const SwRect aFlyRect( aOutRect );
//Wenn der Fly eine automatische Ausrichtung hat (rechts oder oben),
//so soll die Automatik erhalten bleiben
SwFrmFmt *pFmt = GetFlyFrm()->GetFmt();
const sal_Int16 eHori = pFmt->GetHoriOrient().GetHoriOrient();
const sal_Int16 eVert = pFmt->GetVertOrient().GetVertOrient();
const sal_Int16 eRelHori = pFmt->GetHoriOrient().GetRelationOrient();
const sal_Int16 eRelVert = pFmt->GetVertOrient().GetRelationOrient();
//Bei Absatzgebundenen Flys muss ausgehend von der neuen Position ein
//neuer Anker gesetzt werden. Anker und neue RelPos werden vom Fly selbst
//berechnet und gesetzt.
if( GetFlyFrm()->IsFlyAtCntFrm() )
((SwFlyAtCntFrm*)GetFlyFrm())->SetAbsPos( aNewPos );
else
{
const SwFrmFmt *pTmpFmt = GetFmt();
const SwFmtVertOrient &rVert = pTmpFmt->GetVertOrient();
const SwFmtHoriOrient &rHori = pTmpFmt->GetHoriOrient();
long lXDiff = aNewPos.X() - aOldPos.X();
if( rHori.IsPosToggle() && text::HoriOrientation::NONE == eHori &&
!GetFlyFrm()->FindPageFrm()->OnRightPage() )
lXDiff = -lXDiff;
if( GetFlyFrm()->GetAnchorFrm()->IsRightToLeft() &&
text::HoriOrientation::NONE == eHori )
lXDiff = -lXDiff;
long lYDiff = aNewPos.Y() - aOldPos.Y();
if( GetFlyFrm()->GetAnchorFrm()->IsVertical() )
{
//lXDiff -= rVert.GetPos();
//lYDiff += rHori.GetPos();
//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
if ( GetFlyFrm()->GetAnchorFrm()->IsVertLR() )
{
lXDiff += rVert.GetPos();
lXDiff = -lXDiff;
}
else
{
lXDiff -= rVert.GetPos();
lYDiff += rHori.GetPos();
}
}
else
{
lXDiff += rHori.GetPos();
lYDiff += rVert.GetPos();
}
if( GetFlyFrm()->GetAnchorFrm()->IsRightToLeft() &&
text::HoriOrientation::NONE != eHori )
lXDiff = GetFlyFrm()->GetAnchorFrm()->Frm().Width() -
aFlyRect.Width() - lXDiff;
const Point aTmp( lXDiff, lYDiff );
GetFlyFrm()->ChgRelPos( aTmp );
}
SwAttrSet aSet( pFmt->GetDoc()->GetAttrPool(),
RES_VERT_ORIENT, RES_HORI_ORIENT );
SwFmtHoriOrient aHori( pFmt->GetHoriOrient() );
SwFmtVertOrient aVert( pFmt->GetVertOrient() );
sal_Bool bPut = sal_False;
if( !GetFlyFrm()->IsFlyLayFrm() &&
::GetHtmlMode(pFmt->GetDoc()->GetDocShell()) )
{
//Im HTML-Modus sind nur automatische Ausrichtungen erlaubt.
//Einzig einen Snap auf Links/Rechts bzw. Linker-/Rechter-Rand koennen
//wir versuchen.
const SwFrm* pAnch = GetFlyFrm()->GetAnchorFrm();
sal_Bool bNextLine = sal_False;
if( !GetFlyFrm()->IsAutoPos() || text::RelOrientation::PAGE_FRAME != aHori.GetRelationOrient() )
{
if( text::RelOrientation::CHAR == eRelHori )
{
aHori.SetHoriOrient( text::HoriOrientation::LEFT );
aHori.SetRelationOrient( text::RelOrientation::CHAR );
}
else
{
bNextLine = sal_True;
//Horizontale Ausrichtung:
const sal_Bool bLeftFrm =
aFlyRect.Left() < pAnch->Frm().Left() + pAnch->Prt().Left(),
bLeftPrt = aFlyRect.Left() + aFlyRect.Width() <
pAnch->Frm().Left() + pAnch->Prt().Width()/2;
if ( bLeftFrm || bLeftPrt )
{
aHori.SetHoriOrient( text::HoriOrientation::LEFT );
aHori.SetRelationOrient( bLeftFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
}
else
{
const sal_Bool bRightFrm = aFlyRect.Left() >
pAnch->Frm().Left() + pAnch->Prt().Width();
aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
aHori.SetRelationOrient( bRightFrm ? text::RelOrientation::FRAME : text::RelOrientation::PRINT_AREA );
}
}
aSet.Put( aHori );
}
//Vertikale Ausrichtung bleibt grundsaetzlich schlicht erhalten,
//nur bei nicht automatischer Ausrichtung wird umgeschaltet.
sal_Bool bRelChar = text::RelOrientation::CHAR == eRelVert;
aVert.SetVertOrient( eVert != text::VertOrientation::NONE ? eVert :
GetFlyFrm()->IsFlyInCntFrm() ? text::VertOrientation::CHAR_CENTER :
bRelChar && bNextLine ? text::VertOrientation::CHAR_TOP : text::VertOrientation::TOP );
if( bRelChar )
aVert.SetRelationOrient( text::RelOrientation::CHAR );
else
aVert.SetRelationOrient( text::RelOrientation::PRINT_AREA );
aSet.Put( aVert );
bPut = sal_True;
}
//Automatische Ausrichtungen wollen wir moeglichst nicht verlieren.
if ( !bPut && bInResize )
{
if ( text::HoriOrientation::NONE != eHori )
{
aHori.SetHoriOrient( eHori );
aHori.SetRelationOrient( eRelHori );
aSet.Put( aHori );
bPut = sal_True;
}
if ( text::VertOrientation::NONE != eVert )
{
aVert.SetVertOrient( eVert );
aVert.SetRelationOrient( eRelVert );
aSet.Put( aVert );
bPut = sal_True;
}
}
if ( bPut )
pFmt->SetFmtAttr( aSet );
}
void __EXPORT SwVirtFlyDrawObj::NbcResize(const Point& rRef,
const Fraction& xFact, const Fraction& yFact)
{
ResizeRect( aOutRect, rRef, xFact, yFact );
const SwFrm* pTmpFrm = GetFlyFrm()->GetAnchorFrm();
if( !pTmpFrm )
pTmpFrm = GetFlyFrm();
const bool bVertX = pTmpFrm->IsVertical();
const sal_Bool bRTL = pTmpFrm->IsRightToLeft();
//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
const bool bVertL2RX = pTmpFrm->IsVertLR();
const Point aNewPos( ( bVertX && !bVertL2RX ) || bRTL ?
aOutRect.Right() + 1 :
aOutRect.Left(),
aOutRect.Top() );
Size aSz( aOutRect.Right() - aOutRect.Left() + 1,
aOutRect.Bottom()- aOutRect.Top() + 1 );
if( aSz != GetFlyFrm()->Frm().SSize() )
{
//Die Breite darf bei Spalten nicht zu schmal werden
if ( GetFlyFrm()->Lower() && GetFlyFrm()->Lower()->IsColumnFrm() )
{
SwBorderAttrAccess aAccess( SwFrm::GetCache(), GetFlyFrm() );
const SwBorderAttrs &rAttrs = *aAccess.Get();
long nMin = rAttrs.CalcLeftLine()+rAttrs.CalcRightLine();
const SwFmtCol& rCol = rAttrs.GetAttrSet().GetCol();
if ( rCol.GetColumns().Count() > 1 )
{
for ( sal_uInt16 i = 0; i < rCol.GetColumns().Count(); ++i )
{
nMin += rCol.GetColumns()[i]->GetLeft() +
rCol.GetColumns()[i]->GetRight() +
MINFLY;
}
nMin -= MINFLY;
}
aSz.Width() = Max( aSz.Width(), nMin );
}
SwFrmFmt *pFmt = GetFmt();
const SwFmtFrmSize aOldFrmSz( pFmt->GetFrmSize() );
GetFlyFrm()->ChgSize( aSz );
SwFmtFrmSize aFrmSz( pFmt->GetFrmSize() );
if ( aFrmSz.GetWidthPercent() || aFrmSz.GetHeightPercent() )
{
long nRelWidth, nRelHeight;
const SwFrm *pRel = GetFlyFrm()->IsFlyLayFrm() ?
GetFlyFrm()->GetAnchorFrm() :
GetFlyFrm()->GetAnchorFrm()->GetUpper();
const ViewShell *pSh = GetFlyFrm()->getRootFrm()->GetCurrShell();
if ( pSh && pRel->IsBodyFrm() &&
pSh->GetViewOptions()->getBrowseMode() &&
pSh->VisArea().HasArea() )
{
nRelWidth = pSh->GetBrowseWidth();
nRelHeight = pSh->VisArea().Height();
const Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
nRelHeight -= 2*aBorder.Height();
}
else
{
nRelWidth = pRel->Prt().Width();
nRelHeight = pRel->Prt().Height();
}
if ( aFrmSz.GetWidthPercent() && aFrmSz.GetWidthPercent() != 0xFF &&
aOldFrmSz.GetWidth() != aFrmSz.GetWidth() )
aFrmSz.SetWidthPercent( sal_uInt8(aSz.Width() * 100L / nRelWidth + 0.5) );
if ( aFrmSz.GetHeightPercent() && aFrmSz.GetHeightPercent() != 0xFF &&
aOldFrmSz.GetHeight() != aFrmSz.GetHeight() )
aFrmSz.SetHeightPercent( sal_uInt8(aSz.Height() * 100L / nRelHeight + 0.5) );
pFmt->GetDoc()->SetAttr( aFrmSz, *pFmt );
}
}
//Position kann auch veraendert sein!
const Point aOldPos( ( bVertX && !bVertL2RX ) || bRTL ?
GetFlyFrm()->Frm().TopRight() :
GetFlyFrm()->Frm().Pos() );
if ( aNewPos != aOldPos )
{
//Kann sich durch das ChgSize veraendert haben!
if( bVertX || bRTL )
{
if( aOutRect.TopRight() != aNewPos )
{
//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
SwTwips nDeltaX;
if ( bVertL2RX )
nDeltaX = aNewPos.X() - aOutRect.Left();
else
nDeltaX = aNewPos.X() - aOutRect.Right();
SwTwips nDeltaY = aNewPos.Y() - aOutRect.Top();
MoveRect( aOutRect, Size( nDeltaX, nDeltaY ) );
}
}
else if ( aOutRect.TopLeft() != aNewPos )
aOutRect.SetPos( aNewPos );
bInResize = sal_True;
NbcMove( Size( 0, 0 ) );
bInResize = sal_False;
}
}
void __EXPORT SwVirtFlyDrawObj::Move(const Size& rSiz)
{
NbcMove( rSiz );
SetChanged();
GetFmt()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
}
void __EXPORT SwVirtFlyDrawObj::Resize(const Point& rRef,
const Fraction& xFact, const Fraction& yFact)
{
NbcResize( rRef, xFact, yFact );
SetChanged();
GetFmt()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false);
}
Pointer __EXPORT SwVirtFlyDrawObj::GetMacroPointer(
const SdrObjMacroHitRec& ) const
{
return Pointer( POINTER_REFHAND );
}
FASTBOOL __EXPORT SwVirtFlyDrawObj::HasMacro() const
{
const SwFmtURL &rURL = pFlyFrm->GetFmt()->GetURL();
return rURL.GetMap() || rURL.GetURL().Len();
}
SdrObject* SwVirtFlyDrawObj::CheckMacroHit( const SdrObjMacroHitRec& rRec ) const
{
const SwFmtURL &rURL = pFlyFrm->GetFmt()->GetURL();
if( rURL.GetMap() || rURL.GetURL().Len() )
{
SwRect aRect;
if ( pFlyFrm->Lower() && pFlyFrm->Lower()->IsNoTxtFrm() )
{
aRect = pFlyFrm->Prt();
aRect += pFlyFrm->Frm().Pos();
}
else
aRect = pFlyFrm->Frm();
if( aRect.IsInside( rRec.aPos ) )
{
SwRect aActRect( aRect );
Size aActSz( aRect.SSize() );
aRect.Pos().X() += rRec.nTol;
aRect.Pos().Y() += rRec.nTol;
aRect.SSize().Height()-= 2 * rRec.nTol;
aRect.SSize().Width() -= 2 * rRec.nTol;
if( aRect.IsInside( rRec.aPos ) )
{
if( !rURL.GetMap() ||
pFlyFrm->GetFmt()->GetIMapObject( rRec.aPos, pFlyFrm ))
return (SdrObject*)this;
return 0;
}
}
}
return SdrObject::CheckMacroHit( rRec );
}
bool SwVirtFlyDrawObj::supportsFullDrag() const
{
// call parent
return SdrVirtObj::supportsFullDrag();
}
SdrObject* SwVirtFlyDrawObj::getFullDragClone() const
{
// call parent
return SdrVirtObj::getFullDragClone();
}
// eof