btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / interface / ChannelSlider.cpp
blobef17bbb376b8e6908ee2d9c83d94e0e01f108931
1 /*
2 * Copyright 2005-2015, Haiku Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Stefano Ceccherini (stefano.ceccherini@gmail.com)
7 * Stephan Aßmus <superstippi@gmx.de>
8 */
10 #include <ChannelSlider.h>
12 #include <new>
14 #include <Bitmap.h>
15 #include <ControlLook.h>
16 #include <Debug.h>
17 #include <PropertyInfo.h>
18 #include <Screen.h>
19 #include <Window.h>
22 const static unsigned char
23 kVerticalKnobData[] = {
24 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
25 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
26 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
27 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
28 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
29 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
30 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
31 0xff, 0x00, 0x3f, 0x3f, 0xcb, 0xcb, 0xcb, 0xcb, 0x3f, 0x3f, 0x00, 0x12,
32 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
33 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
34 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
35 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
36 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
37 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12,
38 0xff, 0xff, 0xff, 0xff, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff
42 const static unsigned char
43 kHorizontalKnobData[] = {
44 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
46 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f,
47 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff,
48 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f,
49 0x3f, 0x00, 0x12, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb,
50 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 0xff, 0x00, 0x3f, 0x3f,
51 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff,
52 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f,
53 0x3f, 0x00, 0x12, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
54 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 0xff, 0x00, 0x3f, 0x3f,
55 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff,
56 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x0c, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x12, 0x12, 0x12,
58 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
59 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
63 static property_info
64 sPropertyInfo[] = {
65 { "Orientation",
66 { B_GET_PROPERTY, B_SET_PROPERTY, 0 },
67 { B_DIRECT_SPECIFIER, 0 }, NULL, 0, { B_INT32_TYPE }
70 { 0 }
74 const static float kPadding = 3.0;
77 BChannelSlider::BChannelSlider(BRect area, const char* name, const char* label,
78 BMessage* model, int32 channels, uint32 resizeMode, uint32 flags)
79 : BChannelControl(area, name, label, model, channels, resizeMode, flags)
81 _InitData();
85 BChannelSlider::BChannelSlider(BRect area, const char* name, const char* label,
86 BMessage* model, orientation orientation, int32 channels,
87 uint32 resizeMode, uint32 flags)
88 : BChannelControl(area, name, label, model, channels, resizeMode, flags)
91 _InitData();
92 SetOrientation(orientation);
96 BChannelSlider::BChannelSlider(const char* name, const char* label,
97 BMessage* model, orientation orientation, int32 channels,
98 uint32 flags)
99 : BChannelControl(name, label, model, channels, flags)
102 _InitData();
103 SetOrientation(orientation);
107 BChannelSlider::BChannelSlider(BMessage* archive)
108 : BChannelControl(archive)
110 _InitData();
112 orientation orient;
113 if (archive->FindInt32("_orient", (int32*)&orient) == B_OK)
114 SetOrientation(orient);
118 BChannelSlider::~BChannelSlider()
120 delete fBacking;
121 delete fLeftKnob;
122 delete fMidKnob;
123 delete fRightKnob;
124 delete[] fInitialValues;
128 BArchivable*
129 BChannelSlider::Instantiate(BMessage* archive)
131 if (validate_instantiation(archive, "BChannelSlider"))
132 return new (std::nothrow) BChannelSlider(archive);
134 return NULL;
138 status_t
139 BChannelSlider::Archive(BMessage* into, bool deep) const
141 status_t status = BChannelControl::Archive(into, deep);
142 if (status == B_OK)
143 status = into->AddInt32("_orient", (int32)Orientation());
145 return status;
149 void
150 BChannelSlider::AttachedToWindow()
152 AdoptParentColors();
153 BChannelControl::AttachedToWindow();
157 void
158 BChannelSlider::AllAttached()
160 BChannelControl::AllAttached();
164 void
165 BChannelSlider::DetachedFromWindow()
167 BChannelControl::DetachedFromWindow();
171 void
172 BChannelSlider::AllDetached()
174 BChannelControl::AllDetached();
178 void
179 BChannelSlider::MessageReceived(BMessage* message)
181 if (message->what == B_COLORS_UPDATED
182 && fBacking != NULL && fBackingView != NULL) {
183 rgb_color color;
184 if (message->FindColor(ui_color_name(B_PANEL_BACKGROUND_COLOR), &color)
185 == B_OK
186 && fBacking->Lock()) {
188 if (fBackingView->LockLooper()) {
189 fBackingView->SetLowColor(color);
190 fBackingView->UnlockLooper();
192 fBacking->Unlock();
196 switch (message->what) {
197 case B_SET_PROPERTY: {
198 case B_GET_PROPERTY:
199 BMessage reply(B_REPLY);
200 int32 index = 0;
201 BMessage specifier;
202 int32 what = 0;
203 const char* property = NULL;
204 bool handled = false;
205 status_t status = message->GetCurrentSpecifier(&index, &specifier,
206 &what, &property);
207 BPropertyInfo propInfo(sPropertyInfo);
208 if (status == B_OK
209 && propInfo.FindMatch(message, index, &specifier, what,
210 property) >= 0) {
211 handled = true;
212 if (message->what == B_SET_PROPERTY) {
213 orientation orient;
214 if (specifier.FindInt32("data", (int32*)&orient) == B_OK) {
215 SetOrientation(orient);
216 Invalidate(Bounds());
218 } else if (message->what == B_GET_PROPERTY)
219 reply.AddInt32("result", (int32)Orientation());
220 else
221 status = B_BAD_SCRIPT_SYNTAX;
224 if (handled) {
225 reply.AddInt32("error", status);
226 message->SendReply(&reply);
227 } else {
228 BChannelControl::MessageReceived(message);
230 } break;
232 default:
233 BChannelControl::MessageReceived(message);
234 break;
239 void
240 BChannelSlider::Draw(BRect updateRect)
242 _UpdateFontDimens();
243 _DrawThumbs();
245 SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
246 BRect bounds(Bounds());
247 if (Label()) {
248 float labelWidth = StringWidth(Label());
249 DrawString(Label(), BPoint((bounds.Width() - labelWidth) / 2.0,
250 fBaseLine));
253 if (MinLimitLabel()) {
254 if (fIsVertical) {
255 if (MinLimitLabel()) {
256 float x = (bounds.Width() - StringWidth(MinLimitLabel()))
257 / 2.0;
258 DrawString(MinLimitLabel(), BPoint(x, bounds.bottom
259 - kPadding));
261 } else {
262 if (MinLimitLabel()) {
263 DrawString(MinLimitLabel(), BPoint(kPadding, bounds.bottom
264 - kPadding));
269 if (MaxLimitLabel()) {
270 if (fIsVertical) {
271 if (MaxLimitLabel()) {
272 float x = (bounds.Width() - StringWidth(MaxLimitLabel()))
273 / 2.0;
274 DrawString(MaxLimitLabel(), BPoint(x, 2 * fLineFeed));
276 } else {
277 if (MaxLimitLabel()) {
278 DrawString(MaxLimitLabel(), BPoint(bounds.right - kPadding
279 - StringWidth(MaxLimitLabel()), bounds.bottom - kPadding));
286 void
287 BChannelSlider::MouseDown(BPoint where)
289 if (!IsEnabled())
290 BControl::MouseDown(where);
291 else {
292 fCurrentChannel = -1;
293 fMinPoint = 0;
295 // Search the channel on which the mouse was over
296 int32 numChannels = CountChannels();
297 for (int32 channel = 0; channel < numChannels; channel++) {
298 BRect frame = ThumbFrameFor(channel);
299 frame.OffsetBy(fClickDelta);
301 float range = ThumbRangeFor(channel);
302 if (fIsVertical) {
303 fMinPoint = frame.top + frame.Height() / 2;
304 frame.bottom += range;
305 } else {
306 // TODO: Fix this, the clickzone isn't perfect
307 frame.right += range;
308 fMinPoint = frame.Width();
311 // Click was on a slider.
312 if (frame.Contains(where)) {
313 fCurrentChannel = channel;
314 SetCurrentChannel(channel);
315 break;
319 // Click wasn't on a slider. Bail out.
320 if (fCurrentChannel == -1)
321 return;
323 uint32 buttons = 0;
324 BMessage* currentMessage = Window()->CurrentMessage();
325 if (currentMessage != NULL)
326 currentMessage->FindInt32("buttons", (int32*)&buttons);
328 fAllChannels = (buttons & B_SECONDARY_MOUSE_BUTTON) == 0;
330 if (fInitialValues != NULL && fAllChannels) {
331 delete[] fInitialValues;
332 fInitialValues = NULL;
335 if (fInitialValues == NULL)
336 fInitialValues = new (std::nothrow) int32[numChannels];
338 if (fInitialValues) {
339 if (fAllChannels) {
340 for (int32 i = 0; i < numChannels; i++)
341 fInitialValues[i] = ValueFor(i);
342 } else {
343 fInitialValues[fCurrentChannel] = ValueFor(fCurrentChannel);
347 if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
348 if (!IsTracking()) {
349 SetTracking(true);
350 _DrawThumbs();
351 Flush();
354 _MouseMovedCommon(where, B_ORIGIN);
355 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS |
356 B_NO_POINTER_HISTORY);
357 } else {
358 do {
359 snooze(30000);
360 GetMouse(&where, &buttons);
361 _MouseMovedCommon(where, B_ORIGIN);
362 } while (buttons != 0);
363 _FinishChange();
364 fCurrentChannel = -1;
365 fAllChannels = false;
371 void
372 BChannelSlider::MouseUp(BPoint where)
374 if (IsEnabled() && IsTracking()) {
375 _FinishChange();
376 SetTracking(false);
377 fAllChannels = false;
378 fCurrentChannel = -1;
379 fMinPoint = 0;
380 } else {
381 BChannelControl::MouseUp(where);
386 void
387 BChannelSlider::MouseMoved(BPoint where, uint32 code, const BMessage* message)
389 if (IsEnabled() && IsTracking())
390 _MouseMovedCommon(where, B_ORIGIN);
391 else
392 BChannelControl::MouseMoved(where, code, message);
396 void
397 BChannelSlider::WindowActivated(bool state)
399 BChannelControl::WindowActivated(state);
403 void
404 BChannelSlider::KeyDown(const char* bytes, int32 numBytes)
406 BControl::KeyDown(bytes, numBytes);
410 void
411 BChannelSlider::KeyUp(const char* bytes, int32 numBytes)
413 BView::KeyUp(bytes, numBytes);
417 void
418 BChannelSlider::FrameResized(float newWidth, float newHeight)
420 BChannelControl::FrameResized(newWidth, newHeight);
422 delete fBacking;
423 fBacking = NULL;
425 Invalidate(Bounds());
429 void
430 BChannelSlider::SetFont(const BFont* font, uint32 mask)
432 BChannelControl::SetFont(font, mask);
436 void
437 BChannelSlider::MakeFocus(bool focusState)
439 if (focusState && !IsFocus())
440 fFocusChannel = -1;
441 BChannelControl::MakeFocus(focusState);
445 void
446 BChannelSlider::GetPreferredSize(float* width, float* height)
448 _UpdateFontDimens();
450 if (fIsVertical) {
451 *width = 11.0 * CountChannels();
452 *width = max_c(*width, ceilf(StringWidth(Label())));
453 *width = max_c(*width, ceilf(StringWidth(MinLimitLabel())));
454 *width = max_c(*width, ceilf(StringWidth(MaxLimitLabel())));
455 *width += kPadding * 2.0;
457 *height = (fLineFeed * 3.0) + (kPadding * 2.0) + 147.0;
458 } else {
459 *width = max_c(64.0, ceilf(StringWidth(Label())));
460 *width = max_c(*width, ceilf(StringWidth(MinLimitLabel()))
461 + ceilf(StringWidth(MaxLimitLabel())) + 10.0);
462 *width += kPadding * 2.0;
464 *height = 11.0 * CountChannels() + (fLineFeed * 2.0)
465 + (kPadding * 2.0);
470 BHandler*
471 BChannelSlider::ResolveSpecifier(BMessage* message, int32 index,
472 BMessage* specifier, int32 form, const char* property)
474 BHandler* target = this;
475 BPropertyInfo propertyInfo(sPropertyInfo);
476 if (propertyInfo.FindMatch(message, index, specifier, form,
477 property) != B_OK) {
478 target = BChannelControl::ResolveSpecifier(message, index, specifier,
479 form, property);
481 return target;
485 status_t
486 BChannelSlider::GetSupportedSuites(BMessage* data)
488 if (data == NULL)
489 return B_BAD_VALUE;
491 status_t err = data->AddString("suites", "suite/vnd.Be-channel-slider");
493 BPropertyInfo propInfo(sPropertyInfo);
494 if (err == B_OK)
495 err = data->AddFlat("messages", &propInfo);
497 if (err == B_OK)
498 return BChannelControl::GetSupportedSuites(data);
499 return err;
503 void
504 BChannelSlider::SetEnabled(bool on)
506 BChannelControl::SetEnabled(on);
510 orientation
511 BChannelSlider::Orientation() const
513 return fIsVertical ? B_VERTICAL : B_HORIZONTAL;
517 void
518 BChannelSlider::SetOrientation(orientation orientation)
520 bool isVertical = orientation == B_VERTICAL;
521 if (isVertical != fIsVertical) {
522 fIsVertical = isVertical;
523 InvalidateLayout();
524 Invalidate(Bounds());
529 int32
530 BChannelSlider::MaxChannelCount() const
532 return 32;
536 bool
537 BChannelSlider::SupportsIndividualLimits() const
539 return false;
543 void
544 BChannelSlider::DrawChannel(BView* into, int32 channel, BRect area,
545 bool pressed)
547 float hCenter = area.Width() / 2;
548 float vCenter = area.Height() / 2;
550 BPoint leftTop;
551 BPoint bottomRight;
552 if (fIsVertical) {
553 leftTop.Set(area.left + hCenter, area.top + vCenter);
554 bottomRight.Set(leftTop.x, leftTop.y + ThumbRangeFor(channel));
555 } else {
556 leftTop.Set(area.left, area.top + vCenter);
557 bottomRight.Set(area.left + ThumbRangeFor(channel), leftTop.y);
560 DrawGroove(into, channel, leftTop, bottomRight);
562 BPoint thumbLocation = leftTop;
563 if (fIsVertical)
564 thumbLocation.y += ThumbDeltaFor(channel);
565 else
566 thumbLocation.x += ThumbDeltaFor(channel);
568 DrawThumb(into, channel, thumbLocation, pressed);
572 void
573 BChannelSlider::DrawGroove(BView* into, int32 channel, BPoint leftTop,
574 BPoint bottomRight)
576 ASSERT(into != NULL);
577 BRect rect(leftTop, bottomRight);
579 rect.InsetBy(-2.5, -2.5);
580 rect.left = floorf(rect.left);
581 rect.top = floorf(rect.top);
582 rect.right = floorf(rect.right);
583 rect.bottom = floorf(rect.bottom);
584 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
585 rgb_color barColor = be_control_look->SliderBarColor(base);
586 uint32 flags = 0;
587 be_control_look->DrawSliderBar(into, rect, rect, base,
588 barColor, flags, Orientation());
592 void
593 BChannelSlider::DrawThumb(BView* into, int32 channel, BPoint where,
594 bool pressed)
596 ASSERT(into != NULL);
598 const BBitmap* thumb = ThumbFor(channel, pressed);
599 if (thumb == NULL)
600 return;
602 BRect bitmapBounds(thumb->Bounds());
603 where.x -= bitmapBounds.right / 2.0;
604 where.y -= bitmapBounds.bottom / 2.0;
606 BRect rect(bitmapBounds.OffsetToCopy(where));
607 rect.InsetBy(1, 1);
608 rect.left = floorf(rect.left);
609 rect.top = floorf(rect.top);
610 rect.right = ceilf(rect.right + 0.5);
611 rect.bottom = ceilf(rect.bottom + 0.5);
612 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
613 uint32 flags = 0;
614 be_control_look->DrawSliderThumb(into, rect, rect, base,
615 flags, Orientation());
619 const BBitmap*
620 BChannelSlider::ThumbFor(int32 channel, bool pressed)
622 if (fLeftKnob != NULL)
623 return fLeftKnob;
625 if (fIsVertical) {
626 fLeftKnob = new (std::nothrow) BBitmap(BRect(0, 0, 11, 14),
627 B_CMAP8);
628 if (fLeftKnob != NULL) {
629 fLeftKnob->SetBits(kVerticalKnobData,
630 sizeof(kVerticalKnobData), 0, B_CMAP8);
632 } else {
633 fLeftKnob = new (std::nothrow) BBitmap(BRect(0, 0, 14, 11),
634 B_CMAP8);
635 if (fLeftKnob != NULL) {
636 fLeftKnob->SetBits(kHorizontalKnobData,
637 sizeof(kHorizontalKnobData), 0, B_CMAP8);
641 return fLeftKnob;
645 BRect
646 BChannelSlider::ThumbFrameFor(int32 channel)
648 _UpdateFontDimens();
650 BRect frame(0.0, 0.0, 0.0, 0.0);
651 const BBitmap* thumb = ThumbFor(channel, false);
652 if (thumb != NULL) {
653 frame = thumb->Bounds();
654 if (fIsVertical) {
655 frame.OffsetBy(channel * frame.Width(), (frame.Height() / 2.0) -
656 (kPadding * 2.0) - 1.0);
657 } else {
658 frame.OffsetBy(frame.Width() / 2.0, channel * frame.Height()
659 + 1.0);
662 return frame;
666 float
667 BChannelSlider::ThumbDeltaFor(int32 channel)
669 float delta = 0.0;
670 if (channel >= 0 && channel < MaxChannelCount()) {
671 float range = ThumbRangeFor(channel);
672 int32 limitRange = MaxLimitList()[channel] - MinLimitList()[channel];
673 delta = (ValueList()[channel] - MinLimitList()[channel]) * range
674 / limitRange;
676 if (fIsVertical)
677 delta = range - delta;
680 return delta;
684 float
685 BChannelSlider::ThumbRangeFor(int32 channel)
687 _UpdateFontDimens();
689 float range = 0;
690 BRect bounds = Bounds();
691 BRect frame = ThumbFrameFor(channel);
692 if (fIsVertical) {
693 // *height = (fLineFeed * 3.0) + (kPadding * 2.0) + 100.0;
694 range = bounds.Height() - frame.Height() - (fLineFeed * 3.0) -
695 (kPadding * 2.0);
696 } else {
697 // *width = some width + kPadding * 2.0;
698 range = bounds.Width() - frame.Width() - (kPadding * 2.0);
700 return range;
704 // #pragma mark -
707 void
708 BChannelSlider::_InitData()
710 _UpdateFontDimens();
712 fLeftKnob = NULL;
713 fMidKnob = NULL;
714 fRightKnob = NULL;
715 fBacking = NULL;
716 fBackingView = NULL;
717 fIsVertical = Bounds().Width() / Bounds().Height() < 1;
718 fClickDelta = B_ORIGIN;
720 fCurrentChannel = -1;
721 fAllChannels = false;
722 fInitialValues = NULL;
723 fMinPoint = 0;
724 fFocusChannel = -1;
728 void
729 BChannelSlider::_FinishChange(bool update)
731 if (fInitialValues != NULL) {
732 bool* inMask = NULL;
733 int32 numChannels = CountChannels();
734 if (!fAllChannels) {
735 inMask = new (std::nothrow) bool[CountChannels()];
736 if (inMask) {
737 for (int i = 0; i < numChannels; i++)
738 inMask[i] = false;
739 inMask[fCurrentChannel] = true;
742 InvokeChannel(update ? ModificationMessage() : NULL, 0, numChannels,
743 inMask);
745 delete[] inMask;
748 if (!update) {
749 SetTracking(false);
750 Invalidate();
755 void
756 BChannelSlider::_UpdateFontDimens()
758 font_height height;
759 GetFontHeight(&height);
760 fBaseLine = height.ascent + height.leading;
761 fLineFeed = fBaseLine + height.descent;
765 void
766 BChannelSlider::_DrawThumbs()
768 if (fBacking == NULL) {
769 // This is the idea: we build a bitmap by taking the coordinates
770 // of the first and last thumb frames (top/left and bottom/right)
771 BRect first = ThumbFrameFor(0);
772 BRect last = ThumbFrameFor(CountChannels() - 1);
773 BRect rect(first.LeftTop(), last.RightBottom());
775 if (fIsVertical)
776 rect.top -= ThumbRangeFor(0);
777 else
778 rect.right += ThumbRangeFor(0);
780 rect.OffsetTo(B_ORIGIN);
781 fBacking = new (std::nothrow) BBitmap(rect, B_RGB32, true);
782 if (fBacking) {
783 fBackingView = new (std::nothrow) BView(rect, "", 0, B_WILL_DRAW);
784 if (fBackingView) {
785 if (fBacking->Lock()) {
786 fBacking->AddChild(fBackingView);
787 fBackingView->SetFontSize(10.0);
788 fBackingView->SetLowColor(
789 ui_color(B_PANEL_BACKGROUND_COLOR));
790 fBackingView->SetViewColor(
791 ui_color(B_PANEL_BACKGROUND_COLOR));
792 fBacking->Unlock();
794 } else {
795 delete fBacking;
796 fBacking = NULL;
801 if (fBacking && fBackingView) {
802 BPoint drawHere;
804 BRect bounds(fBacking->Bounds());
805 drawHere.x = (Bounds().Width() - bounds.Width()) / 2.0;
806 drawHere.y = (Bounds().Height() - bounds.Height()) - kPadding
807 - fLineFeed;
809 if (fBacking->Lock()) {
810 // Clear the view's background
811 fBackingView->FillRect(fBackingView->Bounds(), B_SOLID_LOW);
813 BRect channelArea;
814 // draw the entire control
815 for (int32 channel = 0; channel < CountChannels(); channel++) {
816 channelArea = ThumbFrameFor(channel);
817 bool pressed = IsTracking()
818 && (channel == fCurrentChannel || fAllChannels);
819 DrawChannel(fBackingView, channel, channelArea, pressed);
822 // draw some kind of current value tool tip
823 if (fCurrentChannel != -1 && fMinPoint != 0) {
824 char valueString[32];
825 snprintf(valueString, 32, "%" B_PRId32,
826 ValueFor(fCurrentChannel));
827 SetToolTip(valueString);
828 ShowToolTip(ToolTip());
829 } else {
830 HideToolTip();
833 fBackingView->Sync();
834 fBacking->Unlock();
837 DrawBitmapAsync(fBacking, drawHere);
839 // fClickDelta is used in MouseMoved()
840 fClickDelta = drawHere;
845 void
846 BChannelSlider::_DrawGrooveFrame(BView* into, const BRect& area)
848 if (into) {
849 rgb_color oldColor = into->HighColor();
851 into->SetHighColor(255, 255, 255);
852 into->StrokeRect(area);
853 into->SetHighColor(tint_color(into->ViewColor(), B_DARKEN_1_TINT));
854 into->StrokeLine(area.LeftTop(), BPoint(area.right, area.top));
855 into->StrokeLine(area.LeftTop(), BPoint(area.left, area.bottom - 1));
856 into->SetHighColor(tint_color(into->ViewColor(), B_DARKEN_2_TINT));
857 into->StrokeLine(BPoint(area.left + 1, area.top + 1),
858 BPoint(area.right - 1, area.top + 1));
859 into->StrokeLine(BPoint(area.left + 1, area.top + 1),
860 BPoint(area.left + 1, area.bottom - 2));
862 into->SetHighColor(oldColor);
867 void
868 BChannelSlider::_MouseMovedCommon(BPoint point, BPoint point2)
870 float floatValue = 0;
871 int32 limitRange = MaxLimitList()[fCurrentChannel] -
872 MinLimitList()[fCurrentChannel];
873 float range = ThumbRangeFor(fCurrentChannel);
874 if (fIsVertical)
875 floatValue = range - (point.y - fMinPoint);
876 else
877 floatValue = range + (point.x - fMinPoint);
879 int32 value = (int32)(floatValue / range * limitRange) +
880 MinLimitList()[fCurrentChannel];
881 if (fAllChannels)
882 SetAllValue(value);
883 else
884 SetValueFor(fCurrentChannel, value);
886 if (ModificationMessage())
887 _FinishChange(true);
889 _DrawThumbs();
893 // #pragma mark - FBC padding
896 void BChannelSlider::_Reserved_BChannelSlider_0(void*, ...) {}
897 void BChannelSlider::_Reserved_BChannelSlider_1(void*, ...) {}
898 void BChannelSlider::_Reserved_BChannelSlider_2(void*, ...) {}
899 void BChannelSlider::_Reserved_BChannelSlider_3(void*, ...) {}
900 void BChannelSlider::_Reserved_BChannelSlider_4(void*, ...) {}
901 void BChannelSlider::_Reserved_BChannelSlider_5(void*, ...) {}
902 void BChannelSlider::_Reserved_BChannelSlider_6(void*, ...) {}
903 void BChannelSlider::_Reserved_BChannelSlider_7(void*, ...) {}