summaryrefslogtreecommitdiff
path: root/sd/source/ui/slidesorter/view/SlsButtonBar.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/view/SlsButtonBar.cxx')
-rw-r--r--sd/source/ui/slidesorter/view/SlsButtonBar.cxx1558
1 files changed, 1558 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/view/SlsButtonBar.cxx b/sd/source/ui/slidesorter/view/SlsButtonBar.cxx
new file mode 100644
index 000000000000..f338a998c56f
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsButtonBar.cxx
@@ -0,0 +1,1558 @@
+/*************************************************************************
+ *
+ * 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/SlsButtonBar.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "view/SlsTheme.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsToolTip.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsSlotManager.hxx"
+#include "controller/SlsCurrentSlideManager.hxx"
+#include "controller/SlsPageSelector.hxx"
+#include "controller/SlsAnimator.hxx"
+#include "controller/SlsAnimationFunction.hxx"
+#include "app.hrc"
+#include "drawdoc.hxx"
+#include <svx/svxids.hrc>
+#include <sfx2/dispatch.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/virdev.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <com/sun/star/presentation/XPresentation2.hpp>
+#include <boost/bind.hpp>
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::presentation::XPresentation2;
+
+namespace sd { namespace slidesorter { namespace view {
+
+/** Base class for the painter of the background bar onto which the buttons
+ are painted. It also provides some size information.
+*/
+class ButtonBar::BackgroundTheme
+{
+public:
+ BackgroundTheme(
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons);
+ /** Set the preview bounding box, the maximal area in which to display
+ buttons. A call to this method triggers a call to Layout().
+ */
+ void SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox);
+ Button::IconSize GetIconSize (void) const;
+
+ virtual BitmapEx CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const = 0;
+ virtual Point GetBackgroundLocation (void) = 0;
+ virtual Rectangle GetButtonArea (void) = 0;
+
+protected:
+ ::boost::shared_ptr<Theme> mpTheme;
+ Rectangle maPreviewBoundingBox;
+ Size maMinimumLargeButtonAreaSize;
+ Size maMinimumMediumButtonAreaSize;
+ Size maMinimumSmallButtonAreaSize;
+ Button::IconSize meIconSize;
+
+ virtual void Layout (void) = 0;
+
+private:
+ void UpdateMinimumIconSizes(const ::std::vector<SharedButton>& rButtons);
+};
+
+
+namespace {
+ /** Rectangular button bar that covers the whole width of the preview.
+ */
+ class RectangleBackgroundTheme : public ButtonBar::BackgroundTheme
+ {
+ public:
+ RectangleBackgroundTheme(
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons);
+ virtual BitmapEx CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const;
+ virtual Point GetBackgroundLocation (void);
+ virtual Rectangle GetButtonArea (void);
+ protected:
+ virtual void Layout (void);
+ private:
+ sal_Int32 mnBarHeight;
+ };
+
+ /** Button bar is composed of three images, the left and right end of
+ the bar and the center image. Buttons are only placed over the
+ center image. The center image is painted as is, it is not scaled.
+ */
+ class BitmapBackgroundTheme : public ButtonBar::BackgroundTheme
+ {
+ public:
+ BitmapBackgroundTheme(
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons);
+ virtual BitmapEx CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const;
+ virtual Point GetBackgroundLocation (void);
+ virtual Rectangle GetButtonArea (void);
+ protected:
+ virtual void Layout (void);
+ private:
+ Rectangle maButtonArea;
+ Point maBackgroundLocation;
+ };
+
+ /** The source mask is essentially multiplied with the given alpha value.
+ The result is writen to the result mask.
+ */
+ void AdaptTransparency (AlphaMask& rMask, const AlphaMask& rSourceMask, const double nAlpha)
+ {
+ BitmapWriteAccess* pBitmap = rMask.AcquireWriteAccess();
+ const BitmapReadAccess* pSourceBitmap = const_cast<AlphaMask&>(rSourceMask).AcquireReadAccess();
+
+ if (pBitmap!=NULL && pSourceBitmap!=NULL)
+ {
+ const sal_Int32 nWidth (pBitmap->Width());
+ const sal_Int32 nHeight (pBitmap->Height());
+
+ for (sal_Int32 nY = 0; nY<nHeight; ++nY)
+ for (sal_Int32 nX = 0; nX<nWidth; ++nX)
+ {
+ const sal_uInt8 nValue (255 - pSourceBitmap->GetPixel(nY, nX).GetBlueOrIndex());
+ const sal_uInt8 nNewValue (nValue * (1-nAlpha));
+ pBitmap->SetPixel(nY, nX, 255-nNewValue);
+ }
+ }
+ }
+
+} // end of anonymous namespace
+
+
+//===== ButtonBar::Lock =======================================================
+
+ButtonBar::Lock::Lock (SlideSorter& rSlideSorter)
+ : mrButtonBar(rSlideSorter.GetView().GetButtonBar())
+{
+ mrButtonBar.AcquireLock();
+}
+
+
+
+
+ButtonBar::Lock::~Lock (void)
+{
+ mrButtonBar.ReleaseLock();
+}
+
+
+
+
+//===== ButtonBar =============================================================
+
+ButtonBar::ButtonBar (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ maPageObjectSize(0,0),
+ maButtonBoundingBox(),
+ maBackgroundLocation(),
+ mpDescriptor(),
+ mbIsExcluded(false),
+ mpButtonUnderMouse(),
+ mpDownButton(),
+ maRegularButtons(),
+ maExcludedButtons(),
+ maNormalBackground(),
+ maButtonDownBackground(),
+ mbIsMouseOverBar(false),
+ mpBackgroundTheme(),
+ mnLockCount(0)
+{
+ HandleDataChangeEvent();
+}
+
+
+
+
+ButtonBar::~ButtonBar (void)
+{
+}
+
+
+
+
+void ButtonBar::ProcessButtonDownEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation)
+{
+ SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
+ if (mpButtonUnderMouse)
+ mpButtonUnderMouse->SetState(Button::State_Down);
+ mpDownButton = mpButtonUnderMouse;
+
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+}
+
+
+
+
+void ButtonBar::ProcessButtonUpEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation)
+{
+ SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
+ if (mpButtonUnderMouse)
+ {
+ mpButtonUnderMouse->SetState(Button::State_Hover);
+ if (mpButtonUnderMouse == mpDownButton)
+ {
+ // This is done only when the buttons are sufficiently visible.
+ if (mpDescriptor->GetVisualState().GetButtonAlpha()<0.7)
+ {
+ mpButtonUnderMouse->ProcessClick(mpDescriptor);
+ mbIsExcluded = mpDescriptor->HasState(model::PageDescriptor::ST_Excluded);
+ ProcessMouseMotionEvent (rpDescriptor, aMouseModelLocation, false);
+ }
+ }
+ }
+ mpDownButton.reset();
+ mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
+}
+
+
+
+
+void ButtonBar::ProcessMouseMotionEvent (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aMouseModelLocation,
+ const bool bIsMouseButtonDown)
+{
+ model::SharedPageDescriptor pOldDescriptor (mpDescriptor);
+ bool bPageHasChanged (false);
+ bool bButtonHasChanged (false);
+ bool bButtonStateHasChanged (false);
+
+ // Update the page object for which to manage the buttons.
+ bPageHasChanged = SetPage(rpDescriptor);
+ mbIsMouseOverBar = IsMouseOverBar(aMouseModelLocation);
+
+ // Update button under mouse.
+ if (rpDescriptor)
+ {
+ bButtonHasChanged = SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
+
+ if (mpButtonUnderMouse)
+ {
+ // When the mouse button is down, mark the button under the
+ // mouse only as pressed when it is the same button the mouse
+ // button was pressed over, and where the button release would
+ // lead to a click action.
+ if (bIsMouseButtonDown)
+ {
+ if (mpButtonUnderMouse==mpDownButton)
+ bButtonStateHasChanged = mpButtonUnderMouse->SetState(Button::State_Down);
+ }
+ else
+ bButtonStateHasChanged = mpButtonUnderMouse->SetState(Button::State_Hover);
+ }
+ }
+
+ // Show a quick help text when the mouse is over a button.
+ if (bButtonHasChanged)
+ {
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ if (mpButtonUnderMouse)
+ mrSlideSorter.GetView().GetToolTip().ShowHelpText(mpButtonUnderMouse->GetHelpText());
+ else
+ mrSlideSorter.GetView().GetToolTip().ShowDefaultHelpText();
+ }
+ }
+
+ if (bPageHasChanged || bButtonHasChanged || bButtonStateHasChanged)
+ {
+ if (pOldDescriptor)
+ mrSlideSorter.GetView().RequestRepaint(pOldDescriptor);
+ if (mpDescriptor && pOldDescriptor!=mpDescriptor)
+ mrSlideSorter.GetView().RequestRepaint(mpDescriptor);
+ }
+}
+
+
+
+
+void ButtonBar::ResetPage (void)
+{
+ SetPage(model::SharedPageDescriptor());
+}
+
+
+
+
+bool ButtonBar::SetPage (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (mpDescriptor != rpDescriptor)
+ {
+ mpDescriptor = rpDescriptor;
+
+ if (mpDescriptor)
+ mbIsExcluded = mpDescriptor->HasState(model::PageDescriptor::ST_Excluded);
+ else
+ mbIsExcluded = false;
+ SetButtonUnderMouse();
+ mpDownButton.reset();
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+sal_Int32 ButtonBar::GetButtonCount (const bool bIsExcluded) const
+{
+ if (bIsExcluded)
+ return maExcludedButtons.size();
+ else
+ return maRegularButtons.size();
+}
+
+
+
+
+::boost::shared_ptr<Button> ButtonBar::GetButton (
+ const bool bIsExcluded,
+ const sal_Int32 nIndex) const
+{
+ const ::std::vector<boost::shared_ptr<Button> >& rButtons (bIsExcluded
+ ? maExcludedButtons
+ : maRegularButtons);
+
+ if (nIndex<0 || sal_uInt32(nIndex)>=rButtons.size())
+ {
+ OSL_ASSERT(nIndex<0 || sal_uInt32(nIndex)>=rButtons.size());
+ return ::boost::shared_ptr<Button>();
+ }
+ else
+ return rButtons[sal_uInt32(nIndex)];
+}
+
+
+
+
+SharedButton ButtonBar::GetButtonAt (const Point aModelLocation)
+{
+ if (IsMouseOverBar(aModelLocation))
+ {
+ const Point aLocalLocation (aModelLocation - mpDescriptor->GetBoundingBox().TopLeft());
+ ::std::vector<SharedButton>& rButtons (
+ mbIsExcluded ? maExcludedButtons : maRegularButtons);
+ for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
+ {
+ if (rButtons[sal_uInt32(nIndex)]->GetBoundingBox().IsInside(aLocalLocation))
+ {
+ if (rButtons[sal_uInt32(nIndex)]->IsEnabled())
+ return rButtons[sal_uInt32(nIndex)];
+ else
+ return SharedButton();
+ }
+ }
+ }
+
+ return SharedButton();
+}
+
+
+
+
+bool ButtonBar::IsMouseOverBar (void) const
+{
+ return mbIsMouseOverBar;
+}
+
+
+
+
+bool ButtonBar::SetButtonUnderMouse (const SharedButton& rButton)
+{
+ if (mpButtonUnderMouse != rButton)
+ {
+ if (mpButtonUnderMouse)
+ mpButtonUnderMouse->SetState(Button::State_Normal);
+
+ mpButtonUnderMouse = rButton;
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+void ButtonBar::Paint (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor)
+{
+ if ( ! rpDescriptor)
+ return;
+
+ const double nButtonBarAlpha (rpDescriptor->GetVisualState().GetButtonBarAlpha());
+ if (nButtonBarAlpha >= 1)
+ return;
+
+ LayoutButtons(rpDescriptor->GetBoundingBox().GetSize());
+
+ const Point aOffset (rpDescriptor->GetBoundingBox().TopLeft());
+
+ // Paint the background.
+ PaintButtonBackground(rDevice, rpDescriptor, aOffset);
+
+ // Paint the buttons.
+ const ::std::vector<SharedButton>& rButtons (
+ rpDescriptor->HasState(model::PageDescriptor::ST_Excluded)
+ ? maExcludedButtons
+ : maRegularButtons);
+
+
+ const double nButtonAlpha (rpDescriptor->GetVisualState().GetButtonAlpha());
+ for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
+ rButtons[nIndex]->Paint(
+ rDevice,
+ aOffset,
+ nButtonAlpha,
+ mrSlideSorter.GetTheme());
+}
+
+
+
+
+bool ButtonBar::IsMouseOverButton (void) const
+{
+ return mpButtonUnderMouse;
+}
+
+
+
+
+void ButtonBar::PaintButtonBackground (
+ OutputDevice& rDevice,
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point aOffset)
+{
+ BitmapEx* pBitmap = NULL;
+ if (maButtonDownBackground.IsEmpty() || maNormalBackground.IsEmpty())
+ {
+ if (mpBackgroundTheme)
+ {
+ maButtonDownBackground = mpBackgroundTheme->CreateBackground(rDevice, true);
+ maNormalBackground = mpBackgroundTheme->CreateBackground(rDevice, false);
+ }
+ }
+ if (mpButtonUnderMouse && mpButtonUnderMouse->IsDown())
+ pBitmap = &maButtonDownBackground;
+ else
+ pBitmap = &maNormalBackground;
+ if (pBitmap != NULL)
+ {
+ AlphaMask aMask (pBitmap->GetSizePixel());
+ AdaptTransparency(
+ aMask,
+ pBitmap->GetAlpha(),
+ rpDescriptor->GetVisualState().GetButtonBarAlpha());
+ rDevice.DrawBitmapEx(maBackgroundLocation+aOffset, BitmapEx(pBitmap->GetBitmap(), aMask));
+ }
+}
+
+
+
+
+bool ButtonBar::IsMouseOverBar (const Point aModelLocation) const
+{
+ if ( ! mpDescriptor || ! mpDescriptor->GetBoundingBox().IsInside(aModelLocation))
+ return false;
+
+ if ( ! maButtonBoundingBox.IsInside(aModelLocation - mpDescriptor->GetBoundingBox().TopLeft()))
+ return false;
+
+ return true;
+}
+
+
+
+
+void ButtonBar::RequestLayout (void)
+{
+ maPageObjectSize = Size(0,0);
+}
+
+
+
+
+void ButtonBar::LayoutButtons (const Size aPageObjectSize)
+{
+ if (maPageObjectSize != aPageObjectSize)
+ {
+ maPageObjectSize = aPageObjectSize;
+
+ if (mpBackgroundTheme)
+ {
+ mpBackgroundTheme->SetPreviewBoundingBox(
+ mrSlideSorter.GetView().GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
+ Point(0,0),
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::ModelCoordinateSystem));
+ LayoutButtons();
+ }
+
+ // Release the background bitmaps so that on the next paint
+ // they are created anew in the right size.
+ maNormalBackground.SetEmpty();
+ maButtonDownBackground.SetEmpty();
+ }
+}
+
+
+
+
+bool ButtonBar::LayoutButtons (void)
+{
+ const sal_Int32 nGap (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonGap));
+ const sal_Int32 nBorder (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonBorder));
+
+ const Button::IconSize eIconSize (mpBackgroundTheme->GetIconSize());
+
+ // Tell buttons which size they are.
+ for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
+ maExcludedButtons[nIndex]->SetIconSize(eIconSize);
+ for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
+ maRegularButtons[nIndex]->SetIconSize(eIconSize);
+
+ // Determine maximal height and total width of the buttons.
+ // Start with the buttons used for the excluded state.
+ sal_Int32 nMaximumHeight (0);
+ sal_Int32 nExcludedTotalWidth ((maExcludedButtons.size()-1) * nGap + 2*nBorder);
+ for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
+ {
+ const Size aSize (maExcludedButtons[nIndex]->GetSize());
+ if (aSize.Height() > nMaximumHeight)
+ nMaximumHeight = aSize.Height();
+ nExcludedTotalWidth += aSize.Width();
+ }
+
+ // Do the same for the regular buttons.
+ sal_Int32 nRegularTotalWidth ((maRegularButtons.size()-1) * nGap + 2*nBorder);
+ for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
+ {
+ const Size aSize (maRegularButtons[nIndex]->GetSize());
+ if (aSize.Height() > nMaximumHeight)
+ nMaximumHeight = aSize.Height();
+ nRegularTotalWidth += aSize.Width();
+ }
+ nMaximumHeight += 2*nBorder;
+
+ // Set up the bounding box of the button bar.
+ maButtonBoundingBox = mpBackgroundTheme->GetButtonArea();
+ maBackgroundLocation = mpBackgroundTheme->GetBackgroundLocation();
+ if (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonPaintType) == 1)
+ {
+ // Center the buttons.
+ maButtonBoundingBox.Left() += (maButtonBoundingBox.GetWidth() - nRegularTotalWidth)/2;
+ maButtonBoundingBox.Right() = maButtonBoundingBox.Left() + nRegularTotalWidth - 1;
+ }
+
+ // Place the buttons.
+ Rectangle aBox (maButtonBoundingBox);
+ aBox.Right() -= nBorder;
+ for (sal_Int32 nIndex=maRegularButtons.size()-1; nIndex>=0; --nIndex)
+ {
+ maRegularButtons[nIndex]->Place(aBox);
+ aBox.Right() = maRegularButtons[nIndex]->GetBoundingBox().Left() - nGap;
+ }
+
+ // For slides excluded from the show there is only one icon placed
+ // exactly like the second of the regular icons.
+ if (maRegularButtons.size()>=2 && maExcludedButtons.size()>=1)
+ {
+ aBox = maRegularButtons[1]->GetBoundingBox();
+ maExcludedButtons[0]->Place(aBox);
+ }
+
+ // We return true only when there is no inactive button.
+ for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
+ if ( ! maExcludedButtons[nIndex]->IsActive())
+ return false;
+ for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
+ if ( ! maRegularButtons[nIndex]->IsActive())
+ return false;
+
+ return true;
+}
+
+
+
+
+void ButtonBar::RequestFadeIn (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate)
+{
+ if ( ! rpDescriptor)
+ return;
+ if (mnLockCount > 0)
+ return;
+
+ const double nMinAlpha (0);
+ if ( ! bAnimate)
+ {
+ rpDescriptor->GetVisualState().SetButtonAlpha(nMinAlpha);
+ rpDescriptor->GetVisualState().SetButtonBarAlpha(nMinAlpha);
+ }
+ else
+ StartFadeAnimation(rpDescriptor, nMinAlpha, true);
+}
+
+
+
+
+void ButtonBar::RequestFadeOut (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate)
+{
+ if ( ! rpDescriptor)
+ return;
+ if (mnLockCount > 0)
+ return;
+
+ const double nMaxAlpha (1);
+ if ( ! bAnimate)
+ {
+ rpDescriptor->GetVisualState().SetButtonAlpha(nMaxAlpha);
+ rpDescriptor->GetVisualState().SetButtonBarAlpha(nMaxAlpha);
+ }
+ else
+ StartFadeAnimation(rpDescriptor, nMaxAlpha, false);
+}
+
+
+
+
+bool ButtonBar::IsVisible (const model::SharedPageDescriptor& rpDescriptor)
+{
+ const double nMaxAlpha (1);
+ return rpDescriptor && rpDescriptor->GetVisualState().GetButtonBarAlpha() < nMaxAlpha;
+}
+
+
+
+
+void ButtonBar::HandleDataChangeEvent (void)
+{
+ maExcludedButtons.clear();
+ maExcludedButtons.push_back(::boost::shared_ptr<Button>(new UnhideButton(mrSlideSorter)));
+
+ maRegularButtons.clear();
+ maRegularButtons.push_back(::boost::shared_ptr<Button>(new StartShowButton(mrSlideSorter)));
+ maRegularButtons.push_back(::boost::shared_ptr<Button>(new HideButton(mrSlideSorter)));
+ maRegularButtons.push_back(::boost::shared_ptr<Button>(new DuplicateButton(mrSlideSorter)));
+
+ mpBackgroundTheme.reset(
+ new BitmapBackgroundTheme(
+ mrSlideSorter.GetTheme(),
+ maRegularButtons));
+
+ // Force layout on next Paint().
+ maPageObjectSize = Size(0,0);
+}
+
+
+
+
+void ButtonBar::StartFadeAnimation (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const double nTargetAlpha,
+ const bool bFadeIn)
+{
+ model::SharedPageDescriptor pDescriptor (rpDescriptor);
+
+ const double nCurrentButtonAlpha (pDescriptor->GetVisualState().GetButtonAlpha());
+ const double nCurrentButtonBarAlpha (pDescriptor->GetVisualState().GetButtonBarAlpha());
+
+ // Stop a running animation.
+ const controller::Animator::AnimationId nId (
+ pDescriptor->GetVisualState().GetButtonAlphaAnimationId());
+ if (nId != controller::Animator::NotAnAnimationId)
+ mrSlideSorter.GetController().GetAnimator()->RemoveAnimation(nId);
+
+ // Prepare the blending functors that translate [0,1] animation
+ // times into alpha values of buttons and button bar.
+ const ::boost::function<double(double)> aButtonBlendFunctor (
+ ::boost::bind(
+ controller::AnimationFunction::Blend,
+ nCurrentButtonAlpha,
+ nTargetAlpha,
+ ::boost::bind(controller::AnimationFunction::Linear, _1)));
+ const ::boost::function<double(double)> aButtonBarBlendFunctor (
+ ::boost::bind(
+ controller::AnimationFunction::Blend,
+ nCurrentButtonBarAlpha,
+ nTargetAlpha,
+ ::boost::bind(controller::AnimationFunction::Linear, _1)));
+
+ // Delay the fade in a little bit when the buttons are not visible at
+ // all so that we do not leave a trail of half-visible buttons when the
+ // mouse is moved across the screen. No delay on fade out or when the
+ // buttons are already showing. Fade out is faster than fade in.
+ const double nDelay (nCurrentButtonBarAlpha>0 && nCurrentButtonBarAlpha<1
+ ? 0
+ : (mrSlideSorter.GetTheme()->GetIntegerValue(bFadeIn
+ ? Theme::Integer_ButtonFadeInDelay
+ : Theme::Integer_ButtonFadeOutDelay)));
+ const double nDuration (mrSlideSorter.GetTheme()->GetIntegerValue(bFadeIn
+ ? Theme::Integer_ButtonFadeInDuration
+ : Theme::Integer_ButtonFadeOutDuration));
+ pDescriptor->GetVisualState().SetButtonAlphaAnimationId(
+ mrSlideSorter.GetController().GetAnimator()->AddAnimation(
+ ::boost::bind(
+ controller::AnimationFunction::ApplyButtonAlphaChange,
+ pDescriptor,
+ ::boost::ref(mrSlideSorter.GetView()),
+ ::boost::bind(aButtonBlendFunctor, _1),
+ ::boost::bind(aButtonBarBlendFunctor, _1)),
+ nDelay,
+ nDuration,
+ ::boost::bind(
+ &model::VisualState::SetButtonAlphaAnimationId,
+ ::boost::ref(pDescriptor->GetVisualState()),
+ controller::Animator::NotAnAnimationId)
+ ));
+}
+
+
+
+
+void ButtonBar::AcquireLock (void)
+{
+ if (mnLockCount == 0 && mpDescriptor)
+ RequestFadeOut(mpDescriptor, true);
+
+ ++mnLockCount;
+}
+
+
+
+
+void ButtonBar::ReleaseLock (void)
+{
+ --mnLockCount;
+
+ if (mnLockCount == 0 && mpDescriptor)
+ RequestFadeIn(mpDescriptor, true);
+}
+
+
+
+
+//===== BackgroundTheme =====================================================
+
+ButtonBar::BackgroundTheme::BackgroundTheme (
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons)
+ : mpTheme(rpTheme)
+{
+ UpdateMinimumIconSizes(rButtons);
+}
+
+
+
+
+void ButtonBar::BackgroundTheme::SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox)
+{
+ maPreviewBoundingBox = rPreviewBoundingBox;
+ Layout();
+}
+
+
+
+
+void ButtonBar::BackgroundTheme::UpdateMinimumIconSizes (
+ const ::std::vector<SharedButton>& rButtons)
+{
+ OSL_ASSERT(mpTheme);
+
+ sal_Int32 nMaximumHeightLarge (0);
+ sal_Int32 nMaximumHeightMedium (0);
+ sal_Int32 nMaximumHeightSmall (0);
+ const sal_Int32 nGap (mpTheme->GetIntegerValue(Theme::Integer_ButtonGap));
+ const sal_Int32 nBorder (mpTheme->GetIntegerValue(Theme::Integer_ButtonBorder));
+ sal_Int32 nTotalWidthLarge ((rButtons.size()-1) * nGap + 2*nBorder);
+ sal_Int32 nTotalWidthMedium ((rButtons.size()-1) * nGap + 2*nBorder);
+ sal_Int32 nTotalWidthSmall ((rButtons.size()-1) * nGap + 2*nBorder);
+ for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
+ {
+ // Update large size.
+ Size aSize = rButtons[nIndex]->GetSize(Button::IconSize_Large);
+ if (aSize.Height() > nMaximumHeightLarge)
+ nMaximumHeightLarge = aSize.Height();
+ nTotalWidthLarge += aSize.Width();
+
+ // Update medium size.
+ aSize = rButtons[nIndex]->GetSize(Button::IconSize_Medium);
+ if (aSize.Height() > nMaximumHeightMedium)
+ nMaximumHeightMedium = aSize.Height();
+ nTotalWidthMedium += aSize.Width();
+
+ // Update small size.
+ aSize = rButtons[nIndex]->GetSize(Button::IconSize_Small);
+ if (aSize.Height() > nMaximumHeightSmall)
+ nMaximumHeightSmall = aSize.Height();
+ nTotalWidthSmall += aSize.Width();
+ }
+ maMinimumLargeButtonAreaSize = Size(nTotalWidthLarge, nMaximumHeightLarge+2*nBorder);
+ maMinimumMediumButtonAreaSize = Size(nTotalWidthMedium, nMaximumHeightMedium+2*nBorder);
+ maMinimumSmallButtonAreaSize = Size(nTotalWidthSmall, nMaximumHeightSmall+2*nBorder);
+}
+
+
+
+
+Button::IconSize ButtonBar::BackgroundTheme::GetIconSize (void) const
+{
+ return meIconSize;
+}
+
+
+
+
+//===== RectangleBackgroundTheme ============================================
+
+RectangleBackgroundTheme::RectangleBackgroundTheme (
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons)
+ : BackgroundTheme(rpTheme, rButtons),
+ mnBarHeight(0)
+{
+}
+
+
+
+
+BitmapEx RectangleBackgroundTheme::CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const
+{
+ OSL_ASSERT(mpTheme);
+
+ // Setup background color.
+ Color aTopFillColor (mpTheme->GetGradientColor(
+ Theme::Gradient_ButtonBackground,
+ Theme::Fill1));
+ Color aTopBorderColor (mpTheme->GetGradientColor(
+ Theme::Gradient_ButtonBackground,
+ Theme::Border1));
+ Color aBottomFillColor (mpTheme->GetGradientColor(
+ Theme::Gradient_ButtonBackground,
+ Theme::Fill2));
+ Color aBottomBorderColor (mpTheme->GetGradientColor(
+ Theme::Gradient_ButtonBackground,
+ Theme::Border2));
+ if (bIsButtonDown)
+ {
+ aTopFillColor.DecreaseLuminance(50);
+ aTopBorderColor.DecreaseLuminance(50);
+ aBottomFillColor.DecreaseLuminance(50);
+ aBottomBorderColor.DecreaseLuminance(50);
+ }
+
+ const int nWidth (maPreviewBoundingBox.GetWidth()+2);
+ const int nHeight (mnBarHeight);
+ const int nCenter (nHeight / 2);
+
+ VirtualDevice aDevice (rTemplateDevice, 0, 8);
+ aDevice.SetOutputSizePixel(Size(nWidth,nHeight));
+
+ // Fill upper and lower half.
+ aDevice.SetLineColor();
+ aDevice.SetFillColor(aTopFillColor);
+ aDevice.DrawRect(Rectangle(0,0,nWidth-1,nCenter));
+ aDevice.SetFillColor(aBottomFillColor);
+ aDevice.DrawRect(Rectangle(0,nCenter,nWidth-1,nHeight-1));
+
+ // Draw border.
+ aDevice.SetFillColor();
+ aDevice.SetLineColor(aTopBorderColor);
+ aDevice.DrawLine(Point(0,nCenter),Point(0,0));
+ aDevice.DrawLine(Point(0,0), Point(nWidth-1,0));
+ aDevice.DrawLine(Point(nWidth-1,0),Point(nWidth-1,nCenter));
+ aDevice.SetLineColor(aBottomBorderColor);
+ aDevice.DrawLine(Point(0,nCenter),Point(0,nHeight-1));
+ aDevice.DrawLine(Point(0,nHeight-1), Point(nWidth-1,nHeight-1));
+ aDevice.DrawLine(Point(nWidth-1,nHeight-1),Point(nWidth-1,nCenter));
+
+ return aDevice.GetBitmapEx(Point(0,0), Size(nWidth,nHeight));
+}
+
+
+
+
+Point RectangleBackgroundTheme::GetBackgroundLocation (void)
+{
+ return Point(
+ maPreviewBoundingBox.Left()-1,
+ maPreviewBoundingBox.Bottom() - mnBarHeight + 2);
+}
+
+
+
+
+Rectangle RectangleBackgroundTheme::GetButtonArea (void)
+{
+ return Rectangle(
+ maPreviewBoundingBox.Left(),
+ maPreviewBoundingBox.Bottom() - mnBarHeight + 2,
+ maPreviewBoundingBox.Right(),
+ maPreviewBoundingBox.Bottom());
+}
+
+
+
+
+void RectangleBackgroundTheme::Layout (void)
+{
+ if (maPreviewBoundingBox.GetWidth() < maMinimumLargeButtonAreaSize.Width())
+ if (maPreviewBoundingBox.GetWidth() < maMinimumMediumButtonAreaSize.Width())
+ {
+ meIconSize = Button::IconSize_Small;
+ mnBarHeight = maMinimumSmallButtonAreaSize.Height();
+ }
+ else
+ {
+ meIconSize = Button::IconSize_Medium;
+ mnBarHeight = maMinimumMediumButtonAreaSize.Height();
+ }
+ else
+ {
+ meIconSize = Button::IconSize_Large;
+ mnBarHeight = maMinimumLargeButtonAreaSize.Height();
+ }
+}
+
+
+
+
+//===== BitmapBackgroundTheme =================================================
+
+BitmapBackgroundTheme::BitmapBackgroundTheme (
+ const ::boost::shared_ptr<Theme>& rpTheme,
+ const ::std::vector<SharedButton>& rButtons)
+ : BackgroundTheme(rpTheme, rButtons),
+ maButtonArea(),
+ maBackgroundLocation()
+{
+}
+
+
+
+
+BitmapEx BitmapBackgroundTheme::CreateBackground (
+ const OutputDevice& rTemplateDevice,
+ const bool bIsButtonDown) const
+{
+ (void)rTemplateDevice;
+ (void)bIsButtonDown;
+
+ OSL_ASSERT(mpTheme);
+
+ // Get images.
+ switch (meIconSize)
+ {
+ case Button::IconSize_Large:
+ default:
+ return mpTheme->GetIcon(Theme::Icon_ButtonBarLarge);
+
+ case Button::IconSize_Medium:
+ return mpTheme->GetIcon(Theme::Icon_ButtonBarMedium);
+
+ case Button::IconSize_Small:
+ return mpTheme->GetIcon(Theme::Icon_ButtonBarSmall);
+ }
+}
+
+
+
+
+Point BitmapBackgroundTheme::GetBackgroundLocation (void)
+{
+ return maBackgroundLocation;
+}
+
+
+
+
+Rectangle BitmapBackgroundTheme::GetButtonArea (void)
+{
+ return maButtonArea;
+}
+
+
+
+
+void BitmapBackgroundTheme::Layout (void)
+{
+ Size aImageSize (mpTheme->GetIcon(Theme::Icon_ButtonBarLarge).GetSizePixel());
+ if (aImageSize.Width() >= maPreviewBoundingBox.GetWidth())
+ {
+ aImageSize = mpTheme->GetIcon(Theme::Icon_ButtonBarMedium).GetSizePixel();
+ if (aImageSize.Width() >= maPreviewBoundingBox.GetWidth())
+ {
+ meIconSize = Button::IconSize_Small;
+ aImageSize = mpTheme->GetIcon(Theme::Icon_ButtonBarSmall).GetSizePixel();
+ }
+ else
+ meIconSize = Button::IconSize_Medium;
+ }
+ else
+ {
+ meIconSize = Button::IconSize_Large;
+ }
+
+ maBackgroundLocation = Point(
+ maPreviewBoundingBox.Left()
+ + (maPreviewBoundingBox.GetWidth()-aImageSize.Width())/2,
+ maPreviewBoundingBox.Bottom() - aImageSize.Height());
+ maButtonArea = Rectangle(maBackgroundLocation, aImageSize);
+}
+
+
+
+
+//===== Button ================================================================
+
+Button::Button (
+ SlideSorter& rSlideSorter,
+ const ::rtl::OUString& rsHelpText)
+ : mrSlideSorter(rSlideSorter),
+ meState(State_Normal),
+ maBoundingBox(),
+ msHelpText(rsHelpText),
+ mbIsActive(false),
+ meIconSize(IconSize_Large)
+{
+}
+
+
+
+
+Button::~Button (void)
+{
+}
+
+
+
+
+bool Button::SetState (const State eState)
+{
+ if (meState != eState)
+ {
+ meState = eState;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+Button::State Button::GetState (void) const
+{
+ return meState;
+}
+
+
+
+
+Rectangle Button::GetBoundingBox (void) const
+{
+ if (mbIsActive)
+ return maBoundingBox;
+ else
+ return Rectangle();
+}
+
+
+
+
+::rtl::OUString Button::GetHelpText (void) const
+{
+ if (mbIsActive)
+ return msHelpText;
+ else
+ return ::rtl::OUString();
+}
+
+
+
+
+bool Button::IsDown (void) const
+{
+ return mbIsActive && meState==State_Down;
+}
+
+
+
+
+void Button::SetActiveState (const bool bIsActive)
+{
+ mbIsActive = bIsActive;
+}
+
+
+
+
+bool Button::IsActive (void) const
+{
+ return mbIsActive;
+}
+
+
+
+
+void Button::SetIconSize (const IconSize eIconSize)
+{
+ meIconSize = eIconSize;
+}
+
+
+
+
+Button::IconSize Button::GetIconSize (void) const
+{
+ return meIconSize;
+}
+
+
+
+
+bool Button::IsEnabled (void) const
+{
+ return true;
+}
+
+
+
+
+//===== TextButton ============================================================
+
+TextButton::TextButton (
+ SlideSorter& rSlideSorter,
+ const ::rtl::OUString& rsText,
+ const ::rtl::OUString& rsHelpText)
+ : Button(rSlideSorter, rsHelpText),
+ msText(rsText)
+{
+}
+
+
+
+
+void TextButton::Place (const Rectangle aButtonBarBox)
+{
+ maBoundingBox = aButtonBarBox;
+ SetActiveState(true);
+}
+
+
+
+
+void TextButton::Paint (
+ OutputDevice& rDevice,
+ const Point aOffset,
+ const double nAlpha,
+ const ::boost::shared_ptr<Theme>& rpTheme) const
+{
+ (void)nAlpha;
+
+ if (mbIsActive)
+ {
+ // Paint text over the button background.
+ if (meState == State_Normal)
+ rDevice.SetTextColor(rpTheme->GetColor(Theme::Color_ButtonText));
+ else
+ rDevice.SetTextColor(rpTheme->GetColor(Theme::Color_ButtonTextHover));
+ Rectangle aBox (maBoundingBox);
+ aBox += aOffset;
+ rDevice.DrawText(aBox, msText, TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER);
+ }
+}
+
+
+
+
+Size TextButton::GetSize (void) const
+{
+ return Size();
+}
+
+
+
+
+Size TextButton::GetSize (const Button::IconSize) const
+{
+ return Size();
+}
+
+
+
+
+//===== ImageButon ============================================================
+
+ImageButton::ImageButton (
+ SlideSorter& rSlideSorter,
+ const BitmapEx& rLargeIcon,
+ const BitmapEx& rLargeHoverIcon,
+ const BitmapEx& rMediumIcon,
+ const BitmapEx& rMediumHoverIcon,
+ const BitmapEx& rSmallIcon,
+ const BitmapEx& rSmallHoverIcon,
+ const ::rtl::OUString& rsHelpText)
+ : Button(rSlideSorter, rsHelpText),
+ maLargeIcon(rLargeIcon),
+ maLargeHoverIcon(rLargeHoverIcon.IsEmpty() ? rLargeIcon : rLargeHoverIcon),
+ maMediumIcon(rMediumIcon),
+ maMediumHoverIcon(rMediumHoverIcon.IsEmpty() ? rMediumIcon : rMediumHoverIcon),
+ maSmallIcon(rSmallIcon),
+ maSmallHoverIcon(rSmallHoverIcon.IsEmpty() ? rSmallIcon : rSmallHoverIcon)
+{
+}
+
+
+
+
+void ImageButton::Place (const Rectangle aButtonBarBox)
+{
+ const sal_Int32 nWidth (GetSize().Width());
+ maBoundingBox = Rectangle(
+ aButtonBarBox.Right() - nWidth,
+ aButtonBarBox.Top(),
+ aButtonBarBox.Right(),
+ aButtonBarBox.Bottom());
+ SetActiveState(aButtonBarBox.IsInside(maBoundingBox));
+}
+
+
+
+
+void ImageButton::Paint (
+ OutputDevice& rDevice,
+ const Point aOffset,
+ const double nAlpha,
+ const ::boost::shared_ptr<Theme>& rpTheme) const
+{
+ (void)rpTheme;
+
+ if ( ! mbIsActive)
+ return;
+
+ const sal_uInt16 nSavedAntialiasingMode (rDevice.GetAntialiasing());
+ rDevice.SetAntialiasing(nSavedAntialiasingMode | ANTIALIASING_ENABLE_B2DDRAW);
+
+ rDevice.SetLineColor();
+
+ // Choose icon.
+ BitmapEx aIcon;
+ switch (meIconSize)
+ {
+ case IconSize_Large:
+ default:
+ if (meState == State_Normal)
+ aIcon = maLargeIcon;
+ else
+ aIcon = maLargeHoverIcon;
+ break;
+
+ case IconSize_Medium:
+ if (meState == State_Normal)
+ aIcon = maMediumIcon;
+ else
+ aIcon = maMediumHoverIcon;
+ break;
+
+ case IconSize_Small:
+ if (meState == State_Normal)
+ aIcon = maSmallIcon;
+ else
+ aIcon = maSmallHoverIcon;
+ break;
+ }
+
+ // Paint icon.
+ if ( ! aIcon.IsEmpty())
+ {
+ AlphaMask aMask (aIcon.GetSizePixel());
+ AdaptTransparency(aMask, aIcon.GetAlpha(), nAlpha);
+ rDevice.DrawBitmapEx(
+ Point(
+ maBoundingBox.Left()
+ + aOffset.X()
+ + (maBoundingBox.GetWidth()-aIcon.GetSizePixel().Width())/2,
+ maBoundingBox.Top()
+ + aOffset.Y()
+ + (maBoundingBox.GetHeight()-aIcon.GetSizePixel().Height())/2),
+ BitmapEx(aIcon.GetBitmap(), aMask));
+ }
+
+ rDevice.SetAntialiasing(nSavedAntialiasingMode);
+}
+
+
+
+
+Size ImageButton::GetSize (void) const
+{
+ return GetSize(meIconSize);
+}
+
+
+
+
+Size ImageButton::GetSize (const Button::IconSize eIconSize) const
+{
+ switch (eIconSize)
+ {
+ case IconSize_Large:
+ default:
+ return maLargeIcon.GetSizePixel();
+
+ case IconSize_Medium:
+ return maMediumIcon.GetSizePixel();
+
+ case IconSize_Small:
+ return maSmallIcon.GetSizePixel();
+ }
+}
+
+
+
+
+//===== UnhideButton ==========================================================
+
+UnhideButton::UnhideButton (SlideSorter& rSlideSorter)
+ : ImageButton(
+ rSlideSorter,
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BLarge),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BLargeHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BMedium),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BMediumHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BSmall),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BSmallHover),
+ rSlideSorter.GetTheme()->GetString(Theme::String_Command2B))
+{
+}
+
+
+
+
+void UnhideButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if ( ! rpDescriptor)
+ return;
+ mrSlideSorter.GetController().GetSlotManager()->ChangeSlideExclusionState(
+ (rpDescriptor->HasState(model::PageDescriptor::ST_Selected)
+ ? model::SharedPageDescriptor()
+ : rpDescriptor),
+ false);
+}
+
+
+
+
+//===== StartSlideShowButton ==================================================
+
+StartShowButton::StartShowButton (SlideSorter& rSlideSorter)
+ : ImageButton(
+ rSlideSorter,
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Large),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1LargeHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Medium),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1MediumHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Small),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1SmallHover),
+ rSlideSorter.GetTheme()->GetString(Theme::String_Command1))
+{
+}
+
+
+
+
+bool StartShowButton::IsEnabled (void) const
+{
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell == NULL)
+ return false;
+ SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
+ if (pDispatcher == NULL)
+ return false;
+
+ const SfxPoolItem* pState = NULL;
+ const SfxItemState eState (pDispatcher->QueryState(SID_PRESENTATION, pState));
+ return (eState & SFX_ITEM_DISABLED) == 0;
+}
+
+
+
+
+void StartShowButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
+{
+ // Hide the tool tip early, while the slide show still intializes.
+ mrSlideSorter.GetView().GetToolTip().SetPage(model::SharedPageDescriptor());
+
+ Reference< XPresentation2 > xPresentation(
+ mrSlideSorter.GetModel().GetDocument()->getPresentation());
+ if (xPresentation.is())
+ {
+ Sequence<PropertyValue> aProperties (1);
+ aProperties[0].Name = ::rtl::OUString::createFromAscii("FirstPage");
+ const ::rtl::OUString sName (rpDescriptor->GetPage()->GetName());
+ aProperties[0].Value = Any(sName);
+ xPresentation->startWithArguments(aProperties);
+ }
+}
+
+
+
+
+//===== HideButton ============================================================
+
+HideButton::HideButton (SlideSorter& rSlideSorter)
+ : ImageButton(
+ rSlideSorter,
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Large),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2LargeHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Medium),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2MediumHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Small),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2SmallHover),
+ rSlideSorter.GetTheme()->GetString(Theme::String_Command2))
+{
+}
+
+
+
+
+void HideButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if ( ! rpDescriptor)
+ return;
+ mrSlideSorter.GetController().GetSlotManager()->ChangeSlideExclusionState(
+ (rpDescriptor->HasState(model::PageDescriptor::ST_Selected)
+ ? model::SharedPageDescriptor()
+ : rpDescriptor),
+ true);
+}
+
+
+
+
+//===== DuplicateButton =======================================================
+
+DuplicateButton::DuplicateButton (SlideSorter& rSlideSorter)
+ : ImageButton(
+ rSlideSorter,
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Large),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3LargeHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Medium),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3MediumHover),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Small),
+ rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3SmallHover),
+ rSlideSorter.GetTheme()->GetString(Theme::String_Command3))
+{
+}
+
+
+
+
+bool DuplicateButton::IsEnabled (void) const
+{
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell == NULL)
+ return false;
+ SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
+ if (pDispatcher == NULL)
+ return false;
+
+ const SfxPoolItem* pState = NULL;
+ const SfxItemState eState (pDispatcher->QueryState(
+ SID_DUPLICATE_PAGE,
+ pState));
+ return (eState & SFX_ITEM_DISABLED) == 0;
+}
+
+
+
+
+void DuplicateButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if ( ! rpDescriptor)
+ return;
+
+ mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor(),false);
+
+ // When the page under the button is not selected then set the
+ // selection to just this page.
+ if ( ! rpDescriptor->HasState(model::PageDescriptor::ST_Selected))
+ {
+ mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
+ mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
+ }
+ // Duplicate the selected pages. Insert the new pages right
+ // after the current selection and select them
+ if (mrSlideSorter.GetViewShell() != NULL
+ && mrSlideSorter.GetViewShell()->GetDispatcher() != NULL)
+ {
+ mrSlideSorter.GetViewShell()->GetDispatcher()->Execute(
+ SID_DUPLICATE_PAGE,
+ SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD);
+ }
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::view