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:
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)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
getTriangle() const88 const basegfx::B2DPolygon& getTriangle() const { return maTriangle; }
getLine() const89 const basegfx::B2DPolygon& getLine() const { return maLine; }
getLineTop() const90 const basegfx::B2DPolygon& getLineTop() const { return maLineTop; }
getAnchorState() const91 AnchorState getAnchorState() const { return maAnchorState; }
getColor() const92 const basegfx::BColor& getColor() const { return maColor; }
getDiscreteLineWidth() const93 double getDiscreteLineWidth() const { return mfDiscreteLineWidth; }
getShadow() const94 bool getShadow() const { return mbShadow; }
getLineSolid() const95 bool getLineSolid() const { return mbLineSolid; }
96
97 virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const;
98
99 DeclPrimitrive2DIDBlock()
100 };
101
create2DDecomposition(const drawinglayer::geometry::ViewInformation2D &) const102 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
operator ==(const drawinglayer::primitive2d::BasePrimitive2D & rPrimitive) const218 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
ImplPrimitrive2DIDBlock(AnchorPrimitive,PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE)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
DestroyAnchorOverlayObject(AnchorOverlayObject * pAnchor)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
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)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
~AnchorOverlayObject()317 AnchorOverlayObject::~AnchorOverlayObject()
318 {
319 }
320
implEnsureGeometry()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
implResetGeometry()345 void AnchorOverlayObject::implResetGeometry()
346 {
347 maTriangle.clear();
348 maLine.clear();
349 maLineTop.clear();
350 }
351
createOverlayObjectPrimitive2DSequence()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
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)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
SetSixthPosition(const basegfx::B2DPoint & rNew)399 void AnchorOverlayObject::SetSixthPosition(const basegfx::B2DPoint& rNew)
400 {
401 if(rNew != maSixthPosition)
402 {
403 maSixthPosition = rNew;
404 implResetGeometry();
405 objectChange();
406 }
407 }
408
SetSeventhPosition(const basegfx::B2DPoint & rNew)409 void AnchorOverlayObject::SetSeventhPosition(const basegfx::B2DPoint& rNew)
410 {
411 if(rNew != maSeventhPosition)
412 {
413 maSeventhPosition = rNew;
414 implResetGeometry();
415 objectChange();
416 }
417 }
418
SetTriPosition(const basegfx::B2DPoint & rPoint1,const basegfx::B2DPoint & rPoint2,const basegfx::B2DPoint & rPoint3,const basegfx::B2DPoint & rPoint4,const basegfx::B2DPoint & rPoint5)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
setLineSolid(const bool bNew)439 void AnchorOverlayObject::setLineSolid( const bool bNew )
440 {
441 if ( bNew != getLineSolid() )
442 {
443 mbLineSolid = bNew;
444 objectChange();
445 }
446 }
447
SetAnchorState(const AnchorState aState)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