2 * Copyright 2001-2013 Haiku, Inc.
3 * Distributed under the terms of the MIT License.
6 * Stephan Aßmus <superstippi@gmx.de>
7 * Axel Dörfler, axeld@pinc-software.de
8 * Marc Flerackers (mflerackers@androme.be)
19 #include <ControlLook.h>
21 #include <LayoutUtils.h>
27 #include <binary_compatibility/Interface.h>
30 #define USE_OFF_SCREEN_VIEW 0
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
),
45 fKeyIncrementValue(1),
48 fHashMarks(B_HASH_MARKS_NONE
),
52 fOrientation(B_HORIZONTAL
),
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
,
66 : BControl(frame
, name
, label
, message
, resizingMode
, flags
),
67 fModificationMessage(NULL
),
75 fKeyIncrementValue(1),
78 fHashMarks(B_HASH_MARKS_NONE
),
82 fOrientation(posture
),
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
),
100 fMaxLimitLabel(NULL
),
104 fKeyIncrementValue(1),
107 fHashMarks(B_HASH_MARKS_NONE
),
111 fOrientation(posture
),
121 BSlider::BSlider(BMessage
*archive
)
124 fModificationMessage
= NULL
;
126 if (archive
->HasMessage("_mod_msg")) {
127 BMessage
* message
= new BMessage
;
129 archive
->FindMessage("_mod_msg", message
);
131 SetModificationMessage(message
);
134 if (archive
->FindInt32("_sdelay", &fSnoozeAmount
) != B_OK
)
135 SetSnoozeAmount(20000);
138 if (archive
->FindInt32("_fcolor", (int32
*)&color
) == B_OK
)
139 UseFillColor(true, &color
);
144 if (archive
->FindInt32("_orient", &orient
) == B_OK
)
145 fOrientation
= (orientation
)orient
;
147 fOrientation
= B_HORIZONTAL
;
149 fMinLimitLabel
= NULL
;
150 fMaxLimitLabel
= NULL
;
152 const char* minlbl
= NULL
;
153 const char* maxlbl
= NULL
;
155 archive
->FindString("_minlbl", &minlbl
);
156 archive
->FindString("_maxlbl", &maxlbl
);
158 SetLimitLabels(minlbl
, maxlbl
);
160 if (archive
->FindInt32("_min", &fMinValue
) != B_OK
)
163 if (archive
->FindInt32("_max", &fMaxValue
) != B_OK
)
166 if (archive
->FindInt32("_incrementvalue", &fKeyIncrementValue
) != B_OK
)
167 fKeyIncrementValue
= 1;
169 if (archive
->FindInt32("_hashcount", &fHashMarkCount
) != B_OK
)
173 if (archive
->FindInt16("_hashloc", &hashloc
) == B_OK
)
174 fHashMarks
= (hash_mark_location
)hashloc
;
176 fHashMarks
= B_HASH_MARKS_NONE
;
179 if (archive
->FindInt16("_sstyle", &sstyle
) == B_OK
)
180 fStyle
= (thumb_style
)sstyle
;
182 fStyle
= B_BLOCK_THUMB
;
184 if (archive
->FindInt32("_bcolor", (int32
*)&color
) != B_OK
)
185 color
= tint_color(ui_color(B_PANEL_BACKGROUND_COLOR
), B_DARKEN_4_TINT
);
189 if (archive
->FindFloat("_bthickness", &bthickness
) == B_OK
)
190 fBarThickness
= bthickness
;
192 fBarThickness
= 6.0f
;
200 #if USE_OFF_SCREEN_VIEW
201 delete fOffScreenBits
;
204 delete fModificationMessage
;
205 free(fMinLimitLabel
);
206 free(fMaxLimitLabel
);
211 BSlider::_InitBarColor()
213 if (be_control_look
!= NULL
) {
214 SetBarColor(be_control_look
->SliderBarColor(
215 ui_color(B_PANEL_BACKGROUND_COLOR
)));
217 SetBarColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR
),
221 UseFillColor(false, NULL
);
226 BSlider::_InitObject()
230 fInitialLocation
.x
= 0;
231 fInitialLocation
.y
= 0;
233 #if USE_OFF_SCREEN_VIEW
234 fOffScreenBits
= NULL
;
235 fOffScreenView
= NULL
;
239 fMinSize
.Set(-1, -1);
240 fMaxUpdateTextWidth
= -1.0;
245 BSlider::Instantiate(BMessage
*archive
)
247 if (validate_instantiation(archive
, "BSlider"))
248 return new BSlider(archive
);
255 BSlider::Archive(BMessage
*archive
, bool deep
) const
257 status_t ret
= BControl::Archive(archive
, deep
);
259 if (ModificationMessage() && ret
== B_OK
)
260 ret
= archive
->AddMessage("_mod_msg", ModificationMessage());
263 ret
= archive
->AddInt32("_sdelay", fSnoozeAmount
);
265 ret
= archive
->AddInt32("_bcolor", (const uint32
&)fBarColor
);
267 if (FillColor(NULL
) && ret
== B_OK
)
268 ret
= archive
->AddInt32("_fcolor", (const uint32
&)fFillColor
);
270 if (ret
== B_OK
&& fMinLimitLabel
)
271 ret
= archive
->AddString("_minlbl", fMinLimitLabel
);
273 if (ret
== B_OK
&& fMaxLimitLabel
)
274 ret
= archive
->AddString("_maxlbl", fMaxLimitLabel
);
277 ret
= archive
->AddInt32("_min", fMinValue
);
279 ret
= archive
->AddInt32("_max", fMaxValue
);
282 ret
= archive
->AddInt32("_incrementvalue", fKeyIncrementValue
);
284 ret
= archive
->AddInt32("_hashcount", fHashMarkCount
);
286 ret
= archive
->AddInt16("_hashloc", fHashMarks
);
288 ret
= archive
->AddInt16("_sstyle", fStyle
);
290 ret
= archive
->AddInt32("_orient", fOrientation
);
292 ret
= archive
->AddFloat("_bthickness", fBarThickness
);
299 BSlider::Perform(perform_code code
, void* _data
)
302 case PERFORM_CODE_MIN_SIZE
:
303 ((perform_data_min_size
*)_data
)->return_value
304 = BSlider::MinSize();
306 case PERFORM_CODE_MAX_SIZE
:
307 ((perform_data_max_size
*)_data
)->return_value
308 = BSlider::MaxSize();
310 case PERFORM_CODE_PREFERRED_SIZE
:
311 ((perform_data_preferred_size
*)_data
)->return_value
312 = BSlider::PreferredSize();
314 case PERFORM_CODE_LAYOUT_ALIGNMENT
:
315 ((perform_data_layout_alignment
*)_data
)->return_value
316 = BSlider::LayoutAlignment();
318 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH
:
319 ((perform_data_has_height_for_width
*)_data
)->return_value
320 = BSlider::HasHeightForWidth();
322 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH
:
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
,
330 case PERFORM_CODE_SET_LAYOUT
:
332 perform_data_set_layout
* data
= (perform_data_set_layout
*)_data
;
333 BSlider::SetLayout(data
->layout
);
336 case PERFORM_CODE_LAYOUT_INVALIDATED
:
338 perform_data_layout_invalidated
* data
339 = (perform_data_layout_invalidated
*)_data
;
340 BSlider::LayoutInvalidated(data
->descendants
);
343 case PERFORM_CODE_DO_LAYOUT
:
348 case PERFORM_CODE_SET_ICON
:
350 perform_data_set_icon
* data
= (perform_data_set_icon
*)_data
;
351 return BSlider::SetIcon(data
->icon
, data
->flags
);
355 return BControl::Perform(code
, _data
);
360 BSlider::WindowActivated(bool state
)
362 BControl::WindowActivated(state
);
367 BSlider::AttachedToWindow()
371 #if USE_OFF_SCREEN_VIEW
372 BRect
bounds(Bounds());
374 if (!fOffScreenView
) {
375 fOffScreenView
= new BView(bounds
, "", B_FOLLOW_ALL
, B_WILL_DRAW
);
379 fOffScreenView
->SetFont(&font
);
382 if (!fOffScreenBits
) {
383 fOffScreenBits
= new BBitmap(bounds
, B_RGBA32
, true, false);
385 if (fOffScreenBits
&& fOffScreenView
)
386 fOffScreenBits
->AddChild(fOffScreenView
);
388 } else if (fOffScreenView
)
389 fOffScreenBits
->AddChild(fOffScreenView
);
390 #endif // USE_OFF_SCREEN_VIEW
392 BControl::AttachedToWindow();
394 BView
* view
= OffscreenView();
395 if (view
&& view
->LockLooper()) {
396 view
->SetViewColor(B_TRANSPARENT_COLOR
);
397 view
->SetLowColor(LowColor());
398 view
->UnlockLooper();
401 int32 value
= Value();
403 // makes sure the value is within valid bounds
404 _SetLocationForValue(Value());
405 // makes sure the location is correct
411 BSlider::AllAttached()
413 BControl::AllAttached();
418 BSlider::AllDetached()
420 BControl::AllDetached();
425 BSlider::DetachedFromWindow()
427 BControl::DetachedFromWindow();
429 #if USE_OFF_SCREEN_VIEW
430 if (fOffScreenBits
) {
431 delete fOffScreenBits
;
432 fOffScreenBits
= NULL
;
433 fOffScreenView
= NULL
;
440 BSlider::MessageReceived(BMessage
*msg
)
442 BControl::MessageReceived(msg
);
447 BSlider::FrameMoved(BPoint new_position
)
449 BControl::FrameMoved(new_position
);
454 BSlider::FrameResized(float w
,float h
)
456 BControl::FrameResized(w
, h
);
458 BRect
bounds(Bounds());
460 if (bounds
.right
<= 0.0f
|| bounds
.bottom
<= 0.0f
)
463 #if USE_OFF_SCREEN_VIEW
464 if (fOffScreenBits
) {
465 fOffScreenBits
->RemoveChild(fOffScreenView
);
466 delete fOffScreenBits
;
468 fOffScreenView
->ResizeTo(bounds
.Width(), bounds
.Height());
470 fOffScreenBits
= new BBitmap(Bounds(), B_RGBA32
, true, false);
471 fOffScreenBits
->AddChild(fOffScreenView
);
480 BSlider::KeyDown(const char *bytes
, int32 numBytes
)
482 if (!IsEnabled() || IsHidden())
485 int32 newValue
= Value();
490 newValue
-= KeyIncrementValue();
495 newValue
+= KeyIncrementValue();
499 newValue
= fMinValue
;
502 newValue
= fMaxValue
;
506 BControl::KeyDown(bytes
, numBytes
);
510 if (newValue
< fMinValue
)
511 newValue
= fMinValue
;
512 if (newValue
> fMaxValue
)
513 newValue
= fMaxValue
;
515 if (newValue
!= Value()) {
516 fInitialLocation
= _Location();
518 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED
);
523 BSlider::KeyUp(const char *bytes
, int32 numBytes
)
525 if (fInitialLocation
!= _Location()) {
526 // The last KeyDown event triggered the modification message or no
527 // notification at all, we may also have sent the modification message
528 // continually while the user kept pressing the key. In either case,
529 // finish with the final message to make the behavior consistent with
530 // changing the value by mouse.
537 Makes sure the \a point is within valid bounds.
538 Returns \c true if the relevant coordinate (depending on the orientation
539 of the slider) differs from \a comparePoint.
542 BSlider::_ConstrainPoint(BPoint
& point
, BPoint comparePoint
) const
544 if (fOrientation
== B_HORIZONTAL
) {
545 if (point
.x
!= comparePoint
.x
) {
546 if (point
.x
< _MinPosition())
547 point
.x
= _MinPosition();
548 else if (point
.x
> _MaxPosition())
549 point
.x
= _MaxPosition();
554 if (point
.y
!= comparePoint
.y
) {
555 if (point
.y
> _MinPosition())
556 point
.y
= _MinPosition();
557 else if (point
.y
< _MaxPosition())
558 point
.y
= _MaxPosition();
569 BSlider::MouseDown(BPoint point
)
574 if (BarFrame().Contains(point
) || ThumbFrame().Contains(point
))
575 fInitialLocation
= _Location();
578 GetMouse(&point
, &buttons
, true);
580 _ConstrainPoint(point
, fInitialLocation
);
581 SetValue(ValueForPoint(point
));
583 if (_Location() != fInitialLocation
)
584 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED
);
586 if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS
) {
588 SetMouseEventMask(B_POINTER_EVENTS
, B_LOCK_WINDOW_FOCUS
| B_NO_POINTER_HISTORY
);
590 // synchronous mouse tracking
596 snooze(SnoozeAmount());
597 GetMouse(&point
, &buttons
, true);
599 if (_ConstrainPoint(point
, prevPoint
)) {
600 int32 value
= ValueForPoint(point
);
601 if (value
!= Value()) {
603 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED
);
607 if (_Location() != fInitialLocation
)
614 BSlider::MouseUp(BPoint point
)
617 if (_Location() != fInitialLocation
)
622 BControl::MouseUp(point
);
627 BSlider::MouseMoved(BPoint point
, uint32 transit
, const BMessage
*message
)
630 if (_ConstrainPoint(point
, _Location())) {
631 int32 value
= ValueForPoint(point
);
632 if (value
!= Value()) {
634 InvokeNotify(ModificationMessage(), B_CONTROL_MODIFIED
);
638 BControl::MouseMoved(point
, transit
, message
);
650 BSlider::SetLabel(const char *label
)
652 BControl::SetLabel(label
);
657 BSlider::SetLimitLabels(const char *minLabel
, const char *maxLabel
)
659 free(fMinLimitLabel
);
660 fMinLimitLabel
= minLabel
? strdup(minLabel
) : NULL
;
662 free(fMaxLimitLabel
);
663 fMaxLimitLabel
= maxLabel
? strdup(maxLabel
) : NULL
;
667 // TODO: This is for backwards compatibility and should
668 // probably be removed when breaking binary compatiblity.
669 // Applications like our own Mouse rely on this behavior.
670 if ((Flags() & B_SUPPORTS_LAYOUT
) == 0)
678 BSlider::MinLimitLabel() const
680 return fMinLimitLabel
;
685 BSlider::MaxLimitLabel() const
687 return fMaxLimitLabel
;
692 BSlider::SetValue(int32 value
)
694 if (value
< fMinValue
)
696 if (value
> fMaxValue
)
699 if (value
== Value())
702 _SetLocationForValue(value
);
704 BRect oldThumbFrame
= ThumbFrame();
706 // While it would be enough to do this dependent on fUseFillColor,
707 // that doesn't work out if DrawBar() has been overridden by a sub class
708 if (fOrientation
== B_HORIZONTAL
)
709 oldThumbFrame
.top
= BarFrame().top
;
711 oldThumbFrame
.left
= BarFrame().left
;
713 BControl::SetValueNoUpdate(value
);
714 BRect invalid
= oldThumbFrame
| ThumbFrame();
716 if (Style() == B_TRIANGLE_THUMB
) {
717 // 1) We need to take care of pixels touched because of anti-aliasing.
718 // 2) We need to update the region with the focus mark as well. (A
719 // method BSlider::FocusMarkFrame() would be nice as well.)
720 if (fOrientation
== B_HORIZONTAL
) {
723 invalid
.InsetBy(-1, 0);
727 invalid
.InsetBy(0, -1);
738 BSlider::ValueForPoint(BPoint location
) const
743 if (fOrientation
== B_HORIZONTAL
) {
744 min
= _MinPosition();
745 max
= _MaxPosition();
746 position
= location
.x
;
748 max
= _MinPosition();
749 min
= _MaxPosition();
750 position
= min
+ (max
- location
.y
);
758 return (int32
)roundf(((position
- min
) * (fMaxValue
- fMinValue
) / (max
- min
)) + fMinValue
);
763 BSlider::SetPosition(float position
)
765 if (position
<= 0.0f
)
767 else if (position
>= 1.0f
)
770 SetValue((int32
)(position
* (fMaxValue
- fMinValue
) + fMinValue
));
775 BSlider::Position() const
777 float range
= (float)(fMaxValue
- fMinValue
);
781 return (float)(Value() - fMinValue
) / range
;
786 BSlider::SetEnabled(bool on
)
788 BControl::SetEnabled(on
);
793 BSlider::GetLimits(int32
*minimum
, int32
*maximum
) const
796 *minimum
= fMinValue
;
798 *maximum
= fMaxValue
;
802 // #pragma mark - drawing
806 BSlider::Draw(BRect updateRect
)
808 // clear out background
809 BRegion
background(updateRect
);
810 background
.Exclude(BarFrame());
811 bool drawBackground
= true;
812 if (Parent() && (Parent()->Flags() & B_DRAW_ON_CHILDREN
) != 0) {
813 // This view is embedded somewhere, most likely the Tracker Desktop
815 drawBackground
= false;
818 #if USE_OFF_SCREEN_VIEW
822 if (fOffScreenBits
->Lock()) {
823 fOffScreenView
->SetViewColor(ViewColor());
824 fOffScreenView
->SetLowColor(LowColor());
827 if (drawBackground
&& background
.Frame().IsValid())
828 OffscreenView()->FillRegion(&background
, B_SOLID_LOW
);
830 #if USE_OFF_SCREEN_VIEW
831 fOffScreenView
->Sync();
832 fOffScreenBits
->Unlock();
841 BSlider::DrawSlider()
844 #if USE_OFF_SCREEN_VIEW
847 if (fOffScreenBits
->Lock()) {
855 #if USE_OFF_SCREEN_VIEW
856 fOffScreenView
->Sync();
857 fOffScreenBits
->Unlock();
859 DrawBitmap(fOffScreenBits
, B_ORIGIN
);
870 BRect frame
= BarFrame();
871 BView
*view
= OffscreenView();
873 if (be_control_look
!= NULL
) {
874 uint32 flags
= be_control_look
->Flags(this);
875 rgb_color base
= ui_color(B_PANEL_BACKGROUND_COLOR
);
876 rgb_color rightFillColor
= fBarColor
;
877 rgb_color leftFillColor
= fUseFillColor
? fFillColor
: fBarColor
;
878 be_control_look
->DrawSliderBar(view
, frame
, frame
, base
, leftFillColor
,
879 rightFillColor
, Position(), flags
, fOrientation
);
883 rgb_color no_tint
= ui_color(B_PANEL_BACKGROUND_COLOR
);
884 rgb_color lightenmax
;
893 lightenmax
= tint_color(no_tint
, B_LIGHTEN_MAX_TINT
);
894 darken1
= tint_color(no_tint
, B_DARKEN_1_TINT
);
895 darken2
= tint_color(no_tint
, B_DARKEN_2_TINT
);
896 darkenmax
= tint_color(no_tint
, B_DARKEN_MAX_TINT
);
897 barColor
= fBarColor
;
898 fillColor
= fFillColor
;
900 lightenmax
= tint_color(no_tint
, B_LIGHTEN_MAX_TINT
);
902 darken2
= tint_color(no_tint
, B_DARKEN_1_TINT
);
903 darkenmax
= tint_color(no_tint
, B_DARKEN_3_TINT
);
905 barColor
.red
= (fBarColor
.red
+ no_tint
.red
) / 2;
906 barColor
.green
= (fBarColor
.green
+ no_tint
.green
) / 2;
907 barColor
.blue
= (fBarColor
.blue
+ no_tint
.blue
) / 2;
908 barColor
.alpha
= 255;
910 fillColor
.red
= (fFillColor
.red
+ no_tint
.red
) / 2;
911 fillColor
.green
= (fFillColor
.green
+ no_tint
.green
) / 2;
912 fillColor
.blue
= (fFillColor
.blue
+ no_tint
.blue
) / 2;
913 fillColor
.alpha
= 255;
916 // exclude the block thumb from the bar filling
918 BRect lowerFrame
= frame
.InsetByCopy(1, 1);
921 BRect upperFrame
= lowerFrame
;
924 if (Style() == B_BLOCK_THUMB
) {
925 thumbFrame
= ThumbFrame();
927 if (fOrientation
== B_HORIZONTAL
) {
928 lowerFrame
.right
= thumbFrame
.left
;
929 upperFrame
.left
= thumbFrame
.right
;
931 lowerFrame
.top
= thumbFrame
.bottom
;
932 upperFrame
.bottom
= thumbFrame
.top
;
934 } else if (fUseFillColor
) {
935 if (fOrientation
== B_HORIZONTAL
) {
936 lowerFrame
.right
= floor(lowerFrame
.left
- 1 + Position()
937 * (lowerFrame
.Width() + 1));
938 upperFrame
.left
= lowerFrame
.right
;
940 lowerFrame
.top
= floor(lowerFrame
.bottom
+ 1 - Position()
941 * (lowerFrame
.Height() + 1));
942 upperFrame
.bottom
= lowerFrame
.top
;
946 view
->SetHighColor(barColor
);
947 view
->FillRect(upperFrame
);
949 if (Style() == B_BLOCK_THUMB
|| fUseFillColor
) {
951 view
->SetHighColor(fillColor
);
952 view
->FillRect(lowerFrame
);
955 if (Style() == B_BLOCK_THUMB
) {
956 // We don't want to stroke the lines over the thumb
961 GetClippingRegion(®ion
);
962 region
.Exclude(thumbFrame
);
963 ConstrainClippingRegion(®ion
);
966 view
->SetHighColor(darken1
);
967 view
->StrokeLine(BPoint(frame
.left
, frame
.top
),
968 BPoint(frame
.left
+ 1.0f
, frame
.top
));
969 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
),
970 BPoint(frame
.left
+ 1.0f
, frame
.bottom
));
971 view
->StrokeLine(BPoint(frame
.right
- 1.0f
, frame
.top
),
972 BPoint(frame
.right
, frame
.top
));
974 view
->SetHighColor(darken2
);
975 view
->StrokeLine(BPoint(frame
.left
+ 1.0f
, frame
.top
),
976 BPoint(frame
.right
- 1.0f
, frame
.top
));
977 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
- 1.0f
),
978 BPoint(frame
.left
, frame
.top
+ 1.0f
));
980 view
->SetHighColor(lightenmax
);
981 view
->StrokeLine(BPoint(frame
.left
+ 1.0f
, frame
.bottom
),
982 BPoint(frame
.right
, frame
.bottom
));
983 view
->StrokeLine(BPoint(frame
.right
, frame
.bottom
- 1.0f
),
984 BPoint(frame
.right
, frame
.top
+ 1.0f
));
986 frame
.InsetBy(1.0f
, 1.0f
);
988 view
->SetHighColor(darkenmax
);
989 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
),
990 BPoint(frame
.left
, frame
.top
));
991 view
->StrokeLine(BPoint(frame
.left
+ 1.0f
, frame
.top
),
992 BPoint(frame
.right
, frame
.top
));
994 if (Style() == B_BLOCK_THUMB
)
1000 BSlider::DrawHashMarks()
1002 if (fHashMarks
== B_HASH_MARKS_NONE
)
1005 BRect frame
= HashMarksFrame();
1006 BView
* view
= OffscreenView();
1008 if (be_control_look
!= NULL
) {
1009 rgb_color base
= ui_color(B_PANEL_BACKGROUND_COLOR
);
1010 uint32 flags
= be_control_look
->Flags(this);
1011 be_control_look
->DrawSliderHashMarks(view
, frame
, frame
, base
,
1012 fHashMarkCount
, fHashMarks
, flags
, fOrientation
);
1016 rgb_color no_tint
= ui_color(B_PANEL_BACKGROUND_COLOR
);
1017 rgb_color lightenmax
;
1021 lightenmax
= tint_color(no_tint
, B_LIGHTEN_MAX_TINT
);
1022 darken2
= tint_color(no_tint
, B_DARKEN_2_TINT
);
1024 lightenmax
= tint_color(no_tint
, B_LIGHTEN_2_TINT
);
1025 darken2
= tint_color(no_tint
, B_DARKEN_1_TINT
);
1028 float pos
= _MinPosition();
1029 int32 hashMarkCount
= max_c(fHashMarkCount
, 2);
1030 // draw at least two hashmarks at min/max if
1031 // fHashMarks != B_HASH_MARKS_NONE
1032 float factor
= (_MaxPosition() - pos
) / (hashMarkCount
- 1);
1034 if (fHashMarks
& B_HASH_MARKS_TOP
) {
1036 view
->BeginLineArray(hashMarkCount
* 2);
1038 if (fOrientation
== B_HORIZONTAL
) {
1039 for (int32 i
= 0; i
< hashMarkCount
; i
++) {
1040 view
->AddLine(BPoint(pos
, frame
.top
),
1041 BPoint(pos
, frame
.top
+ 5), darken2
);
1042 view
->AddLine(BPoint(pos
+ 1, frame
.top
),
1043 BPoint(pos
+ 1, frame
.top
+ 5), lightenmax
);
1048 for (int32 i
= 0; i
< hashMarkCount
; i
++) {
1049 view
->AddLine(BPoint(frame
.left
, pos
),
1050 BPoint(frame
.left
+ 5, pos
), darken2
);
1051 view
->AddLine(BPoint(frame
.left
, pos
+ 1),
1052 BPoint(frame
.left
+ 5, pos
+ 1), lightenmax
);
1058 view
->EndLineArray();
1061 pos
= _MinPosition();
1063 if (fHashMarks
& B_HASH_MARKS_BOTTOM
) {
1065 view
->BeginLineArray(hashMarkCount
* 2);
1067 if (fOrientation
== B_HORIZONTAL
) {
1068 for (int32 i
= 0; i
< hashMarkCount
; i
++) {
1069 view
->AddLine(BPoint(pos
, frame
.bottom
- 5),
1070 BPoint(pos
, frame
.bottom
), darken2
);
1071 view
->AddLine(BPoint(pos
+ 1, frame
.bottom
- 5),
1072 BPoint(pos
+ 1, frame
.bottom
), lightenmax
);
1077 for (int32 i
= 0; i
< hashMarkCount
; i
++) {
1078 view
->AddLine(BPoint(frame
.right
- 5, pos
),
1079 BPoint(frame
.right
, pos
), darken2
);
1080 view
->AddLine(BPoint(frame
.right
- 5, pos
+ 1),
1081 BPoint(frame
.right
, pos
+ 1), lightenmax
);
1087 view
->EndLineArray();
1093 BSlider::DrawThumb()
1095 if (Style() == B_BLOCK_THUMB
)
1098 _DrawTriangleThumb();
1103 BSlider::DrawFocusMark()
1108 OffscreenView()->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR
));
1110 BRect frame
= ThumbFrame();
1112 if (fStyle
== B_BLOCK_THUMB
) {
1115 frame
.right
-= 3.0f
;
1116 frame
.bottom
-= 3.0f
;
1117 OffscreenView()->StrokeRect(frame
);
1119 if (fOrientation
== B_HORIZONTAL
) {
1120 OffscreenView()->StrokeLine(BPoint(frame
.left
, frame
.bottom
+ 2.0f
),
1121 BPoint(frame
.right
, frame
.bottom
+ 2.0f
));
1123 OffscreenView()->StrokeLine(BPoint(frame
.left
- 2.0f
, frame
.top
),
1124 BPoint(frame
.left
- 2.0f
, frame
.bottom
));
1133 BRect
bounds(Bounds());
1134 BView
*view
= OffscreenView();
1136 rgb_color base
= LowColor();
1138 if (be_control_look
== NULL
) {
1140 view
->SetHighColor(0, 0, 0);
1142 view
->SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT
));
1145 flags
= be_control_look
->Flags(this);
1147 font_height fontHeight
;
1148 GetFontHeight(&fontHeight
);
1149 if (Orientation() == B_HORIZONTAL
) {
1151 if (be_control_look
== NULL
) {
1152 view
->DrawString(Label(),
1153 BPoint(0.0, ceilf(fontHeight
.ascent
)));
1155 be_control_look
->DrawLabel(view
, Label(), base
, flags
,
1156 BPoint(0.0, ceilf(fontHeight
.ascent
)));
1160 // the update text is updated in SetValue() only
1161 if (fUpdateText
!= NULL
) {
1162 if (be_control_look
== NULL
) {
1163 view
->DrawString(fUpdateText
, BPoint(bounds
.right
1164 - StringWidth(fUpdateText
), ceilf(fontHeight
.ascent
)));
1166 be_control_look
->DrawLabel(view
, fUpdateText
, base
, flags
,
1167 BPoint(bounds
.right
- StringWidth(fUpdateText
),
1168 ceilf(fontHeight
.ascent
)));
1172 if (fMinLimitLabel
) {
1173 if (be_control_look
== NULL
) {
1174 view
->DrawString(fMinLimitLabel
, BPoint(0.0, bounds
.bottom
1175 - fontHeight
.descent
));
1177 be_control_look
->DrawLabel(view
, fMinLimitLabel
, base
, flags
,
1178 BPoint(0.0, bounds
.bottom
- fontHeight
.descent
));
1182 if (fMaxLimitLabel
) {
1183 if (be_control_look
== NULL
) {
1184 view
->DrawString(fMaxLimitLabel
, BPoint(bounds
.right
1185 - StringWidth(fMaxLimitLabel
), bounds
.bottom
1186 - fontHeight
.descent
));
1188 be_control_look
->DrawLabel(view
, fMaxLimitLabel
, base
, flags
,
1189 BPoint(bounds
.right
- StringWidth(fMaxLimitLabel
),
1190 bounds
.bottom
- fontHeight
.descent
));
1194 float lineHeight
= ceilf(fontHeight
.ascent
) + ceilf(fontHeight
.descent
)
1195 + ceilf(fontHeight
.leading
);
1196 float baseLine
= ceilf(fontHeight
.ascent
);
1199 if (be_control_look
== NULL
) {
1200 view
->DrawString(Label(), BPoint((bounds
.Width()
1201 - StringWidth(Label())) / 2.0, baseLine
));
1203 be_control_look
->DrawLabel(view
, Label(), base
, flags
,
1204 BPoint((bounds
.Width() - StringWidth(Label())) / 2.0,
1207 baseLine
+= lineHeight
;
1210 if (fMaxLimitLabel
) {
1211 if (be_control_look
== NULL
) {
1212 view
->DrawString(fMaxLimitLabel
, BPoint((bounds
.Width()
1213 - StringWidth(fMaxLimitLabel
)) / 2.0, baseLine
));
1215 be_control_look
->DrawLabel(view
, fMaxLimitLabel
, base
, flags
,
1216 BPoint((bounds
.Width()
1217 - StringWidth(fMaxLimitLabel
)) / 2.0, baseLine
));
1221 baseLine
= bounds
.bottom
- ceilf(fontHeight
.descent
);
1223 if (fMinLimitLabel
) {
1224 if (be_control_look
== NULL
) {
1225 view
->DrawString(fMinLimitLabel
, BPoint((bounds
.Width()
1226 - StringWidth(fMinLimitLabel
)) / 2.0, baseLine
));
1228 be_control_look
->DrawLabel(view
, fMinLimitLabel
, base
, flags
,
1229 BPoint((bounds
.Width()
1230 - StringWidth(fMinLimitLabel
)) / 2.0, baseLine
));
1232 baseLine
-= lineHeight
;
1235 if (fUpdateText
!= NULL
) {
1236 if (be_control_look
== NULL
) {
1237 view
->DrawString(fUpdateText
, BPoint((bounds
.Width()
1238 - StringWidth(fUpdateText
)) / 2.0, baseLine
));
1240 be_control_look
->DrawLabel(view
, fUpdateText
, base
, flags
,
1241 BPoint((bounds
.Width()
1242 - StringWidth(fUpdateText
)) / 2.0, baseLine
));
1253 BSlider::UpdateText() const
1260 BSlider::UpdateTextChanged()
1262 // update text label
1263 float oldWidth
= 0.0;
1264 if (fUpdateText
!= NULL
)
1265 oldWidth
= StringWidth(fUpdateText
);
1267 const char* oldUpdateText
= fUpdateText
;
1268 fUpdateText
= UpdateText();
1269 bool updateTextOnOff
= (fUpdateText
== NULL
&& oldUpdateText
!= NULL
)
1270 || (fUpdateText
!= NULL
&& oldUpdateText
== NULL
);
1272 float newWidth
= 0.0;
1273 if (fUpdateText
!= NULL
)
1274 newWidth
= StringWidth(fUpdateText
);
1276 float width
= ceilf(max_c(newWidth
, oldWidth
)) + 2.0f
;
1278 font_height fontHeight
;
1279 GetFontHeight(&fontHeight
);
1281 float height
= ceilf(fontHeight
.ascent
) + ceilf(fontHeight
.descent
);
1282 float lineHeight
= height
+ ceilf(fontHeight
.leading
);
1283 BRect
invalid(Bounds());
1284 if (fOrientation
== B_HORIZONTAL
)
1285 invalid
= BRect(invalid
.right
- width
, 0, invalid
.right
, height
);
1287 if (!updateTextOnOff
) {
1288 invalid
.left
= (invalid
.left
+ invalid
.right
- width
) / 2;
1289 invalid
.right
= invalid
.left
+ width
;
1291 invalid
.bottom
-= lineHeight
;
1292 invalid
.top
= invalid
.bottom
- height
;
1295 Invalidate(invalid
);
1298 float oldMaxUpdateTextWidth
= fMaxUpdateTextWidth
;
1299 fMaxUpdateTextWidth
= MaxUpdateTextWidth();
1300 if (oldMaxUpdateTextWidth
!= fMaxUpdateTextWidth
)
1306 BSlider::BarFrame() const
1308 BRect
frame(Bounds());
1310 font_height fontHeight
;
1311 GetFontHeight(&fontHeight
);
1313 float textHeight
= ceilf(fontHeight
.ascent
) + ceilf(fontHeight
.descent
);
1314 float leading
= ceilf(fontHeight
.leading
);
1317 if (fStyle
== B_BLOCK_THUMB
)
1322 if (Orientation() == B_HORIZONTAL
) {
1323 frame
.left
= thumbInset
;
1324 frame
.top
= 6.0 + (Label() || fUpdateText
? textHeight
+ 4.0 : 0.0);
1325 frame
.right
-= thumbInset
;
1326 frame
.bottom
= frame
.top
+ fBarThickness
;
1328 frame
.left
= floorf((frame
.Width() - fBarThickness
) / 2.0);
1329 frame
.top
= thumbInset
;
1331 frame
.top
+= textHeight
;
1332 if (fMaxLimitLabel
) {
1333 frame
.top
+= textHeight
;
1335 frame
.top
+= leading
;
1338 frame
.right
= frame
.left
+ fBarThickness
;
1339 frame
.bottom
= frame
.bottom
- thumbInset
;
1341 frame
.bottom
-= textHeight
;
1343 frame
.bottom
-= textHeight
;
1345 frame
.bottom
-= leading
;
1354 BSlider::HashMarksFrame() const
1356 BRect
frame(BarFrame());
1358 if (fOrientation
== B_HORIZONTAL
) {
1360 frame
.bottom
+= 6.0;
1371 BSlider::ThumbFrame() const
1373 // TODO: The slider looks really ugly and broken when it is too little.
1374 // I would suggest using BarFrame() here to get the top and bottom coords
1375 // and spread them further apart for the thumb
1377 BRect frame
= Bounds();
1379 font_height fontHeight
;
1380 GetFontHeight(&fontHeight
);
1382 float textHeight
= ceilf(fontHeight
.ascent
) + ceilf(fontHeight
.descent
);
1384 if (fStyle
== B_BLOCK_THUMB
) {
1385 if (Orientation() == B_HORIZONTAL
) {
1386 frame
.left
= floorf(Position() * (_MaxPosition()
1387 - _MinPosition()) + _MinPosition()) - 8;
1388 frame
.top
= 2 + (Label() || fUpdateText
? textHeight
+ 4 : 0);
1389 frame
.right
= frame
.left
+ 17;
1390 frame
.bottom
= frame
.top
+ fBarThickness
+ 7;
1392 frame
.left
= floor((frame
.Width() - fBarThickness
) / 2) - 4;
1393 frame
.top
= floorf(Position() * (_MaxPosition()
1394 - _MinPosition()) + _MinPosition()) - 8;
1395 frame
.right
= frame
.left
+ fBarThickness
+ 7;
1396 frame
.bottom
= frame
.top
+ 17;
1399 if (Orientation() == B_HORIZONTAL
) {
1400 frame
.left
= floorf(Position() * (_MaxPosition()
1401 - _MinPosition()) + _MinPosition()) - 6;
1402 frame
.right
= frame
.left
+ 12;
1403 frame
.top
= 3 + fBarThickness
+ (Label() ? textHeight
+ 4 : 0);
1404 frame
.bottom
= frame
.top
+ 8;
1406 frame
.left
= floorf((frame
.Width() + fBarThickness
) / 2) - 3;
1407 frame
.top
= floorf(Position() * (_MaxPosition()
1408 - _MinPosition())) + _MinPosition() - 6;
1409 frame
.right
= frame
.left
+ 8;
1410 frame
.bottom
= frame
.top
+ 12;
1419 BSlider::SetFlags(uint32 flags
)
1421 BControl::SetFlags(flags
);
1426 BSlider::SetResizingMode(uint32 mode
)
1428 BControl::SetResizingMode(mode
);
1433 BSlider::GetPreferredSize(float* _width
, float* _height
)
1435 BSize preferredSize
= PreferredSize();
1437 if (Orientation() == B_HORIZONTAL
) {
1438 if (_width
!= NULL
) {
1439 // NOTE: For compatibility reasons, a horizontal BSlider
1440 // never shrinks horizontally. This only affects applications
1441 // which do not use the new layout system.
1442 *_width
= max_c(Bounds().Width(), preferredSize
.width
);
1445 if (_height
!= NULL
)
1446 *_height
= preferredSize
.height
;
1449 *_width
= preferredSize
.width
;
1451 if (_height
!= NULL
) {
1452 // NOTE: Similarly, a vertical BSlider never shrinks
1453 // vertically. This only affects applications which do not
1454 // use the new layout system.
1455 *_height
= max_c(Bounds().Height(), preferredSize
.height
);
1462 BSlider::ResizeToPreferred()
1464 BControl::ResizeToPreferred();
1469 BSlider::Invoke(BMessage
* message
)
1471 return BControl::Invoke(message
);
1476 BSlider::ResolveSpecifier(BMessage
* message
, int32 index
, BMessage
* specifier
,
1477 int32 command
, const char *property
)
1479 return BControl::ResolveSpecifier(message
, index
, specifier
, command
,
1485 BSlider::GetSupportedSuites(BMessage
* message
)
1487 return BControl::GetSupportedSuites(message
);
1492 BSlider::SetModificationMessage(BMessage
* message
)
1494 delete fModificationMessage
;
1495 fModificationMessage
= message
;
1500 BSlider::ModificationMessage() const
1502 return fModificationMessage
;
1507 BSlider::SetSnoozeAmount(int32 snoozeTime
)
1509 if (snoozeTime
< 10000)
1511 else if (snoozeTime
> 1000000)
1512 snoozeTime
= 1000000;
1514 fSnoozeAmount
= snoozeTime
;
1519 BSlider::SnoozeAmount() const
1521 return fSnoozeAmount
;
1526 BSlider::SetKeyIncrementValue(int32 incrementValue
)
1528 fKeyIncrementValue
= incrementValue
;
1533 BSlider::KeyIncrementValue() const
1535 return fKeyIncrementValue
;
1540 BSlider::SetHashMarkCount(int32 hashMarkCount
)
1542 fHashMarkCount
= hashMarkCount
;
1548 BSlider::HashMarkCount() const
1550 return fHashMarkCount
;
1555 BSlider::SetHashMarks(hash_mark_location where
)
1558 // TODO: enable if the hashmark look is influencing the control size!
1559 // InvalidateLayout();
1565 BSlider::HashMarks() const
1572 BSlider::SetStyle(thumb_style style
)
1581 BSlider::Style() const
1588 BSlider::SetBarColor(rgb_color barColor
)
1590 fBarColor
= barColor
;
1591 Invalidate(BarFrame());
1596 BSlider::BarColor() const
1603 BSlider::UseFillColor(bool useFill
, const rgb_color
* barColor
)
1605 fUseFillColor
= useFill
;
1607 if (useFill
&& barColor
)
1608 fFillColor
= *barColor
;
1610 Invalidate(BarFrame());
1615 BSlider::FillColor(rgb_color
* barColor
) const
1617 if (barColor
&& fUseFillColor
)
1618 *barColor
= fFillColor
;
1620 return fUseFillColor
;
1625 BSlider::OffscreenView() const
1627 #if USE_OFF_SCREEN_VIEW
1628 return fOffScreenView
;
1630 return (BView
*)this;
1636 BSlider::Orientation() const
1638 return fOrientation
;
1643 BSlider::SetOrientation(orientation posture
)
1645 if (fOrientation
== posture
)
1648 fOrientation
= posture
;
1655 BSlider::BarThickness() const
1657 return fBarThickness
;
1662 BSlider::SetBarThickness(float thickness
)
1664 if (thickness
< 1.0)
1667 thickness
= roundf(thickness
);
1669 if (thickness
!= fBarThickness
) {
1670 // calculate invalid barframe and extend by hashmark size
1673 if (fOrientation
== B_HORIZONTAL
)
1677 BRect invalid
= BarFrame().InsetByCopy(hInset
, vInset
) | ThumbFrame();
1679 fBarThickness
= thickness
;
1681 invalid
= invalid
| BarFrame().InsetByCopy(hInset
, vInset
)
1683 Invalidate(invalid
);
1690 BSlider::SetFont(const BFont
*font
, uint32 properties
)
1692 BControl::SetFont(font
, properties
);
1694 #if USE_OFF_SCREEN_VIEW
1695 if (fOffScreenView
&& fOffScreenBits
) {
1696 if (fOffScreenBits
->Lock()) {
1697 fOffScreenView
->SetFont(font
, properties
);
1698 fOffScreenBits
->Unlock();
1708 BSlider::SetLimits(int32 minimum
, int32 maximum
)
1710 if (minimum
<= maximum
) {
1711 fMinValue
= minimum
;
1712 fMaxValue
= maximum
;
1714 int32 value
= Value();
1715 value
= max_c(minimum
, value
);
1716 value
= min_c(maximum
, value
);
1718 if (value
!= Value()) {
1726 BSlider::MaxUpdateTextWidth()
1728 // very simplistic implementation that assumes the string will be widest
1729 // at the maximum value
1730 int32 value
= Value();
1731 SetValueNoUpdate(fMaxValue
);
1732 float width
= StringWidth(UpdateText());
1733 SetValueNoUpdate(value
);
1734 // in case the derived class uses a fixed buffer, the contents
1735 // should be reset for the old value
1741 // #pragma mark - layout related
1747 return BLayoutUtils::ComposeSize(ExplicitMinSize(),
1748 _ValidateMinSize());
1755 BSize maxSize
= _ValidateMinSize();
1756 if (fOrientation
== B_HORIZONTAL
)
1757 maxSize
.width
= B_SIZE_UNLIMITED
;
1759 maxSize
.height
= B_SIZE_UNLIMITED
;
1760 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), maxSize
);
1765 BSlider::PreferredSize()
1767 BSize preferredSize
= _ValidateMinSize();
1768 if (fOrientation
== B_HORIZONTAL
)
1769 preferredSize
.width
= max_c(100.0, preferredSize
.width
);
1771 preferredSize
.height
= max_c(100.0, preferredSize
.height
);
1772 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), preferredSize
);
1777 BSlider::SetIcon(const BBitmap
* icon
, uint32 flags
)
1779 return BControl::SetIcon(icon
, flags
);
1784 BSlider::LayoutInvalidated(bool descendants
)
1786 // invalidate cached preferred size
1787 fMinSize
.Set(-1, -1);
1791 // #pragma mark - private
1794 BSlider::_DrawBlockThumb()
1796 BRect frame
= ThumbFrame();
1797 BView
*view
= OffscreenView();
1799 if (be_control_look
!= NULL
) {
1800 rgb_color base
= ui_color(B_PANEL_BACKGROUND_COLOR
);
1801 uint32 flags
= be_control_look
->Flags(this);
1802 be_control_look
->DrawSliderThumb(view
, frame
, frame
, base
, flags
,
1807 rgb_color no_tint
= ui_color(B_PANEL_BACKGROUND_COLOR
);
1812 rgb_color darkenmax
;
1815 lighten2
= tint_color(no_tint
, B_LIGHTEN_2_TINT
);
1817 darken2
= tint_color(no_tint
, B_DARKEN_2_TINT
);
1818 darken3
= tint_color(no_tint
, B_DARKEN_3_TINT
);
1819 darkenmax
= tint_color(no_tint
, B_DARKEN_MAX_TINT
);
1821 lighten2
= tint_color(no_tint
, B_LIGHTEN_2_TINT
);
1822 lighten1
= tint_color(no_tint
, B_LIGHTEN_1_TINT
);
1823 darken2
= tint_color(no_tint
, (B_NO_TINT
+ B_DARKEN_1_TINT
) / 2.0);
1824 darken3
= tint_color(no_tint
, B_DARKEN_1_TINT
);
1825 darkenmax
= tint_color(no_tint
, B_DARKEN_3_TINT
);
1828 // blank background for shadow
1829 // ToDo: this also draws over the hash marks (though it's not *that* noticeable)
1830 view
->SetHighColor(no_tint
);
1831 view
->StrokeLine(BPoint(frame
.left
, frame
.top
),
1832 BPoint(frame
.left
, frame
.top
));
1834 BRect barFrame
= BarFrame();
1835 if (barFrame
.right
>= frame
.right
) {
1836 // leave out barFrame from shadow background clearing
1837 view
->StrokeLine(BPoint(frame
.right
, frame
.top
),
1838 BPoint(frame
.right
, barFrame
.top
- 1.0f
));
1839 view
->StrokeLine(BPoint(frame
.right
, barFrame
.bottom
+ 1.0f
),
1840 BPoint(frame
.right
, frame
.bottom
));
1842 view
->StrokeLine(BPoint(frame
.right
, frame
.top
),
1843 BPoint(frame
.right
, frame
.bottom
));
1846 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
),
1847 BPoint(frame
.right
- 1.0f
, frame
.bottom
));
1848 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
- 1.0f
),
1849 BPoint(frame
.left
, frame
.bottom
- 1.0f
));
1850 view
->StrokeLine(BPoint(frame
.right
- 1.0f
, frame
.top
),
1851 BPoint(frame
.right
- 1.0f
, frame
.top
));
1853 // Outline (top, left)
1854 view
->SetHighColor(darken3
);
1855 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
- 2.0f
),
1856 BPoint(frame
.left
, frame
.top
+ 1.0f
));
1857 view
->StrokeLine(BPoint(frame
.left
+ 1.0f
, frame
.top
),
1858 BPoint(frame
.right
- 2.0f
, frame
.top
));
1861 view
->SetHighColor(0, 0, 0, IsEnabled() ? 100 : 50);
1862 view
->SetDrawingMode(B_OP_ALPHA
);
1863 view
->StrokeLine(BPoint(frame
.right
, frame
.top
+ 2.0f
),
1864 BPoint(frame
.right
, frame
.bottom
- 1.0f
));
1865 view
->StrokeLine(BPoint(frame
.left
+ 2.0f
, frame
.bottom
),
1866 BPoint(frame
.right
- 1.0f
, frame
.bottom
));
1868 view
->SetDrawingMode(B_OP_COPY
);
1869 view
->SetHighColor(darken3
);
1870 view
->StrokeLine(BPoint(frame
.right
- 1.0f
, frame
.bottom
- 1.0f
),
1871 BPoint(frame
.right
- 1.0f
, frame
.bottom
- 1.0f
));
1875 frame
.InsetBy(1.0f
, 1.0f
);
1877 view
->SetHighColor(darkenmax
);
1878 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
),
1879 BPoint(frame
.right
- 1.0f
, frame
.bottom
));
1880 view
->StrokeLine(BPoint(frame
.right
, frame
.bottom
- 1.0f
),
1881 BPoint(frame
.right
, frame
.top
));
1883 view
->SetHighColor(lighten2
);
1884 view
->StrokeLine(BPoint(frame
.left
, frame
.top
),
1885 BPoint(frame
.left
, frame
.bottom
- 1.0f
));
1886 view
->StrokeLine(BPoint(frame
.left
+ 1.0f
, frame
.top
),
1887 BPoint(frame
.right
- 1.0f
, frame
.top
));
1889 frame
.InsetBy(1.0f
, 1.0f
);
1891 view
->FillRect(BRect(frame
.left
, frame
.top
, frame
.right
- 1.0f
, frame
.bottom
- 1.0f
));
1893 // Second bevel and center dots
1894 view
->SetHighColor(darken2
);
1895 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
),
1896 BPoint(frame
.right
, frame
.bottom
));
1897 view
->StrokeLine(BPoint(frame
.right
, frame
.bottom
- 1.0f
),
1898 BPoint(frame
.right
, frame
.top
));
1900 if (Orientation() == B_HORIZONTAL
) {
1901 view
->StrokeLine(BPoint(frame
.left
+ 6.0f
, frame
.top
+ 2.0f
),
1902 BPoint(frame
.left
+ 6.0f
, frame
.top
+ 2.0f
));
1903 view
->StrokeLine(BPoint(frame
.left
+ 6.0f
, frame
.top
+ 4.0f
),
1904 BPoint(frame
.left
+ 6.0f
, frame
.top
+ 4.0f
));
1905 view
->StrokeLine(BPoint(frame
.left
+ 6.0f
, frame
.top
+ 6.0f
),
1906 BPoint(frame
.left
+ 6.0f
, frame
.top
+ 6.0f
));
1908 view
->StrokeLine(BPoint(frame
.left
+ 2.0f
, frame
.top
+ 6.0f
),
1909 BPoint(frame
.left
+ 2.0f
, frame
.top
+ 6.0f
));
1910 view
->StrokeLine(BPoint(frame
.left
+ 4.0f
, frame
.top
+ 6.0f
),
1911 BPoint(frame
.left
+ 4.0f
, frame
.top
+ 6.0f
));
1912 view
->StrokeLine(BPoint(frame
.left
+ 6.0f
, frame
.top
+ 6.0f
),
1913 BPoint(frame
.left
+ 6.0f
, frame
.top
+ 6.0f
));
1916 frame
.InsetBy(1.0f
, 1.0f
);
1919 view
->SetHighColor(lighten1
);
1920 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
),
1921 BPoint(frame
.right
, frame
.bottom
));
1922 view
->StrokeLine(BPoint(frame
.right
, frame
.bottom
- 1.0f
),
1923 BPoint(frame
.right
, frame
.top
));
1928 BSlider::_DrawTriangleThumb()
1930 BRect frame
= ThumbFrame();
1931 BView
*view
= OffscreenView();
1933 if (be_control_look
!= NULL
) {
1934 rgb_color base
= ui_color(B_PANEL_BACKGROUND_COLOR
);
1935 uint32 flags
= be_control_look
->Flags(this);
1936 be_control_look
->DrawSliderTriangle(view
, frame
, frame
, base
, flags
,
1941 rgb_color no_tint
= ui_color(B_PANEL_BACKGROUND_COLOR
);
1942 rgb_color lightenmax
;
1946 rgb_color darkenmax
;
1949 lightenmax
= tint_color(no_tint
, B_LIGHTEN_MAX_TINT
);
1951 darken2
= tint_color(no_tint
, B_DARKEN_2_TINT
);
1952 darken3
= tint_color(no_tint
, B_DARKEN_3_TINT
);
1953 darkenmax
= tint_color(no_tint
, B_DARKEN_MAX_TINT
);
1955 lightenmax
= tint_color(no_tint
, B_LIGHTEN_2_TINT
);
1956 lighten1
= tint_color(no_tint
, B_LIGHTEN_1_TINT
);
1957 darken2
= tint_color(no_tint
, (B_NO_TINT
+ B_DARKEN_1_TINT
) / 2);
1958 darken3
= tint_color(no_tint
, B_DARKEN_1_TINT
);
1959 darkenmax
= tint_color(no_tint
, B_DARKEN_3_TINT
);
1962 if (Orientation() == B_HORIZONTAL
) {
1963 view
->SetHighColor(lighten1
);
1965 BPoint(frame
.left
+ 1, frame
.bottom
- 3),
1966 BPoint((frame
.left
+ frame
.right
) / 2, frame
.top
+ 1),
1967 BPoint(frame
.right
- 1, frame
.bottom
- 3));
1969 view
->SetHighColor(no_tint
);
1970 view
->StrokeLine(BPoint(frame
.right
- 2, frame
.bottom
- 3),
1971 BPoint(frame
.left
+ 3, frame
.bottom
- 3));
1973 view
->SetHighColor(darkenmax
);
1974 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
- 1),
1975 BPoint(frame
.right
, frame
.bottom
- 1));
1976 view
->StrokeLine(BPoint(frame
.right
, frame
.bottom
- 2),
1977 BPoint((frame
.left
+ frame
.right
) / 2, frame
.top
));
1979 view
->SetHighColor(darken2
);
1980 view
->StrokeLine(BPoint(frame
.right
- 1, frame
.bottom
- 2),
1981 BPoint(frame
.left
+ 1, frame
.bottom
- 2));
1982 view
->SetHighColor(darken3
);
1983 view
->StrokeLine(BPoint(frame
.left
, frame
.bottom
- 2),
1984 BPoint((frame
.left
+ frame
.right
) / 2 - 1, frame
.top
+ 1));
1986 view
->SetHighColor(lightenmax
);
1987 view
->StrokeLine(BPoint(frame
.left
+ 2, frame
.bottom
- 3),
1988 BPoint((frame
.left
+ frame
.right
) / 2, frame
.top
+ 1));
1991 view
->SetHighColor(0, 0, 0, IsEnabled() ? 80 : 40);
1992 view
->SetDrawingMode(B_OP_ALPHA
);
1993 view
->StrokeLine(BPoint(frame
.left
+ 1, frame
.bottom
),
1994 BPoint(frame
.right
, frame
.bottom
));
1996 view
->SetHighColor(lighten1
);
1998 BPoint(frame
.left
, (frame
.top
+ frame
.bottom
) / 2),
1999 BPoint(frame
.right
- 1, frame
.top
+ 1),
2000 BPoint(frame
.right
- 1, frame
.bottom
- 1));
2002 view
->SetHighColor(darkenmax
);
2003 view
->StrokeLine(BPoint(frame
.right
- 1, frame
.top
),
2004 BPoint(frame
.right
- 1, frame
.bottom
));
2005 view
->StrokeLine(BPoint(frame
.right
- 1, frame
.bottom
),
2006 BPoint(frame
.right
- 2, frame
.bottom
));
2008 view
->SetHighColor(darken2
);
2009 view
->StrokeLine(BPoint(frame
.right
- 2, frame
.top
+ 2),
2010 BPoint(frame
.right
- 2, frame
.bottom
- 1));
2012 BPoint(frame
.left
, (frame
.top
+ frame
.bottom
) / 2),
2013 BPoint(frame
.right
- 2, frame
.top
));
2014 view
->SetHighColor(darken3
);
2016 BPoint(frame
.left
+ 1, (frame
.top
+ frame
.bottom
) / 2 + 1),
2017 BPoint(frame
.right
- 3, frame
.bottom
- 1));
2019 view
->SetHighColor(lightenmax
);
2021 BPoint(frame
.left
+ 1, (frame
.top
+ frame
.bottom
) / 2),
2022 BPoint(frame
.right
- 2, frame
.top
+ 1));
2025 view
->SetHighColor(0, 0, 0, IsEnabled() ? 80 : 40);
2026 view
->SetDrawingMode(B_OP_ALPHA
);
2027 view
->StrokeLine(BPoint(frame
.right
, frame
.top
+ 1),
2028 BPoint(frame
.right
, frame
.bottom
));
2031 view
->SetDrawingMode(B_OP_COPY
);
2036 BSlider::_Location() const
2043 BSlider::_SetLocationForValue(int32 value
)
2046 float range
= (float)(fMaxValue
- fMinValue
);
2050 float pos
= (float)(value
- fMinValue
) / range
*
2051 (_MaxPosition() - _MinPosition());
2053 if (fOrientation
== B_HORIZONTAL
) {
2054 loc
.x
= ceil(_MinPosition() + pos
);
2058 loc
.y
= floor(_MaxPosition() - pos
);
2065 BSlider::_MinPosition() const
2067 if (fOrientation
== B_HORIZONTAL
)
2068 return BarFrame().left
+ 1.0f
;
2070 return BarFrame().bottom
- 1.0f
;
2075 BSlider::_MaxPosition() const
2077 if (fOrientation
== B_HORIZONTAL
)
2078 return BarFrame().right
- 1.0f
;
2080 return BarFrame().top
+ 1.0f
;
2085 BSlider::_ValidateMinSize()
2087 if (fMinSize
.width
>= 0) {
2088 // the preferred size is up to date
2092 font_height fontHeight
;
2093 GetFontHeight(&fontHeight
);
2098 if (fMaxUpdateTextWidth
< 0.0)
2099 fMaxUpdateTextWidth
= MaxUpdateTextWidth();
2101 if (Orientation() == B_HORIZONTAL
) {
2102 height
= 12.0 + fBarThickness
;
2105 float labelWidth
= 0;
2106 int32 labelRows
= 0;
2107 float labelSpacing
= StringWidth("M") * 2;
2109 labelWidth
= StringWidth(Label());
2112 if (fMaxUpdateTextWidth
> 0.0) {
2114 labelWidth
+= labelSpacing
;
2115 labelWidth
+= fMaxUpdateTextWidth
;
2120 if (MinLimitLabel())
2121 width
= StringWidth(MinLimitLabel());
2122 if (MaxLimitLabel()) {
2123 // some space between the labels
2124 if (MinLimitLabel())
2125 width
+= labelSpacing
;
2127 width
+= StringWidth(MaxLimitLabel());
2130 if (labelWidth
> width
)
2135 if (MinLimitLabel() || MaxLimitLabel())
2138 height
+= rows
* (ceilf(fontHeight
.ascent
)
2139 + ceilf(fontHeight
.descent
) + 4.0);
2142 width
= 12.0 + fBarThickness
;
2145 float lineHeightNoLeading
= ceilf(fontHeight
.ascent
)
2146 + ceilf(fontHeight
.descent
);
2147 float lineHeight
= lineHeightNoLeading
+ ceilf(fontHeight
.leading
);
2149 // find largest label
2150 float labelWidth
= 0;
2152 labelWidth
= StringWidth(Label());
2153 height
+= lineHeightNoLeading
;
2155 if (MaxLimitLabel()) {
2156 labelWidth
= max_c(labelWidth
, StringWidth(MaxLimitLabel()));
2157 height
+= Label() ? lineHeight
: lineHeightNoLeading
;
2159 if (MinLimitLabel()) {
2160 labelWidth
= max_c(labelWidth
, StringWidth(MinLimitLabel()));
2161 height
+= lineHeightNoLeading
;
2163 if (fMaxUpdateTextWidth
> 0.0) {
2164 labelWidth
= max_c(labelWidth
, fMaxUpdateTextWidth
);
2165 height
+= MinLimitLabel() ? lineHeight
: lineHeightNoLeading
;
2168 width
= max_c(labelWidth
, width
);
2171 fMinSize
.width
= width
;
2172 fMinSize
.height
= height
;
2174 ResetLayoutInvalidation();
2180 // #pragma mark - FBC padding
2182 void BSlider::_ReservedSlider6() {}
2183 void BSlider::_ReservedSlider7() {}
2184 void BSlider::_ReservedSlider8() {}
2185 void BSlider::_ReservedSlider9() {}
2186 void BSlider::_ReservedSlider10() {}
2187 void BSlider::_ReservedSlider11() {}
2188 void BSlider::_ReservedSlider12() {}
2192 BSlider::operator=(const BSlider
&)
2198 // #pragma mark - BeOS compatibility
2204 GetLimits__7BSliderPlT1(BSlider
* slider
, int32
* minimum
, int32
* maximum
)
2206 slider
->GetLimits(minimum
, maximum
);
2211 _ReservedSlider4__7BSlider(BSlider
*slider
, int32 minimum
, int32 maximum
)
2213 slider
->BSlider::SetLimits(minimum
, maximum
);
2217 _ReservedSlider5__7BSlider(BSlider
*slider
)
2219 return slider
->BSlider::MaxUpdateTextWidth();
2224 _ReservedSlider1__7BSlider(BSlider
* slider
, orientation _orientation
)
2226 slider
->BSlider::SetOrientation(_orientation
);
2231 _ReservedSlider2__7BSlider(BSlider
* slider
, float thickness
)
2233 slider
->BSlider::SetBarThickness(thickness
);
2238 _ReservedSlider3__7BSlider(BSlider
* slider
, const BFont
* font
,
2241 slider
->BSlider::SetFont(font
, properties
);
2245 #endif // __GNUC__ < 3
2249 B_IF_GCC_2(InvalidateLayout__7BSliderb
, _ZN7BSlider16InvalidateLayoutEb
)(
2250 BView
* view
, bool descendants
)
2252 perform_data_layout_invalidated data
;
2253 data
.descendants
= descendants
;
2255 view
->Perform(PERFORM_CODE_LAYOUT_INVALIDATED
, &data
);