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