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 written 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 initializes.
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