BCheckBox: Add tri-state support

* Add possible control state B_CONTROL_PARTIALLY_ON and support it in
  BCheckBox and BControlLook.
* BCheckBox: Add partialStateToOff property defining whether the
  partial state should transition to off. Defaults to false (i.e.
  partial to on).
This commit is contained in:
Ingo Weinhold
2013-12-21 02:12:04 +01:00
parent 7bcfb21538
commit df37cd4edd
5 changed files with 88 additions and 22 deletions
+5
View File
@@ -69,6 +69,9 @@ public:
virtual status_t Perform(perform_code code, void* data); virtual status_t Perform(perform_code code, void* data);
bool IsPartialStateToOff() const;
void SetPartialStateToOff(bool partialToOff);
protected: protected:
virtual void LayoutInvalidated(bool descendants = false); virtual void LayoutInvalidated(bool descendants = false);
@@ -81,6 +84,7 @@ private:
private: private:
BRect _CheckBoxFrame() const; BRect _CheckBoxFrame() const;
BSize _ValidatePreferredSize(); BSize _ValidatePreferredSize();
int32 _NextState() const;
private: private:
// Forbidden // Forbidden
@@ -89,6 +93,7 @@ private:
private: private:
BSize fPreferredSize; BSize fPreferredSize;
bool fOutlined; bool fOutlined;
bool fPartialToOff;
}; };
#endif // _CHECK_BOX_H #endif // _CHECK_BOX_H
+2 -1
View File
@@ -12,7 +12,8 @@
enum { enum {
B_CONTROL_OFF = 0, B_CONTROL_OFF = 0,
B_CONTROL_ON = 1 B_CONTROL_ON = 1,
B_CONTROL_PARTIALLY_ON = 2
}; };
class BWindow; class BWindow;
+8 -7
View File
@@ -69,13 +69,14 @@ public:
}; };
enum { enum {
B_FOCUSED = 1 << 0, B_FOCUSED = 1 << 0,
B_CLICKED = 1 << 1, // some controls activate on mouse up B_CLICKED = 1 << 1, // some controls activate on mouse up
B_ACTIVATED = 1 << 2, B_ACTIVATED = 1 << 2,
B_HOVER = 1 << 3, B_HOVER = 1 << 3,
B_DISABLED = 1 << 4, B_DISABLED = 1 << 4,
B_DEFAULT_BUTTON = 1 << 5, B_DEFAULT_BUTTON = 1 << 5,
B_IGNORE_OUTLINE = 1 << 6, B_IGNORE_OUTLINE = 1 << 6,
B_PARTIALLY_ACTIVATED = 1 << 7, // like B_ACTIVATED, but for tri-state
B_BLEND_FRAME = 1 << 16 B_BLEND_FRAME = 1 << 16
}; };
+59 -9
View File
@@ -26,7 +26,8 @@ BCheckBox::BCheckBox(BRect frame, const char *name, const char *label,
: :
BControl(frame, name, label, message, resizingMode, flags), BControl(frame, name, label, message, resizingMode, flags),
fPreferredSize(), fPreferredSize(),
fOutlined(false) fOutlined(false),
fPartialToOff(false)
{ {
// Resize to minimum height if needed // Resize to minimum height if needed
font_height fontHeight; font_height fontHeight;
@@ -43,7 +44,8 @@ BCheckBox::BCheckBox(const char *name, const char *label, BMessage *message,
: :
BControl(name, label, message, flags | B_WILL_DRAW | B_NAVIGABLE), BControl(name, label, message, flags | B_WILL_DRAW | B_NAVIGABLE),
fPreferredSize(), fPreferredSize(),
fOutlined(false) fOutlined(false),
fPartialToOff(false)
{ {
} }
@@ -52,7 +54,8 @@ BCheckBox::BCheckBox(const char *label, BMessage *message)
: :
BControl(NULL, label, message, B_WILL_DRAW | B_NAVIGABLE), BControl(NULL, label, message, B_WILL_DRAW | B_NAVIGABLE),
fPreferredSize(), fPreferredSize(),
fOutlined(false) fOutlined(false),
fPartialToOff(false)
{ {
} }
@@ -60,7 +63,8 @@ BCheckBox::BCheckBox(const char *label, BMessage *message)
BCheckBox::BCheckBox(BMessage *archive) BCheckBox::BCheckBox(BMessage *archive)
: :
BControl(archive), BControl(archive),
fOutlined(false) fOutlined(false),
fPartialToOff(false)
{ {
} }
@@ -322,7 +326,16 @@ BCheckBox::MessageReceived(BMessage *message)
void void
BCheckBox::KeyDown(const char *bytes, int32 numBytes) BCheckBox::KeyDown(const char *bytes, int32 numBytes)
{ {
BControl::KeyDown(bytes, numBytes); if (*bytes == B_ENTER || *bytes == B_SPACE) {
if (!IsEnabled())
return;
SetValue(_NextState());
Invoke();
} else {
// skip the BControl implementation
BView::KeyDown(bytes, numBytes);
}
} }
@@ -360,7 +373,7 @@ BCheckBox::MouseDown(BPoint point)
if (fOutlined) { if (fOutlined) {
fOutlined = false; fOutlined = false;
SetValue(!Value()); SetValue(_NextState());
Invoke(); Invoke();
} else { } else {
Invalidate(); Invalidate();
@@ -385,7 +398,7 @@ BCheckBox::MouseUp(BPoint point)
if (fOutlined) { if (fOutlined) {
fOutlined = false; fOutlined = false;
SetValue(!Value()); SetValue(_NextState());
Invoke(); Invoke();
} else { } else {
Invalidate(); Invalidate();
@@ -485,8 +498,16 @@ BCheckBox::MakeFocus(bool focused)
void void
BCheckBox::SetValue(int32 value) BCheckBox::SetValue(int32 value)
{ {
value = value ? B_CONTROL_ON : B_CONTROL_OFF; // We only accept three possible values.
// we only accept boolean values switch (value) {
case B_CONTROL_OFF:
case B_CONTROL_ON:
case B_CONTROL_PARTIALLY_ON:
break;
default:
value = B_CONTROL_ON;
break;
}
if (value != Value()) { if (value != Value()) {
BControl::SetValueNoUpdate(value); BControl::SetValueNoUpdate(value);
@@ -582,6 +603,20 @@ BCheckBox::LayoutInvalidated(bool descendants)
} }
bool
BCheckBox::IsPartialStateToOff() const
{
return fPartialToOff;
}
void
BCheckBox::SetPartialStateToOff(bool partialToOff)
{
fPartialToOff = partialToOff;
}
// #pragma mark - FBC padding // #pragma mark - FBC padding
@@ -625,6 +660,21 @@ BCheckBox::_ValidatePreferredSize()
} }
int32
BCheckBox::_NextState() const
{
switch (Value()) {
case B_CONTROL_OFF:
return B_CONTROL_ON;
case B_CONTROL_PARTIALLY_ON:
return fPartialToOff ? B_CONTROL_OFF : B_CONTROL_ON;
case B_CONTROL_ON:
default:
return B_CONTROL_OFF;
}
}
BCheckBox & BCheckBox &
BCheckBox::operator=(const BCheckBox &) BCheckBox::operator=(const BCheckBox &)
{ {
+14 -5
View File
@@ -92,8 +92,14 @@ BControlLook::Flags(BControl* control) const
flags |= B_FOCUSED; flags |= B_FOCUSED;
} }
if (control->Value() == B_CONTROL_ON) switch (control->Value()) {
flags |= B_ACTIVATED; case B_CONTROL_ON:
flags |= B_ACTIVATED;
break;
case B_CONTROL_PARTIALLY_ON:
flags |= B_PARTIALLY_ACTIVATED;
break;
}
if (control->Parent() != NULL if (control->Parent() != NULL
&& (control->Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) { && (control->Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) {
@@ -3198,7 +3204,7 @@ bool
BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base, BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
rgb_color& color, uint32 flags) const rgb_color& color, uint32 flags) const
{ {
if ((flags & (B_ACTIVATED | B_CLICKED)) == 0) { if ((flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED | B_CLICKED)) == 0) {
// no mark to be drawn at all // no mark to be drawn at all
return false; return false;
} }
@@ -3212,12 +3218,15 @@ BControlLook::_RadioButtonAndCheckBoxMarkColor(const rgb_color& base,
mix = 0.4; mix = 0.4;
} else if ((flags & B_CLICKED) != 0) { } else if ((flags & B_CLICKED) != 0) {
if ((flags & B_ACTIVATED) != 0) { if ((flags & B_ACTIVATED) != 0) {
// loosing activation // losing activation
mix = 0.7; mix = 0.7;
} else { } else {
// becoming activated // becoming activated (or losing partial activation)
mix = 0.3; mix = 0.3;
} }
} else if ((flags & B_PARTIALLY_ACTIVATED) != 0) {
// partially activated
mix = 0.5;
} else { } else {
// simply activated // simply activated
} }