1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 25 #include "precompiled_sw.hxx" 26 27 #include <AnchorOverlayObject.hxx> 28 #include <SidebarWindowsConsts.hxx> 29 30 #include <swrect.hxx> 31 #include <view.hxx> 32 #include <svx/sdrpaintwindow.hxx> 33 #include <svx/svdview.hxx> 34 #include <svx/sdr/overlay/overlaymanager.hxx> 35 36 #include <sw_primitivetypes2d.hxx> 37 #include <drawinglayer/primitive2d/primitivetools2d.hxx> 38 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> 39 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 40 #include <drawinglayer/primitive2d/shadowprimitive2d.hxx> 41 42 namespace sw { namespace sidebarwindows { 43 44 ////////////////////////////////////////////////////////////////////////////// 45 // helper class: Primitive for discrete visualisation 46 47 class AnchorPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D 48 { 49 private: 50 basegfx::B2DPolygon maTriangle; 51 basegfx::B2DPolygon maLine; 52 basegfx::B2DPolygon maLineTop; 53 const AnchorState maAnchorState; 54 basegfx::BColor maColor; 55 56 // discrete line width 57 double mfDiscreteLineWidth; 58 59 // bitfield 60 bool mbShadow : 1; 61 bool mbLineSolid : 1; 62 63 protected: 64 virtual drawinglayer::primitive2d::Primitive2DSequence create2DDecomposition( 65 const drawinglayer::geometry::ViewInformation2D& rViewInformation) const; 66 67 public: 68 AnchorPrimitive( const basegfx::B2DPolygon& rTriangle, 69 const basegfx::B2DPolygon& rLine, 70 const basegfx::B2DPolygon& rLineTop, 71 AnchorState aAnchorState, 72 const basegfx::BColor& rColor, 73 double fDiscreteLineWidth, 74 bool bShadow, 75 bool bLineSolid ) 76 : drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D(), 77 maTriangle(rTriangle), 78 maLine(rLine), 79 maLineTop(rLineTop), 80 maAnchorState(aAnchorState), 81 maColor(rColor), 82 mfDiscreteLineWidth(fDiscreteLineWidth), 83 mbShadow(bShadow), 84 mbLineSolid(bLineSolid) 85 {} 86 87 // data access 88 const basegfx::B2DPolygon& getTriangle() const { return maTriangle; } 89 const basegfx::B2DPolygon& getLine() const { return maLine; } 90 const basegfx::B2DPolygon& getLineTop() const { return maLineTop; } 91 AnchorState getAnchorState() const { return maAnchorState; } 92 const basegfx::BColor& getColor() const { return maColor; } 93 double getDiscreteLineWidth() const { return mfDiscreteLineWidth; } 94 bool getShadow() const { return mbShadow; } 95 bool getLineSolid() const { return mbLineSolid; } 96 97 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const; 98 99 DeclPrimitrive2DIDBlock() 100 }; 101 102 drawinglayer::primitive2d::Primitive2DSequence AnchorPrimitive::create2DDecomposition( 103 const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const 104 { 105 drawinglayer::primitive2d::Primitive2DSequence aRetval; 106 107 if ( AS_TRI == maAnchorState || 108 AS_ALL == maAnchorState || 109 AS_START == maAnchorState ) 110 { 111 // create triangle 112 const drawinglayer::primitive2d::Primitive2DReference aTriangle( 113 new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( 114 basegfx::B2DPolyPolygon(getTriangle()), 115 getColor())); 116 117 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aTriangle); 118 } 119 120 // prepare view-independent LineWidth and color 121 const drawinglayer::attribute::LineAttribute aLineAttribute( 122 getColor(), 123 getDiscreteLineWidth() * getDiscreteUnit()); 124 125 if ( AS_ALL == maAnchorState || 126 AS_START == maAnchorState ) 127 { 128 // create line start 129 if(getLineSolid()) 130 { 131 const drawinglayer::primitive2d::Primitive2DReference aSolidLine( 132 new drawinglayer::primitive2d::PolygonStrokePrimitive2D( 133 getLine(), 134 aLineAttribute)); 135 136 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aSolidLine); 137 } 138 else 139 { 140 ::std::vector< double > aDotDashArray; 141 const double fDistance(3.0 * 15.0); 142 const double fDashLen(5.0 * 15.0); 143 144 aDotDashArray.push_back(fDashLen); 145 aDotDashArray.push_back(fDistance); 146 147 const drawinglayer::attribute::StrokeAttribute aStrokeAttribute( 148 aDotDashArray, 149 fDistance + fDashLen); 150 151 const drawinglayer::primitive2d::Primitive2DReference aStrokedLine( 152 new drawinglayer::primitive2d::PolygonStrokePrimitive2D( 153 getLine(), 154 aLineAttribute, 155 aStrokeAttribute)); 156 157 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aStrokedLine); 158 } 159 } 160 161 if(aRetval.hasElements() && getShadow()) 162 { 163 // shadow is only for triangle and line start, and in upper left 164 // and lower right direction, in different colors 165 const double fColorChange(20.0 / 255.0); 166 const basegfx::B3DTuple aColorChange(fColorChange, fColorChange, fColorChange); 167 basegfx::BColor aLighterColor(getColor() + aColorChange); 168 basegfx::BColor aDarkerColor(getColor() - aColorChange); 169 170 aLighterColor.clamp(); 171 aDarkerColor.clamp(); 172 173 // create shadow sequence 174 drawinglayer::primitive2d::Primitive2DSequence aShadows(2); 175 basegfx::B2DHomMatrix aTransform; 176 177 aTransform.set(0, 2, -getDiscreteUnit()); 178 aTransform.set(1, 2, -getDiscreteUnit()); 179 180 aShadows[0] = drawinglayer::primitive2d::Primitive2DReference( 181 new drawinglayer::primitive2d::ShadowPrimitive2D( 182 aTransform, 183 aLighterColor, 184 aRetval)); 185 186 aTransform.set(0, 2, getDiscreteUnit()); 187 aTransform.set(1, 2, getDiscreteUnit()); 188 189 aShadows[1] = drawinglayer::primitive2d::Primitive2DReference( 190 new drawinglayer::primitive2d::ShadowPrimitive2D( 191 aTransform, 192 aDarkerColor, 193 aRetval)); 194 195 // add shadow before geometry to make it be proccessed first 196 const drawinglayer::primitive2d::Primitive2DSequence aTemporary(aRetval); 197 198 aRetval = aShadows; 199 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, aTemporary); 200 } 201 202 if ( AS_ALL == maAnchorState || 203 AS_END == maAnchorState ) 204 { 205 // LineTop has to be created, too, but uses no shadow, so add after 206 // the other parts are created 207 const drawinglayer::primitive2d::Primitive2DReference aLineTop( 208 new drawinglayer::primitive2d::PolygonStrokePrimitive2D( 209 getLineTop(), 210 aLineAttribute)); 211 212 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aLineTop); 213 } 214 215 return aRetval; 216 } 217 218 bool AnchorPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const 219 { 220 if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) 221 { 222 const AnchorPrimitive& rCompare = static_cast< const AnchorPrimitive& >(rPrimitive); 223 224 return (getTriangle() == rCompare.getTriangle() 225 && getLine() == rCompare.getLine() 226 && getLineTop() == rCompare.getLineTop() 227 && getAnchorState() == rCompare.getAnchorState() 228 && getColor() == rCompare.getColor() 229 && getDiscreteLineWidth() == rCompare.getDiscreteLineWidth() 230 && getShadow() == rCompare.getShadow() 231 && getLineSolid() == rCompare.getLineSolid()); 232 } 233 234 return false; 235 } 236 237 ImplPrimitrive2DIDBlock(AnchorPrimitive, PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE) 238 239 /****** AnchorOverlayObject ***********************************************************/ 240 /*static*/ AnchorOverlayObject* AnchorOverlayObject::CreateAnchorOverlayObject( 241 SwView& rDocView, 242 const SwRect& aAnchorRect, 243 const long& aPageBorder, 244 const Point& aLineStart, 245 const Point& aLineEnd, 246 const Color& aColorAnchor ) 247 { 248 AnchorOverlayObject* pAnchorOverlayObject( 0 ); 249 if ( rDocView.GetDrawView() ) 250 { 251 SdrPaintWindow* pPaintWindow = rDocView.GetDrawView()->GetPaintWindow(0); 252 if( pPaintWindow ) 253 { 254 sdr::overlay::OverlayManager* pOverlayManager = pPaintWindow->GetOverlayManager(); 255 256 if ( pOverlayManager ) 257 { 258 pAnchorOverlayObject = new AnchorOverlayObject( 259 basegfx::B2DPoint( aAnchorRect.Left() , aAnchorRect.Bottom()-5*15), 260 basegfx::B2DPoint( aAnchorRect.Left()-5*15 , aAnchorRect.Bottom()+5*15), 261 basegfx::B2DPoint( aAnchorRect.Left()+5*15 , aAnchorRect.Bottom()+5*15), 262 basegfx::B2DPoint( aAnchorRect.Left(), aAnchorRect.Bottom()+2*15), 263 basegfx::B2DPoint( aPageBorder ,aAnchorRect.Bottom()+2*15), 264 basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()), 265 basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()) , 266 aColorAnchor, 267 false, 268 false); 269 pOverlayManager->add(*pAnchorOverlayObject); 270 } 271 } 272 } 273 274 return pAnchorOverlayObject; 275 } 276 277 /*static*/ void AnchorOverlayObject::DestroyAnchorOverlayObject( AnchorOverlayObject* pAnchor ) 278 { 279 if ( pAnchor ) 280 { 281 if ( pAnchor->getOverlayManager() ) 282 { 283 // remove this object from the chain 284 pAnchor->getOverlayManager()->remove(*pAnchor); 285 } 286 delete pAnchor; 287 } 288 } 289 290 AnchorOverlayObject::AnchorOverlayObject( const basegfx::B2DPoint& rBasePos, 291 const basegfx::B2DPoint& rSecondPos, 292 const basegfx::B2DPoint& rThirdPos, 293 const basegfx::B2DPoint& rFourthPos, 294 const basegfx::B2DPoint& rFifthPos, 295 const basegfx::B2DPoint& rSixthPos, 296 const basegfx::B2DPoint& rSeventhPos, 297 const Color aBaseColor, 298 const bool bShadowedEffect, 299 const bool bLineSolid) 300 : OverlayObjectWithBasePosition( rBasePos, aBaseColor ) 301 , maSecondPosition(rSecondPos) 302 , maThirdPosition(rThirdPos) 303 , maFourthPosition(rFourthPos) 304 , maFifthPosition(rFifthPos) 305 , maSixthPosition(rSixthPos) 306 , maSeventhPosition(rSeventhPos) 307 , maTriangle() 308 , maLine() 309 , maLineTop() 310 , mHeight(0) 311 , mAnchorState(AS_ALL) 312 , mbShadowedEffect(bShadowedEffect) 313 , mbLineSolid(bLineSolid) 314 { 315 } 316 317 AnchorOverlayObject::~AnchorOverlayObject() 318 { 319 } 320 321 void AnchorOverlayObject::implEnsureGeometry() 322 { 323 if(!maTriangle.count()) 324 { 325 maTriangle.append(getBasePosition()); 326 maTriangle.append(GetSecondPosition()); 327 maTriangle.append(GetThirdPosition()); 328 maTriangle.setClosed(true); 329 } 330 331 if(!maLine.count()) 332 { 333 maLine.append(GetFourthPosition()); 334 maLine.append(GetFifthPosition()); 335 maLine.append(GetSixthPosition()); 336 } 337 338 if(!maLineTop.count()) 339 { 340 maLineTop.append(GetSixthPosition()); 341 maLineTop.append(GetSeventhPosition()); 342 } 343 } 344 345 void AnchorOverlayObject::implResetGeometry() 346 { 347 maTriangle.clear(); 348 maLine.clear(); 349 maLineTop.clear(); 350 } 351 352 drawinglayer::primitive2d::Primitive2DSequence AnchorOverlayObject::createOverlayObjectPrimitive2DSequence() 353 { 354 implEnsureGeometry(); 355 356 static double aDiscreteLineWidth(1.6); 357 const drawinglayer::primitive2d::Primitive2DReference aReference( 358 new AnchorPrimitive( maTriangle, 359 maLine, 360 maLineTop, 361 GetAnchorState(), 362 getBaseColor().getBColor(), 363 ANCHORLINE_WIDTH * aDiscreteLineWidth, 364 getShadowedEffect(), 365 getLineSolid()) ); 366 367 return drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1); 368 } 369 370 void AnchorOverlayObject::SetAllPosition( const basegfx::B2DPoint& rPoint1, 371 const basegfx::B2DPoint& rPoint2, 372 const basegfx::B2DPoint& rPoint3, 373 const basegfx::B2DPoint& rPoint4, 374 const basegfx::B2DPoint& rPoint5, 375 const basegfx::B2DPoint& rPoint6, 376 const basegfx::B2DPoint& rPoint7) 377 { 378 if ( rPoint1 != getBasePosition() || 379 rPoint2 != GetSecondPosition() || 380 rPoint3 != GetThirdPosition() || 381 rPoint4 != GetFourthPosition() || 382 rPoint5 != GetFifthPosition() || 383 rPoint6 != GetSixthPosition() || 384 rPoint7 != GetSeventhPosition() ) 385 { 386 maBasePosition = rPoint1; 387 maSecondPosition = rPoint2; 388 maThirdPosition = rPoint3; 389 maFourthPosition = rPoint4; 390 maFifthPosition = rPoint5; 391 maSixthPosition = rPoint6; 392 maSeventhPosition = rPoint7; 393 394 implResetGeometry(); 395 objectChange(); 396 } 397 } 398 399 void AnchorOverlayObject::SetSixthPosition(const basegfx::B2DPoint& rNew) 400 { 401 if(rNew != maSixthPosition) 402 { 403 maSixthPosition = rNew; 404 implResetGeometry(); 405 objectChange(); 406 } 407 } 408 409 void AnchorOverlayObject::SetSeventhPosition(const basegfx::B2DPoint& rNew) 410 { 411 if(rNew != maSeventhPosition) 412 { 413 maSeventhPosition = rNew; 414 implResetGeometry(); 415 objectChange(); 416 } 417 } 418 419 void AnchorOverlayObject::SetTriPosition(const basegfx::B2DPoint& rPoint1,const basegfx::B2DPoint& rPoint2,const basegfx::B2DPoint& rPoint3, 420 const basegfx::B2DPoint& rPoint4,const basegfx::B2DPoint& rPoint5) 421 { 422 if(rPoint1 != getBasePosition() 423 || rPoint2 != GetSecondPosition() 424 || rPoint3 != GetThirdPosition() 425 || rPoint4 != GetFourthPosition() 426 || rPoint5 != GetFifthPosition()) 427 { 428 maBasePosition = rPoint1; 429 maSecondPosition = rPoint2; 430 maThirdPosition = rPoint3; 431 maFourthPosition = rPoint4; 432 maFifthPosition = rPoint5; 433 434 implResetGeometry(); 435 objectChange(); 436 } 437 } 438 439 void AnchorOverlayObject::setLineSolid( const bool bNew ) 440 { 441 if ( bNew != getLineSolid() ) 442 { 443 mbLineSolid = bNew; 444 objectChange(); 445 } 446 } 447 448 void AnchorOverlayObject::SetAnchorState( const AnchorState aState) 449 { 450 if ( mAnchorState != aState) 451 { 452 mAnchorState = aState; 453 objectChange(); 454 } 455 } 456 457 } } // end of namespace sw::annotation 458 459