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.
This commit is contained in:
Ingo Weinhold
2013-12-22 04:48:21 +01:00
parent 6af520e2a9
commit f829889455
2 changed files with 48 additions and 177 deletions
+2
View File
@@ -84,6 +84,8 @@ private:
virtual void _ReservedCheckBox3(); virtual void _ReservedCheckBox3();
private: private:
inline BRect _CheckBoxFrame(const font_height& fontHeight)
const;
BRect _CheckBoxFrame() const; BRect _CheckBoxFrame() const;
BSize _ValidatePreferredSize(); BSize _ValidatePreferredSize();
int32 _NextState() const; int32 _NextState() const;
+37 -168
View File
@@ -12,8 +12,10 @@
#include <CheckBox.h> #include <CheckBox.h>
#include <algorithm>
#include <new> #include <new>
#include <Bitmap.h>
#include <ControlLook.h> #include <ControlLook.h>
#include <LayoutUtils.h> #include <LayoutUtils.h>
#include <Window.h> #include <Window.h>
@@ -100,7 +102,6 @@ BCheckBox::Archive(BMessage *archive, bool deep) const
void void
BCheckBox::Draw(BRect updateRect) 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); uint32 flags = be_control_look->Flags(this);
@@ -112,155 +113,14 @@ BCheckBox::Draw(BRect updateRect)
be_control_look->DrawCheckBox(this, rect, updateRect,base, flags); be_control_look->DrawCheckBox(this, rect, updateRect,base, flags);
BRect labelRect(Bounds()); BRect labelRect(Bounds());
labelRect.left = checkBoxRect.right labelRect.left = checkBoxRect.right + 1
+ be_control_look->DefaultLabelSpacing(); + be_control_look->DefaultLabelSpacing();
be_control_look->DrawLabel(this, Label(), labelRect, updateRect, const BBitmap* icon = IconBitmap(
B_OFF_BITMAP | (IsEnabled() ? 0 : B_DISABLED_BITMAP));
be_control_look->DrawLabel(this, Label(), icon, labelRect, updateRect,
base, flags); base, flags);
return;
}
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)));
}
} }
@@ -429,20 +289,13 @@ BCheckBox::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
void void
BCheckBox::GetPreferredSize(float* _width, float* _height) BCheckBox::GetPreferredSize(float* _width, float* _height)
{ {
font_height fontHeight; _ValidatePreferredSize();
GetFontHeight(&fontHeight);
if (_width) { if (_width)
float width = 12.0f + fontHeight.ascent; *_width = fPreferredSize.width;
if (Label())
width += StringWidth(Label());
*_width = (float)ceil(width);
}
if (_height) 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 status_t
BCheckBox::SetIcon(const BBitmap* icon, uint32 flags) 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() {} 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 BRect
BCheckBox::_CheckBoxFrame() const BCheckBox::_CheckBoxFrame() const
{ {
font_height fontHeight; font_height fontHeight;
GetFontHeight(&fontHeight); GetFontHeight(&fontHeight);
return _CheckBoxFrame(fontHeight);
return BRect(0.0f, 2.0f, ceilf(3.0f + fontHeight.ascent),
ceilf(5.0f + fontHeight.ascent));
} }
@@ -655,15 +514,25 @@ BCheckBox::_ValidatePreferredSize()
font_height fontHeight; font_height fontHeight;
GetFontHeight(&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()) const BBitmap* icon = IconBitmap(B_OFF_BITMAP);
width += StringWidth(Label()); 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 fPreferredSize.Set(width, height);
+ fontHeight.descent);
ResetLayoutInvalidation(); ResetLayoutInvalidation();
} }