blob: afa8bfbd39bcece55fa1d1bd3e5bb4f2808cbbfa [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.
*
*************************************************************/
#include "precompiled_sw.hxx"
#include <AnchorOverlayObject.hxx>
#include <SidebarWindowsConsts.hxx>
#include <swrect.hxx>
#include <view.hxx>
#include <svx/sdrpaintwindow.hxx>
#include <svx/svdview.hxx>
#include <svx/sdr/overlay/overlaymanager.hxx>
#include <sw_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/primitivetools2d.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/shadowprimitive2d.hxx>
namespace sw { namespace sidebarwindows {
//////////////////////////////////////////////////////////////////////////////
// helper class: Primitive for discrete visualisation
class AnchorPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D
{
private:
basegfx::B2DPolygon maTriangle;
basegfx::B2DPolygon maLine;
basegfx::B2DPolygon maLineTop;
const AnchorState maAnchorState;
basegfx::BColor maColor;
// discrete line width
double mfDiscreteLineWidth;
// bitfield
bool mbShadow : 1;
bool mbLineSolid : 1;
protected:
virtual drawinglayer::primitive2d::Primitive2DSequence create2DDecomposition(
const drawinglayer::geometry::ViewInformation2D& rViewInformation) const;
public:
AnchorPrimitive( const basegfx::B2DPolygon& rTriangle,
const basegfx::B2DPolygon& rLine,
const basegfx::B2DPolygon& rLineTop,
AnchorState aAnchorState,
const basegfx::BColor& rColor,
double fDiscreteLineWidth,
bool bShadow,
bool bLineSolid )
: drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D(),
maTriangle(rTriangle),
maLine(rLine),
maLineTop(rLineTop),
maAnchorState(aAnchorState),
maColor(rColor),
mfDiscreteLineWidth(fDiscreteLineWidth),
mbShadow(bShadow),
mbLineSolid(bLineSolid)
{}
// data access
const basegfx::B2DPolygon& getTriangle() const { return maTriangle; }
const basegfx::B2DPolygon& getLine() const { return maLine; }
const basegfx::B2DPolygon& getLineTop() const { return maLineTop; }
AnchorState getAnchorState() const { return maAnchorState; }
const basegfx::BColor& getColor() const { return maColor; }
double getDiscreteLineWidth() const { return mfDiscreteLineWidth; }
bool getShadow() const { return mbShadow; }
bool getLineSolid() const { return mbLineSolid; }
virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
DeclPrimitrive2DIDBlock()
};
drawinglayer::primitive2d::Primitive2DSequence AnchorPrimitive::create2DDecomposition(
const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const
{
drawinglayer::primitive2d::Primitive2DSequence aRetval;
if ( AS_TRI == maAnchorState ||
AS_ALL == maAnchorState ||
AS_START == maAnchorState )
{
// create triangle
const drawinglayer::primitive2d::Primitive2DReference aTriangle(
new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
basegfx::B2DPolyPolygon(getTriangle()),
getColor()));
drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aTriangle);
}
// prepare view-independent LineWidth and color
const drawinglayer::attribute::LineAttribute aLineAttribute(
getColor(),
getDiscreteLineWidth() * getDiscreteUnit());
if ( AS_ALL == maAnchorState ||
AS_START == maAnchorState )
{
// create line start
if(getLineSolid())
{
const drawinglayer::primitive2d::Primitive2DReference aSolidLine(
new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
getLine(),
aLineAttribute));
drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aSolidLine);
}
else
{
::std::vector< double > aDotDashArray;
const double fDistance(3.0 * 15.0);
const double fDashLen(5.0 * 15.0);
aDotDashArray.push_back(fDashLen);
aDotDashArray.push_back(fDistance);
const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(
aDotDashArray,
fDistance + fDashLen);
const drawinglayer::primitive2d::Primitive2DReference aStrokedLine(
new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
getLine(),
aLineAttribute,
aStrokeAttribute));
drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aStrokedLine);
}
}
if(aRetval.hasElements() && getShadow())
{
// shadow is only for triangle and line start, and in upper left
// and lower right direction, in different colors
const double fColorChange(20.0 / 255.0);
const basegfx::B3DTuple aColorChange(fColorChange, fColorChange, fColorChange);
basegfx::BColor aLighterColor(getColor() + aColorChange);
basegfx::BColor aDarkerColor(getColor() - aColorChange);
aLighterColor.clamp();
aDarkerColor.clamp();
// create shadow sequence
drawinglayer::primitive2d::Primitive2DSequence aShadows(2);
basegfx::B2DHomMatrix aTransform;
aTransform.set(0, 2, -getDiscreteUnit());
aTransform.set(1, 2, -getDiscreteUnit());
aShadows[0] = drawinglayer::primitive2d::Primitive2DReference(
new drawinglayer::primitive2d::ShadowPrimitive2D(
aTransform,
aLighterColor,
aRetval));
aTransform.set(0, 2, getDiscreteUnit());
aTransform.set(1, 2, getDiscreteUnit());
aShadows[1] = drawinglayer::primitive2d::Primitive2DReference(
new drawinglayer::primitive2d::ShadowPrimitive2D(
aTransform,
aDarkerColor,
aRetval));
// add shadow before geometry to make it be proccessed first
const drawinglayer::primitive2d::Primitive2DSequence aTemporary(aRetval);
aRetval = aShadows;
drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, aTemporary);
}
if ( AS_ALL == maAnchorState ||
AS_END == maAnchorState )
{
// LineTop has to be created, too, but uses no shadow, so add after
// the other parts are created
const drawinglayer::primitive2d::Primitive2DReference aLineTop(
new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
getLineTop(),
aLineAttribute));
drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aLineTop);
}
return aRetval;
}
bool AnchorPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const
{
if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
{
const AnchorPrimitive& rCompare = static_cast< const AnchorPrimitive& >(rPrimitive);
return (getTriangle() == rCompare.getTriangle()
&& getLine() == rCompare.getLine()
&& getLineTop() == rCompare.getLineTop()
&& getAnchorState() == rCompare.getAnchorState()
&& getColor() == rCompare.getColor()
&& getDiscreteLineWidth() == rCompare.getDiscreteLineWidth()
&& getShadow() == rCompare.getShadow()
&& getLineSolid() == rCompare.getLineSolid());
}
return false;
}
ImplPrimitrive2DIDBlock(AnchorPrimitive, PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE)
/****** AnchorOverlayObject ***********************************************************/
/*static*/ AnchorOverlayObject* AnchorOverlayObject::CreateAnchorOverlayObject(
SwView& rDocView,
const SwRect& aAnchorRect,
const long& aPageBorder,
const Point& aLineStart,
const Point& aLineEnd,
const Color& aColorAnchor )
{
AnchorOverlayObject* pAnchorOverlayObject( 0 );
if ( rDocView.GetDrawView() )
{
SdrPaintWindow* pPaintWindow = rDocView.GetDrawView()->GetPaintWindow(0);
if( pPaintWindow )
{
sdr::overlay::OverlayManager* pOverlayManager = pPaintWindow->GetOverlayManager();
if ( pOverlayManager )
{
pAnchorOverlayObject = new AnchorOverlayObject(
basegfx::B2DPoint( aAnchorRect.Left() , aAnchorRect.Bottom()-5*15),
basegfx::B2DPoint( aAnchorRect.Left()-5*15 , aAnchorRect.Bottom()+5*15),
basegfx::B2DPoint( aAnchorRect.Left()+5*15 , aAnchorRect.Bottom()+5*15),
basegfx::B2DPoint( aAnchorRect.Left(), aAnchorRect.Bottom()+2*15),
basegfx::B2DPoint( aPageBorder ,aAnchorRect.Bottom()+2*15),
basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()) ,
aColorAnchor,
false,
false);
pOverlayManager->add(*pAnchorOverlayObject);
}
}
}
return pAnchorOverlayObject;
}
/*static*/ void AnchorOverlayObject::DestroyAnchorOverlayObject( AnchorOverlayObject* pAnchor )
{
if ( pAnchor )
{
if ( pAnchor->getOverlayManager() )
{
// remove this object from the chain
pAnchor->getOverlayManager()->remove(*pAnchor);
}
delete pAnchor;
}
}
AnchorOverlayObject::AnchorOverlayObject( const basegfx::B2DPoint& rBasePos,
const basegfx::B2DPoint& rSecondPos,
const basegfx::B2DPoint& rThirdPos,
const basegfx::B2DPoint& rFourthPos,
const basegfx::B2DPoint& rFifthPos,
const basegfx::B2DPoint& rSixthPos,
const basegfx::B2DPoint& rSeventhPos,
const Color aBaseColor,
const bool bShadowedEffect,
const bool bLineSolid)
: OverlayObjectWithBasePosition( rBasePos, aBaseColor )
, maSecondPosition(rSecondPos)
, maThirdPosition(rThirdPos)
, maFourthPosition(rFourthPos)
, maFifthPosition(rFifthPos)
, maSixthPosition(rSixthPos)
, maSeventhPosition(rSeventhPos)
, maTriangle()
, maLine()
, maLineTop()
, mHeight(0)
, mAnchorState(AS_ALL)
, mbShadowedEffect(bShadowedEffect)
, mbLineSolid(bLineSolid)
{
}
AnchorOverlayObject::~AnchorOverlayObject()
{
}
void AnchorOverlayObject::implEnsureGeometry()
{
if(!maTriangle.count())
{
maTriangle.append(getBasePosition());
maTriangle.append(GetSecondPosition());
maTriangle.append(GetThirdPosition());
maTriangle.setClosed(true);
}
if(!maLine.count())
{
maLine.append(GetFourthPosition());
maLine.append(GetFifthPosition());
maLine.append(GetSixthPosition());
}
if(!maLineTop.count())
{
maLineTop.append(GetSixthPosition());
maLineTop.append(GetSeventhPosition());
}
}
void AnchorOverlayObject::implResetGeometry()
{
maTriangle.clear();
maLine.clear();
maLineTop.clear();
}
drawinglayer::primitive2d::Primitive2DSequence AnchorOverlayObject::createOverlayObjectPrimitive2DSequence()
{
implEnsureGeometry();
static double aDiscreteLineWidth(1.6);
const drawinglayer::primitive2d::Primitive2DReference aReference(
new AnchorPrimitive( maTriangle,
maLine,
maLineTop,
GetAnchorState(),
getBaseColor().getBColor(),
ANCHORLINE_WIDTH * aDiscreteLineWidth,
getShadowedEffect(),
getLineSolid()) );
return drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1);
}
void AnchorOverlayObject::SetAllPosition( const basegfx::B2DPoint& rPoint1,
const basegfx::B2DPoint& rPoint2,
const basegfx::B2DPoint& rPoint3,
const basegfx::B2DPoint& rPoint4,
const basegfx::B2DPoint& rPoint5,
const basegfx::B2DPoint& rPoint6,
const basegfx::B2DPoint& rPoint7)
{
if ( rPoint1 != getBasePosition() ||
rPoint2 != GetSecondPosition() ||
rPoint3 != GetThirdPosition() ||
rPoint4 != GetFourthPosition() ||
rPoint5 != GetFifthPosition() ||
rPoint6 != GetSixthPosition() ||
rPoint7 != GetSeventhPosition() )
{
maBasePosition = rPoint1;
maSecondPosition = rPoint2;
maThirdPosition = rPoint3;
maFourthPosition = rPoint4;
maFifthPosition = rPoint5;
maSixthPosition = rPoint6;
maSeventhPosition = rPoint7;
implResetGeometry();
objectChange();
}
}
void AnchorOverlayObject::SetSixthPosition(const basegfx::B2DPoint& rNew)
{
if(rNew != maSixthPosition)
{
maSixthPosition = rNew;
implResetGeometry();
objectChange();
}
}
void AnchorOverlayObject::SetSeventhPosition(const basegfx::B2DPoint& rNew)
{
if(rNew != maSeventhPosition)
{
maSeventhPosition = rNew;
implResetGeometry();
objectChange();
}
}
void AnchorOverlayObject::SetTriPosition(const basegfx::B2DPoint& rPoint1,const basegfx::B2DPoint& rPoint2,const basegfx::B2DPoint& rPoint3,
const basegfx::B2DPoint& rPoint4,const basegfx::B2DPoint& rPoint5)
{
if(rPoint1 != getBasePosition()
|| rPoint2 != GetSecondPosition()
|| rPoint3 != GetThirdPosition()
|| rPoint4 != GetFourthPosition()
|| rPoint5 != GetFifthPosition())
{
maBasePosition = rPoint1;
maSecondPosition = rPoint2;
maThirdPosition = rPoint3;
maFourthPosition = rPoint4;
maFifthPosition = rPoint5;
implResetGeometry();
objectChange();
}
}
void AnchorOverlayObject::setLineSolid( const bool bNew )
{
if ( bNew != getLineSolid() )
{
mbLineSolid = bNew;
objectChange();
}
}
void AnchorOverlayObject::SetAnchorState( const AnchorState aState)
{
if ( mAnchorState != aState)
{
mAnchorState = aState;
objectChange();
}
}
} } // end of namespace sw::annotation