vfs: check userland buffers before reading them.
[haiku.git] / src / apps / networkstatus / RadioView.cpp
blobd3aa6af4da015cfdccc31f4e7ab524390b7d7db3
1 /*
2 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "RadioView.h"
9 #include <stdio.h>
11 #include <MessageRunner.h>
14 const uint32 kMsgPulse = 'puls';
16 const bigtime_t kMinPulseInterval = 100000;
17 const bigtime_t kMaxPulseInterval = 300000;
18 const float kMinStep = 3.f;
21 RadioView::RadioView(BRect frame, const char* name, int32 resizingMode)
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(DefaultMax())
33 RadioView::~RadioView()
38 void
39 RadioView::SetPercent(int32 percent)
41 if (percent < 0)
42 percent = 0;
43 if (percent > 100)
44 percent = 100;
46 if (percent == fPercent)
47 return;
49 fPercent = percent;
50 Invalidate();
54 void
55 RadioView::SetMax(int32 max)
57 if (max < 0)
58 max = 0;
59 if (max > 100)
60 max = 100;
61 if (max == fMax)
62 return;
64 fMax = max;
65 Invalidate();
69 void
70 RadioView::StartPulsing()
72 fPhase = 0;
73 _RestartPulsing();
77 void
78 RadioView::StopPulsing()
80 if (!IsPulsing())
81 return;
83 delete fPulse;
84 fPulse = NULL;
85 fPhase = 0;
86 Invalidate();
90 /*static*/ void
91 RadioView::Draw(BView* view, BRect rect, int32 percent, int32 maxCount)
93 view->PushState();
95 BPoint center;
96 int32 count;
97 float step;
98 _Compute(rect, center, count, maxCount, step);
100 for (int32 i = 0; i < count; i++) {
101 _SetColor(view, percent, 0, i, count);
102 _DrawBow(view, i, center, count, step);
104 view->PopState();
108 /*static*/ int32
109 RadioView::DefaultMax()
111 return 7;
115 void
116 RadioView::AttachedToWindow()
118 if (Parent() != NULL)
119 SetViewColor(Parent()->ViewColor());
120 else
121 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
125 void
126 RadioView::DetachedFromWindow()
128 StopPulsing();
132 void
133 RadioView::MessageReceived(BMessage* message)
135 switch (message->what) {
136 case kMsgPulse:
137 fPhase++;
138 Invalidate();
139 break;
141 default:
142 BView::MessageReceived(message);
143 break;
148 void
149 RadioView::Draw(BRect updateRect)
151 SetLowColor(ViewColor());
153 BPoint center;
154 int32 count;
155 float step;
156 _Compute(Bounds(), center, count, fMax, step);
158 for (int32 i = 0; i < count; i++) {
159 _SetColor(this, fPercent, fPhase, i, count);
160 if (step == kMinStep && _IsDisabled(fPercent, i, count))
161 continue;
163 _DrawBow(this, i, center, count, step);
168 void
169 RadioView::FrameResized(float /*width*/, float /*height*/)
171 if (IsPulsing())
172 _RestartPulsing();
176 void
177 RadioView::_RestartPulsing()
179 delete fPulse;
181 // The pulse speed depends on the size of the view
182 BPoint center;
183 int32 count;
184 float step;
185 _Compute(Bounds(), center, count, fMax, step);
187 BMessage message(kMsgPulse);
188 fPulse = new BMessageRunner(this, &message, (bigtime_t)(kMinPulseInterval
189 + (kMaxPulseInterval - kMinPulseInterval) / step), -1);
193 /*static*/ void
194 RadioView::_Compute(const BRect& bounds, BPoint& center, int32& count,
195 int32 max, float& step)
197 center.Set(roundf(bounds.Width() / 2), bounds.bottom);
198 float size = min_c(center.x * 3 / 2, center.y);
199 step = floorf(size / max);
200 if (step < kMinStep) {
201 count = (int32)(size / kMinStep);
202 step = kMinStep;
203 } else
204 count = max;
206 center.x += bounds.left;
210 /*static*/ void
211 RadioView::_DrawBow(BView* view, int32 index, const BPoint& center,
212 int32 count, float step)
214 float radius = step * index + 1;
216 if (step < 4)
217 view->SetPenSize(step / 2);
218 else
219 view->SetPenSize(step * 2 / 3);
221 view->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN);
222 view->StrokeArc(center, radius, radius, 50, 80);
226 /*static*/ void
227 RadioView::_SetColor(BView* view, int32 percent, int32 phase, int32 index,
228 int32 count)
230 if (_IsDisabled(percent, index, count)) {
231 // disabled
232 view->SetHighColor(tint_color(view->LowColor(), B_DARKEN_1_TINT));
233 } else if (phase == 0 || phase % count != index) {
234 // enabled
235 view->SetHighColor(tint_color(view->LowColor(), B_DARKEN_3_TINT));
236 } else {
237 // pulsing
238 view->SetHighColor(tint_color(view->LowColor(), B_DARKEN_2_TINT));
243 /*static*/ bool
244 RadioView::_IsDisabled(int32 percent, int32 index, int32 count)
246 return percent < 100 * index / count;