1/*
2 * Copyright 2010, Stephan A��mus <superstippi@gmx.de>.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "PlayPauseButton.h"
8
9#include <GradientLinear.h>
10#include <LayoutUtils.h>
11#include <Shape.h>
12
13
14static const rgb_color kGreen = (rgb_color){ 116, 224, 0, 255 };
15
16
17// constructor
18PlayPauseButton::PlayPauseButton(const char* name,
19		BShape* playSymbolShape, BShape* pauseSymbolShape, BMessage* message,
20		uint32 borders)
21	:
22	SymbolButton(name, NULL, message, borders),
23	fPlaySymbol(playSymbolShape),
24	fPauseSymbol(pauseSymbolShape),
25	fPlaybackState(kStopped)
26{
27}
28
29
30PlayPauseButton::~PlayPauseButton()
31{
32	delete fPlaySymbol;
33	delete fPauseSymbol;
34}
35
36
37void
38PlayPauseButton::Draw(BRect updateRect)
39{
40	SymbolButton::Draw(updateRect);
41
42	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
43	rgb_color active = (rgb_color){ 116, 224, 0, 255 };
44
45	if (IsEnabled()) {
46		if (Value() == B_CONTROL_ON)
47			base = tint_color(base, (B_DARKEN_4_TINT + B_DARKEN_MAX_TINT) / 2);
48		else
49			base = tint_color(base, B_DARKEN_4_TINT);
50	} else {
51		if (Value() == B_CONTROL_ON)
52			base = tint_color(base, B_DARKEN_2_TINT);
53		else
54			base = tint_color(base, B_DARKEN_1_TINT);
55	}
56	BRect bounds(Bounds());
57	BRect pauseBounds = fPauseSymbol->Bounds();
58	BRect playBounds = fPlaySymbol->Bounds();
59
60	BPoint offset;
61	float spacing = pauseBounds.Height() / 4;
62	offset.x = (bounds.left + bounds.right) / 2;
63	offset.y = (bounds.top + bounds.bottom) / 2;
64	offset.x -= (pauseBounds.Width() + playBounds.Width() + spacing) / 2;
65	offset.y -= pauseBounds.Height() / 2;
66	offset.x = floorf(offset.x - playBounds.left + 0.5);
67	offset.y = ceilf(offset.y - pauseBounds.top);
68	if (Value() == B_CONTROL_ON) {
69		offset.x += 1;
70		offset.y += 1;
71	}
72
73	bool playActive = IsEnabled()
74		&& ((fPlaybackState == kPlaying && Value() == B_CONTROL_OFF)
75			|| (fPlaybackState == kPaused && Value() == B_CONTROL_ON));
76	bool pauseActive = IsEnabled()
77		&& ((fPlaybackState == kPaused && Value() == B_CONTROL_OFF)
78			|| (fPlaybackState == kPlaying && Value() == B_CONTROL_ON));
79
80	MovePenTo(offset);
81	BGradientLinear gradient;
82	if (playActive) {
83		gradient.AddColor(active, 0);
84		gradient.AddColor(tint_color(active, B_LIGHTEN_1_TINT), 255);
85	} else {
86		gradient.AddColor(tint_color(base, B_DARKEN_1_TINT), 0);
87		gradient.AddColor(base, 255);
88	}
89	gradient.SetStart(offset);
90	offset.y += playBounds.Height();
91	gradient.SetEnd(offset);
92	FillShape(fPlaySymbol, gradient);
93	if (playActive) {
94		SetHighColor(tint_color(active, B_DARKEN_3_TINT));
95		MovePenBy(0.5, 0.5);
96		StrokeShape(fPlaySymbol);
97	}
98
99	offset.y -= playBounds.Height();
100	offset.x += ceilf(playBounds.Width() + spacing);
101	MovePenTo(offset);
102	gradient.MakeEmpty();
103	if (pauseActive) {
104		gradient.AddColor(active, 0);
105		gradient.AddColor(tint_color(active, B_LIGHTEN_1_TINT), 255);
106	} else {
107		gradient.AddColor(tint_color(base, B_DARKEN_1_TINT), 0);
108		gradient.AddColor(base, 255);
109	}
110	gradient.SetStart(offset);
111	offset.y += playBounds.Height();
112	gradient.SetEnd(offset);
113	FillShape(fPauseSymbol, gradient);
114	if (pauseActive) {
115		SetHighColor(tint_color(active, B_DARKEN_3_TINT));
116		MovePenBy(0.5, 0.5);
117		StrokeShape(fPauseSymbol);
118	}
119}
120
121
122BSize
123PlayPauseButton::MinSize()
124{
125	if (fPauseSymbol == NULL || fPlaySymbol == NULL)
126		return BButton::MinSize();
127
128	BSize size;
129	size.width = ceilf(
130		(fPlaySymbol->Bounds().Width() + fPauseSymbol->Bounds().Width())
131			* 2.5f);
132	size.height = ceilf(fPauseSymbol->Bounds().Height() * 2.5f);
133	return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
134}
135
136
137BSize
138PlayPauseButton::MaxSize()
139{
140	BSize size(MinSize());
141	size.width = ceilf(size.width * 1.5f);
142	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
143}
144
145
146void
147PlayPauseButton::SetPlaying()
148{
149	_SetPlaybackState(kPlaying);
150}
151
152
153void
154PlayPauseButton::SetPaused()
155{
156	_SetPlaybackState(kPaused);
157}
158
159
160void
161PlayPauseButton::SetStopped()
162{
163	_SetPlaybackState(kStopped);
164}
165
166
167void
168PlayPauseButton::SetSymbols(BShape* playSymbolShape, BShape* pauseSymbolShape)
169{
170	BSize oldSize = MinSize();
171
172	delete fPlaySymbol;
173	fPlaySymbol = playSymbolShape;
174	delete fPauseSymbol;
175	fPauseSymbol = pauseSymbolShape;
176
177	if (MinSize() != oldSize)
178		InvalidateLayout();
179
180	Invalidate();
181}
182
183
184void
185PlayPauseButton::_SetPlaybackState(uint32 state)
186{
187	if (fPlaybackState == state)
188		return;
189	fPlaybackState = state;
190	Invalidate();
191}
192