diff --git a/headers/os/interface/Button.h b/headers/os/interface/Button.h index 304bd64e9e..c98993dfc0 100644 --- a/headers/os/interface/Button.h +++ b/headers/os/interface/Button.h @@ -39,6 +39,9 @@ public: virtual void SetLabel(const char* string); bool IsDefault() const; + bool IsFlat() const; + void SetFlat(bool flat); + virtual void MessageReceived(BMessage* message); virtual void WindowActivated(bool active); virtual void MouseMoved(BPoint point, uint32 transit, @@ -79,7 +82,6 @@ private: virtual void _ReservedButton2(); virtual void _ReservedButton3(); -private: BButton& operator=(const BButton &); BSize _ValidatePreferredSize(); @@ -87,9 +89,15 @@ private: BRect _DrawDefault(BRect bounds, bool enabled); void _DrawFocusLine(float x, float y, float width, bool bVisible); + + inline bool _Flag(uint32 flag) const; + inline bool _SetFlag(uint32 flag, bool set); +private: BSize fPreferredSize; + uint32 fFlags; bool fDrawAsDefault; + bool fFlat; uint32 _reserved[2]; }; diff --git a/headers/os/interface/ControlLook.h b/headers/os/interface/ControlLook.h index 8222ae2f80..43fc15bfa6 100644 --- a/headers/os/interface/ControlLook.h +++ b/headers/os/interface/ControlLook.h @@ -82,6 +82,7 @@ public: B_DEFAULT_BUTTON = 1 << 5, B_IGNORE_OUTLINE = 1 << 6, B_PARTIALLY_ACTIVATED = 1 << 7, // like B_ACTIVATED, but for tri-state + B_FLAT = 1 << 8, // flat look (e.g. button background) B_BLEND_FRAME = 1 << 16 }; diff --git a/src/kits/interface/Button.cpp b/src/kits/interface/Button.cpp index 5587106249..b99ae6c3c4 100644 --- a/src/kits/interface/Button.cpp +++ b/src/kits/interface/Button.cpp @@ -26,6 +26,13 @@ #include +enum { + FLAG_DEFAULT = 0x01, + FLAG_FLAT = 0x02, + FLAG_INSIDE = 0x04, +}; + + static const float kLabelMargin = 3; @@ -34,7 +41,7 @@ BButton::BButton(BRect frame, const char* name, const char* label, : BControl(frame, name, label, message, resizingMode, flags | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), fPreferredSize(-1, -1), - fDrawAsDefault(false) + fFlags(0) { // Resize to minimum height if needed font_height fh; @@ -50,7 +57,7 @@ BButton::BButton(const char* name, const char* label, BMessage* message, : BControl(name, label, message, flags | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), fPreferredSize(-1, -1), - fDrawAsDefault(false) + fFlags(0) { } @@ -59,7 +66,7 @@ BButton::BButton(const char* label, BMessage* message) : BControl(NULL, label, message, B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE), fPreferredSize(-1, -1), - fDrawAsDefault(false) + fFlags(0) { } @@ -71,10 +78,12 @@ BButton::~BButton() BButton::BButton(BMessage* archive) : BControl(archive), - fPreferredSize(-1, -1) + fPreferredSize(-1, -1), + fFlags(0) { - if (archive->FindBool("_default", &fDrawAsDefault) != B_OK) - fDrawAsDefault = false; + bool isDefault = false; + if (archive->FindBool("_default", &isDefault) == B_OK && isDefault) + _SetFlag(FLAG_DEFAULT, true); // NOTE: Default button state will be synchronized with the window // in AttachedToWindow(). } @@ -112,8 +121,13 @@ BButton::Draw(BRect updateRect) rgb_color background = LowColor(); rgb_color base = background; uint32 flags = be_control_look->Flags(this); - if (IsDefault()) + if (_Flag(FLAG_DEFAULT)) flags |= BControlLook::B_DEFAULT_BUTTON; + if (_Flag(FLAG_FLAT) && !IsTracking()) + flags |= BControlLook::B_FLAT; + if (_Flag(FLAG_INSIDE)) + flags |= BControlLook::B_HOVER; + be_control_look->DrawButtonFrame(this, rect, updateRect, base, background, flags); be_control_look->DrawButtonBackground(this, rect, updateRect, @@ -207,12 +221,10 @@ BButton::MakeDefault(bool flag) oldDefault = window->DefaultButton(); if (flag) { - if (fDrawAsDefault && oldDefault == this) + if (_Flag(FLAG_DEFAULT) && oldDefault == this) return; - if (!fDrawAsDefault) { - fDrawAsDefault = true; - + if (_SetFlag(FLAG_DEFAULT, true)) { if ((Flags() & B_SUPPORTS_LAYOUT) != 0) InvalidateLayout(); else { @@ -224,11 +236,9 @@ BButton::MakeDefault(bool flag) if (window && oldDefault != this) window->SetDefaultButton(this); } else { - if (!fDrawAsDefault) + if (!_SetFlag(FLAG_DEFAULT, false)) return; - fDrawAsDefault = false; - if ((Flags() & B_SUPPORTS_LAYOUT) != 0) InvalidateLayout(); else { @@ -252,7 +262,22 @@ BButton::SetLabel(const char *string) bool BButton::IsDefault() const { - return fDrawAsDefault; + return _Flag(FLAG_DEFAULT); +} + + +bool +BButton::IsFlat() const +{ + return _Flag(FLAG_FLAT); +} + + +void +BButton::SetFlat(bool flat) +{ + if (_SetFlag(FLAG_FLAT, flat)) + Invalidate(); } @@ -273,11 +298,13 @@ BButton::WindowActivated(bool active) void BButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message) { + bool inside = Bounds().Contains(point); + if (_SetFlag(FLAG_INSIDE, inside)) + Invalidate(); + if (!IsTracking()) return; - bool inside = Bounds().Contains(point); - if ((Value() == B_CONTROL_ON) != inside) SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF); } @@ -291,6 +318,8 @@ BButton::MouseUp(BPoint point) if (Bounds().Contains(point)) Invoke(); + else if (_Flag(FLAG_FLAT)) + Invalidate(); SetTracking(false); } @@ -516,7 +545,7 @@ BButton::_ValidatePreferredSize() float left, top, right, bottom; be_control_look->GetInsets(BControlLook::B_BUTTON_FRAME, BControlLook::B_BUTTON_BACKGROUND, - fDrawAsDefault ? BControlLook::B_DEFAULT_BUTTON : 0, + IsDefault() ? BControlLook::B_DEFAULT_BUTTON : 0, left, top, right, bottom); // width @@ -608,6 +637,28 @@ BButton::_DrawFocusLine(float x, float y, float width, bool visible) } +inline bool +BButton::_Flag(uint32 flag) const +{ + return (fFlags & flag) != 0; +} + + +inline bool +BButton::_SetFlag(uint32 flag, bool set) +{ + if (((fFlags & flag) != 0) == set) + return false; + + if (set) + fFlags |= flag; + else + fFlags &= ~flag; + + return true; +} + + extern "C" void B_IF_GCC_2(InvalidateLayout__7BButtonb, _ZN7BButton16InvalidateLayoutEb)( BView* view, bool descendants) diff --git a/src/kits/interface/ControlLook.cpp b/src/kits/interface/ControlLook.cpp index 7032239dc3..fc1c7dc7d9 100644 --- a/src/kits/interface/ControlLook.cpp +++ b/src/kits/interface/ControlLook.cpp @@ -2046,6 +2046,20 @@ BControlLook::_DrawButtonFrame(BView* view, BRect& rect, BRegion clipping(updateRect); view->ConstrainClippingRegion(&clipping); + // If the button is flat and neither activated nor otherwise highlighted + // (mouse hovering or focussed), draw it flat. + if ((flags & B_FLAT) != 0 + && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 + && ((flags & (B_HOVER | B_FOCUSED)) == 0 + || (flags & B_DISABLED) != 0)) { + _DrawFrame(view, rect, background, background, background, + background, borders); + _DrawFrame(view, rect, background, background, background, + background, borders); + view->PopState(); + return; + } + // outer edge colors rgb_color edgeLightColor; rgb_color edgeShadowColor; @@ -2317,6 +2331,19 @@ BControlLook::_DrawButtonBackground(BView* view, BRect& rect, BRegion clipping(updateRect); view->ConstrainClippingRegion(&clipping); + // If the button is flat and neither activated nor otherwise highlighted + // (mouse hovering or focussed), draw it flat. + if ((flags & B_FLAT) != 0 + && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 + && ((flags & (B_HOVER | B_FOCUSED)) == 0 + || (flags & B_DISABLED) != 0)) { + _DrawFrame(view, rect, base, base, base, base, borders); + view->SetHighColor(base); + view->FillRect(rect); + view->PopState(); + return; + } + // inner bevel colors rgb_color bevelLightColor = _BevelLightColor(base, flags); rgb_color bevelShadowColor = _BevelShadowColor(base, flags);