summaryrefslogtreecommitdiff
path: root/svx/source/sdr/overlay/overlaymanager.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/sdr/overlay/overlaymanager.cxx')
-rw-r--r--svx/source/sdr/overlay/overlaymanager.cxx393
1 files changed, 393 insertions, 0 deletions
diff --git a/svx/source/sdr/overlay/overlaymanager.cxx b/svx/source/sdr/overlay/overlaymanager.cxx
new file mode 100644
index 000000000000..f52205d88e45
--- /dev/null
+++ b/svx/source/sdr/overlay/overlaymanager.cxx
@@ -0,0 +1,393 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <svx/sdr/overlay/overlaymanager.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <tools/gen.hxx>
+#include <vcl/salbtype.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/window.hxx>
+#include <svx/sdr/overlay/overlayobject.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <drawinglayer/processor2d/baseprocessor2d.hxx>
+#include <svx/sdr/contact/objectcontacttools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+using namespace com::sun::star;
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace sdr
+{
+ namespace overlay
+ {
+ void OverlayManager::ImpDrawMembers(const basegfx::B2DRange& rRange, OutputDevice& rDestinationDevice) const
+ {
+ const sal_uInt32 nSize(maOverlayObjects.size());
+
+ if(nSize)
+ {
+ const sal_uInt16 nOriginalAA(rDestinationDevice.GetAntialiasing());
+ const bool bIsAntiAliasing(getDrawinglayerOpt().IsAntiAliasing());
+
+ // create processor
+ drawinglayer::processor2d::BaseProcessor2D* pProcessor = ::sdr::contact::createBaseProcessor2DFromOutputDevice(
+ rDestinationDevice,
+ getCurrentViewInformation2D());
+
+ if(pProcessor)
+ {
+ for(OverlayObjectVector::const_iterator aIter(maOverlayObjects.begin()); aIter != maOverlayObjects.end(); aIter++)
+ {
+ OSL_ENSURE(*aIter, "Corrupted OverlayObject List (!)");
+ const OverlayObject& rCandidate = **aIter;
+
+ if(rCandidate.isVisible())
+ {
+ const drawinglayer::primitive2d::Primitive2DSequence& rSequence = rCandidate.getOverlayObjectPrimitive2DSequence();
+
+ if(rSequence.hasElements())
+ {
+ if(rRange.overlaps(rCandidate.getBaseRange()))
+ {
+ if(bIsAntiAliasing && rCandidate.allowsAntiAliase())
+ {
+ rDestinationDevice.SetAntialiasing(nOriginalAA | ANTIALIASING_ENABLE_B2DDRAW);
+ }
+ else
+ {
+ rDestinationDevice.SetAntialiasing(nOriginalAA & ~ANTIALIASING_ENABLE_B2DDRAW);
+ }
+
+ pProcessor->process(rSequence);
+ }
+ }
+ }
+ }
+
+ delete pProcessor;
+ }
+
+ // restore AA settings
+ rDestinationDevice.SetAntialiasing(nOriginalAA);
+ }
+ }
+
+ void OverlayManager::ImpStripeDefinitionChanged()
+ {
+ const sal_uInt32 nSize(maOverlayObjects.size());
+
+ if(nSize)
+ {
+ for(OverlayObjectVector::iterator aIter(maOverlayObjects.begin()); aIter != maOverlayObjects.end(); aIter++)
+ {
+ OSL_ENSURE(*aIter, "Corrupted OverlayObject List (!)");
+ OverlayObject& rCandidate = **aIter;
+ rCandidate.stripeDefinitionHasChanged();
+ }
+ }
+ }
+
+ double OverlayManager::getDiscreteOne() const
+ {
+ if(basegfx::fTools::equalZero(mfDiscreteOne))
+ {
+ const basegfx::B2DVector aDiscreteInLogic(getOutputDevice().GetInverseViewTransformation() * basegfx::B2DVector(1.0, 0.0));
+ const_cast< OverlayManager* >(this)->mfDiscreteOne = aDiscreteInLogic.getLength();
+ }
+
+ return mfDiscreteOne;
+ }
+
+ OverlayManager::OverlayManager(
+ OutputDevice& rOutputDevice,
+ OverlayManager* pOldOverlayManager)
+ : Scheduler(),
+ rmOutputDevice(rOutputDevice),
+ maOverlayObjects(),
+ maStripeColorA(Color(COL_BLACK)),
+ maStripeColorB(Color(COL_WHITE)),
+ mnStripeLengthPixel(5),
+ maDrawinglayerOpt(),
+ maViewTransformation(),
+ maViewInformation2D(0),
+ mfDiscreteOne(0.0)
+ {
+ // set Property 'ReducedDisplayQuality' to true to allow simpler interaction
+ // visualisations
+ static bool bUseReducedDisplayQualityForDrag(true);
+
+ if(bUseReducedDisplayQualityForDrag)
+ {
+ uno::Sequence< beans::PropertyValue > xProperties(1);
+ xProperties[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReducedDisplayQuality"));
+ xProperties[0].Value <<= true;
+ maViewInformation2D = drawinglayer::geometry::ViewInformation2D(xProperties);
+ }
+
+ if(pOldOverlayManager)
+ {
+ // take over OverlayObjects from given OverlayManager. Copy
+ // the vector of pointers
+ maOverlayObjects = pOldOverlayManager->maOverlayObjects;
+ const sal_uInt32 nSize(maOverlayObjects.size());
+
+ if(nSize)
+ {
+ for(OverlayObjectVector::iterator aIter(maOverlayObjects.begin()); aIter != maOverlayObjects.end(); aIter++)
+ {
+ OSL_ENSURE(*aIter, "Corrupted OverlayObject List (!)");
+ OverlayObject& rCandidate = **aIter;
+
+ // remove from old and add to new OverlayManager
+ pOldOverlayManager->impApplyRemoveActions(rCandidate);
+ impApplyAddActions(rCandidate);
+ }
+
+ pOldOverlayManager->maOverlayObjects.clear();
+ }
+ }
+ }
+
+ const drawinglayer::geometry::ViewInformation2D OverlayManager::getCurrentViewInformation2D() const
+ {
+ if(getOutputDevice().GetViewTransformation() != maViewTransformation)
+ {
+ basegfx::B2DRange aViewRange(maViewInformation2D.getViewport());
+
+ if(OUTDEV_WINDOW == getOutputDevice().GetOutDevType())
+ {
+ const Size aOutputSizePixel(getOutputDevice().GetOutputSizePixel());
+ aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
+ aViewRange.transform(getOutputDevice().GetInverseViewTransformation());
+ }
+
+ OverlayManager* pThis = const_cast< OverlayManager* >(this);
+
+ pThis->maViewTransformation = getOutputDevice().GetViewTransformation();
+ pThis->maViewInformation2D = drawinglayer::geometry::ViewInformation2D(
+ maViewInformation2D.getObjectTransformation(),
+ maViewTransformation,
+ aViewRange,
+ maViewInformation2D.getVisualizedPage(),
+ maViewInformation2D.getViewTime(),
+ maViewInformation2D.getExtendedInformationSequence());
+ pThis->mfDiscreteOne = 0.0;
+ }
+
+ return maViewInformation2D;
+ }
+
+ void OverlayManager::impApplyRemoveActions(OverlayObject& rTarget)
+ {
+ // handle evtl. animation
+ if(rTarget.allowsAnimation())
+ {
+ // remove from event chain
+ RemoveEvent(&rTarget);
+ }
+
+ // make invisible
+ invalidateRange(rTarget.getBaseRange());
+
+ // clear manager
+ rTarget.mpOverlayManager = 0;
+ }
+
+ void OverlayManager::impApplyAddActions(OverlayObject& rTarget)
+ {
+ // set manager
+ rTarget.mpOverlayManager = this;
+
+ // make visible
+ invalidateRange(rTarget.getBaseRange());
+
+ // handle evtl. animation
+ if(rTarget.allowsAnimation())
+ {
+ // Trigger at current time to get alive. This will do the
+ // object-specific next time calculation and hand over adding
+ // again to the scheduler to the animated object, too. This works for
+ // a paused or non-paused animator.
+ rTarget.Trigger(GetTime());
+ }
+ }
+
+ OverlayManager::~OverlayManager()
+ {
+ // The OverlayManager is not the owner of the OverlayObjects
+ // and thus will not delete them, but remove them. Profit here
+ // from knowing that all will be removed
+ const sal_uInt32 nSize(maOverlayObjects.size());
+
+ if(nSize)
+ {
+ for(OverlayObjectVector::iterator aIter(maOverlayObjects.begin()); aIter != maOverlayObjects.end(); aIter++)
+ {
+ OSL_ENSURE(*aIter, "Corrupted OverlayObject List (!)");
+ OverlayObject& rCandidate = **aIter;
+ impApplyRemoveActions(rCandidate);
+ }
+
+ // erase vector
+ maOverlayObjects.clear();
+ }
+ }
+
+ void OverlayManager::completeRedraw(const Region& rRegion, OutputDevice* pPreRenderDevice) const
+ {
+ if(!rRegion.IsEmpty() && maOverlayObjects.size())
+ {
+ // check for changed MapModes. That may influence the
+ // logical size of pixel based OverlayObjects (like BitmapHandles)
+ //ImpCheckMapModeChange();
+
+ // paint members
+ const Rectangle aRegionBoundRect(rRegion.GetBoundRect());
+ const basegfx::B2DRange aRegionRange(
+ aRegionBoundRect.Left(), aRegionBoundRect.Top(),
+ aRegionBoundRect.Right(), aRegionBoundRect.Bottom());
+
+ OutputDevice& rTarget = (pPreRenderDevice) ? *pPreRenderDevice : getOutputDevice();
+ ImpDrawMembers(aRegionRange, rTarget);
+ }
+ }
+
+ void OverlayManager::flush()
+ {
+ // default has nothing to do
+ }
+
+ // #i68597# part of content gets copied, react on it
+ void OverlayManager::copyArea(const Point& /*rDestPt*/, const Point& /*rSrcPt*/, const Size& /*rSrcSize*/)
+ {
+ // unbuffered versions do nothing here
+ }
+
+ void OverlayManager::restoreBackground(const Region& /*rRegion*/) const
+ {
+ // unbuffered versions do nothing here
+ }
+
+ void OverlayManager::add(OverlayObject& rOverlayObject)
+ {
+ OSL_ENSURE(0 == rOverlayObject.mpOverlayManager, "OverlayObject is added twice to an OverlayManager (!)");
+
+ // add to the end of chain to preserve display order in paint
+ maOverlayObjects.push_back(&rOverlayObject);
+
+ // execute add actions
+ impApplyAddActions(rOverlayObject);
+ }
+
+ void OverlayManager::remove(OverlayObject& rOverlayObject)
+ {
+ OSL_ENSURE(rOverlayObject.mpOverlayManager == this, "OverlayObject is removed from wrong OverlayManager (!)");
+
+ // execute remove actions
+ impApplyRemoveActions(rOverlayObject);
+
+ // remove from vector
+ const OverlayObjectVector::iterator aFindResult = ::std::find(maOverlayObjects.begin(), maOverlayObjects.end(), &rOverlayObject);
+ const bool bFound(aFindResult != maOverlayObjects.end());
+ OSL_ENSURE(bFound, "OverlayObject NOT found at OverlayManager (!)");
+
+ if(bFound)
+ {
+ maOverlayObjects.erase(aFindResult);
+ }
+ }
+
+ void OverlayManager::invalidateRange(const basegfx::B2DRange& rRange)
+ {
+ if(OUTDEV_WINDOW == getOutputDevice().GetOutDevType())
+ {
+ if(getDrawinglayerOpt().IsAntiAliasing())
+ {
+ // assume AA needs one pixel more and invalidate one pixel more
+ const double fDiscreteOne(getDiscreteOne());
+ const Rectangle aInvalidateRectangle(
+ (sal_Int32)floor(rRange.getMinX() - fDiscreteOne),
+ (sal_Int32)floor(rRange.getMinY() - fDiscreteOne),
+ (sal_Int32)ceil(rRange.getMaxX() + fDiscreteOne),
+ (sal_Int32)ceil(rRange.getMaxY() + fDiscreteOne));
+
+ // simply invalidate
+ ((Window&)getOutputDevice()).Invalidate(aInvalidateRectangle, INVALIDATE_NOERASE);
+ }
+ else
+ {
+ // #i77674# transform to rectangle. Use floor/ceil to get all covered
+ // discrete pixels, see #i75163# and OverlayManagerBuffered::invalidateRange
+ const Rectangle aInvalidateRectangle(
+ (sal_Int32)floor(rRange.getMinX()), (sal_Int32)floor(rRange.getMinY()),
+ (sal_Int32)ceil(rRange.getMaxX()), (sal_Int32)ceil(rRange.getMaxY()));
+
+ // simply invalidate
+ ((Window&)getOutputDevice()).Invalidate(aInvalidateRectangle, INVALIDATE_NOERASE);
+ }
+ }
+ }
+
+ // stripe support ColA
+ void OverlayManager::setStripeColorA(Color aNew)
+ {
+ if(aNew != maStripeColorA)
+ {
+ maStripeColorA = aNew;
+ ImpStripeDefinitionChanged();
+ }
+ }
+
+ // stripe support ColB
+ void OverlayManager::setStripeColorB(Color aNew)
+ {
+ if(aNew != maStripeColorB)
+ {
+ maStripeColorB = aNew;
+ ImpStripeDefinitionChanged();
+ }
+ }
+
+ // stripe support StripeLengthPixel
+ void OverlayManager::setStripeLengthPixel(sal_uInt32 nNew)
+ {
+ if(nNew != mnStripeLengthPixel)
+ {
+ mnStripeLengthPixel = nNew;
+ ImpStripeDefinitionChanged();
+ }
+ }
+ } // end of namespace overlay
+} // end of namespace sdr
+
+//////////////////////////////////////////////////////////////////////////////
+// eof