* Changed the signature of UpdateText() to return a "const char*" (char*
really makes no sense if the pointer belongs to the derived class and only confuses). Note this change does not affect binary compatibility. * Introduced a new MaxUpdateTextWidth() virtual method which is really necessary to handle the update text correctly in the layout. * Introduced a new UpdateTextChanged() method which can be called to notify the control of a changed update text. Internally, SetValue() also uses it. * Handle the width or height of the UpdateText() correctly in the layout. For horizontal layout, the width was forgotten to be included in GetPreferredSize(), for vertical layout, it was completely broken before. * Handle invalidation correctly when the UpdateText() changes. * Remove the arbitrary insets for labels from the border the control. This makes it easier to align the control's labels with other controls. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26447 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -91,7 +91,8 @@ class BSlider : public BControl {
|
||||
virtual void DrawThumb();
|
||||
virtual void DrawFocusMark();
|
||||
virtual void DrawText();
|
||||
virtual char* UpdateText() const;
|
||||
virtual const char* UpdateText() const;
|
||||
void UpdateTextChanged();
|
||||
|
||||
virtual BRect BarFrame() const;
|
||||
virtual BRect HashMarksFrame() const;
|
||||
@@ -145,6 +146,8 @@ class BSlider : public BControl {
|
||||
|
||||
virtual void SetLimits(int32 minimum, int32 maximum);
|
||||
|
||||
virtual float MaxUpdateTextWidth();
|
||||
|
||||
virtual void InvalidateLayout(bool descendants = false);
|
||||
|
||||
virtual BSize MinSize();
|
||||
@@ -164,7 +167,6 @@ class BSlider : public BControl {
|
||||
|
||||
BSize _ValidateMinSize();
|
||||
|
||||
virtual void _ReservedSlider5();
|
||||
virtual void _ReservedSlider6();
|
||||
virtual void _ReservedSlider7();
|
||||
virtual void _ReservedSlider8();
|
||||
@@ -187,7 +189,7 @@ class BSlider : public BControl {
|
||||
|
||||
char* fMinLimitLabel;
|
||||
char* fMaxLimitLabel;
|
||||
char* fUpdateText;
|
||||
const char* fUpdateText;
|
||||
|
||||
int32 fMinValue;
|
||||
int32 fMaxValue;
|
||||
@@ -211,10 +213,12 @@ class BSlider : public BControl {
|
||||
|
||||
BSize fMinSize;
|
||||
|
||||
float fMaxUpdateTextWidth;
|
||||
|
||||
#if USE_OFF_SCREEN_VIEW
|
||||
uint32 _reserved[5];
|
||||
uint32 _reserved[4];
|
||||
#else
|
||||
uint32 _reserved[7];
|
||||
uint32 _reserved[6];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
+192
-113
@@ -21,6 +21,7 @@
|
||||
#include <LayoutUtils.h>
|
||||
#include <Message.h>
|
||||
#include <Region.h>
|
||||
#include <String.h>
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
@@ -225,6 +226,7 @@ BSlider::_InitObject()
|
||||
|
||||
fUpdateText = NULL;
|
||||
fMinSize.Set(-1, -1);
|
||||
fMaxUpdateTextWidth = -1.0;
|
||||
}
|
||||
|
||||
|
||||
@@ -662,25 +664,7 @@ BSlider::SetValue(int32 value)
|
||||
|
||||
Invalidate(invalid);
|
||||
|
||||
// update text label
|
||||
|
||||
float oldWidth = 0.0f, width = 0.0f;
|
||||
if (fUpdateText != NULL)
|
||||
oldWidth = StringWidth(fUpdateText);
|
||||
|
||||
fUpdateText = UpdateText();
|
||||
if (fUpdateText != NULL)
|
||||
width = StringWidth(fUpdateText);
|
||||
|
||||
width = ceilf(max_c(width, oldWidth)) + 2.0f;
|
||||
if (width != 0) {
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
|
||||
BRect rect(-width, 0, 0, ceilf(fontHeight.ascent + fontHeight.descent));
|
||||
rect.OffsetBy(Bounds().Width(), 0);
|
||||
Invalidate(rect);
|
||||
}
|
||||
UpdateTextChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -1069,46 +1053,53 @@ BSlider::DrawText()
|
||||
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
|
||||
if (Orientation() == B_HORIZONTAL) {
|
||||
if (Label())
|
||||
view->DrawString(Label(), BPoint(2.0f, ceilf(fontHeight.ascent)));
|
||||
view->DrawString(Label(), BPoint(0.0, ceilf(fontHeight.ascent)));
|
||||
|
||||
// the update text is updated in SetValue() only
|
||||
if (fUpdateText != NULL) {
|
||||
view->DrawString(fUpdateText, BPoint(bounds.right - StringWidth(fUpdateText)
|
||||
- 2.0f, ceilf(fontHeight.ascent)));
|
||||
}
|
||||
|
||||
if (fMinLimitLabel)
|
||||
view->DrawString(fMinLimitLabel, BPoint(2.0f, bounds.bottom - 4.0f));
|
||||
|
||||
if (fMaxLimitLabel) {
|
||||
view->DrawString(fMaxLimitLabel, BPoint(bounds.right
|
||||
- StringWidth(fMaxLimitLabel) - 2.0f, bounds.bottom - 4.0f));
|
||||
}
|
||||
} else {
|
||||
if (Label()) {
|
||||
view->DrawString(Label(), BPoint(bounds.Width() / 2.0f -
|
||||
StringWidth(Label()) / 2.0f,
|
||||
fontHeight.ascent));
|
||||
}
|
||||
|
||||
if (fUpdateText != NULL) {
|
||||
view->DrawString(fUpdateText, BPoint(bounds.Width() / 2.0f -
|
||||
StringWidth(fUpdateText) / 2.0f, bounds.bottom - fontHeight.descent - 4.0f));
|
||||
}
|
||||
|
||||
if (fMaxLimitLabel) {
|
||||
view->DrawString(fMaxLimitLabel, BPoint(bounds.Width() / 2.0f -
|
||||
StringWidth(fMaxLimitLabel) / 2.0f, fontHeight.ascent + (Label()
|
||||
? ceilf(fontHeight.ascent + fontHeight.descent + fontHeight.leading + 2.0f)
|
||||
: 0.0f)));
|
||||
view->DrawString(fUpdateText, BPoint(bounds.right
|
||||
- StringWidth(fUpdateText), ceilf(fontHeight.ascent)));
|
||||
}
|
||||
|
||||
if (fMinLimitLabel) {
|
||||
view->DrawString(fMinLimitLabel, BPoint(bounds.Width() / 2.0f
|
||||
- StringWidth(fMinLimitLabel) / 2.0f, bounds.bottom - 2.0f));
|
||||
view->DrawString(fMinLimitLabel, BPoint(0.0, bounds.bottom
|
||||
- fontHeight.descent));
|
||||
}
|
||||
|
||||
if (fMaxLimitLabel) {
|
||||
view->DrawString(fMaxLimitLabel, BPoint(bounds.right
|
||||
- StringWidth(fMaxLimitLabel), bounds.bottom
|
||||
- fontHeight.descent));
|
||||
}
|
||||
} else {
|
||||
float lineHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent)
|
||||
+ ceilf(fontHeight.leading);
|
||||
float baseLine = ceilf(fontHeight.ascent);
|
||||
|
||||
if (Label()) {
|
||||
view->DrawString(Label(), BPoint((bounds.Width()
|
||||
- StringWidth(Label())) / 2.0, baseLine));
|
||||
baseLine += lineHeight;
|
||||
}
|
||||
|
||||
if (fMaxLimitLabel) {
|
||||
view->DrawString(fMaxLimitLabel, BPoint((bounds.Width()
|
||||
- StringWidth(fMaxLimitLabel)) / 2.0, baseLine));
|
||||
}
|
||||
|
||||
baseLine = bounds.bottom - ceilf(fontHeight.descent);
|
||||
|
||||
if (fMinLimitLabel) {
|
||||
view->DrawString(fMinLimitLabel, BPoint((bounds.Width()
|
||||
- StringWidth(fMinLimitLabel)) / 2.0, baseLine));
|
||||
baseLine -= lineHeight;
|
||||
}
|
||||
|
||||
if (fUpdateText != NULL) {
|
||||
view->DrawString(fUpdateText, BPoint((bounds.Width()
|
||||
- StringWidth(fUpdateText)) / 2.0, baseLine));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1117,13 +1108,59 @@ BSlider::DrawText()
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
char*
|
||||
const char*
|
||||
BSlider::UpdateText() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BSlider::UpdateTextChanged()
|
||||
{
|
||||
// update text label
|
||||
float oldWidth = 0.0;
|
||||
if (fUpdateText != NULL)
|
||||
oldWidth = StringWidth(fUpdateText);
|
||||
|
||||
const char* oldUpdateText = fUpdateText;
|
||||
fUpdateText = UpdateText();
|
||||
bool updateTextOnOff = fUpdateText == NULL && oldUpdateText != NULL
|
||||
|| fUpdateText != NULL && oldUpdateText == NULL;
|
||||
|
||||
float newWidth = 0.0;
|
||||
if (fUpdateText != NULL)
|
||||
newWidth = StringWidth(fUpdateText);
|
||||
|
||||
float width = ceilf(max_c(newWidth, oldWidth)) + 2.0f;
|
||||
if (width != 0) {
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
|
||||
float height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
|
||||
float lineHeight = height + ceilf(fontHeight.leading);
|
||||
BRect invalid(Bounds());
|
||||
if (fOrientation == B_HORIZONTAL)
|
||||
invalid = BRect(invalid.right - width, 0, invalid.right, height);
|
||||
else {
|
||||
if (!updateTextOnOff) {
|
||||
invalid.left = (invalid.left + invalid.right - width) / 2;
|
||||
invalid.right = invalid.left + width;
|
||||
if (fMinLimitLabel)
|
||||
invalid.bottom -= lineHeight;
|
||||
invalid.top = invalid.bottom - height;
|
||||
}
|
||||
}
|
||||
Invalidate(invalid);
|
||||
}
|
||||
|
||||
float oldMaxUpdateTextWidth = fMaxUpdateTextWidth;
|
||||
fMaxUpdateTextWidth = MaxUpdateTextWidth();
|
||||
if (oldMaxUpdateTextWidth != fMaxUpdateTextWidth)
|
||||
InvalidateLayout();
|
||||
}
|
||||
|
||||
|
||||
BRect
|
||||
BSlider::BarFrame() const
|
||||
{
|
||||
@@ -1132,35 +1169,39 @@ BSlider::BarFrame() const
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
|
||||
float textHeight = (float)ceil(fontHeight.ascent + fontHeight.descent);
|
||||
|
||||
if (fStyle == B_BLOCK_THUMB) {
|
||||
if (Orientation() == B_HORIZONTAL) {
|
||||
frame.left = 8.0f;
|
||||
frame.top = 6.0f + (Label() ? textHeight + 4.0f : 0.0f);
|
||||
frame.right -= 8.0f;
|
||||
frame.bottom = frame.top + fBarThickness;
|
||||
} else {
|
||||
frame.left = floor((frame.Width() - fBarThickness) / 2.0f);
|
||||
frame.top = 12.0f + (Label() ? textHeight : 0.0f) +
|
||||
(fMaxLimitLabel ? textHeight : 0.0f);
|
||||
frame.right = frame.left + fBarThickness;
|
||||
frame.bottom = frame.bottom - 8.0f -
|
||||
(fMinLimitLabel ? textHeight + 4 : 0.0f);
|
||||
}
|
||||
float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
|
||||
float leading = ceilf(fontHeight.leading);
|
||||
|
||||
float thumbInset;
|
||||
if (fStyle == B_BLOCK_THUMB)
|
||||
thumbInset = 8.0;
|
||||
else
|
||||
thumbInset = 7.0;
|
||||
|
||||
if (Orientation() == B_HORIZONTAL) {
|
||||
frame.left = thumbInset;
|
||||
frame.top = 6.0 + (Label() ? textHeight + 4.0 : 0.0);
|
||||
frame.right -= thumbInset;
|
||||
frame.bottom = frame.top + fBarThickness;
|
||||
} else {
|
||||
if (Orientation() == B_HORIZONTAL) {
|
||||
frame.left = 7.0f;
|
||||
frame.top = 6.0f + (Label() ? textHeight + 4.0f : 0.0f);
|
||||
frame.right -= 7.0f;
|
||||
frame.bottom = frame.top + fBarThickness;
|
||||
} else {
|
||||
frame.left = floor((frame.Width() - fBarThickness) / 2.0f);
|
||||
frame.top = 11.0f + (Label() ? textHeight : 0.0f) +
|
||||
(fMaxLimitLabel ? textHeight : 0.0f);
|
||||
frame.right = frame.left + fBarThickness;
|
||||
frame.bottom = frame.bottom - 7.0f -
|
||||
(fMinLimitLabel ? textHeight + 4 : 0.0f);
|
||||
frame.left = floorf((frame.Width() - fBarThickness) / 2.0);
|
||||
frame.top = thumbInset;
|
||||
if (Label())
|
||||
frame.top += textHeight;
|
||||
if (fMaxLimitLabel) {
|
||||
frame.top += textHeight;
|
||||
if (Label())
|
||||
frame.top += leading;
|
||||
}
|
||||
|
||||
frame.right = frame.left + fBarThickness;
|
||||
frame.bottom = frame.bottom - thumbInset;
|
||||
if (fMinLimitLabel)
|
||||
frame.bottom -= textHeight;
|
||||
if (fUpdateText) {
|
||||
frame.bottom -= textHeight;
|
||||
if (fMinLimitLabel)
|
||||
frame.bottom -= leading;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1174,11 +1215,11 @@ BSlider::HashMarksFrame() const
|
||||
BRect frame(BarFrame());
|
||||
|
||||
if (fOrientation == B_HORIZONTAL) {
|
||||
frame.top -= 6.0f;
|
||||
frame.bottom += 6.0f;
|
||||
frame.top -= 6.0;
|
||||
frame.bottom += 6.0;
|
||||
} else {
|
||||
frame.left -= 6.0f;
|
||||
frame.right += 6.0f;
|
||||
frame.left -= 6.0;
|
||||
frame.right += 6.0;
|
||||
}
|
||||
|
||||
return frame;
|
||||
@@ -1193,25 +1234,25 @@ BSlider::ThumbFrame() const
|
||||
// and spread them further apart for the thumb
|
||||
|
||||
BRect frame = Bounds();
|
||||
font_height fheight;
|
||||
|
||||
GetFontHeight(&fheight);
|
||||
font_height fontHeight;
|
||||
GetFontHeight(&fontHeight);
|
||||
|
||||
float textHeight = (float)ceil(fheight.ascent + fheight.descent);
|
||||
float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent);
|
||||
|
||||
if (fStyle == B_BLOCK_THUMB) {
|
||||
if (Orientation() == B_HORIZONTAL) {
|
||||
frame.left = (float)floor(Position() * (_MaxPosition() - _MinPosition()) +
|
||||
_MinPosition()) - 8.0f;
|
||||
frame.top = 2.0f + (Label() ? textHeight + 4.0f : 0.0f);
|
||||
frame.right = frame.left + 17.0f;
|
||||
frame.bottom = frame.top + fBarThickness + 7.0f;
|
||||
_MinPosition()) - 8.0;
|
||||
frame.top = 2.0 + (Label() ? textHeight + 4.0 : 0.0);
|
||||
frame.right = frame.left + 17.0;
|
||||
frame.bottom = frame.top + fBarThickness + 7.0;
|
||||
} else {
|
||||
frame.left = floor((frame.Width() - fBarThickness) / 2.0f) - 4;
|
||||
frame.left = floor((frame.Width() - fBarThickness) / 2.0) - 4;
|
||||
frame.top = (float)floor(Position() * (_MaxPosition() - _MinPosition()) +
|
||||
_MinPosition()) - 8.0f;
|
||||
frame.right = frame.left + fBarThickness + 7.0f;
|
||||
frame.bottom = frame.top + 17;
|
||||
_MinPosition()) - 8.0;
|
||||
frame.right = frame.left + fBarThickness + 7.0;
|
||||
frame.bottom = frame.top + 17.0;
|
||||
}
|
||||
} else {
|
||||
if (Orientation() == B_HORIZONTAL) {
|
||||
@@ -1508,6 +1549,22 @@ BSlider::SetLimits(int32 minimum, int32 maximum)
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
BSlider::MaxUpdateTextWidth()
|
||||
{
|
||||
// very simplistic implementation that assumes the string will be widest
|
||||
// at the maximum value
|
||||
int32 value = Value();
|
||||
SetValueNoUpdate(fMaxValue);
|
||||
float width = StringWidth(UpdateText());
|
||||
SetValueNoUpdate(value);
|
||||
// in case the derived class uses a fixed buffer, the contents
|
||||
// should be reset for the old value
|
||||
UpdateText();
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - layout related
|
||||
|
||||
|
||||
@@ -1812,23 +1869,35 @@ BSlider::_ValidateMinSize()
|
||||
|
||||
float width = 0.0;
|
||||
float height = 0.0;
|
||||
int32 rows = 0;
|
||||
|
||||
if (fMaxUpdateTextWidth < 0.0)
|
||||
fMaxUpdateTextWidth = MaxUpdateTextWidth();
|
||||
|
||||
if (Orientation() == B_HORIZONTAL) {
|
||||
height = 12.0 + fBarThickness;
|
||||
int32 rows = 0;
|
||||
|
||||
float labelWidth = 0;
|
||||
int32 labelRows = 0;
|
||||
float labelSpacing = StringWidth("M") * 2;
|
||||
if (Label()) {
|
||||
labelWidth = StringWidth(Label());
|
||||
rows++;
|
||||
labelRows = 1;
|
||||
}
|
||||
if (fMaxUpdateTextWidth > 0.0) {
|
||||
if (labelWidth > 0)
|
||||
labelWidth += labelSpacing;
|
||||
labelWidth += fMaxUpdateTextWidth;
|
||||
labelRows = 1;
|
||||
}
|
||||
rows += labelRows;
|
||||
|
||||
if (MinLimitLabel())
|
||||
width = StringWidth(MinLimitLabel());
|
||||
if (MaxLimitLabel()) {
|
||||
// some space between the labels
|
||||
if (MinLimitLabel())
|
||||
width += 8.0;
|
||||
width += labelSpacing;
|
||||
|
||||
width += StringWidth(MaxLimitLabel());
|
||||
}
|
||||
@@ -1846,29 +1915,32 @@ BSlider::_ValidateMinSize()
|
||||
} else {
|
||||
// B_VERTICAL
|
||||
width = 12.0 + fBarThickness;
|
||||
height = 32.0;
|
||||
|
||||
float lineHeightNoLeading = ceilf(fontHeight.ascent)
|
||||
+ ceilf(fontHeight.descent);
|
||||
float lineHeight = lineHeightNoLeading + ceilf(fontHeight.leading);
|
||||
|
||||
// find largest label
|
||||
float labelWidth = 0;
|
||||
if (Label()) {
|
||||
labelWidth = StringWidth(Label());
|
||||
rows++;
|
||||
}
|
||||
if (MinLimitLabel()) {
|
||||
labelWidth = max_c(labelWidth, StringWidth(MinLimitLabel()));
|
||||
rows++;
|
||||
height += lineHeightNoLeading;
|
||||
}
|
||||
if (MaxLimitLabel()) {
|
||||
labelWidth = max_c(labelWidth, StringWidth(MaxLimitLabel()));
|
||||
rows++;
|
||||
height += Label() ? lineHeight : lineHeightNoLeading;
|
||||
}
|
||||
if (MinLimitLabel()) {
|
||||
labelWidth = max_c(labelWidth, StringWidth(MinLimitLabel()));
|
||||
height += lineHeightNoLeading;
|
||||
}
|
||||
if (fMaxUpdateTextWidth > 0.0) {
|
||||
labelWidth = max_c(labelWidth, fMaxUpdateTextWidth);
|
||||
height += MinLimitLabel() ? lineHeight : lineHeightNoLeading;
|
||||
}
|
||||
|
||||
width = max_c(labelWidth, width);
|
||||
|
||||
height = 32.0 + rows * (ceilf(fontHeight.ascent)
|
||||
+ ceilf(fontHeight.descent) + 4.0);
|
||||
|
||||
if (Label() && MaxLimitLabel())
|
||||
height -= 4.0f;
|
||||
}
|
||||
|
||||
fMinSize.width = width;
|
||||
@@ -1880,7 +1952,6 @@ BSlider::_ValidateMinSize()
|
||||
|
||||
// #pragma mark - FBC padding
|
||||
|
||||
void BSlider::_ReservedSlider5() {}
|
||||
void BSlider::_ReservedSlider6() {}
|
||||
void BSlider::_ReservedSlider7() {}
|
||||
void BSlider::_ReservedSlider8() {}
|
||||
@@ -1897,17 +1968,25 @@ BSlider::operator=(const BSlider &)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - R4.5 compatibility
|
||||
// #pragma mark - BeOS compatibility
|
||||
|
||||
|
||||
#if __GNUC__ < 3
|
||||
|
||||
extern "C"
|
||||
void _ReservedSlider4__7BSlider(BSlider *slider, int32 minimum, int32 maximum)
|
||||
void
|
||||
_ReservedSlider4__7BSlider(BSlider *slider, int32 minimum, int32 maximum)
|
||||
{
|
||||
slider->BSlider::SetLimits(minimum, maximum);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
float
|
||||
_ReservedSlider5__7BSlider(BSlider *slider)
|
||||
{
|
||||
return slider->BSlider::MaxUpdateTextWidth();
|
||||
}
|
||||
|
||||
extern "C" void _ReservedSlider1__7BSlider() {}
|
||||
extern "C" void _ReservedSlider2__7BSlider() {}
|
||||
extern "C" void _ReservedSlider3__7BSlider() {}
|
||||
|
||||
Reference in New Issue
Block a user