1 /* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Stephan Aßmus <superstippi@gmx.de> 8 * Axel Dörfler, axeld@pinc-software.de 9 */ 10 11 12 #include <stdio.h> 13 14 #include <stdlib.h> 15 #include <string.h> 16 17 #include <Bitmap.h> 18 #include <Errors.h> 19 #include <Message.h> 20 #include <Region.h> 21 #include <Window.h> 22 23 #include <Slider.h> 24 25 26 BSlider::BSlider(BRect frame, const char *name, const char *label, BMessage *message, 27 int32 minValue, int32 maxValue, thumb_style thumbType, 28 uint32 resizingMode, uint32 flags) 29 : BControl(frame, name, label, message, resizingMode, flags) 30 { 31 fModificationMessage = NULL; 32 fSnoozeAmount = 20000; 33 fOrientation = B_HORIZONTAL; 34 fBarThickness = 6.0f; 35 fMinLimitLabel = NULL; 36 fMaxLimitLabel = NULL; 37 fMinValue = minValue; 38 fMaxValue = maxValue; 39 40 fKeyIncrementValue = 1; 41 fHashMarkCount = 0; 42 fHashMarks = B_HASH_MARKS_NONE; 43 fStyle = thumbType; 44 45 if (Style() == B_BLOCK_THUMB) { 46 SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 47 B_DARKEN_4_TINT)); 48 } else { 49 SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 50 B_DARKEN_4_TINT)); 51 } 52 53 UseFillColor(false, NULL); 54 55 _InitObject(); 56 SetValue(0); 57 } 58 59 60 BSlider::BSlider(BRect frame, const char *name, const char *label, BMessage *message, 61 int32 minValue, int32 maxValue, orientation posture, 62 thumb_style thumbType, uint32 resizingMode, uint32 flags) 63 : BControl(frame, name, label, message, resizingMode, flags) 64 { 65 fModificationMessage = NULL; 66 fSnoozeAmount = 20000; 67 fOrientation = posture; 68 fBarThickness = 6.0f; 69 fMinLimitLabel = NULL; 70 fMaxLimitLabel = NULL; 71 fMinValue = minValue; 72 fMaxValue = maxValue; 73 74 fKeyIncrementValue = 1; 75 fHashMarkCount = 0; 76 fHashMarks = B_HASH_MARKS_NONE; 77 fStyle = thumbType; 78 79 if (Style() == B_BLOCK_THUMB) 80 SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 81 B_DARKEN_4_TINT)); 82 else 83 SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 84 B_DARKEN_4_TINT)); 85 86 UseFillColor(false, NULL); 87 88 _InitObject(); 89 SetValue(0); 90 } 91 92 93 BSlider::BSlider(BMessage *archive) 94 : BControl(archive) 95 { 96 fModificationMessage = NULL; 97 98 if (archive->HasMessage("_mod_msg")) { 99 BMessage *message = new BMessage; 100 101 archive->FindMessage("_mod_msg", message); 102 103 SetModificationMessage(message); 104 } 105 106 if (archive->FindInt32("_sdelay", &fSnoozeAmount) != B_OK) 107 SetSnoozeAmount(20000); 108 109 rgb_color color; 110 111 if (archive->FindInt32("_fcolor", (int32 *)&color) == B_OK) { 112 UseFillColor(true, &color); 113 } else 114 UseFillColor(false); 115 116 int32 orient; 117 118 if (archive->FindInt32("_orient", &orient) == B_OK) 119 fOrientation = (orientation)orient; 120 else 121 fOrientation = B_HORIZONTAL; 122 123 fMinLimitLabel = NULL; 124 fMaxLimitLabel = NULL; 125 126 const char *minlbl = NULL, *maxlbl = NULL; 127 128 archive->FindString("_minlbl", &minlbl); 129 archive->FindString("_maxlbl", &maxlbl); 130 131 SetLimitLabels(minlbl, maxlbl); 132 133 if (archive->FindInt32("_min", &fMinValue) != B_OK) 134 fMinValue = 0; 135 136 if (archive->FindInt32("_max", &fMaxValue) != B_OK) 137 fMaxValue = 100; 138 139 if (archive->FindInt32("_incrementvalue", &fKeyIncrementValue) != B_OK) 140 fKeyIncrementValue = 1; 141 142 if (archive->FindInt32("_hashcount", &fHashMarkCount) != B_OK) 143 fHashMarkCount = 11; 144 145 int16 hashloc; 146 147 if (archive->FindInt16("_hashloc", &hashloc) == B_OK) 148 fHashMarks = (hash_mark_location)hashloc; 149 else 150 fHashMarks = B_HASH_MARKS_NONE; 151 152 int16 sstyle; 153 154 if (archive->FindInt16("_sstyle", &sstyle) == B_OK) 155 fStyle = (thumb_style)sstyle; 156 else 157 fStyle = B_BLOCK_THUMB; 158 159 if (archive->FindInt32("_bcolor", (int32 *)&color) == B_OK) 160 SetBarColor(color); 161 else { 162 if (Style() == B_BLOCK_THUMB) 163 SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 164 B_DARKEN_4_TINT)); 165 else 166 SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 167 B_DARKEN_4_TINT)); 168 } 169 170 float bthickness; 171 172 if (archive->FindFloat("_bthickness", &bthickness) == B_OK) 173 fBarThickness = bthickness; 174 else 175 fBarThickness = 6.0f; 176 177 _InitObject(); 178 } 179 180 181 BSlider::~BSlider() 182 { 183 #if USE_OFF_SCREEN_VIEW 184 if (fOffScreenBits) 185 delete fOffScreenBits; 186 #endif 187 188 delete fModificationMessage; 189 free(fMinLimitLabel); 190 free(fMaxLimitLabel); 191 } 192 193 194 void 195 BSlider::_InitObject() 196 { 197 fLocation.x = 0; 198 fLocation.y = 0; 199 fInitialLocation.x = 0; 200 fInitialLocation.y = 0; 201 202 #if USE_OFF_SCREEN_VIEW 203 fOffScreenBits = NULL; 204 fOffScreenView = NULL; 205 #endif 206 207 fUpdateText = NULL; 208 } 209 210 211 BArchivable* 212 BSlider::Instantiate(BMessage *archive) 213 { 214 if (validate_instantiation(archive, "BSlider")) 215 return new BSlider(archive); 216 217 return NULL; 218 } 219 220 221 status_t 222 BSlider::Archive(BMessage *archive, bool deep) const 223 { 224 status_t ret = BControl::Archive(archive, deep); 225 226 if (ModificationMessage() && ret == B_OK) 227 ret = archive->AddMessage("_mod_msg", ModificationMessage()); 228 229 if (ret == B_OK) 230 ret = archive->AddInt32("_sdelay", fSnoozeAmount); 231 if (ret == B_OK) 232 ret = archive->AddInt32("_bcolor", (const uint32 &)fBarColor); 233 234 if (FillColor(NULL) && ret == B_OK) 235 ret = archive->AddInt32("_fcolor", (const uint32 &)fFillColor); 236 237 if (ret == B_OK && fMinLimitLabel) 238 ret = archive->AddString("_minlbl", fMinLimitLabel); 239 240 if (ret == B_OK && fMaxLimitLabel) 241 ret = archive->AddString("_maxlbl", fMaxLimitLabel); 242 243 if (ret == B_OK) 244 ret = archive->AddInt32("_min", fMinValue); 245 if (ret == B_OK) 246 ret = archive->AddInt32("_max", fMaxValue); 247 248 if (ret == B_OK) 249 ret = archive->AddInt32("_incrementvalue", fKeyIncrementValue); 250 if (ret == B_OK) 251 ret = archive->AddInt32("_hashcount", fHashMarkCount); 252 if (ret == B_OK) 253 ret = archive->AddInt16("_hashloc", fHashMarks); 254 if (ret == B_OK) 255 ret = archive->AddInt16("_sstyle", fStyle); 256 if (ret == B_OK) 257 ret = archive->AddInt32("_orient", fOrientation); 258 if (ret == B_OK) 259 ret = archive->AddFloat("_bthickness", fBarThickness); 260 261 return ret; 262 } 263 264 265 status_t 266 BSlider::Perform(perform_code d, void *arg) 267 { 268 return BControl::Perform(d, arg); 269 } 270 271 272 void 273 BSlider::WindowActivated(bool state) 274 { 275 BControl::WindowActivated(state); 276 } 277 278 279 void 280 BSlider::AttachedToWindow() 281 { 282 ResizeToPreferred(); 283 284 fLocation.Set(9.0f, 0.0f); 285 fUpdateText = UpdateText(); 286 287 #if USE_OFF_SCREEN_VIEW 288 BRect bounds(Bounds()); 289 290 if (!fOffScreenView) { 291 fOffScreenView = new BView(bounds, "", B_FOLLOW_ALL, B_WILL_DRAW); 292 293 BFont font; 294 GetFont(&font); 295 fOffScreenView->SetFont(&font); 296 } 297 298 if (!fOffScreenBits) { 299 fOffScreenBits = new BBitmap(bounds, B_CMAP8, true, false); 300 301 if (fOffScreenBits && fOffScreenView) 302 fOffScreenBits->AddChild(fOffScreenView); 303 304 } else if (fOffScreenView) 305 fOffScreenBits->AddChild(fOffScreenView); 306 #endif // USE_OFF_SCREEN_VIEW 307 308 BControl::AttachedToWindow(); 309 310 BView* view = OffscreenView(); 311 if (view) { 312 rgb_color color = ViewColor(); 313 if (Parent() != NULL) 314 color = Parent()->ViewColor(); 315 316 /* fOffScreenBits->Lock(); 317 fOffScreenView->SetViewColor(color); 318 fOffScreenView->SetLowColor(color); 319 fOffScreenBits->Unlock();*/ 320 321 view->LockLooper(); 322 view->SetViewColor(B_TRANSPARENT_COLOR); 323 view->SetLowColor(color); 324 view->UnlockLooper(); 325 } 326 327 SetValue(Value()); 328 // makes sure the value is within valid bounds 329 } 330 331 332 void 333 BSlider::AllAttached() 334 { 335 BControl::AllAttached(); 336 } 337 338 339 void 340 BSlider::AllDetached() 341 { 342 BControl::AllDetached(); 343 } 344 345 346 void 347 BSlider::DetachedFromWindow() 348 { 349 BControl::DetachedFromWindow(); 350 351 #if USE_OFF_SCREEN_VIEW 352 if (fOffScreenBits) { 353 delete fOffScreenBits; 354 fOffScreenBits = NULL; 355 fOffScreenView = NULL; 356 } 357 #endif 358 } 359 360 361 void 362 BSlider::MessageReceived(BMessage *msg) 363 { 364 BControl::MessageReceived(msg); 365 } 366 367 368 void 369 BSlider::FrameMoved(BPoint new_position) 370 { 371 BControl::FrameMoved(new_position); 372 } 373 374 375 void 376 BSlider::FrameResized(float w,float h) 377 { 378 BControl::FrameResized(w, h); 379 380 BRect bounds(Bounds()); 381 382 if (bounds.right <= 0.0f || bounds.bottom <= 0.0f) 383 return; 384 385 #if USE_OFF_SCREEN_VIEW 386 if (fOffScreenBits) { 387 fOffScreenBits->RemoveChild(fOffScreenView); 388 delete fOffScreenBits; 389 390 fOffScreenView->ResizeTo(bounds.Width(), bounds.Height()); 391 392 fOffScreenBits = new BBitmap(Bounds(), B_CMAP8, true, false); 393 fOffScreenBits->AddChild(fOffScreenView); 394 } 395 #endif 396 397 Invalidate(); 398 } 399 400 401 void 402 BSlider::KeyDown(const char *bytes, int32 numBytes) 403 { 404 if (!IsEnabled() || IsHidden()) 405 return; 406 407 switch (bytes[0]) { 408 case B_LEFT_ARROW: 409 case B_DOWN_ARROW: { 410 SetValue(Value() - KeyIncrementValue()); 411 Invoke(); 412 break; 413 } 414 case B_RIGHT_ARROW: 415 case B_UP_ARROW: { 416 SetValue(Value() + KeyIncrementValue()); 417 Invoke(); 418 break; 419 } 420 default: 421 BControl::KeyDown(bytes, numBytes); 422 } 423 } 424 425 426 bool 427 BSlider::_ConstrainPoint(BPoint point, BPoint comparePoint) const 428 { 429 if (fOrientation == B_HORIZONTAL) { 430 if (point.x != comparePoint.x) { 431 if (point.x < _MinPosition()) 432 point.x = _MinPosition(); 433 else if (point.x > _MaxPosition()) 434 point.x = _MaxPosition(); 435 436 return true; 437 } 438 } else { 439 if (point.y != comparePoint.y) { 440 if (point.y > _MinPosition()) 441 point.y = _MinPosition(); 442 else if (point.y < _MaxPosition()) 443 point.y = _MaxPosition(); 444 445 return true; 446 } 447 } 448 449 return false; 450 } 451 452 453 void 454 BSlider::MouseDown(BPoint point) 455 { 456 if (!IsEnabled()) 457 return; 458 459 if (BarFrame().Contains(point) || ThumbFrame().Contains(point)) 460 fInitialLocation = _Location(); 461 462 uint32 buttons; 463 GetMouse(&point, &buttons, true); 464 465 _ConstrainPoint(point, fInitialLocation); 466 SetValue(ValueForPoint(point)); 467 468 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED); 469 470 if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) { 471 SetTracking(true); 472 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); 473 } else { 474 // synchronous mouse tracking 475 BPoint prevPoint; 476 477 while (buttons) { 478 prevPoint = point; 479 480 snooze(SnoozeAmount()); 481 GetMouse(&point, &buttons, true); 482 483 if (_ConstrainPoint(point, prevPoint)) { 484 SetValue(ValueForPoint(point)); 485 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED); 486 } 487 } 488 if (_Location() != fInitialLocation) 489 Invoke(); 490 } 491 } 492 493 494 void 495 BSlider::MouseUp(BPoint point) 496 { 497 if (IsTracking()) { 498 if (_Location() != fInitialLocation) 499 Invoke(); 500 501 SetTracking(false); 502 } else 503 BControl::MouseUp(point); 504 } 505 506 507 void 508 BSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message) 509 { 510 if (IsTracking()) { 511 if (_ConstrainPoint(point, _Location())) { 512 SetValue(ValueForPoint(point)); 513 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED); 514 } 515 } else 516 BControl::MouseMoved(point, transit, message); 517 } 518 519 520 void 521 BSlider::Pulse() 522 { 523 BControl::Pulse(); 524 } 525 526 527 void 528 BSlider::SetLabel(const char *label) 529 { 530 BControl::SetLabel(label); 531 } 532 533 534 void 535 BSlider::SetLimitLabels(const char *minLabel, const char *maxLabel) 536 { 537 if (minLabel) { 538 free(fMinLimitLabel); 539 fMinLimitLabel = strdup(minLabel); 540 } 541 542 if (maxLabel) { 543 free(fMaxLimitLabel); 544 fMaxLimitLabel = strdup(maxLabel); 545 } 546 547 // TODO: Auto resizing?!? I would not want this as an app programmer! 548 ResizeToPreferred(); 549 Invalidate(); 550 } 551 552 553 const char* 554 BSlider::MinLimitLabel() const 555 { 556 return fMinLimitLabel; 557 } 558 559 560 const char* 561 BSlider::MaxLimitLabel() const 562 { 563 return fMaxLimitLabel; 564 } 565 566 567 void 568 BSlider::SetValue(int32 value) 569 { 570 if (value < fMinValue) 571 value = fMinValue; 572 if (value > fMaxValue) 573 value = fMaxValue; 574 575 if (value != Value()) { 576 BPoint loc; 577 float range = (float)(fMaxValue - fMinValue); 578 if (range == 0) 579 range = 1; 580 581 float pos = (float)(value - fMinValue) / range * 582 _MaxPosition() - _MinPosition(); 583 584 if (fOrientation == B_HORIZONTAL) { 585 loc.x = ceil(_MinPosition() + pos); 586 loc.y = 0; 587 } else { 588 loc.x = 0; 589 loc.y = floor(_MaxPosition() - pos); 590 } 591 592 BRect oldThumbFrame = ThumbFrame(); 593 594 if (IsFocus() && Style() == B_TRIANGLE_THUMB) { 595 // we need to update the region with the focus mark as well 596 // (a method BSlider::FocusMarkFrame() would be nice as well) 597 if (fOrientation == B_HORIZONTAL) 598 oldThumbFrame.bottom += 2; 599 else 600 oldThumbFrame.left -= 2; 601 } 602 603 // While it would be enough to do this dependent on fUseFillColor, 604 // that doesn't work out if DrawBar() has been overridden by a sub class 605 if (fOrientation == B_HORIZONTAL) 606 oldThumbFrame.top = BarFrame().top; 607 else 608 oldThumbFrame.right = BarFrame().right; 609 610 _SetLocation(loc); 611 612 BControl::SetValueNoUpdate(value); 613 Invalidate(oldThumbFrame | ThumbFrame()); 614 615 // update text label 616 617 float oldWidth = 0.0f, width = 0.0f; 618 if (fUpdateText != NULL) 619 oldWidth = StringWidth(fUpdateText); 620 621 fUpdateText = UpdateText(); 622 if (fUpdateText != NULL) 623 width = StringWidth(fUpdateText); 624 625 width = ceilf(max_c(width, oldWidth)) + 2.0f; 626 if (width != 0) { 627 font_height fontHeight; 628 GetFontHeight(&fontHeight); 629 630 BRect rect(-width, 0, 0, ceilf(fontHeight.ascent + fontHeight.descent)); 631 rect.OffsetBy(Bounds().Width(), 0); 632 Invalidate(rect); 633 } 634 } 635 } 636 637 638 int32 639 BSlider::ValueForPoint(BPoint location) const 640 { 641 float position = fOrientation == B_HORIZONTAL ? location.x : location.y; 642 float min = _MinPosition(); 643 float max = _MaxPosition(); 644 645 if (position < min) 646 position = min; 647 if (position > max) 648 position = max; 649 650 return (int32)roundf(((position - min) * (fMaxValue - fMinValue) / (max - min)) + fMinValue); 651 } 652 653 654 void 655 BSlider::SetPosition(float position) 656 { 657 if (position <= 0.0f) 658 BControl::SetValue(fMinValue); 659 else if (position >= 1.0f) 660 BControl::SetValue(fMaxValue); 661 else 662 BControl::SetValue((int32)(position * (fMaxValue - fMinValue) + fMinValue)); 663 } 664 665 666 float 667 BSlider::Position() const 668 { 669 float range = (float)(fMaxValue - fMinValue); 670 if (range == 0.0f) 671 range = 1.0f; 672 673 return (float)(Value() - fMinValue) / range; 674 } 675 676 677 void 678 BSlider::SetEnabled(bool on) 679 { 680 BControl::SetEnabled(on); 681 } 682 683 684 void 685 BSlider::GetLimits(int32 *minimum, int32 *maximum) 686 { 687 *minimum = fMinValue; 688 *maximum = fMaxValue; 689 } 690 691 692 void 693 BSlider::Draw(BRect updateRect) 694 { 695 // clear out background 696 BRegion background(updateRect); 697 background.Exclude(BarFrame()); 698 699 // ToDo: the triangle thumb doesn't delete its background, so we still have to do it 700 // Note, this also creates a different behaviour for subclasses, depending on the 701 // thumb style - if possible this should be avoided. 702 if (Style() == B_BLOCK_THUMB) 703 background.Exclude(ThumbFrame()); 704 705 #if USE_OFF_SCREEN_VIEW 706 if (!fOffScreenBits) 707 return; 708 709 if (fOffScreenBits->Lock()) { 710 #endif 711 712 if (background.Frame().IsValid()) 713 OffscreenView()->FillRegion(&background, B_SOLID_LOW); 714 715 #if USE_OFF_SCREEN_VIEW 716 fOffScreenView->Sync(); 717 fOffScreenBits->Unlock(); 718 } 719 #endif 720 721 DrawSlider(); 722 } 723 724 725 void 726 BSlider::DrawSlider() 727 { 728 if (LockLooper()) { 729 #if USE_OFF_SCREEN_VIEW 730 if (!fOffScreenBits) 731 return; 732 if (fOffScreenBits->Lock()) { 733 #endif 734 DrawBar(); 735 DrawHashMarks(); 736 DrawThumb(); 737 DrawFocusMark(); 738 DrawText(); 739 740 #if USE_OFF_SCREEN_VIEW 741 fOffScreenView->Sync(); 742 fOffScreenBits->Unlock(); 743 744 DrawBitmap(fOffScreenBits, B_ORIGIN); 745 } 746 #endif 747 UnlockLooper(); 748 } 749 } 750 751 752 void 753 BSlider::DrawBar() 754 { 755 BRect frame = BarFrame(); 756 BView *view = OffscreenView(); 757 758 rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR); 759 rgb_color lightenmax; 760 rgb_color darken1; 761 rgb_color darken2; 762 rgb_color darkenmax; 763 764 rgb_color barColor; 765 rgb_color fillColor; 766 767 if (IsEnabled()) { 768 lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT); 769 darken1 = tint_color(no_tint, B_DARKEN_1_TINT); 770 darken2 = tint_color(no_tint, B_DARKEN_2_TINT); 771 darkenmax = tint_color(no_tint, B_DARKEN_MAX_TINT); 772 barColor = fBarColor; 773 fillColor = fFillColor; 774 } else { 775 lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT); 776 darken1 = no_tint; 777 darken2 = tint_color(no_tint, B_DARKEN_1_TINT); 778 darkenmax = tint_color(no_tint, B_DARKEN_3_TINT); 779 780 barColor.red = (fBarColor.red + no_tint.red) / 2; 781 barColor.green = (fBarColor.green + no_tint.green) / 2; 782 barColor.blue = (fBarColor.blue + no_tint.blue) / 2; 783 784 fillColor.red = (fFillColor.red + no_tint.red) / 2; 785 fillColor.green = (fFillColor.green + no_tint.green) / 2; 786 fillColor.blue = (fFillColor.blue + no_tint.blue) / 2; 787 } 788 789 // exclude the block thumb from the bar filling 790 791 BRect lowerFrame = frame.InsetByCopy(1, 1); 792 lowerFrame.top++; 793 lowerFrame.left++; 794 BRect upperFrame = lowerFrame; 795 BRect thumbFrame; 796 797 if (Style() == B_BLOCK_THUMB) { 798 thumbFrame = ThumbFrame(); 799 800 if (fOrientation == B_HORIZONTAL) { 801 lowerFrame.right = thumbFrame.left; 802 upperFrame.left = thumbFrame.right; 803 } else { 804 lowerFrame.top = thumbFrame.bottom; 805 upperFrame.bottom = thumbFrame.top; 806 } 807 } else if (fUseFillColor) { 808 if (fOrientation == B_HORIZONTAL) { 809 lowerFrame.right = floor(lowerFrame.left - 1 + Position() 810 * (lowerFrame.Width() + 1)); 811 upperFrame.left = lowerFrame.right; 812 } else { 813 lowerFrame.top = floor(lowerFrame.bottom + 1 - Position() 814 * (lowerFrame.Height() + 1)); 815 upperFrame.bottom = lowerFrame.top; 816 } 817 } 818 819 view->SetHighColor(barColor); 820 view->FillRect(upperFrame); 821 822 if (Style() == B_BLOCK_THUMB || fUseFillColor) { 823 if (fUseFillColor) 824 view->SetHighColor(fillColor); 825 view->FillRect(lowerFrame); 826 } 827 828 if (Style() == B_BLOCK_THUMB) { 829 // We don't want to stroke the lines over the thumb 830 831 PushState(); 832 833 BRegion region; 834 GetClippingRegion(®ion); 835 region.Exclude(thumbFrame); 836 ConstrainClippingRegion(®ion); 837 } 838 839 view->SetHighColor(darken1); 840 view->StrokeLine(BPoint(frame.left, frame.top), 841 BPoint(frame.left + 1.0f, frame.top)); 842 view->StrokeLine(BPoint(frame.left, frame.bottom), 843 BPoint(frame.left + 1.0f, frame.bottom)); 844 view->StrokeLine(BPoint(frame.right - 1.0f, frame.top), 845 BPoint(frame.right, frame.top)); 846 847 view->SetHighColor(darken2); 848 view->StrokeLine(BPoint(frame.left + 1.0f, frame.top), 849 BPoint(frame.right - 1.0f, frame.top)); 850 view->StrokeLine(BPoint(frame.left, frame.bottom - 1.0f), 851 BPoint(frame.left, frame.top + 1.0f)); 852 853 view->SetHighColor(lightenmax); 854 view->StrokeLine(BPoint(frame.left + 1.0f, frame.bottom), 855 BPoint(frame.right, frame.bottom)); 856 view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f), 857 BPoint(frame.right, frame.top + 1.0f)); 858 859 frame.InsetBy(1.0f, 1.0f); 860 861 view->SetHighColor(darkenmax); 862 view->StrokeLine(BPoint(frame.left, frame.bottom), 863 BPoint(frame.left, frame.top)); 864 view->StrokeLine(BPoint(frame.left + 1.0f, frame.top), 865 BPoint(frame.right, frame.top)); 866 867 if (Style() == B_BLOCK_THUMB) 868 PopState(); 869 } 870 871 872 void 873 BSlider::DrawHashMarks() 874 { 875 BRect frame = HashMarksFrame(); 876 BView *view = OffscreenView(); 877 878 rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR); 879 rgb_color lightenmax; 880 rgb_color darken2; 881 882 if (IsEnabled()) { 883 lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT); 884 darken2 = tint_color(no_tint, B_DARKEN_2_TINT); 885 } else { 886 lightenmax = tint_color(no_tint, B_LIGHTEN_2_TINT); 887 darken2 = tint_color(no_tint, B_DARKEN_1_TINT); 888 } 889 890 float pos = _MinPosition(); 891 float factor = 0.0f; 892 if (fHashMarkCount > 1) 893 factor = (_MaxPosition() - pos) / (fHashMarkCount - 1); 894 895 if (fHashMarks & B_HASH_MARKS_TOP && fHashMarkCount > 0) { 896 897 view->BeginLineArray(fHashMarkCount * 2); 898 899 if (fOrientation == B_HORIZONTAL) { 900 for (int32 i = 0; i < fHashMarkCount; i++) { 901 view->AddLine(BPoint(pos, frame.top), 902 BPoint(pos, frame.top + 5), darken2); 903 view->AddLine(BPoint(pos + 1, frame.top), 904 BPoint(pos + 1, frame.top + 5), lightenmax); 905 906 pos += factor; 907 } 908 } else { 909 for (int32 i = 0; i < fHashMarkCount; i++) { 910 view->AddLine(BPoint(frame.left, pos), 911 BPoint(frame.left + 5, pos), darken2); 912 view->AddLine(BPoint(frame.left, pos + 1), 913 BPoint(frame.left + 5, pos + 1), lightenmax); 914 915 pos += factor; 916 } 917 } 918 919 view->EndLineArray(); 920 } 921 922 pos = _MinPosition(); 923 924 if (fHashMarks & B_HASH_MARKS_BOTTOM && fHashMarkCount > 0) { 925 view->BeginLineArray(fHashMarkCount * 2); 926 927 if (fOrientation == B_HORIZONTAL) { 928 for (int32 i = 0; i < fHashMarkCount; i++) { 929 view->AddLine(BPoint(pos, frame.bottom - 5), 930 BPoint(pos, frame.bottom), darken2); 931 view->AddLine(BPoint(pos + 1, frame.bottom - 5), 932 BPoint(pos + 1, frame.bottom), lightenmax); 933 934 pos += factor; 935 } 936 } else { 937 for (int32 i = 0; i < fHashMarkCount; i++) { 938 view->AddLine(BPoint(frame.right - 5, pos), 939 BPoint(frame.right, pos), darken2); 940 view->AddLine(BPoint(frame.right - 5, pos + 1), 941 BPoint(frame.right, pos + 1), lightenmax); 942 943 pos += factor; 944 } 945 } 946 947 view->EndLineArray(); 948 } 949 } 950 951 952 void 953 BSlider::DrawThumb() 954 { 955 if (Style() == B_BLOCK_THUMB) 956 _DrawBlockThumb(); 957 else 958 _DrawTriangleThumb(); 959 } 960 961 962 void 963 BSlider::DrawFocusMark() 964 { 965 if (!IsFocus()) 966 return; 967 968 OffscreenView()->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 969 970 BRect frame = ThumbFrame(); 971 972 if (fStyle == B_BLOCK_THUMB) { 973 frame.left += 2.0f; 974 frame.top += 2.0f; 975 frame.right -= 3.0f; 976 frame.bottom -= 3.0f; 977 OffscreenView()->StrokeRect(frame); 978 } else { 979 if (fOrientation == B_HORIZONTAL) { 980 OffscreenView()->StrokeLine(BPoint(frame.left, frame.bottom + 2.0f), 981 BPoint(frame.right, frame.bottom + 2.0f)); 982 } else { 983 OffscreenView()->StrokeLine(BPoint(frame.left - 2.0f, frame.top), 984 BPoint(frame.left - 2.0f, frame.bottom)); 985 } 986 } 987 } 988 989 990 void 991 BSlider::DrawText() 992 { 993 BRect bounds(Bounds()); 994 BView *view = OffscreenView(); 995 996 if (IsEnabled()) { 997 view->SetHighColor(0, 0, 0); 998 } else { 999 view->SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT)); 1000 } 1001 1002 font_height fontHeight; 1003 GetFontHeight(&fontHeight); 1004 1005 if (Orientation() == B_HORIZONTAL) { 1006 if (Label()) 1007 view->DrawString(Label(), BPoint(2.0f, ceilf(fontHeight.ascent))); 1008 1009 // the update text is updated in SetValue() only 1010 if (fUpdateText != NULL) { 1011 view->DrawString(fUpdateText, BPoint(bounds.right - StringWidth(fUpdateText) 1012 - 2.0f, ceilf(fontHeight.ascent))); 1013 } 1014 1015 if (fMinLimitLabel) 1016 view->DrawString(fMinLimitLabel, BPoint(2.0f, bounds.bottom - 4.0f)); 1017 1018 if (fMaxLimitLabel) { 1019 view->DrawString(fMaxLimitLabel, BPoint(bounds.right 1020 - StringWidth(fMaxLimitLabel) - 2.0f, bounds.bottom - 4.0f)); 1021 } 1022 } else { 1023 if (Label()) { 1024 view->DrawString(Label(), BPoint(bounds.Width() / 2.0f - 1025 StringWidth(Label()) / 2.0f, 1026 fontHeight.ascent)); 1027 } 1028 1029 if (fUpdateText != NULL) { 1030 view->DrawString(fUpdateText, BPoint(bounds.Width() / 2.0f - 1031 StringWidth(fUpdateText) / 2.0f, bounds.bottom - fontHeight.descent - 4.0f)); 1032 } 1033 1034 if (fMaxLimitLabel) { 1035 view->DrawString(fMaxLimitLabel, BPoint(bounds.Width() / 2.0f - 1036 StringWidth(fMaxLimitLabel) / 2.0f, fontHeight.ascent + (Label() 1037 ? ceilf(fontHeight.ascent + fontHeight.descent + fontHeight.leading + 2.0f) 1038 : 0.0f))); 1039 } 1040 1041 if (fMinLimitLabel) { 1042 view->DrawString(fMinLimitLabel, BPoint(bounds.Width() / 2.0f 1043 - StringWidth(fMinLimitLabel) / 2.0f, bounds.bottom - 2.0f)); 1044 } 1045 } 1046 } 1047 1048 1049 char* 1050 BSlider::UpdateText() const 1051 { 1052 return NULL; 1053 } 1054 1055 1056 BRect 1057 BSlider::BarFrame() const 1058 { 1059 BRect frame(Bounds()); 1060 1061 font_height fontHeight; 1062 GetFontHeight(&fontHeight); 1063 1064 float textHeight = (float)ceil(fontHeight.ascent + fontHeight.descent); 1065 1066 if (fStyle == B_BLOCK_THUMB) { 1067 if (Orientation() == B_HORIZONTAL) { 1068 frame.left = 8.0f; 1069 frame.top = 6.0f + (Label() ? textHeight + 4.0f : 0.0f); 1070 frame.right -= 8.0f; 1071 frame.bottom = frame.top + fBarThickness; 1072 } else { 1073 frame.left = floor((frame.Width() - fBarThickness) / 2.0f); 1074 frame.top = 12.0f + (Label() ? textHeight : 0.0f) + 1075 (fMaxLimitLabel ? textHeight : 0.0f); 1076 frame.right = frame.left + fBarThickness; 1077 frame.bottom = frame.bottom - 8.0f - 1078 (fMinLimitLabel ? textHeight + 4 : 0.0f); 1079 } 1080 } else { 1081 if (Orientation() == B_HORIZONTAL) { 1082 frame.left = 7.0f; 1083 frame.top = 6.0f + (Label() ? textHeight + 4.0f : 0.0f); 1084 frame.right -= 7.0f; 1085 frame.bottom = frame.top + fBarThickness; 1086 } else { 1087 frame.left = floor((frame.Width() - fBarThickness) / 2.0f); 1088 frame.top = 11.0f + (Label() ? textHeight : 0.0f) + 1089 (fMaxLimitLabel ? textHeight : 0.0f); 1090 frame.right = frame.left + fBarThickness; 1091 frame.bottom = frame.bottom - 7.0f - 1092 (fMinLimitLabel ? textHeight + 4 : 0.0f); 1093 } 1094 } 1095 1096 return frame; 1097 } 1098 1099 1100 BRect 1101 BSlider::HashMarksFrame() const 1102 { 1103 BRect frame(BarFrame()); 1104 1105 if (fOrientation == B_HORIZONTAL) { 1106 frame.top -= 6.0f; 1107 frame.bottom += 6.0f; 1108 } else { 1109 frame.left -= 6.0f; 1110 frame.right += 6.0f; 1111 } 1112 1113 return frame; 1114 } 1115 1116 1117 BRect 1118 BSlider::ThumbFrame() const 1119 { 1120 // TODO: The slider looks really ugly and broken when it is too little. 1121 // I would suggest using BarFrame() here to get the top and bottom coords 1122 // and spread them further apart for the thumb 1123 1124 BRect frame = Bounds(); 1125 font_height fheight; 1126 1127 GetFontHeight(&fheight); 1128 1129 float textHeight = (float)ceil(fheight.ascent + fheight.descent); 1130 1131 if (fStyle == B_BLOCK_THUMB) { 1132 if (Orientation() == B_HORIZONTAL) { 1133 frame.left = (float)floor(Position() * (_MaxPosition() - _MinPosition()) + 1134 _MinPosition()) - 8.0f; 1135 frame.top = 2.0f + (Label() ? textHeight + 4.0f : 0.0f); 1136 frame.right = frame.left + 17.0f; 1137 frame.bottom = frame.top + fBarThickness + 7.0f; 1138 } else { 1139 frame.left = floor((frame.Width() - fBarThickness) / 2.0f) - 4; 1140 frame.top = (float)floor(Position() * (_MaxPosition() - _MinPosition()) + 1141 _MinPosition()) - 8.0f; 1142 frame.right = frame.left + fBarThickness + 7.0f; 1143 frame.bottom = frame.top + 17; 1144 } 1145 } else { 1146 if (Orientation() == B_HORIZONTAL) { 1147 frame.left = (float)floor(Position() * (_MaxPosition() - _MinPosition()) + 1148 _MinPosition()) - 6; 1149 frame.right = frame.left + 12.0f; 1150 frame.bottom = frame.bottom - 2.0f - 1151 (MinLimitLabel() || MaxLimitLabel() ? textHeight + 4.0f : 0.0f); 1152 frame.top = frame.bottom - 8.0f; 1153 } else { 1154 frame.left = floor((frame.Width() - fBarThickness) / 2.0f) - 3; 1155 frame.top = (float)floor(Position() * (_MaxPosition() - _MinPosition())) + 1156 _MinPosition() - 6.0f; 1157 frame.right = frame.left + 7; 1158 frame.bottom = frame.top + 12; 1159 } 1160 } 1161 1162 return frame; 1163 } 1164 1165 1166 void 1167 BSlider::SetFlags(uint32 flags) 1168 { 1169 BControl::SetFlags(flags); 1170 } 1171 1172 1173 void 1174 BSlider::SetResizingMode(uint32 mode) 1175 { 1176 BControl::SetResizingMode(mode); 1177 } 1178 1179 1180 void 1181 BSlider::GetPreferredSize(float* _width, float* _height) 1182 { 1183 font_height fontHeight; 1184 GetFontHeight(&fontHeight); 1185 1186 float width, height; 1187 int32 rows = 0; 1188 1189 if (Orientation() == B_HORIZONTAL) { 1190 width = Frame().Width(); 1191 height = 12.0f + fBarThickness; 1192 1193 float labelWidth = 0; 1194 if (Label()) { 1195 labelWidth = StringWidth(Label()); 1196 rows++; 1197 } 1198 1199 float minWidth = 0; 1200 if (MinLimitLabel()) 1201 minWidth = StringWidth(MinLimitLabel()); 1202 if (MaxLimitLabel()) { 1203 // some space between the labels 1204 if (MinLimitLabel()) 1205 minWidth += 8.0f; 1206 1207 minWidth += StringWidth(MaxLimitLabel()); 1208 } 1209 1210 if (minWidth > width) 1211 width = minWidth; 1212 if (labelWidth > width) 1213 width = labelWidth; 1214 if (width < 32.0f) 1215 width = 32.0f; 1216 1217 if (MinLimitLabel() || MaxLimitLabel()) 1218 rows++; 1219 1220 height += rows * ((float)ceil(fontHeight.ascent + fontHeight.descent) + 4.0f); 1221 } else { 1222 // B_VERTICAL 1223 width = 12.0f + fBarThickness; 1224 height = Frame().Height(); 1225 1226 // find largest label 1227 1228 float minWidth = 0; 1229 if (Label()) { 1230 minWidth = StringWidth(Label()); 1231 rows++; 1232 } 1233 if (MinLimitLabel()) { 1234 float width = StringWidth(MinLimitLabel()); 1235 if (width > minWidth) 1236 minWidth = width; 1237 rows++; 1238 } 1239 if (MaxLimitLabel()) { 1240 float width = StringWidth(MaxLimitLabel()); 1241 if (width > minWidth) 1242 minWidth = width; 1243 rows++; 1244 } 1245 1246 if (minWidth > width) 1247 width = minWidth; 1248 1249 float minHeight = 32.0f + rows 1250 * ((float)ceil(fontHeight.ascent + fontHeight.descent) + 4.0f); 1251 1252 if (Label() && MaxLimitLabel()) 1253 minHeight -= 4.0f; 1254 1255 if (minHeight > height) 1256 height = minHeight; 1257 } 1258 1259 if (_width) 1260 *_width = width; 1261 if (_height) 1262 *_height = height; 1263 } 1264 1265 1266 void 1267 BSlider::ResizeToPreferred() 1268 { 1269 BControl::ResizeToPreferred(); 1270 } 1271 1272 1273 status_t 1274 BSlider::Invoke(BMessage *msg) 1275 { 1276 return BControl::Invoke(msg); 1277 } 1278 1279 1280 BHandler* 1281 BSlider::ResolveSpecifier(BMessage *message, int32 index, 1282 BMessage *specifier, int32 command, 1283 const char *property) 1284 { 1285 return BControl::ResolveSpecifier(message, index, specifier, 1286 command, property); 1287 } 1288 1289 1290 status_t 1291 BSlider::GetSupportedSuites(BMessage *message) 1292 { 1293 return BControl::GetSupportedSuites(message); 1294 } 1295 1296 1297 void 1298 BSlider::SetModificationMessage(BMessage *message) 1299 { 1300 if (fModificationMessage) 1301 delete fModificationMessage; 1302 1303 fModificationMessage = message; 1304 } 1305 1306 1307 BMessage* 1308 BSlider::ModificationMessage() const 1309 { 1310 return fModificationMessage; 1311 } 1312 1313 1314 void 1315 BSlider::SetSnoozeAmount(int32 snoozeTime) 1316 { 1317 if (snoozeTime < 10000) 1318 snoozeTime = 10000; 1319 else if (snoozeTime > 1000000) 1320 snoozeTime = 1000000; 1321 1322 fSnoozeAmount = snoozeTime; 1323 } 1324 1325 1326 int32 1327 BSlider::SnoozeAmount() const 1328 { 1329 return fSnoozeAmount; 1330 } 1331 1332 1333 void 1334 BSlider::SetKeyIncrementValue(int32 increment_value) 1335 { 1336 fKeyIncrementValue = increment_value; 1337 } 1338 1339 1340 int32 1341 BSlider::KeyIncrementValue() const 1342 { 1343 return fKeyIncrementValue; 1344 } 1345 1346 1347 void 1348 BSlider::SetHashMarkCount(int32 hash_mark_count) 1349 { 1350 fHashMarkCount = hash_mark_count; 1351 Invalidate(); 1352 } 1353 1354 1355 int32 1356 BSlider::HashMarkCount() const 1357 { 1358 return fHashMarkCount; 1359 } 1360 1361 1362 void 1363 BSlider::SetHashMarks(hash_mark_location where) 1364 { 1365 fHashMarks = where; 1366 Invalidate(); 1367 } 1368 1369 1370 hash_mark_location 1371 BSlider::HashMarks() const 1372 { 1373 return fHashMarks; 1374 } 1375 1376 1377 void 1378 BSlider::SetStyle(thumb_style style) 1379 { 1380 fStyle = style; 1381 Invalidate(); 1382 } 1383 1384 1385 thumb_style 1386 BSlider::Style() const 1387 { 1388 return fStyle; 1389 } 1390 1391 1392 void 1393 BSlider::SetBarColor(rgb_color bar_color) 1394 { 1395 fBarColor = bar_color; 1396 Invalidate(); 1397 } 1398 1399 1400 rgb_color 1401 BSlider::BarColor() const 1402 { 1403 return fBarColor; 1404 } 1405 1406 1407 void 1408 BSlider::UseFillColor(bool use_fill, const rgb_color *bar_color) 1409 { 1410 fUseFillColor = use_fill; 1411 1412 if (use_fill && bar_color) 1413 fFillColor = *bar_color; 1414 1415 Invalidate(); 1416 } 1417 1418 1419 bool 1420 BSlider::FillColor(rgb_color *bar_color) const 1421 { 1422 if (bar_color && fUseFillColor) 1423 *bar_color = fFillColor; 1424 1425 return fUseFillColor; 1426 } 1427 1428 1429 BView* 1430 BSlider::OffscreenView() const 1431 { 1432 #if USE_OFF_SCREEN_VIEW 1433 return fOffScreenView; 1434 #else 1435 return (BView*)this; 1436 #endif 1437 } 1438 1439 1440 orientation 1441 BSlider::Orientation() const 1442 { 1443 return fOrientation; 1444 } 1445 1446 1447 void 1448 BSlider::SetOrientation(orientation posture) 1449 { 1450 fOrientation = posture; 1451 Invalidate(); 1452 } 1453 1454 1455 float 1456 BSlider::BarThickness() const 1457 { 1458 return fBarThickness; 1459 } 1460 1461 1462 void 1463 BSlider::SetBarThickness(float thickness) 1464 { 1465 if (thickness >= 1.0f) 1466 fBarThickness = thickness; 1467 } 1468 1469 1470 void 1471 BSlider::SetFont(const BFont *font, uint32 properties) 1472 { 1473 BControl::SetFont(font, properties); 1474 1475 #if USE_OFF_SCREEN_VIEW 1476 if (fOffScreenView && fOffScreenBits) { 1477 if (fOffScreenBits->Lock()) { 1478 fOffScreenView->SetFont(font, properties); 1479 fOffScreenBits->Unlock(); 1480 } 1481 } 1482 #endif 1483 } 1484 1485 1486 void 1487 BSlider::SetLimits(int32 minimum, int32 maximum) 1488 { 1489 if (minimum <= maximum) { 1490 fMinValue = minimum; 1491 fMaxValue = maximum; 1492 1493 int32 value = Value(); 1494 value = max_c(minimum, value); 1495 value = min_c(maximum, value); 1496 1497 if (value != Value()) { 1498 SetValue(value); 1499 } 1500 } 1501 } 1502 1503 1504 void 1505 BSlider::_DrawBlockThumb() 1506 { 1507 BRect frame = ThumbFrame(); 1508 BView *view = OffscreenView(); 1509 1510 rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR); 1511 rgb_color lighten2; 1512 rgb_color lighten1; 1513 rgb_color darken2; 1514 rgb_color darken3; 1515 rgb_color darkenmax; 1516 1517 if (IsEnabled()) { 1518 lighten2 = tint_color(no_tint, B_LIGHTEN_2_TINT); 1519 lighten1 = no_tint; 1520 darken2 = tint_color(no_tint, B_DARKEN_2_TINT); 1521 darken3 = tint_color(no_tint, B_DARKEN_3_TINT); 1522 darkenmax = tint_color(no_tint, B_DARKEN_MAX_TINT); 1523 } else { 1524 lighten2 = tint_color(no_tint, B_LIGHTEN_2_TINT); 1525 lighten1 = tint_color(no_tint, B_LIGHTEN_1_TINT); 1526 darken2 = tint_color(no_tint, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0); 1527 darken3 = tint_color(no_tint, B_DARKEN_1_TINT); 1528 darkenmax = tint_color(no_tint, B_DARKEN_3_TINT); 1529 } 1530 1531 // blank background for shadow 1532 // ToDo: this also draws over the hash marks (though it's not *that* noticeable) 1533 view->SetHighColor(no_tint); 1534 view->StrokeLine(BPoint(frame.left, frame.top), 1535 BPoint(frame.left, frame.top)); 1536 1537 BRect barFrame = BarFrame(); 1538 if (barFrame.right >= frame.right) { 1539 // leave out barFrame from shadow background clearing 1540 view->StrokeLine(BPoint(frame.right, frame.top), 1541 BPoint(frame.right, barFrame.top - 1.0f)); 1542 view->StrokeLine(BPoint(frame.right, barFrame.bottom + 1.0f), 1543 BPoint(frame.right, frame.bottom)); 1544 } else { 1545 view->StrokeLine(BPoint(frame.right, frame.top), 1546 BPoint(frame.right, frame.bottom)); 1547 } 1548 1549 view->StrokeLine(BPoint(frame.left, frame.bottom), 1550 BPoint(frame.right - 1.0f, frame.bottom)); 1551 view->StrokeLine(BPoint(frame.left, frame.bottom - 1.0f), 1552 BPoint(frame.left, frame.bottom - 1.0f)); 1553 view->StrokeLine(BPoint(frame.right - 1.0f, frame.top), 1554 BPoint(frame.right - 1.0f, frame.top)); 1555 1556 // Outline (top, left) 1557 view->SetHighColor(darken3); 1558 view->StrokeLine(BPoint(frame.left, frame.bottom - 2.0f), 1559 BPoint(frame.left, frame.top + 1.0f)); 1560 view->StrokeLine(BPoint(frame.left + 1.0f, frame.top), 1561 BPoint(frame.right - 2.0f, frame.top)); 1562 1563 // Shadow 1564 view->SetHighColor(0, 0, 0, IsEnabled() ? 100 : 50); 1565 view->SetDrawingMode(B_OP_ALPHA); 1566 view->StrokeLine(BPoint(frame.right, frame.top + 2.0f), 1567 BPoint(frame.right, frame.bottom - 1.0f)); 1568 view->StrokeLine(BPoint(frame.left + 2.0f, frame.bottom), 1569 BPoint(frame.right - 1.0f, frame.bottom)); 1570 1571 view->SetDrawingMode(B_OP_COPY); 1572 view->SetHighColor(darken3); 1573 view->StrokeLine(BPoint(frame.right - 1.0f, frame.bottom - 1.0f), 1574 BPoint(frame.right - 1.0f, frame.bottom - 1.0f)); 1575 1576 1577 // First bevel 1578 frame.InsetBy(1.0f, 1.0f); 1579 1580 view->SetHighColor(darkenmax); 1581 view->StrokeLine(BPoint(frame.left, frame.bottom), 1582 BPoint(frame.right - 1.0f, frame.bottom)); 1583 view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f), 1584 BPoint(frame.right, frame.top)); 1585 1586 view->SetHighColor(lighten2); 1587 view->StrokeLine(BPoint(frame.left, frame.top), 1588 BPoint(frame.left, frame.bottom - 1.0f)); 1589 view->StrokeLine(BPoint(frame.left + 1.0f, frame.top), 1590 BPoint(frame.right - 1.0f, frame.top)); 1591 1592 frame.InsetBy(1.0f, 1.0f); 1593 1594 view->FillRect(BRect(frame.left, frame.top, frame.right - 1.0f, frame.bottom - 1.0f)); 1595 1596 // Second bevel and center dots 1597 view->SetHighColor(darken2); 1598 view->StrokeLine(BPoint(frame.left, frame.bottom), 1599 BPoint(frame.right, frame.bottom)); 1600 view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f), 1601 BPoint(frame.right, frame.top)); 1602 1603 if (Orientation() == B_HORIZONTAL) { 1604 view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 2.0f), 1605 BPoint(frame.left + 6.0f, frame.top + 2.0f)); 1606 view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 4.0f), 1607 BPoint(frame.left + 6.0f, frame.top + 4.0f)); 1608 view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 6.0f), 1609 BPoint(frame.left + 6.0f, frame.top + 6.0f)); 1610 } else { 1611 view->StrokeLine(BPoint(frame.left + 2.0f, frame.top + 6.0f), 1612 BPoint(frame.left + 2.0f, frame.top + 6.0f)); 1613 view->StrokeLine(BPoint(frame.left + 4.0f, frame.top + 6.0f), 1614 BPoint(frame.left + 4.0f, frame.top + 6.0f)); 1615 view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 6.0f), 1616 BPoint(frame.left + 6.0f, frame.top + 6.0f)); 1617 } 1618 1619 frame.InsetBy(1.0f, 1.0f); 1620 1621 // Third bevel 1622 view->SetHighColor(lighten1); 1623 view->StrokeLine(BPoint(frame.left, frame.bottom), 1624 BPoint(frame.right, frame.bottom)); 1625 view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f), 1626 BPoint(frame.right, frame.top)); 1627 } 1628 1629 1630 void 1631 BSlider::_DrawTriangleThumb() 1632 { 1633 BRect frame = ThumbFrame(); 1634 BView *view = OffscreenView(); 1635 1636 rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR); 1637 rgb_color lightenmax; 1638 rgb_color lighten1; 1639 rgb_color darken2; 1640 rgb_color darken3; 1641 rgb_color darkenmax; 1642 1643 if (IsEnabled()) { 1644 lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT); 1645 lighten1 = no_tint; 1646 darken2 = tint_color(no_tint, B_DARKEN_2_TINT); 1647 darken3 = tint_color(no_tint, B_DARKEN_3_TINT); 1648 darkenmax = tint_color(no_tint, B_DARKEN_MAX_TINT); 1649 } else { 1650 lightenmax = tint_color(no_tint, B_LIGHTEN_2_TINT); 1651 lighten1 = tint_color(no_tint, B_LIGHTEN_1_TINT); 1652 darken2 = tint_color(no_tint, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0); 1653 darken3 = tint_color(no_tint, B_DARKEN_1_TINT); 1654 darkenmax = tint_color(no_tint, B_DARKEN_3_TINT); 1655 } 1656 1657 view->SetDrawingMode(B_OP_OVER); 1658 1659 if (Orientation() == B_HORIZONTAL) { 1660 view->SetHighColor(lighten1); 1661 view->FillTriangle(BPoint(frame.left + 1.0, frame.bottom - 2.0), 1662 BPoint(frame.left + 6.0, frame.top + 1.0), 1663 BPoint(frame.right - 1.0, frame.bottom - 2.0)); 1664 1665 view->SetHighColor(no_tint); 1666 view->StrokeLine(BPoint(frame.right - 2.0, frame.bottom - 2.0), 1667 BPoint(frame.left + 3.0, frame.bottom - 2.0)); 1668 1669 view->SetHighColor(darkenmax); 1670 view->StrokeLine(BPoint(frame.left, frame.bottom), 1671 BPoint(frame.right, frame.bottom)); 1672 view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0), 1673 BPoint(frame.left + 6.0, frame.top + 1.0)); 1674 1675 view->SetHighColor(darken2); 1676 view->StrokeLine(BPoint(frame.right - 1.0, frame.bottom - 1.0), 1677 BPoint(frame.left + 1.0, frame.bottom - 1.0)); 1678 view->SetHighColor(darken3); 1679 view->StrokeLine(BPoint(frame.left, frame.bottom - 1.0), 1680 BPoint(frame.left + 5.0, frame.top + 2.0)); 1681 1682 view->SetHighColor(lightenmax); 1683 view->StrokeLine(BPoint(frame.left + 2.0, frame.bottom - 2.0), 1684 BPoint(frame.left + 6.0, frame.top + 2.0)); 1685 } else { 1686 view->SetHighColor(lighten1); 1687 view->FillTriangle(BPoint(frame.left + 1.0f, frame.top), 1688 BPoint(frame.left + 7.0f, frame.top + 6.0f), 1689 BPoint(frame.left + 1.0f, frame.bottom)); 1690 1691 view->SetHighColor(darkenmax); 1692 view->StrokeLine(BPoint(frame.left, frame.top + 1), 1693 BPoint(frame.left, frame.bottom)); 1694 view->StrokeLine(BPoint(frame.left + 1.0f, frame.bottom), 1695 BPoint(frame.left + 7.0f, frame.top + 6.0f)); 1696 1697 view->SetHighColor(darken2); 1698 view->StrokeLine(BPoint(frame.left, frame.top), 1699 BPoint(frame.left, frame.bottom - 1)); 1700 view->StrokeLine(BPoint(frame.left + 1.0f, frame.top), 1701 BPoint(frame.left + 6.0f, frame.top + 5.0f)); 1702 1703 view->SetHighColor(no_tint); 1704 view->StrokeLine(BPoint(frame.left + 1.0f, frame.top + 2.0f), 1705 BPoint(frame.left + 1.0f, frame.bottom - 1.0f)); 1706 view->StrokeLine(BPoint(frame.left + 2.0f, frame.bottom - 2.0f), 1707 BPoint(frame.left + 6.0f, frame.top + 6.0f)); 1708 } 1709 1710 view->SetDrawingMode(B_OP_COPY); 1711 } 1712 1713 1714 BPoint 1715 BSlider::_Location() const 1716 { 1717 return fLocation; 1718 } 1719 1720 1721 void 1722 BSlider::_SetLocation(BPoint p) 1723 { 1724 fLocation = p; 1725 } 1726 1727 1728 float 1729 BSlider::_MinPosition() const 1730 { 1731 if (fOrientation == B_HORIZONTAL) 1732 return BarFrame().left + 1.0f; 1733 1734 return BarFrame().bottom - 1.0f; 1735 } 1736 1737 1738 float 1739 BSlider::_MaxPosition() const 1740 { 1741 if (fOrientation == B_HORIZONTAL) 1742 return BarFrame().right - 1.0f; 1743 1744 return BarFrame().top + 1.0f; 1745 } 1746 1747 1748 void BSlider::_ReservedSlider5() {} 1749 void BSlider::_ReservedSlider6() {} 1750 void BSlider::_ReservedSlider7() {} 1751 void BSlider::_ReservedSlider8() {} 1752 void BSlider::_ReservedSlider9() {} 1753 void BSlider::_ReservedSlider10() {} 1754 void BSlider::_ReservedSlider11() {} 1755 void BSlider::_ReservedSlider12() {} 1756 1757 1758 BSlider & 1759 BSlider::operator=(const BSlider &) 1760 { 1761 return *this; 1762 } 1763 1764 1765 // #pragma mark - R4.5 compatibility 1766 1767 1768 #if __GNUC__ < 3 1769 1770 extern "C" 1771 void _ReservedSlider4__7BSlider(BSlider *slider, int32 minimum, int32 maximum) 1772 { 1773 slider->BSlider::SetLimits(minimum, maximum); 1774 } 1775 1776 extern "C" void _ReservedSlider1__7BSlider() {} 1777 extern "C" void _ReservedSlider2__7BSlider() {} 1778 extern "C" void _ReservedSlider3__7BSlider() {} 1779 1780 #endif // __GNUC__ < 3 1781