diff options
Diffstat (limited to 'sd/source/ui/slidesorter/view/SlsViewOverlay.cxx')
-rw-r--r-- | sd/source/ui/slidesorter/view/SlsViewOverlay.cxx | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx b/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx new file mode 100644 index 000000000000..32576240036c --- /dev/null +++ b/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx @@ -0,0 +1,606 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#include "precompiled_sd.hxx" + +#include "view/SlsViewOverlay.hxx" + +#include "SlideSorter.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageDescriptor.hxx" +#include "model/SlsPageEnumeration.hxx" +#include "view/SlideSorterView.hxx" +#include "SlideSorterViewShell.hxx" +#include "view/SlsLayouter.hxx" +#include "view/SlsPageObject.hxx" +#include "view/SlsPageObjectViewObjectContact.hxx" +#include "ViewShell.hxx" +#include "ViewShellBase.hxx" +#include "UpdateLockManager.hxx" + +#include "Window.hxx" +#include "sdpage.hxx" + +#include <basegfx/range/b2drectangle.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/svdpagv.hxx> +#include <svx/sdrpagewindow.hxx> +#include <vcl/svapp.hxx> + +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> + +using namespace ::sdr::overlay; + +namespace { + const static sal_Int32 gnSubstitutionStripeLength (3); +} + +namespace sd { namespace slidesorter { namespace view { + +//===== ViewOverlay ========================================================= + +ViewOverlay::ViewOverlay (SlideSorter& rSlideSorter) + : mrSlideSorter(rSlideSorter), + maSelectionRectangleOverlay(*this), + maMouseOverIndicatorOverlay(*this), + maInsertionIndicatorOverlay(*this), + maSubstitutionOverlay(*this) +{ +} + + + + +ViewOverlay::~ViewOverlay (void) +{ +} + + + + +SelectionRectangleOverlay& ViewOverlay::GetSelectionRectangleOverlay (void) +{ + return maSelectionRectangleOverlay; +} + + + + +MouseOverIndicatorOverlay& ViewOverlay::GetMouseOverIndicatorOverlay (void) +{ + return maMouseOverIndicatorOverlay; +} + + + + +InsertionIndicatorOverlay& ViewOverlay::GetInsertionIndicatorOverlay (void) +{ + return maInsertionIndicatorOverlay; +} + + + + +SubstitutionOverlay& ViewOverlay::GetSubstitutionOverlay (void) +{ + return maSubstitutionOverlay; +} + + + + +SlideSorter& ViewOverlay::GetSlideSorter (void) const +{ + return mrSlideSorter; +} + + + + +OverlayManager* ViewOverlay::GetOverlayManager (void) const +{ + OverlayManager* pOverlayManager = NULL; + + SlideSorterView& rView (mrSlideSorter.GetView()); + SdrPageView* pPageView = rView.GetSdrPageView(); + if (pPageView != NULL && pPageView->PageWindowCount()>0) + { + SdrPageWindow* pPageWindow = pPageView->GetPageWindow(0); + if (pPageWindow != NULL) + pOverlayManager = pPageWindow->GetOverlayManager(); + } + + return pOverlayManager; +} + + + + +//===== OverlayBase ========================================================= + +OverlayBase::OverlayBase (ViewOverlay& rViewOverlay) + : OverlayObject(Color(0,0,0)), + mrViewOverlay(rViewOverlay) +{ + setVisible(false); +} + + + + +OverlayBase::~OverlayBase (void) +{ + OSL_ENSURE(!getOverlayManager(), "Please call RemoveRegistration() in the derived class; it's too late to call it in the base class since virtual methods will be missing when called in the destructor."); +} + + + + +void OverlayBase::EnsureRegistration (void) +{ + if (getOverlayManager() == NULL) + { + OverlayManager* pOverlayManager = mrViewOverlay.GetOverlayManager(); + if (pOverlayManager != NULL) + pOverlayManager->add(*this); + } +} + + + + +void OverlayBase::RemoveRegistration() +{ + OverlayManager* pOverlayManager = getOverlayManager(); + if (pOverlayManager != NULL) + pOverlayManager->remove(*this); +} + + + + +//===== SubstitutionOverlay ================================================= + +SubstitutionOverlay::SubstitutionOverlay (ViewOverlay& rViewOverlay) + : OverlayBase(rViewOverlay), + maPosition(0,0), + maShapes() +{ +} + + + + +SubstitutionOverlay::~SubstitutionOverlay (void) +{ + RemoveRegistration(); +} + + + + +void SubstitutionOverlay::Create ( + model::PageEnumeration& rSelection, + const Point& rPosition) +{ + EnsureRegistration(); + + maPosition = rPosition; + + maShapes.clear(); + while (rSelection.HasMoreElements()) + { + const Rectangle aBox (rSelection.GetNextElement()->GetPageObject()->GetCurrentBoundRect()); + basegfx::B2DRectangle aB2DBox( + aBox.Left(), + aBox.Top(), + aBox.Right(), + aBox.Bottom()); + maShapes.append(basegfx::tools::createPolygonFromRect(aB2DBox), 4); + } + + setVisible(maShapes.count() > 0); + // The selection indicator may have been visible already so call + // objectChange() to enforce an update. + objectChange(); +} + + + + +void SubstitutionOverlay::Clear (void) +{ + maShapes.clear(); + setVisible(false); +} + + + + +void SubstitutionOverlay::Move (const Point& rOffset) +{ + const basegfx::B2DHomMatrix aTranslation(basegfx::tools::createTranslateB2DHomMatrix(rOffset.X(), rOffset.Y())); + + maShapes.transform(aTranslation); + maPosition += rOffset; + + objectChange(); +} + + + + +void SubstitutionOverlay::SetPosition (const Point& rPosition) +{ + Move(rPosition - GetPosition()); +} + + + + +Point SubstitutionOverlay::GetPosition (void) const +{ + return maPosition; +} + + + + +drawinglayer::primitive2d::Primitive2DSequence SubstitutionOverlay::createOverlayObjectPrimitive2DSequence() +{ + drawinglayer::primitive2d::Primitive2DSequence aRetval; + const sal_uInt32 nCount(maShapes.count()); + + if(nCount && getOverlayManager()) + { + aRetval.realloc(nCount); + const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor()); + const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor()); + + for(sal_uInt32 a(0); a < nCount; a++) + { + aRetval[a] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolygonMarkerPrimitive2D( + maShapes.getB2DPolygon(a), + aRGBColorA, + aRGBColorB, + gnSubstitutionStripeLength)); + } + } + + return aRetval; +} + +void SubstitutionOverlay::stripeDefinitionHasChanged() +{ + // react on OverlayManager's stripe definition change + objectChange(); +} + + +//===== SelectionRectangleOverlay =========================================== + +SelectionRectangleOverlay::SelectionRectangleOverlay (ViewOverlay& rViewOverlay) + : OverlayBase (rViewOverlay), + maAnchor(0,0), + maSecondCorner(0,0) +{ +} + + + +SelectionRectangleOverlay::~SelectionRectangleOverlay() +{ + RemoveRegistration(); +} + + + + +Rectangle SelectionRectangleOverlay::GetSelectionRectangle (void) +{ + return Rectangle(maAnchor, maSecondCorner); +} + + + + +void SelectionRectangleOverlay::Start (const Point& rAnchor) +{ + EnsureRegistration(); + setVisible(false); + maAnchor = rAnchor; +} + + + + +void SelectionRectangleOverlay::Update (const Point& rSecondCorner) +{ + maSecondCorner = rSecondCorner; + setVisible(true); + // The selection rectangle may have been visible already so call + // objectChange() to enforce an update. + objectChange(); +} + + + + +drawinglayer::primitive2d::Primitive2DSequence SelectionRectangleOverlay::createOverlayObjectPrimitive2DSequence() +{ + drawinglayer::primitive2d::Primitive2DSequence aRetval; + const basegfx::B2DRange aRange(maAnchor.X(), maAnchor.Y(), maSecondCorner.X(), maSecondCorner.Y()); + const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(aRange)); + + if(aPolygon.count()) + { + const basegfx::BColor aRGBColorA(getOverlayManager()->getStripeColorA().getBColor()); + const basegfx::BColor aRGBColorB(getOverlayManager()->getStripeColorB().getBColor()); + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::PolygonMarkerPrimitive2D( + aPolygon, + aRGBColorA, + aRGBColorB, + gnSubstitutionStripeLength)); + + aRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); + } + + return aRetval; +} + +void SelectionRectangleOverlay::stripeDefinitionHasChanged() +{ + // react on OverlayManager's stripe definition change + objectChange(); +} + + + + +//===== InsertionIndicatorOverlay =========================================== + +InsertionIndicatorOverlay::InsertionIndicatorOverlay (ViewOverlay& rViewOverlay) + : OverlayBase (rViewOverlay), + mnInsertionIndex(-1), + maBoundingBox() +{ +} + + + + +InsertionIndicatorOverlay::~InsertionIndicatorOverlay() +{ + RemoveRegistration(); +} + + + + +void InsertionIndicatorOverlay::SetPositionAndSize (const Rectangle& aNewBoundingBox) +{ + EnsureRegistration(); + maBoundingBox = aNewBoundingBox; + setVisible( ! maBoundingBox.IsEmpty()); + // The insertion indicator may have been visible already so call + // objectChange() to enforce an update. + objectChange(); +} + + + + +void InsertionIndicatorOverlay::SetPosition (const Point& rPoint) +{ + static const bool bAllowHorizontalInsertMarker = true; + Layouter& rLayouter (mrViewOverlay.GetSlideSorter().GetView().GetLayouter()); + USHORT nPageCount + = (USHORT)mrViewOverlay.GetSlideSorter().GetModel().GetPageCount(); + + sal_Int32 nInsertionIndex = rLayouter.GetInsertionIndex (rPoint, + bAllowHorizontalInsertMarker); + if (nInsertionIndex >= nPageCount) + nInsertionIndex = nPageCount-1; + sal_Int32 nDrawIndex = nInsertionIndex; + + bool bVertical = false; + bool bLeftOrTop = false; + if (nInsertionIndex >= 0) + { + // Now that we know where to insert, we still have to determine + // where to draw the marker. There are two decisions to make: + // 1. Draw a vertical or a horizontal insert marker. + // The horizontal one may only be chosen when there is only one + // column. + // 2. The vertical (standard) insert marker may be painted left to + // the insert page or right of the previous one. When both pages + // are in the same row this makes no difference. Otherwise the + // posiotions are at the left and right ends of two rows. + + Point aPageCenter (rLayouter.GetPageObjectBox ( + nInsertionIndex).Center()); + + if (bAllowHorizontalInsertMarker + && rLayouter.GetColumnCount() == 1) + { + bVertical = false; + bLeftOrTop = (rPoint.Y() <= aPageCenter.Y()); + } + else + { + bVertical = true; + bLeftOrTop = (rPoint.X() <= aPageCenter.X()); + } + + // Add one when the mark was painted below or to the right of the + // page object. + if ( ! bLeftOrTop) + nInsertionIndex += 1; + } + + mnInsertionIndex = nInsertionIndex; + + Rectangle aBox; + if (mnInsertionIndex >= 0) + aBox = rLayouter.GetInsertionMarkerBox ( + nDrawIndex, + bVertical, + bLeftOrTop); + SetPositionAndSize (aBox); +} + + + + +sal_Int32 InsertionIndicatorOverlay::GetInsertionPageIndex (void) const +{ + return mnInsertionIndex; +} + + + + +drawinglayer::primitive2d::Primitive2DSequence InsertionIndicatorOverlay::createOverlayObjectPrimitive2DSequence() +{ + drawinglayer::primitive2d::Primitive2DSequence aRetval(2); + const basegfx::B2DRange aRange(maBoundingBox.Left(), maBoundingBox.Top(), maBoundingBox.Right(), maBoundingBox.Bottom()); + const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(aRange)); + const basegfx::BColor aRGBColor(Application::GetDefaultDevice()->GetSettings().GetStyleSettings().GetFontColor().getBColor()); + + aRetval[0] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + aRGBColor)); + aRetval[1] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( + aPolygon, + aRGBColor)); + + return aRetval; +} + + + + +//===== MouseOverIndicatorOverlay =========================================== + +MouseOverIndicatorOverlay::MouseOverIndicatorOverlay (ViewOverlay& rViewOverlay) + : OverlayBase (rViewOverlay), + mpPageUnderMouse() +{ +} + + + + +MouseOverIndicatorOverlay::~MouseOverIndicatorOverlay (void) +{ + RemoveRegistration(); +} + + + + +void MouseOverIndicatorOverlay::SetSlideUnderMouse ( + const model::SharedPageDescriptor& rpDescriptor) +{ + ViewShellBase* pBase = mrViewOverlay.GetSlideSorter().GetViewShellBase(); + if (pBase==NULL || ! pBase->GetUpdateLockManager()->IsLocked()) + { + model::SharedPageDescriptor pDescriptor; + if ( ! mpPageUnderMouse.expired()) + { + try + { + pDescriptor = model::SharedPageDescriptor(mpPageUnderMouse); + } + catch (::boost::bad_weak_ptr) + { + } + } + + if (pDescriptor != rpDescriptor) + { + // Switch to the new (possibly empty) descriptor. + mpPageUnderMouse = rpDescriptor; + + EnsureRegistration(); + + // Show the indicator when a valid page descriptor is given. + setVisible( ! mpPageUnderMouse.expired()); + // The mouse over indicator may have been visible already so call + // objectChange() to enforce an update. + objectChange(); + } + } +} + + + + +drawinglayer::primitive2d::Primitive2DSequence MouseOverIndicatorOverlay::createOverlayObjectPrimitive2DSequence() +{ + view::PageObjectViewObjectContact* pContact = GetViewObjectContact(); + + if(pContact) + { + return pContact->createMouseOverEffectPrimitive2DSequence(); + } + + return drawinglayer::primitive2d::Primitive2DSequence(); +} + + + + +view::PageObjectViewObjectContact* MouseOverIndicatorOverlay::GetViewObjectContact (void) const +{ + if ( ! mpPageUnderMouse.expired()) + { + model::SharedPageDescriptor pDescriptor (mpPageUnderMouse); + return pDescriptor->GetViewObjectContact(); + } + return NULL; +} + + + + +} } } // end of namespace ::sd::slidesorter::view + |