xref: /AOO41X/main/sd/source/ui/slidesorter/view/SlsButtonBar.cxx (revision b191c3038d411d8f20d409e94ba7a35bd6c8e459)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "view/SlsButtonBar.hxx"
31 
32 #include "SlideSorter.hxx"
33 #include "model/SlsPageDescriptor.hxx"
34 #include "model/SlideSorterModel.hxx"
35 #include "view/SlsTheme.hxx"
36 #include "view/SlideSorterView.hxx"
37 #include "view/SlsToolTip.hxx"
38 #include "controller/SlideSorterController.hxx"
39 #include "controller/SlsSlotManager.hxx"
40 #include "controller/SlsCurrentSlideManager.hxx"
41 #include "controller/SlsPageSelector.hxx"
42 #include "controller/SlsAnimator.hxx"
43 #include "controller/SlsAnimationFunction.hxx"
44 #include "app.hrc"
45 #include "drawdoc.hxx"
46 #include "sddll.hxx"
47 #include "optsitem.hxx"
48 #include <svx/svxids.hrc>
49 #include <sfx2/dispatch.hxx>
50 #include <vcl/bmpacc.hxx>
51 #include <vcl/virdev.hxx>
52 #include <basegfx/polygon/b2dpolygontools.hxx>
53 #include <basegfx/polygon/b2dpolygon.hxx>
54 #include <basegfx/numeric/ftools.hxx>
55 #include <com/sun/star/presentation/XPresentation2.hpp>
56 #include <boost/bind.hpp>
57 
58 using ::com::sun::star::uno::Any;
59 using ::com::sun::star::uno::Reference;
60 using ::com::sun::star::uno::Sequence;
61 using ::com::sun::star::beans::PropertyValue;
62 using ::com::sun::star::presentation::XPresentation2;
63 
64 namespace sd { namespace slidesorter { namespace view {
65 
66 /** Base class for the painter of the background bar onto which the buttons
67     are painted.  It also provides some size information.
68 */
69 class ButtonBar::BackgroundTheme
70 {
71 public:
72     BackgroundTheme(
73         const ::boost::shared_ptr<Theme>& rpTheme,
74         const ::std::vector<SharedButton>& rButtons);
75     /** Set the preview bounding box, the maximal area in which to display
76         buttons.  A call to this method triggers a call to Layout().
77     */
78     void SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox);
79     Button::IconSize GetIconSize (void) const;
80 
81     virtual BitmapEx CreateBackground (
82         const OutputDevice& rTemplateDevice,
83         const bool bIsButtonDown) const = 0;
84     virtual Point GetBackgroundLocation (void) = 0;
85     virtual Rectangle GetButtonArea (void) = 0;
86 
87 protected:
88     ::boost::shared_ptr<Theme> mpTheme;
89     Rectangle maPreviewBoundingBox;
90     Size maMinimumLargeButtonAreaSize;
91     Size maMinimumMediumButtonAreaSize;
92     Size maMinimumSmallButtonAreaSize;
93     Button::IconSize meIconSize;
94 
95     virtual void Layout (void) = 0;
96 
97 private:
98     void UpdateMinimumIconSizes(const ::std::vector<SharedButton>& rButtons);
99 };
100 
101 
102 namespace {
103     /** Rectangular button bar that covers the whole width of the preview.
104     */
105     class RectangleBackgroundTheme : public ButtonBar::BackgroundTheme
106     {
107     public:
108         RectangleBackgroundTheme(
109             const ::boost::shared_ptr<Theme>& rpTheme,
110             const ::std::vector<SharedButton>& rButtons);
111         virtual BitmapEx CreateBackground (
112             const OutputDevice& rTemplateDevice,
113             const bool bIsButtonDown) const;
114         virtual Point GetBackgroundLocation (void);
115         virtual Rectangle GetButtonArea (void);
116     protected:
117         virtual void Layout (void);
118     private:
119         sal_Int32 mnBarHeight;
120     };
121 
122     /** Button bar is composed of three images, the left and right end of
123         the bar and the center image.  Buttons are only placed over the
124         center image.  The center image is painted as is, it is not scaled.
125     */
126     class BitmapBackgroundTheme : public ButtonBar::BackgroundTheme
127     {
128     public:
129         BitmapBackgroundTheme(
130             const ::boost::shared_ptr<Theme>& rpTheme,
131             const ::std::vector<SharedButton>& rButtons);
132         virtual BitmapEx CreateBackground (
133             const OutputDevice& rTemplateDevice,
134             const bool bIsButtonDown) const;
135         virtual Point GetBackgroundLocation (void);
136         virtual Rectangle GetButtonArea (void);
137     protected:
138         virtual void Layout (void);
139     private:
140         Rectangle maButtonArea;
141         Point maBackgroundLocation;
142     };
143 
144     /** The source mask is essentially multiplied with the given alpha value.
145         The result is writen to the result mask.
146     */
147     void AdaptTransparency (AlphaMask& rMask, const AlphaMask& rSourceMask, const double nAlpha)
148     {
149         BitmapWriteAccess* pBitmap = rMask.AcquireWriteAccess();
150         const BitmapReadAccess* pSourceBitmap = const_cast<AlphaMask&>(rSourceMask).AcquireReadAccess();
151 
152         if (pBitmap!=NULL && pSourceBitmap!=NULL)
153         {
154             const sal_Int32 nWidth (pBitmap->Width());
155             const sal_Int32 nHeight (pBitmap->Height());
156 
157             for (sal_Int32 nY = 0; nY<nHeight; ++nY)
158                 for (sal_Int32 nX = 0; nX<nWidth; ++nX)
159                 {
160                     const sal_uInt8 nValue (255 - pSourceBitmap->GetPixel(nY, nX).GetBlueOrIndex());
161                     const sal_Int32 nNewValue (::basegfx::clamp<sal_Int32>(
162                             static_cast<sal_Int32>(nValue * (1-nAlpha)),
163                             0,
164                             255));
165                     pBitmap->SetPixel(nY, nX, 255-sal_uInt8(nNewValue));
166                 }
167         }
168     }
169 
170 } // end of anonymous namespace
171 
172 
173 //===== ButtonBar::Lock =======================================================
174 
175 ButtonBar::Lock::Lock (SlideSorter& rSlideSorter)
176     : mrButtonBar(rSlideSorter.GetView().GetButtonBar())
177 {
178     mrButtonBar.AcquireLock();
179 }
180 
181 
182 
183 
184 ButtonBar::Lock::~Lock (void)
185 {
186     mrButtonBar.ReleaseLock();
187 }
188 
189 
190 
191 
192 //===== ButtonBar =============================================================
193 
194 ButtonBar::ButtonBar (SlideSorter& rSlideSorter)
195     : mrSlideSorter(rSlideSorter),
196       maPageObjectSize(0,0),
197       maButtonBoundingBox(),
198       maBackgroundLocation(),
199       mpDescriptor(),
200       mbIsExcluded(false),
201       mpButtonUnderMouse(),
202       mpDownButton(),
203       maRegularButtons(),
204       maExcludedButtons(),
205       maNormalBackground(),
206       maButtonDownBackground(),
207       mbIsMouseOverBar(false),
208       mpBackgroundTheme(),
209       mnLockCount(0)
210 {
211     HandleDataChangeEvent();
212 }
213 
214 
215 
216 
217 ButtonBar::~ButtonBar (void)
218 {
219 }
220 
221 
222 
223 
224 void ButtonBar::ProcessButtonDownEvent (
225     const model::SharedPageDescriptor& rpDescriptor,
226     const Point aMouseModelLocation)
227 {
228     SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
229     if (mpButtonUnderMouse)
230         mpButtonUnderMouse->SetState(Button::State_Down);
231     mpDownButton = mpButtonUnderMouse;
232 
233     mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
234 }
235 
236 
237 
238 
239 void ButtonBar::ProcessButtonUpEvent (
240     const model::SharedPageDescriptor& rpDescriptor,
241     const Point aMouseModelLocation)
242 {
243     SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
244     if (mpButtonUnderMouse)
245     {
246         mpButtonUnderMouse->SetState(Button::State_Hover);
247         if (mpButtonUnderMouse == mpDownButton)
248         {
249             // This is done only when the buttons are sufficiently visible.
250             if (mpDescriptor->GetVisualState().GetButtonAlpha()<0.7)
251             {
252                 mpButtonUnderMouse->ProcessClick(mpDescriptor);
253                 mbIsExcluded = mpDescriptor->HasState(model::PageDescriptor::ST_Excluded);
254                 ProcessMouseMotionEvent (rpDescriptor, aMouseModelLocation, false);
255             }
256         }
257     }
258     mpDownButton.reset();
259     mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
260 }
261 
262 
263 
264 
265 void ButtonBar::ProcessMouseMotionEvent (
266     const model::SharedPageDescriptor& rpDescriptor,
267     const Point aMouseModelLocation,
268     const bool bIsMouseButtonDown)
269 {
270     model::SharedPageDescriptor pOldDescriptor (mpDescriptor);
271     bool bPageHasChanged (false);
272     bool bButtonHasChanged (false);
273     bool bButtonStateHasChanged (false);
274 
275     // Update the page object for which to manage the buttons.
276     bPageHasChanged = SetPage(rpDescriptor);
277     mbIsMouseOverBar = IsMouseOverBar(aMouseModelLocation);
278 
279     // Update button under mouse.
280     if (rpDescriptor)
281     {
282         bButtonHasChanged = SetButtonUnderMouse(GetButtonAt(aMouseModelLocation));
283 
284         if (mpButtonUnderMouse)
285         {
286             // When the mouse button is down, mark the button under the
287             // mouse only as pressed when it is the same button the mouse
288             // button was pressed over, and where the button release would
289             // lead to a click action.
290             if (bIsMouseButtonDown)
291             {
292                 if (mpButtonUnderMouse==mpDownButton)
293                     bButtonStateHasChanged = mpButtonUnderMouse->SetState(Button::State_Down);
294             }
295             else
296                 bButtonStateHasChanged = mpButtonUnderMouse->SetState(Button::State_Hover);
297         }
298     }
299 
300     // Show a quick help text when the mouse is over a button.
301     if (bButtonHasChanged)
302     {
303         SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
304         if (pWindow)
305         {
306             if (mpButtonUnderMouse)
307                 mrSlideSorter.GetView().GetToolTip().ShowHelpText(mpButtonUnderMouse->GetHelpText());
308             else
309                 mrSlideSorter.GetView().GetToolTip().ShowDefaultHelpText();
310         }
311     }
312 
313     if (bPageHasChanged || bButtonHasChanged || bButtonStateHasChanged)
314     {
315         if (pOldDescriptor)
316             mrSlideSorter.GetView().RequestRepaint(pOldDescriptor);
317         if (mpDescriptor && pOldDescriptor!=mpDescriptor)
318             mrSlideSorter.GetView().RequestRepaint(mpDescriptor);
319     }
320 }
321 
322 
323 
324 
325 void ButtonBar::ResetPage (void)
326 {
327     SetPage(model::SharedPageDescriptor());
328 }
329 
330 
331 
332 
333 bool ButtonBar::SetPage (const model::SharedPageDescriptor& rpDescriptor)
334 {
335     if (mpDescriptor != rpDescriptor)
336     {
337         mpDescriptor = rpDescriptor;
338 
339         if (mpDescriptor)
340             mbIsExcluded = mpDescriptor->HasState(model::PageDescriptor::ST_Excluded);
341         else
342             mbIsExcluded = false;
343         SetButtonUnderMouse();
344         mpDownButton.reset();
345 
346         return true;
347     }
348     else
349         return false;
350 }
351 
352 
353 
354 
355 sal_Int32 ButtonBar::GetButtonCount (const bool bIsExcluded) const
356 {
357     if (bIsExcluded)
358         return maExcludedButtons.size();
359     else
360         return maRegularButtons.size();
361 }
362 
363 
364 
365 
366 ::boost::shared_ptr<Button> ButtonBar::GetButton (
367     const bool bIsExcluded,
368     const sal_Int32 nIndex) const
369 {
370     const ::std::vector<boost::shared_ptr<Button> >& rButtons (bIsExcluded
371         ? maExcludedButtons
372         : maRegularButtons);
373 
374     if (nIndex<0 || sal_uInt32(nIndex)>=rButtons.size())
375     {
376         OSL_ASSERT(nIndex<0 || sal_uInt32(nIndex)>=rButtons.size());
377         return ::boost::shared_ptr<Button>();
378     }
379     else
380         return rButtons[sal_uInt32(nIndex)];
381 }
382 
383 
384 
385 
386 SharedButton ButtonBar::GetButtonAt (const Point aModelLocation)
387 {
388     if (IsMouseOverBar(aModelLocation))
389     {
390         const Point aLocalLocation (aModelLocation - mpDescriptor->GetBoundingBox().TopLeft());
391         ::std::vector<SharedButton>& rButtons (
392             mbIsExcluded ? maExcludedButtons : maRegularButtons);
393         for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
394         {
395             if (rButtons[sal_uInt32(nIndex)]->GetBoundingBox().IsInside(aLocalLocation))
396             {
397                 if (rButtons[sal_uInt32(nIndex)]->IsEnabled())
398                     return rButtons[sal_uInt32(nIndex)];
399                 else
400                     return SharedButton();
401             }
402         }
403     }
404 
405     return SharedButton();
406 }
407 
408 
409 
410 
411 bool ButtonBar::IsMouseOverBar (void) const
412 {
413     return mbIsMouseOverBar;
414 }
415 
416 
417 
418 
419 bool ButtonBar::SetButtonUnderMouse (const SharedButton& rButton)
420 {
421     if (mpButtonUnderMouse != rButton)
422     {
423         if (mpButtonUnderMouse)
424             mpButtonUnderMouse->SetState(Button::State_Normal);
425 
426         mpButtonUnderMouse = rButton;
427 
428         return true;
429     }
430     else
431         return false;
432 }
433 
434 
435 
436 
437 void ButtonBar::Paint (
438     OutputDevice& rDevice,
439     const model::SharedPageDescriptor& rpDescriptor)
440 {
441     if ( ! rpDescriptor)
442         return;
443 
444     const double nButtonBarAlpha (rpDescriptor->GetVisualState().GetButtonBarAlpha());
445     if (nButtonBarAlpha >= 1)
446         return;
447 
448     LayoutButtons(rpDescriptor->GetBoundingBox().GetSize());
449 
450     const Point aOffset (rpDescriptor->GetBoundingBox().TopLeft());
451 
452     // Paint the background.
453     PaintButtonBackground(rDevice, rpDescriptor, aOffset);
454 
455     // Paint the buttons.
456     const ::std::vector<SharedButton>& rButtons (
457         rpDescriptor->HasState(model::PageDescriptor::ST_Excluded)
458             ? maExcludedButtons
459             : maRegularButtons);
460 
461 
462     const double nButtonAlpha (rpDescriptor->GetVisualState().GetButtonAlpha());
463     for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
464         rButtons[nIndex]->Paint(
465             rDevice,
466             aOffset,
467             nButtonAlpha,
468             mrSlideSorter.GetTheme());
469 }
470 
471 
472 
473 
474 bool ButtonBar::IsMouseOverButton (void) const
475 {
476     return mpButtonUnderMouse;
477 }
478 
479 
480 
481 
482 void ButtonBar::PaintButtonBackground (
483     OutputDevice& rDevice,
484     const model::SharedPageDescriptor& rpDescriptor,
485     const Point aOffset)
486 {
487     BitmapEx* pBitmap = NULL;
488     if (maButtonDownBackground.IsEmpty() || maNormalBackground.IsEmpty())
489     {
490         if (mpBackgroundTheme)
491         {
492             maButtonDownBackground = mpBackgroundTheme->CreateBackground(rDevice, true);
493             maNormalBackground = mpBackgroundTheme->CreateBackground(rDevice, false);
494         }
495     }
496     if (mpButtonUnderMouse && mpButtonUnderMouse->IsDown())
497         pBitmap = &maButtonDownBackground;
498     else
499         pBitmap = &maNormalBackground;
500     if (pBitmap != NULL)
501     {
502         AlphaMask aMask (pBitmap->GetSizePixel());
503         AdaptTransparency(
504             aMask,
505             pBitmap->GetAlpha(),
506             rpDescriptor->GetVisualState().GetButtonBarAlpha());
507         rDevice.DrawBitmapEx(maBackgroundLocation+aOffset, BitmapEx(pBitmap->GetBitmap(), aMask));
508     }
509 }
510 
511 
512 
513 
514 bool ButtonBar::IsMouseOverBar (const Point aModelLocation) const
515 {
516     if ( ! mpDescriptor || ! mpDescriptor->GetBoundingBox().IsInside(aModelLocation))
517         return false;
518 
519     if ( ! maButtonBoundingBox.IsInside(aModelLocation - mpDescriptor->GetBoundingBox().TopLeft()))
520         return false;
521 
522     return true;
523 }
524 
525 
526 
527 
528 void ButtonBar::RequestLayout (void)
529 {
530     maPageObjectSize = Size(0,0);
531 }
532 
533 
534 
535 
536 void ButtonBar::LayoutButtons (const Size aPageObjectSize)
537 {
538     if (maPageObjectSize != aPageObjectSize)
539     {
540         maPageObjectSize = aPageObjectSize;
541 
542         if (mpBackgroundTheme)
543         {
544             mpBackgroundTheme->SetPreviewBoundingBox(
545                 mrSlideSorter.GetView().GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
546                     Point(0,0),
547                     PageObjectLayouter::Preview,
548                     PageObjectLayouter::ModelCoordinateSystem));
549             LayoutButtons();
550         }
551 
552         // Release the background bitmaps so that on the next paint
553         // they are created anew in the right size.
554         maNormalBackground.SetEmpty();
555         maButtonDownBackground.SetEmpty();
556     }
557 }
558 
559 
560 
561 
562 bool ButtonBar::LayoutButtons (void)
563 {
564     const sal_Int32 nGap (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonGap));
565     const sal_Int32 nBorder (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonBorder));
566 
567     const Button::IconSize eIconSize (mpBackgroundTheme->GetIconSize());
568 
569     // Tell buttons which size they are.
570     for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
571         maExcludedButtons[nIndex]->SetIconSize(eIconSize);
572     for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
573         maRegularButtons[nIndex]->SetIconSize(eIconSize);
574 
575     // Determine maximal height and total width of the buttons.
576     // Start with the buttons used for the excluded state.
577     sal_Int32 nMaximumHeight (0);
578     sal_Int32 nExcludedTotalWidth ((maExcludedButtons.size()-1) * nGap + 2*nBorder);
579     for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
580     {
581         const Size aSize (maExcludedButtons[nIndex]->GetSize());
582         if (aSize.Height() > nMaximumHeight)
583             nMaximumHeight = aSize.Height();
584         nExcludedTotalWidth += aSize.Width();
585     }
586 
587     // Do the same for the regular buttons.
588     sal_Int32 nRegularTotalWidth ((maRegularButtons.size()-1) * nGap + 2*nBorder);
589     for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
590     {
591         const Size aSize (maRegularButtons[nIndex]->GetSize());
592         if (aSize.Height() > nMaximumHeight)
593             nMaximumHeight = aSize.Height();
594         nRegularTotalWidth += aSize.Width();
595     }
596     nMaximumHeight += 2*nBorder;
597 
598     // Set up the bounding box of the button bar.
599     maButtonBoundingBox = mpBackgroundTheme->GetButtonArea();
600     maBackgroundLocation = mpBackgroundTheme->GetBackgroundLocation();
601     if (mrSlideSorter.GetTheme()->GetIntegerValue(Theme::Integer_ButtonPaintType) == 1)
602     {
603         // Center the buttons.
604         maButtonBoundingBox.Left() += (maButtonBoundingBox.GetWidth() - nRegularTotalWidth)/2;
605         maButtonBoundingBox.Right() = maButtonBoundingBox.Left() + nRegularTotalWidth - 1;
606     }
607 
608     // Place the buttons.
609     Rectangle aBox (maButtonBoundingBox);
610     aBox.Right() -= nBorder;
611     for (sal_Int32 nIndex=maRegularButtons.size()-1; nIndex>=0; --nIndex)
612     {
613         maRegularButtons[nIndex]->Place(aBox);
614         aBox.Right() = maRegularButtons[nIndex]->GetBoundingBox().Left() - nGap;
615     }
616 
617     // For slides excluded from the show there is only one icon placed
618     // exactly like the second of the regular icons.
619     if (maRegularButtons.size()>=2 && maExcludedButtons.size()>=1)
620     {
621         aBox = maRegularButtons[1]->GetBoundingBox();
622         maExcludedButtons[0]->Place(aBox);
623     }
624 
625     // We return true only when there is no inactive button.
626     for (sal_uInt32 nIndex=0; nIndex<maExcludedButtons.size(); ++nIndex)
627         if ( ! maExcludedButtons[nIndex]->IsActive())
628             return false;
629     for (sal_uInt32 nIndex=0; nIndex<maRegularButtons.size(); ++nIndex)
630         if ( ! maRegularButtons[nIndex]->IsActive())
631             return false;
632 
633     return true;
634 }
635 
636 
637 
638 
639 void ButtonBar::RequestFadeIn (
640     const model::SharedPageDescriptor& rpDescriptor,
641     const bool bAnimate)
642 {
643     if ( ! rpDescriptor)
644         return;
645     if (mnLockCount > 0)
646         return;
647 
648     const double nMinAlpha (0);
649     if ( ! bAnimate)
650     {
651         rpDescriptor->GetVisualState().SetButtonAlpha(nMinAlpha);
652         rpDescriptor->GetVisualState().SetButtonBarAlpha(nMinAlpha);
653     }
654     else
655         StartFadeAnimation(rpDescriptor, nMinAlpha, true);
656 }
657 
658 
659 
660 
661 void ButtonBar::RequestFadeOut (
662     const model::SharedPageDescriptor& rpDescriptor,
663     const bool bAnimate)
664 {
665     if ( ! rpDescriptor)
666         return;
667     if (mnLockCount > 0)
668         return;
669 
670     const double nMaxAlpha (1);
671     if ( ! bAnimate)
672     {
673         rpDescriptor->GetVisualState().SetButtonAlpha(nMaxAlpha);
674         rpDescriptor->GetVisualState().SetButtonBarAlpha(nMaxAlpha);
675     }
676     else
677         StartFadeAnimation(rpDescriptor, nMaxAlpha, false);
678 }
679 
680 
681 
682 
683 bool ButtonBar::IsVisible (const model::SharedPageDescriptor& rpDescriptor)
684 {
685     const double nMaxAlpha (1);
686     return rpDescriptor && rpDescriptor->GetVisualState().GetButtonBarAlpha() < nMaxAlpha;
687 }
688 
689 
690 
691 
692 void ButtonBar::HandleDataChangeEvent (void)
693 {
694     maExcludedButtons.clear();
695     maExcludedButtons.push_back(::boost::shared_ptr<Button>(new UnhideButton(mrSlideSorter)));
696 
697     maRegularButtons.clear();
698     maRegularButtons.push_back(::boost::shared_ptr<Button>(new StartShowButton(mrSlideSorter)));
699     maRegularButtons.push_back(::boost::shared_ptr<Button>(new HideButton(mrSlideSorter)));
700     maRegularButtons.push_back(::boost::shared_ptr<Button>(new DuplicateButton(mrSlideSorter)));
701 
702     mpBackgroundTheme.reset(
703         new BitmapBackgroundTheme(
704             mrSlideSorter.GetTheme(),
705             maRegularButtons));
706 
707     // Force layout on next Paint().
708     maPageObjectSize = Size(0,0);
709 }
710 
711 
712 
713 
714 void ButtonBar::StartFadeAnimation (
715     const model::SharedPageDescriptor& rpDescriptor,
716     const double nTargetAlpha,
717     const bool bFadeIn)
718 {
719     model::SharedPageDescriptor pDescriptor (rpDescriptor);
720 
721     const double nCurrentButtonAlpha (pDescriptor->GetVisualState().GetButtonAlpha());
722     const double nCurrentButtonBarAlpha (pDescriptor->GetVisualState().GetButtonBarAlpha());
723 
724     // Stop a running animation.
725     const controller::Animator::AnimationId nId (
726         pDescriptor->GetVisualState().GetButtonAlphaAnimationId());
727     if (nId != controller::Animator::NotAnAnimationId)
728         mrSlideSorter.GetController().GetAnimator()->RemoveAnimation(nId);
729 
730     // Prepare the blending functors that translate [0,1] animation
731     // times into alpha values of buttons and button bar.
732     const ::boost::function<double(double)> aButtonBlendFunctor (
733         ::boost::bind(
734             controller::AnimationFunction::Blend,
735             nCurrentButtonAlpha,
736             nTargetAlpha,
737             ::boost::bind(controller::AnimationFunction::Linear, _1)));
738     const ::boost::function<double(double)> aButtonBarBlendFunctor (
739         ::boost::bind(
740             controller::AnimationFunction::Blend,
741             nCurrentButtonBarAlpha,
742             nTargetAlpha,
743             ::boost::bind(controller::AnimationFunction::Linear, _1)));
744 
745     // Delay the fade in a little bit when the buttons are not visible at
746     // all so that we do not leave a trail of half-visible buttons when the
747     // mouse is moved across the screen.  No delay on fade out or when the
748     // buttons are already showing.  Fade out is faster than fade in.
749     const sal_Int32 nDelay (nCurrentButtonBarAlpha>0 && nCurrentButtonBarAlpha<1
750         ? 0
751         : (mrSlideSorter.GetTheme()->GetIntegerValue(bFadeIn
752             ?  Theme::Integer_ButtonFadeInDelay
753             :  Theme::Integer_ButtonFadeOutDelay)));
754     const sal_Int32 nDuration (mrSlideSorter.GetTheme()->GetIntegerValue(bFadeIn
755             ?  Theme::Integer_ButtonFadeInDuration
756             :  Theme::Integer_ButtonFadeOutDuration));
757     pDescriptor->GetVisualState().SetButtonAlphaAnimationId(
758         mrSlideSorter.GetController().GetAnimator()->AddAnimation(
759             ::boost::bind(
760                 controller::AnimationFunction::ApplyButtonAlphaChange,
761                 pDescriptor,
762                 ::boost::ref(mrSlideSorter.GetView()),
763                 ::boost::bind(aButtonBlendFunctor, _1),
764                 ::boost::bind(aButtonBarBlendFunctor, _1)),
765             nDelay,
766             nDuration,
767             ::boost::bind(
768                 &model::VisualState::SetButtonAlphaAnimationId,
769                 ::boost::ref(pDescriptor->GetVisualState()),
770                 controller::Animator::NotAnAnimationId)
771             ));
772 }
773 
774 
775 
776 
777 void ButtonBar::AcquireLock (void)
778 {
779     if (mnLockCount == 0 && mpDescriptor)
780         RequestFadeOut(mpDescriptor, true);
781 
782     ++mnLockCount;
783 }
784 
785 
786 
787 
788 void ButtonBar::ReleaseLock (void)
789 {
790     --mnLockCount;
791 
792     if (mnLockCount == 0 && mpDescriptor)
793         RequestFadeIn(mpDescriptor, true);
794 }
795 
796 
797 
798 
799 //===== BackgroundTheme =====================================================
800 
801 ButtonBar::BackgroundTheme::BackgroundTheme (
802     const ::boost::shared_ptr<Theme>& rpTheme,
803     const ::std::vector<SharedButton>& rButtons)
804     : mpTheme(rpTheme)
805 {
806     UpdateMinimumIconSizes(rButtons);
807 }
808 
809 
810 
811 
812 void ButtonBar::BackgroundTheme::SetPreviewBoundingBox (const Rectangle& rPreviewBoundingBox)
813 {
814     maPreviewBoundingBox = rPreviewBoundingBox;
815     Layout();
816 }
817 
818 
819 
820 
821 void ButtonBar::BackgroundTheme::UpdateMinimumIconSizes (
822     const ::std::vector<SharedButton>& rButtons)
823 {
824     OSL_ASSERT(mpTheme);
825 
826     sal_Int32 nMaximumHeightLarge (0);
827     sal_Int32 nMaximumHeightMedium (0);
828     sal_Int32 nMaximumHeightSmall (0);
829     const sal_Int32 nGap (mpTheme->GetIntegerValue(Theme::Integer_ButtonGap));
830     const sal_Int32 nBorder (mpTheme->GetIntegerValue(Theme::Integer_ButtonBorder));
831     sal_Int32 nTotalWidthLarge ((rButtons.size()-1) * nGap + 2*nBorder);
832     sal_Int32 nTotalWidthMedium ((rButtons.size()-1) * nGap + 2*nBorder);
833     sal_Int32 nTotalWidthSmall ((rButtons.size()-1) * nGap + 2*nBorder);
834     for (sal_uInt32 nIndex=0; nIndex<rButtons.size(); ++nIndex)
835     {
836         // Update large size.
837         Size aSize = rButtons[nIndex]->GetSize(Button::IconSize_Large);
838         if (aSize.Height() > nMaximumHeightLarge)
839             nMaximumHeightLarge = aSize.Height();
840         nTotalWidthLarge += aSize.Width();
841 
842         // Update medium size.
843         aSize = rButtons[nIndex]->GetSize(Button::IconSize_Medium);
844         if (aSize.Height() > nMaximumHeightMedium)
845             nMaximumHeightMedium = aSize.Height();
846         nTotalWidthMedium += aSize.Width();
847 
848         // Update small size.
849         aSize = rButtons[nIndex]->GetSize(Button::IconSize_Small);
850         if (aSize.Height() > nMaximumHeightSmall)
851             nMaximumHeightSmall = aSize.Height();
852         nTotalWidthSmall += aSize.Width();
853     }
854     maMinimumLargeButtonAreaSize = Size(nTotalWidthLarge, nMaximumHeightLarge+2*nBorder);
855     maMinimumMediumButtonAreaSize = Size(nTotalWidthMedium, nMaximumHeightMedium+2*nBorder);
856     maMinimumSmallButtonAreaSize = Size(nTotalWidthSmall, nMaximumHeightSmall+2*nBorder);
857 }
858 
859 
860 
861 
862 Button::IconSize ButtonBar::BackgroundTheme::GetIconSize (void) const
863 {
864     return meIconSize;
865 }
866 
867 
868 
869 
870 //===== RectangleBackgroundTheme ============================================
871 
872 RectangleBackgroundTheme::RectangleBackgroundTheme (
873     const ::boost::shared_ptr<Theme>& rpTheme,
874     const ::std::vector<SharedButton>& rButtons)
875     : BackgroundTheme(rpTheme, rButtons),
876       mnBarHeight(0)
877 {
878 }
879 
880 
881 
882 
883 BitmapEx RectangleBackgroundTheme::CreateBackground (
884     const OutputDevice& rTemplateDevice,
885     const bool bIsButtonDown) const
886 {
887     OSL_ASSERT(mpTheme);
888 
889     // Setup background color.
890     Color aTopFillColor (mpTheme->GetGradientColor(
891         Theme::Gradient_ButtonBackground,
892         Theme::Fill1));
893     Color aTopBorderColor (mpTheme->GetGradientColor(
894         Theme::Gradient_ButtonBackground,
895         Theme::Border1));
896     Color aBottomFillColor (mpTheme->GetGradientColor(
897         Theme::Gradient_ButtonBackground,
898         Theme::Fill2));
899     Color aBottomBorderColor (mpTheme->GetGradientColor(
900         Theme::Gradient_ButtonBackground,
901         Theme::Border2));
902     if (bIsButtonDown)
903     {
904         aTopFillColor.DecreaseLuminance(50);
905         aTopBorderColor.DecreaseLuminance(50);
906         aBottomFillColor.DecreaseLuminance(50);
907         aBottomBorderColor.DecreaseLuminance(50);
908     }
909 
910     const int nWidth (maPreviewBoundingBox.GetWidth()+2);
911     const int nHeight (mnBarHeight);
912     const int nCenter (nHeight / 2);
913 
914     VirtualDevice aDevice (rTemplateDevice, 0, 8);
915     aDevice.SetOutputSizePixel(Size(nWidth,nHeight));
916 
917     // Fill upper and lower half.
918     aDevice.SetLineColor();
919     aDevice.SetFillColor(aTopFillColor);
920     aDevice.DrawRect(Rectangle(0,0,nWidth-1,nCenter));
921     aDevice.SetFillColor(aBottomFillColor);
922     aDevice.DrawRect(Rectangle(0,nCenter,nWidth-1,nHeight-1));
923 
924     // Draw border.
925     aDevice.SetFillColor();
926     aDevice.SetLineColor(aTopBorderColor);
927     aDevice.DrawLine(Point(0,nCenter),Point(0,0));
928     aDevice.DrawLine(Point(0,0), Point(nWidth-1,0));
929     aDevice.DrawLine(Point(nWidth-1,0),Point(nWidth-1,nCenter));
930     aDevice.SetLineColor(aBottomBorderColor);
931     aDevice.DrawLine(Point(0,nCenter),Point(0,nHeight-1));
932     aDevice.DrawLine(Point(0,nHeight-1), Point(nWidth-1,nHeight-1));
933     aDevice.DrawLine(Point(nWidth-1,nHeight-1),Point(nWidth-1,nCenter));
934 
935     return aDevice.GetBitmapEx(Point(0,0), Size(nWidth,nHeight));
936 }
937 
938 
939 
940 
941 Point RectangleBackgroundTheme::GetBackgroundLocation (void)
942 {
943     return Point(
944         maPreviewBoundingBox.Left()-1,
945         maPreviewBoundingBox.Bottom() - mnBarHeight + 2);
946 }
947 
948 
949 
950 
951 Rectangle RectangleBackgroundTheme::GetButtonArea (void)
952 {
953     return Rectangle(
954         maPreviewBoundingBox.Left(),
955         maPreviewBoundingBox.Bottom() - mnBarHeight + 2,
956         maPreviewBoundingBox.Right(),
957         maPreviewBoundingBox.Bottom());
958 }
959 
960 
961 
962 
963 void RectangleBackgroundTheme::Layout (void)
964 {
965     if (maPreviewBoundingBox.GetWidth() < maMinimumLargeButtonAreaSize.Width())
966         if (maPreviewBoundingBox.GetWidth() < maMinimumMediumButtonAreaSize.Width())
967         {
968             meIconSize = Button::IconSize_Small;
969             mnBarHeight = maMinimumSmallButtonAreaSize.Height();
970         }
971         else
972         {
973             meIconSize = Button::IconSize_Medium;
974             mnBarHeight = maMinimumMediumButtonAreaSize.Height();
975         }
976     else
977     {
978         meIconSize = Button::IconSize_Large;
979         mnBarHeight = maMinimumLargeButtonAreaSize.Height();
980     }
981 }
982 
983 
984 
985 
986 //===== BitmapBackgroundTheme =================================================
987 
988 BitmapBackgroundTheme::BitmapBackgroundTheme (
989     const ::boost::shared_ptr<Theme>& rpTheme,
990     const ::std::vector<SharedButton>& rButtons)
991     : BackgroundTheme(rpTheme, rButtons),
992       maButtonArea(),
993       maBackgroundLocation()
994 {
995 }
996 
997 
998 
999 
1000 BitmapEx BitmapBackgroundTheme::CreateBackground (
1001     const OutputDevice& rTemplateDevice,
1002     const bool bIsButtonDown) const
1003 {
1004     (void)rTemplateDevice;
1005     (void)bIsButtonDown;
1006 
1007     OSL_ASSERT(mpTheme);
1008 
1009     // Get images.
1010     switch (meIconSize)
1011     {
1012         case Button::IconSize_Large:
1013         default:
1014             return mpTheme->GetIcon(Theme::Icon_ButtonBarLarge);
1015 
1016         case Button::IconSize_Medium:
1017             return mpTheme->GetIcon(Theme::Icon_ButtonBarMedium);
1018 
1019         case Button::IconSize_Small:
1020             return mpTheme->GetIcon(Theme::Icon_ButtonBarSmall);
1021     }
1022 }
1023 
1024 
1025 
1026 
1027 Point BitmapBackgroundTheme::GetBackgroundLocation (void)
1028 {
1029     return maBackgroundLocation;
1030 }
1031 
1032 
1033 
1034 
1035 Rectangle BitmapBackgroundTheme::GetButtonArea (void)
1036 {
1037     return maButtonArea;
1038 }
1039 
1040 
1041 
1042 
1043 void BitmapBackgroundTheme::Layout (void)
1044 {
1045     Size aImageSize (mpTheme->GetIcon(Theme::Icon_ButtonBarLarge).GetSizePixel());
1046     if (aImageSize.Width() >= maPreviewBoundingBox.GetWidth())
1047     {
1048         aImageSize = mpTheme->GetIcon(Theme::Icon_ButtonBarMedium).GetSizePixel();
1049         if (aImageSize.Width() >= maPreviewBoundingBox.GetWidth())
1050         {
1051             meIconSize = Button::IconSize_Small;
1052             aImageSize = mpTheme->GetIcon(Theme::Icon_ButtonBarSmall).GetSizePixel();
1053         }
1054         else
1055             meIconSize = Button::IconSize_Medium;
1056     }
1057     else
1058     {
1059         meIconSize = Button::IconSize_Large;
1060     }
1061 
1062     maBackgroundLocation = Point(
1063         maPreviewBoundingBox.Left()
1064             + (maPreviewBoundingBox.GetWidth()-aImageSize.Width())/2,
1065         maPreviewBoundingBox.Bottom() - aImageSize.Height());
1066     maButtonArea = Rectangle(maBackgroundLocation, aImageSize);
1067 }
1068 
1069 
1070 
1071 
1072 //===== Button ================================================================
1073 
1074 Button::Button (
1075     SlideSorter& rSlideSorter,
1076     const ::rtl::OUString& rsHelpText)
1077     : mrSlideSorter(rSlideSorter),
1078       meState(State_Normal),
1079       maBoundingBox(),
1080       msHelpText(rsHelpText),
1081       mbIsActive(false),
1082       meIconSize(IconSize_Large)
1083 {
1084 }
1085 
1086 
1087 
1088 
1089 Button::~Button (void)
1090 {
1091 }
1092 
1093 
1094 
1095 
1096 bool Button::SetState (const State eState)
1097 {
1098     if (meState != eState)
1099     {
1100         meState = eState;
1101         return true;
1102     }
1103     else
1104         return false;
1105 }
1106 
1107 
1108 
1109 
1110 Button::State Button::GetState (void) const
1111 {
1112     return meState;
1113 }
1114 
1115 
1116 
1117 
1118 Rectangle Button::GetBoundingBox (void) const
1119 {
1120     if (mbIsActive)
1121         return maBoundingBox;
1122     else
1123         return Rectangle();
1124 }
1125 
1126 
1127 
1128 
1129 ::rtl::OUString Button::GetHelpText (void) const
1130 {
1131     if (mbIsActive)
1132         return msHelpText;
1133     else
1134         return ::rtl::OUString();
1135 }
1136 
1137 
1138 
1139 
1140 bool Button::IsDown (void) const
1141 {
1142     return mbIsActive && meState==State_Down;
1143 }
1144 
1145 
1146 
1147 
1148 void Button::SetActiveState (const bool bIsActive)
1149 {
1150     mbIsActive = bIsActive;
1151 }
1152 
1153 
1154 
1155 
1156 bool Button::IsActive (void) const
1157 {
1158     return mbIsActive;
1159 }
1160 
1161 
1162 
1163 
1164 void Button::SetIconSize (const IconSize eIconSize)
1165 {
1166     meIconSize = eIconSize;
1167 }
1168 
1169 
1170 
1171 
1172 Button::IconSize Button::GetIconSize (void) const
1173 {
1174     return meIconSize;
1175 }
1176 
1177 
1178 
1179 
1180 bool Button::IsEnabled (void) const
1181 {
1182     return true;
1183 }
1184 
1185 
1186 
1187 
1188 //===== TextButton ============================================================
1189 
1190 TextButton::TextButton (
1191     SlideSorter& rSlideSorter,
1192     const ::rtl::OUString& rsText,
1193     const ::rtl::OUString& rsHelpText)
1194     : Button(rSlideSorter, rsHelpText),
1195       msText(rsText)
1196 {
1197 }
1198 
1199 
1200 
1201 
1202 void TextButton::Place (const Rectangle aButtonBarBox)
1203 {
1204     maBoundingBox = aButtonBarBox;
1205     SetActiveState(true);
1206 }
1207 
1208 
1209 
1210 
1211 void TextButton::Paint (
1212     OutputDevice& rDevice,
1213     const Point aOffset,
1214     const double nAlpha,
1215     const ::boost::shared_ptr<Theme>& rpTheme) const
1216 {
1217     (void)nAlpha;
1218 
1219     if (mbIsActive)
1220     {
1221         // Paint text over the button background.
1222         if (meState == State_Normal)
1223             rDevice.SetTextColor(rpTheme->GetColor(Theme::Color_ButtonText));
1224         else
1225             rDevice.SetTextColor(rpTheme->GetColor(Theme::Color_ButtonTextHover));
1226         Rectangle aBox (maBoundingBox);
1227         aBox += aOffset;
1228         rDevice.DrawText(aBox, msText, TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER);
1229     }
1230 }
1231 
1232 
1233 
1234 
1235 Size TextButton::GetSize (void) const
1236 {
1237     return Size();
1238 }
1239 
1240 
1241 
1242 
1243 Size TextButton::GetSize (const Button::IconSize) const
1244 {
1245     return Size();
1246 }
1247 
1248 
1249 
1250 
1251 //===== ImageButon ============================================================
1252 
1253 ImageButton::ImageButton (
1254     SlideSorter& rSlideSorter,
1255     const BitmapEx& rLargeIcon,
1256     const BitmapEx& rLargeHoverIcon,
1257     const BitmapEx& rMediumIcon,
1258     const BitmapEx& rMediumHoverIcon,
1259     const BitmapEx& rSmallIcon,
1260     const BitmapEx& rSmallHoverIcon,
1261     const ::rtl::OUString& rsHelpText)
1262     : Button(rSlideSorter, rsHelpText),
1263       maLargeIcon(rLargeIcon),
1264       maLargeHoverIcon(rLargeHoverIcon.IsEmpty() ? rLargeIcon : rLargeHoverIcon),
1265       maMediumIcon(rMediumIcon),
1266       maMediumHoverIcon(rMediumHoverIcon.IsEmpty() ? rMediumIcon : rMediumHoverIcon),
1267       maSmallIcon(rSmallIcon),
1268       maSmallHoverIcon(rSmallHoverIcon.IsEmpty() ? rSmallIcon : rSmallHoverIcon)
1269 {
1270 }
1271 
1272 
1273 
1274 
1275 void ImageButton::Place (const Rectangle aButtonBarBox)
1276 {
1277     const sal_Int32 nWidth (GetSize().Width());
1278     maBoundingBox = Rectangle(
1279         aButtonBarBox.Right() - nWidth,
1280         aButtonBarBox.Top(),
1281         aButtonBarBox.Right(),
1282         aButtonBarBox.Bottom());
1283     SetActiveState(aButtonBarBox.IsInside(maBoundingBox));
1284 }
1285 
1286 
1287 
1288 
1289 void ImageButton::Paint (
1290     OutputDevice& rDevice,
1291     const Point aOffset,
1292     const double nAlpha,
1293     const ::boost::shared_ptr<Theme>& rpTheme) const
1294 {
1295     (void)rpTheme;
1296 
1297     if ( ! mbIsActive)
1298         return;
1299 
1300     const sal_uInt16 nSavedAntialiasingMode (rDevice.GetAntialiasing());
1301     rDevice.SetAntialiasing(nSavedAntialiasingMode | ANTIALIASING_ENABLE_B2DDRAW);
1302 
1303     rDevice.SetLineColor();
1304 
1305     // Choose icon.
1306     BitmapEx aIcon;
1307     switch (meIconSize)
1308     {
1309         case IconSize_Large:
1310         default:
1311             if (meState == State_Normal)
1312                 aIcon = maLargeIcon;
1313             else
1314                 aIcon = maLargeHoverIcon;
1315             break;
1316 
1317         case IconSize_Medium:
1318             if (meState == State_Normal)
1319                 aIcon = maMediumIcon;
1320             else
1321                 aIcon = maMediumHoverIcon;
1322             break;
1323 
1324         case IconSize_Small:
1325             if (meState == State_Normal)
1326                 aIcon = maSmallIcon;
1327             else
1328                 aIcon = maSmallHoverIcon;
1329             break;
1330     }
1331 
1332     // Paint icon.
1333     if ( ! aIcon.IsEmpty())
1334     {
1335         AlphaMask aMask (aIcon.GetSizePixel());
1336         AdaptTransparency(aMask, aIcon.GetAlpha(), nAlpha);
1337         rDevice.DrawBitmapEx(
1338             Point(
1339                 maBoundingBox.Left()
1340                     + aOffset.X()
1341                     + (maBoundingBox.GetWidth()-aIcon.GetSizePixel().Width())/2,
1342                 maBoundingBox.Top()
1343                     + aOffset.Y()
1344                     + (maBoundingBox.GetHeight()-aIcon.GetSizePixel().Height())/2),
1345             BitmapEx(aIcon.GetBitmap(), aMask));
1346     }
1347 
1348     rDevice.SetAntialiasing(nSavedAntialiasingMode);
1349 }
1350 
1351 
1352 
1353 
1354 Size ImageButton::GetSize (void) const
1355 {
1356     return GetSize(meIconSize);
1357 }
1358 
1359 
1360 
1361 
1362 Size ImageButton::GetSize (const Button::IconSize eIconSize) const
1363 {
1364     switch (eIconSize)
1365     {
1366         case IconSize_Large:
1367         default:
1368             return maLargeIcon.GetSizePixel();
1369 
1370         case IconSize_Medium:
1371             return maMediumIcon.GetSizePixel();
1372 
1373         case IconSize_Small:
1374             return maSmallIcon.GetSizePixel();
1375     }
1376 }
1377 
1378 
1379 
1380 
1381 //===== UnhideButton ==========================================================
1382 
1383 UnhideButton::UnhideButton (SlideSorter& rSlideSorter)
1384     : ImageButton(
1385         rSlideSorter,
1386         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BLarge),
1387         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BLargeHover),
1388         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BMedium),
1389         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BMediumHover),
1390         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BSmall),
1391         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2BSmallHover),
1392         rSlideSorter.GetTheme()->GetString(Theme::String_Command2B))
1393 {
1394 }
1395 
1396 
1397 
1398 
1399 void UnhideButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
1400 {
1401     if ( ! rpDescriptor)
1402         return;
1403     mrSlideSorter.GetController().GetSlotManager()->ChangeSlideExclusionState(
1404         (rpDescriptor->HasState(model::PageDescriptor::ST_Selected)
1405             ? model::SharedPageDescriptor()
1406             : rpDescriptor),
1407         false);
1408 }
1409 
1410 
1411 
1412 
1413 //===== StartSlideShowButton ==================================================
1414 
1415 StartShowButton::StartShowButton (SlideSorter& rSlideSorter)
1416     : ImageButton(
1417         rSlideSorter,
1418         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Large),
1419         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1LargeHover),
1420         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Medium),
1421         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1MediumHover),
1422         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1Small),
1423         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command1SmallHover),
1424         rSlideSorter.GetTheme()->GetString(Theme::String_Command1))
1425 {
1426 }
1427 
1428 
1429 
1430 
1431 bool StartShowButton::IsEnabled (void) const
1432 {
1433     ViewShell* pViewShell = mrSlideSorter.GetViewShell();
1434     if (pViewShell == NULL)
1435         return false;
1436     SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
1437     if (pDispatcher == NULL)
1438         return false;
1439 
1440     const SfxPoolItem* pState = NULL;
1441 	const SfxItemState eState (pDispatcher->QueryState(SID_PRESENTATION, pState));
1442     return (eState & SFX_ITEM_DISABLED) == 0;
1443 }
1444 
1445 
1446 
1447 
1448 void StartShowButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
1449 {
1450     // Hide the tool tip early, while the slide show still intializes.
1451     mrSlideSorter.GetView().GetToolTip().SetPage(model::SharedPageDescriptor());
1452 
1453     Reference< XPresentation2 > xPresentation(
1454         mrSlideSorter.GetModel().GetDocument()->getPresentation());
1455     if (xPresentation.is())
1456     {
1457         Sequence<PropertyValue> aProperties (1);
1458         aProperties[0].Name = ::rtl::OUString::createFromAscii("FirstPage");
1459         const ::rtl::OUString sName (rpDescriptor->GetPage()->GetName());
1460         aProperties[0].Value = Any(sName);
1461 
1462         // We have to temporarily change the options value
1463         // StartWithActualPage to make the slide show use the
1464         // specified first page.
1465         const DocumentType eType (mrSlideSorter.GetModel().GetDocument()->GetDocumentType());
1466         const sal_Bool bSavedState (SD_MOD()->GetSdOptions(eType)->IsStartWithActualPage());
1467         SD_MOD()->GetSdOptions(eType)->SetStartWithActualPage(sal_False);
1468 
1469         xPresentation->startWithArguments(aProperties);
1470 
1471         // Restore previous StartWithActualPage value.
1472         SD_MOD()->GetSdOptions(eType)->SetStartWithActualPage(bSavedState);
1473     }
1474 }
1475 
1476 
1477 
1478 
1479 //===== HideButton ============================================================
1480 
1481 HideButton::HideButton (SlideSorter& rSlideSorter)
1482     : ImageButton(
1483         rSlideSorter,
1484         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Large),
1485         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2LargeHover),
1486         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Medium),
1487         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2MediumHover),
1488         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2Small),
1489         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command2SmallHover),
1490         rSlideSorter.GetTheme()->GetString(Theme::String_Command2))
1491 {
1492 }
1493 
1494 
1495 
1496 
1497 void HideButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
1498 {
1499     if ( ! rpDescriptor)
1500         return;
1501     mrSlideSorter.GetController().GetSlotManager()->ChangeSlideExclusionState(
1502         (rpDescriptor->HasState(model::PageDescriptor::ST_Selected)
1503             ? model::SharedPageDescriptor()
1504             : rpDescriptor),
1505         true);
1506 }
1507 
1508 
1509 
1510 
1511 //===== DuplicateButton =======================================================
1512 
1513 DuplicateButton::DuplicateButton (SlideSorter& rSlideSorter)
1514     : ImageButton(
1515         rSlideSorter,
1516         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Large),
1517         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3LargeHover),
1518         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Medium),
1519         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3MediumHover),
1520         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3Small),
1521         rSlideSorter.GetTheme()->GetIcon(Theme::Icon_Command3SmallHover),
1522         rSlideSorter.GetTheme()->GetString(Theme::String_Command3))
1523 {
1524 }
1525 
1526 
1527 
1528 
1529 bool DuplicateButton::IsEnabled (void) const
1530 {
1531     ViewShell* pViewShell = mrSlideSorter.GetViewShell();
1532     if (pViewShell == NULL)
1533         return false;
1534     SfxDispatcher* pDispatcher = pViewShell->GetDispatcher();
1535     if (pDispatcher == NULL)
1536         return false;
1537 
1538     const SfxPoolItem* pState = NULL;
1539 	const SfxItemState eState (pDispatcher->QueryState(
1540         SID_DUPLICATE_PAGE,
1541         pState));
1542     return (eState & SFX_ITEM_DISABLED) == 0;
1543 }
1544 
1545 
1546 
1547 
1548 void DuplicateButton::ProcessClick (const model::SharedPageDescriptor& rpDescriptor)
1549 {
1550     if ( ! rpDescriptor)
1551         return;
1552 
1553     mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor(),false);
1554 
1555     // When the page under the button is not selected then set the
1556     // selection to just this page.
1557     if ( ! rpDescriptor->HasState(model::PageDescriptor::ST_Selected))
1558     {
1559         mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
1560         mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
1561     }
1562     // Duplicate the selected pages.  Insert the new pages right
1563     // after the current selection and select them
1564     if (mrSlideSorter.GetViewShell() != NULL
1565         && mrSlideSorter.GetViewShell()->GetDispatcher() != NULL)
1566     {
1567         mrSlideSorter.GetViewShell()->GetDispatcher()->Execute(
1568             SID_DUPLICATE_PAGE,
1569             SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD);
1570     }
1571 }
1572 
1573 
1574 
1575 } } } // end of namespace ::sd::slidesorter::view
1576