2008/04/01 15:51:42 thb 1.29.194.3: #i85898# Stripping all external header guards 2008/04/01 12:50:01 thb 1.29.194.2: #i85898# Stripping all external header guards 2008/03/31 14:23:33 rt 1.29.194.1: #i87441# Change license header to LPGL v3.
860 lines
26 KiB
C++
860 lines
26 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: svdorect.cxx,v $
|
|
* $Revision: 1.30 $
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_svx.hxx"
|
|
|
|
#include <svx/svdorect.hxx>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <svx/xpool.hxx>
|
|
#include <svx/xpoly.hxx>
|
|
#include "svdxout.hxx"
|
|
#include <svx/svdattr.hxx>
|
|
#include <svx/svdpool.hxx>
|
|
#include "svdtouch.hxx"
|
|
#include <svx/svdtrans.hxx>
|
|
#include <svx/svdetc.hxx>
|
|
#include <svx/svddrag.hxx>
|
|
#include <svx/svdmodel.hxx>
|
|
#include <svx/svdpage.hxx>
|
|
#include <svx/svdocapt.hxx> // fuer Import von SdrFileVersion 2
|
|
#include <svx/svdpagv.hxx> // fuer
|
|
#include <svx/svdview.hxx> // das
|
|
#include <svx/svdundo.hxx> // Macro-Beispiel
|
|
#include <svx/svdopath.hxx>
|
|
#include "svdglob.hxx" // Stringcache
|
|
#include "svdstr.hrc" // Objektname
|
|
#include <svx/xflclit.hxx>
|
|
#include <svx/xlnclit.hxx>
|
|
#include <svx/xlnwtit.hxx>
|
|
#include "svdoimp.hxx"
|
|
#include <svx/sdr/properties/rectangleproperties.hxx>
|
|
#include <basegfx/polygon/b2dpolygon.hxx>
|
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
sdr::properties::BaseProperties* SdrRectObj::CreateObjectSpecificProperties()
|
|
{
|
|
return new sdr::properties::RectangleProperties(*this);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
TYPEINIT1(SdrRectObj,SdrTextObj);
|
|
|
|
SdrRectObj::SdrRectObj()
|
|
: mpXPoly(0L)
|
|
{
|
|
bClosedObj=TRUE;
|
|
}
|
|
|
|
SdrRectObj::SdrRectObj(const Rectangle& rRect)
|
|
: SdrTextObj(rRect),
|
|
mpXPoly(NULL)
|
|
{
|
|
bClosedObj=TRUE;
|
|
}
|
|
|
|
SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind)
|
|
: SdrTextObj(eNewTextKind),
|
|
mpXPoly(NULL)
|
|
{
|
|
DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT ||
|
|
eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT,
|
|
"SdrRectObj::SdrRectObj(SdrObjKind) ist nur fuer Textrahmen gedacht");
|
|
bClosedObj=TRUE;
|
|
}
|
|
|
|
SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind, const Rectangle& rRect)
|
|
: SdrTextObj(eNewTextKind,rRect),
|
|
mpXPoly(NULL)
|
|
{
|
|
DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT ||
|
|
eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT,
|
|
"SdrRectObj::SdrRectObj(SdrObjKind,...) ist nur fuer Textrahmen gedacht");
|
|
bClosedObj=TRUE;
|
|
}
|
|
|
|
SdrRectObj::SdrRectObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect, SvStream& rInput, const String& rBaseURL, USHORT eFormat)
|
|
: SdrTextObj(eNewTextKind,rNewRect,rInput,rBaseURL,eFormat),
|
|
mpXPoly(NULL)
|
|
{
|
|
DBG_ASSERT(eTextKind==OBJ_TEXT || eTextKind==OBJ_TEXTEXT ||
|
|
eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT,
|
|
"SdrRectObj::SdrRectObj(SdrObjKind,...) ist nur fuer Textrahmen gedacht");
|
|
bClosedObj=TRUE;
|
|
}
|
|
|
|
SdrRectObj::~SdrRectObj()
|
|
{
|
|
if(mpXPoly)
|
|
{
|
|
delete mpXPoly;
|
|
}
|
|
}
|
|
|
|
void SdrRectObj::SetXPolyDirty()
|
|
{
|
|
if(mpXPoly)
|
|
{
|
|
delete mpXPoly;
|
|
mpXPoly = 0L;
|
|
}
|
|
}
|
|
|
|
FASTBOOL SdrRectObj::PaintNeedsXPoly(long nEckRad) const
|
|
{
|
|
FASTBOOL bNeed=aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || nEckRad!=0;
|
|
return bNeed;
|
|
}
|
|
|
|
XPolygon SdrRectObj::ImpCalcXPoly(const Rectangle& rRect1, long nRad1) const
|
|
{
|
|
XPolygon aXPoly(rRect1,nRad1,nRad1);
|
|
const sal_uInt16 nPointAnz(aXPoly.GetPointCount());
|
|
XPolygon aNeuPoly(nPointAnz+1);
|
|
sal_uInt16 nShift=nPointAnz-2;
|
|
if (nRad1!=0) nShift=nPointAnz-5;
|
|
sal_uInt16 j=nShift;
|
|
for (sal_uInt16 i=1; i<nPointAnz; i++) {
|
|
aNeuPoly[i]=aXPoly[j];
|
|
aNeuPoly.SetFlags(i,aXPoly.GetFlags(j));
|
|
j++;
|
|
if (j>=nPointAnz) j=1;
|
|
}
|
|
aNeuPoly[0]=rRect1.BottomCenter();
|
|
aNeuPoly[nPointAnz]=aNeuPoly[0];
|
|
aXPoly=aNeuPoly;
|
|
|
|
// Die Winkelangaben beziehen sich immer auf die linke obere Ecke von !aRect!
|
|
if (aGeo.nShearWink!=0) ShearXPoly(aXPoly,aRect.TopLeft(),aGeo.nTan);
|
|
if (aGeo.nDrehWink!=0) RotateXPoly(aXPoly,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
|
|
return aXPoly;
|
|
}
|
|
|
|
void SdrRectObj::RecalcXPoly()
|
|
{
|
|
mpXPoly = new XPolygon(ImpCalcXPoly(aRect,GetEckenradius()));
|
|
}
|
|
|
|
const XPolygon& SdrRectObj::GetXPoly() const
|
|
{
|
|
if(!mpXPoly)
|
|
{
|
|
((SdrRectObj*)this)->RecalcXPoly();
|
|
}
|
|
|
|
return *mpXPoly;
|
|
}
|
|
|
|
void SdrRectObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
|
|
{
|
|
FASTBOOL bNoTextFrame=!IsTextFrame();
|
|
rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nDrehWink%9000==0;
|
|
rInfo.bResizePropAllowed=TRUE;
|
|
rInfo.bRotateFreeAllowed=TRUE;
|
|
rInfo.bRotate90Allowed =TRUE;
|
|
rInfo.bMirrorFreeAllowed=bNoTextFrame;
|
|
rInfo.bMirror45Allowed =bNoTextFrame;
|
|
rInfo.bMirror90Allowed =bNoTextFrame;
|
|
|
|
// allow transparence
|
|
rInfo.bTransparenceAllowed = TRUE;
|
|
|
|
// gradient depends on fillstyle
|
|
XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue();
|
|
rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT);
|
|
|
|
rInfo.bShearAllowed =bNoTextFrame;
|
|
rInfo.bEdgeRadiusAllowed=TRUE;
|
|
|
|
FASTBOOL bCanConv=!HasText() || ImpCanConvTextToCurve();
|
|
if (bCanConv && !bNoTextFrame && !HasText()) {
|
|
bCanConv=HasFill() || HasLine();
|
|
}
|
|
rInfo.bCanConvToPath =bCanConv;
|
|
rInfo.bCanConvToPoly =bCanConv;
|
|
rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
|
|
}
|
|
|
|
UINT16 SdrRectObj::GetObjIdentifier() const
|
|
{
|
|
if (IsTextFrame()) return UINT16(eTextKind);
|
|
else return UINT16(OBJ_RECT);
|
|
}
|
|
|
|
void SdrRectObj::RecalcBoundRect()
|
|
{
|
|
aOutRect=GetSnapRect();
|
|
long nLineWdt=ImpGetLineWdt();
|
|
|
|
// #i25616#
|
|
if(!LineIsOutsideGeometry())
|
|
{
|
|
nLineWdt++; nLineWdt/=2;
|
|
}
|
|
|
|
if (nLineWdt!=0) {
|
|
long a=nLineWdt;
|
|
if ((aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) && GetEckenradius()==0) {
|
|
a*=2; // doppelt, wegen evtl. spitzen Ecken
|
|
}
|
|
aOutRect.Left ()-=a;
|
|
aOutRect.Top ()-=a;
|
|
aOutRect.Right ()+=a;
|
|
aOutRect.Bottom()+=a;
|
|
}
|
|
ImpAddShadowToBoundRect();
|
|
ImpAddTextToBoundRect();
|
|
}
|
|
|
|
void SdrRectObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
|
|
{
|
|
rRect=aRect;
|
|
if (aGeo.nShearWink!=0) {
|
|
long nDst=Round((aRect.Bottom()-aRect.Top())*aGeo.nTan);
|
|
if (aGeo.nShearWink>0) {
|
|
Point aRef(rRect.TopLeft());
|
|
rRect.Left()-=nDst;
|
|
Point aTmpPt(rRect.TopLeft());
|
|
RotatePoint(aTmpPt,aRef,aGeo.nSin,aGeo.nCos);
|
|
aTmpPt-=rRect.TopLeft();
|
|
rRect.Move(aTmpPt.X(),aTmpPt.Y());
|
|
} else {
|
|
rRect.Right()-=nDst;
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// #i25616#
|
|
|
|
void SdrRectObj::ImpDoPaintRectObjShadow(XOutputDevice& rXOut, sal_Bool bPaintFill, sal_Bool bPaintLine) const
|
|
{
|
|
const bool bHideContour(IsHideContour());
|
|
const SfxItemSet& rSet = GetObjectItemSet();
|
|
SfxItemSet aShadowSet(rSet);
|
|
|
|
if(!bHideContour && ImpSetShadowAttributes(rSet, aShadowSet))
|
|
{
|
|
// perepare ItemSet to avoid old XOut line drawing
|
|
SfxItemSet aEmptySet(*rSet.GetPool());
|
|
aEmptySet.Put(XLineStyleItem(XLINE_NONE));
|
|
aEmptySet.Put(XFillStyleItem(XFILL_NONE));
|
|
rXOut.SetFillAttr(aShadowSet);
|
|
|
|
sal_uInt32 nXDist(((SdrShadowXDistItem&)(rSet.Get(SDRATTR_SHADOWXDIST))).GetValue());
|
|
sal_uInt32 nYDist(((SdrShadowYDistItem&)(rSet.Get(SDRATTR_SHADOWYDIST))).GetValue());
|
|
|
|
// avoid shadow line drawing in XOut
|
|
rXOut.SetLineAttr(aEmptySet);
|
|
|
|
if(bPaintFill)
|
|
{
|
|
// #100127# Output original geometry for metafiles
|
|
ImpGraphicFill aFill( *this, rXOut, aShadowSet, true );
|
|
const sal_Int32 nEckRad(GetEckenradius());
|
|
|
|
if (PaintNeedsXPoly(nEckRad))
|
|
{
|
|
XPolygon aX(GetXPoly());
|
|
aX.Move(nXDist,nYDist);
|
|
rXOut.DrawPolygon(aX.getB2DPolygon());
|
|
}
|
|
else
|
|
{
|
|
Rectangle aR(aRect);
|
|
aR.Move(nXDist,nYDist);
|
|
rXOut.DrawRect(aR,USHORT(2*nEckRad),USHORT(2*nEckRad));
|
|
}
|
|
}
|
|
|
|
if(bPaintLine)
|
|
{
|
|
// prepare line geometry
|
|
// #b4899532# if not filled but fill draft, avoid object being invisible in using
|
|
// a hair linestyle and COL_LIGHTGRAY
|
|
SfxItemSet aItemSet(rSet);
|
|
|
|
// prepare line geometry
|
|
::std::auto_ptr< SdrLineGeometry > pLineGeometry(ImpPrepareLineGeometry(rXOut, aItemSet));
|
|
|
|
// new shadow line drawing
|
|
if( pLineGeometry.get() )
|
|
{
|
|
// draw the line geometry
|
|
ImpDrawShadowLineGeometry(rXOut, aItemSet, *pLineGeometry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// #i25616#
|
|
|
|
void SdrRectObj::ImpDoPaintRectObj(XOutputDevice& rXOut, sal_Bool bPaintFill, sal_Bool bPaintLine) const
|
|
{
|
|
const bool bHideContour(IsHideContour());
|
|
|
|
if(!bHideContour)
|
|
{
|
|
// prepare ItemSet of this object
|
|
const SfxItemSet& rSet = GetObjectItemSet();
|
|
|
|
// perepare ItemSet to avoid old XOut line drawing
|
|
SfxItemSet aEmptySet(*rSet.GetPool());
|
|
aEmptySet.Put(XLineStyleItem(XLINE_NONE));
|
|
aEmptySet.Put(XFillStyleItem(XFILL_NONE));
|
|
|
|
// Before here the LineAttr were set: if(pLineAttr) rXOut.SetLineAttr(*pLineAttr);
|
|
rXOut.SetLineAttr(aEmptySet);
|
|
rXOut.SetFillAttr( rSet );
|
|
|
|
if (!bHideContour && bPaintFill)
|
|
{
|
|
// #100127# Output original geometry for metafiles
|
|
ImpGraphicFill aFill( *this, rXOut, rSet );
|
|
const sal_Int32 nEckRad(GetEckenradius());
|
|
|
|
if (PaintNeedsXPoly(nEckRad))
|
|
{
|
|
rXOut.DrawPolygon(GetXPoly().getB2DPolygon());
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT(nEckRad==0,"SdrRectObj::DoPaintObject(): XOut.DrawRect() unterstuetz kein Eckenradius!");
|
|
rXOut.DrawRect(aRect/*,USHORT(2*nEckRad),USHORT(2*nEckRad)*/);
|
|
}
|
|
}
|
|
|
|
DBG_ASSERT(aRect.GetWidth()>1 && aRect.GetHeight()>1,"SdrRectObj::DoPaintObject(): Rect hat Nullgroesse (oder negativ)!");
|
|
|
|
// Own line drawing
|
|
if( !bHideContour && bPaintLine)
|
|
{
|
|
// prepare line geometry
|
|
// #b4899532# if not filled but fill draft, avoid object being invisible in using
|
|
// a hair linestyle and COL_LIGHTGRAY
|
|
SfxItemSet aItemSet(rSet);
|
|
|
|
// prepare line geometry
|
|
::std::auto_ptr< SdrLineGeometry > pLineGeometry( ImpPrepareLineGeometry(rXOut, aItemSet) );
|
|
|
|
if( pLineGeometry.get() )
|
|
{
|
|
// draw the line geometry
|
|
ImpDrawColorLineGeometry(rXOut, aItemSet, *pLineGeometry);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
sal_Bool SdrRectObj::DoPaintObject(XOutputDevice& rXOut, const SdrPaintInfoRec& rInfoRec) const
|
|
{
|
|
if (bTextFrame && aGeo.nShearWink!=0) {
|
|
DBG_WARNING("Shearwinkel vom TextFrame innerhalb von SdrRectObj::DoPaintObject() auf 0 gesetzt");
|
|
((SdrRectObj*)this)->ImpCheckShear();
|
|
((SdrRectObj*)this)->SetRectsDirty();
|
|
}
|
|
|
|
sal_Bool bOk(sal_True);
|
|
|
|
// draw shadow
|
|
ImpDoPaintRectObjShadow(rXOut, sal_True, sal_True);
|
|
|
|
// draw geometry
|
|
ImpDoPaintRectObj(rXOut, sal_True, sal_True);
|
|
|
|
// draw text
|
|
if(HasText() && !LineIsOutsideGeometry())
|
|
{
|
|
bOk = SdrTextObj::DoPaintObject(rXOut,rInfoRec);
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
|
|
SdrObject* SdrRectObj::ImpCheckHit(const Point& rPnt, USHORT nTol, const SetOfByte* pVisiLayer, FASTBOOL bForceFilled, FASTBOOL bForceTol) const
|
|
{
|
|
if(pVisiLayer && !pVisiLayer->IsSet(sal::static_int_cast< sal_uInt8 >(GetLayer())))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
INT32 nMyTol=nTol;
|
|
FASTBOOL bFilled=bForceFilled || HasFill();
|
|
FASTBOOL bPickThrough=pModel!=NULL && pModel->IsPickThroughTransparentTextFrames();
|
|
if (bTextFrame && !bPickThrough) bFilled=TRUE;
|
|
FASTBOOL bLine=HasLine();
|
|
|
|
INT32 nWdt=bLine ? ImpGetLineWdt() :0; // Halbe Strichstaerke
|
|
|
|
// #i25616#
|
|
if(nWdt && !LineIsOutsideGeometry())
|
|
{
|
|
nWdt /= 2;
|
|
}
|
|
|
|
long nBoundWdt=aRect.GetWidth()-1;
|
|
long nBoundHgt=aRect.GetHeight()-1;
|
|
if (bFilled && nBoundWdt>short(nTol) && nBoundHgt>short(nTol) && Abs(aGeo.nShearWink)<=4500) {
|
|
if (!bForceTol && !bTextFrame ) nMyTol=0; // Keine Toleranz noetig hier
|
|
}
|
|
if (nWdt>nMyTol && (!bTextFrame || pEdtOutl==NULL)) nMyTol=nWdt; // Bei dicker Umrandung keine Toleranz noetig, ausser wenn bei TextEdit
|
|
Rectangle aR(aRect);
|
|
if (nMyTol!=0 && bFilled) {
|
|
aR.Left ()-=nMyTol;
|
|
aR.Top ()-=nMyTol;
|
|
aR.Right ()+=nMyTol;
|
|
aR.Bottom()+=nMyTol;
|
|
}
|
|
|
|
if (bFilled || bLine || bTextFrame) { // Bei TextFrame so tun, alsob Linie da
|
|
unsigned nCnt=0;
|
|
INT32 nXShad=0,nYShad=0;
|
|
long nEckRad=/*bTextFrame ? 0 :*/ GetEckenradius();
|
|
do { // 1 Durchlauf, bei Schatten 2 Durchlaeufe.
|
|
if (nCnt!=0) aR.Move(nXShad,nYShad);
|
|
if (aGeo.nDrehWink!=0 || aGeo.nShearWink!=0 || nEckRad!=0 || !bFilled) {
|
|
Polygon aPol(aR);
|
|
if (nEckRad!=0) {
|
|
INT32 nRad=nEckRad;
|
|
if (bFilled) nRad+=nMyTol; // um korrekt zu sein ...
|
|
XPolygon aXPoly(ImpCalcXPoly(aR,nRad));
|
|
aPol = Polygon(basegfx::tools::adaptiveSubdivideByAngle(aXPoly.getB2DPolygon()));
|
|
} else {
|
|
if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan);
|
|
if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
|
|
}
|
|
if (bFilled) {
|
|
if (IsPointInsidePoly(aPol,rPnt)) return (SdrObject*)this;
|
|
} else {
|
|
Rectangle aTouchRect(rPnt.X()-nMyTol,rPnt.Y()-nMyTol,rPnt.X()+nMyTol,rPnt.Y()+nMyTol);
|
|
if (IsRectTouchesLine(aPol,aTouchRect)) return (SdrObject*)this;
|
|
}
|
|
} else {
|
|
if (aR.IsInside(rPnt)) return (SdrObject*)this;
|
|
}
|
|
} while (nCnt++==0 && ImpGetShadowDist(nXShad,nYShad));
|
|
}
|
|
FASTBOOL bCheckText=TRUE;
|
|
if (bCheckText && HasText() && (!bTextFrame || bPickThrough)) {
|
|
return SdrTextObj::CheckHit(rPnt,nTol,pVisiLayer);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SdrObject* SdrRectObj::CheckHit(const Point& rPnt, USHORT nTol, const SetOfByte* pVisiLayer) const
|
|
{
|
|
return ImpCheckHit(rPnt,nTol,pVisiLayer,FALSE/*,bTextFrame*/);
|
|
}
|
|
|
|
void SdrRectObj::TakeObjNameSingul(XubString& rName) const
|
|
{
|
|
if (IsTextFrame())
|
|
{
|
|
SdrTextObj::TakeObjNameSingul(rName);
|
|
}
|
|
else
|
|
{
|
|
USHORT nResId=STR_ObjNameSingulRECT;
|
|
if (aGeo.nShearWink!=0) {
|
|
nResId+=4; // Parallelogramm oder Raute
|
|
// Raute ist nicht, weil Shear die vertikalen Kanten verlaengert!
|
|
// Wenn Zeit ist, werde ich das mal berechnen.
|
|
} else {
|
|
if (aRect.GetWidth()==aRect.GetHeight()) nResId+=2; // Quadrat
|
|
}
|
|
if (GetEckenradius()!=0) nResId+=8; // abgerundet
|
|
rName=ImpGetResStr(nResId);
|
|
|
|
String aName( GetName() );
|
|
if(aName.Len())
|
|
{
|
|
rName += sal_Unicode(' ');
|
|
rName += sal_Unicode('\'');
|
|
rName += aName;
|
|
rName += sal_Unicode('\'');
|
|
}
|
|
}
|
|
}
|
|
|
|
void SdrRectObj::TakeObjNamePlural(XubString& rName) const
|
|
{
|
|
if (IsTextFrame()) SdrTextObj::TakeObjNamePlural(rName);
|
|
else {
|
|
USHORT nResId=STR_ObjNamePluralRECT;
|
|
if (aGeo.nShearWink!=0) {
|
|
nResId+=4; // Parallelogramm oder Raute
|
|
} else {
|
|
if (aRect.GetWidth()==aRect.GetHeight()) nResId+=2; // Quadrat
|
|
}
|
|
if (GetEckenradius()!=0) nResId+=8; // abgerundet
|
|
rName=ImpGetResStr(nResId);
|
|
}
|
|
}
|
|
|
|
void SdrRectObj::operator=(const SdrObject& rObj)
|
|
{
|
|
SdrTextObj::operator=(rObj);
|
|
}
|
|
|
|
basegfx::B2DPolyPolygon SdrRectObj::TakeXorPoly(sal_Bool /*bDetail*/) const
|
|
{
|
|
XPolyPolygon aXPP;
|
|
aXPP.Insert(ImpCalcXPoly(aRect,GetEckenradius()));
|
|
return aXPP.getB2DPolyPolygon();
|
|
}
|
|
|
|
void SdrRectObj::RecalcSnapRect()
|
|
{
|
|
long nEckRad=GetEckenradius();
|
|
if ((aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) && nEckRad!=0) {
|
|
maSnapRect=GetXPoly().GetBoundRect();
|
|
} else {
|
|
SdrTextObj::RecalcSnapRect();
|
|
}
|
|
}
|
|
|
|
void SdrRectObj::NbcSetSnapRect(const Rectangle& rRect)
|
|
{
|
|
SdrTextObj::NbcSetSnapRect(rRect);
|
|
SetXPolyDirty();
|
|
}
|
|
|
|
void SdrRectObj::NbcSetLogicRect(const Rectangle& rRect)
|
|
{
|
|
SdrTextObj::NbcSetLogicRect(rRect);
|
|
SetXPolyDirty();
|
|
}
|
|
|
|
sal_uInt32 SdrRectObj::GetHdlCount() const
|
|
{
|
|
return 9L;
|
|
}
|
|
|
|
SdrHdl* SdrRectObj::GetHdl(sal_uInt32 nHdlNum) const
|
|
{
|
|
SdrHdl* pH=NULL;
|
|
Point aPnt;
|
|
SdrHdlKind eKind=HDL_MOVE;
|
|
switch (nHdlNum) {
|
|
case 0: {
|
|
long a=GetEckenradius();
|
|
long b=Max(aRect.GetWidth(),aRect.GetHeight())/2; // Wird aufgerundet, da GetWidth() eins draufaddiert
|
|
if (a>b) a=b;
|
|
if (a<0) a=0;
|
|
aPnt=aRect.TopLeft();
|
|
aPnt.X()+=a;
|
|
eKind=HDL_CIRC;
|
|
} break; // Eckenradius
|
|
case 1: aPnt=aRect.TopLeft(); eKind=HDL_UPLFT; break; // Oben links
|
|
case 2: aPnt=aRect.TopCenter(); eKind=HDL_UPPER; break; // Oben
|
|
case 3: aPnt=aRect.TopRight(); eKind=HDL_UPRGT; break; // Oben rechts
|
|
case 4: aPnt=aRect.LeftCenter(); eKind=HDL_LEFT ; break; // Links
|
|
case 5: aPnt=aRect.RightCenter(); eKind=HDL_RIGHT; break; // Rechts
|
|
case 6: aPnt=aRect.BottomLeft(); eKind=HDL_LWLFT; break; // Unten links
|
|
case 7: aPnt=aRect.BottomCenter(); eKind=HDL_LOWER; break; // Unten
|
|
case 8: aPnt=aRect.BottomRight(); eKind=HDL_LWRGT; break; // Unten rechts
|
|
}
|
|
if (aGeo.nShearWink!=0) ShearPoint(aPnt,aRect.TopLeft(),aGeo.nTan);
|
|
if (aGeo.nDrehWink!=0) RotatePoint(aPnt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
|
|
if (eKind!=HDL_MOVE) {
|
|
pH=new SdrHdl(aPnt,eKind);
|
|
pH->SetObj((SdrObject*)this);
|
|
pH->SetDrehWink(aGeo.nDrehWink);
|
|
}
|
|
return pH;
|
|
}
|
|
|
|
FASTBOOL SdrRectObj::HasSpecialDrag() const
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
FASTBOOL SdrRectObj::BegDrag(SdrDragStat& rDrag) const
|
|
{
|
|
FASTBOOL bRad=rDrag.GetHdl()!=NULL && rDrag.GetHdl()->GetKind()==HDL_CIRC;
|
|
if (bRad) {
|
|
rDrag.SetEndDragChangesAttributes(TRUE);
|
|
return TRUE;
|
|
} else {
|
|
return SdrTextObj::BegDrag(rDrag);
|
|
}
|
|
}
|
|
|
|
FASTBOOL SdrRectObj::MovDrag(SdrDragStat& rDrag) const
|
|
{
|
|
FASTBOOL bRad=rDrag.GetHdl()!=NULL && rDrag.GetHdl()->GetKind()==HDL_CIRC;
|
|
if (bRad) {
|
|
return TRUE;
|
|
} else {
|
|
return SdrTextObj::MovDrag(rDrag);
|
|
}
|
|
}
|
|
|
|
FASTBOOL SdrRectObj::EndDrag(SdrDragStat& rDrag)
|
|
{
|
|
FASTBOOL bRad=rDrag.GetHdl()!=NULL && rDrag.GetHdl()->GetKind()==HDL_CIRC;
|
|
if (bRad) {
|
|
Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
|
|
// #110094#-14 SendRepaintBroadcast();
|
|
Point aPt(rDrag.GetNow());
|
|
if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); // -sin fuer Umkehrung
|
|
// Shear nicht noetig, da Pt auf einer Linie mit dem RefPt (LiOb Ecke des Rect)
|
|
long nRad=aPt.X()-aRect.Left();
|
|
if (nRad<0) nRad=0;
|
|
long nAltRad=GetEckenradius();
|
|
if (nRad!=nAltRad) NbcSetEckenradius(nRad);
|
|
SetChanged();
|
|
SetRectsDirty();
|
|
SetXPolyDirty();
|
|
BroadcastObjectChange();
|
|
SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
|
|
return TRUE;
|
|
} else {
|
|
return SdrTextObj::EndDrag(rDrag);
|
|
}
|
|
}
|
|
|
|
void SdrRectObj::BrkDrag(SdrDragStat& rDrag) const
|
|
{
|
|
FASTBOOL bRad=rDrag.GetHdl()!=NULL && rDrag.GetHdl()->GetKind()==HDL_CIRC;
|
|
if (bRad) {
|
|
} else {
|
|
SdrTextObj::BrkDrag(rDrag);
|
|
}
|
|
}
|
|
|
|
XubString SdrRectObj::GetDragComment(const SdrDragStat& rDrag, FASTBOOL bUndoDragComment, FASTBOOL bCreateComment) const
|
|
{
|
|
if(bCreateComment)
|
|
return String();
|
|
|
|
BOOL bRad(rDrag.GetHdl() && rDrag.GetHdl()->GetKind() == HDL_CIRC);
|
|
|
|
if(bRad)
|
|
{
|
|
Point aPt(rDrag.GetNow());
|
|
|
|
// -sin fuer Umkehrung
|
|
if(aGeo.nDrehWink)
|
|
RotatePoint(aPt, aRect.TopLeft(), -aGeo.nSin, aGeo.nCos);
|
|
|
|
INT32 nRad(aPt.X() - aRect.Left());
|
|
|
|
if(nRad < 0)
|
|
nRad = 0;
|
|
|
|
XubString aStr;
|
|
|
|
ImpTakeDescriptionStr(STR_DragRectEckRad, aStr);
|
|
aStr.AppendAscii(" (");
|
|
aStr += GetMetrStr(nRad);
|
|
aStr += sal_Unicode(')');
|
|
|
|
return aStr;
|
|
}
|
|
else
|
|
{
|
|
return SdrTextObj::GetDragComment(rDrag, bUndoDragComment, FALSE);
|
|
}
|
|
}
|
|
|
|
basegfx::B2DPolyPolygon SdrRectObj::TakeDragPoly(const SdrDragStat& rDrag) const
|
|
{
|
|
XPolyPolygon aXPP;
|
|
const bool bRad(rDrag.GetHdl() && HDL_CIRC == rDrag.GetHdl()->GetKind());
|
|
|
|
if(bRad)
|
|
{
|
|
Point aPt(rDrag.GetNow());
|
|
if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),-aGeo.nSin,aGeo.nCos); // -sin fuer Umkehrung
|
|
// Shear nicht noetig, da Pt auf einer Linie mit dem RefPt (LiOb Ecke des Rect)
|
|
long nRad=aPt.X()-aRect.Left();
|
|
if (nRad<0) nRad=0;
|
|
aXPP.Insert(ImpCalcXPoly(aRect,nRad));
|
|
}
|
|
else
|
|
{
|
|
aXPP.Insert(ImpCalcXPoly(ImpDragCalcRect(rDrag),GetEckenradius()));
|
|
}
|
|
|
|
return aXPP.getB2DPolyPolygon();
|
|
}
|
|
|
|
basegfx::B2DPolyPolygon SdrRectObj::TakeCreatePoly(const SdrDragStat& rDrag) const
|
|
{
|
|
Rectangle aRect1;
|
|
rDrag.TakeCreateRect(aRect1);
|
|
aRect1.Justify();
|
|
|
|
basegfx::B2DPolyPolygon aRetval;
|
|
aRetval.append(ImpCalcXPoly(aRect1,GetEckenradius()).getB2DPolygon());
|
|
return aRetval;
|
|
}
|
|
|
|
Pointer SdrRectObj::GetCreatePointer() const
|
|
{
|
|
if (IsTextFrame()) return Pointer(POINTER_DRAW_TEXT);
|
|
return Pointer(POINTER_DRAW_RECT);
|
|
}
|
|
|
|
void SdrRectObj::NbcMove(const Size& rSiz)
|
|
{
|
|
SdrTextObj::NbcMove(rSiz);
|
|
SetXPolyDirty();
|
|
}
|
|
|
|
void SdrRectObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
|
|
{
|
|
SdrTextObj::NbcResize(rRef,xFact,yFact);
|
|
SetXPolyDirty();
|
|
}
|
|
|
|
void SdrRectObj::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
|
|
{
|
|
SdrTextObj::NbcRotate(rRef,nWink,sn,cs);
|
|
SetXPolyDirty();
|
|
}
|
|
|
|
void SdrRectObj::NbcShear(const Point& rRef, long nWink, double tn, FASTBOOL bVShear)
|
|
{
|
|
SdrTextObj::NbcShear(rRef,nWink,tn,bVShear);
|
|
SetXPolyDirty();
|
|
}
|
|
|
|
void SdrRectObj::NbcMirror(const Point& rRef1, const Point& rRef2)
|
|
{
|
|
SdrTextObj::NbcMirror(rRef1,rRef2);
|
|
SetXPolyDirty();
|
|
}
|
|
|
|
FASTBOOL SdrRectObj::DoMacro(const SdrObjMacroHitRec& rRec)
|
|
{
|
|
return SdrTextObj::DoMacro(rRec);
|
|
}
|
|
|
|
XubString SdrRectObj::GetMacroPopupComment(const SdrObjMacroHitRec& rRec) const
|
|
{
|
|
return SdrTextObj::GetMacroPopupComment(rRec);
|
|
}
|
|
|
|
SdrGluePoint SdrRectObj::GetVertexGluePoint(USHORT nPosNum) const
|
|
{
|
|
INT32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue();
|
|
|
|
// #i25616#
|
|
if(!LineIsOutsideGeometry())
|
|
{
|
|
nWdt++;
|
|
nWdt /= 2;
|
|
}
|
|
|
|
Point aPt;
|
|
switch (nPosNum) {
|
|
case 0: aPt=aRect.TopCenter(); aPt.Y()-=nWdt; break;
|
|
case 1: aPt=aRect.RightCenter(); aPt.X()+=nWdt; break;
|
|
case 2: aPt=aRect.BottomCenter(); aPt.Y()+=nWdt; break;
|
|
case 3: aPt=aRect.LeftCenter(); aPt.X()-=nWdt; break;
|
|
}
|
|
if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan);
|
|
if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
|
|
aPt-=GetSnapRect().Center();
|
|
SdrGluePoint aGP(aPt);
|
|
aGP.SetPercent(FALSE);
|
|
return aGP;
|
|
}
|
|
|
|
SdrGluePoint SdrRectObj::GetCornerGluePoint(USHORT nPosNum) const
|
|
{
|
|
INT32 nWdt = ImpGetLineWdt(); // #i25616# ((XLineWidthItem&)(GetObjectItem(XATTR_LINEWIDTH))).GetValue();
|
|
|
|
// #i25616#
|
|
if(!LineIsOutsideGeometry())
|
|
{
|
|
nWdt++;
|
|
nWdt /= 2;
|
|
}
|
|
|
|
Point aPt;
|
|
switch (nPosNum) {
|
|
case 0: aPt=aRect.TopLeft(); aPt.X()-=nWdt; aPt.Y()-=nWdt; break;
|
|
case 1: aPt=aRect.TopRight(); aPt.X()+=nWdt; aPt.Y()-=nWdt; break;
|
|
case 2: aPt=aRect.BottomRight(); aPt.X()+=nWdt; aPt.Y()+=nWdt; break;
|
|
case 3: aPt=aRect.BottomLeft(); aPt.X()-=nWdt; aPt.Y()+=nWdt; break;
|
|
}
|
|
if (aGeo.nShearWink!=0) ShearPoint(aPt,aRect.TopLeft(),aGeo.nTan);
|
|
if (aGeo.nDrehWink!=0) RotatePoint(aPt,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
|
|
aPt-=GetSnapRect().Center();
|
|
SdrGluePoint aGP(aPt);
|
|
aGP.SetPercent(FALSE);
|
|
return aGP;
|
|
}
|
|
|
|
SdrObject* SdrRectObj::DoConvertToPolyObj(BOOL bBezier) const
|
|
{
|
|
XPolygon aXP(ImpCalcXPoly(aRect,GetEckenradius()));
|
|
{ // #40608# Nur Uebergangsweise bis zum neuen TakeContour()
|
|
aXP.Remove(0,1);
|
|
aXP[aXP.GetPointCount()-1]=aXP[0];
|
|
}
|
|
|
|
basegfx::B2DPolyPolygon aPolyPolygon(aXP.getB2DPolygon());
|
|
SdrObject* pRet = 0L;
|
|
|
|
if(!IsTextFrame() || HasFill() || HasLine())
|
|
{
|
|
pRet = ImpConvertMakeObj(aPolyPolygon, sal_True, bBezier);
|
|
}
|
|
|
|
pRet = ImpConvertAddText(pRet, bBezier);
|
|
|
|
return pRet;
|
|
}
|
|
|
|
void SdrRectObj::SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType, const SfxHint& rHint, const TypeId& rHintType)
|
|
{
|
|
SdrTextObj::SFX_NOTIFY(rBC,rBCType,rHint,rHintType);
|
|
SetXPolyDirty(); // wg. Eckenradius
|
|
}
|
|
|
|
void SdrRectObj::RestGeoData(const SdrObjGeoData& rGeo)
|
|
{
|
|
SdrTextObj::RestGeoData(rGeo);
|
|
SetXPolyDirty();
|
|
}
|
|
|
|
// eof
|