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