Ticket #7996: InterfaceKit-RangeSlider-20110922.diff

File InterfaceKit-RangeSlider-20110922.diff, 25.1 KB (added by jwlh172, 13 years ago)
  • src/kits/interface/ControlLook.cpp

     
    931931
    932932void
    933933BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
     934    const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor,
     935    float sliderScale, float offsetSliderScale, uint32 flags, enum orientation orientation)
     936{
     937    if (!rect.IsValid() || !rect.Intersects(updateRect))
     938        return;
     939
     940    // separate the bar into three regions
     941    float sliderPosition;
     942    float offsetSliderPosition;
     943    BRect leftBarSide = rect;
     944    BRect midBarSide = rect;
     945    BRect rightBarSide = rect;
     946
     947    if (orientation == B_HORIZONTAL) {
     948        sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2)
     949            * sliderScale);
     950        offsetSliderPosition = floorf(rect.left + 2 + (rect.Width() - 2)
     951            * offsetSliderScale);
     952        leftBarSide.right = offsetSliderPosition - 1;
     953        midBarSide.left = offsetSliderPosition;
     954        midBarSide.right = sliderPosition - 1;
     955        rightBarSide.left = sliderPosition;
     956    } else {
     957        // NOTE: position is reverse of coords
     958        sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2)
     959            * (1.0 - sliderScale));
     960        offsetSliderPosition = floorf(rect.top + 2 + (rect.Height() - 2)
     961            * (1.0 - offsetSliderScale));
     962        leftBarSide.top = offsetSliderPosition;
     963        midBarSide.bottom = offsetSliderPosition - 1;
     964        midBarSide.top = sliderPosition;
     965        rightBarSide.bottom = sliderPosition - 1;
     966    }
     967
     968    // fill the background for the corners, exclude the middle bar for now
     969    BRegion region(rect);
     970    region.Exclude(rightBarSide);
     971    region.Exclude(midBarSide);
     972    view->ConstrainClippingRegion(&region);
     973
     974    view->PushState();
     975
     976    DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags,
     977        orientation);
     978
     979    view->PopState();
     980   
     981    region.Set(rect);
     982    region.Exclude(leftBarSide);
     983    region.Exclude(rightBarSide);
     984    view->ConstrainClippingRegion(&region);
     985   
     986    view->PushState();
     987   
     988    DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags,
     989        orientation);
     990       
     991    view->PopState();
     992
     993    region.Set(rect);
     994    region.Exclude(leftBarSide);
     995    region.Exclude(midBarSide);
     996    view->ConstrainClippingRegion(&region);
     997
     998    view->PushState();
     999
     1000    DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags,
     1001        orientation);
     1002
     1003    view->PopState();
     1004
     1005    view->ConstrainClippingRegion(NULL);
     1006}
     1007
     1008
     1009void
     1010BControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect,
    9341011    const rgb_color& base, rgb_color fillColor, uint32 flags,
    9351012    enum orientation orientation)
    9361013{
  • src/kits/interface/Slider.cpp

     
    3232
    3333BSlider::BSlider(BRect frame, const char* name, const char* label,
    3434            BMessage* message, int32 minValue, int32 maxValue,
    35             thumb_style thumbType, uint32 resizingMode, uint32 flags)
     35            thumb_style thumbType, uint32 resizingMode, uint32 flags,
     36            bool dualMode)
    3637    : BControl(frame, name, label, message, resizingMode, flags),
    3738    fModificationMessage(NULL),
    3839    fSnoozeAmount(20000),
     
    5253    fOrientation(B_HORIZONTAL),
    5354    fBarThickness(6.0)
    5455{
     56    fDualMode = dualMode;
     57   
    5558    _InitBarColor();
    5659
    5760    _InitObject();
     
    6265BSlider::BSlider(BRect frame, const char *name, const char *label,
    6366            BMessage *message, int32 minValue, int32 maxValue,
    6467            orientation posture, thumb_style thumbType, uint32 resizingMode,
    65             uint32 flags)
     68            uint32 flags, bool dualMode)
    6669    : BControl(frame, name, label, message, resizingMode, flags),
    6770    fModificationMessage(NULL),
    6871    fSnoozeAmount(20000),
     
    8285    fOrientation(posture),
    8386    fBarThickness(6.0)
    8487{
     88    fDualMode = dualMode;
     89   
    8590    _InitBarColor();
    8691
    8792    _InitObject();
     
    9196
    9297BSlider::BSlider(const char *name, const char *label, BMessage *message,
    9398            int32 minValue, int32 maxValue, orientation posture,
    94             thumb_style thumbType, uint32 flags)
     99            thumb_style thumbType, uint32 flags, bool dualMode)
    95100    : BControl(name, label, message, flags),
    96101    fModificationMessage(NULL),
    97102    fSnoozeAmount(20000),
     
    111116    fOrientation(posture),
    112117    fBarThickness(6.0)
    113118{
     119    fDualMode = dualMode;
     120   
    114121    _InitBarColor();
    115122
    116123    _InitObject();
     
    190197        fBarThickness = bthickness;
    191198    else
    192199        fBarThickness = 6.0f;
     200   
     201    if (archive->FindBool("_dualmode", &fDualMode) != B_OK)
     202        fDualMode = false;
     203   
     204    if (archive->FindInt32("_offsetvalue", &fOffsetValue) != B_OK)
     205        fOffsetValue = 0;
    193206
    194207    _InitObject();
    195208}
     
    225238void
    226239BSlider::_InitObject()
    227240{
     241    fOffsetLocation.x = 0;
     242    fOffsetLocation.y = 0;
     243    fOffsetInitialLocation.x = 0;
     244    fOffsetInitialLocation.y = 0;
     245    fOffsetValue = fMinValue;
     246   
    228247    fLocation.x = 0;
    229248    fLocation.y = 0;
    230249    fInitialLocation.x = 0;
     
    290309        ret = archive->AddInt32("_orient", fOrientation);
    291310    if (ret == B_OK)
    292311        ret = archive->AddFloat("_bthickness", fBarThickness);
     312   
     313    if (ret == B_OK)
     314        ret = archive->AddBool("_dualmode", fDualMode);
     315    if (ret == B_OK)
     316        ret = archive->AddInt32("_offsetvalue", fOffsetValue);
    293317
    294318    return ret;
    295319}
     
    398422        // makes sure the value is within valid bounds
    399423    _SetLocationForValue(Value());
    400424        // makes sure the location is correct
     425    if (DualMode()) {
     426        value = OffsetValue();
     427        SetOffsetValue(value);
     428        _SetOffsetLocationForValue(OffsetValue());
     429    }
    401430    UpdateTextChanged();
    402431}
    403432
     
    502531            return;
    503532    }
    504533
    505     if (newValue < fMinValue)
    506         newValue = fMinValue;
     534    if (DualMode()) {
     535        if (newValue < OffsetValue())
     536            newValue = OffsetValue();
     537    } else {
     538        if (newValue < fMinValue)
     539            newValue = fMinValue;
     540    }
    507541    if (newValue > fMaxValue)
    508542        newValue = fMaxValue;
    509543
     
    566600    if (!IsEnabled())
    567601        return;
    568602
    569     if (BarFrame().Contains(point) || ThumbFrame().Contains(point))
     603    if (ThumbFrame().Contains(point) && !(Value() == fMaxValue && DualMode()
     604        && ThumbFrame().Intersects(OffsetThumbFrame()))) {
    570605        fInitialLocation = _Location();
    571606
    572     uint32 buttons;
    573     GetMouse(&point, &buttons, true);
     607        uint32 buttons;
     608        GetMouse(&point, &buttons, true);
     609   
     610        _ConstrainPoint(point, fInitialLocation);
     611        SetValue(ValueForPoint(point));
     612   
     613        if (_Location() != fInitialLocation)
     614            InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
     615   
     616        if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
     617            _SetTrackingOffset(false);
     618            SetTracking(true);
     619            SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
     620        } else {
     621            // synchronous mouse tracking
     622            BPoint prevPoint;
     623   
     624            while (buttons) {
     625                prevPoint = point;
     626   
     627                snooze(SnoozeAmount());
     628                GetMouse(&point, &buttons, true);
     629   
     630                if (_ConstrainPoint(point, prevPoint)) {
     631                    int32 value = ValueForPoint(point);
     632                    if (value != Value()) {
     633                        SetValue(value);
     634                        InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
     635                    }
     636                }
     637            }
     638            if (_Location() != fInitialLocation)
     639                Invoke();
     640        }
     641    } else if (DualMode() && OffsetThumbFrame().Contains(point)) {
     642        fOffsetInitialLocation = _OffsetLocation();
    574643
    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);
     644        uint32 buttons;
     645        GetMouse(&point, &buttons, true);
     646   
     647        _ConstrainPoint(point, fOffsetInitialLocation);
     648        SetOffsetValue(ValueForPoint(point));
     649   
     650        if (_OffsetLocation() != fOffsetInitialLocation)
     651            InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
     652   
     653        if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
     654            _SetTrackingOffset(true);
     655            SetTracking(true);
     656            SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
     657        } else {
     658            // synchronous mouse tracking
     659            BPoint prevPoint;
     660   
     661            while (buttons) {
     662                prevPoint = point;
     663   
     664                snooze(SnoozeAmount());
     665                GetMouse(&point, &buttons, true);
     666   
     667                if (_ConstrainPoint(point, prevPoint)) {
     668                    int32 value = ValueForPoint(point);
     669                    if (value != OffsetValue()) {
     670                        SetOffsetValue(value);
     671                        InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
     672                    }
    599673                }
    600674            }
     675            if (_OffsetLocation() != fOffsetInitialLocation)
     676                Invoke();
    601677        }
    602         if (_Location() != fInitialLocation)
    603             Invoke();
    604678    }
    605679}
    606680
     
    608682void
    609683BSlider::MouseUp(BPoint point)
    610684{
    611     if (IsTracking()) {
     685    if (IsTracking() && _TrackingOffset()) {
     686        if (_OffsetLocation() != fOffsetInitialLocation)
     687            Invoke();
     688
     689        SetTracking(false);
     690        _SetTrackingOffset(false);
     691    } else if (IsTracking()) {
    612692        if (_Location() != fInitialLocation)
    613693            Invoke();
    614694
     
    621701void
    622702BSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
    623703{
    624     if (IsTracking()) {
     704    if (IsTracking() && _TrackingOffset()) {
     705        if (_ConstrainPoint(point, _OffsetLocation())) {
     706            int32 value = ValueForPoint(point);
     707            if (value != OffsetValue()) {
     708                SetOffsetValue(value);
     709                InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED);
     710            }
     711        }
     712    } else if (IsTracking()) {
    625713        if (_ConstrainPoint(point, _Location())) {
    626714            int32 value = ValueForPoint(point);
    627715            if (value != Value()) {
     
    686774void
    687775BSlider::SetValue(int32 value)
    688776{
    689     if (value < fMinValue)
    690         value = fMinValue;
     777    if (DualMode()) {
     778        if (value < OffsetValue())
     779            value = OffsetValue();
     780    } else {
     781        if (value < fMinValue)
     782            value = fMinValue;
     783    }
    691784    if (value > fMaxValue)
    692785        value = fMaxValue;
    693786
     
    729822}
    730823
    731824
     825void
     826BSlider::SetOffsetValue(int32 value)
     827{
     828    if (DualMode()) {
     829        if (value < fMinValue)
     830            value = fMinValue;
     831        if (value > Value())
     832            value = Value();
     833   
     834        if (value == OffsetValue())
     835            return;
     836   
     837        _SetOffsetLocationForValue(value);
     838   
     839        BRect oldThumbFrame = OffsetThumbFrame();
     840   
     841        // While it would be enough to do this dependent on fUseFillColor,
     842        // that doesn't work out if DrawBar() has been overridden by a sub class
     843        if (fOrientation == B_HORIZONTAL)
     844            oldThumbFrame.top = BarFrame().top;
     845        else
     846            oldThumbFrame.left = BarFrame().left;
     847   
     848        fOffsetValue = value;
     849        BRect invalid = oldThumbFrame | OffsetThumbFrame();
     850   
     851        if (Style() == B_TRIANGLE_THUMB) {
     852            // 1) We need to take care of pixels touched because of anti-aliasing.
     853            // 2) We need to update the region with the focus mark as well. (A
     854            // method BSlider::FocusMarkFrame() would be nice as well.)
     855            if (fOrientation == B_HORIZONTAL) {
     856                if (IsFocus())
     857                    invalid.bottom += 2;
     858                invalid.InsetBy(-1, 0);
     859            } else {
     860                if (IsFocus())
     861                    invalid.left -= 2;
     862                invalid.InsetBy(0, -1);
     863            }
     864        }
     865   
     866        Invalidate(invalid);
     867   
     868        UpdateTextChanged();
     869    }
     870}
     871
     872
    732873int32
     874BSlider::OffsetValue() const
     875{
     876    return fOffsetValue;
     877}
     878
     879
     880int32
    733881BSlider::ValueForPoint(BPoint location) const
    734882{
    735883    float min;
     
    778926
    779927
    780928void
     929BSlider::SetOffsetPosition(float position)
     930{
     931    if (DualMode()) {
     932        if (position <= 0.0f)
     933            SetOffsetValue(fMinValue);
     934        else if (position >= 1.0f)
     935            SetOffsetValue(fMaxValue);
     936        else
     937            SetOffsetValue((int32)(position * (fMaxValue - fMinValue) + fMinValue));
     938    }
     939}
     940
     941
     942float
     943BSlider::OffsetPosition() const
     944{
     945    float range = (float)(fMaxValue - fMinValue);
     946    if (range == 0.0f)
     947        range = 1.0f;
     948
     949    return (float)(OffsetValue() - fMinValue) / range;
     950}
     951
     952
     953void
    781954BSlider::SetEnabled(bool on)
    782955{
    783956    BControl::SetEnabled(on);
     
    794967}
    795968
    796969
     970void
     971BSlider::SetDualMode(bool dualMode)
     972{
     973    fDualMode = dualMode;
     974    if (!dualMode) {
     975        fOffsetValue = fMinValue;
     976        _SetOffsetLocationForValue(fOffsetValue);
     977    }
     978   
     979    Invalidate();
     980   
     981    UpdateTextChanged();
     982}
     983
     984
     985bool
     986BSlider::DualMode() const
     987{
     988    return fDualMode;
     989}
     990
     991
    797992// #pragma mark - drawing
    798993
    799994
     
    8701065        rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
    8711066        rgb_color rightFillColor = fBarColor;
    8721067        rgb_color leftFillColor = fUseFillColor ? fFillColor : fBarColor;
    873         be_control_look->DrawSliderBar(view, frame, frame, base, leftFillColor,
    874             rightFillColor, Position(), flags, fOrientation);
     1068        if (DualMode()) {
     1069            be_control_look->DrawSliderBar(view, frame, frame, base, leftFillColor,
     1070                rightFillColor, Position(), OffsetPosition(), flags, fOrientation);
     1071        } else {
     1072            be_control_look->DrawSliderBar(view, frame, frame, base, leftFillColor,
     1073                rightFillColor, Position(), flags, fOrientation);
     1074        }
    8751075        return;
    8761076    }
    8771077
     
    9081108        fillColor.alpha = 255;
    9091109    }
    9101110
    911     // exclude the block thumb from the bar filling
    912 
    913     BRect lowerFrame = frame.InsetByCopy(1, 1);
    914     lowerFrame.top++;
    915     lowerFrame.left++;
    916     BRect upperFrame = lowerFrame;
    917     BRect thumbFrame;
    918 
    919     if (Style() == B_BLOCK_THUMB) {
    920         thumbFrame = ThumbFrame();
    921 
    922         if (fOrientation == B_HORIZONTAL) {
    923             lowerFrame.right = thumbFrame.left;
    924             upperFrame.left = thumbFrame.right;
    925         } else {
    926             lowerFrame.top = thumbFrame.bottom;
    927             upperFrame.bottom = thumbFrame.top;
     1111    if (DualMode()) {
     1112        // exclude the block thumb from the bar filling
     1113   
     1114        BRect lowerFrame = frame.InsetByCopy(1, 1);
     1115        lowerFrame.top++;
     1116        lowerFrame.left++;
     1117        BRect upperFrame = lowerFrame;
     1118        BRect midFrame = lowerFrame;
     1119        BRect thumbFrame;
     1120        BRect offsetThumbFrame;
     1121   
     1122        if (Style() == B_BLOCK_THUMB) {
     1123            thumbFrame = ThumbFrame();
     1124            offsetThumbFrame = OffsetThumbFrame();
     1125   
     1126            if (fOrientation == B_HORIZONTAL) {
     1127                lowerFrame.right = offsetThumbFrame.left;
     1128                midFrame.left = offsetThumbFrame.right;
     1129                midFrame.right = thumbFrame.left;
     1130                upperFrame.left = thumbFrame.right;
     1131            } else {
     1132                lowerFrame.top = offsetThumbFrame.bottom;
     1133                midFrame.bottom = offsetThumbFrame.top;
     1134                midFrame.top = thumbFrame.bottom;
     1135                upperFrame.bottom = thumbFrame.top;
     1136            }
     1137        } else if (fUseFillColor) {
     1138            if (fOrientation == B_HORIZONTAL) {
     1139                lowerFrame.right = floor(lowerFrame.left - 1 + OffsetPosition()
     1140                    * (lowerFrame.Width() + 1));
     1141                midFrame.left = lowerFrame.right;
     1142                midFrame.right = floor(midFrame.left - 1 + Position()
     1143                    * (midFrame.Width() + 1));
     1144                upperFrame.left = midFrame.right;
     1145            } else {
     1146                lowerFrame.top = floor(lowerFrame.bottom + 1 - OffsetPosition()
     1147                    * (lowerFrame.Height() + 1));
     1148                midFrame.bottom = lowerFrame.top;
     1149                midFrame.top = floor(midFrame.bottom + 1 - Position()
     1150                    * (midFrame.Height() + 1));
     1151                upperFrame.bottom = midFrame.top;
     1152            }
    9281153        }
    929     } else if (fUseFillColor) {
    930         if (fOrientation == B_HORIZONTAL) {
    931             lowerFrame.right = floor(lowerFrame.left - 1 + Position()
    932                 * (lowerFrame.Width() + 1));
    933             upperFrame.left = lowerFrame.right;
    934         } else {
    935             lowerFrame.top = floor(lowerFrame.bottom + 1 - Position()
    936                 * (lowerFrame.Height() + 1));
    937             upperFrame.bottom = lowerFrame.top;
     1154   
     1155        view->SetHighColor(barColor);
     1156        view->FillRect(upperFrame);
     1157        view->FillRect(lowerFrame);
     1158   
     1159        if (Style() == B_BLOCK_THUMB || fUseFillColor) {
     1160            if (fUseFillColor)
     1161                view->SetHighColor(fillColor);
     1162            view->FillRect(midFrame);
    9381163        }
     1164   
     1165        if (Style() == B_BLOCK_THUMB) {
     1166            // We don't want to stroke the lines over the thumb
     1167   
     1168            PushState();
     1169   
     1170            BRegion region;
     1171            GetClippingRegion(&region);
     1172            region.Exclude(thumbFrame);
     1173            region.Exclude(offsetThumbFrame);
     1174            ConstrainClippingRegion(&region);
     1175        }
     1176    } else {
     1177        // exclude the block thumb from the bar filling
     1178   
     1179        BRect lowerFrame = frame.InsetByCopy(1, 1);
     1180        lowerFrame.top++;
     1181        lowerFrame.left++;
     1182        BRect upperFrame = lowerFrame;
     1183        BRect thumbFrame;
     1184   
     1185        if (Style() == B_BLOCK_THUMB) {
     1186            thumbFrame = ThumbFrame();
     1187   
     1188            if (fOrientation == B_HORIZONTAL) {
     1189                lowerFrame.right = thumbFrame.left;
     1190                upperFrame.left = thumbFrame.right;
     1191            } else {
     1192                lowerFrame.top = thumbFrame.bottom;
     1193                upperFrame.bottom = thumbFrame.top;
     1194            }
     1195        } else if (fUseFillColor) {
     1196            if (fOrientation == B_HORIZONTAL) {
     1197                lowerFrame.right = floor(lowerFrame.left - 1 + Position()
     1198                    * (lowerFrame.Width() + 1));
     1199                upperFrame.left = lowerFrame.right;
     1200            } else {
     1201                lowerFrame.top = floor(lowerFrame.bottom + 1 - Position()
     1202                    * (lowerFrame.Height() + 1));
     1203                upperFrame.bottom = lowerFrame.top;
     1204            }
     1205        }
     1206   
     1207        view->SetHighColor(barColor);
     1208        view->FillRect(upperFrame);
     1209   
     1210        if (Style() == B_BLOCK_THUMB || fUseFillColor) {
     1211            if (fUseFillColor)
     1212                view->SetHighColor(fillColor);
     1213            view->FillRect(lowerFrame);
     1214        }
     1215   
     1216        if (Style() == B_BLOCK_THUMB) {
     1217            // We don't want to stroke the lines over the thumb
     1218   
     1219            PushState();
     1220   
     1221            BRegion region;
     1222            GetClippingRegion(&region);
     1223            region.Exclude(thumbFrame);
     1224            ConstrainClippingRegion(&region);
     1225        }
    9391226    }
    9401227
    941     view->SetHighColor(barColor);
    942     view->FillRect(upperFrame);
    943 
    944     if (Style() == B_BLOCK_THUMB || fUseFillColor) {
    945         if (fUseFillColor)
    946             view->SetHighColor(fillColor);
    947         view->FillRect(lowerFrame);
    948     }
    949 
    950     if (Style() == B_BLOCK_THUMB) {
    951         // We don't want to stroke the lines over the thumb
    952 
    953         PushState();
    954 
    955         BRegion region;
    956         GetClippingRegion(&region);
    957         region.Exclude(thumbFrame);
    958         ConstrainClippingRegion(&region);
    959     }
    960 
    9611228    view->SetHighColor(darken1);
    9621229    view->StrokeLine(BPoint(frame.left, frame.top),
    9631230                     BPoint(frame.left + 1.0f, frame.top));
     
    10881355BSlider::DrawThumb()
    10891356{
    10901357    if (Style() == B_BLOCK_THUMB)
    1091         _DrawBlockThumb();
     1358        _DrawBlockThumb(ThumbFrame());
    10921359    else
    1093         _DrawTriangleThumb();
     1360        _DrawTriangleThumb(ThumbFrame());
     1361   
     1362    if (DualMode()) {
     1363        if (Style() == B_BLOCK_THUMB)
     1364            _DrawBlockThumb(OffsetThumbFrame());
     1365        else
     1366            _DrawTriangleThumb(OffsetThumbFrame());
     1367    }
    10941368}
    10951369
    10961370
     
    11191393                BPoint(frame.left - 2.0f, frame.bottom));
    11201394        }
    11211395    }
     1396   
     1397    if (DualMode()) {
     1398        frame = OffsetThumbFrame();
     1399   
     1400        if (fStyle == B_BLOCK_THUMB) {
     1401            frame.left += 2.0f;
     1402            frame.top += 2.0f;
     1403            frame.right -= 3.0f;
     1404            frame.bottom -= 3.0f;
     1405            OffscreenView()->StrokeRect(frame);
     1406        } else {
     1407            if (fOrientation == B_HORIZONTAL) {
     1408                OffscreenView()->StrokeLine(BPoint(frame.left, frame.bottom + 2.0f),
     1409                    BPoint(frame.right, frame.bottom + 2.0f));
     1410            } else {
     1411                OffscreenView()->StrokeLine(BPoint(frame.left - 2.0f, frame.top),
     1412                    BPoint(frame.left - 2.0f, frame.bottom));
     1413            }
     1414        }
     1415    }
    11221416}
    11231417
    11241418
     
    14101704}
    14111705
    14121706
     1707BRect
     1708BSlider::OffsetThumbFrame() const
     1709{
     1710    if (DualMode()) {
     1711        // TODO: The slider looks really ugly and broken when it is too little.
     1712        // I would suggest using BarFrame() here to get the top and bottom coords
     1713        // and spread them further apart for the thumb
     1714   
     1715        BRect frame = Bounds();
     1716   
     1717        font_height fontHeight;
     1718        GetFontHeight(&fontHeight);
     1719   
     1720        float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
     1721   
     1722        if (fStyle == B_BLOCK_THUMB) {
     1723            if (Orientation() == B_HORIZONTAL) {
     1724                frame.left = floorf(OffsetPosition() * (_MaxPosition()
     1725                    - _MinPosition()) + _MinPosition()) - 8;
     1726                frame.top = 2 + (Label() || fUpdateText ? textHeight + 4 : 0);
     1727                frame.right = frame.left + 17;
     1728                frame.bottom = frame.top + fBarThickness + 7;
     1729            } else {
     1730                frame.left = floor((frame.Width() - fBarThickness) / 2) - 4;
     1731                frame.top = floorf(OffsetPosition() * (_MaxPosition()
     1732                    - _MinPosition()) + _MinPosition()) - 8;
     1733                frame.right = frame.left + fBarThickness + 7;
     1734                frame.bottom = frame.top + 17;
     1735            }
     1736        } else {
     1737            if (Orientation() == B_HORIZONTAL) {
     1738                frame.left = floorf(OffsetPosition() * (_MaxPosition()
     1739                    - _MinPosition()) + _MinPosition()) - 6;
     1740                frame.right = frame.left + 12;
     1741                frame.top = 3 + fBarThickness + (Label() ? textHeight + 4 : 0);
     1742                frame.bottom = frame.top + 8;
     1743            } else {
     1744                frame.left = floorf((frame.Width() + fBarThickness) / 2) - 3;
     1745                frame.top = floorf(OffsetPosition() * (_MaxPosition()
     1746                    - _MinPosition())) + _MinPosition() - 6;
     1747                frame.right = frame.left + 8;
     1748                frame.bottom = frame.top + 12;
     1749            }
     1750        }
     1751       
     1752        return frame;
     1753    }
     1754
     1755    return BRect(0, 0, 0, 0);
     1756}
     1757
     1758
    14131759void
    14141760BSlider::SetFlags(uint32 flags)
    14151761{
     
    17812127// #pragma mark - private
    17822128
    17832129void
    1784 BSlider::_DrawBlockThumb()
     2130BSlider::_DrawBlockThumb(BRect frame)
    17852131{
    1786     BRect frame = ThumbFrame();
    17872132    BView *view = OffscreenView();
    17882133
    17892134    if (be_control_look != NULL) {
     
    19152260
    19162261
    19172262void
    1918 BSlider::_DrawTriangleThumb()
     2263BSlider::_DrawTriangleThumb(BRect frame)
    19192264{
    1920     BRect frame = ThumbFrame();
    19212265    BView *view = OffscreenView();
    19222266
    19232267    if (be_control_look != NULL) {
     
    20512395}
    20522396
    20532397
     2398BPoint
     2399BSlider::_OffsetLocation() const
     2400{
     2401    return fOffsetLocation;
     2402}
     2403
     2404
     2405void
     2406BSlider::_SetOffsetLocationForValue(int32 value)
     2407{
     2408    BPoint loc;
     2409    float range = (float)(fMaxValue - fMinValue);
     2410    if (range == 0)
     2411        range = 1;
     2412
     2413    float pos = (float)(value - fMinValue) / range *
     2414        (_MaxPosition() - _MinPosition());
     2415
     2416    if (fOrientation == B_HORIZONTAL) {
     2417        loc.x = ceil(_MinPosition() + pos);
     2418        loc.y = 0;
     2419    } else {
     2420        loc.x = 0;
     2421        loc.y = floor(_MaxPosition() - pos);
     2422    }
     2423    fOffsetLocation = loc;
     2424}
     2425
     2426
    20542427float
    20552428BSlider::_MinPosition() const
    20562429{
     
    21672540}
    21682541
    21692542
     2543void
     2544BSlider::_SetTrackingOffset(bool tracking)
     2545{
     2546    fTrackingOffset = tracking;
     2547}
     2548
     2549
     2550bool
     2551BSlider::_TrackingOffset() const
     2552{
     2553    return fTrackingOffset;
     2554}
     2555
     2556
    21702557// #pragma mark - FBC padding
    21712558
    21722559void BSlider::_ReservedSlider6() {}
  • headers/os/interface/Slider.h

     
    3333                                    uint32 resizingMode
    3434                                        = B_FOLLOW_LEFT | B_FOLLOW_TOP,
    3535                                    uint32 flags = B_NAVIGABLE | B_WILL_DRAW
    36                                         | B_FRAME_EVENTS);
     36                                        | B_FRAME_EVENTS,
     37                                    bool dualMode = false);
    3738
    3839                                BSlider(BRect frame, const char* name,
    3940                                    const char* label, BMessage* message,
     
    4344                                    uint32 resizingMode
    4445                                        = B_FOLLOW_LEFT | B_FOLLOW_TOP,
    4546                                    uint32 flags = B_NAVIGABLE | B_WILL_DRAW
    46                                         | B_FRAME_EVENTS);
     47                                        | B_FRAME_EVENTS,
     48                                    bool dualMode = false);
    4749
    4850                                BSlider(const char* name, const char* label,
    4951                                    BMessage* message, int32 minValue,
    5052                                    int32 maxValue, orientation posture,
    5153                                    thumb_style thumbType = B_BLOCK_THUMB,
    5254                                    uint32 flags = B_NAVIGABLE | B_WILL_DRAW
    53                                         | B_FRAME_EVENTS);
     55                                        | B_FRAME_EVENTS,
     56                                    bool dualMode = false);
    5457
    5558                                BSlider(BMessage* archive);
    5659    virtual                     ~BSlider();
     
    8285                                    const char* maxLabel);
    8386            const char*         MinLimitLabel() const;
    8487            const char*         MaxLimitLabel() const;
     88           
     89    virtual void                SetOffsetValue(int32);
     90            int32               OffsetValue() const;       
    8591    virtual void                SetValue(int32);
    8692    virtual int32               ValueForPoint(BPoint) const;
     93    virtual void                SetOffsetPosition(float);
     94            float               OffsetPosition() const;
    8795    virtual void                SetPosition(float);
    8896            float               Position() const;
    8997    virtual void                SetEnabled(bool on);
     
    103111    virtual BRect               BarFrame() const;
    104112    virtual BRect               HashMarksFrame() const;
    105113    virtual BRect               ThumbFrame() const;
     114    virtual BRect               OffsetThumbFrame() const;
    106115
    107116    virtual void                SetFlags(uint32 flags);
    108117    virtual void                SetResizingMode(uint32 mode);
     
    161170    virtual BSize               MinSize();
    162171    virtual BSize               MaxSize();
    163172    virtual BSize               PreferredSize();
     173   
     174            void                SetDualMode(bool);
     175            bool                DualMode() const;
    164176
    165177private:
    166             void                _DrawBlockThumb();
    167             void                _DrawTriangleThumb();
     178            void                _DrawBlockThumb(BRect);
     179            void                _DrawTriangleThumb(BRect);
    168180
    169181            BPoint              _Location() const;
    170182            void                _SetLocationForValue(int32 value);
     183            BPoint              _OffsetLocation() const;
     184            void                _SetOffsetLocationForValue(int32 value);
    171185
    172186            float               _MinPosition() const;
    173187            float               _MaxPosition() const;
     
    178192
    179193            void                _InitBarColor();
    180194            void                _InitObject();
     195           
     196            void                _SetTrackingOffset(bool);
     197            bool                _TrackingOffset() const;           
    181198
    182199private:
    183200    // FBC padding and forbidden methods
     
    217234
    218235            BPoint              fLocation;
    219236            BPoint              fInitialLocation;
     237            BPoint              fOffsetLocation;
     238            BPoint              fOffsetInitialLocation;
     239           
     240            int32               fOffsetValue;
     241           
     242            bool                fDualMode;
     243           
     244            bool                fTrackingOffset;
    220245
    221246            orientation         fOrientation;
    222247            float               fBarThickness;
  • headers/os/interface/ControlLook.h

     
    185185                                    float sliderScale, uint32 flags,
    186186                                    enum orientation orientation);
    187187
     188    virtual void                DrawSliderBar(BView* view, BRect rect,
     189                                    const BRect& updateRect,
     190                                    const rgb_color& base,
     191                                    rgb_color leftFillColor,
     192                                    rgb_color rightFillColor,
     193                                    float sliderScale, float offsetSliderScale,
     194                                    uint32 flags, enum orientation orientation);
     195
    188196    virtual void                DrawSliderBar(BView* view, BRect rect,
    189197                                    const BRect& updateRect,
    190198                                    const rgb_color& base, rgb_color fillColor,