xref: /haiku/src/apps/networkstatus/RadioView.cpp (revision 6751b48834620dd17d380ec679a80fcbddf323af)
1 /*
2  * Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "RadioView.h"
8 
9 #include <stdio.h>
10 
11 #include <MessageRunner.h>
12 
13 
14 const uint32 kMsgPulse = 'puls';
15 
16 const bigtime_t kMinPulseInterval = 100000;
17 const bigtime_t kMaxPulseInterval = 300000;
18 const float kMinStep = 3.f;
19 
20 
21 RadioView::RadioView(BRect frame, const char* name, int32 resizingMode)
22 	:
23 	BView(frame, name, resizingMode,
24 		B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW | B_FRAME_EVENTS),
25 	fPercent(0),
26 	fPulse(NULL),
27 	fPhase(0),
28 	fMax(7)
29 {
30 }
31 
32 
33 RadioView::~RadioView()
34 {
35 }
36 
37 
38 void
39 RadioView::SetPercent(int32 percent)
40 {
41 	if (percent < 0)
42 		percent = 0;
43 	if (percent > 100)
44 		percent = 100;
45 
46 	if (percent == fPercent)
47 		return;
48 
49 	fPercent = percent;
50 	Invalidate();
51 }
52 
53 
54 void
55 RadioView::SetMax(int32 max)
56 {
57 	if (max < 0)
58 		max = 0;
59 	if (max > 100)
60 		max = 100;
61 	if (max == fMax)
62 		return;
63 
64 	fMax = max;
65 	Invalidate();
66 }
67 
68 
69 void
70 RadioView::StartPulsing()
71 {
72 	fPhase = 0;
73 	_RestartPulsing();
74 }
75 
76 
77 void
78 RadioView::StopPulsing()
79 {
80 	if (!IsPulsing())
81 		return;
82 
83 	delete fPulse;
84 	fPulse = NULL;
85 	fPhase = 0;
86 	Invalidate();
87 }
88 
89 
90 void
91 RadioView::AttachedToWindow()
92 {
93 	if (Parent() != NULL)
94 		SetViewColor(Parent()->ViewColor());
95 	else
96 		SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
97 }
98 
99 
100 void
101 RadioView::DetachedFromWindow()
102 {
103 	StopPulsing();
104 }
105 
106 
107 void
108 RadioView::MessageReceived(BMessage* message)
109 {
110 	switch (message->what) {
111 		case kMsgPulse:
112 			fPhase++;
113 			Invalidate();
114 			break;
115 
116 		default:
117 			BView::MessageReceived(message);
118 			break;
119 	}
120 }
121 
122 
123 void
124 RadioView::Draw(BRect updateRect)
125 {
126 	SetLowColor(ViewColor());
127 
128 	BPoint center;
129 	int32 count;
130 	float step;
131 	_Compute(Bounds(), center, count, step);
132 
133 	for (int32 i = 0; i < count; i++) {
134 		_SetColor(i, count);
135 		if (step == kMinStep && _IsDisabled(i, count))
136 			continue;
137 
138 		_DrawBow(i, center, count, step);
139 	}
140 }
141 
142 
143 void
144 RadioView::FrameResized(float /*width*/, float /*height*/)
145 {
146 	if (IsPulsing())
147 		_RestartPulsing();
148 }
149 
150 
151 void
152 RadioView::_RestartPulsing()
153 {
154 	delete fPulse;
155 
156 	// The pulse speed depends on the size of the view
157 	BPoint center;
158 	int32 count;
159 	float step;
160 	_Compute(Bounds(), center, count, step);
161 
162 	BMessage message(kMsgPulse);
163 	fPulse = new BMessageRunner(this, &message, (bigtime_t)(kMinPulseInterval
164 			+ (kMaxPulseInterval - kMinPulseInterval) / step), -1);
165 }
166 
167 
168 void
169 RadioView::_Compute(const BRect& bounds, BPoint& center, int32& count,
170 	float& step) const
171 {
172 	center.Set(roundf(bounds.Width() / 2), bounds.bottom);
173 	float size = min_c(center.x * 3 / 2, center.y);
174 	step = floorf(size / fMax);
175 	if (step < kMinStep) {
176 		count = (int32)(size / kMinStep);
177 		step = kMinStep;
178 	} else
179 		count = fMax;
180 }
181 
182 
183 void
184 RadioView::_DrawBow(int32 index, const BPoint& center, int32 count, float step)
185 {
186 	float radius = step * index + 1;
187 
188 	if (step < 4)
189 		SetPenSize(step / 2);
190 	else
191 		SetPenSize(step * 2 / 3);
192 
193 	SetLineMode(B_ROUND_CAP, B_ROUND_JOIN);
194 	StrokeArc(center, radius, radius, 50, 80);
195 }
196 
197 
198 void
199 RadioView::_SetColor(int32 index, int32 count)
200 {
201 	if (_IsDisabled(index, count)) {
202 		// disabled
203 		SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
204 	} else if (fPhase == 0 || fPhase % count != index) {
205 		// enabled
206 		SetHighColor(tint_color(ViewColor(), B_DARKEN_3_TINT));
207 	} else {
208 		// pulsing
209 		SetHighColor(tint_color(ViewColor(), B_DARKEN_2_TINT));
210 	}
211 }
212 
213 
214 bool
215 RadioView::_IsDisabled(int32 index, int32 count) const
216 {
217 	return fPercent < 100 * index / count;
218 }
219