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 mfLogicLineWidth; 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 fLogicLineWidth, 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 mfLogicLineWidth(fLogicLineWidth), 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 getLogicLineWidth() const { return mfLogicLineWidth; } 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 if ( AS_ALL == maAnchorState || 121 AS_START == maAnchorState ) 122 { 123 // create line start 124 const drawinglayer::attribute::LineAttribute aLineAttribute( 125 getColor(), 126 getLogicLineWidth() / (basegfx::fTools::equalZero(getDiscreteUnit()) ? 1.0 : getDiscreteUnit())); 127 128 if(getLineSolid()) 129 { 130 const drawinglayer::primitive2d::Primitive2DReference aSolidLine( 131 new drawinglayer::primitive2d::PolygonStrokePrimitive2D( 132 getLine(), 133 aLineAttribute)); 134 135 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aSolidLine); 136 } 137 else 138 { 139 ::std::vector< double > aDotDashArray; 140 const double fDistance(3.0 * 15.0); 141 const double fDashLen(5.0 * 15.0); 142 143 aDotDashArray.push_back(fDashLen); 144 aDotDashArray.push_back(fDistance); 145 146 const drawinglayer::attribute::StrokeAttribute aStrokeAttribute( 147 aDotDashArray, 148 fDistance + fDashLen); 149 150 const drawinglayer::primitive2d::Primitive2DReference aStrokedLine( 151 new drawinglayer::primitive2d::PolygonStrokePrimitive2D( 152 getLine(), 153 aLineAttribute, 154 aStrokeAttribute)); 155 156 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aStrokedLine); 157 } 158 } 159 160 if(aRetval.hasElements() && getShadow()) 161 { 162 // shadow is only for triangle and line start, and in upper left 163 // and lower right direction, in different colors 164 const double fColorChange(20.0 / 255.0); 165 const basegfx::B3DTuple aColorChange(fColorChange, fColorChange, fColorChange); 166 basegfx::BColor aLighterColor(getColor() + aColorChange); 167 basegfx::BColor aDarkerColor(getColor() - aColorChange); 168 169 aLighterColor.clamp(); 170 aDarkerColor.clamp(); 171 172 // create shadow sequence 173 drawinglayer::primitive2d::Primitive2DSequence aShadows(2); 174 basegfx::B2DHomMatrix aTransform; 175 176 aTransform.set(0, 2, -getDiscreteUnit()); 177 aTransform.set(1, 2, -getDiscreteUnit()); 178 179 aShadows[0] = drawinglayer::primitive2d::Primitive2DReference( 180 new drawinglayer::primitive2d::ShadowPrimitive2D( 181 aTransform, 182 aLighterColor, 183 aRetval)); 184 185 aTransform.set(0, 2, getDiscreteUnit()); 186 aTransform.set(1, 2, getDiscreteUnit()); 187 188 aShadows[1] = drawinglayer::primitive2d::Primitive2DReference( 189 new drawinglayer::primitive2d::ShadowPrimitive2D( 190 aTransform, 191 aDarkerColor, 192 aRetval)); 193 194 // add shadow before geometry to make it be proccessed first 195 const drawinglayer::primitive2d::Primitive2DSequence aTemporary(aRetval); 196 197 aRetval = aShadows; 198 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, aTemporary); 199 } 200 201 if ( AS_ALL == maAnchorState || 202 AS_END == maAnchorState ) 203 { 204 // LineTop has to be created, too, but uses no shadow, so add after 205 // the other parts are created 206 const drawinglayer::attribute::LineAttribute aLineAttribute( 207 getColor(), 208 getLogicLineWidth() / (basegfx::fTools::equalZero(getDiscreteUnit()) ? 1.0 : getDiscreteUnit())); 209 210 const drawinglayer::primitive2d::Primitive2DReference aLineTop( 211 new drawinglayer::primitive2d::PolygonStrokePrimitive2D( 212 getLineTop(), 213 aLineAttribute)); 214 215 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aLineTop); 216 } 217 218 return aRetval; 219 } 220 221 bool AnchorPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const 222 { 223 if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) 224 { 225 const AnchorPrimitive& rCompare = static_cast< const AnchorPrimitive& >(rPrimitive); 226 227 return (getTriangle() == rCompare.getTriangle() 228 && getLine() == rCompare.getLine() 229 && getLineTop() == rCompare.getLineTop() 230 && getAnchorState() == rCompare.getAnchorState() 231 && getColor() == rCompare.getColor() 232 && getLogicLineWidth() == rCompare.getLogicLineWidth() 233 && getShadow() == rCompare.getShadow() 234 && getLineSolid() == rCompare.getLineSolid()); 235 } 236 237 return false; 238 } 239 240 ImplPrimitrive2DIDBlock(AnchorPrimitive, PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE) 241 242 /****** AnchorOverlayObject ***********************************************************/ 243 /*static*/ AnchorOverlayObject* AnchorOverlayObject::CreateAnchorOverlayObject( 244 SwView& rDocView, 245 const SwRect& aAnchorRect, 246 const long& aPageBorder, 247 const Point& aLineStart, 248 const Point& aLineEnd, 249 const Color& aColorAnchor ) 250 { 251 AnchorOverlayObject* pAnchorOverlayObject( 0 ); 252 if ( rDocView.GetDrawView() ) 253 { 254 SdrPaintWindow* pPaintWindow = rDocView.GetDrawView()->GetPaintWindow(0); 255 if( pPaintWindow ) 256 { 257 sdr::overlay::OverlayManager* pOverlayManager = pPaintWindow->GetOverlayManager(); 258 259 if ( pOverlayManager ) 260 { 261 pAnchorOverlayObject = new AnchorOverlayObject( 262 basegfx::B2DPoint( aAnchorRect.Left() , aAnchorRect.Bottom()-5*15), 263 basegfx::B2DPoint( aAnchorRect.Left()-5*15 , aAnchorRect.Bottom()+5*15), 264 basegfx::B2DPoint( aAnchorRect.Left()+5*15 , aAnchorRect.Bottom()+5*15), 265 basegfx::B2DPoint( aAnchorRect.Left(), aAnchorRect.Bottom()+2*15), 266 basegfx::B2DPoint( aPageBorder ,aAnchorRect.Bottom()+2*15), 267 basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()), 268 basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()) , 269 aColorAnchor, 270 false, 271 false); 272 pOverlayManager->add(*pAnchorOverlayObject); 273 } 274 } 275 } 276 277 return pAnchorOverlayObject; 278 } 279 280 /*static*/ void AnchorOverlayObject::DestroyAnchorOverlayObject( AnchorOverlayObject* pAnchor ) 281 { 282 if ( pAnchor ) 283 { 284 if ( pAnchor->getOverlayManager() ) 285 { 286 // remove this object from the chain 287 pAnchor->getOverlayManager()->remove(*pAnchor); 288 } 289 delete pAnchor; 290 } 291 } 292 293 AnchorOverlayObject::AnchorOverlayObject( const basegfx::B2DPoint& rBasePos, 294 const basegfx::B2DPoint& rSecondPos, 295 const basegfx::B2DPoint& rThirdPos, 296 const basegfx::B2DPoint& rFourthPos, 297 const basegfx::B2DPoint& rFifthPos, 298 const basegfx::B2DPoint& rSixthPos, 299 const basegfx::B2DPoint& rSeventhPos, 300 const Color aBaseColor, 301 const bool bShadowedEffect, 302 const bool bLineSolid) 303 : OverlayObjectWithBasePosition( rBasePos, aBaseColor ) 304 , maSecondPosition(rSecondPos) 305 , maThirdPosition(rThirdPos) 306 , maFourthPosition(rFourthPos) 307 , maFifthPosition(rFifthPos) 308 , maSixthPosition(rSixthPos) 309 , maSeventhPosition(rSeventhPos) 310 , maTriangle() 311 , maLine() 312 , maLineTop() 313 , mHeight(0) 314 , mAnchorState(AS_ALL) 315 , mbShadowedEffect(bShadowedEffect) 316 , mbLineSolid(bLineSolid) 317 { 318 } 319 320 AnchorOverlayObject::~AnchorOverlayObject() 321 { 322 } 323 324 void AnchorOverlayObject::implEnsureGeometry() 325 { 326 if(!maTriangle.count()) 327 { 328 maTriangle.append(getBasePosition()); 329 maTriangle.append(GetSecondPosition()); 330 maTriangle.append(GetThirdPosition()); 331 maTriangle.setClosed(true); 332 } 333 334 if(!maLine.count()) 335 { 336 maLine.append(GetFourthPosition()); 337 maLine.append(GetFifthPosition()); 338 maLine.append(GetSixthPosition()); 339 } 340 341 if(!maLineTop.count()) 342 { 343 maLineTop.append(GetSixthPosition()); 344 maLineTop.append(GetSeventhPosition()); 345 } 346 } 347 348 void AnchorOverlayObject::implResetGeometry() 349 { 350 maTriangle.clear(); 351 maLine.clear(); 352 maLineTop.clear(); 353 } 354 355 drawinglayer::primitive2d::Primitive2DSequence AnchorOverlayObject::createOverlayObjectPrimitive2DSequence() 356 { 357 implEnsureGeometry(); 358 359 const drawinglayer::primitive2d::Primitive2DReference aReference( 360 new AnchorPrimitive( maTriangle, 361 maLine, 362 maLineTop, 363 GetAnchorState(), 364 getBaseColor().getBColor(), 365 ANCHORLINE_WIDTH * 15.0, 366 getShadowedEffect(), 367 getLineSolid()) ); 368 369 return drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1); 370 } 371 372 void AnchorOverlayObject::SetAllPosition( const basegfx::B2DPoint& rPoint1, 373 const basegfx::B2DPoint& rPoint2, 374 const basegfx::B2DPoint& rPoint3, 375 const basegfx::B2DPoint& rPoint4, 376 const basegfx::B2DPoint& rPoint5, 377 const basegfx::B2DPoint& rPoint6, 378 const basegfx::B2DPoint& rPoint7) 379 { 380 if ( rPoint1 != getBasePosition() || 381 rPoint2 != GetSecondPosition() || 382 rPoint3 != GetThirdPosition() || 383 rPoint4 != GetFourthPosition() || 384 rPoint5 != GetFifthPosition() || 385 rPoint6 != GetSixthPosition() || 386 rPoint7 != GetSeventhPosition() ) 387 { 388 maBasePosition = rPoint1; 389 maSecondPosition = rPoint2; 390 maThirdPosition = rPoint3; 391 maFourthPosition = rPoint4; 392 maFifthPosition = rPoint5; 393 maSixthPosition = rPoint6; 394 maSeventhPosition = rPoint7; 395 396 implResetGeometry(); 397 objectChange(); 398 } 399 } 400 401 void AnchorOverlayObject::SetSixthPosition(const basegfx::B2DPoint& rNew) 402 { 403 if(rNew != maSixthPosition) 404 { 405 maSixthPosition = rNew; 406 implResetGeometry(); 407 objectChange(); 408 } 409 } 410 411 void AnchorOverlayObject::SetSeventhPosition(const basegfx::B2DPoint& rNew) 412 { 413 if(rNew != maSeventhPosition) 414 { 415 maSeventhPosition = rNew; 416 implResetGeometry(); 417 objectChange(); 418 } 419 } 420 421 void AnchorOverlayObject::SetTriPosition(const basegfx::B2DPoint& rPoint1,const basegfx::B2DPoint& rPoint2,const basegfx::B2DPoint& rPoint3, 422 const basegfx::B2DPoint& rPoint4,const basegfx::B2DPoint& rPoint5) 423 { 424 if(rPoint1 != getBasePosition() 425 || rPoint2 != GetSecondPosition() 426 || rPoint3 != GetThirdPosition() 427 || rPoint4 != GetFourthPosition() 428 || rPoint5 != GetFifthPosition()) 429 { 430 maBasePosition = rPoint1; 431 maSecondPosition = rPoint2; 432 maThirdPosition = rPoint3; 433 maFourthPosition = rPoint4; 434 maFifthPosition = rPoint5; 435 436 implResetGeometry(); 437 objectChange(); 438 } 439 } 440 441 void AnchorOverlayObject::setLineSolid( const bool bNew ) 442 { 443 if ( bNew != getLineSolid() ) 444 { 445 mbLineSolid = bNew; 446 objectChange(); 447 } 448 } 449 450 void AnchorOverlayObject::SetAnchorState( const AnchorState aState) 451 { 452 if ( mAnchorState != aState) 453 { 454 mAnchorState = aState; 455 objectChange(); 456 } 457 } 458 459 } } // end of namespace sw::annotation 460 461