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