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