/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the 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 "sddll.hxx" #include "optsitem.hxx" #include #include #include #include #include #include #include #include #include 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& rpTheme, const ::std::vector& 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 mpTheme; Rectangle maPreviewBoundingBox; Size maMinimumLargeButtonAreaSize; Size maMinimumMediumButtonAreaSize; Size maMinimumSmallButtonAreaSize; Button::IconSize meIconSize; virtual void Layout (void) = 0; private: void UpdateMinimumIconSizes(const ::std::vector& rButtons); }; namespace { /** Rectangular button bar that covers the whole width of the preview. */ class RectangleBackgroundTheme : public ButtonBar::BackgroundTheme { public: RectangleBackgroundTheme( const ::boost::shared_ptr& rpTheme, const ::std::vector& 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& rpTheme, const ::std::vector& 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 written to the result mask. */ void AdaptTransparency (AlphaMask& rMask, const AlphaMask& rSourceMask, const double nAlpha) { BitmapWriteAccess* pBitmap = rMask.AcquireWriteAccess(); const BitmapReadAccess* pSourceBitmap = const_cast(rSourceMask).AcquireReadAccess(); if (pBitmap!=NULL && pSourceBitmap!=NULL) { const sal_Int32 nWidth (pBitmap->Width()); const sal_Int32 nHeight (pBitmap->Height()); for (sal_Int32 nY = 0; nYGetPixel(nY, nX).GetBlueOrIndex()); const sal_Int32 nNewValue (::basegfx::clamp( static_cast(nValue * (1-nAlpha)), 0, 255)); pBitmap->SetPixelIndex(nY, nX, static_cast(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