vfs: check userland buffers before reading them.
[haiku.git] / src / apps / mediaplayer / interface / VolumeSlider.cpp
blob2f913abcb35aecebebabf59b9531218026eb5601
1 /*
2 * Copyright 2010, Stephan Aßmus <superstippi@gmx.de>.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "VolumeSlider.h"
9 #include <GradientLinear.h>
11 #include <stdio.h>
12 #include <string.h>
15 #define KNOB_EMBEDDED 0
16 #define ROUND_KNOB 0
18 static const rgb_color kGreen = (rgb_color){ 116, 224, 0, 255 };
21 // constructor
22 VolumeSlider::VolumeSlider(const char* name, int32 minValue, int32 maxValue,
23 int32 snapValue, BMessage* message)
25 BSlider(name, NULL, NULL, minValue, maxValue, B_HORIZONTAL,
26 B_BLOCK_THUMB),
27 fMuted(false),
28 fSnapValue(snapValue),
29 fSnapping(false)
31 SetModificationMessage(message);
32 UseFillColor(true, &kGreen);
33 SetBarThickness(PreferredBarThickness());
37 VolumeSlider::~VolumeSlider()
42 void
43 VolumeSlider::MouseMoved(BPoint where, uint32 transit,
44 const BMessage* dragMessage)
46 if (!IsTracking()) {
47 BSlider::MouseMoved(where, transit, dragMessage);
48 return;
51 float cursorPosition = Orientation() == B_HORIZONTAL ? where.x : where.y;
53 if (fSnapping
54 && cursorPosition >= fMinSnap && cursorPosition <= fMaxSnap) {
55 // Don't move the slider, keep the current value for a few
56 // more pixels
57 return;
60 fSnapping = false;
62 int32 oldValue = Value();
63 int32 newValue = ValueForPoint(where);
64 if (oldValue == newValue) {
65 BSlider::MouseMoved(where, transit, dragMessage);
66 return;
69 // Check if there is a 0 dB transition at all
70 if ((oldValue < fSnapValue && newValue >= fSnapValue)
71 || (oldValue > fSnapValue && newValue <= fSnapValue)) {
72 SetValue(fSnapValue);
73 if (ModificationMessage() != NULL)
74 Messenger().SendMessage(ModificationMessage());
76 float snapPoint = _PointForValue(fSnapValue);
77 const float kMaxSnapOffset = 6;
78 if (oldValue > newValue) {
79 // movement from right to left
80 fMinSnap = snapPoint - kMaxSnapOffset;
81 fMaxSnap = snapPoint + 1;
82 } else {
83 // movement from left to right
84 fMinSnap = snapPoint - 1;
85 fMaxSnap = snapPoint + kMaxSnapOffset;
88 fSnapping = true;
89 return;
92 BSlider::MouseMoved(where, transit, dragMessage);
96 BRect
97 VolumeSlider::ThumbFrame() const
99 #if !ROUND_KNOB
100 BRect rect = BSlider::ThumbFrame();
101 rect.InsetBy(2, 2);
102 rect.bottom += 1;
103 #else
104 BRect rect(BarFrame());
105 # if KNOB_EMBEDDED
106 // Knob embedded in bar frame
107 rect.InsetBy(0, 1);
108 # else
109 // Knob extends outside the bar frame
110 rect.InsetBy(0, -1);
111 # endif
112 rect.InsetBy(rect.Height() / 2, 0);
113 rect.left = rect.left + rect.Width() * Position() - rect.Height() / 2;
114 rect.right = rect.left + rect.Height();
115 #endif
117 return rect;
121 void
122 VolumeSlider::DrawThumb()
124 #if ROUND_KNOB
125 // Draw a round thumb
126 BRect rect(ThumbFrame());
128 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
129 rgb_color frameLightColor;
130 rgb_color frameShadowColor;
131 rgb_color shadowColor = (rgb_color){ 0, 0, 0, 60 };
133 float topTint = 0.49;
134 float middleTint1 = 0.62;
135 float middleTint2 = 0.76;
136 float bottomTint = 0.90;
138 if (!IsEnabled()) {
139 topTint = (topTint + B_NO_TINT) / 2;
140 middleTint1 = (middleTint1 + B_NO_TINT) / 2;
141 middleTint2 = (middleTint2 + B_NO_TINT) / 2;
142 bottomTint = (bottomTint + B_NO_TINT) / 2;
143 shadowColor = (rgb_color){ 0, 0, 0, 30 };
146 // Draw shadow
147 #if !KNOB_EMBEDDED
148 rect.left++;
149 rect.top++;
150 SetDrawingMode(B_OP_ALPHA);
151 SetHighColor(shadowColor);
152 FillEllipse(rect);
154 // Draw thumb shape
155 rect.OffsetBy(-1, -1);
156 #endif
158 if (IsFocus()) {
159 // focused
160 frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR);
161 frameShadowColor = frameLightColor;
162 } else {
163 // figure out the tints to be used
164 float frameLightTint;
165 float frameShadowTint;
167 if (!IsEnabled()) {
168 frameLightTint = 1.30;
169 frameShadowTint = 1.35;
170 shadowColor.alpha = 30;
171 } else {
172 frameLightTint = 1.6;
173 frameShadowTint = 1.65;
176 frameLightColor = tint_color(base, frameLightTint);
177 frameShadowColor = tint_color(base, frameShadowTint);
180 BGradientLinear frameGradient;
181 frameGradient.AddColor(frameShadowColor, 0);
182 frameGradient.AddColor(frameLightColor, 255);
183 frameGradient.SetStart(rect.LeftTop());
184 frameGradient.SetEnd(rect.RightBottom());
186 FillEllipse(rect, frameGradient);
187 rect.InsetBy(1, 1);
189 // frameGradient.MakeEmpty();
190 // frameGradient.AddColor(borderColor, 0);
191 // frameGradient.AddColor(tint_color(borderColor, 0.8), 255);
192 // view->FillEllipse(rect, frameGradient);
193 // rect.InsetBy(1, 1);
195 BGradientLinear gradient;
196 if (!IsEnabled()) {
197 gradient.AddColor(tint_color(base, topTint), 0);
198 gradient.AddColor(tint_color(base, bottomTint), 255);
199 } else {
200 gradient.AddColor(tint_color(base, topTint), 0);
201 gradient.AddColor(tint_color(base, middleTint1), 132);
202 gradient.AddColor(tint_color(base, middleTint2), 136);
203 gradient.AddColor(tint_color(base, bottomTint), 255);
205 gradient.SetStart(rect.LeftTop());
206 gradient.SetEnd(rect.LeftBottom());
207 FillEllipse(rect, gradient);
208 #else
209 BSlider::DrawThumb();
210 #endif
214 BSize
215 VolumeSlider::MinSize()
217 BSize size = BSlider::MinSize();
218 size.width *= 2;
219 return size;
223 void
224 VolumeSlider::SetMuted(bool mute)
226 if (mute == fMuted)
227 return;
229 fMuted = mute;
231 rgb_color fillColor = kGreen;
232 if (fMuted) {
233 fillColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
234 B_DARKEN_2_TINT);
237 UseFillColor(true, &fillColor);
239 Invalidate();
243 float
244 VolumeSlider::PreferredBarThickness() const
246 #if KNOB_EMBEDDED
247 return 10.0f;
248 #else
249 return 8.0f;
250 #endif
254 float
255 VolumeSlider::_PointForValue(int32 value) const
257 int32 min, max;
258 GetLimits(&min, &max);
260 if (Orientation() == B_HORIZONTAL) {
261 return ceilf(1.0f * (value - min) / (max - min)
262 * (BarFrame().Width() - 2) + BarFrame().left + 1);
265 return ceilf(BarFrame().top - 1.0f * (value - min) / (max - min)
266 * BarFrame().Height());