1 /* 2 * Copyright 2005, Haiku Inc. All Rights Reserved. 3 * Author: Stefano Ceccherini (burton666@libero.it) 4 * Distributed under the terms of the MIT License. 5 */ 6 7 #include <Bitmap.h> 8 #include <ChannelSlider.h> 9 #include <Debug.h> 10 #include <PropertyInfo.h> 11 #include <Screen.h> 12 #include <Window.h> 13 14 15 const static unsigned char 16 kVerticalKnobData[] = { 17 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 18 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 19 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 20 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 21 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 22 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 23 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 24 0xff, 0x00, 0x3f, 0x3f, 0xcb, 0xcb, 0xcb, 0xcb, 0x3f, 0x3f, 0x00, 0x12, 25 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 26 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 27 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 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, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 31 0xff, 0xff, 0xff, 0xff, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff 32 }; 33 34 35 const static unsigned char 36 kHorizontalKnobData[] = { 37 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 38 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff, 39 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff, 40 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 41 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 42 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 43 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 44 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 45 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 46 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0xff, 47 0xff, 0xff, 0xff, 0xff, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xff, 48 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 49 }; 50 51 52 static property_info 53 sPropertyInfo[] = { 54 { "Orientation", 55 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 56 { B_DIRECT_SPECIFIER, 0 }, NULL, 0, { B_INT32_TYPE } 57 }, 58 59 { 0 } 60 }; 61 62 63 const static float kPadding = 10.0; 64 65 BChannelSlider::BChannelSlider(BRect area, const char *name, const char *label, 66 BMessage *model, int32 channels, uint32 resizeMode, uint32 flags) 67 : BChannelControl(area, name, label, model, channels, resizeMode, flags) 68 { 69 InitData(); 70 } 71 72 73 BChannelSlider::BChannelSlider(BRect area, const char *name, const char *label, 74 BMessage *model, orientation o, int32 channels, uint32 resizeMode, uint32 flags) 75 : BChannelControl(area, name, label, model, channels, resizeMode, flags) 76 77 { 78 InitData(); 79 SetOrientation(o); 80 } 81 82 83 BChannelSlider::BChannelSlider(BMessage *archive) 84 : BChannelControl(archive) 85 { 86 InitData(); 87 88 orientation orient; 89 if (archive->FindInt32("_orient", (int32 *)&orient) == B_OK) 90 SetOrientation(orient); 91 } 92 93 94 BChannelSlider::~BChannelSlider() 95 { 96 delete fLeftKnob; 97 delete fMidKnob; 98 delete fRightKnob; 99 delete[] fInitialValues; 100 } 101 102 103 BArchivable * 104 BChannelSlider::Instantiate(BMessage *archive) 105 { 106 if (validate_instantiation(archive, "BChannelSlider")) 107 return new BChannelSlider(archive); 108 else 109 return NULL; 110 } 111 112 113 status_t 114 BChannelSlider::Archive(BMessage *into, bool deep) const 115 { 116 status_t status = BChannelControl::Archive(into, deep); 117 if (status == B_OK) 118 status = into->AddInt32("_orient", (int32)Orientation()); 119 120 return status; 121 } 122 123 124 orientation 125 BChannelSlider::Orientation() const 126 { 127 return Vertical() ? B_VERTICAL : B_HORIZONTAL; 128 } 129 130 131 void 132 BChannelSlider::SetOrientation(orientation _orientation) 133 { 134 bool isVertical = _orientation == B_VERTICAL; 135 if (isVertical != Vertical()) { 136 fVertical = isVertical; 137 Invalidate(Bounds()); 138 } 139 } 140 141 142 int32 143 BChannelSlider::MaxChannelCount() const 144 { 145 return 32; 146 } 147 148 149 bool 150 BChannelSlider::SupportsIndividualLimits() const 151 { 152 return false; 153 } 154 155 156 void 157 BChannelSlider::AttachedToWindow() 158 { 159 BView *parent = Parent(); 160 if (parent != NULL) 161 SetViewColor(parent->ViewColor()); 162 163 inherited::AttachedToWindow(); 164 } 165 166 167 void 168 BChannelSlider::AllAttached() 169 { 170 BControl::AllAttached(); 171 } 172 173 174 void 175 BChannelSlider::DetachedFromWindow() 176 { 177 inherited::DetachedFromWindow(); 178 } 179 180 181 void 182 BChannelSlider::AllDetached() 183 { 184 BControl::AllDetached(); 185 } 186 187 188 void 189 BChannelSlider::MessageReceived(BMessage *message) 190 { 191 switch (message->what) { 192 case B_SET_PROPERTY: 193 case B_GET_PROPERTY: 194 { 195 BMessage reply(B_REPLY); 196 int32 index = 0; 197 BMessage specifier; 198 int32 what = 0; 199 const char *property = NULL; 200 bool handled = false; 201 status_t status = message->GetCurrentSpecifier(&index, &specifier, &what, &property); 202 BPropertyInfo propInfo(sPropertyInfo); 203 if (status == B_OK 204 && propInfo.FindMatch(message, index, &specifier, what, property) >= 0) { 205 handled = true; 206 if (message->what == B_SET_PROPERTY) { 207 orientation orient; 208 if (specifier.FindInt32("data", (int32 *)&orient) == B_OK) { 209 SetOrientation(orient); 210 Invalidate(Bounds()); 211 } 212 } else if (message->what == B_GET_PROPERTY) 213 reply.AddInt32("result", (int32)Orientation()); 214 else 215 status = B_BAD_SCRIPT_SYNTAX; 216 } 217 218 if (handled) { 219 reply.AddInt32("error", status); 220 message->SendReply(&reply); 221 } else 222 inherited::MessageReceived(message); 223 break; 224 } 225 default: 226 inherited::MessageReceived(message); 227 break; 228 } 229 } 230 231 232 void 233 BChannelSlider::Draw(BRect updateRect) 234 { 235 UpdateFontDimens(); 236 DrawThumbs(); 237 238 if (Label()) { 239 BRect bounds(Bounds()); 240 float labelWidth = StringWidth(Label()); 241 242 DrawString(Label(), BPoint((bounds.Width() - labelWidth) / 2, fBaseLine)); 243 } 244 } 245 246 247 void 248 BChannelSlider::MouseDown(BPoint where) 249 { 250 if (!IsEnabled()) 251 BControl::MouseDown(where); 252 else { 253 fCurrentChannel = -1; 254 fMinpoint = 0; 255 256 // Search the channel on which the mouse was over 257 int32 numChannels = CountChannels(); 258 for (int32 channel = 0; channel < numChannels; channel++) { 259 BRect frame = ThumbFrameFor(channel); 260 frame.OffsetBy(fClickDelta); 261 262 float range = ThumbRangeFor(channel); 263 if (Vertical()) { 264 fMinpoint = frame.top + frame.Height() / 2; 265 frame.bottom += range; 266 } else { 267 // TODO: Fix this, the clickzone isn't perfect 268 frame.right += range; 269 fMinpoint = frame.Width(); 270 } 271 272 // Click was on a slider. 273 if (frame.Contains(where)) { 274 fCurrentChannel = channel; 275 break; 276 } 277 } 278 279 // Click wasn't on a slider. Bail out. 280 if (fCurrentChannel == -1) 281 return; 282 283 uint32 buttons = 0; 284 BMessage *currentMessage = Window()->CurrentMessage(); 285 if (currentMessage != NULL) 286 currentMessage->FindInt32("buttons", (int32 *)&buttons); 287 288 fAllChannels = (buttons & B_SECONDARY_MOUSE_BUTTON) == 0; 289 290 if (fInitialValues != NULL && fAllChannels) { 291 delete[] fInitialValues; 292 fInitialValues = NULL; 293 } 294 295 if (fInitialValues == NULL) 296 fInitialValues = new int32[numChannels]; 297 298 if (fAllChannels) { 299 for (int32 i = 0; i < numChannels; i++) 300 fInitialValues[i] = ValueFor(i); 301 } else 302 fInitialValues[fCurrentChannel] = ValueFor(fCurrentChannel); 303 304 if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) { 305 if (!IsTracking()) { 306 SetTracking(true); 307 DrawThumbs(); 308 Flush(); 309 } 310 311 MouseMovedCommon(where, B_ORIGIN); 312 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); 313 } else { 314 do { 315 snooze(30000); 316 GetMouse(&where, &buttons); 317 MouseMovedCommon(where, B_ORIGIN); 318 } while (buttons != 0); 319 FinishChange(); 320 fCurrentChannel = -1; 321 fAllChannels = false; 322 } 323 } 324 } 325 326 327 void 328 BChannelSlider::MouseUp(BPoint where) 329 { 330 if (IsEnabled() && IsTracking()) { 331 FinishChange(); 332 SetTracking(false); 333 fAllChannels = false; 334 fCurrentChannel = -1; 335 fMinpoint = 0; 336 } else 337 BControl::MouseUp(where); 338 } 339 340 341 void 342 BChannelSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message) 343 { 344 if (IsEnabled() && IsTracking()) 345 MouseMovedCommon(where, B_ORIGIN); 346 else 347 BControl::MouseMoved(where, code, message); 348 } 349 350 351 void 352 BChannelSlider::WindowActivated(bool state) 353 { 354 BControl::WindowActivated(state); 355 } 356 357 358 void 359 BChannelSlider::KeyDown(const char *bytes, int32 numBytes) 360 { 361 BControl::KeyDown(bytes, numBytes); 362 } 363 364 365 void 366 BChannelSlider::KeyUp(const char *bytes, int32 numBytes) 367 { 368 BView::KeyUp(bytes, numBytes); 369 } 370 371 372 void 373 BChannelSlider::FrameResized(float newWidth, float newHeight) 374 { 375 inherited::FrameResized(newWidth, newHeight); 376 Invalidate(Bounds()); 377 } 378 379 380 void 381 BChannelSlider::SetFont(const BFont *font, uint32 mask) 382 { 383 inherited::SetFont(font, mask); 384 } 385 386 387 void 388 BChannelSlider::MakeFocus(bool focusState) 389 { 390 if (focusState && !IsFocus()) 391 fFocusChannel = -1; 392 BControl::MakeFocus(focusState); 393 } 394 395 396 void 397 BChannelSlider::SetEnabled(bool on) 398 { 399 BControl::SetEnabled(on); 400 } 401 402 403 void 404 BChannelSlider::GetPreferredSize(float *width, float *height) 405 { 406 if (width) { 407 float _width = (float)ceil(StringWidth(Label())); 408 if (Vertical()) { 409 *width = max_c(_width, 2 + 12 * CountChannels()); 410 } else { 411 *width = max_c(_width, 64); 412 } 413 } 414 if (height) { 415 if (Vertical()) 416 *height = 195; 417 else 418 *height = 71; 419 } 420 } 421 422 423 BHandler * 424 BChannelSlider::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier, 425 int32 form, const char *property) 426 { 427 BHandler *target = this; 428 BPropertyInfo propertyInfo(sPropertyInfo); 429 if (propertyInfo.FindMatch(msg, index, specifier, form, property) < B_OK) 430 target = BChannelControl::ResolveSpecifier(msg, index, specifier, form, property); 431 432 return target; 433 } 434 435 436 status_t 437 BChannelSlider::GetSupportedSuites(BMessage *data) 438 { 439 if (data == NULL) 440 return B_BAD_VALUE; 441 442 status_t err = data->AddString("suites", "suite/vnd.Be-channel-slider"); 443 444 BPropertyInfo propInfo(sPropertyInfo); 445 if (err == B_OK) 446 err = data->AddFlat("messages", &propInfo); 447 448 if (err == B_OK) 449 return BChannelControl::GetSupportedSuites(data); 450 return err; 451 } 452 453 454 void 455 BChannelSlider::DrawChannel(BView *into, int32 channel, BRect area, bool pressed) 456 { 457 float hCenter = area.Width() / 2; 458 float vCenter = area.Height() / 2; 459 460 BPoint leftTop; 461 BPoint bottomRight; 462 if (Vertical()) { 463 leftTop.Set(area.left + hCenter, area.top + vCenter); 464 bottomRight.Set(leftTop.x, leftTop.y + ThumbRangeFor(channel)); 465 } else { 466 leftTop.Set(area.left, area.top + vCenter); 467 bottomRight.Set(area.left + ThumbRangeFor(channel), leftTop.y); 468 } 469 470 DrawGroove(into, channel, leftTop, bottomRight); 471 472 BPoint thumbLocation = leftTop; 473 if (Vertical()) 474 thumbLocation.y += ThumbDeltaFor(channel); 475 else 476 thumbLocation.x += ThumbDeltaFor(channel); 477 478 DrawThumb(into, channel, thumbLocation, pressed); 479 } 480 481 482 void 483 BChannelSlider::DrawGroove(BView *into, int32 channel, BPoint topLeft, BPoint bottomRight) 484 { 485 ASSERT(into != NULL); 486 BRect rect(topLeft, bottomRight); 487 488 DrawThumbFrame(fBackingView, rect.InsetByCopy(-2.5, -2.5)); 489 490 rect.InsetBy(-0.5, -0.5); 491 into->FillRect(rect, B_SOLID_HIGH); 492 } 493 494 495 void 496 BChannelSlider::DrawThumb(BView *into, int32 channel, BPoint where, bool pressed) 497 { 498 ASSERT(into != NULL); 499 500 const BBitmap *thumb = ThumbFor(channel, pressed); 501 if (thumb == NULL) 502 return; 503 504 BRect bitmapBounds = thumb->Bounds(); 505 where.x -= bitmapBounds.right / 2; 506 where.y -= bitmapBounds.bottom / 2; 507 508 into->PushState(); 509 510 into->SetDrawingMode(B_OP_OVER); 511 into->DrawBitmapAsync(thumb, where); 512 513 if (pressed) { 514 into->SetDrawingMode(B_OP_ALPHA); 515 516 rgb_color color = tint_color(into->ViewColor(), B_DARKEN_4_TINT); 517 color.alpha = 128; 518 into->SetHighColor(color); 519 520 BRect destRect(where, where); 521 destRect.right += bitmapBounds.right; 522 destRect.bottom += bitmapBounds.bottom; 523 524 into->FillRect(destRect); 525 } 526 527 into->PopState(); 528 } 529 530 531 const BBitmap * 532 BChannelSlider::ThumbFor(int32 channel, bool pressed) 533 { 534 // TODO: Finish me 535 if (fLeftKnob == NULL) { 536 if (Vertical()) { 537 fLeftKnob = new BBitmap(BRect(0, 0, 11, 14), B_CMAP8); 538 fLeftKnob->SetBits(kVerticalKnobData, sizeof(kVerticalKnobData), 0, B_CMAP8); 539 } else { 540 fLeftKnob = new BBitmap(BRect(0, 0, 14, 11), B_CMAP8); 541 fLeftKnob->SetBits(kHorizontalKnobData, sizeof(kHorizontalKnobData), 0, B_CMAP8); 542 } 543 } 544 545 return fLeftKnob; 546 } 547 548 549 BRect 550 BChannelSlider::ThumbFrameFor(int32 channel) 551 { 552 UpdateFontDimens(); 553 554 BRect frame(0, 0, 0, 0); 555 const BBitmap *thumb = ThumbFor(channel, false); 556 if (thumb != NULL) { 557 frame = thumb->Bounds(); 558 if (Vertical()) 559 frame.OffsetBy(channel * frame.Width(), fLineFeed + kPadding); 560 else 561 frame.OffsetBy(kPadding, fLineFeed + channel * frame.Height()); 562 } 563 564 return frame; 565 } 566 567 568 float 569 BChannelSlider::ThumbDeltaFor(int32 channel) 570 { 571 float delta = 0; 572 if (channel >= 0 && channel < MaxChannelCount()) { 573 float range = ThumbRangeFor(channel); 574 int32 limitRange = MaxLimitList()[channel] - MinLimitList()[channel]; 575 delta = ValueList()[channel] * range / limitRange; 576 577 if (Vertical()) 578 delta = range - delta; 579 } 580 581 return delta; 582 } 583 584 585 float 586 BChannelSlider::ThumbRangeFor(int32 channel) 587 { 588 UpdateFontDimens(); 589 590 float range = 0; 591 BRect bounds = Bounds(); 592 BRect frame = ThumbFrameFor(channel); 593 if (Vertical()) 594 range = bounds.Height() - frame.Height() - (kPadding + fLineFeed) * 2; 595 else 596 range = bounds.Width() - frame.Width() - kPadding * 2; 597 598 return range; 599 } 600 601 602 void 603 BChannelSlider::InitData() 604 { 605 UpdateFontDimens(); 606 607 fLeftKnob = NULL; 608 fMidKnob = NULL; 609 fRightKnob = NULL; 610 fBacking = NULL; 611 fBackingView = NULL; 612 fVertical = Bounds().Width() / Bounds().Height() < 1; 613 fClickDelta = B_ORIGIN; 614 615 fCurrentChannel = -1; 616 fAllChannels = false; 617 fInitialValues = NULL; 618 fMinpoint = 0; 619 fFocusChannel = -1; 620 621 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 622 } 623 624 625 void 626 BChannelSlider::FinishChange() 627 { 628 if (fInitialValues != NULL) { 629 if (fAllChannels) { 630 // TODO: Iterate through the list of channels, and invoke only 631 // for changed values ? 632 633 InvokeChannel(); 634 635 } else { 636 if (ValueList()[fCurrentChannel] != fInitialValues[fCurrentChannel]) { 637 SetValueFor(fCurrentChannel, ValueList()[fCurrentChannel]); 638 Invoke(); 639 } 640 } 641 } 642 643 SetTracking(false); 644 Redraw(); 645 } 646 647 648 void 649 BChannelSlider::UpdateFontDimens() 650 { 651 font_height height; 652 GetFontHeight(&height); 653 fBaseLine = height.ascent + height.leading; 654 fLineFeed = fBaseLine + height.descent; 655 } 656 657 658 void 659 BChannelSlider::DrawThumbs() 660 { 661 if (fBacking == NULL) { 662 // This is the idea: we build a bitmap by taking the coordinates 663 // of the first and last thumb frames (top/left and bottom/right) 664 BRect first = ThumbFrameFor(0); 665 BRect last = ThumbFrameFor(CountChannels() - 1); 666 BRect bitmapFrame(first.LeftTop(), last.RightBottom()); 667 668 if (Vertical()) 669 bitmapFrame.top -= ThumbRangeFor(0); 670 else 671 bitmapFrame.right += ThumbRangeFor(0); 672 673 fBacking = new BBitmap(bitmapFrame.OffsetToCopy(B_ORIGIN), 674 #ifdef __HAIKU__ 675 BScreen(Window()).ColorSpace(), 676 #else 677 B_RGB32, 678 #endif 679 true, false); 680 if (fBacking->Lock()) { 681 fBackingView = new BView(bitmapFrame.OffsetToCopy(B_ORIGIN), "backing view", B_FOLLOW_NONE, B_WILL_DRAW); 682 fBacking->AddChild(fBackingView); 683 fBackingView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 684 fBackingView->SetLowColor(fBackingView->ViewColor()); 685 fBacking->Unlock(); 686 } 687 } 688 689 BPoint drawHere; 690 drawHere.x = (Bounds().Width() - fBacking->Bounds().Width()) / 2; 691 drawHere.y = (Bounds().Height() - fBacking->Bounds().Height() + fLineFeed) / 2; 692 693 if (fBacking->Lock()) { 694 // Clear the view's background 695 fBackingView->FillRect(fBackingView->Bounds(), B_SOLID_LOW); 696 697 BRect channelArea; 698 int32 channelCount = CountChannels(); 699 for (int32 channel = 0; channel < channelCount; channel++) { 700 channelArea = ThumbFrameFor(channel); 701 // TODO: This is (apparently) needed because ThumbFrameFor() doesn't 702 // take into account that the view we draw on is attached to an offscreen 703 // bitmap. Still this doesn't make much sense: 704 // could be that I'm simply missing something. 705 if (Vertical()) 706 channelArea.OffsetBy(0, -channelArea.top); 707 else 708 channelArea.OffsetBy(0, -channelArea.Height()); 709 710 bool pressed = fMinpoint != 0 && (channel == fCurrentChannel || fAllChannels); 711 DrawChannel(fBackingView, channel, channelArea, pressed); 712 } 713 714 #if 1 715 // This part draws the current value over the thumb. 716 // TODO: make it nicer. Simplify the code. 717 if (fCurrentChannel != -1 && fMinpoint != 0) { 718 char valueString[32]; 719 snprintf(valueString, 32, "%ld", ValueFor(fCurrentChannel)); 720 float width = fBackingView->StringWidth(valueString); 721 BRect valueRect(0, 0, width, 10); 722 rgb_color oldColor = fBackingView->HighColor(); 723 if (Vertical()) 724 valueRect.OffsetTo((ThumbFrameFor(fCurrentChannel).Width() - width) / 2 + fCurrentChannel * ThumbFrameFor(fCurrentChannel).Width(), 725 ThumbDeltaFor(fCurrentChannel)); 726 else 727 valueRect.OffsetTo(ThumbDeltaFor(fCurrentChannel), ThumbFrameFor(fCurrentChannel).top - 10); 728 fBackingView->SetHighColor(255, 255, 172); 729 fBackingView->FillRect(valueRect); 730 fBackingView->SetHighColor(0, 0, 0); 731 valueRect.OffsetBy(1 , 9); 732 fBackingView->DrawString(valueString, valueRect.LeftTop()); 733 fBackingView->SetHighColor(oldColor); 734 } 735 #endif 736 fBackingView->Sync(); 737 fBacking->Unlock(); 738 } 739 740 DrawBitmapAsync(fBacking, drawHere); 741 742 #if 0 743 // this part draws the value at the bottom of the sliders. 744 if (fCurrentChannel != -1 && fMinpoint != 0) { 745 char valueString[32]; 746 snprintf(valueString, 32, "%ld", ValueFor(fCurrentChannel)); 747 BPoint stringPoint = drawHere; 748 float stringWidth = StringWidth(valueString); 749 stringPoint.x += (fBacking->Bounds().Width() - stringWidth) / 2; 750 stringPoint.y += fBacking->Bounds().Height() + fBaseLine; 751 BRect stringRect(stringPoint, stringPoint); 752 stringRect.left -= 10; 753 stringRect.right += StringWidth("100"); 754 stringRect.top -= fLineFeed; 755 756 SetHighColor(ViewColor()); 757 FillRect(stringRect); 758 759 SetHighColor(0, 0, 0); 760 DrawString(valueString, stringPoint); 761 } 762 #endif 763 764 // fClickDelta is used in MouseMoved() 765 fClickDelta = drawHere; 766 767 // TODO: See above 768 if (Vertical()) 769 fClickDelta.y -= ThumbFrameFor(0).top; 770 else 771 fClickDelta.y -= ThumbFrameFor(0).Height(); 772 } 773 774 775 void 776 BChannelSlider::DrawThumbFrame(BView *into, const BRect &area) 777 { 778 rgb_color oldColor = into->HighColor(); 779 780 into->SetHighColor(255, 255, 255); 781 into->StrokeRect(area); 782 into->SetHighColor(tint_color(into->ViewColor(), B_DARKEN_1_TINT)); 783 into->StrokeLine(area.LeftTop(), BPoint(area.right, area.top)); 784 into->StrokeLine(area.LeftTop(), BPoint(area.left, area.bottom - 1)); 785 into->SetHighColor(tint_color(into->ViewColor(), B_DARKEN_2_TINT)); 786 into->StrokeLine(BPoint(area.left + 1, area.top + 1), BPoint(area.right - 1, area.top + 1)); 787 into->StrokeLine(BPoint(area.left + 1, area.top + 1), BPoint(area.left + 1, area.bottom - 2)); 788 789 into->SetHighColor(oldColor); 790 } 791 792 793 bool 794 BChannelSlider::Vertical() const 795 { 796 return fVertical; 797 } 798 799 800 void 801 BChannelSlider::Redraw() 802 { 803 Invalidate(Bounds()); 804 Flush(); 805 } 806 807 808 void 809 BChannelSlider::MouseMovedCommon(BPoint point, BPoint point2) 810 { 811 float floatValue = 0; 812 int32 limitRange = MaxLimitList()[fCurrentChannel] - MinLimitList()[fCurrentChannel]; 813 float range = ThumbRangeFor(fCurrentChannel); 814 if (Vertical()) 815 floatValue = range - (point.y - fMinpoint); 816 else 817 floatValue = range + (point.x - fMinpoint); 818 819 int32 value = (int32)(floatValue / range * limitRange); 820 if (fAllChannels) 821 SetAllValue(value); 822 else 823 SetValueFor(fCurrentChannel, value); 824 825 InvokeNotifyChannel(ModificationMessage()); 826 DrawThumbs(); 827 } 828 829 830 void BChannelSlider::_Reserved_BChannelSlider_0(void *, ...) {} 831 void BChannelSlider::_Reserved_BChannelSlider_1(void *, ...) {} 832 void BChannelSlider::_Reserved_BChannelSlider_2(void *, ...) {} 833 void BChannelSlider::_Reserved_BChannelSlider_3(void *, ...) {} 834 void BChannelSlider::_Reserved_BChannelSlider_4(void *, ...) {} 835 void BChannelSlider::_Reserved_BChannelSlider_5(void *, ...) {} 836 void BChannelSlider::_Reserved_BChannelSlider_6(void *, ...) {} 837 void BChannelSlider::_Reserved_BChannelSlider_7(void *, ...) {} 838