Update ooo320-m1
[ooovba.git] / svx / source / sdr / contact / viewobjectcontact.cxx
blob2a600fd5d537f42253faba88bc316000f53f44e7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: viewobjectcontact.cxx,v $
10 * $Revision: 1.17.18.1 $
12 * This file is part of OpenOffice.org.
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.
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).
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.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <svx/sdr/contact/viewobjectcontact.hxx>
34 #include <svx/sdr/contact/viewcontact.hxx>
35 #include <svx/sdr/contact/objectcontact.hxx>
36 #include <svx/sdr/contact/displayinfo.hxx>
37 #include <vcl/region.hxx>
38 #include <svx/sdr/animation/objectanimator.hxx>
39 #include <svx/sdr/animation/animationstate.hxx>
40 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
41 #include <basegfx/numeric/ftools.hxx>
42 #include <basegfx/color/bcolor.hxx>
43 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
44 #include <basegfx/tools/canvastools.hxx>
45 #include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
46 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
47 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
48 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
50 //////////////////////////////////////////////////////////////////////////////
52 using namespace com::sun::star;
54 //////////////////////////////////////////////////////////////////////////////
56 namespace
58 // animated extractor
60 // Necessary to filter a sequence of animated primitives from
61 // a sequence of primitives to find out if animated or not. The decision for
62 // what to decompose is hard-coded and only done for knowingly animated primitives
63 // to not decompose too deeply and unnecessarily. This implies that the list
64 // which is view-specific needs to be expanded by hand when new animated objects
65 // are added. This may eventually be changed to a dynamically configurable approach
66 // if necessary.
67 class AnimatedExtractingProcessor2D : public drawinglayer::processor2d::BaseProcessor2D
69 protected:
70 // the found animated primitives
71 drawinglayer::primitive2d::Primitive2DSequence maPrimitive2DSequence;
73 // bitfield
74 // text animation allowed?
75 unsigned mbTextAnimationAllowed : 1;
77 // graphic animation allowed?
78 unsigned mbGraphicAnimationAllowed : 1;
80 // as tooling, the process() implementation takes over API handling and calls this
81 // virtual render method when the primitive implementation is BasePrimitive2D-based.
82 virtual void processBasePrimitive2D(const drawinglayer::primitive2d::BasePrimitive2D& rCandidate);
84 public:
85 AnimatedExtractingProcessor2D(
86 const drawinglayer::geometry::ViewInformation2D& rViewInformation,
87 bool bTextAnimationAllowed,
88 bool bGraphicAnimationAllowed);
89 virtual ~AnimatedExtractingProcessor2D();
91 // data access
92 const drawinglayer::primitive2d::Primitive2DSequence& getPrimitive2DSequence() const { return maPrimitive2DSequence; }
93 bool isTextAnimationAllowed() const { return mbTextAnimationAllowed; }
94 bool isGraphicAnimationAllowed() const { return mbGraphicAnimationAllowed; }
97 AnimatedExtractingProcessor2D::AnimatedExtractingProcessor2D(
98 const drawinglayer::geometry::ViewInformation2D& rViewInformation,
99 bool bTextAnimationAllowed,
100 bool bGraphicAnimationAllowed)
101 : drawinglayer::processor2d::BaseProcessor2D(rViewInformation),
102 maPrimitive2DSequence(),
103 mbTextAnimationAllowed(bTextAnimationAllowed),
104 mbGraphicAnimationAllowed(bGraphicAnimationAllowed)
108 AnimatedExtractingProcessor2D::~AnimatedExtractingProcessor2D()
112 void AnimatedExtractingProcessor2D::processBasePrimitive2D(const drawinglayer::primitive2d::BasePrimitive2D& rCandidate)
114 // known implementation, access directly
115 switch(rCandidate.getPrimitiveID())
117 // add and accept animated primitives directly, no need to decompose
118 case PRIMITIVE2D_ID_ANIMATEDSWITCHPRIMITIVE2D :
119 case PRIMITIVE2D_ID_ANIMATEDBLINKPRIMITIVE2D :
120 case PRIMITIVE2D_ID_ANIMATEDINTERPOLATEPRIMITIVE2D :
122 const drawinglayer::primitive2d::AnimatedSwitchPrimitive2D& rSwitchPrimitive = static_cast< const drawinglayer::primitive2d::AnimatedSwitchPrimitive2D& >(rCandidate);
124 if((rSwitchPrimitive.isTextAnimation() && isTextAnimationAllowed())
125 || (rSwitchPrimitive.isGraphicAnimation() && isGraphicAnimationAllowed()))
127 const drawinglayer::primitive2d::Primitive2DReference xReference(const_cast< drawinglayer::primitive2d::BasePrimitive2D* >(&rCandidate));
128 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(maPrimitive2DSequence, xReference);
130 break;
133 // decompose animated gifs where SdrGrafPrimitive2D produces a GraphicPrimitive2D
134 // which then produces the animation infos (all when used/needed)
135 case PRIMITIVE2D_ID_SDRGRAFPRIMITIVE2D :
136 case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
138 // decompose SdrObjects with evtl. animated text
139 case PRIMITIVE2D_ID_SDRCAPTIONPRIMITIVE2D :
140 case PRIMITIVE2D_ID_SDRCONNECTORPRIMITIVE2D :
141 case PRIMITIVE2D_ID_SDRCUSTOMSHAPEPRIMITIVE2D :
142 case PRIMITIVE2D_ID_SDRELLIPSEPRIMITIVE2D :
143 case PRIMITIVE2D_ID_SDRELLIPSESEGMENTPRIMITIVE2D :
144 case PRIMITIVE2D_ID_SDRMEASUREPRIMITIVE2D :
145 case PRIMITIVE2D_ID_SDRPATHPRIMITIVE2D :
146 case PRIMITIVE2D_ID_SDRRECTANGLEPRIMITIVE2D :
148 // decompose evtl. animated text contained in MaskPrimitive2D
149 // or group rimitives
150 case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
151 case PRIMITIVE2D_ID_GROUPPRIMITIVE2D :
153 process(rCandidate.get2DDecomposition(getViewInformation2D()));
154 break;
157 default :
159 // nothing to do for the rest
160 break;
164 } // end of anonymous namespace
166 //////////////////////////////////////////////////////////////////////////////
168 namespace sdr
170 namespace contact
172 ViewObjectContact::ViewObjectContact(ObjectContact& rObjectContact, ViewContact& rViewContact)
173 : mrObjectContact(rObjectContact),
174 mrViewContact(rViewContact),
175 maObjectRange(),
176 mxPrimitive2DSequence(),
177 mpPrimitiveAnimation(0),
178 mbLazyInvalidate(false)
180 // make the ViewContact remember me
181 mrViewContact.AddViewObjectContact(*this);
183 // make the ObjectContact remember me
184 mrObjectContact.AddViewObjectContact(*this);
187 ViewObjectContact::~ViewObjectContact()
189 // invalidate in view
190 if(!maObjectRange.isEmpty())
192 GetObjectContact().InvalidatePartOfView(maObjectRange);
195 // delete PrimitiveAnimation
196 if(mpPrimitiveAnimation)
198 delete mpPrimitiveAnimation;
199 mpPrimitiveAnimation = 0;
202 // take care of remebered ObjectContact. Remove from
203 // OC first. The VC removal (below) CAN trigger a StopGettingViewed()
204 // which (depending of it's implementation) may destroy other OCs. This
205 // can trigger the deletion of the helper OC of a page visualising object
206 // which IS the OC of this object. Eventually StopGettingViewed() needs
207 // to get asynchron later
208 GetObjectContact().RemoveViewObjectContact(*this);
210 // take care of remebered ViewContact
211 GetViewContact().RemoveViewObjectContact(*this);
214 const basegfx::B2DRange& ViewObjectContact::getObjectRange() const
216 if(maObjectRange.isEmpty())
218 // if range is not computed (new or LazyInvalidate objects), force it
219 const DisplayInfo aDisplayInfo;
220 const drawinglayer::primitive2d::Primitive2DSequence xSequence(getPrimitive2DSequence(aDisplayInfo));
222 if(xSequence.hasElements())
224 const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
225 const_cast< ViewObjectContact* >(this)->maObjectRange =
226 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xSequence, rViewInformation2D);
230 return maObjectRange;
233 void ViewObjectContact::ActionChanged()
235 if(!mbLazyInvalidate)
237 // set local flag
238 mbLazyInvalidate = true;
240 // force ObjectRange
241 getObjectRange();
243 if(!maObjectRange.isEmpty())
245 // invalidate current valid range
246 GetObjectContact().InvalidatePartOfView(maObjectRange);
248 // reset ObjectRange, it needs to be recalculated
249 maObjectRange.reset();
252 // register at OC for lazy invalidate
253 GetObjectContact().setLazyInvalidate(*this);
257 void ViewObjectContact::triggerLazyInvalidate()
259 if(mbLazyInvalidate)
261 // reset flag
262 mbLazyInvalidate = false;
264 // force ObjectRange
265 getObjectRange();
267 if(!maObjectRange.isEmpty())
269 // invalidate current valid range
270 GetObjectContact().InvalidatePartOfView(maObjectRange);
275 // Take some action when new objects are inserted
276 void ViewObjectContact::ActionChildInserted(ViewContact& rChild)
278 // force creation of the new VOC and trigger it's refresh, so it
279 // will take part in LazyInvalidate immediately
280 rChild.GetViewObjectContact(GetObjectContact()).ActionChanged();
282 // forward action to ObjectContact
283 // const ViewObjectContact& rChildVOC = rChild.GetViewObjectContact(GetObjectContact());
284 // GetObjectContact().InvalidatePartOfView(rChildVOC.getObjectRange());
287 void ViewObjectContact::checkForPrimitive2DAnimations()
289 // remove old one
290 if(mpPrimitiveAnimation)
292 delete mpPrimitiveAnimation;
293 mpPrimitiveAnimation = 0;
296 // check for animated primitives
297 if(mxPrimitive2DSequence.hasElements())
299 const bool bTextAnimationAllowed(GetObjectContact().IsTextAnimationAllowed());
300 const bool bGraphicAnimationAllowed(GetObjectContact().IsGraphicAnimationAllowed());
302 if(bTextAnimationAllowed || bGraphicAnimationAllowed)
304 AnimatedExtractingProcessor2D aAnimatedExtractor(GetObjectContact().getViewInformation2D(),
305 bTextAnimationAllowed, bGraphicAnimationAllowed);
306 aAnimatedExtractor.process(mxPrimitive2DSequence);
308 if(aAnimatedExtractor.getPrimitive2DSequence().hasElements())
310 // dervied primitiveList is animated, setup new PrimitiveAnimation
311 mpPrimitiveAnimation = new sdr::animation::PrimitiveAnimation(*this, aAnimatedExtractor.getPrimitive2DSequence());
317 drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
319 // get the view-independent Primitive from the viewContact
320 drawinglayer::primitive2d::Primitive2DSequence xRetval(GetViewContact().getViewIndependentPrimitive2DSequence());
322 if(xRetval.hasElements())
324 // handle GluePoint
325 if(!GetObjectContact().isOutputToPrinter() && GetObjectContact().AreGluePointsVisible())
327 const drawinglayer::primitive2d::Primitive2DSequence xGlue(GetViewContact().createGluePointPrimitive2DSequence());
329 if(xGlue.hasElements())
331 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xRetval, xGlue);
335 // handle ghosted
336 if(isPrimitiveGhosted(rDisplayInfo))
338 const basegfx::BColor aRGBWhite(1.0, 1.0, 1.0);
339 const basegfx::BColorModifier aBColorModifier(aRGBWhite, 0.5, basegfx::BCOLORMODIFYMODE_INTERPOLATE);
340 const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::ModifiedColorPrimitive2D(xRetval, aBColorModifier));
341 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
345 return xRetval;
348 drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
350 drawinglayer::primitive2d::Primitive2DSequence xNewPrimitiveSequence;
352 // take care of redirectors and create new list
353 ViewObjectContactRedirector* pRedirector = GetObjectContact().GetViewObjectContactRedirector();
355 if(pRedirector)
357 xNewPrimitiveSequence = pRedirector->createRedirectedPrimitive2DSequence(*this, rDisplayInfo);
359 else
361 xNewPrimitiveSequence = createPrimitive2DSequence(rDisplayInfo);
364 // local up-to-date checks. New list different from local one?
365 if(!drawinglayer::primitive2d::arePrimitive2DSequencesEqual(mxPrimitive2DSequence, xNewPrimitiveSequence))
367 // has changed, copy content
368 const_cast< ViewObjectContact* >(this)->mxPrimitive2DSequence = xNewPrimitiveSequence;
370 // check for animated stuff
371 const_cast< ViewObjectContact* >(this)->checkForPrimitive2DAnimations();
373 // always update object range when PrimitiveSequence changes
374 const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
375 const_cast< ViewObjectContact* >(this)->maObjectRange =
376 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(mxPrimitive2DSequence, rViewInformation2D);
379 // return current Primitive2DSequence
380 return mxPrimitive2DSequence;
383 bool ViewObjectContact::isPrimitiveVisible(const DisplayInfo& /*rDisplayInfo*/) const
385 // default: always visible
386 return true;
389 bool ViewObjectContact::isPrimitiveGhosted(const DisplayInfo& rDisplayInfo) const
391 // default: standard check
392 return (GetObjectContact().DoVisualizeEnteredGroup() && !GetObjectContact().isOutputToPrinter() && rDisplayInfo.IsGhostedDrawModeActive());
395 drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequenceHierarchy(DisplayInfo& rDisplayInfo) const
397 drawinglayer::primitive2d::Primitive2DSequence xRetval;
399 // check model-view visibility
400 if(isPrimitiveVisible(rDisplayInfo))
402 xRetval = getPrimitive2DSequence(rDisplayInfo);
404 if(xRetval.hasElements())
406 // get ranges
407 const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
408 const basegfx::B2DRange aObjectRange(drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xRetval, rViewInformation2D));
409 const basegfx::B2DRange aViewRange(rViewInformation2D.getViewport());
411 // check geometrical visibility
412 if(!aViewRange.isEmpty() && !aViewRange.overlaps(aObjectRange))
414 // not visible, release
415 xRetval.realloc(0);
420 return xRetval;
423 drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequenceSubHierarchy(DisplayInfo& rDisplayInfo) const
425 const sal_uInt32 nSubHierarchyCount(GetViewContact().GetObjectCount());
426 drawinglayer::primitive2d::Primitive2DSequence xSeqRetval;
428 for(sal_uInt32 a(0); a < nSubHierarchyCount; a++)
430 const ViewObjectContact& rCandidate(GetViewContact().GetViewContact(a).GetViewObjectContact(GetObjectContact()));
432 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xSeqRetval, rCandidate.getPrimitive2DSequenceHierarchy(rDisplayInfo));
435 return xSeqRetval;
437 } // end of namespace contact
438 } // end of namespace sdr
440 //////////////////////////////////////////////////////////////////////////////
441 // eof