From f829889455c220fd756cdd4fb807297f691e63b7 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 22 Dec 2013 04:48:21 +0100 Subject: [PATCH] BCheckBox: Add icon support * Draw(): Remove the non-BControlLook code. * GetPreferredSize(): Implement based on _ValidatePreferredSize() to avoid code duplication. * Draw(): Fix off-by-one error. The label was too close to the box. * Draw(), _ValidatePreferredSize(): Add icon support. _ValidatePreferredSize() is now actually aligned with what Draw() expects. The preferred width is now a tight fit; there were three or four pixels of empty space before. Due to the fixed check box position the layout isn't that nice in some situations (particularly with an icon larger than the text), IMHO. --- headers/os/interface/CheckBox.h | 2 + src/kits/interface/CheckBox.cpp | 223 +++++++------------------------- 2 files changed, 48 insertions(+), 177 deletions(-) diff --git a/headers/os/interface/CheckBox.h b/headers/os/interface/CheckBox.h index 70f89a8388..995e4e5d5e 100644 --- a/headers/os/interface/CheckBox.h +++ b/headers/os/interface/CheckBox.h @@ -84,6 +84,8 @@ private: virtual void _ReservedCheckBox3(); private: + inline BRect _CheckBoxFrame(const font_height& fontHeight) + const; BRect _CheckBoxFrame() const; BSize _ValidatePreferredSize(); int32 _NextState() const; diff --git a/src/kits/interface/CheckBox.cpp b/src/kits/interface/CheckBox.cpp index d991bd068b..56225e22ea 100644 --- a/src/kits/interface/CheckBox.cpp +++ b/src/kits/interface/CheckBox.cpp @@ -12,8 +12,10 @@ #include +#include #include +#include #include #include #include @@ -100,167 +102,25 @@ BCheckBox::Archive(BMessage *archive, bool deep) const void BCheckBox::Draw(BRect updateRect) { - if (be_control_look != NULL) { - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - uint32 flags = be_control_look->Flags(this); - if (fOutlined) - flags |= BControlLook::B_CLICKED; + uint32 flags = be_control_look->Flags(this); + if (fOutlined) + flags |= BControlLook::B_CLICKED; - BRect checkBoxRect(_CheckBoxFrame()); - BRect rect(checkBoxRect); - be_control_look->DrawCheckBox(this, rect, updateRect,base, flags); + BRect checkBoxRect(_CheckBoxFrame()); + BRect rect(checkBoxRect); + be_control_look->DrawCheckBox(this, rect, updateRect,base, flags); - BRect labelRect(Bounds()); - labelRect.left = checkBoxRect.right - + be_control_look->DefaultLabelSpacing(); + BRect labelRect(Bounds()); + labelRect.left = checkBoxRect.right + 1 + + be_control_look->DefaultLabelSpacing(); - be_control_look->DrawLabel(this, Label(), labelRect, updateRect, - base, flags); - return; - } + const BBitmap* icon = IconBitmap( + B_OFF_BITMAP | (IsEnabled() ? 0 : B_DISABLED_BITMAP)); - font_height fontHeight; - GetFontHeight(&fontHeight); - - // If the focus is changing, just redraw the focus indicator - if (IsFocusChanging()) { - float x = (float)ceil(10.0f + fontHeight.ascent); - float y = 5.0f + (float)ceil(fontHeight.ascent); - - if (IsFocus()) - SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); - else - SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - - StrokeLine(BPoint(x, y), BPoint(x + StringWidth(Label()), y)); - return; - } - - rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR); - rgb_color lighten1 = tint_color(noTint, B_LIGHTEN_1_TINT); - rgb_color lightenMax = tint_color(noTint, B_LIGHTEN_MAX_TINT); - rgb_color darken1 = tint_color(noTint, B_DARKEN_1_TINT); - rgb_color darken2 = tint_color(noTint, B_DARKEN_2_TINT); - rgb_color darken3 = tint_color(noTint, B_DARKEN_3_TINT); - rgb_color darken4 = tint_color(noTint, B_DARKEN_4_TINT); - rgb_color darkenmax = tint_color(noTint, B_DARKEN_MAX_TINT); - - BRect rect = _CheckBoxFrame(); - - if (IsEnabled()) { - // Filling - SetHighColor(lightenMax); - FillRect(rect); - - // Box - if (fOutlined) { - SetHighColor(darken3); - StrokeRect(rect); - - rect.InsetBy(1, 1); - - BeginLineArray(6); - - AddLine(BPoint(rect.left, rect.bottom), - BPoint(rect.left, rect.top), darken2); - AddLine(BPoint(rect.left, rect.top), - BPoint(rect.right, rect.top), darken2); - AddLine(BPoint(rect.left, rect.bottom), - BPoint(rect.right, rect.bottom), darken4); - AddLine(BPoint(rect.right, rect.bottom), - BPoint(rect.right, rect.top), darken4); - - EndLineArray(); - } else { - BeginLineArray(6); - - AddLine(BPoint(rect.left, rect.bottom), - BPoint(rect.left, rect.top), darken1); - AddLine(BPoint(rect.left, rect.top), - BPoint(rect.right, rect.top), darken1); - rect.InsetBy(1, 1); - AddLine(BPoint(rect.left, rect.bottom), - BPoint(rect.left, rect.top), darken4); - AddLine(BPoint(rect.left, rect.top), - BPoint(rect.right, rect.top), darken4); - AddLine(BPoint(rect.left + 1.0f, rect.bottom), - BPoint(rect.right, rect.bottom), noTint); - AddLine(BPoint(rect.right, rect.bottom), - BPoint(rect.right, rect.top + 1.0f), noTint); - - EndLineArray(); - } - - // Checkmark - if (Value() == B_CONTROL_ON) { - rect.InsetBy(3, 3); - - SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); - SetPenSize(2); - StrokeLine(BPoint(rect.left, rect.top), - BPoint(rect.right, rect.bottom)); - StrokeLine(BPoint(rect.left, rect.bottom), - BPoint(rect.right, rect.top)); - SetPenSize(1); - } - - // Label - SetHighColor(darkenmax); - DrawString(Label(), BPoint((float)ceil(10.0f + fontHeight.ascent), - 3.0f + (float)ceil(fontHeight.ascent))); - - // Focus - if (IsFocus()) { - float x = (float)ceil(10.0f + fontHeight.ascent); - float y = 5.0f + (float)ceil(fontHeight.ascent); - - SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); - StrokeLine(BPoint(x, y), BPoint(x + StringWidth(Label()), y)); - } - } else { - // Filling - SetHighColor(lighten1); - FillRect(rect); - - // Box - BeginLineArray(6); - - AddLine(BPoint(rect.left, rect.bottom), - BPoint(rect.left, rect.top), noTint); - AddLine(BPoint(rect.left, rect.top), - BPoint(rect.right, rect.top), noTint); - rect.InsetBy(1, 1); - AddLine(BPoint(rect.left, rect.bottom), - BPoint(rect.left, rect.top), darken2); - AddLine(BPoint(rect.left, rect.top), - BPoint(rect.right, rect.top), darken2); - AddLine(BPoint(rect.left + 1.0f, rect.bottom), - BPoint(rect.right, rect.bottom), darken1); - AddLine(BPoint(rect.right, rect.bottom), - BPoint(rect.right, rect.top + 1.0f), darken1); - - EndLineArray(); - - // Checkmark - if (Value() == B_CONTROL_ON) { - rect.InsetBy(3, 3); - - SetHighColor(tint_color(ui_color(B_KEYBOARD_NAVIGATION_COLOR), - B_DISABLED_MARK_TINT)); - SetPenSize(2); - StrokeLine(BPoint(rect.left, rect.top), - BPoint(rect.right, rect.bottom)); - StrokeLine(BPoint(rect.left, rect.bottom), - BPoint(rect.right, rect.top)); - SetPenSize(1); - } - - // Label - SetHighColor(tint_color(noTint, B_DISABLED_LABEL_TINT)); - DrawString(Label(), BPoint((float)ceil(10.0f + fontHeight.ascent), - 3.0f + (float)ceil(fontHeight.ascent))); - } + be_control_look->DrawLabel(this, Label(), icon, labelRect, updateRect, + base, flags); } @@ -429,20 +289,13 @@ BCheckBox::MouseMoved(BPoint point, uint32 transit, const BMessage *message) void BCheckBox::GetPreferredSize(float* _width, float* _height) { - font_height fontHeight; - GetFontHeight(&fontHeight); + _ValidatePreferredSize(); - if (_width) { - float width = 12.0f + fontHeight.ascent; - - if (Label()) - width += StringWidth(Label()); - - *_width = (float)ceil(width); - } + if (_width) + *_width = fPreferredSize.width; if (_height) - *_height = (float)ceil(6.0f + fontHeight.ascent + fontHeight.descent); + *_height = fPreferredSize.height; } @@ -603,7 +456,7 @@ BCheckBox::Perform(perform_code code, void* _data) status_t BCheckBox::SetIcon(const BBitmap* icon, uint32 flags) { - return BControl::SetIcon(icon, flags); + return BControl::SetIcon(icon, flags | B_CREATE_DISABLED_BITMAPS); } @@ -637,14 +490,20 @@ void BCheckBox::_ReservedCheckBox2() {} void BCheckBox::_ReservedCheckBox3() {} +BRect +BCheckBox::_CheckBoxFrame(const font_height& fontHeight) const +{ + return BRect(0.0f, 2.0f, ceilf(3.0f + fontHeight.ascent), + ceilf(5.0f + fontHeight.ascent)); +} + + BRect BCheckBox::_CheckBoxFrame() const { font_height fontHeight; GetFontHeight(&fontHeight); - - return BRect(0.0f, 2.0f, ceilf(3.0f + fontHeight.ascent), - ceilf(5.0f + fontHeight.ascent)); + return _CheckBoxFrame(fontHeight); } @@ -655,15 +514,25 @@ BCheckBox::_ValidatePreferredSize() font_height fontHeight; GetFontHeight(&fontHeight); - float width = 12.0f + fontHeight.ascent; + BRect rect(_CheckBoxFrame(fontHeight)); + float width = rect.right + rect.left; + float height = rect.bottom + rect.top; - if (Label()) - width += StringWidth(Label()); + const BBitmap* icon = IconBitmap(B_OFF_BITMAP); + if (icon != NULL) { + width += be_control_look->DefaultLabelSpacing() + + icon->Bounds().Width() + 1; + height = std::max(height, icon->Bounds().Height()); + } - fPreferredSize.width = (float)ceil(width); + if (const char* label = Label()) { + width += be_control_look->DefaultLabelSpacing() + + ceilf(StringWidth(label)); + height = std::max(height, + ceilf(6.0f + fontHeight.ascent + fontHeight.descent)); + } - fPreferredSize.height = (float)ceil(6.0f + fontHeight.ascent - + fontHeight.descent); + fPreferredSize.Set(width, height); ResetLayoutInvalidation(); }