Until now the 'local' StyleSheet got set, but that may not be the same as the original. It was/gets identified just by searching by name and type, not comparing content. What to do? We could... (a) the Style-Friendly way: - check if StyleSheet is identical - if not, create a new in-between StyleSheet hosting missing Items - if yes, use, done. (b) the pragmatic/practical way: - Just hard-attribute the Items that are detected as different similar to what BurnInStyleSheetAttributes does/did, but only for a view differing Items (b) is the most simple for now, but will lead to more hard attributes. The other possibilities will be better in the long term. For now, I will use (b). Note that there are more cases in that VERY complex and grown stuff emerging from SdDrawDocument::PasteBookmarkAsPage. More things will need to be fixed, see this as a 1st step. Needed to adapt postProcessAfterCloneToDifferentModel due to UT testTdf96206 failing, see comment there for details. That 1st implementation showed weaknesses with those Items critical and only on MasterPages, so decided to give up on that and implement ContentCompare to SdPage::Equals. That was easier than thought: No parameter needed, only used by InsertBookmarkAsPage_FindDuplicateLayouts::operator(). Thus, SdPage::Equals needs no change, just SdrObject::Equals. Due to still problems with Items corrected in Objects on MasterPages I will for now exclude this. Could now isolate remaining problems, these are defaults and/or PresObj things on MasterPages. Important is that I can completely correct all Items for all Objects in postProcessAfterCloneToDifferentModel. I can react to these false-positives in the ContentCompare in SdrObject::Equals. Signed-off-by: Armin Le Grand (collabora) <Armin.LeGrand@collabora.com> Change-Id: I10e17c8d6a893dbe92ab716182f07bafce1f3284 Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/6595 Tested-by: Jenkins CPCI <releng@collaboraoffice.com> Reviewed-by: Armin Le Grand <armin.legrand@collabora.com> (cherry picked from commit 92ffaeac04c5c8586006b026f29ce12fba3674f1) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211729 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
1427 lines
48 KiB
C++
1427 lines
48 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <svx/dialmgr.hxx>
|
|
#include <svx/strings.hrc>
|
|
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
|
#include <basegfx/point/b2dpoint.hxx>
|
|
#include <basegfx/polygon/b2dpolygon.hxx>
|
|
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
|
#include <editeng/editdata.hxx>
|
|
#include <editeng/editobj.hxx>
|
|
#include <editeng/eeitem.hxx>
|
|
#include <editeng/flditem.hxx>
|
|
#include <editeng/measfld.hxx>
|
|
#include <editeng/outlobj.hxx>
|
|
#include <math.h>
|
|
#include <svl/style.hxx>
|
|
|
|
#include <sdr/contact/viewcontactofsdrmeasureobj.hxx>
|
|
#include <sdr/properties/measureproperties.hxx>
|
|
#include <svx/svddrag.hxx>
|
|
#include <svx/svdhdl.hxx>
|
|
#include <svx/svdmodel.hxx>
|
|
#include <svx/svdogrp.hxx>
|
|
#include <svx/svdomeas.hxx>
|
|
#include <svx/svdopath.hxx>
|
|
#include <svx/svdoutl.hxx>
|
|
#include <svx/svdpage.hxx>
|
|
#include <svx/svdtrans.hxx>
|
|
#include <svx/svdview.hxx>
|
|
#include <svx/sxmbritm.hxx>
|
|
#include <svx/sxmlhitm.hxx>
|
|
#include <sxmsitm.hxx>
|
|
#include <sxmtaitm.hxx>
|
|
#include <svx/sxmtfitm.hxx>
|
|
#include <svx/sxmtpitm.hxx>
|
|
#include <svx/sxmtritm.hxx>
|
|
#include <svx/sxmuitm.hxx>
|
|
#include <svx/xlnedcit.hxx>
|
|
#include <svx/xlnedit.hxx>
|
|
#include <svx/xlnedwit.hxx>
|
|
#include <svx/xlnstcit.hxx>
|
|
#include <svx/xlnstit.hxx>
|
|
#include <svx/xlnstwit.hxx>
|
|
#include <svx/xlnwtit.hxx>
|
|
#include <svx/xpoly.hxx>
|
|
#include <unotools/syslocale.hxx>
|
|
#include <unotools/localedatawrapper.hxx>
|
|
#include <vcl/ptrstyle.hxx>
|
|
|
|
|
|
SdrMeasureObjGeoData::SdrMeasureObjGeoData() {}
|
|
SdrMeasureObjGeoData::~SdrMeasureObjGeoData() {}
|
|
|
|
OUString SdrMeasureObj::TakeRepresentation(SdrMeasureFieldKind eMeasureFieldKind) const
|
|
{
|
|
OUString aStr;
|
|
double fMeasureScale = 1.0;
|
|
bool bTextRota90(false);
|
|
bool bShowUnit(false);
|
|
FieldUnit eMeasureUnit(FieldUnit::NONE);
|
|
FieldUnit eModUIUnit(FieldUnit::NONE);
|
|
|
|
const SfxItemSet& rSet = GetMergedItemSet();
|
|
bTextRota90 = rSet.Get(SDRATTR_MEASURETEXTROTA90).GetValue();
|
|
eMeasureUnit = rSet.Get(SDRATTR_MEASUREUNIT).GetValue();
|
|
fMeasureScale = rSet.Get(SDRATTR_MEASURESCALE).GetValue();
|
|
bShowUnit = rSet.Get(SDRATTR_MEASURESHOWUNIT).GetValue();
|
|
sal_Int16 nNumDigits = rSet.Get(SDRATTR_MEASUREDECIMALPLACES).GetValue();
|
|
|
|
switch(eMeasureFieldKind)
|
|
{
|
|
case SdrMeasureFieldKind::Value:
|
|
{
|
|
eModUIUnit = getSdrModelFromSdrObject().GetUIUnit();
|
|
|
|
if(eMeasureUnit == FieldUnit::NONE)
|
|
eMeasureUnit = eModUIUnit;
|
|
|
|
sal_Int32 nLen(GetLen(m_aPt2 - m_aPt1));
|
|
double fFact = 1.0;
|
|
|
|
if(eMeasureUnit != eModUIUnit)
|
|
{
|
|
// for the unit conversion
|
|
fFact *= GetMapFactor(eModUIUnit, eMeasureUnit).X();
|
|
}
|
|
|
|
if(fMeasureScale != 1.0)
|
|
{
|
|
fFact *= fMeasureScale;
|
|
}
|
|
|
|
if(fFact != 1.0)
|
|
{
|
|
nLen = nLen * fFact;
|
|
}
|
|
|
|
aStr = getSdrModelFromSdrObject().GetMetricString(nLen, true, nNumDigits);
|
|
|
|
// tdf#138414 - respect decimal precision for dimension lines
|
|
const auto bAutoNumDigits = rSet.Get(SDRATTR_MEASUREAUTODECIMALPLACES).GetValue();
|
|
if (bAutoNumDigits)
|
|
{
|
|
SvtSysLocale aSysLocale;
|
|
const LocaleDataWrapper& rLocaleDataWrapper = aSysLocale.GetLocaleData();
|
|
sal_Unicode cDec(rLocaleDataWrapper.getNumDecimalSep()[0]);
|
|
sal_Unicode cDecAlt(rLocaleDataWrapper.getNumDecimalSepAlt().toChar());
|
|
|
|
if (aStr.indexOf(cDec) != -1 || (cDecAlt && aStr.indexOf(cDecAlt) != -1))
|
|
{
|
|
sal_Int32 nLen2(aStr.getLength() - 1);
|
|
|
|
while (aStr[nLen2] == '0')
|
|
{
|
|
aStr = aStr.copy(0, nLen2);
|
|
nLen2--;
|
|
}
|
|
|
|
if (aStr[nLen2] == cDec || (cDecAlt && aStr[nLen2] == cDecAlt))
|
|
{
|
|
aStr = aStr.copy(0, nLen2);
|
|
nLen2--;
|
|
}
|
|
|
|
if (aStr.isEmpty())
|
|
aStr += "0";
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case SdrMeasureFieldKind::Unit:
|
|
{
|
|
if(bShowUnit)
|
|
{
|
|
eModUIUnit = getSdrModelFromSdrObject().GetUIUnit();
|
|
|
|
if(eMeasureUnit == FieldUnit::NONE)
|
|
eMeasureUnit = eModUIUnit;
|
|
|
|
aStr = SdrModel::GetUnitString(eMeasureUnit);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case SdrMeasureFieldKind::Rotate90Blanks:
|
|
{
|
|
if(bTextRota90)
|
|
{
|
|
aStr = " ";
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
return aStr;
|
|
}
|
|
|
|
|
|
// BaseProperties section
|
|
|
|
std::unique_ptr<sdr::properties::BaseProperties> SdrMeasureObj::CreateObjectSpecificProperties()
|
|
{
|
|
return std::make_unique<sdr::properties::MeasureProperties>(*this);
|
|
}
|
|
|
|
|
|
// DrawContact section
|
|
|
|
std::unique_ptr<sdr::contact::ViewContact> SdrMeasureObj::CreateObjectSpecificViewContact()
|
|
{
|
|
return std::make_unique<sdr::contact::ViewContactOfSdrMeasureObj>(*this);
|
|
}
|
|
|
|
|
|
SdrMeasureObj::SdrMeasureObj(SdrModel& rSdrModel)
|
|
: SdrTextObj(rSdrModel),
|
|
m_bTextDirty(false)
|
|
{
|
|
// #i25616#
|
|
mbSupportTextIndentingOnLineWidthChange = false;
|
|
}
|
|
|
|
SdrMeasureObj::SdrMeasureObj(SdrModel& rSdrModel, SdrMeasureObj const & rSource)
|
|
: SdrTextObj(rSdrModel, rSource),
|
|
m_bTextDirty(false)
|
|
{
|
|
// #i25616#
|
|
mbSupportTextIndentingOnLineWidthChange = false;
|
|
|
|
m_aPt1 = rSource.m_aPt1;
|
|
m_aPt2 = rSource.m_aPt2;
|
|
m_bTextDirty = rSource.m_bTextDirty;
|
|
}
|
|
|
|
SdrMeasureObj::SdrMeasureObj(
|
|
SdrModel& rSdrModel,
|
|
const Point& rPt1,
|
|
const Point& rPt2)
|
|
: SdrTextObj(rSdrModel),
|
|
m_aPt1(rPt1),
|
|
m_aPt2(rPt2),
|
|
m_bTextDirty(false)
|
|
{
|
|
// #i25616#
|
|
mbSupportTextIndentingOnLineWidthChange = false;
|
|
}
|
|
|
|
SdrMeasureObj::~SdrMeasureObj()
|
|
{
|
|
}
|
|
|
|
void SdrMeasureObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
|
|
{
|
|
rInfo.bMoveAllowed =true;
|
|
rInfo.bResizeFreeAllowed=true;
|
|
rInfo.bResizePropAllowed=true;
|
|
rInfo.bRotateFreeAllowed=true;
|
|
rInfo.bRotate90Allowed =true;
|
|
rInfo.bMirrorFreeAllowed=true;
|
|
rInfo.bMirror45Allowed =true;
|
|
rInfo.bMirror90Allowed =true;
|
|
rInfo.bTransparenceAllowed = false;
|
|
rInfo.bShearAllowed =true;
|
|
rInfo.bEdgeRadiusAllowed=false;
|
|
rInfo.bNoOrthoDesired =true;
|
|
rInfo.bNoContortion =false;
|
|
rInfo.bCanConvToPath =false;
|
|
rInfo.bCanConvToPoly =true;
|
|
rInfo.bCanConvToPathLineToArea=false;
|
|
rInfo.bCanConvToPolyLineToArea=false;
|
|
rInfo.bCanConvToContour = LineGeometryUsageIsNecessary();
|
|
}
|
|
|
|
SdrObjKind SdrMeasureObj::GetObjIdentifier() const
|
|
{
|
|
return SdrObjKind::Measure;
|
|
}
|
|
|
|
struct ImpMeasureRec : public SdrDragStatUserData
|
|
{
|
|
Point aPt1;
|
|
Point aPt2;
|
|
css::drawing::MeasureTextHorzPos eWantTextHPos;
|
|
css::drawing::MeasureTextVertPos eWantTextVPos;
|
|
tools::Long nLineDist;
|
|
tools::Long nHelplineOverhang;
|
|
tools::Long nHelplineDist;
|
|
tools::Long nHelpline1Len;
|
|
tools::Long nHelpline2Len;
|
|
bool bBelowRefEdge;
|
|
bool bTextRota90;
|
|
bool bTextUpsideDown;
|
|
bool bTextAutoAngle;
|
|
Degree100 nTextAutoAngleView;
|
|
};
|
|
|
|
namespace {
|
|
|
|
struct ImpLineRec
|
|
{
|
|
Point aP1;
|
|
Point aP2;
|
|
};
|
|
|
|
}
|
|
|
|
struct ImpMeasurePoly
|
|
{
|
|
ImpLineRec aMainline1; // those with the 1st arrowhead
|
|
ImpLineRec aMainline2; // those with the 2nd arrowhead
|
|
ImpLineRec aMainline3; // those in between
|
|
ImpLineRec aHelpline1;
|
|
ImpLineRec aHelpline2;
|
|
Size aTextSize;
|
|
tools::Long nLineLen;
|
|
Degree100 nLineAngle;
|
|
Degree100 nTextAngle;
|
|
Degree100 nHlpAngle;
|
|
double nLineSin;
|
|
double nLineCos;
|
|
sal_uInt16 nMainlineCnt;
|
|
css::drawing::MeasureTextHorzPos eUsedTextHPos;
|
|
css::drawing::MeasureTextVertPos eUsedTextVPos;
|
|
tools::Long nLineWdt2; // half the line width
|
|
tools::Long nArrow1Len; // length of 1st arrowhead; for Center, use only half
|
|
tools::Long nArrow2Len; // length of 2nd arrowhead; for Center, use only half
|
|
tools::Long nArrow1Wdt; // width of 1st arrow
|
|
tools::Long nArrow2Wdt; // width of 2nd arrow
|
|
tools::Long nShortLineLen; // line length, if PfeileAussen (arrowheads on the outside)
|
|
bool bAutoUpsideDown; // UpsideDown via automation
|
|
bool bBreakedLine;
|
|
};
|
|
|
|
void SdrMeasureObj::ImpTakeAttr(ImpMeasureRec& rRec) const
|
|
{
|
|
rRec.aPt1 = m_aPt1;
|
|
rRec.aPt2 = m_aPt2;
|
|
|
|
const SfxItemSet& rSet = GetObjectItemSet();
|
|
rRec.eWantTextHPos =rSet.Get(SDRATTR_MEASURETEXTHPOS ).GetValue();
|
|
rRec.eWantTextVPos =rSet.Get(SDRATTR_MEASURETEXTVPOS ).GetValue();
|
|
rRec.nLineDist =rSet.Get(SDRATTR_MEASURELINEDIST ).GetValue();
|
|
rRec.nHelplineOverhang =rSet.Get(SDRATTR_MEASUREHELPLINEOVERHANG).GetValue();
|
|
rRec.nHelplineDist =rSet.Get(SDRATTR_MEASUREHELPLINEDIST ).GetValue();
|
|
rRec.nHelpline1Len =rSet.Get(SDRATTR_MEASUREHELPLINE1LEN ).GetValue();
|
|
rRec.nHelpline2Len =rSet.Get(SDRATTR_MEASUREHELPLINE2LEN ).GetValue();
|
|
rRec.bBelowRefEdge =rSet.Get(SDRATTR_MEASUREBELOWREFEDGE ).GetValue();
|
|
rRec.bTextRota90 =rSet.Get(SDRATTR_MEASURETEXTROTA90 ).GetValue();
|
|
rRec.bTextUpsideDown =static_cast<const SdrMeasureTextUpsideDownItem& >(rSet.Get(SDRATTR_MEASURETEXTUPSIDEDOWN )).GetValue();
|
|
rRec.bTextAutoAngle =rSet.Get(SDRATTR_MEASURETEXTAUTOANGLE ).GetValue();
|
|
rRec.nTextAutoAngleView=static_cast<const SdrMeasureTextAutoAngleViewItem&>(rSet.Get(SDRATTR_MEASURETEXTAUTOANGLEVIEW)).GetValue();
|
|
}
|
|
|
|
static tools::Long impGetLineStartEndDistance(const basegfx::B2DPolyPolygon& rPolyPolygon, tools::Long nNewWidth, bool bCenter)
|
|
{
|
|
const basegfx::B2DRange aPolygonRange(rPolyPolygon.getB2DRange());
|
|
const double fOldWidth(std::max(aPolygonRange.getWidth(), 1.0));
|
|
const double fScale(static_cast<double>(nNewWidth) / fOldWidth);
|
|
tools::Long nHeight(basegfx::fround<tools::Long>(aPolygonRange.getHeight() * fScale));
|
|
|
|
if(bCenter)
|
|
{
|
|
nHeight /= 2;
|
|
}
|
|
|
|
return nHeight;
|
|
}
|
|
|
|
void SdrMeasureObj::ImpCalcGeometrics(const ImpMeasureRec& rRec, ImpMeasurePoly& rPol) const
|
|
{
|
|
Point aP1(rRec.aPt1);
|
|
Point aP2(rRec.aPt2);
|
|
Point aDelt(aP2); aDelt-=aP1;
|
|
|
|
rPol.aTextSize=GetTextSize();
|
|
rPol.nLineLen=GetLen(aDelt);
|
|
|
|
rPol.nLineWdt2=0;
|
|
tools::Long nArrow1Len=0; bool bArrow1Center=false;
|
|
tools::Long nArrow2Len=0; bool bArrow2Center=false;
|
|
tools::Long nArrow1Wdt=0;
|
|
tools::Long nArrow2Wdt=0;
|
|
rPol.nArrow1Wdt=0;
|
|
rPol.nArrow2Wdt=0;
|
|
tools::Long nArrowNeed=0;
|
|
tools::Long nShortLen=0;
|
|
bool bPfeileAussen = false;
|
|
|
|
const SfxItemSet& rSet = GetObjectItemSet();
|
|
sal_Int32 nLineWdt = rSet.Get(XATTR_LINEWIDTH).GetValue(); // line width
|
|
rPol.nLineWdt2 = (nLineWdt + 1) / 2;
|
|
|
|
nArrow1Wdt = rSet.Get(XATTR_LINESTARTWIDTH).GetValue();
|
|
if(nArrow1Wdt < 0)
|
|
nArrow1Wdt = -nLineWdt * nArrow1Wdt / 100; // <0 = relative
|
|
|
|
nArrow2Wdt = rSet.Get(XATTR_LINEENDWIDTH).GetValue();
|
|
if(nArrow2Wdt < 0)
|
|
nArrow2Wdt = -nLineWdt * nArrow2Wdt / 100; // <0 = relative
|
|
|
|
basegfx::B2DPolyPolygon aPol1(rSet.Get(XATTR_LINESTART).GetLineStartValue());
|
|
basegfx::B2DPolyPolygon aPol2(rSet.Get(XATTR_LINEEND).GetLineEndValue());
|
|
bArrow1Center = rSet.Get(XATTR_LINESTARTCENTER).GetValue();
|
|
bArrow2Center = rSet.Get(XATTR_LINEENDCENTER).GetValue();
|
|
nArrow1Len = impGetLineStartEndDistance(aPol1, nArrow1Wdt, bArrow1Center) - 1;
|
|
nArrow2Len = impGetLineStartEndDistance(aPol2, nArrow2Wdt, bArrow2Center) - 1;
|
|
|
|
// nArrowLen is already halved at bCenter.
|
|
// In the case of 2 arrowheads each 4mm long, we can't go below 10mm.
|
|
nArrowNeed=nArrow1Len+nArrow2Len+(nArrow1Wdt+nArrow2Wdt)/2;
|
|
if (rPol.nLineLen<nArrowNeed) bPfeileAussen = true;
|
|
nShortLen=(nArrow1Len+nArrow1Wdt + nArrow2Len+nArrow2Wdt) /2;
|
|
|
|
rPol.eUsedTextHPos=rRec.eWantTextHPos;
|
|
rPol.eUsedTextVPos=rRec.eWantTextVPos;
|
|
if (rPol.eUsedTextVPos == css::drawing::MeasureTextVertPos_AUTO)
|
|
rPol.eUsedTextVPos = css::drawing::MeasureTextVertPos_EAST;
|
|
bool bBrkLine=false;
|
|
if (rPol.eUsedTextVPos == css::drawing::MeasureTextVertPos_CENTERED)
|
|
{
|
|
OutlinerParaObject* pOutlinerParaObject = SdrTextObj::GetOutlinerParaObject();
|
|
if (pOutlinerParaObject!=nullptr && pOutlinerParaObject->GetTextObject().GetParagraphCount()==1)
|
|
{
|
|
bBrkLine=true; // dashed line if there's only on paragraph.
|
|
}
|
|
}
|
|
rPol.bBreakedLine=bBrkLine;
|
|
if (rPol.eUsedTextHPos==css::drawing::MeasureTextHorzPos_AUTO) { // if text is too wide, push it outside
|
|
bool bOutside = false;
|
|
tools::Long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height();
|
|
if (nNeedSiz>rPol.nLineLen) bOutside = true; // text doesn't fit in between
|
|
if (bBrkLine) {
|
|
if (nNeedSiz+nArrowNeed>rPol.nLineLen) bPfeileAussen = true; // text fits in between, if arrowheads are on the outside
|
|
} else {
|
|
tools::Long nSmallNeed=nArrow1Len+nArrow2Len+(nArrow1Wdt+nArrow2Wdt)/2/4;
|
|
if (nNeedSiz+nSmallNeed>rPol.nLineLen) bPfeileAussen = true; // text fits in between, if arrowheads are on the outside
|
|
}
|
|
rPol.eUsedTextHPos=bOutside ? css::drawing::MeasureTextHorzPos_LEFTOUTSIDE : css::drawing::MeasureTextHorzPos_INSIDE;
|
|
}
|
|
if (rPol.eUsedTextHPos != css::drawing::MeasureTextHorzPos_INSIDE) bPfeileAussen = true;
|
|
rPol.nArrow1Wdt=nArrow1Wdt;
|
|
rPol.nArrow2Wdt=nArrow2Wdt;
|
|
rPol.nShortLineLen=nShortLen;
|
|
rPol.nArrow1Len=nArrow1Len;
|
|
rPol.nArrow2Len=nArrow2Len;
|
|
|
|
rPol.nLineAngle=GetAngle(aDelt);
|
|
double a = toRadians(rPol.nLineAngle);
|
|
double nLineSin=sin(a);
|
|
double nLineCos=cos(a);
|
|
rPol.nLineSin=nLineSin;
|
|
rPol.nLineCos=nLineCos;
|
|
|
|
rPol.nTextAngle=rPol.nLineAngle;
|
|
if (rRec.bTextRota90) rPol.nTextAngle+=9000_deg100;
|
|
|
|
rPol.bAutoUpsideDown=false;
|
|
if (rRec.bTextAutoAngle) {
|
|
Degree100 nTmpAngle=NormAngle36000(rPol.nTextAngle-rRec.nTextAutoAngleView);
|
|
if (nTmpAngle>=18000_deg100) {
|
|
rPol.nTextAngle+=18000_deg100;
|
|
rPol.bAutoUpsideDown=true;
|
|
}
|
|
}
|
|
|
|
if (rRec.bTextUpsideDown) rPol.nTextAngle+=18000_deg100;
|
|
rPol.nTextAngle=NormAngle36000(rPol.nTextAngle);
|
|
rPol.nHlpAngle=rPol.nLineAngle+9000_deg100;
|
|
if (rRec.bBelowRefEdge) rPol.nHlpAngle+=18000_deg100;
|
|
rPol.nHlpAngle=NormAngle36000(rPol.nHlpAngle);
|
|
double nHlpSin=nLineCos;
|
|
double nHlpCos=-nLineSin;
|
|
if (rRec.bBelowRefEdge) {
|
|
nHlpSin=-nHlpSin;
|
|
nHlpCos=-nHlpCos;
|
|
}
|
|
|
|
tools::Long nLineDist=rRec.nLineDist;
|
|
tools::Long nOverhang=rRec.nHelplineOverhang;
|
|
tools::Long nHelplineDist=rRec.nHelplineDist;
|
|
|
|
tools::Long dx = basegfx::fround<tools::Long>(nLineDist * nHlpCos);
|
|
tools::Long dy = basegfx::fround<tools::Long>(nLineDist * -nHlpSin);
|
|
tools::Long dxh1a = basegfx::fround<tools::Long>((nHelplineDist - rRec.nHelpline1Len) * nHlpCos);
|
|
tools::Long dyh1a = basegfx::fround<tools::Long>((nHelplineDist - rRec.nHelpline1Len) * -nHlpSin);
|
|
tools::Long dxh1b = basegfx::fround<tools::Long>((nHelplineDist - rRec.nHelpline2Len) * nHlpCos);
|
|
tools::Long dyh1b = basegfx::fround<tools::Long>((nHelplineDist - rRec.nHelpline2Len) * -nHlpSin);
|
|
tools::Long dxh2 = basegfx::fround<tools::Long>((nLineDist + nOverhang) * nHlpCos);
|
|
tools::Long dyh2 = basegfx::fround<tools::Long>((nLineDist + nOverhang) * -nHlpSin);
|
|
|
|
// extension line 1
|
|
rPol.aHelpline1.aP1=Point(aP1.X()+dxh1a,aP1.Y()+dyh1a);
|
|
rPol.aHelpline1.aP2=Point(aP1.X()+dxh2,aP1.Y()+dyh2);
|
|
|
|
// extension line 2
|
|
rPol.aHelpline2.aP1=Point(aP2.X()+dxh1b,aP2.Y()+dyh1b);
|
|
rPol.aHelpline2.aP2=Point(aP2.X()+dxh2,aP2.Y()+dyh2);
|
|
|
|
// dimension line
|
|
Point aMainlinePt1(aP1.X()+dx,aP1.Y()+dy);
|
|
Point aMainlinePt2(aP2.X()+dx,aP2.Y()+dy);
|
|
if (!bPfeileAussen) {
|
|
rPol.aMainline1.aP1=aMainlinePt1;
|
|
rPol.aMainline1.aP2=aMainlinePt2;
|
|
rPol.aMainline2=rPol.aMainline1;
|
|
rPol.aMainline3=rPol.aMainline1;
|
|
rPol.nMainlineCnt=1;
|
|
if (bBrkLine) {
|
|
tools::Long nNeedSiz=!rRec.bTextRota90 ? rPol.aTextSize.Width() : rPol.aTextSize.Height();
|
|
tools::Long nHalfLen=(rPol.nLineLen-nNeedSiz-nArrow1Wdt/4-nArrow2Wdt/4) /2;
|
|
rPol.nMainlineCnt=2;
|
|
rPol.aMainline1.aP2=aMainlinePt1;
|
|
rPol.aMainline1.aP2.AdjustX(nHalfLen );
|
|
RotatePoint(rPol.aMainline1.aP2,rPol.aMainline1.aP1,nLineSin,nLineCos);
|
|
rPol.aMainline2.aP1=aMainlinePt2;
|
|
rPol.aMainline2.aP1.AdjustX( -nHalfLen );
|
|
RotatePoint(rPol.aMainline2.aP1,rPol.aMainline2.aP2,nLineSin,nLineCos);
|
|
}
|
|
} else {
|
|
tools::Long nLen1=nShortLen; // arrowhead's width as line length outside of the arrowhead
|
|
tools::Long nLen2=nShortLen;
|
|
tools::Long nTextWdt=rRec.bTextRota90 ? rPol.aTextSize.Height() : rPol.aTextSize.Width();
|
|
if (!bBrkLine) {
|
|
if (rPol.eUsedTextHPos==css::drawing::MeasureTextHorzPos_LEFTOUTSIDE) nLen1=nArrow1Len+nTextWdt;
|
|
if (rPol.eUsedTextHPos==css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE) nLen2=nArrow2Len+nTextWdt;
|
|
}
|
|
rPol.aMainline1.aP1=aMainlinePt1;
|
|
rPol.aMainline1.aP2=aMainlinePt1; rPol.aMainline1.aP2.AdjustX( -nLen1 ); RotatePoint(rPol.aMainline1.aP2,aMainlinePt1,nLineSin,nLineCos);
|
|
rPol.aMainline2.aP1=aMainlinePt2; rPol.aMainline2.aP1.AdjustX(nLen2 ); RotatePoint(rPol.aMainline2.aP1,aMainlinePt2,nLineSin,nLineCos);
|
|
rPol.aMainline2.aP2=aMainlinePt2;
|
|
rPol.aMainline3.aP1=aMainlinePt1;
|
|
rPol.aMainline3.aP2=aMainlinePt2;
|
|
rPol.nMainlineCnt=3;
|
|
if (bBrkLine && rPol.eUsedTextHPos==css::drawing::MeasureTextHorzPos_INSIDE) rPol.nMainlineCnt=2;
|
|
}
|
|
}
|
|
|
|
basegfx::B2DPolyPolygon SdrMeasureObj::ImpCalcXPoly(const ImpMeasurePoly& rPol)
|
|
{
|
|
basegfx::B2DPolyPolygon aRetval;
|
|
basegfx::B2DPolygon aPartPolyA;
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline1.aP1.X(), rPol.aMainline1.aP1.Y()));
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline1.aP2.X(), rPol.aMainline1.aP2.Y()));
|
|
aRetval.append(aPartPolyA);
|
|
|
|
if(rPol.nMainlineCnt > 1)
|
|
{
|
|
aPartPolyA.clear();
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline2.aP1.X(), rPol.aMainline2.aP1.Y()));
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline2.aP2.X(), rPol.aMainline2.aP2.Y()));
|
|
aRetval.append(aPartPolyA);
|
|
}
|
|
|
|
if(rPol.nMainlineCnt > 2)
|
|
{
|
|
aPartPolyA.clear();
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline3.aP1.X(), rPol.aMainline3.aP1.Y()));
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aMainline3.aP2.X(), rPol.aMainline3.aP2.Y()));
|
|
aRetval.append(aPartPolyA);
|
|
}
|
|
|
|
aPartPolyA.clear();
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline1.aP1.X(), rPol.aHelpline1.aP1.Y()));
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline1.aP2.X(), rPol.aHelpline1.aP2.Y()));
|
|
aRetval.append(aPartPolyA);
|
|
|
|
aPartPolyA.clear();
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline2.aP1.X(), rPol.aHelpline2.aP1.Y()));
|
|
aPartPolyA.append(basegfx::B2DPoint(rPol.aHelpline2.aP2.X(), rPol.aHelpline2.aP2.Y()));
|
|
aRetval.append(aPartPolyA);
|
|
|
|
return aRetval;
|
|
}
|
|
|
|
bool SdrMeasureObj::CalcFieldValue(const SvxFieldItem& rField, sal_Int32 nPara, sal_uInt16 nPos,
|
|
bool bEdit,
|
|
std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle, OUString& rRet) const
|
|
{
|
|
const SvxFieldData* pField=rField.GetField();
|
|
const SdrMeasureField* pMeasureField=dynamic_cast<const SdrMeasureField*>( pField );
|
|
if (pMeasureField!=nullptr) {
|
|
rRet = TakeRepresentation(pMeasureField->GetMeasureFieldKind());
|
|
if (rpFldColor && !bEdit)
|
|
{
|
|
rpFldColor.reset();
|
|
}
|
|
return true;
|
|
} else {
|
|
return SdrTextObj::CalcFieldValue(rField,nPara,nPos,bEdit,rpTxtColor,rpFldColor,rpFldLineStyle,rRet);
|
|
}
|
|
}
|
|
|
|
void SdrMeasureObj::UndirtyText() const
|
|
{
|
|
if (!m_bTextDirty)
|
|
return;
|
|
|
|
SdrOutliner& rOutliner=ImpGetDrawOutliner();
|
|
OutlinerParaObject* pOutlinerParaObject = SdrTextObj::GetOutlinerParaObject();
|
|
if(pOutlinerParaObject==nullptr)
|
|
{
|
|
rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SdrMeasureFieldKind::Rotate90Blanks), EE_FEATURE_FIELD), ESelection(0,0));
|
|
rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SdrMeasureFieldKind::Value), EE_FEATURE_FIELD),ESelection(0,1));
|
|
rOutliner.QuickInsertText(u" "_ustr, ESelection(0,2));
|
|
rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SdrMeasureFieldKind::Unit), EE_FEATURE_FIELD),ESelection(0,3));
|
|
rOutliner.QuickInsertField(SvxFieldItem(SdrMeasureField(SdrMeasureFieldKind::Rotate90Blanks), EE_FEATURE_FIELD),ESelection(0,4));
|
|
|
|
if(GetStyleSheet())
|
|
rOutliner.SetStyleSheet(0, GetStyleSheet());
|
|
|
|
rOutliner.SetParaAttribs(0, GetObjectItemSet());
|
|
|
|
// cast to nonconst
|
|
const_cast<SdrMeasureObj*>(this)->NbcSetOutlinerParaObject( rOutliner.CreateParaObject() );
|
|
}
|
|
else
|
|
{
|
|
rOutliner.SetText(*pOutlinerParaObject);
|
|
}
|
|
|
|
rOutliner.SetUpdateLayout(true);
|
|
rOutliner.UpdateFields();
|
|
Size aSiz(rOutliner.CalcTextSize());
|
|
rOutliner.Clear();
|
|
// cast to nonconst three times
|
|
const_cast<SdrMeasureObj*>(this)->maTextSize = aSiz;
|
|
const_cast<SdrMeasureObj*>(this)->mbTextSizeDirty = false;
|
|
const_cast<SdrMeasureObj*>(this)->m_bTextDirty = false;
|
|
}
|
|
|
|
void SdrMeasureObj::TakeUnrotatedSnapRect(tools::Rectangle& rRect) const
|
|
{
|
|
if (m_bTextDirty) UndirtyText();
|
|
ImpMeasureRec aRec;
|
|
ImpMeasurePoly aMPol;
|
|
ImpTakeAttr(aRec);
|
|
ImpCalcGeometrics(aRec,aMPol);
|
|
|
|
// determine TextSize including text frame margins
|
|
Size aTextSize2(aMPol.aTextSize);
|
|
if (aTextSize2.Width()<1) aTextSize2.setWidth(1 );
|
|
if (aTextSize2.Height()<1) aTextSize2.setHeight(1 );
|
|
aTextSize2.AdjustWidth(GetTextLeftDistance()+GetTextRightDistance() );
|
|
aTextSize2.AdjustHeight(GetTextUpperDistance()+GetTextLowerDistance() );
|
|
|
|
Point aPt1b(aMPol.aMainline1.aP1);
|
|
tools::Long nLen=aMPol.nLineLen;
|
|
tools::Long nLWdt=aMPol.nLineWdt2;
|
|
tools::Long nArr1Len=aMPol.nArrow1Len;
|
|
tools::Long nArr2Len=aMPol.nArrow2Len;
|
|
if (aMPol.bBreakedLine) {
|
|
// In the case of a dashed line and Outside, the text should be
|
|
// placed next to the line at the arrowhead instead of directly
|
|
// at the arrowhead.
|
|
nArr1Len=aMPol.nShortLineLen+aMPol.nArrow1Wdt/4;
|
|
nArr2Len=aMPol.nShortLineLen+aMPol.nArrow2Wdt/4;
|
|
}
|
|
|
|
Point aTextPos;
|
|
bool bRota90=aRec.bTextRota90;
|
|
bool bUpsideDown=aRec.bTextUpsideDown!=aMPol.bAutoUpsideDown;
|
|
bool bBelowRefEdge=aRec.bBelowRefEdge;
|
|
css::drawing::MeasureTextHorzPos eMH=aMPol.eUsedTextHPos;
|
|
css::drawing::MeasureTextVertPos eMV=aMPol.eUsedTextVPos;
|
|
if (!bRota90) {
|
|
switch (eMH) {
|
|
case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: aTextPos.setX(aPt1b.X()-aTextSize2.Width()-nArr1Len-nLWdt ); break;
|
|
case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: aTextPos.setX(aPt1b.X()+nLen+nArr2Len+nLWdt ); break;
|
|
default: aTextPos.setX(aPt1b.X() ); aTextSize2.setWidth(nLen );
|
|
}
|
|
switch (eMV) {
|
|
case css::drawing::MeasureTextVertPos_CENTERED:
|
|
aTextPos.setY(aPt1b.Y()-aTextSize2.Height()/2 ); break;
|
|
case css::drawing::MeasureTextVertPos_WEST: {
|
|
if (!bUpsideDown) aTextPos.setY(aPt1b.Y()+nLWdt );
|
|
else aTextPos.setY(aPt1b.Y()-aTextSize2.Height()-nLWdt );
|
|
} break;
|
|
default: {
|
|
if (!bUpsideDown) aTextPos.setY(aPt1b.Y()-aTextSize2.Height()-nLWdt );
|
|
else aTextPos.setY(aPt1b.Y()+nLWdt );
|
|
}
|
|
}
|
|
if (bUpsideDown) {
|
|
aTextPos.AdjustX(aTextSize2.Width() );
|
|
aTextPos.AdjustY(aTextSize2.Height() );
|
|
}
|
|
} else { // also if bTextRota90==TRUE
|
|
switch (eMH) {
|
|
case css::drawing::MeasureTextHorzPos_LEFTOUTSIDE: aTextPos.setX(aPt1b.X()-aTextSize2.Height()-nArr1Len ); break;
|
|
case css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE: aTextPos.setX(aPt1b.X()+nLen+nArr2Len ); break;
|
|
default: aTextPos.setX(aPt1b.X() ); aTextSize2.setHeight(nLen );
|
|
}
|
|
switch (eMV) {
|
|
case css::drawing::MeasureTextVertPos_CENTERED:
|
|
aTextPos.setY(aPt1b.Y()+aTextSize2.Width()/2 ); break;
|
|
case css::drawing::MeasureTextVertPos_WEST: {
|
|
if (!bBelowRefEdge) aTextPos.setY(aPt1b.Y()+aTextSize2.Width()+nLWdt );
|
|
else aTextPos.setY(aPt1b.Y()-nLWdt );
|
|
} break;
|
|
default: {
|
|
if (!bBelowRefEdge) aTextPos.setY(aPt1b.Y()-nLWdt );
|
|
else aTextPos.setY(aPt1b.Y()+aTextSize2.Width()+nLWdt );
|
|
}
|
|
}
|
|
if (bUpsideDown) {
|
|
aTextPos.AdjustX(aTextSize2.Height() );
|
|
aTextPos.AdjustY( -(aTextSize2.Width()) );
|
|
}
|
|
}
|
|
if (aMPol.nTextAngle != maGeo.m_nRotationAngle) {
|
|
const_cast<SdrMeasureObj*>(this)->maGeo.m_nRotationAngle=aMPol.nTextAngle;
|
|
const_cast<SdrMeasureObj*>(this)->maGeo.RecalcSinCos();
|
|
}
|
|
RotatePoint(aTextPos,aPt1b,aMPol.nLineSin,aMPol.nLineCos);
|
|
aTextSize2.AdjustWidth( 1 ); aTextSize2.AdjustHeight( 1 ); // because of the Rect-Ctor's odd behavior
|
|
rRect=tools::Rectangle(aTextPos,aTextSize2);
|
|
rRect.Normalize();
|
|
const_cast<SdrMeasureObj*>(this)->setRectangle(rRect);
|
|
|
|
if (aMPol.nTextAngle != maGeo.m_nRotationAngle) {
|
|
const_cast<SdrMeasureObj*>(this)->maGeo.m_nRotationAngle=aMPol.nTextAngle;
|
|
const_cast<SdrMeasureObj*>(this)->maGeo.RecalcSinCos();
|
|
}
|
|
}
|
|
|
|
rtl::Reference<SdrObject> SdrMeasureObj::implCloneSdrObject(SdrModel& rTargetModel) const
|
|
{
|
|
return new SdrMeasureObj(rTargetModel, *this);
|
|
}
|
|
|
|
OUString SdrMeasureObj::TakeObjNameSingul() const
|
|
{
|
|
OUString sName(SvxResId(STR_ObjNameSingulMEASURE));
|
|
|
|
OUString aName( GetName() );
|
|
if (!aName.isEmpty())
|
|
sName += " '" + aName + "'";
|
|
|
|
return sName;
|
|
}
|
|
|
|
OUString SdrMeasureObj::TakeObjNamePlural() const
|
|
{
|
|
return SvxResId(STR_ObjNamePluralMEASURE);
|
|
}
|
|
|
|
basegfx::B2DPolyPolygon SdrMeasureObj::TakeXorPoly() const
|
|
{
|
|
ImpMeasureRec aRec;
|
|
ImpMeasurePoly aMPol;
|
|
ImpTakeAttr(aRec);
|
|
ImpCalcGeometrics(aRec,aMPol);
|
|
return ImpCalcXPoly(aMPol);
|
|
}
|
|
|
|
sal_uInt32 SdrMeasureObj::GetHdlCount() const
|
|
{
|
|
return 6;
|
|
}
|
|
|
|
void SdrMeasureObj::AddToHdlList(SdrHdlList& rHdlList) const
|
|
{
|
|
ImpMeasureRec aRec;
|
|
ImpMeasurePoly aMPol;
|
|
ImpTakeAttr(aRec);
|
|
aRec.nHelplineDist=0;
|
|
ImpCalcGeometrics(aRec,aMPol);
|
|
|
|
for (sal_uInt32 nHdlNum=0; nHdlNum<6; ++nHdlNum)
|
|
{
|
|
Point aPt;
|
|
switch (nHdlNum) {
|
|
case 0: aPt=aMPol.aHelpline1.aP1; break;
|
|
case 1: aPt=aMPol.aHelpline2.aP1; break;
|
|
case 2: aPt=m_aPt1; break;
|
|
case 3: aPt=m_aPt2; break;
|
|
case 4: aPt=aMPol.aHelpline1.aP2; break;
|
|
case 5: aPt=aMPol.aHelpline2.aP2; break;
|
|
} // switch
|
|
std::unique_ptr<SdrHdl> pHdl(new ImpMeasureHdl(aPt,SdrHdlKind::User));
|
|
pHdl->SetObjHdlNum(nHdlNum);
|
|
pHdl->SetRotationAngle(aMPol.nLineAngle);
|
|
rHdlList.AddHdl(std::move(pHdl));
|
|
}
|
|
}
|
|
|
|
|
|
bool SdrMeasureObj::hasSpecialDrag() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool SdrMeasureObj::beginSpecialDrag(SdrDragStat& rDrag) const
|
|
{
|
|
const SdrHdl* pHdl = rDrag.GetHdl();
|
|
|
|
if(pHdl)
|
|
{
|
|
const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum());
|
|
|
|
if(nHdlNum != 2 && nHdlNum != 3)
|
|
{
|
|
rDrag.SetEndDragChangesAttributes(true);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool SdrMeasureObj::applySpecialDrag(SdrDragStat& rDrag)
|
|
{
|
|
ImpMeasureRec aMeasureRec;
|
|
const SdrHdl* pHdl = rDrag.GetHdl();
|
|
const sal_uInt32 nHdlNum(pHdl->GetObjHdlNum());
|
|
|
|
ImpTakeAttr(aMeasureRec);
|
|
ImpEvalDrag(aMeasureRec, rDrag);
|
|
|
|
switch (nHdlNum)
|
|
{
|
|
case 2:
|
|
{
|
|
m_aPt1 = aMeasureRec.aPt1;
|
|
SetTextDirty();
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
m_aPt2 = aMeasureRec.aPt2;
|
|
SetTextDirty();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
switch(nHdlNum)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
{
|
|
ImpMeasureRec aOrigMeasureRec;
|
|
ImpTakeAttr(aOrigMeasureRec);
|
|
|
|
if(aMeasureRec.nHelpline1Len != aOrigMeasureRec.nHelpline1Len)
|
|
{
|
|
SetObjectItem(makeSdrMeasureHelpline1LenItem(aMeasureRec.nHelpline1Len));
|
|
}
|
|
|
|
if(aMeasureRec.nHelpline2Len != aOrigMeasureRec.nHelpline2Len)
|
|
{
|
|
SetObjectItem(makeSdrMeasureHelpline2LenItem(aMeasureRec.nHelpline2Len));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 4:
|
|
case 5:
|
|
{
|
|
ImpMeasureRec aOrigMeasureRec;
|
|
ImpTakeAttr(aOrigMeasureRec);
|
|
|
|
if(aMeasureRec.nLineDist != aOrigMeasureRec.nLineDist)
|
|
{
|
|
SetObjectItem(makeSdrMeasureLineDistItem(aMeasureRec.nLineDist));
|
|
}
|
|
|
|
if(aMeasureRec.bBelowRefEdge != aOrigMeasureRec.bBelowRefEdge)
|
|
{
|
|
SetObjectItem(SdrMeasureBelowRefEdgeItem(aMeasureRec.bBelowRefEdge));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // switch
|
|
|
|
SetBoundAndSnapRectsDirty();
|
|
SetChanged();
|
|
|
|
return true;
|
|
}
|
|
|
|
OUString SdrMeasureObj::getSpecialDragComment(const SdrDragStat& /*rDrag*/) const
|
|
{
|
|
return OUString();
|
|
}
|
|
|
|
void SdrMeasureObj::ImpEvalDrag(ImpMeasureRec& rRec, const SdrDragStat& rDrag) const
|
|
{
|
|
Degree100 nLineAngle=GetAngle(rRec.aPt2-rRec.aPt1);
|
|
double a = toRadians(nLineAngle);
|
|
double nSin=sin(a);
|
|
double nCos=cos(a);
|
|
|
|
const SdrHdl* pHdl=rDrag.GetHdl();
|
|
sal_uInt32 nHdlNum(pHdl->GetObjHdlNum());
|
|
bool bOrtho=rDrag.GetView()!=nullptr && rDrag.GetView()->IsOrtho();
|
|
bool bBigOrtho=bOrtho && rDrag.GetView()->IsBigOrtho();
|
|
bool bBelow=rRec.bBelowRefEdge;
|
|
Point aPt(rDrag.GetNow());
|
|
|
|
switch (nHdlNum) {
|
|
case 0: {
|
|
RotatePoint(aPt,m_aPt1,nSin,-nCos);
|
|
rRec.nHelpline1Len=m_aPt1.Y()-aPt.Y();
|
|
if (bBelow) rRec.nHelpline1Len=-rRec.nHelpline1Len;
|
|
if (bOrtho) rRec.nHelpline2Len=rRec.nHelpline1Len;
|
|
} break;
|
|
case 1: {
|
|
RotatePoint(aPt,m_aPt2,nSin,-nCos);
|
|
rRec.nHelpline2Len=m_aPt2.Y()-aPt.Y();
|
|
if (bBelow) rRec.nHelpline2Len=-rRec.nHelpline2Len;
|
|
if (bOrtho) rRec.nHelpline1Len=rRec.nHelpline2Len;
|
|
} break;
|
|
case 2: case 3: {
|
|
bool bAnf=nHdlNum==2;
|
|
Point& rMov=bAnf ? rRec.aPt1 : rRec.aPt2;
|
|
Point aMov(rMov);
|
|
Point aFix(bAnf ? rRec.aPt2 : rRec.aPt1);
|
|
if (bOrtho) {
|
|
tools::Long ndx0=aMov.X()-aFix.X();
|
|
tools::Long ndy0=aMov.Y()-aFix.Y();
|
|
bool bHLin=ndy0==0;
|
|
bool bVLin=ndx0==0;
|
|
if (!bHLin || !bVLin) { // else aPt1==aPt2
|
|
tools::Long ndx=aPt.X()-aFix.X();
|
|
tools::Long ndy=aPt.Y()-aFix.Y();
|
|
double nXFact=0; if (!bVLin) nXFact=static_cast<double>(ndx)/static_cast<double>(ndx0);
|
|
double nYFact=0; if (!bHLin) nYFact=static_cast<double>(ndy)/static_cast<double>(ndy0);
|
|
bool bHor=bHLin || (!bVLin && (nXFact>nYFact) ==bBigOrtho);
|
|
bool bVer=bVLin || (!bHLin && (nXFact<=nYFact)==bBigOrtho);
|
|
if (bHor) ndy=tools::Long(ndy0*nXFact);
|
|
if (bVer) ndx=tools::Long(ndx0*nYFact);
|
|
aPt=aFix;
|
|
aPt.AdjustX(ndx );
|
|
aPt.AdjustY(ndy );
|
|
} // else Ortho8
|
|
}
|
|
rMov=aPt;
|
|
} break;
|
|
case 4: case 5: {
|
|
tools::Long nVal0=rRec.nLineDist;
|
|
RotatePoint(aPt,(nHdlNum==4 ? m_aPt1 : m_aPt2),nSin,-nCos);
|
|
rRec.nLineDist=aPt.Y()- (nHdlNum==4 ? m_aPt1.Y() : m_aPt2.Y());
|
|
if (bBelow) rRec.nLineDist=-rRec.nLineDist;
|
|
if (rRec.nLineDist<0) {
|
|
rRec.nLineDist=-rRec.nLineDist;
|
|
rRec.bBelowRefEdge=!bBelow;
|
|
}
|
|
rRec.nLineDist-=rRec.nHelplineOverhang;
|
|
if (bOrtho) rRec.nLineDist=nVal0;
|
|
} break;
|
|
} // switch
|
|
}
|
|
|
|
|
|
bool SdrMeasureObj::BegCreate(SdrDragStat& rStat)
|
|
{
|
|
rStat.SetOrtho8Possible();
|
|
m_aPt1=rStat.GetStart();
|
|
m_aPt2=rStat.GetNow();
|
|
SetTextDirty();
|
|
return true;
|
|
}
|
|
|
|
bool SdrMeasureObj::MovCreate(SdrDragStat& rStat)
|
|
{
|
|
SdrView* pView=rStat.GetView();
|
|
m_aPt1=rStat.GetStart();
|
|
m_aPt2=rStat.GetNow();
|
|
if (pView!=nullptr && pView->IsCreate1stPointAsCenter()) {
|
|
m_aPt1+=m_aPt1;
|
|
m_aPt1-=rStat.GetNow();
|
|
}
|
|
SetTextDirty();
|
|
SetBoundRectDirty();
|
|
m_bSnapRectDirty=true;
|
|
return true;
|
|
}
|
|
|
|
bool SdrMeasureObj::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
|
|
{
|
|
SetTextDirty();
|
|
SetBoundAndSnapRectsDirty();
|
|
return (eCmd==SdrCreateCmd::ForceEnd || rStat.GetPointCount()>=2);
|
|
}
|
|
|
|
bool SdrMeasureObj::BckCreate(SdrDragStat& /*rStat*/)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void SdrMeasureObj::BrkCreate(SdrDragStat& /*rStat*/)
|
|
{
|
|
}
|
|
|
|
basegfx::B2DPolyPolygon SdrMeasureObj::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
|
|
{
|
|
ImpMeasureRec aRec;
|
|
ImpMeasurePoly aMPol;
|
|
|
|
ImpTakeAttr(aRec);
|
|
ImpCalcGeometrics(aRec, aMPol);
|
|
|
|
return ImpCalcXPoly(aMPol);
|
|
}
|
|
|
|
PointerStyle SdrMeasureObj::GetCreatePointer() const
|
|
{
|
|
return PointerStyle::Cross;
|
|
}
|
|
|
|
void SdrMeasureObj::NbcMove(const Size& rSiz)
|
|
{
|
|
SdrTextObj::NbcMove(rSiz);
|
|
m_aPt1.Move(rSiz);
|
|
m_aPt2.Move(rSiz);
|
|
}
|
|
|
|
void SdrMeasureObj::NbcResize(const Point& rRef, double xFact, double yFact)
|
|
{
|
|
SdrTextObj::NbcResize(rRef,xFact,yFact);
|
|
ResizePoint(m_aPt1,rRef,xFact,yFact);
|
|
ResizePoint(m_aPt2,rRef,xFact,yFact);
|
|
SetTextDirty();
|
|
}
|
|
|
|
void SdrMeasureObj::NbcRotate(const Point& rRef, Degree100 nAngle, double sn, double cs)
|
|
{
|
|
SdrTextObj::NbcRotate(rRef,nAngle,sn,cs);
|
|
tools::Long nLen0=GetLen(m_aPt2-m_aPt1);
|
|
RotatePoint(m_aPt1,rRef,sn,cs);
|
|
RotatePoint(m_aPt2,rRef,sn,cs);
|
|
tools::Long nLen1=GetLen(m_aPt2-m_aPt1);
|
|
if (nLen1!=nLen0) { // rounding error!
|
|
tools::Long dx=m_aPt2.X()-m_aPt1.X();
|
|
tools::Long dy=m_aPt2.Y()-m_aPt1.Y();
|
|
dx=BigMulDiv(dx,nLen0,nLen1);
|
|
dy=BigMulDiv(dy,nLen0,nLen1);
|
|
if (rRef==m_aPt2) {
|
|
m_aPt1.setX(m_aPt2.X()-dx );
|
|
m_aPt1.setY(m_aPt2.Y()-dy );
|
|
} else {
|
|
m_aPt2.setX(m_aPt1.X()+dx );
|
|
m_aPt2.setY(m_aPt1.Y()+dy );
|
|
}
|
|
}
|
|
SetBoundAndSnapRectsDirty();
|
|
}
|
|
|
|
void SdrMeasureObj::NbcMirror(const Point& rRef1, const Point& rRef2)
|
|
{
|
|
SdrTextObj::NbcMirror(rRef1,rRef2);
|
|
MirrorPoint(m_aPt1,rRef1,rRef2);
|
|
MirrorPoint(m_aPt2,rRef1,rRef2);
|
|
SetBoundAndSnapRectsDirty();
|
|
}
|
|
|
|
void SdrMeasureObj::NbcShear(const Point& rRef, Degree100 nAngle, double tn, bool bVShear)
|
|
{
|
|
SdrTextObj::NbcShear(rRef,nAngle,tn,bVShear);
|
|
ShearPoint(m_aPt1,rRef,tn,bVShear);
|
|
ShearPoint(m_aPt2,rRef,tn,bVShear);
|
|
SetBoundAndSnapRectsDirty();
|
|
SetTextDirty();
|
|
}
|
|
|
|
Degree100 SdrMeasureObj::GetRotateAngle() const
|
|
{
|
|
return GetAngle(m_aPt2-m_aPt1);
|
|
}
|
|
|
|
void SdrMeasureObj::RecalcSnapRect()
|
|
{
|
|
ImpMeasureRec aRec;
|
|
ImpMeasurePoly aMPol;
|
|
XPolyPolygon aXPP;
|
|
|
|
ImpTakeAttr(aRec);
|
|
ImpCalcGeometrics(aRec, aMPol);
|
|
aXPP = XPolyPolygon(ImpCalcXPoly(aMPol));
|
|
maSnapRect = aXPP.GetBoundRect();
|
|
}
|
|
|
|
sal_uInt32 SdrMeasureObj::GetSnapPointCount() const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
Point SdrMeasureObj::GetSnapPoint(sal_uInt32 i) const
|
|
{
|
|
if (i==0) return m_aPt1;
|
|
else return m_aPt2;
|
|
}
|
|
|
|
bool SdrMeasureObj::IsPolyObj() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
sal_uInt32 SdrMeasureObj::GetPointCount() const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
Point SdrMeasureObj::GetPoint(sal_uInt32 i) const
|
|
{
|
|
return (0 == i) ? m_aPt1 : m_aPt2;
|
|
}
|
|
|
|
void SdrMeasureObj::NbcSetPoint(const Point& rPnt, sal_uInt32 i)
|
|
{
|
|
if (0 == i)
|
|
m_aPt1=rPnt;
|
|
if (1 == i)
|
|
m_aPt2=rPnt;
|
|
SetBoundAndSnapRectsDirty();
|
|
SetTextDirty();
|
|
}
|
|
|
|
std::unique_ptr<SdrObjGeoData> SdrMeasureObj::NewGeoData() const
|
|
{
|
|
return std::make_unique<SdrMeasureObjGeoData>();
|
|
}
|
|
|
|
void SdrMeasureObj::SaveGeoData(SdrObjGeoData& rGeo) const
|
|
{
|
|
SdrTextObj::SaveGeoData(rGeo);
|
|
SdrMeasureObjGeoData& rMGeo=static_cast<SdrMeasureObjGeoData&>(rGeo);
|
|
rMGeo.aPt1=m_aPt1;
|
|
rMGeo.aPt2=m_aPt2;
|
|
}
|
|
|
|
void SdrMeasureObj::RestoreGeoData(const SdrObjGeoData& rGeo)
|
|
{
|
|
SdrTextObj::RestoreGeoData(rGeo);
|
|
const SdrMeasureObjGeoData& rMGeo=static_cast<const SdrMeasureObjGeoData&>(rGeo);
|
|
m_aPt1=rMGeo.aPt1;
|
|
m_aPt2=rMGeo.aPt2;
|
|
SetTextDirty();
|
|
}
|
|
|
|
rtl::Reference<SdrObject> SdrMeasureObj::DoConvertToPolyObj(bool bBezier, bool bAddText) const
|
|
{
|
|
// get XOR Poly as base
|
|
XPolyPolygon aTmpPolyPolygon(TakeXorPoly());
|
|
|
|
// get local ItemSet and StyleSheet
|
|
SfxItemSet aSet(GetObjectItemSet());
|
|
SfxStyleSheet* pStyleSheet = GetStyleSheet();
|
|
|
|
// prepare group
|
|
rtl::Reference<SdrObjGroup> pGroup(new SdrObjGroup(getSdrModelFromSdrObject()));
|
|
|
|
// prepare parameters
|
|
basegfx::B2DPolyPolygon aPolyPoly;
|
|
rtl::Reference<SdrPathObj> pPath;
|
|
sal_uInt16 nCount(aTmpPolyPolygon.Count());
|
|
sal_uInt16 nLoopStart(0);
|
|
|
|
if(nCount == 3)
|
|
{
|
|
// three lines, first one is the middle one
|
|
aPolyPoly.clear();
|
|
aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon());
|
|
|
|
pPath = new SdrPathObj(
|
|
getSdrModelFromSdrObject(),
|
|
SdrObjKind::PathLine,
|
|
aPolyPoly);
|
|
|
|
pPath->SetMergedItemSet(aSet);
|
|
pPath->SetStyleSheet(pStyleSheet, true);
|
|
pGroup->GetSubList()->NbcInsertObject(pPath.get());
|
|
aSet.Put(XLineStartWidthItem(0));
|
|
aSet.Put(XLineEndWidthItem(0));
|
|
nLoopStart = 1;
|
|
}
|
|
else if(nCount == 4)
|
|
{
|
|
// four lines, middle line with gap, so there are two lines used
|
|
// which have one arrow each
|
|
sal_Int32 nEndWidth = aSet.Get(XATTR_LINEENDWIDTH).GetValue();
|
|
aSet.Put(XLineEndWidthItem(0));
|
|
|
|
aPolyPoly.clear();
|
|
aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon());
|
|
pPath = new SdrPathObj(
|
|
getSdrModelFromSdrObject(),
|
|
SdrObjKind::PathLine,
|
|
aPolyPoly);
|
|
|
|
pPath->SetMergedItemSet(aSet);
|
|
pPath->SetStyleSheet(pStyleSheet, true);
|
|
|
|
pGroup->GetSubList()->NbcInsertObject(pPath.get());
|
|
|
|
aSet.Put(XLineEndWidthItem(nEndWidth));
|
|
aSet.Put(XLineStartWidthItem(0));
|
|
|
|
aPolyPoly.clear();
|
|
aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon());
|
|
pPath = new SdrPathObj(
|
|
getSdrModelFromSdrObject(),
|
|
SdrObjKind::PathLine,
|
|
aPolyPoly);
|
|
|
|
pPath->SetMergedItemSet(aSet);
|
|
pPath->SetStyleSheet(pStyleSheet, true);
|
|
|
|
pGroup->GetSubList()->NbcInsertObject(pPath.get());
|
|
|
|
aSet.Put(XLineEndWidthItem(0));
|
|
nLoopStart = 2;
|
|
}
|
|
else if(nCount == 5)
|
|
{
|
|
// five lines, first two are the outer ones
|
|
sal_Int32 nEndWidth = aSet.Get(XATTR_LINEENDWIDTH).GetValue();
|
|
|
|
aSet.Put(XLineEndWidthItem(0));
|
|
|
|
aPolyPoly.clear();
|
|
aPolyPoly.append(aTmpPolyPolygon[0].getB2DPolygon());
|
|
pPath = new SdrPathObj(
|
|
getSdrModelFromSdrObject(),
|
|
SdrObjKind::PathLine,
|
|
aPolyPoly);
|
|
|
|
pPath->SetMergedItemSet(aSet);
|
|
pPath->SetStyleSheet(pStyleSheet, true);
|
|
|
|
pGroup->GetSubList()->NbcInsertObject(pPath.get());
|
|
|
|
aSet.Put(XLineEndWidthItem(nEndWidth));
|
|
aSet.Put(XLineStartWidthItem(0));
|
|
|
|
aPolyPoly.clear();
|
|
aPolyPoly.append(aTmpPolyPolygon[1].getB2DPolygon());
|
|
pPath = new SdrPathObj(
|
|
getSdrModelFromSdrObject(),
|
|
SdrObjKind::PathLine,
|
|
aPolyPoly);
|
|
|
|
pPath->SetMergedItemSet(aSet);
|
|
pPath->SetStyleSheet(pStyleSheet, true);
|
|
|
|
pGroup->GetSubList()->NbcInsertObject(pPath.get());
|
|
|
|
aSet.Put(XLineEndWidthItem(0));
|
|
nLoopStart = 2;
|
|
}
|
|
|
|
for(;nLoopStart<nCount;nLoopStart++)
|
|
{
|
|
aPolyPoly.clear();
|
|
aPolyPoly.append(aTmpPolyPolygon[nLoopStart].getB2DPolygon());
|
|
pPath = new SdrPathObj(
|
|
getSdrModelFromSdrObject(),
|
|
SdrObjKind::PathLine,
|
|
aPolyPoly);
|
|
|
|
pPath->SetMergedItemSet(aSet);
|
|
pPath->SetStyleSheet(pStyleSheet, true);
|
|
|
|
pGroup->GetSubList()->NbcInsertObject(pPath.get());
|
|
}
|
|
|
|
if(bAddText)
|
|
{
|
|
return ImpConvertAddText(std::move(pGroup), bBezier);
|
|
}
|
|
else
|
|
{
|
|
return pGroup;
|
|
}
|
|
}
|
|
|
|
bool SdrMeasureObj::BegTextEdit(SdrOutliner& rOutl)
|
|
{
|
|
UndirtyText();
|
|
return SdrTextObj::BegTextEdit(rOutl);
|
|
}
|
|
|
|
const Size& SdrMeasureObj::GetTextSize() const
|
|
{
|
|
if (m_bTextDirty) UndirtyText();
|
|
return SdrTextObj::GetTextSize();
|
|
}
|
|
|
|
OutlinerParaObject* SdrMeasureObj::GetOutlinerParaObject() const
|
|
{
|
|
if(m_bTextDirty)
|
|
UndirtyText();
|
|
return SdrTextObj::GetOutlinerParaObject();
|
|
}
|
|
|
|
void SdrMeasureObj::NbcSetOutlinerParaObject(std::optional<OutlinerParaObject> pTextObject, bool bAdjustTextFrameWidthAndHeight)
|
|
{
|
|
SdrTextObj::NbcSetOutlinerParaObject(std::move(pTextObject), bAdjustTextFrameWidthAndHeight);
|
|
if(SdrTextObj::GetOutlinerParaObject())
|
|
SetTextDirty(); // recalculate text
|
|
}
|
|
|
|
void SdrMeasureObj::TakeTextRect( SdrOutliner& rOutliner, tools::Rectangle& rTextRect, bool bNoEditText,
|
|
tools::Rectangle* pAnchorRect, bool bLineWidth ) const
|
|
{
|
|
if (m_bTextDirty) UndirtyText();
|
|
SdrTextObj::TakeTextRect( rOutliner, rTextRect, bNoEditText, pAnchorRect, bLineWidth );
|
|
}
|
|
|
|
void SdrMeasureObj::TakeTextAnchorRect(tools::Rectangle& rAnchorRect) const
|
|
{
|
|
if (m_bTextDirty) UndirtyText();
|
|
SdrTextObj::TakeTextAnchorRect(rAnchorRect);
|
|
}
|
|
|
|
void SdrMeasureObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, tools::Rectangle* pViewInit, tools::Rectangle* pViewMin) const
|
|
{
|
|
if (m_bTextDirty) UndirtyText();
|
|
SdrTextObj::TakeTextEditArea(pPaperMin,pPaperMax,pViewInit,pViewMin);
|
|
}
|
|
|
|
EEAnchorMode SdrMeasureObj::GetOutlinerViewAnchorMode() const
|
|
{
|
|
if (m_bTextDirty) UndirtyText();
|
|
ImpMeasureRec aRec;
|
|
ImpMeasurePoly aMPol;
|
|
ImpTakeAttr(aRec);
|
|
ImpCalcGeometrics(aRec,aMPol);
|
|
|
|
SdrTextHorzAdjust eTH=GetTextHorizontalAdjust();
|
|
SdrTextVertAdjust eTV=GetTextVerticalAdjust();
|
|
css::drawing::MeasureTextHorzPos eMH = aMPol.eUsedTextHPos;
|
|
css::drawing::MeasureTextVertPos eMV = aMPol.eUsedTextVPos;
|
|
bool bTextRota90=aRec.bTextRota90;
|
|
bool bBelowRefEdge=aRec.bBelowRefEdge;
|
|
|
|
// TODO: bTextUpsideDown should be interpreted here!
|
|
if (!bTextRota90) {
|
|
if (eMH==css::drawing::MeasureTextHorzPos_LEFTOUTSIDE) eTH=SDRTEXTHORZADJUST_RIGHT;
|
|
if (eMH==css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE) eTH=SDRTEXTHORZADJUST_LEFT;
|
|
// at eMH==css::drawing::MeasureTextHorzPos_INSIDE we can anchor horizontally
|
|
if (eMV==css::drawing::MeasureTextVertPos_EAST) eTV=SDRTEXTVERTADJUST_BOTTOM;
|
|
if (eMV==css::drawing::MeasureTextVertPos_WEST) eTV=SDRTEXTVERTADJUST_TOP;
|
|
if (eMV==css::drawing::MeasureTextVertPos_CENTERED) eTV=SDRTEXTVERTADJUST_CENTER;
|
|
} else {
|
|
if (eMH==css::drawing::MeasureTextHorzPos_LEFTOUTSIDE) eTV=SDRTEXTVERTADJUST_BOTTOM;
|
|
if (eMH==css::drawing::MeasureTextHorzPos_RIGHTOUTSIDE) eTV=SDRTEXTVERTADJUST_TOP;
|
|
// at eMH==css::drawing::MeasureTextHorzPos_INSIDE we can anchor vertically
|
|
if (!bBelowRefEdge) {
|
|
if (eMV==css::drawing::MeasureTextVertPos_EAST) eTH=SDRTEXTHORZADJUST_LEFT;
|
|
if (eMV==css::drawing::MeasureTextVertPos_WEST) eTH=SDRTEXTHORZADJUST_RIGHT;
|
|
} else {
|
|
if (eMV==css::drawing::MeasureTextVertPos_EAST) eTH=SDRTEXTHORZADJUST_RIGHT;
|
|
if (eMV==css::drawing::MeasureTextVertPos_WEST) eTH=SDRTEXTHORZADJUST_LEFT;
|
|
}
|
|
if (eMV==css::drawing::MeasureTextVertPos_CENTERED) eTH=SDRTEXTHORZADJUST_CENTER;
|
|
}
|
|
|
|
EEAnchorMode eRet=EEAnchorMode::BottomHCenter;
|
|
if (eTH==SDRTEXTHORZADJUST_LEFT) {
|
|
if (eTV==SDRTEXTVERTADJUST_TOP) eRet=EEAnchorMode::TopLeft;
|
|
else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=EEAnchorMode::BottomLeft;
|
|
else eRet=EEAnchorMode::VCenterLeft;
|
|
} else if (eTH==SDRTEXTHORZADJUST_RIGHT) {
|
|
if (eTV==SDRTEXTVERTADJUST_TOP) eRet=EEAnchorMode::TopRight;
|
|
else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=EEAnchorMode::BottomRight;
|
|
else eRet=EEAnchorMode::VCenterRight;
|
|
} else {
|
|
if (eTV==SDRTEXTVERTADJUST_TOP) eRet=EEAnchorMode::TopHCenter;
|
|
else if (eTV==SDRTEXTVERTADJUST_BOTTOM) eRet=EEAnchorMode::BottomHCenter;
|
|
else eRet=EEAnchorMode::VCenterHCenter;
|
|
}
|
|
return eRet;
|
|
}
|
|
|
|
|
|
// #i97878#
|
|
// TRGetBaseGeometry/TRSetBaseGeometry needs to be based on two positions,
|
|
// same as line geometry in SdrPathObj. Thus needs to be overridden and
|
|
// implemented since currently it is derived from SdrTextObj which uses
|
|
// a functionality based on SnapRect which is not useful here
|
|
|
|
bool SdrMeasureObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
|
|
{
|
|
// handle the same as a simple line since the definition is based on two points
|
|
const basegfx::B2DRange aRange(m_aPt1.X(), m_aPt1.Y(), m_aPt2.X(), m_aPt2.Y());
|
|
basegfx::B2DTuple aScale(aRange.getRange());
|
|
basegfx::B2DTuple aTranslate(aRange.getMinimum());
|
|
|
|
// position maybe relative to anchor position, convert
|
|
if( getSdrModelFromSdrObject().IsWriter() )
|
|
{
|
|
if(GetAnchorPos().X() || GetAnchorPos().Y())
|
|
{
|
|
aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
|
|
}
|
|
}
|
|
|
|
// build return value matrix
|
|
rMatrix = basegfx::utils::createScaleTranslateB2DHomMatrix(aScale, aTranslate);
|
|
|
|
return true;
|
|
}
|
|
|
|
void SdrMeasureObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
|
|
{
|
|
// use given transformation to derive the two defining points from unit line
|
|
basegfx::B2DPoint aPosA(rMatrix * basegfx::B2DPoint(0.0, 0.0));
|
|
basegfx::B2DPoint aPosB(rMatrix * basegfx::B2DPoint(1.0, 0.0));
|
|
|
|
if( getSdrModelFromSdrObject().IsWriter() )
|
|
{
|
|
// if anchor is used, make position relative to it
|
|
if(GetAnchorPos().X() || GetAnchorPos().Y())
|
|
{
|
|
const basegfx::B2DVector aAnchorOffset(GetAnchorPos().X(), GetAnchorPos().Y());
|
|
|
|
aPosA += aAnchorOffset;
|
|
aPosB += aAnchorOffset;
|
|
}
|
|
}
|
|
|
|
// derive new model data
|
|
const Point aNewPt1(basegfx::fround<tools::Long>(aPosA.getX()), basegfx::fround<tools::Long>(aPosA.getY()));
|
|
const Point aNewPt2(basegfx::fround<tools::Long>(aPosB.getX()), basegfx::fround<tools::Long>(aPosB.getY()));
|
|
|
|
if(aNewPt1 == m_aPt1 && aNewPt2 == m_aPt2)
|
|
return;
|
|
|
|
// set model values and broadcast
|
|
tools::Rectangle aBoundRect0; if (m_pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
|
|
|
|
m_aPt1 = aNewPt1;
|
|
m_aPt2 = aNewPt2;
|
|
|
|
SetTextDirty();
|
|
ActionChanged();
|
|
SetChanged();
|
|
BroadcastObjectChange();
|
|
SendUserCall(SdrUserCallType::MoveOnly,aBoundRect0);
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|