alvin_

Slider.cpp

Dec 4th, 2013
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 103.78 KB | None | 0 0
  1. /*
  2.  * Copyright 2001-2013 Haiku, Inc.
  3.  * Distributed under the terms of the MIT License.
  4.  *
  5.  * Authors:
  6.  *      Stephan Aßmus <[email protected]>
  7.  *      Axel Dörfler, [email protected]
  8.  *      Marc Flerackers ([email protected])
  9.  */
  10.  
  11.  
  12. #include <Slider.h>
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17.  
  18. #include <Bitmap.h>
  19. #include <ControlLook.h>
  20. #include <Errors.h>
  21. #include <LayoutUtils.h>
  22. #include <Message.h>
  23. #include <Region.h>
  24. #include <String.h>
  25. #include <Window.h>
  26.  
  27. #include <binary_compatibility/Interface.h>
  28.  
  29.  
  30. #define USE_OFF_SCREEN_VIEW 0
  31.  
  32.  
  33. BSlider::BSlider(BRect frame, const char* name, const char* label,
  34.             BMessage* message, int32 minValue, int32 maxValue,
  35.             thumb_style thumbType, uint32 resizingMode, uint32 flags)
  36.     : BControl(frame, name, label, message, resizingMode, flags),
  37.     fModificationMessage(NULL),
  38.     fSnoozeAmount(20000),
  39.  
  40.     fMinLimitLabel(NULL),
  41.     fMaxLimitLabel(NULL),
  42.  
  43.     fMinValue(minValue),
  44.     fMaxValue(maxValue),
  45.     fKeyIncrementValue(1),
  46.  
  47.     fHashMarkCount(0),
  48.     fHashMarks(B_HASH_MARKS_NONE),
  49.  
  50.     fStyle(thumbType),
  51.  
  52.     fOrientation(B_HORIZONTAL),
  53.     fBarThickness(6.0)
  54. {
  55.     _InitBarColor();
  56.  
  57.     _InitObject();
  58.     SetValue(0);
  59. }
  60.  
  61.  
  62. BSlider::BSlider(BRect frame, const char *name, const char *label,
  63.             BMessage *message, int32 minValue, int32 maxValue,
  64.             orientation posture, thumb_style thumbType, uint32 resizingMode,
  65.             uint32 flags)
  66.     : BControl(frame, name, label, message, resizingMode, flags),
  67.     fModificationMessage(NULL),
  68.     fSnoozeAmount(20000),
  69.  
  70.     fMinLimitLabel(NULL),
  71.     fMaxLimitLabel(NULL),
  72.  
  73.     fMinValue(minValue),
  74.     fMaxValue(maxValue),
  75.     fKeyIncrementValue(1),
  76.  
  77.     fHashMarkCount(0),
  78.     fHashMarks(B_HASH_MARKS_NONE),
  79.  
  80.     fStyle(thumbType),
  81.  
  82.     fOrientation(posture),
  83.     fBarThickness(6.0)
  84. {
  85.     _InitBarColor();
  86.  
  87.     _InitObject();
  88.     SetValue(0);
  89. }
  90.  
  91.  
  92. BSlider::BSlider(const char *name, const char *label, BMessage *message,
  93.             int32 minValue, int32 maxValue, orientation posture,
  94.             thumb_style thumbType, uint32 flags)
  95.     : BControl(name, label, message, flags),
  96.     fModificationMessage(NULL),
  97.     fSnoozeAmount(20000),
  98.  
  99.     fMinLimitLabel(NULL),
  100.     fMaxLimitLabel(NULL),
  101.  
  102.     fMinValue(minValue),
  103.     fMaxValue(maxValue),
  104.     fKeyIncrementValue(1),
  105.  
  106.     fHashMarkCount(0),
  107.     fHashMarks(B_HASH_MARKS_NONE),
  108.  
  109.     fStyle(thumbType),
  110.  
  111.     fOrientation(posture),
  112.     fBarThickness(6.0)
  113. {
  114.     _InitBarColor();
  115.  
  116.     _InitObject();
  117.     SetValue(0);
  118. }
  119.  
  120.  
  121. BSlider::BSlider(BMessage *archive)
  122.     : BControl(archive)
  123. {
  124.     fModificationMessage = NULL;
  125.  
  126.     if (archive->HasMessage("_mod_msg")) {
  127.         BMessage* message = new BMessage;
  128.  
  129.         archive->FindMessage("_mod_msg", message);
  130.  
  131.         SetModificationMessage(message);
  132.     }
  133.  
  134.     if (archive->FindInt32("_sdelay", &fSnoozeAmount) != B_OK)
  135.         SetSnoozeAmount(20000);
  136.  
  137.     rgb_color color;
  138.     if (archive->FindInt32("_fcolor", (int32 *)&color) == B_OK)
  139.         UseFillColor(true, &color);
  140.     else
  141.         UseFillColor(false);
  142.  
  143.     int32 orient;
  144.     if (archive->FindInt32("_orient", &orient) == B_OK)
  145.         fOrientation = (orientation)orient;
  146.     else
  147.         fOrientation = B_HORIZONTAL;
  148.  
  149.     fMinLimitLabel = NULL;
  150.     fMaxLimitLabel = NULL;
  151.  
  152.     const char* minlbl = NULL;
  153.     const char* maxlbl = NULL;
  154.  
  155.     archive->FindString("_minlbl", &minlbl);
  156.     archive->FindString("_maxlbl", &maxlbl);
  157.  
  158.     SetLimitLabels(minlbl, maxlbl);
  159.  
  160.     if (archive->FindInt32("_min", &fMinValue) != B_OK)
  161.         fMinValue = 0;
  162.  
  163.     if (archive->FindInt32("_max", &fMaxValue) != B_OK)
  164.         fMaxValue = 100;
  165.  
  166.     if (archive->FindInt32("_incrementvalue", &fKeyIncrementValue) != B_OK)
  167.         fKeyIncrementValue = 1;
  168.  
  169.     if (archive->FindInt32("_hashcount", &fHashMarkCount) != B_OK)
  170.         fHashMarkCount = 11;
  171.  
  172.     int16 hashloc;
  173.     if (archive->FindInt16("_hashloc", &hashloc) == B_OK)
  174.         fHashMarks = (hash_mark_location)hashloc;
  175.     else
  176.         fHashMarks = B_HASH_MARKS_NONE;
  177.  
  178.     int16 sstyle;
  179.     if (archive->FindInt16("_sstyle", &sstyle) == B_OK)
  180.         fStyle = (thumb_style)sstyle;
  181.     else
  182.         fStyle = B_BLOCK_THUMB;
  183.  
  184.     if (archive->FindInt32("_bcolor", (int32 *)&color) != B_OK)
  185.         color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_4_TINT);
  186.     SetBarColor(color);
  187.  
  188.     float bthickness;
  189.     if (archive->FindFloat("_bthickness", &bthickness) == B_OK)
  190.         fBarThickness = bthickness;
  191.     else
  192.         fBarThickness = 6.0f;
  193.  
  194.     _InitObject();
  195. }
  196.  
  197.  
  198. BSlider::~BSlider()
  199. {
  200. #if USE_OFF_SCREEN_VIEW
  201.     delete fOffScreenBits;
  202. #endif
  203.  
  204.     delete fModificationMessage;
  205.     free(fMinLimitLabel);
  206.     free(fMaxLimitLabel);
  207. }
  208.  
  209.  
  210. void
  211. BSlider::_InitBarColor()
  212. {
  213.     if (be_control_look != NULL) {
  214.         SetBarColor(be_control_look->SliderBarColor(
  215.             ui_color(B_PANEL_BACKGROUND_COLOR)));
  216.     } else {
  217.         SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
  218.             B_DARKEN_4_TINT));
  219.     }
  220.  
  221.     UseFillColor(false, NULL);
  222. }
  223.  
  224.  
  225. void
  226. BSlider::_InitObject()
  227. {
  228.     fLocation.x = 0;
  229.     fLocation.y = 0;
  230.     fInitialLocation.x = 0;
  231.     fInitialLocation.y = 0;
  232.  
  233. #if USE_OFF_SCREEN_VIEW
  234.     fOffScreenBits = NULL;
  235.     fOffScreenView = NULL;
  236. #endif
  237.  
  238.     fUpdateText = NULL;
  239.     fMinSize.Set(-1, -1);
  240.     fMaxUpdateTextWidth = -1.0;
  241. }
  242.  
  243.  
  244. BArchivable*
  245. BSlider::Instantiate(BMessage *archive)
  246. {
  247.     if (validate_instantiation(archive, "BSlider"))
  248.         return new BSlider(archive);
  249.  
  250.     return NULL;
  251. }
  252.  
  253.  
  254. status_t
  255. BSlider::Archive(BMessage *archive, bool deep) const
  256. {
  257.     status_t ret = BControl::Archive(archive, deep);
  258.  
  259.     if (ModificationMessage() && ret == B_OK)
  260.         ret = archive->AddMessage("_mod_msg", ModificationMessage());
  261.  
  262.     if (ret == B_OK)
  263.         ret = archive->AddInt32("_sdelay", fSnoozeAmount);
  264.     if (ret == B_OK)
  265.         ret = archive->AddInt32("_bcolor", (const uint32 &)fBarColor);
  266.  
  267.     if (FillColor(NULL) && ret == B_OK)
  268.         ret = archive->AddInt32("_fcolor", (const uint32 &)fFillColor);
  269.  
  270.     if (ret == B_OK && fMinLimitLabel)
  271.         ret = archive->AddString("_minlbl", fMinLimitLabel);
  272.  
  273.     if (ret == B_OK && fMaxLimitLabel)
  274.         ret = archive->AddString("_maxlbl", fMaxLimitLabel);
  275.  
  276.     if (ret == B_OK)
  277.         ret = archive->AddInt32("_min", fMinValue);
  278.     if (ret == B_OK)
  279.         ret = archive->AddInt32("_max", fMaxValue);
  280.  
  281.     if (ret == B_OK)
  282.         ret = archive->AddInt32("_incrementvalue", fKeyIncrementValue);
  283.     if (ret == B_OK)
  284.         ret = archive->AddInt32("_hashcount", fHashMarkCount);
  285.     if (ret == B_OK)
  286.         ret = archive->AddInt16("_hashloc", fHashMarks);
  287.     if (ret == B_OK)
  288.         ret = archive->AddInt16("_sstyle", fStyle);
  289.     if (ret == B_OK)
  290.         ret = archive->AddInt32("_orient", fOrientation);
  291.     if (ret == B_OK)
  292.         ret = archive->AddFloat("_bthickness", fBarThickness);
  293.  
  294.     return ret;
  295. }
  296.  
  297.  
  298. status_t
  299. BSlider::Perform(perform_code code, void* _data)
  300. {
  301.     switch (code) {
  302.         case PERFORM_CODE_MIN_SIZE:
  303.             ((perform_data_min_size*)_data)->return_value
  304.                 = BSlider::MinSize();
  305.             return B_OK;
  306.         case PERFORM_CODE_MAX_SIZE:
  307.             ((perform_data_max_size*)_data)->return_value
  308.                 = BSlider::MaxSize();
  309.             return B_OK;
  310.         case PERFORM_CODE_PREFERRED_SIZE:
  311.             ((perform_data_preferred_size*)_data)->return_value
  312.                 = BSlider::PreferredSize();
  313.             return B_OK;
  314.         case PERFORM_CODE_LAYOUT_ALIGNMENT:
  315.             ((perform_data_layout_alignment*)_data)->return_value
  316.                 = BSlider::LayoutAlignment();
  317.             return B_OK;
  318.         case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
  319.             ((perform_data_has_height_for_width*)_data)->return_value
  320.                 = BSlider::HasHeightForWidth();
  321.             return B_OK;
  322.         case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
  323.         {
  324.             perform_data_get_height_for_width* data
  325.                 = (perform_data_get_height_for_width*)_data;
  326.             BSlider::GetHeightForWidth(data->width, &data->min, &data->max,
  327.                 &data->preferred);
  328.             return B_OK;
  329.         }
  330.         case PERFORM_CODE_SET_LAYOUT:
  331.         {
  332.             perform_data_set_layout* data = (perform_data_set_layout*)_data;
  333.             BSlider::SetLayout(data->layout);
  334.             return B_OK;
  335.         }
  336.         case PERFORM_CODE_LAYOUT_INVALIDATED:
  337.         {
  338.             perform_data_layout_invalidated* data
  339.                 = (perform_data_layout_invalidated*)_data;
  340.             BSlider::LayoutInvalidated(data->descendants);
  341.             return B_OK;
  342.         }
  343.         case PERFORM_CODE_DO_LAYOUT:
  344.         {
  345.             BSlider::DoLayout();
  346.             return B_OK;
  347.         }
  348.     }
  349.  
  350.     return BControl::Perform(code, _data);
  351. }
  352.  
  353.  
  354. void
  355. BSlider::WindowActivated(bool state)
  356. {
  357.     BControl::WindowActivated(state);
  358. }
  359.  
  360.  
  361. void
  362. BSlider::AttachedToWindow()
  363. {
  364.     ResizeToPreferred();
  365.  
  366. #if USE_OFF_SCREEN_VIEW
  367.     BRect bounds(Bounds());
  368.  
  369.     if (!fOffScreenView) {
  370.         fOffScreenView = new BView(bounds, "", B_FOLLOW_ALL, B_WILL_DRAW);
  371.  
  372.         BFont font;
  373.         GetFont(&font);
  374.         fOffScreenView->SetFont(&font);
  375.     }
  376.  
  377.     if (!fOffScreenBits) {
  378.         fOffScreenBits = new BBitmap(bounds, B_RGBA32, true, false);
  379.  
  380.         if (fOffScreenBits && fOffScreenView)
  381.             fOffScreenBits->AddChild(fOffScreenView);
  382.  
  383.     } else if (fOffScreenView)
  384.         fOffScreenBits->AddChild(fOffScreenView);
  385. #endif // USE_OFF_SCREEN_VIEW
  386.  
  387.     BControl::AttachedToWindow();
  388.  
  389.     BView* view = OffscreenView();
  390.     if (view && view->LockLooper()) {
  391.         view->SetViewColor(B_TRANSPARENT_COLOR);
  392.         view->SetLowColor(LowColor());
  393.         view->UnlockLooper();
  394.     }
  395.  
  396.     int32 value = Value();
  397.     SetValue(value);
  398.         // makes sure the value is within valid bounds
  399.     _SetLocationForValue(Value());
  400.         // makes sure the location is correct
  401.     UpdateTextChanged();
  402. }
  403.  
  404.  
  405. void
  406. BSlider::AllAttached()
  407. {
  408.     BControl::AllAttached();
  409. }
  410.  
  411.  
  412. void
  413. BSlider::AllDetached()
  414. {
  415.     BControl::AllDetached();
  416. }
  417.  
  418.  
  419. void
  420. BSlider::DetachedFromWindow()
  421. {
  422.     BControl::DetachedFromWindow();
  423.  
  424. #if USE_OFF_SCREEN_VIEW
  425.     if (fOffScreenBits) {
  426.         delete fOffScreenBits;
  427.         fOffScreenBits = NULL;
  428.         fOffScreenView = NULL;
  429.     }
  430. #endif
  431. }
  432.  
  433.  
  434. void
  435. BSlider::MessageReceived(BMessage *msg)
  436. {
  437.     BControl::MessageReceived(msg);
  438. }
  439.  
  440.  
  441. void
  442. BSlider::FrameMoved(BPoint new_position)
  443. {
  444.     BControl::FrameMoved(new_position);
  445. }
  446.  
  447.  
  448. void
  449. BSlider::FrameResized(float w,float h)
  450. {
  451.     BControl::FrameResized(w, h);
  452.  
  453.     BRect bounds(Bounds());
  454.  
  455.     if (bounds.right <= 0.0f || bounds.bottom <= 0.0f)
  456.         return;
  457.  
  458. #if USE_OFF_SCREEN_VIEW
  459.     if (fOffScreenBits) {
  460.         fOffScreenBits->RemoveChild(fOffScreenView);
  461.         delete fOffScreenBits;
  462.  
  463.         fOffScreenView->ResizeTo(bounds.Width(), bounds.Height());
  464.  
  465.         fOffScreenBits = new BBitmap(Bounds(), B_RGBA32, true, false);
  466.         fOffScreenBits->AddChild(fOffScreenView);
  467.     }
  468. #endif
  469.  
  470.     Invalidate();
  471. }
  472.  
  473.  
  474. void
  475. BSlider::KeyDown(const char *bytes, int32 numBytes)
  476. {
  477.     if (!IsEnabled() || IsHidden())
  478.         return;
  479.  
  480.     int32 newValue = Value();
  481.  
  482.     switch (bytes[0]) {
  483.         case B_LEFT_ARROW:
  484.         case B_DOWN_ARROW:
  485.             newValue -= KeyIncrementValue();
  486.             break;
  487.  
  488.         case B_RIGHT_ARROW:
  489.         case B_UP_ARROW:
  490.             newValue += KeyIncrementValue();
  491.             break;
  492.  
  493.         case B_HOME:
  494.             newValue = fMinValue;
  495.             break;
  496.         case B_END:
  497.             newValue = fMaxValue;
  498.             break;
  499.  
  500.         default:
  501.             BControl::KeyDown(bytes, numBytes);
  502.             return;
  503.     }
  504.  
  505.     if (newValue < fMinValue)
  506.         newValue = fMinValue;
  507.     if (newValue > fMaxValue)
  508.         newValue = fMaxValue;
  509.  
  510.     if (newValue != Value()) {
  511.         fInitialLocation = _Location();
  512.         SetValue(newValue);
  513.         InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
  514.     }
  515. }
  516.  
  517. void
  518. BSlider::KeyUp(const char *bytes, int32 numBytes)
  519. {
  520.     if (fInitialLocation != _Location()) {
  521.         // The last KeyDown event triggered the modification message or no
  522.         // notification at all, we may also have sent the modification message
  523.         // continually while the user kept pressing the key. In either case,
  524.         // finish with the final message to make the behavior consistent with
  525.         // changing the value by mouse.
  526.         Invoke();
  527.     }
  528. }
  529.  
  530.  
  531. /*!
  532.     Makes sure the \a point is within valid bounds.
  533.     Returns \c true if the relevant coordinate (depending on the orientation
  534.     of the slider) differs from \a comparePoint.
  535. */
  536. bool
  537. BSlider::_ConstrainPoint(BPoint& point, BPoint comparePoint) const
  538. {
  539.     if (fOrientation == B_HORIZONTAL) {
  540.         if (point.x != comparePoint.x) {
  541.             if (point.x < _MinPosition())
  542.                 point.x = _MinPosition();
  543.             else if (point.x > _MaxPosition())
  544.                 point.x = _MaxPosition();
  545.  
  546.             return true;
  547.         }
  548.     } else {
  549.         if (point.y != comparePoint.y) {
  550.             if (point.y > _MinPosition())
  551.                 point.y = _MinPosition();
  552.             else if (point.y < _MaxPosition())
  553.                 point.y = _MaxPosition();
  554.  
  555.             return true;
  556.         }
  557.     }
  558.  
  559.     return false;
  560. }
  561.  
  562.  
  563. void
  564. BSlider::MouseDown(BPoint point)
  565. {
  566.     if (!IsEnabled())
  567.         return;
  568.  
  569.     if (BarFrame().Contains(point) || ThumbFrame().Contains(point))
  570.         fInitialLocation = _Location();
  571.  
  572.     uint32 buttons;
  573.     GetMouse(&point, &buttons, true);
  574.  
  575.     _ConstrainPoint(point, fInitialLocation);
  576.     SetValue(ValueForPoint(point));
  577.  
  578.     if (_Location() != fInitialLocation)
  579.         InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
  580.  
  581.     if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
  582.         SetTracking(true);
  583.         SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
  584.     } else {
  585.         // synchronous mouse tracking
  586.         BPoint prevPoint;
  587.  
  588.         while (buttons) {
  589.             prevPoint = point;
  590.  
  591.             snooze(SnoozeAmount());
  592.             GetMouse(&point, &buttons, true);
  593.  
  594.             if (_ConstrainPoint(point, prevPoint)) {
  595.                 int32 value = ValueForPoint(point);
  596.                 if (value != Value()) {
  597.                     SetValue(value);
  598.                     InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
  599.                 }
  600.             }
  601.         }
  602.         if (_Location() != fInitialLocation)
  603.             Invoke();
  604.     }
  605. }
  606.  
  607.  
  608. void
  609. BSlider::MouseUp(BPoint point)
  610. {
  611.     if (IsTracking()) {
  612.         if (_Location() != fInitialLocation)
  613.             Invoke();
  614.  
  615.         SetTracking(false);
  616.     } else
  617.         BControl::MouseUp(point);
  618. }
  619.  
  620.  
  621. void
  622. BSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
  623. {
  624.     if (IsTracking()) {
  625.         if (_ConstrainPoint(point, _Location())) {
  626.             int32 value = ValueForPoint(point);
  627.             if (value != Value()) {
  628.                 SetValue(value);
  629.                 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
  630.             }
  631.         }
  632.     } else
  633.         BControl::MouseMoved(point, transit, message);
  634. }
  635.  
  636.  
  637. void
  638. BSlider::Pulse()
  639. {
  640.     BControl::Pulse();
  641. }
  642.  
  643.  
  644. void
  645. BSlider::SetLabel(const char *label)
  646. {
  647.     BControl::SetLabel(label);
  648. }
  649.  
  650.  
  651. void
  652. BSlider::SetLimitLabels(const char *minLabel, const char *maxLabel)
  653. {
  654.     free(fMinLimitLabel);
  655.     fMinLimitLabel = minLabel ? strdup(minLabel) : NULL;
  656.  
  657.     free(fMaxLimitLabel);
  658.     fMaxLimitLabel = maxLabel ? strdup(maxLabel) : NULL;
  659.  
  660.     InvalidateLayout();
  661.  
  662.     // TODO: This is for backwards compatibility and should
  663.     // probably be removed when breaking binary compatiblity.
  664.     // Applications like our own Mouse rely on this behavior.
  665.     if ((Flags() & B_SUPPORTS_LAYOUT) == 0)
  666.         ResizeToPreferred();
  667.  
  668.     Invalidate();
  669. }
  670.  
  671.  
  672. const char*
  673. BSlider::MinLimitLabel() const
  674. {
  675.     return fMinLimitLabel;
  676. }
  677.  
  678.  
  679. const char*
  680. BSlider::MaxLimitLabel() const
  681. {
  682.     return fMaxLimitLabel;
  683. }
  684.  
  685.  
  686. void
  687. BSlider::SetValue(int32 value)
  688. {
  689.     if (value < fMinValue)
  690.         value = fMinValue;
  691.     if (value > fMaxValue)
  692.         value = fMaxValue;
  693.  
  694.     if (value == Value())
  695.         return;
  696.  
  697.     _SetLocationForValue(value);
  698.  
  699.     BRect oldThumbFrame = ThumbFrame();
  700.  
  701.     // While it would be enough to do this dependent on fUseFillColor,
  702.     // that doesn't work out if DrawBar() has been overridden by a sub class
  703.     if (fOrientation == B_HORIZONTAL)
  704.         oldThumbFrame.top = BarFrame().top;
  705.     else
  706.         oldThumbFrame.left = BarFrame().left;
  707.  
  708.     BControl::SetValueNoUpdate(value);
  709.     BRect invalid = oldThumbFrame | ThumbFrame();
  710.  
  711.     if (Style() == B_TRIANGLE_THUMB) {
  712.         // 1) We need to take care of pixels touched because of anti-aliasing.
  713.         // 2) We need to update the region with the focus mark as well. (A
  714.         // method BSlider::FocusMarkFrame() would be nice as well.)
  715.         if (fOrientation == B_HORIZONTAL) {
  716.             if (IsFocus())
  717.                 invalid.bottom += 2;
  718.             invalid.InsetBy(-1, 0);
  719.         } else {
  720.             if (IsFocus())
  721.                 invalid.left -= 2;
  722.             invalid.InsetBy(0, -1);
  723.         }
  724.     }
  725.  
  726.     Invalidate(invalid);
  727.  
  728.     UpdateTextChanged();
  729. }
  730.  
  731.  
  732. int32
  733. BSlider::ValueForPoint(BPoint location) const
  734. {
  735.     float min;
  736.     float max;
  737.     float position;
  738.     if (fOrientation == B_HORIZONTAL) {
  739.         min = _MinPosition();
  740.         max = _MaxPosition();
  741.         position = location.x;
  742.     } else {
  743.         max = _MinPosition();
  744.         min = _MaxPosition();
  745.         position = min + (max - location.y);
  746.     }
  747.  
  748.     if (position < min)
  749.         position = min;
  750.     if (position > max)
  751.         position = max;
  752.  
  753.     return (int32)roundf(((position - min) * (fMaxValue - fMinValue) / (max - min)) + fMinValue);
  754. }
  755.  
  756.  
  757. void
  758. BSlider::SetPosition(float position)
  759. {
  760.     if (position <= 0.0f)
  761.         SetValue(fMinValue);
  762.     else if (position >= 1.0f)
  763.         SetValue(fMaxValue);
  764.     else
  765.         SetValue((int32)(position * (fMaxValue - fMinValue) + fMinValue));
  766. }
  767.  
  768.  
  769. float
  770. BSlider::Position() const
  771. {
  772.     float range = (float)(fMaxValue - fMinValue);
  773.     if (range == 0.0f)
  774.         range = 1.0f;
  775.  
  776.     return (float)(Value() - fMinValue) / range;
  777. }
  778.  
  779.  
  780. void
  781. BSlider::SetEnabled(bool on)
  782. {
  783.     BControl::SetEnabled(on);
  784. }
  785.  
  786.  
  787. void
  788. BSlider::GetLimits(int32 *minimum, int32 *maximum) const
  789. {
  790.     if (minimum != NULL)
  791.         *minimum = fMinValue;
  792.     if (maximum != NULL)
  793.         *maximum = fMaxValue;
  794. }
  795.  
  796.  
  797. // #pragma mark - drawing
  798.  
  799.  
  800. void
  801. BSlider::Draw(BRect updateRect)
  802. {
  803.     // clear out background
  804.     BRegion background(updateRect);
  805.     background.Exclude(BarFrame());
  806.     bool drawBackground = true;
  807.     if (Parent() && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) {
  808.         // This view is embedded somewhere, most likely the Tracker Desktop
  809.         // shelf.
  810.         drawBackground = false;
  811.     }
  812.  
  813. #if USE_OFF_SCREEN_VIEW
  814.     if (!fOffScreenBits)
  815.         return;
  816.  
  817.     if (fOffScreenBits->Lock()) {
  818.         fOffScreenView->SetViewColor(ViewColor());
  819.         fOffScreenView->SetLowColor(LowColor());
  820. #endif
  821.  
  822.         if (drawBackground && background.Frame().IsValid())
  823.             OffscreenView()->FillRegion(&background, B_SOLID_LOW);
  824.  
  825. #if USE_OFF_SCREEN_VIEW
  826.         fOffScreenView->Sync();
  827.         fOffScreenBits->Unlock();
  828.     }
  829. #endif
  830.  
  831.     DrawSlider();
  832.     DrawEllipse();
  833. }
  834.  
  835.  
  836. void
  837. BSlider::DrawSlider()
  838. {
  839.     if (LockLooper()) {
  840. #if USE_OFF_SCREEN_VIEW
  841.         if (!fOffScreenBits)
  842.             return;
  843.         if (fOffScreenBits->Lock()) {
  844. #endif
  845.             //DrawBar();
  846.             //DrawHashMarks();
  847.             //DrawThumb();
  848.             //DrawFocusMark();
  849.             //DrawText();
  850.            
  851. #if USE_OFF_SCREEN_VIEW
  852.             fOffScreenView->Sync();
  853.             fOffScreenBits->Unlock();
  854.  
  855.             DrawBitmap(fOffScreenBits, B_ORIGIN);
  856.         }
  857. #endif
  858.         UnlockLooper();
  859.     }
  860. }
  861.  
  862. void
  863. BSlider::DrawEllipse()
  864. {
  865.     StrokeEllipse(BRect(1,1,27,27), B_SOLID_HIGH);
  866.     SetHighColor(150,150,150,255);
  867.     FillEllipse(BRect(1,1,27,27), B_SOLID_HIGH);
  868.     SetHighColor(100,100,100,255);
  869.     FillEllipse(BRect(4,4,24,24), B_SOLID_HIGH);
  870.     StrokeLine(BPoint(26/2 + 1, 26/2 + 1),
  871.                     BPoint(26/2 - 26/4 - 1, 26/2 + 26/4 + 1), B_SOLID_HIGH);
  872.     StrokeLine(BPoint(26/2 + 1, 26/2 + 1),
  873.                     BPoint(26/2 + 26/4 + 1, 26/2 + 26/4 + 1), B_SOLID_HIGH);
  874. }
  875.  
  876.  
  877. void
  878. BSlider::DrawBar()
  879. {
  880.     BRect frame = BarFrame();
  881.     BView *view = OffscreenView();
  882.  
  883.     if (be_control_look != NULL) {
  884.         uint32 flags = be_control_look->Flags(this);
  885.         rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
  886.         rgb_color rightFillColor = fBarColor;
  887.         rgb_color leftFillColor = fUseFillColor ? fFillColor : fBarColor;
  888.         be_control_look->DrawSliderBar(view, frame, frame, base, leftFillColor,
  889.             rightFillColor, Position(), flags, fOrientation);
  890.         return;
  891.     }
  892.  
  893.     rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
  894.     rgb_color lightenmax;
  895.     rgb_color darken1;
  896.     rgb_color darken2;
  897.     rgb_color darkenmax;
  898.  
  899.     rgb_color barColor;
  900.     rgb_color fillColor;
  901.  
  902.     if (IsEnabled()) {
  903.         lightenmax  = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
  904.         darken1     = tint_color(no_tint, B_DARKEN_1_TINT);
  905.         darken2     = tint_color(no_tint, B_DARKEN_2_TINT);
  906.         darkenmax   = tint_color(no_tint, B_DARKEN_MAX_TINT);
  907.         barColor    = fBarColor;
  908.         fillColor   = fFillColor;
  909.     } else {
  910.         lightenmax  = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
  911.         darken1     = no_tint;
  912.         darken2     = tint_color(no_tint, B_DARKEN_1_TINT);
  913.         darkenmax   = tint_color(no_tint, B_DARKEN_3_TINT);
  914.  
  915.         barColor.red    = (fBarColor.red + no_tint.red) / 2;
  916.         barColor.green  = (fBarColor.green + no_tint.green) / 2;
  917.         barColor.blue   = (fBarColor.blue + no_tint.blue) / 2;
  918.         barColor.alpha  = 255;
  919.  
  920.         fillColor.red   = (fFillColor.red + no_tint.red) / 2;
  921.         fillColor.green = (fFillColor.green + no_tint.green) / 2;
  922.         fillColor.blue  = (fFillColor.blue + no_tint.blue) / 2;
  923.         fillColor.alpha = 255;
  924.     }
  925.  
  926.     // exclude the block thumb from the bar filling
  927.  
  928.     BRect lowerFrame = frame.InsetByCopy(1, 1);
  929.     lowerFrame.top++;
  930.     lowerFrame.left++;
  931.     BRect upperFrame = lowerFrame;
  932.     BRect thumbFrame;
  933.  
  934.     if (Style() == B_BLOCK_THUMB) {
  935.         thumbFrame = ThumbFrame();
  936.  
  937.         if (fOrientation == B_HORIZONTAL) {
  938.             lowerFrame.right = thumbFrame.left;
  939.             upperFrame.left = thumbFrame.right;
  940.         } else {
  941.             lowerFrame.top = thumbFrame.bottom;
  942.             upperFrame.bottom = thumbFrame.top;
  943.         }
  944.     } else if (fUseFillColor) {
  945.         if (fOrientation == B_HORIZONTAL) {
  946.             lowerFrame.right = floor(lowerFrame.left - 1 + Position()
  947.                 * (lowerFrame.Width() + 1));
  948.             upperFrame.left = lowerFrame.right;
  949.         } else {
  950.             lowerFrame.top = floor(lowerFrame.bottom + 1 - Position()
  951.                 * (lowerFrame.Height() + 1));
  952.             upperFrame.bottom = lowerFrame.top;
  953.         }
  954.     }
  955.  
  956.     view->SetHighColor(barColor);
  957.     view->FillRect(upperFrame);
  958.  
  959.     if (Style() == B_BLOCK_THUMB || fUseFillColor) {
  960.         if (fUseFillColor)
  961.             view->SetHighColor(fillColor);
  962.         view->FillRect(lowerFrame);
  963.     }
  964.  
  965.     if (Style() == B_BLOCK_THUMB) {
  966.         // We don't want to stroke the lines over the thumb
  967.  
  968.         PushState();
  969.  
  970.         BRegion region;
  971.         GetClippingRegion(&region);
  972.         region.Exclude(thumbFrame);
  973.         ConstrainClippingRegion(&region);
  974.     }
  975.  
  976.     view->SetHighColor(darken1);
  977.     view->StrokeLine(BPoint(frame.left, frame.top),
  978.                      BPoint(frame.left + 1.0f, frame.top));
  979.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  980.                      BPoint(frame.left + 1.0f, frame.bottom));
  981.     view->StrokeLine(BPoint(frame.right - 1.0f, frame.top),
  982.                      BPoint(frame.right, frame.top));
  983.  
  984.     view->SetHighColor(darken2);
  985.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.top),
  986.                      BPoint(frame.right - 1.0f, frame.top));
  987.     view->StrokeLine(BPoint(frame.left, frame.bottom - 1.0f),
  988.                      BPoint(frame.left, frame.top + 1.0f));
  989.  
  990.     view->SetHighColor(lightenmax);
  991.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.bottom),
  992.                      BPoint(frame.right, frame.bottom));
  993.     view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f),
  994.                      BPoint(frame.right, frame.top + 1.0f));
  995.  
  996.     frame.InsetBy(1.0f, 1.0f);
  997.  
  998.     view->SetHighColor(darkenmax);
  999.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  1000.                      BPoint(frame.left, frame.top));
  1001.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.top),
  1002.                      BPoint(frame.right, frame.top));
  1003.  
  1004.     if (Style() == B_BLOCK_THUMB)
  1005.         PopState();
  1006.    
  1007. }
  1008.  
  1009.  
  1010. void
  1011. BSlider::DrawHashMarks()
  1012. {
  1013.     if (fHashMarks == B_HASH_MARKS_NONE)
  1014.         return;
  1015.  
  1016.     BRect frame = HashMarksFrame();
  1017.     BView* view = OffscreenView();
  1018.  
  1019.     if (be_control_look != NULL) {
  1020.         rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
  1021.         uint32 flags = be_control_look->Flags(this);
  1022.         be_control_look->DrawSliderHashMarks(view, frame, frame, base,
  1023.             fHashMarkCount, fHashMarks, flags, fOrientation);
  1024.         return;
  1025.     }
  1026.  
  1027.     rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
  1028.     rgb_color lightenmax;
  1029.     rgb_color darken2;
  1030.  
  1031.     if (IsEnabled()) {
  1032.         lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
  1033.         darken2 = tint_color(no_tint, B_DARKEN_2_TINT);
  1034.     } else {
  1035.         lightenmax = tint_color(no_tint, B_LIGHTEN_2_TINT);
  1036.         darken2 = tint_color(no_tint, B_DARKEN_1_TINT);
  1037.     }
  1038.  
  1039.     float pos = _MinPosition();
  1040.     int32 hashMarkCount = max_c(fHashMarkCount, 2);
  1041.         // draw at least two hashmarks at min/max if
  1042.         // fHashMarks != B_HASH_MARKS_NONE
  1043.     float factor = (_MaxPosition() - pos) / (hashMarkCount - 1);
  1044.  
  1045.     if (fHashMarks & B_HASH_MARKS_TOP) {
  1046.  
  1047.         view->BeginLineArray(hashMarkCount * 2);
  1048.  
  1049.         if (fOrientation == B_HORIZONTAL) {
  1050.             for (int32 i = 0; i < hashMarkCount; i++) {
  1051.                 view->AddLine(BPoint(pos, frame.top),
  1052.                               BPoint(pos, frame.top + 5), darken2);
  1053.                 view->AddLine(BPoint(pos + 1, frame.top),
  1054.                               BPoint(pos + 1, frame.top + 5), lightenmax);
  1055.  
  1056.                 pos += factor;
  1057.             }
  1058.         } else {
  1059.             for (int32 i = 0; i < hashMarkCount; i++) {
  1060.                 view->AddLine(BPoint(frame.left, pos),
  1061.                               BPoint(frame.left + 5, pos), darken2);
  1062.                 view->AddLine(BPoint(frame.left, pos + 1),
  1063.                               BPoint(frame.left + 5, pos + 1), lightenmax);
  1064.  
  1065.                 pos += factor;
  1066.             }
  1067.         }
  1068.  
  1069.         view->EndLineArray();
  1070.     }
  1071.  
  1072.     pos = _MinPosition();
  1073.  
  1074.     if (fHashMarks & B_HASH_MARKS_BOTTOM) {
  1075.  
  1076.         view->BeginLineArray(hashMarkCount * 2);
  1077.  
  1078.         if (fOrientation == B_HORIZONTAL) {
  1079.             for (int32 i = 0; i < hashMarkCount; i++) {
  1080.                 view->AddLine(BPoint(pos, frame.bottom - 5),
  1081.                               BPoint(pos, frame.bottom), darken2);
  1082.                 view->AddLine(BPoint(pos + 1, frame.bottom - 5),
  1083.                               BPoint(pos + 1, frame.bottom), lightenmax);
  1084.  
  1085.                 pos += factor;
  1086.             }
  1087.         } else {
  1088.             for (int32 i = 0; i < hashMarkCount; i++) {
  1089.                 view->AddLine(BPoint(frame.right - 5, pos),
  1090.                               BPoint(frame.right, pos), darken2);
  1091.                 view->AddLine(BPoint(frame.right - 5, pos + 1),
  1092.                               BPoint(frame.right, pos + 1), lightenmax);
  1093.  
  1094.                 pos += factor;
  1095.             }
  1096.         }
  1097.  
  1098.         view->EndLineArray();
  1099.     }
  1100. }
  1101.  
  1102.  
  1103. void
  1104. BSlider::DrawThumb()
  1105. {
  1106.     if (Style() == B_BLOCK_THUMB)
  1107.         _DrawBlockThumb();
  1108.     else
  1109.         _DrawTriangleThumb();
  1110. }
  1111.  
  1112.  
  1113. void
  1114. BSlider::DrawFocusMark()
  1115. {
  1116.     if (!IsFocus())
  1117.         return;
  1118.  
  1119.     OffscreenView()->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
  1120.  
  1121.     BRect frame = ThumbFrame();
  1122.  
  1123.     if (fStyle == B_BLOCK_THUMB) {
  1124.         frame.left += 2.0f;
  1125.         frame.top += 2.0f;
  1126.         frame.right -= 3.0f;
  1127.         frame.bottom -= 3.0f;
  1128.         OffscreenView()->StrokeRect(frame);
  1129.     } else {
  1130.         if (fOrientation == B_HORIZONTAL) {
  1131.             OffscreenView()->StrokeLine(BPoint(frame.left, frame.bottom + 2.0f),
  1132.                 BPoint(frame.right, frame.bottom + 2.0f));
  1133.         } else {
  1134.             OffscreenView()->StrokeLine(BPoint(frame.left - 2.0f, frame.top),
  1135.                 BPoint(frame.left - 2.0f, frame.bottom));
  1136.         }
  1137.     }
  1138. }
  1139.  
  1140.  
  1141. void
  1142. BSlider::DrawText()
  1143. {
  1144.     BRect bounds(Bounds());
  1145.     BView *view = OffscreenView();
  1146.  
  1147.     rgb_color base = LowColor();
  1148.     uint32 flags = 0;
  1149.     if (be_control_look == NULL) {
  1150.         if (IsEnabled()) {
  1151.             view->SetHighColor(0, 0, 0);
  1152.         } else {
  1153.             view->SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT));
  1154.         }
  1155.     } else
  1156.         flags = be_control_look->Flags(this);
  1157.  
  1158.     font_height fontHeight;
  1159.     GetFontHeight(&fontHeight);
  1160.     if (Orientation() == B_HORIZONTAL) {
  1161.         if (Label()) {
  1162.             if (be_control_look == NULL) {
  1163.                 view->DrawString(Label(),
  1164.                     BPoint(0.0, ceilf(fontHeight.ascent)));
  1165.             } else {
  1166.                 be_control_look->DrawLabel(view, Label(), base, flags,
  1167.                     BPoint(0.0, ceilf(fontHeight.ascent)));
  1168.             }
  1169.         }
  1170.  
  1171.         // the update text is updated in SetValue() only
  1172.         if (fUpdateText != NULL) {
  1173.             if (be_control_look == NULL) {
  1174.                 view->DrawString(fUpdateText, BPoint(bounds.right
  1175.                     - StringWidth(fUpdateText), ceilf(fontHeight.ascent)));
  1176.             } else {
  1177.                 be_control_look->DrawLabel(view, fUpdateText, base, flags,
  1178.                     BPoint(bounds.right - StringWidth(fUpdateText),
  1179.                         ceilf(fontHeight.ascent)));
  1180.             }
  1181.         }
  1182.  
  1183.         if (fMinLimitLabel) {
  1184.             if (be_control_look == NULL) {
  1185.                 view->DrawString(fMinLimitLabel, BPoint(0.0, bounds.bottom
  1186.                     - fontHeight.descent));
  1187.             } else {
  1188.                 be_control_look->DrawLabel(view, fMinLimitLabel, base, flags,
  1189.                     BPoint(0.0, bounds.bottom - fontHeight.descent));
  1190.             }
  1191.         }
  1192.  
  1193.         if (fMaxLimitLabel) {
  1194.             if (be_control_look == NULL) {
  1195.                 view->DrawString(fMaxLimitLabel, BPoint(bounds.right
  1196.                     - StringWidth(fMaxLimitLabel), bounds.bottom
  1197.                     - fontHeight.descent));
  1198.             } else {
  1199.                 be_control_look->DrawLabel(view, fMaxLimitLabel, base, flags,
  1200.                     BPoint(bounds.right - StringWidth(fMaxLimitLabel),
  1201.                         bounds.bottom - fontHeight.descent));
  1202.             }
  1203.         }
  1204.     } else {
  1205.         float lineHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent)
  1206.             + ceilf(fontHeight.leading);
  1207.         float baseLine = ceilf(fontHeight.ascent);
  1208.  
  1209.         if (Label()) {
  1210.             if (be_control_look == NULL) {
  1211.                 view->DrawString(Label(), BPoint((bounds.Width()
  1212.                     - StringWidth(Label())) / 2.0, baseLine));
  1213.             } else {
  1214.                 be_control_look->DrawLabel(view, Label(), base, flags,
  1215.                     BPoint((bounds.Width() - StringWidth(Label())) / 2.0,
  1216.                         baseLine));
  1217.             }
  1218.             baseLine += lineHeight;
  1219.         }
  1220.  
  1221.         if (fMaxLimitLabel) {
  1222.             if (be_control_look == NULL) {
  1223.                 view->DrawString(fMaxLimitLabel, BPoint((bounds.Width()
  1224.                     - StringWidth(fMaxLimitLabel)) / 2.0, baseLine));
  1225.             } else {
  1226.                 be_control_look->DrawLabel(view, fMaxLimitLabel, base, flags,
  1227.                     BPoint((bounds.Width()
  1228.                         - StringWidth(fMaxLimitLabel)) / 2.0, baseLine));
  1229.             }
  1230.         }
  1231.  
  1232.         baseLine = bounds.bottom - ceilf(fontHeight.descent);
  1233.  
  1234.         if (fMinLimitLabel) {
  1235.             if (be_control_look == NULL) {
  1236.                 view->DrawString(fMinLimitLabel, BPoint((bounds.Width()
  1237.                     - StringWidth(fMinLimitLabel)) / 2.0, baseLine));
  1238.             } else {
  1239.                 be_control_look->DrawLabel(view, fMinLimitLabel, base, flags,
  1240.                     BPoint((bounds.Width()
  1241.                         - StringWidth(fMinLimitLabel)) / 2.0, baseLine));
  1242.             }
  1243.             baseLine -= lineHeight;
  1244.         }
  1245.  
  1246.         if (fUpdateText != NULL) {
  1247.             if (be_control_look == NULL) {
  1248.                 view->DrawString(fUpdateText, BPoint((bounds.Width()
  1249.                     - StringWidth(fUpdateText)) / 2.0, baseLine));
  1250.             } else {
  1251.                 be_control_look->DrawLabel(view, fUpdateText, base, flags,
  1252.                     BPoint((bounds.Width()
  1253.                         - StringWidth(fUpdateText)) / 2.0, baseLine));
  1254.             }
  1255.         }
  1256.     }
  1257. }
  1258.  
  1259.  
  1260. // #pragma mark -
  1261.  
  1262.  
  1263. const char*
  1264. BSlider::UpdateText() const
  1265. {
  1266.     return NULL;
  1267. }
  1268.  
  1269.  
  1270. void
  1271. BSlider::UpdateTextChanged()
  1272. {
  1273.     // update text label
  1274.     float oldWidth = 0.0;
  1275.     if (fUpdateText != NULL)
  1276.         oldWidth = StringWidth(fUpdateText);
  1277.  
  1278.     const char* oldUpdateText = fUpdateText;
  1279.     fUpdateText = UpdateText();
  1280.     bool updateTextOnOff = (fUpdateText == NULL && oldUpdateText != NULL)
  1281.         || (fUpdateText != NULL && oldUpdateText == NULL);
  1282.  
  1283.     float newWidth = 0.0;
  1284.     if (fUpdateText != NULL)
  1285.         newWidth = StringWidth(fUpdateText);
  1286.  
  1287.     float width = ceilf(max_c(newWidth, oldWidth)) + 2.0f;
  1288.     if (width != 0) {
  1289.         font_height fontHeight;
  1290.         GetFontHeight(&fontHeight);
  1291.  
  1292.         float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
  1293.         float lineHeight = height + ceilf(fontHeight.leading);
  1294.         BRect invalid(Bounds());
  1295.         if (fOrientation == B_HORIZONTAL)
  1296.             invalid = BRect(invalid.right - width, 0, invalid.right, height);
  1297.         else {
  1298.             if (!updateTextOnOff) {
  1299.                 invalid.left = (invalid.left + invalid.right - width) / 2;
  1300.                 invalid.right = invalid.left + width;
  1301.                 if (fMinLimitLabel)
  1302.                     invalid.bottom -= lineHeight;
  1303.                 invalid.top = invalid.bottom - height;
  1304.             }
  1305.         }
  1306.         Invalidate(invalid);
  1307.     }
  1308.  
  1309.     float oldMaxUpdateTextWidth = fMaxUpdateTextWidth;
  1310.     fMaxUpdateTextWidth = MaxUpdateTextWidth();
  1311.     if (oldMaxUpdateTextWidth != fMaxUpdateTextWidth)
  1312.         InvalidateLayout();
  1313. }
  1314.  
  1315.  
  1316. BRect
  1317. BSlider::BarFrame() const
  1318. {
  1319.     BRect frame(Bounds());
  1320.  
  1321.     font_height fontHeight;
  1322.     GetFontHeight(&fontHeight);
  1323.  
  1324.     float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
  1325.     float leading = ceilf(fontHeight.leading);
  1326.  
  1327.     float thumbInset;
  1328.     if (fStyle == B_BLOCK_THUMB)
  1329.         thumbInset = 8.0;
  1330.     else
  1331.         thumbInset = 7.0;
  1332.  
  1333.     if (Orientation() == B_HORIZONTAL) {
  1334.         frame.left = thumbInset;
  1335.         frame.top = 6.0 + (Label() || fUpdateText ? textHeight + 4.0 : 0.0);
  1336.         frame.right -= thumbInset;
  1337.         frame.bottom = frame.top + fBarThickness;
  1338.     } else {
  1339.         frame.left = floorf((frame.Width() - fBarThickness) / 2.0);
  1340.         frame.top = thumbInset;
  1341.         if (Label())
  1342.             frame.top += textHeight;
  1343.         if (fMaxLimitLabel) {
  1344.             frame.top += textHeight;
  1345.             if (Label())
  1346.                 frame.top += leading;
  1347.         }
  1348.  
  1349.         frame.right = frame.left + fBarThickness;
  1350.         frame.bottom = frame.bottom - thumbInset;
  1351.         if (fMinLimitLabel)
  1352.             frame.bottom -= textHeight;
  1353.         if (fUpdateText) {
  1354.             frame.bottom -= textHeight;
  1355.             if (fMinLimitLabel)
  1356.                 frame.bottom -= leading;
  1357.         }
  1358.     }
  1359.  
  1360.     return frame;
  1361. }
  1362.  
  1363.  
  1364. BRect
  1365. BSlider::HashMarksFrame() const
  1366. {
  1367.     BRect frame(BarFrame());
  1368.  
  1369.     if (fOrientation == B_HORIZONTAL) {
  1370.         frame.top -= 6.0;
  1371.         frame.bottom += 6.0;
  1372.     } else {
  1373.         frame.left -= 6.0;
  1374.         frame.right += 6.0;
  1375.     }
  1376.  
  1377.     return frame;
  1378. }
  1379.  
  1380.  
  1381. BRect
  1382. BSlider::ThumbFrame() const
  1383. {
  1384.     // TODO: The slider looks really ugly and broken when it is too little.
  1385.     // I would suggest using BarFrame() here to get the top and bottom coords
  1386.     // and spread them further apart for the thumb
  1387.  
  1388.     BRect frame = Bounds();
  1389.  
  1390.     font_height fontHeight;
  1391.     GetFontHeight(&fontHeight);
  1392.  
  1393.     float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
  1394.  
  1395.     if (fStyle == B_BLOCK_THUMB) {
  1396.         if (Orientation() == B_HORIZONTAL) {
  1397.             frame.left = floorf(Position() * (_MaxPosition()
  1398.                 - _MinPosition()) + _MinPosition()) - 8;
  1399.             frame.top = 2 + (Label() || fUpdateText ? textHeight + 4 : 0);
  1400.             frame.right = frame.left + 17;
  1401.             frame.bottom = frame.top + fBarThickness + 7;
  1402.         } else {
  1403.             frame.left = floor((frame.Width() - fBarThickness) / 2) - 4;
  1404.             frame.top = floorf(Position() * (_MaxPosition()
  1405.                 - _MinPosition()) + _MinPosition()) - 8;
  1406.             frame.right = frame.left + fBarThickness + 7;
  1407.             frame.bottom = frame.top + 17;
  1408.         }
  1409.     } else {
  1410.         if (Orientation() == B_HORIZONTAL) {
  1411.             frame.left = floorf(Position() * (_MaxPosition()
  1412.                 - _MinPosition()) + _MinPosition()) - 6;
  1413.             frame.right = frame.left + 12;
  1414.             frame.top = 3 + fBarThickness + (Label() ? textHeight + 4 : 0);
  1415.             frame.bottom = frame.top + 8;
  1416.         } else {
  1417.             frame.left = floorf((frame.Width() + fBarThickness) / 2) - 3;
  1418.             frame.top = floorf(Position() * (_MaxPosition()
  1419.                 - _MinPosition())) + _MinPosition() - 6;
  1420.             frame.right = frame.left + 8;
  1421.             frame.bottom = frame.top + 12;
  1422.         }
  1423.     }
  1424.  
  1425.     return frame;
  1426. }
  1427.  
  1428.  
  1429. void
  1430. BSlider::SetFlags(uint32 flags)
  1431. {
  1432.     BControl::SetFlags(flags);
  1433. }
  1434.  
  1435.  
  1436. void
  1437. BSlider::SetResizingMode(uint32 mode)
  1438. {
  1439.     BControl::SetResizingMode(mode);
  1440. }
  1441.  
  1442.  
  1443. void
  1444. BSlider::GetPreferredSize(float* _width, float* _height)
  1445. {
  1446.     BSize preferredSize = PreferredSize();
  1447.  
  1448.     if (Orientation() == B_HORIZONTAL) {
  1449.         if (_width != NULL) {
  1450.             // NOTE: For compatibility reasons, a horizontal BSlider
  1451.             // never shrinks horizontally. This only affects applications
  1452.             // which do not use the new layout system.
  1453.             *_width = max_c(Bounds().Width(), preferredSize.width);
  1454.         }
  1455.  
  1456.         if (_height != NULL)
  1457.             *_height = preferredSize.height;
  1458.     } else {
  1459.         if (_width != NULL)
  1460.             *_width = preferredSize.width;
  1461.  
  1462.         if (_height != NULL) {
  1463.             // NOTE: Similarly, a vertical BSlider never shrinks
  1464.             // vertically. This only affects applications which do not
  1465.             // use the new layout system.
  1466.             *_height = max_c(Bounds().Height(), preferredSize.height);
  1467.         }
  1468.     }
  1469. }
  1470.  
  1471.  
  1472. void
  1473. BSlider::ResizeToPreferred()
  1474. {
  1475.     BControl::ResizeToPreferred();
  1476. }
  1477.  
  1478.  
  1479. status_t
  1480. BSlider::Invoke(BMessage* message)
  1481. {
  1482.     return BControl::Invoke(message);
  1483. }
  1484.  
  1485.  
  1486. BHandler*
  1487. BSlider::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier,
  1488.     int32 command, const char *property)
  1489. {
  1490.     return BControl::ResolveSpecifier(message, index, specifier, command,
  1491.         property);
  1492. }
  1493.  
  1494.  
  1495. status_t
  1496. BSlider::GetSupportedSuites(BMessage* message)
  1497. {
  1498.     return BControl::GetSupportedSuites(message);
  1499. }
  1500.  
  1501.  
  1502. void
  1503. BSlider::SetModificationMessage(BMessage* message)
  1504. {
  1505.     delete fModificationMessage;
  1506.     fModificationMessage = message;
  1507. }
  1508.  
  1509.  
  1510. BMessage*
  1511. BSlider::ModificationMessage() const
  1512. {
  1513.     return fModificationMessage;
  1514. }
  1515.  
  1516.  
  1517. void
  1518. BSlider::SetSnoozeAmount(int32 snoozeTime)
  1519. {
  1520.     if (snoozeTime < 10000)
  1521.         snoozeTime = 10000;
  1522.     else if (snoozeTime > 1000000)
  1523.         snoozeTime = 1000000;
  1524.  
  1525.     fSnoozeAmount = snoozeTime;
  1526. }
  1527.  
  1528.  
  1529. int32
  1530. BSlider::SnoozeAmount() const
  1531. {
  1532.     return fSnoozeAmount;
  1533. }
  1534.  
  1535.  
  1536. void
  1537. BSlider::SetKeyIncrementValue(int32 incrementValue)
  1538. {
  1539.     fKeyIncrementValue = incrementValue;
  1540. }
  1541.  
  1542.  
  1543. int32
  1544. BSlider::KeyIncrementValue() const
  1545. {
  1546.     return fKeyIncrementValue;
  1547. }
  1548.  
  1549.  
  1550. void
  1551. BSlider::SetHashMarkCount(int32 hashMarkCount)
  1552. {
  1553.     fHashMarkCount = hashMarkCount;
  1554.     Invalidate();
  1555. }
  1556.  
  1557.  
  1558. int32
  1559. BSlider::HashMarkCount() const
  1560. {
  1561.     return fHashMarkCount;
  1562. }
  1563.  
  1564.  
  1565. void
  1566. BSlider::SetHashMarks(hash_mark_location where)
  1567. {
  1568.     fHashMarks = where;
  1569. // TODO: enable if the hashmark look is influencing the control size!
  1570. //  InvalidateLayout();
  1571.     Invalidate();
  1572. }
  1573.  
  1574.  
  1575. hash_mark_location
  1576. BSlider::HashMarks() const
  1577. {
  1578.     return fHashMarks;
  1579. }
  1580.  
  1581.  
  1582. void
  1583. BSlider::SetStyle(thumb_style style)
  1584. {
  1585.     fStyle = style;
  1586.     InvalidateLayout();
  1587.     Invalidate();
  1588. }
  1589.  
  1590.  
  1591. thumb_style
  1592. BSlider::Style() const
  1593. {
  1594.     return fStyle;
  1595. }
  1596.  
  1597.  
  1598. void
  1599. BSlider::SetBarColor(rgb_color barColor)
  1600. {
  1601.     fBarColor = barColor;
  1602.     Invalidate(BarFrame());
  1603. }
  1604.  
  1605.  
  1606. rgb_color
  1607. BSlider::BarColor() const
  1608. {
  1609.     return fBarColor;
  1610. }
  1611.  
  1612.  
  1613. void
  1614. BSlider::UseFillColor(bool useFill, const rgb_color* barColor)
  1615. {
  1616.     fUseFillColor = useFill;
  1617.  
  1618.     if (useFill && barColor)
  1619.         fFillColor = *barColor;
  1620.  
  1621.     Invalidate(BarFrame());
  1622. }
  1623.  
  1624.  
  1625. bool
  1626. BSlider::FillColor(rgb_color* barColor) const
  1627. {
  1628.     if (barColor && fUseFillColor)
  1629.         *barColor = fFillColor;
  1630.  
  1631.     return fUseFillColor;
  1632. }
  1633.  
  1634.  
  1635. BView*
  1636. BSlider::OffscreenView() const
  1637. {
  1638. #if USE_OFF_SCREEN_VIEW
  1639.     return fOffScreenView;
  1640. #else
  1641.     return (BView*)this;
  1642. #endif
  1643. }
  1644.  
  1645.  
  1646. orientation
  1647. BSlider::Orientation() const
  1648. {
  1649.     return fOrientation;
  1650. }
  1651.  
  1652.  
  1653. void
  1654. BSlider::SetOrientation(orientation posture)
  1655. {
  1656.     if (fOrientation == posture)
  1657.         return;
  1658.  
  1659.     fOrientation = posture;
  1660.     InvalidateLayout();
  1661.     Invalidate();
  1662. }
  1663.  
  1664.  
  1665. float
  1666. BSlider::BarThickness() const
  1667. {
  1668.     return fBarThickness;
  1669. }
  1670.  
  1671.  
  1672. void
  1673. BSlider::SetBarThickness(float thickness)
  1674. {
  1675.     if (thickness < 1.0)
  1676.         thickness = 1.0;
  1677.     else
  1678.         thickness = roundf(thickness);
  1679.  
  1680.     if (thickness != fBarThickness) {
  1681.         // calculate invalid barframe and extend by hashmark size
  1682.         float hInset = 0.0;
  1683.         float vInset = 0.0;
  1684.         if (fOrientation == B_HORIZONTAL)
  1685.             vInset = -6.0;
  1686.         else
  1687.             hInset = -6.0;
  1688.         BRect invalid = BarFrame().InsetByCopy(hInset, vInset) | ThumbFrame();
  1689.  
  1690.         fBarThickness = thickness;
  1691.  
  1692.         invalid = invalid | BarFrame().InsetByCopy(hInset, vInset)
  1693.             | ThumbFrame();
  1694.         Invalidate(invalid);
  1695.         InvalidateLayout();
  1696.     }
  1697. }
  1698.  
  1699.  
  1700. void
  1701. BSlider::SetFont(const BFont *font, uint32 properties)
  1702. {
  1703.     BControl::SetFont(font, properties);
  1704.  
  1705. #if USE_OFF_SCREEN_VIEW
  1706.     if (fOffScreenView && fOffScreenBits) {
  1707.         if (fOffScreenBits->Lock()) {
  1708.             fOffScreenView->SetFont(font, properties);
  1709.             fOffScreenBits->Unlock();
  1710.         }
  1711.     }
  1712. #endif
  1713.  
  1714.     InvalidateLayout();
  1715. }
  1716.  
  1717.  
  1718. void
  1719. BSlider::SetLimits(int32 minimum, int32 maximum)
  1720. {
  1721.     if (minimum <= maximum) {
  1722.         fMinValue = minimum;
  1723.         fMaxValue = maximum;
  1724.  
  1725.         int32 value = Value();
  1726.         value = max_c(minimum, value);
  1727.         value = min_c(maximum, value);
  1728.  
  1729.         if (value != Value()) {
  1730.             SetValue(value);
  1731.         }
  1732.     }
  1733. }
  1734.  
  1735.  
  1736. float
  1737. BSlider::MaxUpdateTextWidth()
  1738. {
  1739.     // very simplistic implementation that assumes the string will be widest
  1740.     // at the maximum value
  1741.     int32 value = Value();
  1742.     SetValueNoUpdate(fMaxValue);
  1743.     float width = StringWidth(UpdateText());
  1744.     SetValueNoUpdate(value);
  1745.     // in case the derived class uses a fixed buffer, the contents
  1746.     // should be reset for the old value
  1747.     UpdateText();
  1748.     return width;
  1749. }
  1750.  
  1751.  
  1752. // #pragma mark - layout related
  1753.  
  1754.  
  1755. BSize
  1756. BSlider::MinSize()
  1757. {
  1758.     return BLayoutUtils::ComposeSize(ExplicitMinSize(),
  1759.         _ValidateMinSize());
  1760. }
  1761.  
  1762.  
  1763. BSize
  1764. BSlider::MaxSize()
  1765. {
  1766.     BSize maxSize = _ValidateMinSize();
  1767.     if (fOrientation == B_HORIZONTAL)
  1768.         maxSize.width = B_SIZE_UNLIMITED;
  1769.     else
  1770.         maxSize.height = B_SIZE_UNLIMITED;
  1771.     return BLayoutUtils::ComposeSize(ExplicitMaxSize(), maxSize);
  1772. }
  1773.  
  1774.  
  1775. BSize
  1776. BSlider::PreferredSize()
  1777. {
  1778.     BSize preferredSize = _ValidateMinSize();
  1779.     if (fOrientation == B_HORIZONTAL)
  1780.         preferredSize.width = max_c(100.0, preferredSize.width);
  1781.     else
  1782.         preferredSize.height = max_c(100.0, preferredSize.height);
  1783.     return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), preferredSize);
  1784. }
  1785.  
  1786.  
  1787. void
  1788. BSlider::LayoutInvalidated(bool descendants)
  1789. {
  1790.     // invalidate cached preferred size
  1791.     fMinSize.Set(-1, -1);
  1792. }
  1793.  
  1794.  
  1795. // #pragma mark - private
  1796.  
  1797. void
  1798. BSlider::_DrawBlockThumb()
  1799. {
  1800.     BRect frame = ThumbFrame();
  1801.     BView *view = OffscreenView();
  1802.  
  1803.     if (be_control_look != NULL) {
  1804.         rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
  1805.         uint32 flags = be_control_look->Flags(this);
  1806.         be_control_look->DrawSliderThumb(view, frame, frame, base, flags,
  1807.             fOrientation);
  1808.         return;
  1809.     }
  1810.  
  1811.     rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
  1812.     rgb_color lighten2;
  1813.     rgb_color lighten1;
  1814.     rgb_color darken2;
  1815.     rgb_color darken3;
  1816.     rgb_color darkenmax;
  1817.  
  1818.     if (IsEnabled()) {
  1819.         lighten2    = tint_color(no_tint, B_LIGHTEN_2_TINT);
  1820.         lighten1    = no_tint;
  1821.         darken2     = tint_color(no_tint, B_DARKEN_2_TINT);
  1822.         darken3     = tint_color(no_tint, B_DARKEN_3_TINT);
  1823.         darkenmax   = tint_color(no_tint, B_DARKEN_MAX_TINT);
  1824.     } else {
  1825.         lighten2    = tint_color(no_tint, B_LIGHTEN_2_TINT);
  1826.         lighten1    = tint_color(no_tint, B_LIGHTEN_1_TINT);
  1827.         darken2     = tint_color(no_tint, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0);
  1828.         darken3     = tint_color(no_tint, B_DARKEN_1_TINT);
  1829.         darkenmax   = tint_color(no_tint, B_DARKEN_3_TINT);
  1830.     }
  1831.  
  1832.     // blank background for shadow
  1833.     // ToDo: this also draws over the hash marks (though it's not *that* noticeable)
  1834.     view->SetHighColor(no_tint);
  1835.     view->StrokeLine(BPoint(frame.left, frame.top),
  1836.                      BPoint(frame.left, frame.top));
  1837.  
  1838.     BRect barFrame = BarFrame();
  1839.     if (barFrame.right >= frame.right) {
  1840.         // leave out barFrame from shadow background clearing
  1841.         view->StrokeLine(BPoint(frame.right, frame.top),
  1842.                          BPoint(frame.right, barFrame.top - 1.0f));
  1843.         view->StrokeLine(BPoint(frame.right, barFrame.bottom + 1.0f),
  1844.                          BPoint(frame.right, frame.bottom));
  1845.     } else {
  1846.         view->StrokeLine(BPoint(frame.right, frame.top),
  1847.                          BPoint(frame.right, frame.bottom));
  1848.     }
  1849.  
  1850.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  1851.                      BPoint(frame.right - 1.0f, frame.bottom));
  1852.     view->StrokeLine(BPoint(frame.left, frame.bottom - 1.0f),
  1853.                      BPoint(frame.left, frame.bottom - 1.0f));
  1854.     view->StrokeLine(BPoint(frame.right - 1.0f, frame.top),
  1855.                      BPoint(frame.right - 1.0f, frame.top));
  1856.  
  1857.     // Outline (top, left)
  1858.     view->SetHighColor(darken3);
  1859.     view->StrokeLine(BPoint(frame.left, frame.bottom - 2.0f),
  1860.                      BPoint(frame.left, frame.top + 1.0f));
  1861.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.top),
  1862.                      BPoint(frame.right - 2.0f, frame.top));
  1863.  
  1864.     // Shadow
  1865.     view->SetHighColor(0, 0, 0, IsEnabled() ? 100 : 50);
  1866.     view->SetDrawingMode(B_OP_ALPHA);
  1867.     view->StrokeLine(BPoint(frame.right, frame.top + 2.0f),
  1868.                      BPoint(frame.right, frame.bottom - 1.0f));
  1869.     view->StrokeLine(BPoint(frame.left + 2.0f, frame.bottom),
  1870.                      BPoint(frame.right - 1.0f, frame.bottom));
  1871.  
  1872.     view->SetDrawingMode(B_OP_COPY);
  1873.     view->SetHighColor(darken3);
  1874.     view->StrokeLine(BPoint(frame.right - 1.0f, frame.bottom - 1.0f),
  1875.                      BPoint(frame.right - 1.0f, frame.bottom - 1.0f));
  1876.  
  1877.  
  1878.     // First bevel
  1879.     frame.InsetBy(1.0f, 1.0f);
  1880.  
  1881.     view->SetHighColor(darkenmax);
  1882.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  1883.                      BPoint(frame.right - 1.0f, frame.bottom));
  1884.     view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f),
  1885.                      BPoint(frame.right, frame.top));
  1886.  
  1887.     view->SetHighColor(lighten2);
  1888.     view->StrokeLine(BPoint(frame.left, frame.top),
  1889.                      BPoint(frame.left, frame.bottom - 1.0f));
  1890.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.top),
  1891.                      BPoint(frame.right - 1.0f, frame.top));
  1892.  
  1893.     frame.InsetBy(1.0f, 1.0f);
  1894.  
  1895.     view->FillRect(BRect(frame.left, frame.top, frame.right - 1.0f, frame.bottom - 1.0f));
  1896.  
  1897.     // Second bevel and center dots
  1898.     view->SetHighColor(darken2);
  1899.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  1900.                      BPoint(frame.right, frame.bottom));
  1901.     view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f),
  1902.                      BPoint(frame.right, frame.top));
  1903.  
  1904.     if (Orientation() == B_HORIZONTAL) {
  1905.         view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 2.0f),
  1906.                          BPoint(frame.left + 6.0f, frame.top + 2.0f));
  1907.         view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 4.0f),
  1908.                          BPoint(frame.left + 6.0f, frame.top + 4.0f));
  1909.         view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 6.0f),
  1910.                          BPoint(frame.left + 6.0f, frame.top + 6.0f));
  1911.     } else {
  1912.         view->StrokeLine(BPoint(frame.left + 2.0f, frame.top + 6.0f),
  1913.                          BPoint(frame.left + 2.0f, frame.top + 6.0f));
  1914.         view->StrokeLine(BPoint(frame.left + 4.0f, frame.top + 6.0f),
  1915.                          BPoint(frame.left + 4.0f, frame.top + 6.0f));
  1916.         view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 6.0f),
  1917.                          BPoint(frame.left + 6.0f, frame.top + 6.0f));
  1918.     }
  1919.  
  1920.     frame.InsetBy(1.0f, 1.0f);
  1921.  
  1922.     // Third bevel
  1923.     view->SetHighColor(lighten1);
  1924.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  1925.                      BPoint(frame.right, frame.bottom));
  1926.     view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f),
  1927.                      BPoint(frame.right, frame.top));
  1928. }
  1929.  
  1930.  
  1931. void
  1932. BSlider::_DrawTriangleThumb()
  1933. {
  1934.     BRect frame = ThumbFrame();
  1935.     BView *view = OffscreenView();
  1936.  
  1937.     if (be_control_look != NULL) {
  1938.         rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
  1939.         uint32 flags = be_control_look->Flags(this);
  1940.         be_control_look->DrawSliderTriangle(view, frame, frame, base, flags,
  1941.             fOrientation);
  1942.         return;
  1943.     }
  1944.  
  1945.     rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
  1946.     rgb_color lightenmax;
  1947.     rgb_color lighten1;
  1948.     rgb_color darken2;
  1949.     rgb_color darken3;
  1950.     rgb_color darkenmax;
  1951.  
  1952.     if (IsEnabled()) {
  1953.         lightenmax  = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
  1954.         lighten1    = no_tint;
  1955.         darken2     = tint_color(no_tint, B_DARKEN_2_TINT);
  1956.         darken3     = tint_color(no_tint, B_DARKEN_3_TINT);
  1957.         darkenmax   = tint_color(no_tint, B_DARKEN_MAX_TINT);
  1958.     } else {
  1959.         lightenmax  = tint_color(no_tint, B_LIGHTEN_2_TINT);
  1960.         lighten1    = tint_color(no_tint, B_LIGHTEN_1_TINT);
  1961.         darken2     = tint_color(no_tint, (B_NO_TINT + B_DARKEN_1_TINT) / 2);
  1962.         darken3     = tint_color(no_tint, B_DARKEN_1_TINT);
  1963.         darkenmax   = tint_color(no_tint, B_DARKEN_3_TINT);
  1964.     }
  1965.  
  1966.     if (Orientation() == B_HORIZONTAL) {
  1967.         view->SetHighColor(lighten1);
  1968.         view->FillTriangle(
  1969.             BPoint(frame.left + 1, frame.bottom - 3),
  1970.             BPoint((frame.left + frame.right) / 2, frame.top + 1),
  1971.             BPoint(frame.right - 1, frame.bottom - 3));
  1972.  
  1973.         view->SetHighColor(no_tint);
  1974.         view->StrokeLine(BPoint(frame.right - 2, frame.bottom - 3),
  1975.             BPoint(frame.left + 3, frame.bottom - 3));
  1976.  
  1977.         view->SetHighColor(darkenmax);
  1978.         view->StrokeLine(BPoint(frame.left, frame.bottom - 1),
  1979.             BPoint(frame.right, frame.bottom - 1));
  1980.         view->StrokeLine(BPoint(frame.right, frame.bottom - 2),
  1981.             BPoint((frame.left + frame.right) / 2, frame.top));
  1982.  
  1983.         view->SetHighColor(darken2);
  1984.         view->StrokeLine(BPoint(frame.right - 1, frame.bottom - 2),
  1985.             BPoint(frame.left + 1, frame.bottom - 2));
  1986.         view->SetHighColor(darken3);
  1987.         view->StrokeLine(BPoint(frame.left, frame.bottom - 2),
  1988.             BPoint((frame.left + frame.right) / 2 - 1, frame.top + 1));
  1989.  
  1990.         view->SetHighColor(lightenmax);
  1991.         view->StrokeLine(BPoint(frame.left + 2, frame.bottom - 3),
  1992.             BPoint((frame.left + frame.right) / 2, frame.top + 1));
  1993.  
  1994.         // Shadow
  1995.         view->SetHighColor(0, 0, 0, IsEnabled() ? 80 : 40);
  1996.         view->SetDrawingMode(B_OP_ALPHA);
  1997.         view->StrokeLine(BPoint(frame.left + 1, frame.bottom),
  1998.             BPoint(frame.right, frame.bottom));
  1999.     } else {
  2000.         view->SetHighColor(lighten1);
  2001.         view->FillTriangle(
  2002.             BPoint(frame.left, (frame.top + frame.bottom) / 2),
  2003.             BPoint(frame.right - 1, frame.top + 1),
  2004.             BPoint(frame.right - 1, frame.bottom - 1));
  2005.  
  2006.         view->SetHighColor(darkenmax);
  2007.         view->StrokeLine(BPoint(frame.right - 1, frame.top),
  2008.             BPoint(frame.right - 1, frame.bottom));
  2009.         view->StrokeLine(BPoint(frame.right - 1, frame.bottom),
  2010.             BPoint(frame.right - 2, frame.bottom));
  2011.  
  2012.         view->SetHighColor(darken2);
  2013.         view->StrokeLine(BPoint(frame.right - 2, frame.top + 2),
  2014.             BPoint(frame.right - 2, frame.bottom - 1));
  2015.         view->StrokeLine(
  2016.             BPoint(frame.left, (frame.top + frame.bottom) / 2),
  2017.             BPoint(frame.right - 2, frame.top));
  2018.         view->SetHighColor(darken3);
  2019.         view->StrokeLine(
  2020.             BPoint(frame.left + 1, (frame.top + frame.bottom) / 2 + 1),
  2021.             BPoint(frame.right - 3, frame.bottom - 1));
  2022.  
  2023.         view->SetHighColor(lightenmax);
  2024.         view->StrokeLine(
  2025.             BPoint(frame.left + 1, (frame.top + frame.bottom) / 2),
  2026.             BPoint(frame.right - 2, frame.top + 1));
  2027.  
  2028.         // Shadow
  2029.         view->SetHighColor(0, 0, 0, IsEnabled() ? 80 : 40);
  2030.         view->SetDrawingMode(B_OP_ALPHA);
  2031.         view->StrokeLine(BPoint(frame.right, frame.top + 1),
  2032.             BPoint(frame.right, frame.bottom));
  2033.     }
  2034.  
  2035.     view->SetDrawingMode(B_OP_COPY);
  2036. }
  2037.  
  2038.  
  2039. BPoint
  2040. BSlider::_Location() const
  2041. {
  2042.     return fLocation;
  2043. }
  2044.  
  2045.  
  2046. void
  2047. BSlider::_SetLocationForValue(int32 value)
  2048. {
  2049.     BPoint loc;
  2050.     float range = (float)(fMaxValue - fMinValue);
  2051.     if (range == 0)
  2052.         range = 1;
  2053.  
  2054.     float pos = (float)(value - fMinValue) / range *
  2055.         (_MaxPosition() - _MinPosition());
  2056.  
  2057.     if (fOrientation == B_HORIZONTAL) {
  2058.         loc.x = ceil(_MinPosition() + pos);
  2059.         loc.y = 0;
  2060.     } else {
  2061.         loc.x = 0;
  2062.         loc.y = floor(_MaxPosition() - pos);
  2063.     }
  2064.     fLocation = loc;
  2065. }
  2066.  
  2067.  
  2068. float
  2069. BSlider::_MinPosition() const
  2070. {
  2071.     if (fOrientation == B_HORIZONTAL)
  2072.         return BarFrame().left + 1.0f;
  2073.  
  2074.     return BarFrame().bottom - 1.0f;
  2075. }
  2076.  
  2077.  
  2078. float
  2079. BSlider::_MaxPosition() const
  2080. {
  2081.     if (fOrientation == B_HORIZONTAL)
  2082.         return BarFrame().right - 1.0f;
  2083.  
  2084.     return BarFrame().top + 1.0f;
  2085. }
  2086.  
  2087.  
  2088. BSize
  2089. BSlider::_ValidateMinSize()
  2090. {
  2091.     if (fMinSize.width >= 0) {
  2092.         // the preferred size is up to date
  2093.         return fMinSize;
  2094.     }
  2095.  
  2096.     font_height fontHeight;
  2097.     GetFontHeight(&fontHeight);
  2098.  
  2099.     float width = 0.0;
  2100.     float height = 0.0;
  2101.  
  2102.     if (fMaxUpdateTextWidth < 0.0)
  2103.         fMaxUpdateTextWidth = MaxUpdateTextWidth();
  2104.  
  2105.     if (Orientation() == B_HORIZONTAL) {
  2106.         height = 12.0 + fBarThickness;
  2107.         int32 rows = 0;
  2108.  
  2109.         float labelWidth = 0;
  2110.         int32 labelRows = 0;
  2111.         float labelSpacing = StringWidth("M") * 2;
  2112.         if (Label()) {
  2113.             labelWidth = StringWidth(Label());
  2114.             labelRows = 1;
  2115.         }
  2116.         if (fMaxUpdateTextWidth > 0.0) {
  2117.             if (labelWidth > 0)
  2118.                 labelWidth += labelSpacing;
  2119.             labelWidth += fMaxUpdateTextWidth;
  2120.             labelRows = 1;
  2121.         }
  2122.         rows += labelRows;
  2123.  
  2124.         if (MinLimitLabel())
  2125.             width = StringWidth(MinLimitLabel());
  2126.         if (MaxLimitLabel()) {
  2127.             // some space between the labels
  2128.             if (MinLimitLabel())
  2129.                 width += labelSpacing;
  2130.  
  2131.             width += StringWidth(MaxLimitLabel());
  2132.         }
  2133.  
  2134.         if (labelWidth > width)
  2135.             width = labelWidth;
  2136.         if (width < 32.0)
  2137.             width = 32.0;
  2138.  
  2139.         if (MinLimitLabel() || MaxLimitLabel())
  2140.             rows++;
  2141.  
  2142.         height += rows * (ceilf(fontHeight.ascent)
  2143.             + ceilf(fontHeight.descent) + 4.0);
  2144.     } else {
  2145.         // B_VERTICAL
  2146.         width = 12.0 + fBarThickness;
  2147.         height = 32.0;
  2148.  
  2149.         float lineHeightNoLeading = ceilf(fontHeight.ascent)
  2150.             + ceilf(fontHeight.descent);
  2151.         float lineHeight = lineHeightNoLeading + ceilf(fontHeight.leading);
  2152.  
  2153.         // find largest label
  2154.         float labelWidth = 0;
  2155.         if (Label()) {
  2156.             labelWidth = StringWidth(Label());
  2157.             height += lineHeightNoLeading;
  2158.         }
  2159.         if (MaxLimitLabel()) {
  2160.             labelWidth = max_c(labelWidth, StringWidth(MaxLimitLabel()));
  2161.             height += Label() ? lineHeight : lineHeightNoLeading;
  2162.         }
  2163.         if (MinLimitLabel()) {
  2164.             labelWidth = max_c(labelWidth, StringWidth(MinLimitLabel()));
  2165.             height += lineHeightNoLeading;
  2166.         }
  2167.         if (fMaxUpdateTextWidth > 0.0) {
  2168.             labelWidth = max_c(labelWidth, fMaxUpdateTextWidth);
  2169.             height += MinLimitLabel() ? lineHeight : lineHeightNoLeading;
  2170.         }
  2171.  
  2172.         width = max_c(labelWidth, width);
  2173.     }
  2174.  
  2175.     fMinSize.width = width;
  2176.     fMinSize.height = height;
  2177.  
  2178.     ResetLayoutInvalidation();
  2179.  
  2180.     return fMinSize;
  2181. }
  2182.  
  2183.  
  2184. // #pragma mark - FBC padding
  2185.  
  2186. void BSlider::_ReservedSlider6() {}
  2187. void BSlider::_ReservedSlider7() {}
  2188. void BSlider::_ReservedSlider8() {}
  2189. void BSlider::_ReservedSlider9() {}
  2190. void BSlider::_ReservedSlider10() {}
  2191. void BSlider::_ReservedSlider11() {}
  2192. void BSlider::_ReservedSlider12() {}
  2193.  
  2194.  
  2195. BSlider &
  2196. BSlider::operator=(const BSlider &)
  2197. {
  2198.     return *this;
  2199. }
  2200.  
  2201.  
  2202. //  #pragma mark - BeOS compatibility
  2203.  
  2204.  
  2205. #if __GNUC__ < 3
  2206.  
  2207. extern "C" void
  2208. GetLimits__7BSliderPlT1(BSlider* slider, int32* minimum, int32* maximum)
  2209. {
  2210.     slider->GetLimits(minimum, maximum);
  2211. }
  2212.  
  2213.  
  2214. extern "C" void
  2215. _ReservedSlider4__7BSlider(BSlider *slider, int32 minimum, int32 maximum)
  2216. {
  2217.     slider->BSlider::SetLimits(minimum, maximum);
  2218. }
  2219.  
  2220. extern "C" float
  2221. _ReservedSlider5__7BSlider(BSlider *slider)
  2222. {
  2223.     return slider->BSlider::MaxUpdateTextWidth();
  2224. }
  2225.  
  2226.  
  2227. extern "C" void
  2228. _ReservedSlider1__7BSlider(BSlider* slider, orientation _orientation)
  2229. {
  2230.     slider->BSlider::SetOrientation(_orientation);
  2231. }
  2232.  
  2233.  
  2234. extern "C" void
  2235. _ReservedSlider2__7BSlider(BSlider* slider, float thickness)
  2236. {
  2237.     slider->BSlider::SetBarThickness(thickness);
  2238. }
  2239.  
  2240.  
  2241. extern "C" void
  2242. _ReservedSlider3__7BSlider(BSlider* slider, const BFont* font,
  2243.     uint32 properties)
  2244. {
  2245.     slider->BSlider::SetFont(font, properties);
  2246. }
  2247.  
  2248.  
  2249. #endif  // __GNUC__ < 3
  2250.  
  2251.  
  2252. extern "C" void
  2253. B_IF_GCC_2(InvalidateLayout__7BSliderb, _ZN7BSlider16InvalidateLayoutEb)(
  2254.     BView* view, bool descendants)
  2255. {
  2256.     perform_data_layout_invalidated data;
  2257.     data.descendants = descendants;
  2258.  
  2259.     view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
  2260. }
  2261.  
  2262. /*
  2263.  * Copyright 2001-2013 Haiku, Inc.
  2264.  * Distributed under the terms of the MIT License.
  2265.  *
  2266.  * Authors:
  2267.  *      Stephan Aßmus <[email protected]>
  2268.  *      Axel Dörfler, [email protected]
  2269.  *      Marc Flerackers ([email protected])
  2270.  */
  2271.  
  2272.  
  2273. #include <Slider.h>
  2274.  
  2275. #include <stdio.h>
  2276. #include <stdlib.h>
  2277. #include <string.h>
  2278.  
  2279. #include <Bitmap.h>
  2280. #include <ControlLook.h>
  2281. #include <Errors.h>
  2282. #include <LayoutUtils.h>
  2283. #include <Message.h>
  2284. #include <Region.h>
  2285. #include <String.h>
  2286. #include <Window.h>
  2287.  
  2288. #include <binary_compatibility/Interface.h>
  2289.  
  2290.  
  2291. #define USE_OFF_SCREEN_VIEW 0
  2292.  
  2293.  
  2294. BSlider::BSlider(BRect frame, const char* name, const char* label,
  2295.             BMessage* message, int32 minValue, int32 maxValue,
  2296.             thumb_style thumbType, uint32 resizingMode, uint32 flags)
  2297.     : BControl(frame, name, label, message, resizingMode, flags),
  2298.     fModificationMessage(NULL),
  2299.     fSnoozeAmount(20000),
  2300.  
  2301.     fMinLimitLabel(NULL),
  2302.     fMaxLimitLabel(NULL),
  2303.  
  2304.     fMinValue(minValue),
  2305.     fMaxValue(maxValue),
  2306.     fKeyIncrementValue(1),
  2307.  
  2308.     fHashMarkCount(0),
  2309.     fHashMarks(B_HASH_MARKS_NONE),
  2310.  
  2311.     fStyle(thumbType),
  2312.  
  2313.     fOrientation(B_HORIZONTAL),
  2314.     fBarThickness(6.0)
  2315. {
  2316.     _InitBarColor();
  2317.  
  2318.     _InitObject();
  2319.     SetValue(0);
  2320. }
  2321.  
  2322.  
  2323. BSlider::BSlider(BRect frame, const char *name, const char *label,
  2324.             BMessage *message, int32 minValue, int32 maxValue,
  2325.             orientation posture, thumb_style thumbType, uint32 resizingMode,
  2326.             uint32 flags)
  2327.     : BControl(frame, name, label, message, resizingMode, flags),
  2328.     fModificationMessage(NULL),
  2329.     fSnoozeAmount(20000),
  2330.  
  2331.     fMinLimitLabel(NULL),
  2332.     fMaxLimitLabel(NULL),
  2333.  
  2334.     fMinValue(minValue),
  2335.     fMaxValue(maxValue),
  2336.     fKeyIncrementValue(1),
  2337.  
  2338.     fHashMarkCount(0),
  2339.     fHashMarks(B_HASH_MARKS_NONE),
  2340.  
  2341.     fStyle(thumbType),
  2342.  
  2343.     fOrientation(posture),
  2344.     fBarThickness(6.0)
  2345. {
  2346.     _InitBarColor();
  2347.  
  2348.     _InitObject();
  2349.     SetValue(0);
  2350. }
  2351.  
  2352.  
  2353. BSlider::BSlider(const char *name, const char *label, BMessage *message,
  2354.             int32 minValue, int32 maxValue, orientation posture,
  2355.             thumb_style thumbType, uint32 flags)
  2356.     : BControl(name, label, message, flags),
  2357.     fModificationMessage(NULL),
  2358.     fSnoozeAmount(20000),
  2359.  
  2360.     fMinLimitLabel(NULL),
  2361.     fMaxLimitLabel(NULL),
  2362.  
  2363.     fMinValue(minValue),
  2364.     fMaxValue(maxValue),
  2365.     fKeyIncrementValue(1),
  2366.  
  2367.     fHashMarkCount(0),
  2368.     fHashMarks(B_HASH_MARKS_NONE),
  2369.  
  2370.     fStyle(thumbType),
  2371.  
  2372.     fOrientation(posture),
  2373.     fBarThickness(6.0)
  2374. {
  2375.     _InitBarColor();
  2376.  
  2377.     _InitObject();
  2378.     SetValue(0);
  2379. }
  2380.  
  2381.  
  2382. BSlider::BSlider(BMessage *archive)
  2383.     : BControl(archive)
  2384. {
  2385.     fModificationMessage = NULL;
  2386.  
  2387.     if (archive->HasMessage("_mod_msg")) {
  2388.         BMessage* message = new BMessage;
  2389.  
  2390.         archive->FindMessage("_mod_msg", message);
  2391.  
  2392.         SetModificationMessage(message);
  2393.     }
  2394.  
  2395.     if (archive->FindInt32("_sdelay", &fSnoozeAmount) != B_OK)
  2396.         SetSnoozeAmount(20000);
  2397.  
  2398.     rgb_color color;
  2399.     if (archive->FindInt32("_fcolor", (int32 *)&color) == B_OK)
  2400.         UseFillColor(true, &color);
  2401.     else
  2402.         UseFillColor(false);
  2403.  
  2404.     int32 orient;
  2405.     if (archive->FindInt32("_orient", &orient) == B_OK)
  2406.         fOrientation = (orientation)orient;
  2407.     else
  2408.         fOrientation = B_HORIZONTAL;
  2409.  
  2410.     fMinLimitLabel = NULL;
  2411.     fMaxLimitLabel = NULL;
  2412.  
  2413.     const char* minlbl = NULL;
  2414.     const char* maxlbl = NULL;
  2415.  
  2416.     archive->FindString("_minlbl", &minlbl);
  2417.     archive->FindString("_maxlbl", &maxlbl);
  2418.  
  2419.     SetLimitLabels(minlbl, maxlbl);
  2420.  
  2421.     if (archive->FindInt32("_min", &fMinValue) != B_OK)
  2422.         fMinValue = 0;
  2423.  
  2424.     if (archive->FindInt32("_max", &fMaxValue) != B_OK)
  2425.         fMaxValue = 100;
  2426.  
  2427.     if (archive->FindInt32("_incrementvalue", &fKeyIncrementValue) != B_OK)
  2428.         fKeyIncrementValue = 1;
  2429.  
  2430.     if (archive->FindInt32("_hashcount", &fHashMarkCount) != B_OK)
  2431.         fHashMarkCount = 11;
  2432.  
  2433.     int16 hashloc;
  2434.     if (archive->FindInt16("_hashloc", &hashloc) == B_OK)
  2435.         fHashMarks = (hash_mark_location)hashloc;
  2436.     else
  2437.         fHashMarks = B_HASH_MARKS_NONE;
  2438.  
  2439.     int16 sstyle;
  2440.     if (archive->FindInt16("_sstyle", &sstyle) == B_OK)
  2441.         fStyle = (thumb_style)sstyle;
  2442.     else
  2443.         fStyle = B_BLOCK_THUMB;
  2444.  
  2445.     if (archive->FindInt32("_bcolor", (int32 *)&color) != B_OK)
  2446.         color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_DARKEN_4_TINT);
  2447.     SetBarColor(color);
  2448.  
  2449.     float bthickness;
  2450.     if (archive->FindFloat("_bthickness", &bthickness) == B_OK)
  2451.         fBarThickness = bthickness;
  2452.     else
  2453.         fBarThickness = 6.0f;
  2454.  
  2455.     _InitObject();
  2456. }
  2457.  
  2458.  
  2459. BSlider::~BSlider()
  2460. {
  2461. #if USE_OFF_SCREEN_VIEW
  2462.     delete fOffScreenBits;
  2463. #endif
  2464.  
  2465.     delete fModificationMessage;
  2466.     free(fMinLimitLabel);
  2467.     free(fMaxLimitLabel);
  2468. }
  2469.  
  2470.  
  2471. void
  2472. BSlider::_InitBarColor()
  2473. {
  2474.     if (be_control_look != NULL) {
  2475.         SetBarColor(be_control_look->SliderBarColor(
  2476.             ui_color(B_PANEL_BACKGROUND_COLOR)));
  2477.     } else {
  2478.         SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
  2479.             B_DARKEN_4_TINT));
  2480.     }
  2481.  
  2482.     UseFillColor(false, NULL);
  2483. }
  2484.  
  2485.  
  2486. void
  2487. BSlider::_InitObject()
  2488. {
  2489.     fLocation.x = 0;
  2490.     fLocation.y = 0;
  2491.     fInitialLocation.x = 0;
  2492.     fInitialLocation.y = 0;
  2493.  
  2494. #if USE_OFF_SCREEN_VIEW
  2495.     fOffScreenBits = NULL;
  2496.     fOffScreenView = NULL;
  2497. #endif
  2498.  
  2499.     fUpdateText = NULL;
  2500.     fMinSize.Set(-1, -1);
  2501.     fMaxUpdateTextWidth = -1.0;
  2502. }
  2503.  
  2504.  
  2505. BArchivable*
  2506. BSlider::Instantiate(BMessage *archive)
  2507. {
  2508.     if (validate_instantiation(archive, "BSlider"))
  2509.         return new BSlider(archive);
  2510.  
  2511.     return NULL;
  2512. }
  2513.  
  2514.  
  2515. status_t
  2516. BSlider::Archive(BMessage *archive, bool deep) const
  2517. {
  2518.     status_t ret = BControl::Archive(archive, deep);
  2519.  
  2520.     if (ModificationMessage() && ret == B_OK)
  2521.         ret = archive->AddMessage("_mod_msg", ModificationMessage());
  2522.  
  2523.     if (ret == B_OK)
  2524.         ret = archive->AddInt32("_sdelay", fSnoozeAmount);
  2525.     if (ret == B_OK)
  2526.         ret = archive->AddInt32("_bcolor", (const uint32 &)fBarColor);
  2527.  
  2528.     if (FillColor(NULL) && ret == B_OK)
  2529.         ret = archive->AddInt32("_fcolor", (const uint32 &)fFillColor);
  2530.  
  2531.     if (ret == B_OK && fMinLimitLabel)
  2532.         ret = archive->AddString("_minlbl", fMinLimitLabel);
  2533.  
  2534.     if (ret == B_OK && fMaxLimitLabel)
  2535.         ret = archive->AddString("_maxlbl", fMaxLimitLabel);
  2536.  
  2537.     if (ret == B_OK)
  2538.         ret = archive->AddInt32("_min", fMinValue);
  2539.     if (ret == B_OK)
  2540.         ret = archive->AddInt32("_max", fMaxValue);
  2541.  
  2542.     if (ret == B_OK)
  2543.         ret = archive->AddInt32("_incrementvalue", fKeyIncrementValue);
  2544.     if (ret == B_OK)
  2545.         ret = archive->AddInt32("_hashcount", fHashMarkCount);
  2546.     if (ret == B_OK)
  2547.         ret = archive->AddInt16("_hashloc", fHashMarks);
  2548.     if (ret == B_OK)
  2549.         ret = archive->AddInt16("_sstyle", fStyle);
  2550.     if (ret == B_OK)
  2551.         ret = archive->AddInt32("_orient", fOrientation);
  2552.     if (ret == B_OK)
  2553.         ret = archive->AddFloat("_bthickness", fBarThickness);
  2554.  
  2555.     return ret;
  2556. }
  2557.  
  2558.  
  2559. status_t
  2560. BSlider::Perform(perform_code code, void* _data)
  2561. {
  2562.     switch (code) {
  2563.         case PERFORM_CODE_MIN_SIZE:
  2564.             ((perform_data_min_size*)_data)->return_value
  2565.                 = BSlider::MinSize();
  2566.             return B_OK;
  2567.         case PERFORM_CODE_MAX_SIZE:
  2568.             ((perform_data_max_size*)_data)->return_value
  2569.                 = BSlider::MaxSize();
  2570.             return B_OK;
  2571.         case PERFORM_CODE_PREFERRED_SIZE:
  2572.             ((perform_data_preferred_size*)_data)->return_value
  2573.                 = BSlider::PreferredSize();
  2574.             return B_OK;
  2575.         case PERFORM_CODE_LAYOUT_ALIGNMENT:
  2576.             ((perform_data_layout_alignment*)_data)->return_value
  2577.                 = BSlider::LayoutAlignment();
  2578.             return B_OK;
  2579.         case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
  2580.             ((perform_data_has_height_for_width*)_data)->return_value
  2581.                 = BSlider::HasHeightForWidth();
  2582.             return B_OK;
  2583.         case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
  2584.         {
  2585.             perform_data_get_height_for_width* data
  2586.                 = (perform_data_get_height_for_width*)_data;
  2587.             BSlider::GetHeightForWidth(data->width, &data->min, &data->max,
  2588.                 &data->preferred);
  2589.             return B_OK;
  2590.         }
  2591.         case PERFORM_CODE_SET_LAYOUT:
  2592.         {
  2593.             perform_data_set_layout* data = (perform_data_set_layout*)_data;
  2594.             BSlider::SetLayout(data->layout);
  2595.             return B_OK;
  2596.         }
  2597.         case PERFORM_CODE_LAYOUT_INVALIDATED:
  2598.         {
  2599.             perform_data_layout_invalidated* data
  2600.                 = (perform_data_layout_invalidated*)_data;
  2601.             BSlider::LayoutInvalidated(data->descendants);
  2602.             return B_OK;
  2603.         }
  2604.         case PERFORM_CODE_DO_LAYOUT:
  2605.         {
  2606.             BSlider::DoLayout();
  2607.             return B_OK;
  2608.         }
  2609.     }
  2610.  
  2611.     return BControl::Perform(code, _data);
  2612. }
  2613.  
  2614.  
  2615. void
  2616. BSlider::WindowActivated(bool state)
  2617. {
  2618.     BControl::WindowActivated(state);
  2619. }
  2620.  
  2621.  
  2622. void
  2623. BSlider::AttachedToWindow()
  2624. {
  2625.     ResizeToPreferred();
  2626.  
  2627. #if USE_OFF_SCREEN_VIEW
  2628.     BRect bounds(Bounds());
  2629.  
  2630.     if (!fOffScreenView) {
  2631.         fOffScreenView = new BView(bounds, "", B_FOLLOW_ALL, B_WILL_DRAW);
  2632.  
  2633.         BFont font;
  2634.         GetFont(&font);
  2635.         fOffScreenView->SetFont(&font);
  2636.     }
  2637.  
  2638.     if (!fOffScreenBits) {
  2639.         fOffScreenBits = new BBitmap(bounds, B_RGBA32, true, false);
  2640.  
  2641.         if (fOffScreenBits && fOffScreenView)
  2642.             fOffScreenBits->AddChild(fOffScreenView);
  2643.  
  2644.     } else if (fOffScreenView)
  2645.         fOffScreenBits->AddChild(fOffScreenView);
  2646. #endif // USE_OFF_SCREEN_VIEW
  2647.  
  2648.     BControl::AttachedToWindow();
  2649.  
  2650.     BView* view = OffscreenView();
  2651.     if (view && view->LockLooper()) {
  2652.         view->SetViewColor(B_TRANSPARENT_COLOR);
  2653.         view->SetLowColor(LowColor());
  2654.         view->UnlockLooper();
  2655.     }
  2656.  
  2657.     int32 value = Value();
  2658.     SetValue(value);
  2659.         // makes sure the value is within valid bounds
  2660.     _SetLocationForValue(Value());
  2661.         // makes sure the location is correct
  2662.     UpdateTextChanged();
  2663. }
  2664.  
  2665.  
  2666. void
  2667. BSlider::AllAttached()
  2668. {
  2669.     BControl::AllAttached();
  2670. }
  2671.  
  2672.  
  2673. void
  2674. BSlider::AllDetached()
  2675. {
  2676.     BControl::AllDetached();
  2677. }
  2678.  
  2679.  
  2680. void
  2681. BSlider::DetachedFromWindow()
  2682. {
  2683.     BControl::DetachedFromWindow();
  2684.  
  2685. #if USE_OFF_SCREEN_VIEW
  2686.     if (fOffScreenBits) {
  2687.         delete fOffScreenBits;
  2688.         fOffScreenBits = NULL;
  2689.         fOffScreenView = NULL;
  2690.     }
  2691. #endif
  2692. }
  2693.  
  2694.  
  2695. void
  2696. BSlider::MessageReceived(BMessage *msg)
  2697. {
  2698.     BControl::MessageReceived(msg);
  2699. }
  2700.  
  2701.  
  2702. void
  2703. BSlider::FrameMoved(BPoint new_position)
  2704. {
  2705.     BControl::FrameMoved(new_position);
  2706. }
  2707.  
  2708.  
  2709. void
  2710. BSlider::FrameResized(float w,float h)
  2711. {
  2712.     BControl::FrameResized(w, h);
  2713.  
  2714.     BRect bounds(Bounds());
  2715.  
  2716.     if (bounds.right <= 0.0f || bounds.bottom <= 0.0f)
  2717.         return;
  2718.  
  2719. #if USE_OFF_SCREEN_VIEW
  2720.     if (fOffScreenBits) {
  2721.         fOffScreenBits->RemoveChild(fOffScreenView);
  2722.         delete fOffScreenBits;
  2723.  
  2724.         fOffScreenView->ResizeTo(bounds.Width(), bounds.Height());
  2725.  
  2726.         fOffScreenBits = new BBitmap(Bounds(), B_RGBA32, true, false);
  2727.         fOffScreenBits->AddChild(fOffScreenView);
  2728.     }
  2729. #endif
  2730.  
  2731.     Invalidate();
  2732. }
  2733.  
  2734.  
  2735. void
  2736. BSlider::KeyDown(const char *bytes, int32 numBytes)
  2737. {
  2738.     if (!IsEnabled() || IsHidden())
  2739.         return;
  2740.  
  2741.     int32 newValue = Value();
  2742.  
  2743.     switch (bytes[0]) {
  2744.         case B_LEFT_ARROW:
  2745.         case B_DOWN_ARROW:
  2746.             newValue -= KeyIncrementValue();
  2747.             break;
  2748.  
  2749.         case B_RIGHT_ARROW:
  2750.         case B_UP_ARROW:
  2751.             newValue += KeyIncrementValue();
  2752.             break;
  2753.  
  2754.         case B_HOME:
  2755.             newValue = fMinValue;
  2756.             break;
  2757.         case B_END:
  2758.             newValue = fMaxValue;
  2759.             break;
  2760.  
  2761.         default:
  2762.             BControl::KeyDown(bytes, numBytes);
  2763.             return;
  2764.     }
  2765.  
  2766.     if (newValue < fMinValue)
  2767.         newValue = fMinValue;
  2768.     if (newValue > fMaxValue)
  2769.         newValue = fMaxValue;
  2770.  
  2771.     if (newValue != Value()) {
  2772.         fInitialLocation = _Location();
  2773.         SetValue(newValue);
  2774.         InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
  2775.     }
  2776. }
  2777.  
  2778. void
  2779. BSlider::KeyUp(const char *bytes, int32 numBytes)
  2780. {
  2781.     if (fInitialLocation != _Location()) {
  2782.         // The last KeyDown event triggered the modification message or no
  2783.         // notification at all, we may also have sent the modification message
  2784.         // continually while the user kept pressing the key. In either case,
  2785.         // finish with the final message to make the behavior consistent with
  2786.         // changing the value by mouse.
  2787.         Invoke();
  2788.     }
  2789. }
  2790.  
  2791.  
  2792. /*!
  2793.     Makes sure the \a point is within valid bounds.
  2794.     Returns \c true if the relevant coordinate (depending on the orientation
  2795.     of the slider) differs from \a comparePoint.
  2796. */
  2797. bool
  2798. BSlider::_ConstrainPoint(BPoint& point, BPoint comparePoint) const
  2799. {
  2800.     if (fOrientation == B_HORIZONTAL) {
  2801.         if (point.x != comparePoint.x) {
  2802.             if (point.x < _MinPosition())
  2803.                 point.x = _MinPosition();
  2804.             else if (point.x > _MaxPosition())
  2805.                 point.x = _MaxPosition();
  2806.  
  2807.             return true;
  2808.         }
  2809.     } else {
  2810.         if (point.y != comparePoint.y) {
  2811.             if (point.y > _MinPosition())
  2812.                 point.y = _MinPosition();
  2813.             else if (point.y < _MaxPosition())
  2814.                 point.y = _MaxPosition();
  2815.  
  2816.             return true;
  2817.         }
  2818.     }
  2819.  
  2820.     return false;
  2821. }
  2822.  
  2823.  
  2824. void
  2825. BSlider::MouseDown(BPoint point)
  2826. {
  2827.     if (!IsEnabled())
  2828.         return;
  2829.  
  2830.     if (BarFrame().Contains(point) || ThumbFrame().Contains(point))
  2831.         fInitialLocation = _Location();
  2832.  
  2833.     uint32 buttons;
  2834.     GetMouse(&point, &buttons, true);
  2835.  
  2836.     _ConstrainPoint(point, fInitialLocation);
  2837.     SetValue(ValueForPoint(point));
  2838.  
  2839.     if (_Location() != fInitialLocation)
  2840.         InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
  2841.  
  2842.     if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
  2843.         SetTracking(true);
  2844.         SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
  2845.     } else {
  2846.         // synchronous mouse tracking
  2847.         BPoint prevPoint;
  2848.  
  2849.         while (buttons) {
  2850.             prevPoint = point;
  2851.  
  2852.             snooze(SnoozeAmount());
  2853.             GetMouse(&point, &buttons, true);
  2854.  
  2855.             if (_ConstrainPoint(point, prevPoint)) {
  2856.                 int32 value = ValueForPoint(point);
  2857.                 if (value != Value()) {
  2858.                     SetValue(value);
  2859.                     InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
  2860.                 }
  2861.             }
  2862.         }
  2863.         if (_Location() != fInitialLocation)
  2864.             Invoke();
  2865.     }
  2866. }
  2867.  
  2868.  
  2869. void
  2870. BSlider::MouseUp(BPoint point)
  2871. {
  2872.     if (IsTracking()) {
  2873.         if (_Location() != fInitialLocation)
  2874.             Invoke();
  2875.  
  2876.         SetTracking(false);
  2877.     } else
  2878.         BControl::MouseUp(point);
  2879. }
  2880.  
  2881.  
  2882. void
  2883. BSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
  2884. {
  2885.     if (IsTracking()) {
  2886.         if (_ConstrainPoint(point, _Location())) {
  2887.             int32 value = ValueForPoint(point);
  2888.             if (value != Value()) {
  2889.                 SetValue(value);
  2890.                 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
  2891.             }
  2892.         }
  2893.     } else
  2894.         BControl::MouseMoved(point, transit, message);
  2895. }
  2896.  
  2897.  
  2898. void
  2899. BSlider::Pulse()
  2900. {
  2901.     BControl::Pulse();
  2902. }
  2903.  
  2904.  
  2905. void
  2906. BSlider::SetLabel(const char *label)
  2907. {
  2908.     BControl::SetLabel(label);
  2909. }
  2910.  
  2911.  
  2912. void
  2913. BSlider::SetLimitLabels(const char *minLabel, const char *maxLabel)
  2914. {
  2915.     free(fMinLimitLabel);
  2916.     fMinLimitLabel = minLabel ? strdup(minLabel) : NULL;
  2917.  
  2918.     free(fMaxLimitLabel);
  2919.     fMaxLimitLabel = maxLabel ? strdup(maxLabel) : NULL;
  2920.  
  2921.     InvalidateLayout();
  2922.  
  2923.     // TODO: This is for backwards compatibility and should
  2924.     // probably be removed when breaking binary compatiblity.
  2925.     // Applications like our own Mouse rely on this behavior.
  2926.     if ((Flags() & B_SUPPORTS_LAYOUT) == 0)
  2927.         ResizeToPreferred();
  2928.  
  2929.     Invalidate();
  2930. }
  2931.  
  2932.  
  2933. const char*
  2934. BSlider::MinLimitLabel() const
  2935. {
  2936.     return fMinLimitLabel;
  2937. }
  2938.  
  2939.  
  2940. const char*
  2941. BSlider::MaxLimitLabel() const
  2942. {
  2943.     return fMaxLimitLabel;
  2944. }
  2945.  
  2946.  
  2947. void
  2948. BSlider::SetValue(int32 value)
  2949. {
  2950.     if (value < fMinValue)
  2951.         value = fMinValue;
  2952.     if (value > fMaxValue)
  2953.         value = fMaxValue;
  2954.  
  2955.     if (value == Value())
  2956.         return;
  2957.  
  2958.     _SetLocationForValue(value);
  2959.  
  2960.     BRect oldThumbFrame = ThumbFrame();
  2961.  
  2962.     // While it would be enough to do this dependent on fUseFillColor,
  2963.     // that doesn't work out if DrawBar() has been overridden by a sub class
  2964.     if (fOrientation == B_HORIZONTAL)
  2965.         oldThumbFrame.top = BarFrame().top;
  2966.     else
  2967.         oldThumbFrame.left = BarFrame().left;
  2968.  
  2969.     BControl::SetValueNoUpdate(value);
  2970.     BRect invalid = oldThumbFrame | ThumbFrame();
  2971.  
  2972.     if (Style() == B_TRIANGLE_THUMB) {
  2973.         // 1) We need to take care of pixels touched because of anti-aliasing.
  2974.         // 2) We need to update the region with the focus mark as well. (A
  2975.         // method BSlider::FocusMarkFrame() would be nice as well.)
  2976.         if (fOrientation == B_HORIZONTAL) {
  2977.             if (IsFocus())
  2978.                 invalid.bottom += 2;
  2979.             invalid.InsetBy(-1, 0);
  2980.         } else {
  2981.             if (IsFocus())
  2982.                 invalid.left -= 2;
  2983.             invalid.InsetBy(0, -1);
  2984.         }
  2985.     }
  2986.  
  2987.     Invalidate(invalid);
  2988.  
  2989.     UpdateTextChanged();
  2990. }
  2991.  
  2992.  
  2993. int32
  2994. BSlider::ValueForPoint(BPoint location) const
  2995. {
  2996.     float min;
  2997.     float max;
  2998.     float position;
  2999.     if (fOrientation == B_HORIZONTAL) {
  3000.         min = _MinPosition();
  3001.         max = _MaxPosition();
  3002.         position = location.x;
  3003.     } else {
  3004.         max = _MinPosition();
  3005.         min = _MaxPosition();
  3006.         position = min + (max - location.y);
  3007.     }
  3008.  
  3009.     if (position < min)
  3010.         position = min;
  3011.     if (position > max)
  3012.         position = max;
  3013.  
  3014.     return (int32)roundf(((position - min) * (fMaxValue - fMinValue) / (max - min)) + fMinValue);
  3015. }
  3016.  
  3017.  
  3018. void
  3019. BSlider::SetPosition(float position)
  3020. {
  3021.     if (position <= 0.0f)
  3022.         SetValue(fMinValue);
  3023.     else if (position >= 1.0f)
  3024.         SetValue(fMaxValue);
  3025.     else
  3026.         SetValue((int32)(position * (fMaxValue - fMinValue) + fMinValue));
  3027. }
  3028.  
  3029.  
  3030. float
  3031. BSlider::Position() const
  3032. {
  3033.     float range = (float)(fMaxValue - fMinValue);
  3034.     if (range == 0.0f)
  3035.         range = 1.0f;
  3036.  
  3037.     return (float)(Value() - fMinValue) / range;
  3038. }
  3039.  
  3040.  
  3041. void
  3042. BSlider::SetEnabled(bool on)
  3043. {
  3044.     BControl::SetEnabled(on);
  3045. }
  3046.  
  3047.  
  3048. void
  3049. BSlider::GetLimits(int32 *minimum, int32 *maximum) const
  3050. {
  3051.     if (minimum != NULL)
  3052.         *minimum = fMinValue;
  3053.     if (maximum != NULL)
  3054.         *maximum = fMaxValue;
  3055. }
  3056.  
  3057.  
  3058. // #pragma mark - drawing
  3059.  
  3060.  
  3061. void
  3062. BSlider::Draw(BRect updateRect)
  3063. {
  3064.     // clear out background
  3065.     BRegion background(updateRect);
  3066.     background.Exclude(BarFrame());
  3067.     bool drawBackground = true;
  3068.     if (Parent() && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) {
  3069.         // This view is embedded somewhere, most likely the Tracker Desktop
  3070.         // shelf.
  3071.         drawBackground = false;
  3072.     }
  3073.  
  3074. #if USE_OFF_SCREEN_VIEW
  3075.     if (!fOffScreenBits)
  3076.         return;
  3077.  
  3078.     if (fOffScreenBits->Lock()) {
  3079.         fOffScreenView->SetViewColor(ViewColor());
  3080.         fOffScreenView->SetLowColor(LowColor());
  3081. #endif
  3082.  
  3083.         if (drawBackground && background.Frame().IsValid())
  3084.             OffscreenView()->FillRegion(&background, B_SOLID_LOW);
  3085.  
  3086. #if USE_OFF_SCREEN_VIEW
  3087.         fOffScreenView->Sync();
  3088.         fOffScreenBits->Unlock();
  3089.     }
  3090. #endif
  3091.  
  3092.     DrawSlider();
  3093.     DrawEllipse();
  3094. }
  3095.  
  3096.  
  3097. void
  3098. BSlider::DrawSlider()
  3099. {
  3100.     if (LockLooper()) {
  3101. #if USE_OFF_SCREEN_VIEW
  3102.         if (!fOffScreenBits)
  3103.             return;
  3104.         if (fOffScreenBits->Lock()) {
  3105. #endif
  3106.             //DrawBar();
  3107.             //DrawHashMarks();
  3108.             //DrawThumb();
  3109.             //DrawFocusMark();
  3110.             //DrawText();
  3111.            
  3112. #if USE_OFF_SCREEN_VIEW
  3113.             fOffScreenView->Sync();
  3114.             fOffScreenBits->Unlock();
  3115.  
  3116.             DrawBitmap(fOffScreenBits, B_ORIGIN);
  3117.         }
  3118. #endif
  3119.         UnlockLooper();
  3120.     }
  3121. }
  3122.  
  3123. void
  3124. BSlider::DrawEllipse()
  3125. {
  3126.     StrokeEllipse(BRect(1,1,27,27), B_SOLID_HIGH);
  3127.     SetHighColor(150,150,150,255);
  3128.     FillEllipse(BRect(1,1,27,27), B_SOLID_HIGH);
  3129.     SetHighColor(100,100,100,255);
  3130.     FillEllipse(BRect(4,4,24,24), B_SOLID_HIGH);
  3131.     StrokeLine(BPoint(26/2 + 1, 26/2 + 1),
  3132.                     BPoint(26/2 - 26/4 - 1, 26/2 + 26/4 + 1), B_SOLID_HIGH);
  3133.     StrokeLine(BPoint(26/2 + 1, 26/2 + 1),
  3134.                     BPoint(26/2 + 26/4 + 1, 26/2 + 26/4 + 1), B_SOLID_HIGH);
  3135. }
  3136.  
  3137.  
  3138. void
  3139. BSlider::DrawBar()
  3140. {
  3141.     BRect frame = BarFrame();
  3142.     BView *view = OffscreenView();
  3143.  
  3144.     if (be_control_look != NULL) {
  3145.         uint32 flags = be_control_look->Flags(this);
  3146.         rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
  3147.         rgb_color rightFillColor = fBarColor;
  3148.         rgb_color leftFillColor = fUseFillColor ? fFillColor : fBarColor;
  3149.         be_control_look->DrawSliderBar(view, frame, frame, base, leftFillColor,
  3150.             rightFillColor, Position(), flags, fOrientation);
  3151.         return;
  3152.     }
  3153.  
  3154.     rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
  3155.     rgb_color lightenmax;
  3156.     rgb_color darken1;
  3157.     rgb_color darken2;
  3158.     rgb_color darkenmax;
  3159.  
  3160.     rgb_color barColor;
  3161.     rgb_color fillColor;
  3162.  
  3163.     if (IsEnabled()) {
  3164.         lightenmax  = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
  3165.         darken1     = tint_color(no_tint, B_DARKEN_1_TINT);
  3166.         darken2     = tint_color(no_tint, B_DARKEN_2_TINT);
  3167.         darkenmax   = tint_color(no_tint, B_DARKEN_MAX_TINT);
  3168.         barColor    = fBarColor;
  3169.         fillColor   = fFillColor;
  3170.     } else {
  3171.         lightenmax  = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
  3172.         darken1     = no_tint;
  3173.         darken2     = tint_color(no_tint, B_DARKEN_1_TINT);
  3174.         darkenmax   = tint_color(no_tint, B_DARKEN_3_TINT);
  3175.  
  3176.         barColor.red    = (fBarColor.red + no_tint.red) / 2;
  3177.         barColor.green  = (fBarColor.green + no_tint.green) / 2;
  3178.         barColor.blue   = (fBarColor.blue + no_tint.blue) / 2;
  3179.         barColor.alpha  = 255;
  3180.  
  3181.         fillColor.red   = (fFillColor.red + no_tint.red) / 2;
  3182.         fillColor.green = (fFillColor.green + no_tint.green) / 2;
  3183.         fillColor.blue  = (fFillColor.blue + no_tint.blue) / 2;
  3184.         fillColor.alpha = 255;
  3185.     }
  3186.  
  3187.     // exclude the block thumb from the bar filling
  3188.  
  3189.     BRect lowerFrame = frame.InsetByCopy(1, 1);
  3190.     lowerFrame.top++;
  3191.     lowerFrame.left++;
  3192.     BRect upperFrame = lowerFrame;
  3193.     BRect thumbFrame;
  3194.  
  3195.     if (Style() == B_BLOCK_THUMB) {
  3196.         thumbFrame = ThumbFrame();
  3197.  
  3198.         if (fOrientation == B_HORIZONTAL) {
  3199.             lowerFrame.right = thumbFrame.left;
  3200.             upperFrame.left = thumbFrame.right;
  3201.         } else {
  3202.             lowerFrame.top = thumbFrame.bottom;
  3203.             upperFrame.bottom = thumbFrame.top;
  3204.         }
  3205.     } else if (fUseFillColor) {
  3206.         if (fOrientation == B_HORIZONTAL) {
  3207.             lowerFrame.right = floor(lowerFrame.left - 1 + Position()
  3208.                 * (lowerFrame.Width() + 1));
  3209.             upperFrame.left = lowerFrame.right;
  3210.         } else {
  3211.             lowerFrame.top = floor(lowerFrame.bottom + 1 - Position()
  3212.                 * (lowerFrame.Height() + 1));
  3213.             upperFrame.bottom = lowerFrame.top;
  3214.         }
  3215.     }
  3216.  
  3217.     view->SetHighColor(barColor);
  3218.     view->FillRect(upperFrame);
  3219.  
  3220.     if (Style() == B_BLOCK_THUMB || fUseFillColor) {
  3221.         if (fUseFillColor)
  3222.             view->SetHighColor(fillColor);
  3223.         view->FillRect(lowerFrame);
  3224.     }
  3225.  
  3226.     if (Style() == B_BLOCK_THUMB) {
  3227.         // We don't want to stroke the lines over the thumb
  3228.  
  3229.         PushState();
  3230.  
  3231.         BRegion region;
  3232.         GetClippingRegion(&region);
  3233.         region.Exclude(thumbFrame);
  3234.         ConstrainClippingRegion(&region);
  3235.     }
  3236.  
  3237.     view->SetHighColor(darken1);
  3238.     view->StrokeLine(BPoint(frame.left, frame.top),
  3239.                      BPoint(frame.left + 1.0f, frame.top));
  3240.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  3241.                      BPoint(frame.left + 1.0f, frame.bottom));
  3242.     view->StrokeLine(BPoint(frame.right - 1.0f, frame.top),
  3243.                      BPoint(frame.right, frame.top));
  3244.  
  3245.     view->SetHighColor(darken2);
  3246.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.top),
  3247.                      BPoint(frame.right - 1.0f, frame.top));
  3248.     view->StrokeLine(BPoint(frame.left, frame.bottom - 1.0f),
  3249.                      BPoint(frame.left, frame.top + 1.0f));
  3250.  
  3251.     view->SetHighColor(lightenmax);
  3252.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.bottom),
  3253.                      BPoint(frame.right, frame.bottom));
  3254.     view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f),
  3255.                      BPoint(frame.right, frame.top + 1.0f));
  3256.  
  3257.     frame.InsetBy(1.0f, 1.0f);
  3258.  
  3259.     view->SetHighColor(darkenmax);
  3260.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  3261.                      BPoint(frame.left, frame.top));
  3262.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.top),
  3263.                      BPoint(frame.right, frame.top));
  3264.  
  3265.     if (Style() == B_BLOCK_THUMB)
  3266.         PopState();
  3267.    
  3268. }
  3269.  
  3270.  
  3271. void
  3272. BSlider::DrawHashMarks()
  3273. {
  3274.     if (fHashMarks == B_HASH_MARKS_NONE)
  3275.         return;
  3276.  
  3277.     BRect frame = HashMarksFrame();
  3278.     BView* view = OffscreenView();
  3279.  
  3280.     if (be_control_look != NULL) {
  3281.         rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
  3282.         uint32 flags = be_control_look->Flags(this);
  3283.         be_control_look->DrawSliderHashMarks(view, frame, frame, base,
  3284.             fHashMarkCount, fHashMarks, flags, fOrientation);
  3285.         return;
  3286.     }
  3287.  
  3288.     rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
  3289.     rgb_color lightenmax;
  3290.     rgb_color darken2;
  3291.  
  3292.     if (IsEnabled()) {
  3293.         lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
  3294.         darken2 = tint_color(no_tint, B_DARKEN_2_TINT);
  3295.     } else {
  3296.         lightenmax = tint_color(no_tint, B_LIGHTEN_2_TINT);
  3297.         darken2 = tint_color(no_tint, B_DARKEN_1_TINT);
  3298.     }
  3299.  
  3300.     float pos = _MinPosition();
  3301.     int32 hashMarkCount = max_c(fHashMarkCount, 2);
  3302.         // draw at least two hashmarks at min/max if
  3303.         // fHashMarks != B_HASH_MARKS_NONE
  3304.     float factor = (_MaxPosition() - pos) / (hashMarkCount - 1);
  3305.  
  3306.     if (fHashMarks & B_HASH_MARKS_TOP) {
  3307.  
  3308.         view->BeginLineArray(hashMarkCount * 2);
  3309.  
  3310.         if (fOrientation == B_HORIZONTAL) {
  3311.             for (int32 i = 0; i < hashMarkCount; i++) {
  3312.                 view->AddLine(BPoint(pos, frame.top),
  3313.                               BPoint(pos, frame.top + 5), darken2);
  3314.                 view->AddLine(BPoint(pos + 1, frame.top),
  3315.                               BPoint(pos + 1, frame.top + 5), lightenmax);
  3316.  
  3317.                 pos += factor;
  3318.             }
  3319.         } else {
  3320.             for (int32 i = 0; i < hashMarkCount; i++) {
  3321.                 view->AddLine(BPoint(frame.left, pos),
  3322.                               BPoint(frame.left + 5, pos), darken2);
  3323.                 view->AddLine(BPoint(frame.left, pos + 1),
  3324.                               BPoint(frame.left + 5, pos + 1), lightenmax);
  3325.  
  3326.                 pos += factor;
  3327.             }
  3328.         }
  3329.  
  3330.         view->EndLineArray();
  3331.     }
  3332.  
  3333.     pos = _MinPosition();
  3334.  
  3335.     if (fHashMarks & B_HASH_MARKS_BOTTOM) {
  3336.  
  3337.         view->BeginLineArray(hashMarkCount * 2);
  3338.  
  3339.         if (fOrientation == B_HORIZONTAL) {
  3340.             for (int32 i = 0; i < hashMarkCount; i++) {
  3341.                 view->AddLine(BPoint(pos, frame.bottom - 5),
  3342.                               BPoint(pos, frame.bottom), darken2);
  3343.                 view->AddLine(BPoint(pos + 1, frame.bottom - 5),
  3344.                               BPoint(pos + 1, frame.bottom), lightenmax);
  3345.  
  3346.                 pos += factor;
  3347.             }
  3348.         } else {
  3349.             for (int32 i = 0; i < hashMarkCount; i++) {
  3350.                 view->AddLine(BPoint(frame.right - 5, pos),
  3351.                               BPoint(frame.right, pos), darken2);
  3352.                 view->AddLine(BPoint(frame.right - 5, pos + 1),
  3353.                               BPoint(frame.right, pos + 1), lightenmax);
  3354.  
  3355.                 pos += factor;
  3356.             }
  3357.         }
  3358.  
  3359.         view->EndLineArray();
  3360.     }
  3361. }
  3362.  
  3363.  
  3364. void
  3365. BSlider::DrawThumb()
  3366. {
  3367.     if (Style() == B_BLOCK_THUMB)
  3368.         _DrawBlockThumb();
  3369.     else
  3370.         _DrawTriangleThumb();
  3371. }
  3372.  
  3373.  
  3374. void
  3375. BSlider::DrawFocusMark()
  3376. {
  3377.     if (!IsFocus())
  3378.         return;
  3379.  
  3380.     OffscreenView()->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
  3381.  
  3382.     BRect frame = ThumbFrame();
  3383.  
  3384.     if (fStyle == B_BLOCK_THUMB) {
  3385.         frame.left += 2.0f;
  3386.         frame.top += 2.0f;
  3387.         frame.right -= 3.0f;
  3388.         frame.bottom -= 3.0f;
  3389.         OffscreenView()->StrokeRect(frame);
  3390.     } else {
  3391.         if (fOrientation == B_HORIZONTAL) {
  3392.             OffscreenView()->StrokeLine(BPoint(frame.left, frame.bottom + 2.0f),
  3393.                 BPoint(frame.right, frame.bottom + 2.0f));
  3394.         } else {
  3395.             OffscreenView()->StrokeLine(BPoint(frame.left - 2.0f, frame.top),
  3396.                 BPoint(frame.left - 2.0f, frame.bottom));
  3397.         }
  3398.     }
  3399. }
  3400.  
  3401.  
  3402. void
  3403. BSlider::DrawText()
  3404. {
  3405.     BRect bounds(Bounds());
  3406.     BView *view = OffscreenView();
  3407.  
  3408.     rgb_color base = LowColor();
  3409.     uint32 flags = 0;
  3410.     if (be_control_look == NULL) {
  3411.         if (IsEnabled()) {
  3412.             view->SetHighColor(0, 0, 0);
  3413.         } else {
  3414.             view->SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT));
  3415.         }
  3416.     } else
  3417.         flags = be_control_look->Flags(this);
  3418.  
  3419.     font_height fontHeight;
  3420.     GetFontHeight(&fontHeight);
  3421.     if (Orientation() == B_HORIZONTAL) {
  3422.         if (Label()) {
  3423.             if (be_control_look == NULL) {
  3424.                 view->DrawString(Label(),
  3425.                     BPoint(0.0, ceilf(fontHeight.ascent)));
  3426.             } else {
  3427.                 be_control_look->DrawLabel(view, Label(), base, flags,
  3428.                     BPoint(0.0, ceilf(fontHeight.ascent)));
  3429.             }
  3430.         }
  3431.  
  3432.         // the update text is updated in SetValue() only
  3433.         if (fUpdateText != NULL) {
  3434.             if (be_control_look == NULL) {
  3435.                 view->DrawString(fUpdateText, BPoint(bounds.right
  3436.                     - StringWidth(fUpdateText), ceilf(fontHeight.ascent)));
  3437.             } else {
  3438.                 be_control_look->DrawLabel(view, fUpdateText, base, flags,
  3439.                     BPoint(bounds.right - StringWidth(fUpdateText),
  3440.                         ceilf(fontHeight.ascent)));
  3441.             }
  3442.         }
  3443.  
  3444.         if (fMinLimitLabel) {
  3445.             if (be_control_look == NULL) {
  3446.                 view->DrawString(fMinLimitLabel, BPoint(0.0, bounds.bottom
  3447.                     - fontHeight.descent));
  3448.             } else {
  3449.                 be_control_look->DrawLabel(view, fMinLimitLabel, base, flags,
  3450.                     BPoint(0.0, bounds.bottom - fontHeight.descent));
  3451.             }
  3452.         }
  3453.  
  3454.         if (fMaxLimitLabel) {
  3455.             if (be_control_look == NULL) {
  3456.                 view->DrawString(fMaxLimitLabel, BPoint(bounds.right
  3457.                     - StringWidth(fMaxLimitLabel), bounds.bottom
  3458.                     - fontHeight.descent));
  3459.             } else {
  3460.                 be_control_look->DrawLabel(view, fMaxLimitLabel, base, flags,
  3461.                     BPoint(bounds.right - StringWidth(fMaxLimitLabel),
  3462.                         bounds.bottom - fontHeight.descent));
  3463.             }
  3464.         }
  3465.     } else {
  3466.         float lineHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent)
  3467.             + ceilf(fontHeight.leading);
  3468.         float baseLine = ceilf(fontHeight.ascent);
  3469.  
  3470.         if (Label()) {
  3471.             if (be_control_look == NULL) {
  3472.                 view->DrawString(Label(), BPoint((bounds.Width()
  3473.                     - StringWidth(Label())) / 2.0, baseLine));
  3474.             } else {
  3475.                 be_control_look->DrawLabel(view, Label(), base, flags,
  3476.                     BPoint((bounds.Width() - StringWidth(Label())) / 2.0,
  3477.                         baseLine));
  3478.             }
  3479.             baseLine += lineHeight;
  3480.         }
  3481.  
  3482.         if (fMaxLimitLabel) {
  3483.             if (be_control_look == NULL) {
  3484.                 view->DrawString(fMaxLimitLabel, BPoint((bounds.Width()
  3485.                     - StringWidth(fMaxLimitLabel)) / 2.0, baseLine));
  3486.             } else {
  3487.                 be_control_look->DrawLabel(view, fMaxLimitLabel, base, flags,
  3488.                     BPoint((bounds.Width()
  3489.                         - StringWidth(fMaxLimitLabel)) / 2.0, baseLine));
  3490.             }
  3491.         }
  3492.  
  3493.         baseLine = bounds.bottom - ceilf(fontHeight.descent);
  3494.  
  3495.         if (fMinLimitLabel) {
  3496.             if (be_control_look == NULL) {
  3497.                 view->DrawString(fMinLimitLabel, BPoint((bounds.Width()
  3498.                     - StringWidth(fMinLimitLabel)) / 2.0, baseLine));
  3499.             } else {
  3500.                 be_control_look->DrawLabel(view, fMinLimitLabel, base, flags,
  3501.                     BPoint((bounds.Width()
  3502.                         - StringWidth(fMinLimitLabel)) / 2.0, baseLine));
  3503.             }
  3504.             baseLine -= lineHeight;
  3505.         }
  3506.  
  3507.         if (fUpdateText != NULL) {
  3508.             if (be_control_look == NULL) {
  3509.                 view->DrawString(fUpdateText, BPoint((bounds.Width()
  3510.                     - StringWidth(fUpdateText)) / 2.0, baseLine));
  3511.             } else {
  3512.                 be_control_look->DrawLabel(view, fUpdateText, base, flags,
  3513.                     BPoint((bounds.Width()
  3514.                         - StringWidth(fUpdateText)) / 2.0, baseLine));
  3515.             }
  3516.         }
  3517.     }
  3518. }
  3519.  
  3520.  
  3521. // #pragma mark -
  3522.  
  3523.  
  3524. const char*
  3525. BSlider::UpdateText() const
  3526. {
  3527.     return NULL;
  3528. }
  3529.  
  3530.  
  3531. void
  3532. BSlider::UpdateTextChanged()
  3533. {
  3534.     // update text label
  3535.     float oldWidth = 0.0;
  3536.     if (fUpdateText != NULL)
  3537.         oldWidth = StringWidth(fUpdateText);
  3538.  
  3539.     const char* oldUpdateText = fUpdateText;
  3540.     fUpdateText = UpdateText();
  3541.     bool updateTextOnOff = (fUpdateText == NULL && oldUpdateText != NULL)
  3542.         || (fUpdateText != NULL && oldUpdateText == NULL);
  3543.  
  3544.     float newWidth = 0.0;
  3545.     if (fUpdateText != NULL)
  3546.         newWidth = StringWidth(fUpdateText);
  3547.  
  3548.     float width = ceilf(max_c(newWidth, oldWidth)) + 2.0f;
  3549.     if (width != 0) {
  3550.         font_height fontHeight;
  3551.         GetFontHeight(&fontHeight);
  3552.  
  3553.         float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
  3554.         float lineHeight = height + ceilf(fontHeight.leading);
  3555.         BRect invalid(Bounds());
  3556.         if (fOrientation == B_HORIZONTAL)
  3557.             invalid = BRect(invalid.right - width, 0, invalid.right, height);
  3558.         else {
  3559.             if (!updateTextOnOff) {
  3560.                 invalid.left = (invalid.left + invalid.right - width) / 2;
  3561.                 invalid.right = invalid.left + width;
  3562.                 if (fMinLimitLabel)
  3563.                     invalid.bottom -= lineHeight;
  3564.                 invalid.top = invalid.bottom - height;
  3565.             }
  3566.         }
  3567.         Invalidate(invalid);
  3568.     }
  3569.  
  3570.     float oldMaxUpdateTextWidth = fMaxUpdateTextWidth;
  3571.     fMaxUpdateTextWidth = MaxUpdateTextWidth();
  3572.     if (oldMaxUpdateTextWidth != fMaxUpdateTextWidth)
  3573.         InvalidateLayout();
  3574. }
  3575.  
  3576.  
  3577. BRect
  3578. BSlider::BarFrame() const
  3579. {
  3580.     BRect frame(Bounds());
  3581.  
  3582.     font_height fontHeight;
  3583.     GetFontHeight(&fontHeight);
  3584.  
  3585.     float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
  3586.     float leading = ceilf(fontHeight.leading);
  3587.  
  3588.     float thumbInset;
  3589.     if (fStyle == B_BLOCK_THUMB)
  3590.         thumbInset = 8.0;
  3591.     else
  3592.         thumbInset = 7.0;
  3593.  
  3594.     if (Orientation() == B_HORIZONTAL) {
  3595.         frame.left = thumbInset;
  3596.         frame.top = 6.0 + (Label() || fUpdateText ? textHeight + 4.0 : 0.0);
  3597.         frame.right -= thumbInset;
  3598.         frame.bottom = frame.top + fBarThickness;
  3599.     } else {
  3600.         frame.left = floorf((frame.Width() - fBarThickness) / 2.0);
  3601.         frame.top = thumbInset;
  3602.         if (Label())
  3603.             frame.top += textHeight;
  3604.         if (fMaxLimitLabel) {
  3605.             frame.top += textHeight;
  3606.             if (Label())
  3607.                 frame.top += leading;
  3608.         }
  3609.  
  3610.         frame.right = frame.left + fBarThickness;
  3611.         frame.bottom = frame.bottom - thumbInset;
  3612.         if (fMinLimitLabel)
  3613.             frame.bottom -= textHeight;
  3614.         if (fUpdateText) {
  3615.             frame.bottom -= textHeight;
  3616.             if (fMinLimitLabel)
  3617.                 frame.bottom -= leading;
  3618.         }
  3619.     }
  3620.  
  3621.     return frame;
  3622. }
  3623.  
  3624.  
  3625. BRect
  3626. BSlider::HashMarksFrame() const
  3627. {
  3628.     BRect frame(BarFrame());
  3629.  
  3630.     if (fOrientation == B_HORIZONTAL) {
  3631.         frame.top -= 6.0;
  3632.         frame.bottom += 6.0;
  3633.     } else {
  3634.         frame.left -= 6.0;
  3635.         frame.right += 6.0;
  3636.     }
  3637.  
  3638.     return frame;
  3639. }
  3640.  
  3641.  
  3642. BRect
  3643. BSlider::ThumbFrame() const
  3644. {
  3645.     // TODO: The slider looks really ugly and broken when it is too little.
  3646.     // I would suggest using BarFrame() here to get the top and bottom coords
  3647.     // and spread them further apart for the thumb
  3648.  
  3649.     BRect frame = Bounds();
  3650.  
  3651.     font_height fontHeight;
  3652.     GetFontHeight(&fontHeight);
  3653.  
  3654.     float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
  3655.  
  3656.     if (fStyle == B_BLOCK_THUMB) {
  3657.         if (Orientation() == B_HORIZONTAL) {
  3658.             frame.left = floorf(Position() * (_MaxPosition()
  3659.                 - _MinPosition()) + _MinPosition()) - 8;
  3660.             frame.top = 2 + (Label() || fUpdateText ? textHeight + 4 : 0);
  3661.             frame.right = frame.left + 17;
  3662.             frame.bottom = frame.top + fBarThickness + 7;
  3663.         } else {
  3664.             frame.left = floor((frame.Width() - fBarThickness) / 2) - 4;
  3665.             frame.top = floorf(Position() * (_MaxPosition()
  3666.                 - _MinPosition()) + _MinPosition()) - 8;
  3667.             frame.right = frame.left + fBarThickness + 7;
  3668.             frame.bottom = frame.top + 17;
  3669.         }
  3670.     } else {
  3671.         if (Orientation() == B_HORIZONTAL) {
  3672.             frame.left = floorf(Position() * (_MaxPosition()
  3673.                 - _MinPosition()) + _MinPosition()) - 6;
  3674.             frame.right = frame.left + 12;
  3675.             frame.top = 3 + fBarThickness + (Label() ? textHeight + 4 : 0);
  3676.             frame.bottom = frame.top + 8;
  3677.         } else {
  3678.             frame.left = floorf((frame.Width() + fBarThickness) / 2) - 3;
  3679.             frame.top = floorf(Position() * (_MaxPosition()
  3680.                 - _MinPosition())) + _MinPosition() - 6;
  3681.             frame.right = frame.left + 8;
  3682.             frame.bottom = frame.top + 12;
  3683.         }
  3684.     }
  3685.  
  3686.     return frame;
  3687. }
  3688.  
  3689.  
  3690. void
  3691. BSlider::SetFlags(uint32 flags)
  3692. {
  3693.     BControl::SetFlags(flags);
  3694. }
  3695.  
  3696.  
  3697. void
  3698. BSlider::SetResizingMode(uint32 mode)
  3699. {
  3700.     BControl::SetResizingMode(mode);
  3701. }
  3702.  
  3703.  
  3704. void
  3705. BSlider::GetPreferredSize(float* _width, float* _height)
  3706. {
  3707.     BSize preferredSize = PreferredSize();
  3708.  
  3709.     if (Orientation() == B_HORIZONTAL) {
  3710.         if (_width != NULL) {
  3711.             // NOTE: For compatibility reasons, a horizontal BSlider
  3712.             // never shrinks horizontally. This only affects applications
  3713.             // which do not use the new layout system.
  3714.             *_width = max_c(Bounds().Width(), preferredSize.width);
  3715.         }
  3716.  
  3717.         if (_height != NULL)
  3718.             *_height = preferredSize.height;
  3719.     } else {
  3720.         if (_width != NULL)
  3721.             *_width = preferredSize.width;
  3722.  
  3723.         if (_height != NULL) {
  3724.             // NOTE: Similarly, a vertical BSlider never shrinks
  3725.             // vertically. This only affects applications which do not
  3726.             // use the new layout system.
  3727.             *_height = max_c(Bounds().Height(), preferredSize.height);
  3728.         }
  3729.     }
  3730. }
  3731.  
  3732.  
  3733. void
  3734. BSlider::ResizeToPreferred()
  3735. {
  3736.     BControl::ResizeToPreferred();
  3737. }
  3738.  
  3739.  
  3740. status_t
  3741. BSlider::Invoke(BMessage* message)
  3742. {
  3743.     return BControl::Invoke(message);
  3744. }
  3745.  
  3746.  
  3747. BHandler*
  3748. BSlider::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier,
  3749.     int32 command, const char *property)
  3750. {
  3751.     return BControl::ResolveSpecifier(message, index, specifier, command,
  3752.         property);
  3753. }
  3754.  
  3755.  
  3756. status_t
  3757. BSlider::GetSupportedSuites(BMessage* message)
  3758. {
  3759.     return BControl::GetSupportedSuites(message);
  3760. }
  3761.  
  3762.  
  3763. void
  3764. BSlider::SetModificationMessage(BMessage* message)
  3765. {
  3766.     delete fModificationMessage;
  3767.     fModificationMessage = message;
  3768. }
  3769.  
  3770.  
  3771. BMessage*
  3772. BSlider::ModificationMessage() const
  3773. {
  3774.     return fModificationMessage;
  3775. }
  3776.  
  3777.  
  3778. void
  3779. BSlider::SetSnoozeAmount(int32 snoozeTime)
  3780. {
  3781.     if (snoozeTime < 10000)
  3782.         snoozeTime = 10000;
  3783.     else if (snoozeTime > 1000000)
  3784.         snoozeTime = 1000000;
  3785.  
  3786.     fSnoozeAmount = snoozeTime;
  3787. }
  3788.  
  3789.  
  3790. int32
  3791. BSlider::SnoozeAmount() const
  3792. {
  3793.     return fSnoozeAmount;
  3794. }
  3795.  
  3796.  
  3797. void
  3798. BSlider::SetKeyIncrementValue(int32 incrementValue)
  3799. {
  3800.     fKeyIncrementValue = incrementValue;
  3801. }
  3802.  
  3803.  
  3804. int32
  3805. BSlider::KeyIncrementValue() const
  3806. {
  3807.     return fKeyIncrementValue;
  3808. }
  3809.  
  3810.  
  3811. void
  3812. BSlider::SetHashMarkCount(int32 hashMarkCount)
  3813. {
  3814.     fHashMarkCount = hashMarkCount;
  3815.     Invalidate();
  3816. }
  3817.  
  3818.  
  3819. int32
  3820. BSlider::HashMarkCount() const
  3821. {
  3822.     return fHashMarkCount;
  3823. }
  3824.  
  3825.  
  3826. void
  3827. BSlider::SetHashMarks(hash_mark_location where)
  3828. {
  3829.     fHashMarks = where;
  3830. // TODO: enable if the hashmark look is influencing the control size!
  3831. //  InvalidateLayout();
  3832.     Invalidate();
  3833. }
  3834.  
  3835.  
  3836. hash_mark_location
  3837. BSlider::HashMarks() const
  3838. {
  3839.     return fHashMarks;
  3840. }
  3841.  
  3842.  
  3843. void
  3844. BSlider::SetStyle(thumb_style style)
  3845. {
  3846.     fStyle = style;
  3847.     InvalidateLayout();
  3848.     Invalidate();
  3849. }
  3850.  
  3851.  
  3852. thumb_style
  3853. BSlider::Style() const
  3854. {
  3855.     return fStyle;
  3856. }
  3857.  
  3858.  
  3859. void
  3860. BSlider::SetBarColor(rgb_color barColor)
  3861. {
  3862.     fBarColor = barColor;
  3863.     Invalidate(BarFrame());
  3864. }
  3865.  
  3866.  
  3867. rgb_color
  3868. BSlider::BarColor() const
  3869. {
  3870.     return fBarColor;
  3871. }
  3872.  
  3873.  
  3874. void
  3875. BSlider::UseFillColor(bool useFill, const rgb_color* barColor)
  3876. {
  3877.     fUseFillColor = useFill;
  3878.  
  3879.     if (useFill && barColor)
  3880.         fFillColor = *barColor;
  3881.  
  3882.     Invalidate(BarFrame());
  3883. }
  3884.  
  3885.  
  3886. bool
  3887. BSlider::FillColor(rgb_color* barColor) const
  3888. {
  3889.     if (barColor && fUseFillColor)
  3890.         *barColor = fFillColor;
  3891.  
  3892.     return fUseFillColor;
  3893. }
  3894.  
  3895.  
  3896. BView*
  3897. BSlider::OffscreenView() const
  3898. {
  3899. #if USE_OFF_SCREEN_VIEW
  3900.     return fOffScreenView;
  3901. #else
  3902.     return (BView*)this;
  3903. #endif
  3904. }
  3905.  
  3906.  
  3907. orientation
  3908. BSlider::Orientation() const
  3909. {
  3910.     return fOrientation;
  3911. }
  3912.  
  3913.  
  3914. void
  3915. BSlider::SetOrientation(orientation posture)
  3916. {
  3917.     if (fOrientation == posture)
  3918.         return;
  3919.  
  3920.     fOrientation = posture;
  3921.     InvalidateLayout();
  3922.     Invalidate();
  3923. }
  3924.  
  3925.  
  3926. float
  3927. BSlider::BarThickness() const
  3928. {
  3929.     return fBarThickness;
  3930. }
  3931.  
  3932.  
  3933. void
  3934. BSlider::SetBarThickness(float thickness)
  3935. {
  3936.     if (thickness < 1.0)
  3937.         thickness = 1.0;
  3938.     else
  3939.         thickness = roundf(thickness);
  3940.  
  3941.     if (thickness != fBarThickness) {
  3942.         // calculate invalid barframe and extend by hashmark size
  3943.         float hInset = 0.0;
  3944.         float vInset = 0.0;
  3945.         if (fOrientation == B_HORIZONTAL)
  3946.             vInset = -6.0;
  3947.         else
  3948.             hInset = -6.0;
  3949.         BRect invalid = BarFrame().InsetByCopy(hInset, vInset) | ThumbFrame();
  3950.  
  3951.         fBarThickness = thickness;
  3952.  
  3953.         invalid = invalid | BarFrame().InsetByCopy(hInset, vInset)
  3954.             | ThumbFrame();
  3955.         Invalidate(invalid);
  3956.         InvalidateLayout();
  3957.     }
  3958. }
  3959.  
  3960.  
  3961. void
  3962. BSlider::SetFont(const BFont *font, uint32 properties)
  3963. {
  3964.     BControl::SetFont(font, properties);
  3965.  
  3966. #if USE_OFF_SCREEN_VIEW
  3967.     if (fOffScreenView && fOffScreenBits) {
  3968.         if (fOffScreenBits->Lock()) {
  3969.             fOffScreenView->SetFont(font, properties);
  3970.             fOffScreenBits->Unlock();
  3971.         }
  3972.     }
  3973. #endif
  3974.  
  3975.     InvalidateLayout();
  3976. }
  3977.  
  3978.  
  3979. void
  3980. BSlider::SetLimits(int32 minimum, int32 maximum)
  3981. {
  3982.     if (minimum <= maximum) {
  3983.         fMinValue = minimum;
  3984.         fMaxValue = maximum;
  3985.  
  3986.         int32 value = Value();
  3987.         value = max_c(minimum, value);
  3988.         value = min_c(maximum, value);
  3989.  
  3990.         if (value != Value()) {
  3991.             SetValue(value);
  3992.         }
  3993.     }
  3994. }
  3995.  
  3996.  
  3997. float
  3998. BSlider::MaxUpdateTextWidth()
  3999. {
  4000.     // very simplistic implementation that assumes the string will be widest
  4001.     // at the maximum value
  4002.     int32 value = Value();
  4003.     SetValueNoUpdate(fMaxValue);
  4004.     float width = StringWidth(UpdateText());
  4005.     SetValueNoUpdate(value);
  4006.     // in case the derived class uses a fixed buffer, the contents
  4007.     // should be reset for the old value
  4008.     UpdateText();
  4009.     return width;
  4010. }
  4011.  
  4012.  
  4013. // #pragma mark - layout related
  4014.  
  4015.  
  4016. BSize
  4017. BSlider::MinSize()
  4018. {
  4019.     return BLayoutUtils::ComposeSize(ExplicitMinSize(),
  4020.         _ValidateMinSize());
  4021. }
  4022.  
  4023.  
  4024. BSize
  4025. BSlider::MaxSize()
  4026. {
  4027.     BSize maxSize = _ValidateMinSize();
  4028.     if (fOrientation == B_HORIZONTAL)
  4029.         maxSize.width = B_SIZE_UNLIMITED;
  4030.     else
  4031.         maxSize.height = B_SIZE_UNLIMITED;
  4032.     return BLayoutUtils::ComposeSize(ExplicitMaxSize(), maxSize);
  4033. }
  4034.  
  4035.  
  4036. BSize
  4037. BSlider::PreferredSize()
  4038. {
  4039.     BSize preferredSize = _ValidateMinSize();
  4040.     if (fOrientation == B_HORIZONTAL)
  4041.         preferredSize.width = max_c(100.0, preferredSize.width);
  4042.     else
  4043.         preferredSize.height = max_c(100.0, preferredSize.height);
  4044.     return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), preferredSize);
  4045. }
  4046.  
  4047.  
  4048. void
  4049. BSlider::LayoutInvalidated(bool descendants)
  4050. {
  4051.     // invalidate cached preferred size
  4052.     fMinSize.Set(-1, -1);
  4053. }
  4054.  
  4055.  
  4056. // #pragma mark - private
  4057.  
  4058. void
  4059. BSlider::_DrawBlockThumb()
  4060. {
  4061.     BRect frame = ThumbFrame();
  4062.     BView *view = OffscreenView();
  4063.  
  4064.     if (be_control_look != NULL) {
  4065.         rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
  4066.         uint32 flags = be_control_look->Flags(this);
  4067.         be_control_look->DrawSliderThumb(view, frame, frame, base, flags,
  4068.             fOrientation);
  4069.         return;
  4070.     }
  4071.  
  4072.     rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
  4073.     rgb_color lighten2;
  4074.     rgb_color lighten1;
  4075.     rgb_color darken2;
  4076.     rgb_color darken3;
  4077.     rgb_color darkenmax;
  4078.  
  4079.     if (IsEnabled()) {
  4080.         lighten2    = tint_color(no_tint, B_LIGHTEN_2_TINT);
  4081.         lighten1    = no_tint;
  4082.         darken2     = tint_color(no_tint, B_DARKEN_2_TINT);
  4083.         darken3     = tint_color(no_tint, B_DARKEN_3_TINT);
  4084.         darkenmax   = tint_color(no_tint, B_DARKEN_MAX_TINT);
  4085.     } else {
  4086.         lighten2    = tint_color(no_tint, B_LIGHTEN_2_TINT);
  4087.         lighten1    = tint_color(no_tint, B_LIGHTEN_1_TINT);
  4088.         darken2     = tint_color(no_tint, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0);
  4089.         darken3     = tint_color(no_tint, B_DARKEN_1_TINT);
  4090.         darkenmax   = tint_color(no_tint, B_DARKEN_3_TINT);
  4091.     }
  4092.  
  4093.     // blank background for shadow
  4094.     // ToDo: this also draws over the hash marks (though it's not *that* noticeable)
  4095.     view->SetHighColor(no_tint);
  4096.     view->StrokeLine(BPoint(frame.left, frame.top),
  4097.                      BPoint(frame.left, frame.top));
  4098.  
  4099.     BRect barFrame = BarFrame();
  4100.     if (barFrame.right >= frame.right) {
  4101.         // leave out barFrame from shadow background clearing
  4102.         view->StrokeLine(BPoint(frame.right, frame.top),
  4103.                          BPoint(frame.right, barFrame.top - 1.0f));
  4104.         view->StrokeLine(BPoint(frame.right, barFrame.bottom + 1.0f),
  4105.                          BPoint(frame.right, frame.bottom));
  4106.     } else {
  4107.         view->StrokeLine(BPoint(frame.right, frame.top),
  4108.                          BPoint(frame.right, frame.bottom));
  4109.     }
  4110.  
  4111.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  4112.                      BPoint(frame.right - 1.0f, frame.bottom));
  4113.     view->StrokeLine(BPoint(frame.left, frame.bottom - 1.0f),
  4114.                      BPoint(frame.left, frame.bottom - 1.0f));
  4115.     view->StrokeLine(BPoint(frame.right - 1.0f, frame.top),
  4116.                      BPoint(frame.right - 1.0f, frame.top));
  4117.  
  4118.     // Outline (top, left)
  4119.     view->SetHighColor(darken3);
  4120.     view->StrokeLine(BPoint(frame.left, frame.bottom - 2.0f),
  4121.                      BPoint(frame.left, frame.top + 1.0f));
  4122.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.top),
  4123.                      BPoint(frame.right - 2.0f, frame.top));
  4124.  
  4125.     // Shadow
  4126.     view->SetHighColor(0, 0, 0, IsEnabled() ? 100 : 50);
  4127.     view->SetDrawingMode(B_OP_ALPHA);
  4128.     view->StrokeLine(BPoint(frame.right, frame.top + 2.0f),
  4129.                      BPoint(frame.right, frame.bottom - 1.0f));
  4130.     view->StrokeLine(BPoint(frame.left + 2.0f, frame.bottom),
  4131.                      BPoint(frame.right - 1.0f, frame.bottom));
  4132.  
  4133.     view->SetDrawingMode(B_OP_COPY);
  4134.     view->SetHighColor(darken3);
  4135.     view->StrokeLine(BPoint(frame.right - 1.0f, frame.bottom - 1.0f),
  4136.                      BPoint(frame.right - 1.0f, frame.bottom - 1.0f));
  4137.  
  4138.  
  4139.     // First bevel
  4140.     frame.InsetBy(1.0f, 1.0f);
  4141.  
  4142.     view->SetHighColor(darkenmax);
  4143.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  4144.                      BPoint(frame.right - 1.0f, frame.bottom));
  4145.     view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f),
  4146.                      BPoint(frame.right, frame.top));
  4147.  
  4148.     view->SetHighColor(lighten2);
  4149.     view->StrokeLine(BPoint(frame.left, frame.top),
  4150.                      BPoint(frame.left, frame.bottom - 1.0f));
  4151.     view->StrokeLine(BPoint(frame.left + 1.0f, frame.top),
  4152.                      BPoint(frame.right - 1.0f, frame.top));
  4153.  
  4154.     frame.InsetBy(1.0f, 1.0f);
  4155.  
  4156.     view->FillRect(BRect(frame.left, frame.top, frame.right - 1.0f, frame.bottom - 1.0f));
  4157.  
  4158.     // Second bevel and center dots
  4159.     view->SetHighColor(darken2);
  4160.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  4161.                      BPoint(frame.right, frame.bottom));
  4162.     view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f),
  4163.                      BPoint(frame.right, frame.top));
  4164.  
  4165.     if (Orientation() == B_HORIZONTAL) {
  4166.         view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 2.0f),
  4167.                          BPoint(frame.left + 6.0f, frame.top + 2.0f));
  4168.         view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 4.0f),
  4169.                          BPoint(frame.left + 6.0f, frame.top + 4.0f));
  4170.         view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 6.0f),
  4171.                          BPoint(frame.left + 6.0f, frame.top + 6.0f));
  4172.     } else {
  4173.         view->StrokeLine(BPoint(frame.left + 2.0f, frame.top + 6.0f),
  4174.                          BPoint(frame.left + 2.0f, frame.top + 6.0f));
  4175.         view->StrokeLine(BPoint(frame.left + 4.0f, frame.top + 6.0f),
  4176.                          BPoint(frame.left + 4.0f, frame.top + 6.0f));
  4177.         view->StrokeLine(BPoint(frame.left + 6.0f, frame.top + 6.0f),
  4178.                          BPoint(frame.left + 6.0f, frame.top + 6.0f));
  4179.     }
  4180.  
  4181.     frame.InsetBy(1.0f, 1.0f);
  4182.  
  4183.     // Third bevel
  4184.     view->SetHighColor(lighten1);
  4185.     view->StrokeLine(BPoint(frame.left, frame.bottom),
  4186.                      BPoint(frame.right, frame.bottom));
  4187.     view->StrokeLine(BPoint(frame.right, frame.bottom - 1.0f),
  4188.                      BPoint(frame.right, frame.top));
  4189. }
  4190.  
  4191.  
  4192. void
  4193. BSlider::_DrawTriangleThumb()
  4194. {
  4195.     BRect frame = ThumbFrame();
  4196.     BView *view = OffscreenView();
  4197.  
  4198.     if (be_control_look != NULL) {
  4199.         rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
  4200.         uint32 flags = be_control_look->Flags(this);
  4201.         be_control_look->DrawSliderTriangle(view, frame, frame, base, flags,
  4202.             fOrientation);
  4203.         return;
  4204.     }
  4205.  
  4206.     rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
  4207.     rgb_color lightenmax;
  4208.     rgb_color lighten1;
  4209.     rgb_color darken2;
  4210.     rgb_color darken3;
  4211.     rgb_color darkenmax;
  4212.  
  4213.     if (IsEnabled()) {
  4214.         lightenmax  = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
  4215.         lighten1    = no_tint;
  4216.         darken2     = tint_color(no_tint, B_DARKEN_2_TINT);
  4217.         darken3     = tint_color(no_tint, B_DARKEN_3_TINT);
  4218.         darkenmax   = tint_color(no_tint, B_DARKEN_MAX_TINT);
  4219.     } else {
  4220.         lightenmax  = tint_color(no_tint, B_LIGHTEN_2_TINT);
  4221.         lighten1    = tint_color(no_tint, B_LIGHTEN_1_TINT);
  4222.         darken2     = tint_color(no_tint, (B_NO_TINT + B_DARKEN_1_TINT) / 2);
  4223.         darken3     = tint_color(no_tint, B_DARKEN_1_TINT);
  4224.         darkenmax   = tint_color(no_tint, B_DARKEN_3_TINT);
  4225.     }
  4226.  
  4227.     if (Orientation() == B_HORIZONTAL) {
  4228.         view->SetHighColor(lighten1);
  4229.         view->FillTriangle(
  4230.             BPoint(frame.left + 1, frame.bottom - 3),
  4231.             BPoint((frame.left + frame.right) / 2, frame.top + 1),
  4232.             BPoint(frame.right - 1, frame.bottom - 3));
  4233.  
  4234.         view->SetHighColor(no_tint);
  4235.         view->StrokeLine(BPoint(frame.right - 2, frame.bottom - 3),
  4236.             BPoint(frame.left + 3, frame.bottom - 3));
  4237.  
  4238.         view->SetHighColor(darkenmax);
  4239.         view->StrokeLine(BPoint(frame.left, frame.bottom - 1),
  4240.             BPoint(frame.right, frame.bottom - 1));
  4241.         view->StrokeLine(BPoint(frame.right, frame.bottom - 2),
  4242.             BPoint((frame.left + frame.right) / 2, frame.top));
  4243.  
  4244.         view->SetHighColor(darken2);
  4245.         view->StrokeLine(BPoint(frame.right - 1, frame.bottom - 2),
  4246.             BPoint(frame.left + 1, frame.bottom - 2));
  4247.         view->SetHighColor(darken3);
  4248.         view->StrokeLine(BPoint(frame.left, frame.bottom - 2),
  4249.             BPoint((frame.left + frame.right) / 2 - 1, frame.top + 1));
  4250.  
  4251.         view->SetHighColor(lightenmax);
  4252.         view->StrokeLine(BPoint(frame.left + 2, frame.bottom - 3),
  4253.             BPoint((frame.left + frame.right) / 2, frame.top + 1));
  4254.  
  4255.         // Shadow
  4256.         view->SetHighColor(0, 0, 0, IsEnabled() ? 80 : 40);
  4257.         view->SetDrawingMode(B_OP_ALPHA);
  4258.         view->StrokeLine(BPoint(frame.left + 1, frame.bottom),
  4259.             BPoint(frame.right, frame.bottom));
  4260.     } else {
  4261.         view->SetHighColor(lighten1);
  4262.         view->FillTriangle(
  4263.             BPoint(frame.left, (frame.top + frame.bottom) / 2),
  4264.             BPoint(frame.right - 1, frame.top + 1),
  4265.             BPoint(frame.right - 1, frame.bottom - 1));
  4266.  
  4267.         view->SetHighColor(darkenmax);
  4268.         view->StrokeLine(BPoint(frame.right - 1, frame.top),
  4269.             BPoint(frame.right - 1, frame.bottom));
  4270.         view->StrokeLine(BPoint(frame.right - 1, frame.bottom),
  4271.             BPoint(frame.right - 2, frame.bottom));
  4272.  
  4273.         view->SetHighColor(darken2);
  4274.         view->StrokeLine(BPoint(frame.right - 2, frame.top + 2),
  4275.             BPoint(frame.right - 2, frame.bottom - 1));
  4276.         view->StrokeLine(
  4277.             BPoint(frame.left, (frame.top + frame.bottom) / 2),
  4278.             BPoint(frame.right - 2, frame.top));
  4279.         view->SetHighColor(darken3);
  4280.         view->StrokeLine(
  4281.             BPoint(frame.left + 1, (frame.top + frame.bottom) / 2 + 1),
  4282.             BPoint(frame.right - 3, frame.bottom - 1));
  4283.  
  4284.         view->SetHighColor(lightenmax);
  4285.         view->StrokeLine(
  4286.             BPoint(frame.left + 1, (frame.top + frame.bottom) / 2),
  4287.             BPoint(frame.right - 2, frame.top + 1));
  4288.  
  4289.         // Shadow
  4290.         view->SetHighColor(0, 0, 0, IsEnabled() ? 80 : 40);
  4291.         view->SetDrawingMode(B_OP_ALPHA);
  4292.         view->StrokeLine(BPoint(frame.right, frame.top + 1),
  4293.             BPoint(frame.right, frame.bottom));
  4294.     }
  4295.  
  4296.     view->SetDrawingMode(B_OP_COPY);
  4297. }
  4298.  
  4299.  
  4300. BPoint
  4301. BSlider::_Location() const
  4302. {
  4303.     return fLocation;
  4304. }
  4305.  
  4306.  
  4307. void
  4308. BSlider::_SetLocationForValue(int32 value)
  4309. {
  4310.     BPoint loc;
  4311.     float range = (float)(fMaxValue - fMinValue);
  4312.     if (range == 0)
  4313.         range = 1;
  4314.  
  4315.     float pos = (float)(value - fMinValue) / range *
  4316.         (_MaxPosition() - _MinPosition());
  4317.  
  4318.     if (fOrientation == B_HORIZONTAL) {
  4319.         loc.x = ceil(_MinPosition() + pos);
  4320.         loc.y = 0;
  4321.     } else {
  4322.         loc.x = 0;
  4323.         loc.y = floor(_MaxPosition() - pos);
  4324.     }
  4325.     fLocation = loc;
  4326. }
  4327.  
  4328.  
  4329. float
  4330. BSlider::_MinPosition() const
  4331. {
  4332.     if (fOrientation == B_HORIZONTAL)
  4333.         return BarFrame().left + 1.0f;
  4334.  
  4335.     return BarFrame().bottom - 1.0f;
  4336. }
  4337.  
  4338.  
  4339. float
  4340. BSlider::_MaxPosition() const
  4341. {
  4342.     if (fOrientation == B_HORIZONTAL)
  4343.         return BarFrame().right - 1.0f;
  4344.  
  4345.     return BarFrame().top + 1.0f;
  4346. }
  4347.  
  4348.  
  4349. BSize
  4350. BSlider::_ValidateMinSize()
  4351. {
  4352.     if (fMinSize.width >= 0) {
  4353.         // the preferred size is up to date
  4354.         return fMinSize;
  4355.     }
  4356.  
  4357.     font_height fontHeight;
  4358.     GetFontHeight(&fontHeight);
  4359.  
  4360.     float width = 0.0;
  4361.     float height = 0.0;
  4362.  
  4363.     if (fMaxUpdateTextWidth < 0.0)
  4364.         fMaxUpdateTextWidth = MaxUpdateTextWidth();
  4365.  
  4366.     if (Orientation() == B_HORIZONTAL) {
  4367.         height = 12.0 + fBarThickness;
  4368.         int32 rows = 0;
  4369.  
  4370.         float labelWidth = 0;
  4371.         int32 labelRows = 0;
  4372.         float labelSpacing = StringWidth("M") * 2;
  4373.         if (Label()) {
  4374.             labelWidth = StringWidth(Label());
  4375.             labelRows = 1;
  4376.         }
  4377.         if (fMaxUpdateTextWidth > 0.0) {
  4378.             if (labelWidth > 0)
  4379.                 labelWidth += labelSpacing;
  4380.             labelWidth += fMaxUpdateTextWidth;
  4381.             labelRows = 1;
  4382.         }
  4383.         rows += labelRows;
  4384.  
  4385.         if (MinLimitLabel())
  4386.             width = StringWidth(MinLimitLabel());
  4387.         if (MaxLimitLabel()) {
  4388.             // some space between the labels
  4389.             if (MinLimitLabel())
  4390.                 width += labelSpacing;
  4391.  
  4392.             width += StringWidth(MaxLimitLabel());
  4393.         }
  4394.  
  4395.         if (labelWidth > width)
  4396.             width = labelWidth;
  4397.         if (width < 32.0)
  4398.             width = 32.0;
  4399.  
  4400.         if (MinLimitLabel() || MaxLimitLabel())
  4401.             rows++;
  4402.  
  4403.         height += rows * (ceilf(fontHeight.ascent)
  4404.             + ceilf(fontHeight.descent) + 4.0);
  4405.     } else {
  4406.         // B_VERTICAL
  4407.         width = 12.0 + fBarThickness;
  4408.         height = 32.0;
  4409.  
  4410.         float lineHeightNoLeading = ceilf(fontHeight.ascent)
  4411.             + ceilf(fontHeight.descent);
  4412.         float lineHeight = lineHeightNoLeading + ceilf(fontHeight.leading);
  4413.  
  4414.         // find largest label
  4415.         float labelWidth = 0;
  4416.         if (Label()) {
  4417.             labelWidth = StringWidth(Label());
  4418.             height += lineHeightNoLeading;
  4419.         }
  4420.         if (MaxLimitLabel()) {
  4421.             labelWidth = max_c(labelWidth, StringWidth(MaxLimitLabel()));
  4422.             height += Label() ? lineHeight : lineHeightNoLeading;
  4423.         }
  4424.         if (MinLimitLabel()) {
  4425.             labelWidth = max_c(labelWidth, StringWidth(MinLimitLabel()));
  4426.             height += lineHeightNoLeading;
  4427.         }
  4428.         if (fMaxUpdateTextWidth > 0.0) {
  4429.             labelWidth = max_c(labelWidth, fMaxUpdateTextWidth);
  4430.             height += MinLimitLabel() ? lineHeight : lineHeightNoLeading;
  4431.         }
  4432.  
  4433.         width = max_c(labelWidth, width);
  4434.     }
  4435.  
  4436.     fMinSize.width = width;
  4437.     fMinSize.height = height;
  4438.  
  4439.     ResetLayoutInvalidation();
  4440.  
  4441.     return fMinSize;
  4442. }
  4443.  
  4444.  
  4445. // #pragma mark - FBC padding
  4446.  
  4447. void BSlider::_ReservedSlider6() {}
  4448. void BSlider::_ReservedSlider7() {}
  4449. void BSlider::_ReservedSlider8() {}
  4450. void BSlider::_ReservedSlider9() {}
  4451. void BSlider::_ReservedSlider10() {}
  4452. void BSlider::_ReservedSlider11() {}
  4453. void BSlider::_ReservedSlider12() {}
  4454.  
  4455.  
  4456. BSlider &
  4457. BSlider::operator=(const BSlider &)
  4458. {
  4459.     return *this;
  4460. }
  4461.  
  4462.  
  4463. //  #pragma mark - BeOS compatibility
  4464.  
  4465.  
  4466. #if __GNUC__ < 3
  4467.  
  4468. extern "C" void
  4469. GetLimits__7BSliderPlT1(BSlider* slider, int32* minimum, int32* maximum)
  4470. {
  4471.     slider->GetLimits(minimum, maximum);
  4472. }
  4473.  
  4474.  
  4475. extern "C" void
  4476. _ReservedSlider4__7BSlider(BSlider *slider, int32 minimum, int32 maximum)
  4477. {
  4478.     slider->BSlider::SetLimits(minimum, maximum);
  4479. }
  4480.  
  4481. extern "C" float
  4482. _ReservedSlider5__7BSlider(BSlider *slider)
  4483. {
  4484.     return slider->BSlider::MaxUpdateTextWidth();
  4485. }
  4486.  
  4487.  
  4488. extern "C" void
  4489. _ReservedSlider1__7BSlider(BSlider* slider, orientation _orientation)
  4490. {
  4491.     slider->BSlider::SetOrientation(_orientation);
  4492. }
  4493.  
  4494.  
  4495. extern "C" void
  4496. _ReservedSlider2__7BSlider(BSlider* slider, float thickness)
  4497. {
  4498.     slider->BSlider::SetBarThickness(thickness);
  4499. }
  4500.  
  4501.  
  4502. extern "C" void
  4503. _ReservedSlider3__7BSlider(BSlider* slider, const BFont* font,
  4504.     uint32 properties)
  4505. {
  4506.     slider->BSlider::SetFont(font, properties);
  4507. }
  4508.  
  4509.  
  4510. #endif  // __GNUC__ < 3
  4511.  
  4512.  
  4513. extern "C" void
  4514. B_IF_GCC_2(InvalidateLayout__7BSliderb, _ZN7BSlider16InvalidateLayoutEb)(
  4515.     BView* view, bool descendants)
  4516. {
  4517.     perform_data_layout_invalidated data;
  4518.     data.descendants = descendants;
  4519.  
  4520.     view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
  4521. }
Advertisement
Add Comment
Please, Sign In to add comment