BButton: Add support for toggle button behavior

Add methods SetBehavior(), Behavior(). Supported behavior constants are
B_BUTTON_BEHAVIOR -- normal button behavior -- and B_TOGGLE_BEHAVIOR
-- toggle button behavior.
This commit is contained in:
Ingo Weinhold
2013-12-29 01:21:45 +01:00
parent b181fabe57
commit b998f9f02f
2 changed files with 81 additions and 20 deletions
+12 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2009, Haiku, Inc. All rights reserved.
* Copyright 2001-2013, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _BUTTON_H
@@ -9,6 +9,12 @@
class BButton : public BControl {
public:
enum BBehavior {
B_BUTTON_BEHAVIOR,
B_TOGGLE_BEHAVIOR,
};
public:
BButton(BRect frame, const char* name,
const char* label, BMessage* message,
@@ -42,6 +48,9 @@ public:
bool IsFlat() const;
void SetFlat(bool flat);
BBehavior Behavior() const;
void SetBehavior(BBehavior behavior);
virtual void MessageReceived(BMessage* message);
virtual void WindowActivated(bool active);
virtual void MouseMoved(BPoint point, uint32 transit,
@@ -96,8 +105,9 @@ private:
private:
BSize fPreferredSize;
uint32 fFlags;
BBehavior fBehavior;
uint32 _reserved[2];
uint32 _reserved[1];
};
#endif // _BUTTON_H
+69 -18
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2001-2008, Haiku Inc. All rights reserved.
* Copyright 2001-2013, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -8,6 +8,7 @@
* Stefano Ceccherini ([email protected])
* Ivan Tonizza
* Stephan Aßmus <[email protected]>
* Ingo Weinhold, [email protected]
*/
@@ -27,9 +28,10 @@
enum {
FLAG_DEFAULT = 0x01,
FLAG_FLAT = 0x02,
FLAG_INSIDE = 0x04,
FLAG_DEFAULT = 0x01,
FLAG_FLAT = 0x02,
FLAG_INSIDE = 0x04,
FLAG_WAS_PRESSED = 0x08,
};
@@ -41,7 +43,8 @@ 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),
fFlags(0)
fFlags(0),
fBehavior(B_BUTTON_BEHAVIOR)
{
// Resize to minimum height if needed
font_height fh;
@@ -57,7 +60,8 @@ 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),
fFlags(0)
fFlags(0),
fBehavior(B_BUTTON_BEHAVIOR)
{
}
@@ -66,7 +70,8 @@ BButton::BButton(const char* label, BMessage* message)
: BControl(NULL, label, message,
B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE),
fPreferredSize(-1, -1),
fFlags(0)
fFlags(0),
fBehavior(B_BUTTON_BEHAVIOR)
{
}
@@ -79,7 +84,8 @@ BButton::~BButton()
BButton::BButton(BMessage* archive)
: BControl(archive),
fPreferredSize(-1, -1),
fFlags(0)
fFlags(0),
fBehavior(B_BUTTON_BEHAVIOR)
{
bool isDefault = false;
if (archive->FindBool("_default", &isDefault) == B_OK && isDefault)
@@ -151,7 +157,15 @@ BButton::MouseDown(BPoint point)
if (!IsEnabled())
return;
SetValue(B_CONTROL_ON);
bool toggleBehavior = fBehavior == B_TOGGLE_BEHAVIOR;
if (toggleBehavior) {
bool wasPressed = Value() == B_CONTROL_ON;
_SetFlag(FLAG_WAS_PRESSED, wasPressed);
SetValue(wasPressed ? B_CONTROL_OFF : B_CONTROL_ON);
Invalidate();
} else
SetValue(B_CONTROL_ON);
if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
SetTracking(true);
@@ -159,6 +173,7 @@ BButton::MouseDown(BPoint point)
} else {
BRect bounds = Bounds();
uint32 buttons;
bool inside = false;
do {
Window()->UpdateIfNeeded();
@@ -166,14 +181,26 @@ BButton::MouseDown(BPoint point)
GetMouse(&point, &buttons, true);
bool inside = bounds.Contains(point);
inside = bounds.Contains(point);
if ((Value() == B_CONTROL_ON) != inside)
SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF);
if (toggleBehavior) {
bool pressed = inside ^ _Flag(FLAG_WAS_PRESSED);
SetValue(pressed ? B_CONTROL_ON : B_CONTROL_OFF);
} else {
if ((Value() == B_CONTROL_ON) != inside)
SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF);
}
} while (buttons != 0);
if (Value() == B_CONTROL_ON)
if (inside) {
if (toggleBehavior) {
SetValue(
_Flag(FLAG_WAS_PRESSED) ? B_CONTROL_OFF : B_CONTROL_ON);
}
Invoke();
} else if (_Flag(FLAG_FLAT))
Invalidate();
}
}
@@ -281,6 +308,21 @@ BButton::SetFlat(bool flat)
}
BButton::BBehavior
BButton::Behavior() const
{
return fBehavior;
}
void
BButton::SetBehavior(BBehavior behavior)
{
if (behavior != fBehavior)
fBehavior = behavior;
}
void
BButton::MessageReceived(BMessage *message)
{
@@ -305,8 +347,13 @@ BButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
if (!IsTracking())
return;
if ((Value() == B_CONTROL_ON) != inside)
SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF);
if (fBehavior == B_TOGGLE_BEHAVIOR) {
bool pressed = inside ^ _Flag(FLAG_WAS_PRESSED);
SetValue(pressed ? B_CONTROL_ON : B_CONTROL_OFF);
} else {
if ((Value() == B_CONTROL_ON) != inside)
SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF);
}
}
@@ -316,9 +363,12 @@ BButton::MouseUp(BPoint point)
if (!IsTracking())
return;
if (Bounds().Contains(point))
if (Bounds().Contains(point)) {
if (fBehavior == B_TOGGLE_BEHAVIOR)
SetValue(_Flag(FLAG_WAS_PRESSED) ? B_CONTROL_OFF : B_CONTROL_ON);
Invoke();
else if (_Flag(FLAG_FLAT))
} else if (_Flag(FLAG_FLAT))
Invalidate();
SetTracking(false);
@@ -368,7 +418,8 @@ BButton::Invoke(BMessage *message)
status_t err = BControl::Invoke(message);
SetValue(B_CONTROL_OFF);
if (fBehavior != B_TOGGLE_BEHAVIOR)
SetValue(B_CONTROL_OFF);
return err;
}