hrev46584 adds 3 changesets to branch 'master' old head: 97bf0ce362dbcc6f8ee0e6a94a831214eae2431f new head: 5e815cf35b7cfada9473824c0e1f651081e9d93f overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5e815cf+%5E97bf0ce ---------------------------------------------------------------------------- f0c3101: BControl: Move icon code to separate class BIcon 36e1566: BRadioButton: Remove non-BControlLook code 5e815cf: BRadioButton: Add icon support * Fix off-by-one issue in Draw() and GetPreferredSize(). The label was too close to the knob. * GetPreferredSize(): Remove empty space to the right, when no label and no icon was specified. Like with BCheckBox there's still two rows of empty pixels above and below the knob. * Draw(), GetPreferredSize(): Add icon support. [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- 3 files changed, 635 insertions(+), 163 deletions(-) headers/private/interface/Icon.h | 68 +++++ src/kits/interface/Icon.cpp | 527 +++++++++++++++++++++++++++++++++ src/kits/interface/RadioButton.cpp | 203 +++---------- ############################################################################ Commit: f0c31011511b6d68aed5a764ffe7c201eb36e91a URL: http://cgit.haiku-os.org/haiku/commit/?id=f0c3101 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sun Dec 22 13:44:27 2013 UTC BControl: Move icon code to separate class BIcon ---------------------------------------------------------------------------- diff --git a/headers/private/interface/Icon.h b/headers/private/interface/Icon.h new file mode 100644 index 0000000..4c68efd --- /dev/null +++ b/headers/private/interface/Icon.h @@ -0,0 +1,68 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _INTERFACE__ICON_H_ +#define _INTERFACE__ICON_H_ + + +#include <InterfaceDefs.h> +#include <ObjectList.h> +#include <Rect.h> + + +class BBitmap; + + +namespace BPrivate { + + +class BIcon { +public: + BIcon(); + ~BIcon(); + + status_t SetTo(const BBitmap* bitmap, uint32 flags = 0); + + bool SetBitmap(BBitmap* bitmap, uint32 which); + BBitmap* Bitmap(uint32 which) const; + + status_t SetExternalBitmap(const BBitmap* bitmap, + uint32 which, uint32 flags); + + BBitmap* CreateBitmap(const BRect& bounds, + color_space colorSpace, uint32 which); + BBitmap* CopyBitmap(const BBitmap& bitmapToClone, + uint32 which); + void DeleteBitmaps(); + + // convenience methods for icon owners + static status_t UpdateIcon(const BBitmap* bitmap, uint32 flags, + BIcon*& _icon); + static status_t SetIconBitmap(const BBitmap* bitmap, + uint32 which, uint32 flags, BIcon*& _icon); + +private: + typedef BObjectList<BBitmap> BitmapList; + +private: + static BBitmap* _ConvertToRGB32(const BBitmap* bitmap, + bool noAppServerLink = false); + static status_t _TrimBitmap(const BBitmap* bitmap, + bool keepAspect, BBitmap*& _trimmedBitmap); + status_t _MakeBitmaps(const BBitmap* bitmap, + uint32 flags); + +private: + BitmapList fEnabledBitmaps; + BitmapList fDisabledBitmaps; +}; + + +} // namespace BPrivate + + +using BPrivate::BIcon; + + +#endif // _INTERFACE__ICON_H_ diff --git a/src/kits/interface/Icon.cpp b/src/kits/interface/Icon.cpp new file mode 100644 index 0000000..1cfbf74 --- /dev/null +++ b/src/kits/interface/Icon.cpp @@ -0,0 +1,527 @@ +/* + * Copyright 2006-2013, Haiku, Inc. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus, superstippi@xxxxxx + * Ingo Weinhold, ingo_weinhold@xxxxxx + */ + + +#include <Icon.h> + +#include <string.h> + +#include <new> + +#include <Bitmap.h> + +#include <AutoDeleter.h> + + +namespace BPrivate { + + +BIcon::BIcon() + : + fEnabledBitmaps(8, true), + fDisabledBitmaps(8, true) +{ +} + + +BIcon::~BIcon() +{ +} + + +status_t +BIcon::SetTo(const BBitmap* bitmap, uint32 flags) +{ + if (!bitmap->IsValid()) + return B_BAD_VALUE; + + DeleteBitmaps(); + + // check the color space + bool hasAlpha = false; + bool canUseForMakeBitmaps = false; + + switch (bitmap->ColorSpace()) { + case B_RGBA32: + case B_RGBA32_BIG: + hasAlpha = true; + // fall through + case B_RGB32: + case B_RGB32_BIG: + canUseForMakeBitmaps = true; + break; + + case B_UVLA32: + case B_LABA32: + case B_HSIA32: + case B_HSVA32: + case B_HLSA32: + case B_CMYA32: + case B_RGBA15: + case B_RGBA15_BIG: + case B_CMAP8: + hasAlpha = true; + break; + + default: + break; + } + + BBitmap* trimmedBitmap = NULL; + + // trim the bitmap, if requested and the bitmap actually has alpha + status_t error; + if ((flags & (B_TRIM_ICON_BITMAP | B_TRIM_ICON_BITMAP_KEEP_ASPECT)) != 0 + && hasAlpha) { + if (bitmap->ColorSpace() == B_RGBA32) { + error = _TrimBitmap(bitmap, + (flags & B_TRIM_ICON_BITMAP_KEEP_ASPECT) != 0, trimmedBitmap); + } else { + BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap, true); + if (rgb32Bitmap != NULL) { + error = _TrimBitmap(rgb32Bitmap, + (flags & B_TRIM_ICON_BITMAP_KEEP_ASPECT) != 0, + trimmedBitmap); + delete rgb32Bitmap; + } else + error = B_NO_MEMORY; + } + + if (error != B_OK) + return error; + + bitmap = trimmedBitmap; + canUseForMakeBitmaps = true; + } + + // create the bitmaps + if (canUseForMakeBitmaps) { + error = _MakeBitmaps(bitmap, flags); + } else { + if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap, true)) { + error = _MakeBitmaps(rgb32Bitmap, flags); + delete rgb32Bitmap; + } else + error = B_NO_MEMORY; + } + + delete trimmedBitmap; + + return error; +} + + +bool +BIcon::SetBitmap(BBitmap* bitmap, uint32 which) +{ + BitmapList& list = (which & B_DISABLED_ICON_BITMAP) == 0 + ? fEnabledBitmaps : fDisabledBitmaps; + which &= ~uint32(B_DISABLED_ICON_BITMAP); + + int32 count = list.CountItems(); + if ((int32)which < count) { + list.ReplaceItem(which, bitmap); + return true; + } + + while (list.CountItems() < (int32)which) { + if (!list.AddItem((BBitmap*)NULL)) + return false; + } + + return list.AddItem(bitmap); +} + + +BBitmap* +BIcon::Bitmap(uint32 which) const +{ + const BitmapList& list = (which & B_DISABLED_ICON_BITMAP) == 0 + ? fEnabledBitmaps : fDisabledBitmaps; + return list.ItemAt(which & ~uint32(B_DISABLED_ICON_BITMAP)); +} + + +BBitmap* +BIcon::CreateBitmap(const BRect& bounds, color_space colorSpace, uint32 which) +{ + BBitmap* bitmap = new(std::nothrow) BBitmap(bounds, colorSpace); + if (bitmap == NULL || !bitmap->IsValid() || !SetBitmap(bitmap, which)) { + delete bitmap; + return NULL; + } + + return bitmap; +} + + +status_t +BIcon::SetExternalBitmap(const BBitmap* bitmap, uint32 which, uint32 flags) +{ + BBitmap* ourBitmap = NULL; + if (bitmap != NULL) { + if (!bitmap->IsValid()) + return B_BAD_VALUE; + + if ((flags & B_KEEP_ICON_BITMAP) != 0) { + ourBitmap = const_cast<BBitmap*>(bitmap); + } else { + ourBitmap = _ConvertToRGB32(bitmap); + if (ourBitmap == NULL) + return B_NO_MEMORY; + } + } + + if (!SetBitmap(ourBitmap, which)) { + if (ourBitmap != bitmap) + delete ourBitmap; + return B_NO_MEMORY; + } + + return B_OK; +} + + +BBitmap* +BIcon::CopyBitmap(const BBitmap& bitmapToClone, uint32 which) +{ + BBitmap* bitmap = new(std::nothrow) BBitmap(bitmapToClone); + if (bitmap == NULL || !bitmap->IsValid() || !SetBitmap(bitmap, which)) { + delete bitmap; + return NULL; + } + + return bitmap; +} + + +void +BIcon::DeleteBitmaps() +{ + fEnabledBitmaps.MakeEmpty(true); + fDisabledBitmaps.MakeEmpty(true); +} + + +/*static*/ status_t +BIcon::UpdateIcon(const BBitmap* bitmap, uint32 flags, BIcon*& _icon) +{ + if (bitmap == NULL) { + delete _icon; + _icon = NULL; + return B_OK; + } + + BIcon* icon = new(std::nothrow) BIcon; + if (icon == NULL) + return B_NO_MEMORY; + + status_t error = icon->SetTo(bitmap, flags); + if (error != B_OK) { + delete icon; + return error; + } + + _icon = icon; + return B_OK; +} + + +/*static*/ status_t +BIcon::SetIconBitmap(const BBitmap* bitmap, uint32 which, uint32 flags, + BIcon*& _icon) +{ + bool newIcon = false; + if (_icon == NULL) { + if (bitmap == NULL) + return B_OK; + + _icon = new(std::nothrow) BIcon; + if (_icon == NULL) + return B_NO_MEMORY; + newIcon = true; + } + + status_t error = _icon->SetExternalBitmap(bitmap, which, flags); + if (error != B_OK) { + if (newIcon) { + delete _icon; + _icon = NULL; + } + return error; + } + + return B_OK; +} + + +/*static*/ BBitmap* +BIcon::_ConvertToRGB32(const BBitmap* bitmap, bool noAppServerLink) +{ + BBitmap* rgb32Bitmap = new(std::nothrow) BBitmap(bitmap->Bounds(), + noAppServerLink ? B_BITMAP_NO_SERVER_LINK : 0, B_RGBA32); + if (rgb32Bitmap == NULL) + return NULL; + + if (!rgb32Bitmap->IsValid() || rgb32Bitmap->ImportBits(bitmap)!= B_OK) { + delete rgb32Bitmap; + return NULL; + } + + return rgb32Bitmap; +} + + +/*static*/ status_t +BIcon::_TrimBitmap(const BBitmap* bitmap, bool keepAspect, + BBitmap*& _trimmedBitmap) +{ + if (bitmap == NULL || !bitmap->IsValid() + || bitmap->ColorSpace() != B_RGBA32) { + return B_BAD_VALUE; + } + + uint8* bits = (uint8*)bitmap->Bits(); + uint32 bpr = bitmap->BytesPerRow(); + uint32 width = bitmap->Bounds().IntegerWidth() + 1; + uint32 height = bitmap->Bounds().IntegerHeight() + 1; + BRect trimmed(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN); + + for (uint32 y = 0; y < height; y++) { + uint8* b = bits + 3; + bool rowHasAlpha = false; + for (uint32 x = 0; x < width; x++) { + if (*b) { + rowHasAlpha = true; + if (x < trimmed.left) + trimmed.left = x; + if (x > trimmed.right) + trimmed.right = x; + } + b += 4; + } + if (rowHasAlpha) { + if (y < trimmed.top) + trimmed.top = y; + if (y > trimmed.bottom) + trimmed.bottom = y; + } + bits += bpr; + } + + if (!trimmed.IsValid()) + return B_BAD_VALUE; + + if (keepAspect) { + float minInset = trimmed.left; + minInset = min_c(minInset, trimmed.top); + minInset = min_c(minInset, bitmap->Bounds().right - trimmed.right); + minInset = min_c(minInset, bitmap->Bounds().bottom - trimmed.bottom); + trimmed = bitmap->Bounds().InsetByCopy(minInset, minInset); + } + trimmed = trimmed & bitmap->Bounds(); + + BBitmap* trimmedBitmap = new(std::nothrow) BBitmap( + trimmed.OffsetToCopy(B_ORIGIN), B_BITMAP_NO_SERVER_LINK, B_RGBA32); + if (trimmedBitmap == NULL) + return B_NO_MEMORY; + + bits = (uint8*)bitmap->Bits(); + bits += 4 * (int32)trimmed.left + bpr * (int32)trimmed.top; + uint8* dst = (uint8*)trimmedBitmap->Bits(); + uint32 trimmedWidth = trimmedBitmap->Bounds().IntegerWidth() + 1; + uint32 trimmedHeight = trimmedBitmap->Bounds().IntegerHeight() + 1; + uint32 trimmedBPR = trimmedBitmap->BytesPerRow(); + for (uint32 y = 0; y < trimmedHeight; y++) { + memcpy(dst, bits, trimmedWidth * 4); + dst += trimmedBPR; + bits += bpr; + } + + _trimmedBitmap = trimmedBitmap; + return B_OK; +} + + +status_t +BIcon::_MakeBitmaps(const BBitmap* bitmap, uint32 flags) +{ + // make our own versions of the bitmap + BRect b(bitmap->Bounds()); + + color_space format = bitmap->ColorSpace(); + BBitmap* normalBitmap = CreateBitmap(b, format, B_INACTIVE_ICON_BITMAP); + if (normalBitmap == NULL) + return B_NO_MEMORY; + + BBitmap* disabledBitmap = NULL; + if ((flags & B_CREATE_DISABLED_ICON_BITMAPS) != 0) { + disabledBitmap = CreateBitmap(b, format, + B_INACTIVE_ICON_BITMAP | B_DISABLED_ICON_BITMAP); + if (disabledBitmap == NULL) + return B_NO_MEMORY; + } + + BBitmap* clickedBitmap = NULL; + if ((flags & (B_CREATE_ACTIVE_ICON_BITMAP + | B_CREATE_PARTIALLY_ACTIVE_ICON_BITMAP)) != 0) { + clickedBitmap = CreateBitmap(b, format, B_ACTIVE_ICON_BITMAP); + if (clickedBitmap == NULL) + return B_NO_MEMORY; + } + + BBitmap* disabledClickedBitmap = NULL; + if (disabledBitmap != NULL && clickedBitmap != NULL) { + disabledClickedBitmap = CreateBitmap(b, format, + B_ACTIVE_ICON_BITMAP | B_DISABLED_ICON_BITMAP); + if (disabledClickedBitmap == NULL) + return B_NO_MEMORY; + } + + // copy bitmaps from file bitmap + uint8* nBits = normalBitmap != NULL ? (uint8*)normalBitmap->Bits() : NULL; + uint8* dBits = disabledBitmap != NULL + ? (uint8*)disabledBitmap->Bits() : NULL; + uint8* cBits = clickedBitmap != NULL ? (uint8*)clickedBitmap->Bits() : NULL; + uint8* dcBits = disabledClickedBitmap != NULL + ? (uint8*)disabledClickedBitmap->Bits() : NULL; + uint8* fBits = (uint8*)bitmap->Bits(); + int32 nbpr = normalBitmap->BytesPerRow(); + int32 fbpr = bitmap->BytesPerRow(); + int32 pixels = b.IntegerWidth() + 1; + int32 lines = b.IntegerHeight() + 1; + if (format == B_RGB32 || format == B_RGB32_BIG) { + // nontransparent version + + // iterate over color components + for (int32 y = 0; y < lines; y++) { + for (int32 x = 0; x < pixels; x++) { + int32 nOffset = 4 * x; + int32 fOffset = 4 * x; + nBits[nOffset + 0] = fBits[fOffset + 0]; + nBits[nOffset + 1] = fBits[fOffset + 1]; + nBits[nOffset + 2] = fBits[fOffset + 2]; + nBits[nOffset + 3] = 255; + + // clicked bits are darker (lame method...) + if (cBits != NULL) { + cBits[nOffset + 0] = uint8((float)nBits[nOffset + 0] * 0.8); + cBits[nOffset + 1] = uint8((float)nBits[nOffset + 1] * 0.8); + cBits[nOffset + 2] = uint8((float)nBits[nOffset + 2] * 0.8); + cBits[nOffset + 3] = 255; + } + + // disabled bits have less contrast (lame method...) + if (dBits != NULL) { + uint8 grey = 216; + float dist = (nBits[nOffset + 0] - grey) * 0.4; + dBits[nOffset + 0] = (uint8)(grey + dist); + dist = (nBits[nOffset + 1] - grey) * 0.4; + dBits[nOffset + 1] = (uint8)(grey + dist); + dist = (nBits[nOffset + 2] - grey) * 0.4; + dBits[nOffset + 2] = (uint8)(grey + dist); + dBits[nOffset + 3] = 255; + } + + // disabled bits have less contrast (lame method...) + if (dcBits != NULL) { + uint8 grey = 188; + float dist = (nBits[nOffset + 0] - grey) * 0.4; + dcBits[nOffset + 0] = (uint8)(grey + dist); + dist = (nBits[nOffset + 1] - grey) * 0.4; + dcBits[nOffset + 1] = (uint8)(grey + dist); + dist = (nBits[nOffset + 2] - grey) * 0.4; + dcBits[nOffset + 2] = (uint8)(grey + dist); + dcBits[nOffset + 3] = 255; + } + } + fBits += fbpr; + nBits += nbpr; + if (cBits != NULL) + cBits += nbpr; + if (dBits != NULL) + dBits += nbpr; + if (dcBits != NULL) + dcBits += nbpr; + } + } else if (format == B_RGBA32 || format == B_RGBA32_BIG) { + // transparent version + + // iterate over color components + for (int32 y = 0; y < lines; y++) { + for (int32 x = 0; x < pixels; x++) { + int32 nOffset = 4 * x; + int32 fOffset = 4 * x; + nBits[nOffset + 0] = fBits[fOffset + 0]; + nBits[nOffset + 1] = fBits[fOffset + 1]; + nBits[nOffset + 2] = fBits[fOffset + 2]; + nBits[nOffset + 3] = fBits[fOffset + 3]; + + // clicked bits are darker (lame method...) + if (cBits != NULL) { + cBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8); + cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8); + cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); + cBits[nOffset + 3] = fBits[fOffset + 3]; + } + + // disabled bits have less opacity + if (dBits != NULL) { + uint8 grey = ((uint16)nBits[nOffset + 0] * 10 + + nBits[nOffset + 1] * 60 + + nBits[nOffset + 2] * 30) / 100; + float dist = (nBits[nOffset + 0] - grey) * 0.3; + dBits[nOffset + 0] = (uint8)(grey + dist); + dist = (nBits[nOffset + 1] - grey) * 0.3; + dBits[nOffset + 1] = (uint8)(grey + dist); + dist = (nBits[nOffset + 2] - grey) * 0.3; + dBits[nOffset + 2] = (uint8)(grey + dist); + dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3); + } + + // disabled bits have less contrast (lame method...) + if (dcBits != NULL) { + dcBits[nOffset + 0] = (uint8)(dBits[nOffset + 0] * 0.8); + dcBits[nOffset + 1] = (uint8)(dBits[nOffset + 1] * 0.8); + dcBits[nOffset + 2] = (uint8)(dBits[nOffset + 2] * 0.8); + dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3); + } + } + fBits += fbpr; + nBits += nbpr; + if (cBits != NULL) + cBits += nbpr; + if (dBits != NULL) + dBits += nbpr; + if (dcBits != NULL) + dcBits += nbpr; + } + } else { + // unsupported format + return B_BAD_VALUE; + } + + // make the partially-on bitmaps a copy of the on bitmaps + if ((flags & B_CREATE_PARTIALLY_ACTIVE_ICON_BITMAP) != 0) { + if (CopyBitmap(clickedBitmap, B_PARTIALLY_ACTIVATE_ICON_BITMAP) == NULL) + return B_NO_MEMORY; + if ((flags & B_CREATE_DISABLED_ICON_BITMAPS) != 0) { + if (CopyBitmap(disabledClickedBitmap, + B_PARTIALLY_ACTIVATE_ICON_BITMAP | B_DISABLED_ICON_BITMAP) + == NULL) { + return B_NO_MEMORY; + } + } + } + + return B_OK; +} + + +} // namespace BPrivate ############################################################################ Commit: 36e1566271e399169564810bb4859d8a5c0467cf URL: http://cgit.haiku-os.org/haiku/commit/?id=36e1566 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sun Dec 22 14:00:16 2013 UTC BRadioButton: Remove non-BControlLook code ---------------------------------------------------------------------------- diff --git a/src/kits/interface/RadioButton.cpp b/src/kits/interface/RadioButton.cpp index 2230c49..a39d59b 100644 --- a/src/kits/interface/RadioButton.cpp +++ b/src/kits/interface/RadioButton.cpp @@ -89,143 +89,22 @@ BRadioButton::Draw(BRect updateRect) font_height fontHeight; GetFontHeight(&fontHeight); - 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 knobRect(_KnobFrame(fontHeight)); - BRect rect(knobRect); - be_control_look->DrawRadioButton(this, rect, updateRect, base, flags); + BRect knobRect(_KnobFrame(fontHeight)); + BRect rect(knobRect); + be_control_look->DrawRadioButton(this, rect, updateRect, base, flags); - BRect labelRect(Bounds()); - labelRect.left = knobRect.right - + be_control_look->DefaultLabelSpacing(); + BRect labelRect(Bounds()); + labelRect.left = knobRect.right + + be_control_look->DefaultLabelSpacing(); - be_control_look->DrawLabel(this, Label(), labelRect, updateRect, - base, flags); - return; - } - - float textHeight = ceilf(fontHeight.ascent + fontHeight.descent); - - // layout the rect for the dot - BRect rect = _KnobFrame(fontHeight); - - BPoint labelPos(rect.right + floorf(textHeight / 2.0), - floorf((rect.top + rect.bottom + textHeight) / 2.0 - - fontHeight.descent + 0.5) + 1.0); - - // if the focus is changing, just redraw the focus indicator - if (IsFocusChanging()) { - if (IsFocus()) - SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); - else - SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - - BPoint underLine = labelPos; - underLine.y += fontHeight.descent; - StrokeLine(underLine, underLine + BPoint(StringWidth(Label()), 0.0)); - - return; - } - - // colors - rgb_color bg = ui_color(B_PANEL_BACKGROUND_COLOR); - rgb_color lightenmax; - rgb_color lighten1; - rgb_color darken1; - rgb_color darken2; - rgb_color darken3; - rgb_color darkenmax; - - rgb_color naviColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); - rgb_color knob; - rgb_color knobDark; - rgb_color knobLight; - - if (IsEnabled()) { - lightenmax = tint_color(bg, B_LIGHTEN_MAX_TINT); - lighten1 = tint_color(bg, B_LIGHTEN_1_TINT); - darken1 = tint_color(bg, B_DARKEN_1_TINT); - darken2 = tint_color(bg, B_DARKEN_2_TINT); - darken3 = tint_color(bg, B_DARKEN_3_TINT); - darkenmax = tint_color(bg, B_DARKEN_MAX_TINT); - - knob = naviColor; - knobDark = tint_color(naviColor, B_DARKEN_3_TINT); - knobLight = tint_color(naviColor, 0.15); - } else { - lightenmax = tint_color(bg, B_LIGHTEN_2_TINT); - lighten1 = bg; - darken1 = bg; - darken2 = tint_color(bg, B_DARKEN_1_TINT); - darken3 = tint_color(bg, B_DARKEN_2_TINT); - darkenmax = tint_color(bg, B_DISABLED_LABEL_TINT); - - knob = tint_color(naviColor, B_LIGHTEN_2_TINT); - knobDark = tint_color(naviColor, B_LIGHTEN_1_TINT); - knobLight = tint_color(naviColor, (B_LIGHTEN_2_TINT - + B_LIGHTEN_MAX_TINT) / 2.0); - } - - // dot - if (Value() == B_CONTROL_ON) { - // full - SetHighColor(knobDark); - FillEllipse(rect); - - SetHighColor(knob); - FillEllipse(BRect(rect.left + 2, rect.top + 2, rect.right - 3, - rect.bottom - 3)); - - SetHighColor(knobLight); - FillEllipse(BRect(rect.left + 3, rect.top + 3, rect.right - 5, - rect.bottom - 5)); - } else { - // empty - SetHighColor(lightenmax); - FillEllipse(rect); - } - - rect.InsetBy(-1.0, -1.0); - - // outer circle - if (fOutlined) { - // indicating "about to change value" - SetHighColor(darken3); - StrokeEllipse(rect); - } else { - SetHighColor(darken1); - StrokeArc(rect, 45.0, 180.0); - SetHighColor(lightenmax); - StrokeArc(rect, 45.0, -180.0); - } - - rect.InsetBy(1, 1); - - // inner circle - SetHighColor(darken3); - StrokeArc(rect, 45.0, 180.0); - SetHighColor(bg); - StrokeArc(rect, 45.0, -180.0); - - // for faster font rendering, we can restore B_OP_COPY - SetDrawingMode(B_OP_COPY); - - // label - SetHighColor(darkenmax); - DrawString(Label(), labelPos); - - // underline label if focused - if (IsFocus()) { - SetHighColor(naviColor); - BPoint underLine = labelPos; - underLine.y += fontHeight.descent; - StrokeLine(underLine, underLine + BPoint(StringWidth(Label()), 0.0)); - } + be_control_look->DrawLabel(this, Label(), labelRect, updateRect, + base, flags); } @@ -615,26 +494,9 @@ BRadioButton::_KnobFrame() const BRect BRadioButton::_KnobFrame(const font_height& fontHeight) const { - if (be_control_look != NULL) { - // Same as BCheckBox... - return BRect(0.0f, 2.0f, ceilf(3.0f + fontHeight.ascent), - ceilf(5.0f + fontHeight.ascent)); - } - - // layout the rect for the dot - BRect rect(Bounds()); - - // its size depends on the text height - float textHeight = ceilf(fontHeight.ascent + fontHeight.descent); - float inset = -floorf(textHeight / 2 - 2); - - rect.left -= (inset - 1); - rect.top = floorf((rect.top + rect.bottom) / 2.0); - rect.bottom = rect.top; - rect.right = rect.left; - rect.InsetBy(inset, inset); - - return rect; + // Same as BCheckBox... + return BRect(0.0f, 2.0f, ceilf(3.0f + fontHeight.ascent), + ceilf(5.0f + fontHeight.ascent)); } ############################################################################ Revision: hrev46584 Commit: 5e815cf35b7cfada9473824c0e1f651081e9d93f URL: http://cgit.haiku-os.org/haiku/commit/?id=5e815cf Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sun Dec 22 14:12:27 2013 UTC BRadioButton: Add icon support * Fix off-by-one issue in Draw() and GetPreferredSize(). The label was too close to the knob. * GetPreferredSize(): Remove empty space to the right, when no label and no icon was specified. Like with BCheckBox there's still two rows of empty pixels above and below the knob. * Draw(), GetPreferredSize(): Add icon support. ---------------------------------------------------------------------------- diff --git a/src/kits/interface/RadioButton.cpp b/src/kits/interface/RadioButton.cpp index a39d59b..40de205 100644 --- a/src/kits/interface/RadioButton.cpp +++ b/src/kits/interface/RadioButton.cpp @@ -15,6 +15,8 @@ #include <RadioButton.h> +#include <algorithm> + #include <ControlLook.h> #include <Debug.h> #include <Box.h> @@ -100,10 +102,13 @@ BRadioButton::Draw(BRect updateRect) be_control_look->DrawRadioButton(this, rect, updateRect, base, flags); BRect labelRect(Bounds()); - labelRect.left = knobRect.right + labelRect.left = knobRect.right + 1 + be_control_look->DefaultLabelSpacing(); - be_control_look->DrawLabel(this, Label(), labelRect, updateRect, + const BBitmap* icon = IconBitmap( + B_INACTIVE_ICON_BITMAP | (IsEnabled() ? 0 : B_DISABLED_ICON_BITMAP)); + + be_control_look->DrawLabel(this, Label(), icon, labelRect, updateRect, base, flags); } @@ -246,19 +251,29 @@ BRadioButton::GetPreferredSize(float* _width, float* _height) font_height fontHeight; GetFontHeight(&fontHeight); - if (_width) { - BRect rect = _KnobFrame(fontHeight); - float width = rect.right + floorf(ceilf(fontHeight.ascent - + fontHeight.descent) / 2.0); + BRect rect(_KnobFrame(fontHeight)); + float width = rect.right + rect.left; + float height = rect.bottom + rect.top; - if (Label()) - width += StringWidth(Label()); - - *_width = ceilf(width); + const BBitmap* icon = IconBitmap(B_INACTIVE_ICON_BITMAP); + if (icon != NULL) { + width += be_control_look->DefaultLabelSpacing() + + icon->Bounds().Width() + 1; + height = std::max(height, icon->Bounds().Height()); } - if (_height) - *_height = ceilf(fontHeight.ascent + fontHeight.descent) + 6.0; + if (const char* label = Label()) { + width += be_control_look->DefaultLabelSpacing() + + ceilf(StringWidth(label)); + height = std::max(height, + ceilf(6.0f + fontHeight.ascent + fontHeight.descent)); + } + + if (_width != NULL) + *_width = width; + + if (_height != NULL) + *_height = height; } @@ -467,7 +482,7 @@ BRadioButton::LayoutAlignment() status_t BRadioButton::SetIcon(const BBitmap* icon, uint32 flags) { - return BControl::SetIcon(icon, flags); + return BControl::SetIcon(icon, flags | B_CREATE_DISABLED_ICON_BITMAPS); }