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