diff --git a/headers/os/interface/RadioButton.h b/headers/os/interface/RadioButton.h index 0a03a62c12..13cd145e83 100644 --- a/headers/os/interface/RadioButton.h +++ b/headers/os/interface/RadioButton.h @@ -100,6 +100,8 @@ virtual void _ReservedRadioButton2(); BRadioButton &operator=(const BRadioButton &); BRect _KnobFrame() const; + // for use in "synchronous" BWindows + void _Redraw(); static BBitmap *sBitmaps[2][3]; diff --git a/src/kits/interface/RadioButton.cpp b/src/kits/interface/RadioButton.cpp index bed19034de..c1af06ac3a 100644 --- a/src/kits/interface/RadioButton.cpp +++ b/src/kits/interface/RadioButton.cpp @@ -1,33 +1,24 @@ -//------------------------------------------------------------------------------ -// Copyright (c) 2001-2005, Haiku, Inc. -// -// Distributed under the terms of the MIT license. -// -// File Name: RadioButton.cpp -// Authors: Marc Flerackers (mflerackers@androme.be) -// Stephan Aßmus -// Description: BRadioButton represents a single on/off button. All -// sibling BRadioButton objects comprise a single -// "multiple choice" control. -//------------------------------------------------------------------------------ +/* + * Copyright 2001-2005, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Authors: + * Marc Flerackers (mflerackers@androme.be) + * Stephan Aßmus + * + * Description: + * BRadioButton represents a single on/off button. + * All sibling BRadioButton objects comprise a single + * "multiple choice" control. + */ -// Standard Includes ----------------------------------------------------------- - -// System Includes ------------------------------------------------------------- -#include -#include #include +#include #include -// Project Includes ------------------------------------------------------------ +#include -// Local Includes -------------------------------------------------------------- -// Local Defines --------------------------------------------------------------- - -// Globals --------------------------------------------------------------------- - -//------------------------------------------------------------------------------ BRadioButton::BRadioButton(BRect frame, const char *name, const char *label, BMessage *message, uint32 resizMask, uint32 flags) : BControl(frame, name, label, message, resizMask, flags), @@ -40,48 +31,52 @@ BRadioButton::BRadioButton(BRect frame, const char *name, const char *label, if (Bounds().Height() < minHeight) ResizeTo(Bounds().Width(), minHeight); } -//------------------------------------------------------------------------------ + + BRadioButton::BRadioButton(BMessage *archive) : BControl(archive), fOutlined(false) { } -//------------------------------------------------------------------------------ + + BRadioButton::~BRadioButton() { } -//------------------------------------------------------------------------------ -BArchivable *BRadioButton::Instantiate(BMessage *archive) + + +BArchivable* +BRadioButton::Instantiate(BMessage *archive) { if (validate_instantiation(archive, "BRadioButton")) return new BRadioButton(archive); else return NULL; } -//------------------------------------------------------------------------------ -status_t BRadioButton::Archive(BMessage *archive, bool deep) const + + +status_t +BRadioButton::Archive(BMessage *archive, bool deep) const { return BControl::Archive(archive, deep); } -//------------------------------------------------------------------------------ -void BRadioButton::Draw(BRect updateRect) + + +void +BRadioButton::Draw(BRect updateRect) { - // NOTE: the commented out StrokeLine() calls appearently tweak the - // rendering on R5, but they are unnecessary under Haiku - - font_height fh; - GetFontHeight(&fh); - // layout the rect for the dot BRect rect = _KnobFrame(); // its size depends on the text height + font_height fh; + GetFontHeight(&fh); float textHeight = floorf(fh.ascent + fh.descent + 0.5); BPoint labelPos(rect.right + floorf(textHeight / 2.0), floorf((rect.top + rect.bottom + textHeight) / 2.0 - fh.descent + 0.5) + 1.0); - // If the focus is changing, just redraw the focus indicator + // if the focus is changing, just redraw the focus indicator if (IsFocusChanging()) { if (IsFocus()) SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); @@ -95,133 +90,106 @@ void BRadioButton::Draw(BRect updateRect) return; } - // Placeholder until sBitmaps is filled in - rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR), - lighten1 = tint_color(no_tint, B_LIGHTEN_1_TINT), - lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT), - darken1 = tint_color(no_tint, B_DARKEN_1_TINT), - darken2 = tint_color(no_tint, B_DARKEN_2_TINT), - darken3 = tint_color(no_tint, B_DARKEN_3_TINT), - //darken4 = tint_color(no_tint, B_DARKEN_4_TINT), - darkenmax = tint_color(no_tint, B_DARKEN_MAX_TINT); + // 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); + } // NOTE: this improves drawing a lot because of // anti-aliased circles and arcs in Haiku SetDrawingMode(B_OP_OVER); - if (IsEnabled()) { - // Dot - if (Value() == B_CONTROL_ON) { - rgb_color kb_color = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + // dot + if (Value() == B_CONTROL_ON) { + // full + SetHighColor(knobDark); + FillEllipse(rect); - SetHighColor(tint_color(kb_color, B_DARKEN_3_TINT)); - FillEllipse(rect); - SetHighColor(kb_color); - FillEllipse(BRect(rect.left + 3, rect.top + 3, rect.right - 4, rect.bottom - 4)); - SetHighColor(tint_color(kb_color, B_DARKEN_3_TINT)); - StrokeLine(BPoint(rect.right - 5, rect.bottom - 4), - BPoint(rect.right - 4, rect.bottom - 5)); - SetHighColor(tint_color(kb_color, B_LIGHTEN_MAX_TINT)); - StrokeLine(BPoint(rect.left + 4, rect.top + 5), - BPoint(rect.left + 5, rect.top + 4)); + SetHighColor(knob); + FillEllipse(BRect(rect.left + 2, rect.top + 2, rect.right - 2, rect.bottom - 2)); - } else { - SetHighColor(lightenmax); - FillEllipse(rect); - } - - rect.InsetBy(-1.0, -1.0); - - // Outer circle - if (fOutlined) { - SetHighColor(darken3); - StrokeEllipse(rect); - } else { - SetHighColor(darken1); - StrokeArc(rect, 45.0f, 180.0f); - SetHighColor(lightenmax); - StrokeArc(rect, 45.0f, -180.0f); - } - - rect.InsetBy(1, 1); - - // Inner circle - SetHighColor(darken3); - StrokeArc(rect, 45.0f, 180.0f); -// StrokeLine(BPoint(rect.left + 1, rect.top + 1), -// BPoint(rect.left + 1, rect.top + 1)); - SetHighColor(no_tint); - StrokeArc(rect, 45.0f, -180.0f); -// StrokeLine(BPoint(rect.left + 1, rect.bottom - 1), -// BPoint(rect.left + 1, rect.bottom - 1)); -// StrokeLine(BPoint(rect.right - 1, rect.bottom - 1), -// BPoint(rect.right - 1, rect.bottom - 1)); -// StrokeLine(BPoint(rect.right - 1, rect.top + 1), -// BPoint(rect.right - 1, rect.top + 1)); - - // For faster font rendering, we can restore B_OP_COPY - SetDrawingMode(B_OP_COPY); - - // Label - SetHighColor(darkenmax); - DrawString(Label(), labelPos); - - // Focus - if (IsFocus()) { - SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); - BPoint underLine = labelPos; - underLine.y += fh.descent; - StrokeLine(underLine, underLine + BPoint(StringWidth(Label()), 0.0)); - } + SetHighColor(knobLight); + FillEllipse(BRect(rect.left + 3, rect.top + 3, rect.right - 4, rect.bottom - 4)); } else { - // Dot - if (Value() == B_CONTROL_ON) { - rgb_color kb_color = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + // empty + SetHighColor(lightenmax); + FillEllipse(rect); + } - SetHighColor(tint_color(kb_color, B_LIGHTEN_2_TINT)); - FillEllipse(rect); - SetHighColor(tint_color(kb_color, B_LIGHTEN_MAX_TINT)); - StrokeLine(BPoint(rect.left + 4, rect.top + 5), - BPoint(rect.left + 5, rect.top + 4)); - SetHighColor(tint_color(kb_color, B_DARKEN_3_TINT)); - StrokeArc(BRect(rect.left + 2, rect.top + 2, rect.right - 2, rect.bottom - 2), - 45.0f, -180.0f); - } else { - SetHighColor(lighten1); - FillEllipse(rect); - } + rect.InsetBy(-1.0, -1.0); - rect.InsetBy(-1.0, -1.0); - - // Outer circle - SetHighColor(no_tint); + // outer circle + if (fOutlined) { + // indicating "about to change value" + SetHighColor(darken3); + StrokeEllipse(rect); + } else { + SetHighColor(darken1); StrokeArc(rect, 45.0f, 180.0f); - SetHighColor(lighten1); + SetHighColor(lightenmax); StrokeArc(rect, 45.0f, -180.0f); + } - rect.InsetBy(1, 1); - - // Inner circle - SetHighColor(darken2); - StrokeArc(rect, 45.0f, 180.0f); -// StrokeLine(BPoint(rect.left + 1, rect.top + 1), -// BPoint(rect.left + 1, rect.top + 1)); - SetHighColor(no_tint); - StrokeArc(rect, 45.0f, -180.0f); -// StrokeLine(BPoint(rect.left + 1, rect.bottom - 1), -// BPoint(rect.left + 1, rect.bottom - 1)); -// StrokeLine(BPoint(rect.right - 1, rect.bottom - 1), -// BPoint(rect.right - 1, rect.bottom - 1)); -// StrokeLine(BPoint(rect.right - 1, rect.top + 1), -// BPoint(rect.right - 1, rect.top + 1)); + rect.InsetBy(1, 1); - // Label - SetHighColor(tint_color(no_tint, B_DISABLED_LABEL_TINT)); - DrawString(Label(), labelPos); + // inner circle + SetHighColor(darken3); + StrokeArc(rect, 45.0f, 180.0f); + SetHighColor(bg); + StrokeArc(rect, 45.0f, -180.0f); + + // 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 += fh.descent; + StrokeLine(underLine, underLine + BPoint(StringWidth(Label()), 0.0)); } } -//------------------------------------------------------------------------------ -void BRadioButton::MouseDown(BPoint point) + + +void +BRadioButton::MouseDown(BPoint point) { if (!IsEnabled()) return; @@ -233,8 +201,7 @@ void BRadioButton::MouseDown(BPoint point) SetTracking(true); SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); } else { - Draw(Bounds()); - Flush(); + _Redraw(); BRect bounds = Bounds(); uint32 buttons; @@ -248,40 +215,40 @@ void BRadioButton::MouseDown(BPoint point) if (fOutlined != inside) { fOutlined = inside; - Draw(Bounds()); - Flush(); + _Redraw(); } } while (buttons != 0); if (fOutlined) { fOutlined = false; - Draw(Bounds()); - Flush(); + _Redraw(); SetValue(B_CONTROL_ON); Invoke(); } else { - Draw(Bounds()); - Flush(); + _Redraw(); } } - } -//------------------------------------------------------------------------------ -void BRadioButton::AttachedToWindow() + + +void +BRadioButton::AttachedToWindow() { BControl::AttachedToWindow(); } -//------------------------------------------------------------------------------ -void BRadioButton::KeyDown(const char *bytes, int32 numBytes) + + +void +BRadioButton::KeyDown(const char *bytes, int32 numBytes) { // TODO add select_next_button functionality - switch (bytes[0]) - { - case ' ': - { - if (IsEnabled() && !Value()) - { + switch (bytes[0]) { + case B_RETURN: + // override B_RETURN, which BControl would use to toggle the value + // but we don't allow setting the control to "off", only "on" + case B_SPACE: { + if (IsEnabled() && !Value()) { SetValue(B_CONTROL_ON); Invoke(); } @@ -292,8 +259,10 @@ void BRadioButton::KeyDown(const char *bytes, int32 numBytes) BControl::KeyDown(bytes, numBytes); } } -//------------------------------------------------------------------------------ -void BRadioButton::SetValue(int32 value) + + +void +BRadioButton::SetValue(int32 value) { if (value != Value()) { BControl::SetValue(value); @@ -306,16 +275,14 @@ void BRadioButton::SetValue(int32 value) BView *parent = Parent(); BView *child = NULL; - if (parent) - { + if (parent) { // If the parent is a BBox, the group parent is the parent of the BBox BBox *box = dynamic_cast(parent); if (box && box->LabelView() == this) parent = box->Parent(); - if (parent) - { + if (parent) { BBox *box = dynamic_cast(parent); // If the parent is a BBox, skip the label if there is one @@ -323,26 +290,21 @@ void BRadioButton::SetValue(int32 value) child = parent->ChildAt(1); else child = parent->ChildAt(0); - } - else + } else child = Window()->ChildAt(0); - } - else if (Window()) + } else if (Window()) child = Window()->ChildAt(0); - while (child) - { + while (child) { BRadioButton *radio = dynamic_cast(child); if (child != this && radio) radio->SetValue(B_CONTROL_OFF); - else - { + else { // If the child is a BBox, check if the label is a radiobutton BBox *box = dynamic_cast(child); - if (box && box->LabelView()) - { + if (box && box->LabelView()) { radio = dynamic_cast(box->LabelView()); if (radio) @@ -353,8 +315,10 @@ void BRadioButton::SetValue(int32 value) child = child->NextSibling(); } } -//------------------------------------------------------------------------------ -void BRadioButton::GetPreferredSize(float *width, float *height) + + +void +BRadioButton::GetPreferredSize(float *width, float *height) { font_height fh; GetFontHeight(&fh); @@ -367,28 +331,38 @@ void BRadioButton::GetPreferredSize(float *width, float *height) *width = (float)ceil(*width); } -//------------------------------------------------------------------------------ -void BRadioButton::ResizeToPreferred() + + +void +BRadioButton::ResizeToPreferred() { BControl::ResizeToPreferred(); } -//------------------------------------------------------------------------------ -status_t BRadioButton::Invoke(BMessage *message) + + +status_t +BRadioButton::Invoke(BMessage *message) { return BControl::Invoke(message); } -//------------------------------------------------------------------------------ -void BRadioButton::MessageReceived(BMessage *message) + + +void +BRadioButton::MessageReceived(BMessage *message) { BControl::MessageReceived(message); } -//------------------------------------------------------------------------------ -void BRadioButton::WindowActivated(bool active) + + +void +BRadioButton::WindowActivated(bool active) { BControl::WindowActivated(active); } -//------------------------------------------------------------------------------ -void BRadioButton::MouseUp(BPoint point) + + +void +BRadioButton::MouseUp(BPoint point) { if (!IsTracking()) return; @@ -403,8 +377,10 @@ void BRadioButton::MouseUp(BPoint point) SetTracking(false); } -//------------------------------------------------------------------------------ -void BRadioButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message) + + +void +BRadioButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message) { if (!IsTracking()) return; @@ -416,63 +392,85 @@ void BRadioButton::MouseMoved(BPoint point, uint32 transit, const BMessage *mess Invalidate(); } } -//------------------------------------------------------------------------------ -void BRadioButton::DetachedFromWindow() + + +void +BRadioButton::DetachedFromWindow() { BControl::DetachedFromWindow(); } -//------------------------------------------------------------------------------ -void BRadioButton::FrameMoved(BPoint newLocation) + + +void +BRadioButton::FrameMoved(BPoint newLocation) { BControl::FrameMoved(newLocation); } -//------------------------------------------------------------------------------ -void BRadioButton::FrameResized(float width, float height) + + +void +BRadioButton::FrameResized(float width, float height) { BControl::FrameResized(width, height); } -//------------------------------------------------------------------------------ -BHandler *BRadioButton::ResolveSpecifier(BMessage *message, int32 index, - BMessage *specifier, int32 what, - const char *property) + + +BHandler* +BRadioButton::ResolveSpecifier(BMessage *message, int32 index, + BMessage *specifier, int32 what, + const char *property) { return BControl::ResolveSpecifier(message, index, specifier, what, property); } -//------------------------------------------------------------------------------ -void BRadioButton::MakeFocus(bool focused) + + +void +BRadioButton::MakeFocus(bool focused) { BControl::MakeFocus(focused); } -//------------------------------------------------------------------------------ -void BRadioButton::AllAttached() + + +void +BRadioButton::AllAttached() { BControl::AllAttached(); } -//------------------------------------------------------------------------------ -void BRadioButton::AllDetached() + + +void +BRadioButton::AllDetached() { BControl::AllDetached(); } -//------------------------------------------------------------------------------ -status_t BRadioButton::GetSupportedSuites(BMessage *message) + + +status_t +BRadioButton::GetSupportedSuites(BMessage *message) { return BControl::GetSupportedSuites(message); } -//------------------------------------------------------------------------------ -status_t BRadioButton::Perform(perform_code d, void *arg) + + +status_t +BRadioButton::Perform(perform_code d, void *arg) { return BControl::Perform(d, arg); } -//------------------------------------------------------------------------------ + + void BRadioButton::_ReservedRadioButton1() {} void BRadioButton::_ReservedRadioButton2() {} -//------------------------------------------------------------------------------ -BRadioButton &BRadioButton::operator=(const BRadioButton &) + + +BRadioButton& +BRadioButton::operator=(const BRadioButton &) { return *this; } -//------------------------------------------------------------------------------ + + BRect BRadioButton::_KnobFrame() const { @@ -496,9 +494,16 @@ BRadioButton::_KnobFrame() const } -/* - * $Log $ - * - * $Id $ - * - */ +void +BRadioButton::_Redraw() +{ + BRect b(Bounds()); + // fill background with ViewColor() + rgb_color highColor = HighColor(); + SetHighColor(ViewColor()); + FillRect(b); + // restore previous HighColor() + SetHighColor(highColor); + Draw(b); + Flush(); +}