Files
libreoffice/sd/source/ui/slidesorter/view/SlsButtonBar.cxx
2012-08-02 21:53:58 +04:00

1227 lines
34 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* 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 "view/SlsButtonBar.hxx"
#include "SlideSorter.hxx"
#include "SlsResource.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 "strings.hrc"
#include "drawdoc.hxx"
#include "sdmod.hxx"
#include "optsitem.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);
virtual ~BackgroundTheme() { }
/** 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;
virtual Point GetBackgroundLocation (void);
virtual Rectangle GetButtonArea (void);
protected:
::boost::shared_ptr<Theme> mpTheme;
Rectangle maPreviewBoundingBox;
Size maMinimumLargeButtonAreaSize;
Size maMinimumMediumButtonAreaSize;
Size maMinimumSmallButtonAreaSize;
Button::IconSize meIconSize;
Rectangle maButtonArea;
Point maBackgroundLocation;
virtual void Layout (void);
private:
/// Compute the size of the are for the given button size.
static Size MinimumSize( Button::IconSize eSize, const ::std::vector<SharedButton>& rButtons );
void UpdateMinimumIconSizes(const ::std::vector<SharedButton>& rButtons);
};
namespace {
/** 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 (static_cast<sal_uInt8>(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(),
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;
}
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)
{
if (maNormalBackground.IsEmpty())
{
if (mpBackgroundTheme)
maNormalBackground = mpBackgroundTheme->CreateBackground();
}
if (!maNormalBackground.IsEmpty())
{
AlphaMask aMask (maNormalBackground.GetSizePixel());
AdaptTransparency(
aMask,
maNormalBackground.GetAlpha(),
rpDescriptor->GetVisualState().GetButtonBarAlpha());
rDevice.DrawBitmapEx(maBackgroundLocation+aOffset, BitmapEx(maNormalBackground.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::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();
}
}
bool ButtonBar::LayoutButtons (void)
{
const sal_Int32 nGap = Theme_ButtonGap;
const sal_Int32 nBorder = Theme_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 (Theme_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 BackgroundTheme(
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
: (bFadeIn ? Theme_ButtonFadeInDelay : Theme_ButtonFadeOutDelay));
const double nDuration (bFadeIn ? Theme_ButtonFadeInDuration : Theme_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)),
static_cast<sal_Int32>(nDelay),
static_cast<sal_Int32>(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),
meIconSize( Button::IconSize_Large ),
maButtonArea(),
maBackgroundLocation()
{
UpdateMinimumIconSizes(rButtons);
}
void ButtonBar::BackgroundTheme::SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox)
{
maPreviewBoundingBox = rPreviewBoundingBox;
Layout();
}
Size ButtonBar::BackgroundTheme::MinimumSize( Button::IconSize eSize,
const ::std::vector<SharedButton>& rButtons )
{
int nMaximumHeight = 0;
const int nGap = Theme_ButtonGap;
const int nBorder = Theme_ButtonBorder;
int nTotalWidth = (rButtons.size()-1) * nGap + 2*nBorder;
for ( int nIndex = 0; nIndex < int( rButtons.size() ); ++nIndex )
{
// Update large size.
Size aSize( rButtons[nIndex]->GetSize(eSize) );
if ( aSize.Height() > nMaximumHeight )
nMaximumHeight = aSize.Height();
nTotalWidth += aSize.Width();
}
return Size( nTotalWidth, nMaximumHeight + 2*nBorder );
}
void ButtonBar::BackgroundTheme::UpdateMinimumIconSizes (
const ::std::vector<SharedButton>& rButtons)
{
maMinimumLargeButtonAreaSize = MinimumSize( Button::IconSize_Large, rButtons );
maMinimumMediumButtonAreaSize = MinimumSize( Button::IconSize_Medium, rButtons );
maMinimumSmallButtonAreaSize = MinimumSize( Button::IconSize_Small, rButtons );
}
Button::IconSize ButtonBar::BackgroundTheme::GetIconSize (void) const
{
return meIconSize;
}
BitmapEx ButtonBar::BackgroundTheme::CreateBackground () const
{
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 ButtonBar::BackgroundTheme::GetBackgroundLocation (void)
{
return maBackgroundLocation;
}
Rectangle ButtonBar::BackgroundTheme::GetButtonArea (void)
{
return maButtonArea;
}
void ButtonBar::BackgroundTheme::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 BitmapEx& rLargeIcon,
const BitmapEx& rLargeHoverIcon,
const BitmapEx& rMediumIcon,
const BitmapEx& rMediumHoverIcon,
const BitmapEx& rSmallIcon,
const BitmapEx& rSmallHoverIcon,
const ::rtl::OUString& rsHelpText)
: mrSlideSorter(rSlideSorter),
meState(State_Normal),
maBoundingBox(),
msHelpText(rsHelpText),
mbIsActive(false),
meIconSize(IconSize_Large),
maLargeIcon(rLargeIcon),
maLargeHoverIcon(rLargeHoverIcon.IsEmpty() ? rLargeIcon : rLargeHoverIcon),
maMediumIcon(rMediumIcon),
maMediumHoverIcon(rMediumHoverIcon.IsEmpty() ? rMediumIcon : rMediumHoverIcon),
maSmallIcon(rSmallIcon),
maSmallHoverIcon(rSmallHoverIcon.IsEmpty() ? rSmallIcon : rSmallHoverIcon)
{
}
Button::~Button (void)
{
}
bool Button::SetState (const State eState)
{
if (meState != eState)
{
meState = eState;
return true;
}
else
return false;
}
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();
}
void Button::SetActiveState (const bool bIsActive)
{
mbIsActive = bIsActive;
}
bool Button::IsActive (void) const
{
return mbIsActive;
}
void Button::SetIconSize (const IconSize eIconSize)
{
meIconSize = eIconSize;
}
bool Button::IsEnabled (void) const
{
return true;
}
void Button::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 Button::Paint (
OutputDevice& rDevice,
const Point aOffset,
const double nAlpha,
const ::boost::shared_ptr<Theme>&) const
{
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 Button::GetSize (void) const
{
return GetSize(meIconSize);
}
Size Button::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)
: Button(
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),
String(SdResId(STRING_SHOW_SLIDE)))
{
}
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)
: Button(
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),
String(SdResId(STRING_START_SLIDESHOW)))
{
}
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("FirstPage");
const ::rtl::OUString sName (rpDescriptor->GetPage()->GetName());
aProperties[0].Value = Any(sName);
// We have to temporarily change the options value
// StartWithActualPage to make the slide show use the
// specified first page.
const DocumentType eType (mrSlideSorter.GetModel().GetDocument()->GetDocumentType());
const sal_Bool bSavedState (SD_MOD()->GetSdOptions(eType)->IsStartWithActualPage());
SD_MOD()->GetSdOptions(eType)->SetStartWithActualPage(sal_False);
xPresentation->startWithArguments(aProperties);
// Restore previous StartWithActualPage value.
SD_MOD()->GetSdOptions(eType)->SetStartWithActualPage(bSavedState);
}
}
//===== HideButton ============================================================
HideButton::HideButton (SlideSorter& rSlideSorter)
: Button(
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),
String(SdResId(STRING_HIDE_SLIDE)))
{
}
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)
: Button(
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),
String(SdResId(STRING_DUPLICATE_SLIDE)))
{
}
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
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */