* Pulled generic button code out of CheckBox into a new base class
AbstractButton. * Added RadioButton and RadioButtonGroup. * In the BBox test the border style can be switched now. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21343 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2007, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "AbstractButton.h"
|
||||
|
||||
#include <View.h>
|
||||
|
||||
|
||||
// #pragma mark - AbstractButton
|
||||
|
||||
|
||||
AbstractButton::AbstractButton(button_policy policy, BMessage* message,
|
||||
BMessenger target)
|
||||
: View(BRect(0, 0, 0, 0)),
|
||||
BInvoker(message, target),
|
||||
fPolicy(policy),
|
||||
fSelected(false),
|
||||
fPressed(false),
|
||||
fPressedInBounds(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::SetPolicy(button_policy policy)
|
||||
{
|
||||
fPolicy = policy;
|
||||
}
|
||||
|
||||
|
||||
button_policy
|
||||
AbstractButton::Policy() const
|
||||
{
|
||||
return fPolicy;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::SetSelected(bool selected)
|
||||
{
|
||||
if (selected != fSelected) {
|
||||
fSelected = selected;
|
||||
Invalidate();
|
||||
|
||||
// check whether to notify the listeners depending on the button policy
|
||||
bool notify = false;
|
||||
switch (fPolicy) {
|
||||
case BUTTON_POLICY_TOGGLE_ON_RELEASE:
|
||||
case BUTTON_POLICY_SELECT_ON_RELEASE:
|
||||
// always notify on selection changes
|
||||
notify = true;
|
||||
break;
|
||||
case BUTTON_POLICY_INVOKE_ON_RELEASE:
|
||||
// only notify when the user interaction has been finished
|
||||
notify = !fPressed;
|
||||
break;
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
// notify synchronous listeners
|
||||
_NotifyListeners();
|
||||
|
||||
// send the message
|
||||
if (Message()) {
|
||||
BMessage message(*Message());
|
||||
message.AddBool("selected", IsSelected());
|
||||
InvokeNotify(&message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AbstractButton::IsSelected() const
|
||||
{
|
||||
return fSelected;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::MouseDown(BPoint where, uint32 buttons, int32 modifiers)
|
||||
{
|
||||
if (fPressed)
|
||||
return;
|
||||
|
||||
fPressed = true;
|
||||
_PressedUpdate(where);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::MouseUp(BPoint where, uint32 buttons, int32 modifiers)
|
||||
{
|
||||
if (!fPressed || (buttons & B_PRIMARY_MOUSE_BUTTON))
|
||||
return;
|
||||
|
||||
_PressedUpdate(where);
|
||||
fPressed = false;
|
||||
if (fPressedInBounds) {
|
||||
fPressedInBounds = false;
|
||||
|
||||
// update selected state according to policy
|
||||
bool selected = fSelected;
|
||||
switch (fPolicy) {
|
||||
case BUTTON_POLICY_TOGGLE_ON_RELEASE:
|
||||
selected = !fSelected;
|
||||
break;
|
||||
case BUTTON_POLICY_SELECT_ON_RELEASE:
|
||||
selected = true;
|
||||
break;
|
||||
case BUTTON_POLICY_INVOKE_ON_RELEASE:
|
||||
selected = false;
|
||||
break;
|
||||
}
|
||||
|
||||
SetSelected(selected);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::MouseMoved(BPoint where, uint32 buttons, int32 modifiers)
|
||||
{
|
||||
if (!fPressed)
|
||||
return;
|
||||
|
||||
_PressedUpdate(where);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::AddListener(Listener* listener)
|
||||
{
|
||||
if (listener && !fListeners.HasItem(listener))
|
||||
fListeners.AddItem(listener);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::RemoveListener(Listener* listener)
|
||||
{
|
||||
if (listener)
|
||||
fListeners.RemoveItem(listener);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AbstractButton::IsPressed() const
|
||||
{
|
||||
return (fPressed && fPressedInBounds);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::_PressedUpdate(BPoint where)
|
||||
{
|
||||
bool pressedInBounds = Bounds().Contains(where);
|
||||
if (pressedInBounds == fPressedInBounds)
|
||||
return;
|
||||
|
||||
fPressedInBounds = pressedInBounds;
|
||||
|
||||
// update the selected state according to the button policy
|
||||
switch (fPolicy) {
|
||||
case BUTTON_POLICY_TOGGLE_ON_RELEASE:
|
||||
case BUTTON_POLICY_SELECT_ON_RELEASE:
|
||||
// nothing to do
|
||||
break;
|
||||
case BUTTON_POLICY_INVOKE_ON_RELEASE:
|
||||
SetSelected(fPressedInBounds);
|
||||
break;
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AbstractButton::_NotifyListeners()
|
||||
{
|
||||
if (!fListeners.IsEmpty()) {
|
||||
BList listeners(fListeners);
|
||||
for (int32 i = 0; Listener* listener = (Listener*)listeners.ItemAt(i);
|
||||
i++) {
|
||||
listener->SelectionChanged(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - AbstractButton::Listener
|
||||
|
||||
|
||||
AbstractButton::Listener::~Listener()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2007, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef WIDGET_LAYOUT_TEST_ABSTRACT_BUTTON_H
|
||||
#define WIDGET_LAYOUT_TEST_ABSTRACT_BUTTON_H
|
||||
|
||||
|
||||
#include <Invoker.h>
|
||||
#include <List.h>
|
||||
|
||||
#include "View.h"
|
||||
|
||||
|
||||
// button behavior policy
|
||||
enum button_policy {
|
||||
BUTTON_POLICY_TOGGLE_ON_RELEASE, // check box
|
||||
BUTTON_POLICY_SELECT_ON_RELEASE, // radio button
|
||||
BUTTON_POLICY_INVOKE_ON_RELEASE // button
|
||||
};
|
||||
|
||||
|
||||
// AbstractButton
|
||||
class AbstractButton : public View, public BInvoker {
|
||||
public:
|
||||
AbstractButton(button_policy policy,
|
||||
BMessage* message = NULL,
|
||||
BMessenger target = BMessenger());
|
||||
|
||||
void SetPolicy(button_policy policy);
|
||||
button_policy Policy() const;
|
||||
|
||||
void SetSelected(bool selected);
|
||||
bool IsSelected() const;
|
||||
|
||||
virtual void MouseDown(BPoint where, uint32 buttons,
|
||||
int32 modifiers);
|
||||
virtual void MouseUp(BPoint where, uint32 buttons,
|
||||
int32 modifiers);
|
||||
virtual void MouseMoved(BPoint where, uint32 buttons,
|
||||
int32 modifiers);
|
||||
|
||||
public:
|
||||
class Listener;
|
||||
|
||||
void AddListener(Listener* listener);
|
||||
void RemoveListener(Listener* listener);
|
||||
|
||||
protected:
|
||||
bool IsPressed() const;
|
||||
|
||||
private:
|
||||
void _PressedUpdate(BPoint where);
|
||||
void _NotifyListeners();
|
||||
|
||||
private:
|
||||
button_policy fPolicy;
|
||||
bool fSelected;
|
||||
bool fPressed;
|
||||
bool fPressedInBounds;
|
||||
BList fListeners;
|
||||
};
|
||||
|
||||
|
||||
// synchronous listener interface
|
||||
class AbstractButton::Listener {
|
||||
public:
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void SelectionChanged(AbstractButton* button) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // WIDGET_LAYOUT_TEST_ABSTRACT_BUTTON_H
|
||||
@@ -10,11 +10,34 @@
|
||||
#include <Box.h>
|
||||
#include <Message.h>
|
||||
|
||||
#include "GroupView.h"
|
||||
#include "RadioButton.h"
|
||||
|
||||
|
||||
// messages
|
||||
enum {
|
||||
MSG_BORDER_STYLE_CHANGED = 'bstc',
|
||||
};
|
||||
|
||||
|
||||
// BorderStyleRadioButton
|
||||
class BoxTest::BorderStyleRadioButton : public LabeledRadioButton {
|
||||
public:
|
||||
BorderStyleRadioButton(const char* label, border_style style)
|
||||
: LabeledRadioButton(label),
|
||||
fBorderStyle(style)
|
||||
{
|
||||
}
|
||||
|
||||
border_style fBorderStyle;
|
||||
};
|
||||
|
||||
|
||||
// constructor
|
||||
BoxTest::BoxTest()
|
||||
: Test("Box", NULL),
|
||||
fBox(new BBox(BRect(0, 0, 9, 9), "test box", B_FOLLOW_NONE))
|
||||
fBox(new BBox(BRect(0, 0, 9, 9), "test box", B_FOLLOW_NONE)),
|
||||
fBorderStyleRadioGroup(NULL)
|
||||
// TODO: Layout-friendly constructor
|
||||
{
|
||||
SetView(fBox);
|
||||
@@ -24,6 +47,7 @@ BoxTest::BoxTest()
|
||||
// destructor
|
||||
BoxTest::~BoxTest()
|
||||
{
|
||||
delete fBorderStyleRadioGroup;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,26 +55,41 @@ BoxTest::~BoxTest()
|
||||
void
|
||||
BoxTest::ActivateTest(View* controls)
|
||||
{
|
||||
/* GroupView* group = new GroupView(B_VERTICAL);
|
||||
// BBox sets its background color to that of its parent in
|
||||
// AttachedToWindow(). Override.
|
||||
rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
fBox->SetViewColor(background);
|
||||
fBox->SetLowColor(background);
|
||||
|
||||
GroupView* group = new GroupView(B_VERTICAL);
|
||||
group->SetFrame(controls->Bounds());
|
||||
group->SetSpacing(0, 8);
|
||||
controls->AddChild(group);
|
||||
|
||||
// long button text
|
||||
fLongTextCheckBox = new LabeledCheckBox("Long Button Text",
|
||||
new BMessage(MSG_CHANGE_BUTTON_TEXT), this);
|
||||
group->AddChild(fLongTextCheckBox);
|
||||
// the radio button group for selecting the border style
|
||||
fBorderStyleRadioGroup = new RadioButtonGroup(
|
||||
new BMessage(MSG_BORDER_STYLE_CHANGED), this);
|
||||
|
||||
// big font
|
||||
fBigFontCheckBox = new LabeledCheckBox("Big Button Font",
|
||||
new BMessage(MSG_CHANGE_BUTTON_FONT), this);
|
||||
group->AddChild(fBigFontCheckBox);
|
||||
// no border
|
||||
LabeledRadioButton* button = new BorderStyleRadioButton("no border",
|
||||
B_NO_BORDER);
|
||||
group->AddChild(button);
|
||||
fBorderStyleRadioGroup->AddButton(button->GetRadioButton());
|
||||
|
||||
// plain border
|
||||
button = new BorderStyleRadioButton("plain border", B_PLAIN_BORDER);
|
||||
group->AddChild(button);
|
||||
fBorderStyleRadioGroup->AddButton(button->GetRadioButton());
|
||||
|
||||
// fancy border
|
||||
button = new BorderStyleRadioButton("fancy border", B_FANCY_BORDER);
|
||||
group->AddChild(button);
|
||||
fBorderStyleRadioGroup->AddButton(button->GetRadioButton());
|
||||
|
||||
// default to no border
|
||||
fBorderStyleRadioGroup->SelectButton(0L);
|
||||
|
||||
group->AddChild(new Glue());
|
||||
|
||||
_SetButtonText(false);
|
||||
_SetButtonFont(false);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@@ -59,3 +98,37 @@ void
|
||||
BoxTest::DectivateTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
BoxTest::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_BORDER_STYLE_CHANGED:
|
||||
_UpdateBorderStyle();
|
||||
break;
|
||||
default:
|
||||
Test::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// _UpdateBorderStyle
|
||||
void
|
||||
BoxTest::_UpdateBorderStyle()
|
||||
{
|
||||
if (fBorderStyleRadioGroup) {
|
||||
// We need to get the parent of the actually selected button, since
|
||||
// that is the labeled radio button we've derived our
|
||||
// BorderStyleRadioButton from.
|
||||
AbstractButton* selectedButton
|
||||
= fBorderStyleRadioGroup->SelectedButton();
|
||||
View* parent = (selectedButton ? selectedButton->Parent() : NULL);
|
||||
BorderStyleRadioButton* button = dynamic_cast<BorderStyleRadioButton*>(
|
||||
parent);
|
||||
if (button)
|
||||
fBox->SetBorder(button->fBorderStyle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
|
||||
class BBox;
|
||||
class View;
|
||||
class RadioButtonGroup;
|
||||
|
||||
|
||||
class BoxTest : public Test {
|
||||
@@ -21,8 +21,16 @@ public:
|
||||
virtual void ActivateTest(View* controls);
|
||||
virtual void DectivateTest();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
void _UpdateBorderStyle();
|
||||
|
||||
private:
|
||||
class BorderStyleRadioButton;
|
||||
|
||||
BBox* fBox;
|
||||
RadioButtonGroup* fBorderStyleRadioGroup;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -14,39 +14,12 @@
|
||||
|
||||
|
||||
CheckBox::CheckBox(BMessage* message, BMessenger target)
|
||||
: View(BRect(0, 0, 12, 12)),
|
||||
BInvoker(message, target),
|
||||
fSelected(false),
|
||||
fPressed(false)
|
||||
: AbstractButton(BUTTON_POLICY_TOGGLE_ON_RELEASE, message, target)
|
||||
{
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CheckBox::SetSelected(bool selected)
|
||||
{
|
||||
if (selected != fSelected) {
|
||||
fSelected = selected;
|
||||
Invalidate();
|
||||
|
||||
// send the message
|
||||
if (Message()) {
|
||||
BMessage message(*Message());
|
||||
message.AddBool("selected", IsSelected());
|
||||
InvokeNotify(&message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CheckBox::IsSelected() const
|
||||
{
|
||||
return fSelected;
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
CheckBox::MinSize()
|
||||
{
|
||||
@@ -66,14 +39,14 @@ CheckBox::Draw(BView* container, BRect updateRect)
|
||||
{
|
||||
BRect rect(Bounds());
|
||||
|
||||
if (fPressed)
|
||||
if (IsPressed())
|
||||
container->SetHighColor((rgb_color){ 120, 0, 0, 255 });
|
||||
else
|
||||
container->SetHighColor((rgb_color){ 0, 0, 0, 255 });
|
||||
|
||||
container->StrokeRect(rect);
|
||||
|
||||
if (fPressed ? fPressedSelected : fSelected) {
|
||||
if (IsSelected()) {
|
||||
rect.InsetBy(2, 2);
|
||||
container->StrokeLine(rect.LeftTop(), rect.RightBottom());
|
||||
container->StrokeLine(rect.RightTop(), rect.LeftBottom());
|
||||
@@ -81,52 +54,6 @@ CheckBox::Draw(BView* container, BRect updateRect)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CheckBox::MouseDown(BPoint where, uint32 buttons, int32 modifiers)
|
||||
{
|
||||
if (fPressed)
|
||||
return;
|
||||
|
||||
fPressed = true;
|
||||
fPressedSelected = fSelected;
|
||||
_PressedUpdate(where);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CheckBox::MouseUp(BPoint where, uint32 buttons, int32 modifiers)
|
||||
{
|
||||
if (!fPressed || (buttons & B_PRIMARY_MOUSE_BUTTON))
|
||||
return;
|
||||
|
||||
_PressedUpdate(where);
|
||||
fPressed = false;
|
||||
SetSelected(fPressedSelected);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CheckBox::MouseMoved(BPoint where, uint32 buttons, int32 modifiers)
|
||||
{
|
||||
if (!fPressed)
|
||||
return;
|
||||
|
||||
_PressedUpdate(where);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CheckBox::_PressedUpdate(BPoint where)
|
||||
{
|
||||
bool pressedSelected = Bounds().Contains(where) ^ fSelected;
|
||||
if (pressedSelected != fPressedSelected) {
|
||||
fPressedSelected = pressedSelected;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - LabeledCheckBox
|
||||
|
||||
|
||||
|
||||
@@ -8,37 +8,20 @@
|
||||
|
||||
#include <Invoker.h>
|
||||
|
||||
#include "AbstractButton.h"
|
||||
#include "GroupView.h"
|
||||
|
||||
|
||||
// CheckBox
|
||||
class CheckBox : public View, public BInvoker {
|
||||
class CheckBox : public AbstractButton {
|
||||
public:
|
||||
CheckBox(BMessage* message = NULL,
|
||||
BMessenger target = BMessenger());
|
||||
|
||||
void SetSelected(bool selected);
|
||||
bool IsSelected() const;
|
||||
|
||||
virtual BSize MinSize();
|
||||
virtual BSize MaxSize();
|
||||
|
||||
virtual void Draw(BView* container, BRect updateRect);
|
||||
|
||||
virtual void MouseDown(BPoint where, uint32 buttons,
|
||||
int32 modifiers);
|
||||
virtual void MouseUp(BPoint where, uint32 buttons,
|
||||
int32 modifiers);
|
||||
virtual void MouseMoved(BPoint where, uint32 buttons,
|
||||
int32 modifiers);
|
||||
|
||||
private:
|
||||
void _PressedUpdate(BPoint where);
|
||||
|
||||
private:
|
||||
bool fSelected;
|
||||
bool fPressed;
|
||||
bool fPressedSelected;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,10 +5,12 @@ SetSubDirSupportedPlatforms haiku libbe_test ;
|
||||
SimpleTest WidgetLayoutTest :
|
||||
WidgetLayoutTest.cpp
|
||||
|
||||
AbstractButton.cpp
|
||||
BoxTest.cpp
|
||||
ButtonTest.cpp
|
||||
CheckBox.cpp
|
||||
GroupView.cpp
|
||||
RadioButton.cpp
|
||||
StringView.cpp
|
||||
Test.cpp
|
||||
TwoDimensionalSliderView.cpp
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright 2007, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "RadioButton.h"
|
||||
|
||||
#include <View.h>
|
||||
|
||||
#include "StringView.h"
|
||||
|
||||
|
||||
// #pragma mark - RadioButton
|
||||
|
||||
|
||||
RadioButton::RadioButton(BMessage* message, BMessenger target)
|
||||
: AbstractButton(BUTTON_POLICY_SELECT_ON_RELEASE, message, target)
|
||||
{
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
RadioButton::MinSize()
|
||||
{
|
||||
return BSize(12, 12);
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
RadioButton::MaxSize()
|
||||
{
|
||||
return MinSize();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RadioButton::Draw(BView* container, BRect updateRect)
|
||||
{
|
||||
BRect rect(Bounds());
|
||||
|
||||
if (IsPressed())
|
||||
container->SetHighColor((rgb_color){ 120, 0, 0, 255 });
|
||||
else
|
||||
container->SetHighColor((rgb_color){ 0, 0, 0, 255 });
|
||||
|
||||
container->StrokeRect(rect);
|
||||
|
||||
if (IsSelected()) {
|
||||
rect.InsetBy(4, 4);
|
||||
container->FillRect(rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - LabeledRadioButton
|
||||
|
||||
|
||||
LabeledRadioButton::LabeledRadioButton(const char* label, BMessage* message,
|
||||
BMessenger target)
|
||||
: GroupView(B_HORIZONTAL),
|
||||
fRadioButton(new RadioButton(message, target))
|
||||
{
|
||||
SetSpacing(8, 0);
|
||||
|
||||
AddChild(fRadioButton);
|
||||
if (label)
|
||||
AddChild(new StringView(label));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LabeledRadioButton::SetTarget(BMessenger messenger)
|
||||
{
|
||||
fRadioButton->SetTarget(messenger);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LabeledRadioButton::SetSelected(bool selected)
|
||||
{
|
||||
fRadioButton->SetSelected(selected);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LabeledRadioButton::IsSelected() const
|
||||
{
|
||||
return fRadioButton->IsSelected();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - RadioButtonGroup
|
||||
|
||||
|
||||
RadioButtonGroup::RadioButtonGroup(BMessage* message, BMessenger target)
|
||||
: BInvoker(message, target),
|
||||
fButtons(10),
|
||||
fSelected(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RadioButtonGroup::~RadioButtonGroup()
|
||||
{
|
||||
// remove as listener from buttons
|
||||
for (int32 i = 0; AbstractButton* button = ButtonAt(i); i++)
|
||||
button->RemoveListener(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RadioButtonGroup::AddButton(AbstractButton* button)
|
||||
{
|
||||
if (!button || fButtons.HasItem(button))
|
||||
return;
|
||||
|
||||
// force radio button policy
|
||||
button->SetPolicy(BUTTON_POLICY_SELECT_ON_RELEASE);
|
||||
|
||||
// deselect the button, if we do already have a selected one
|
||||
if (fSelected)
|
||||
button->SetSelected(false);
|
||||
|
||||
// add ourselves as listener
|
||||
button->AddListener(this);
|
||||
|
||||
// add the button to our list
|
||||
fButtons.AddItem(button);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
RadioButtonGroup::RemoveButton(AbstractButton* button)
|
||||
{
|
||||
return RemoveButton(IndexOfButton(button));
|
||||
}
|
||||
|
||||
|
||||
AbstractButton*
|
||||
RadioButtonGroup::RemoveButton(int32 index)
|
||||
{
|
||||
// remove the button from our list
|
||||
AbstractButton* button = (AbstractButton*)fButtons.RemoveItem(index);
|
||||
if (!button)
|
||||
return NULL;
|
||||
|
||||
// remove ourselves as listener
|
||||
button->RemoveListener(this);
|
||||
|
||||
// if it was the selected one, we don't have a selection anymore
|
||||
if (button == fSelected) {
|
||||
fSelected = NULL;
|
||||
_SelectionChanged();
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
RadioButtonGroup::CountButtons() const
|
||||
{
|
||||
return fButtons.CountItems();
|
||||
}
|
||||
|
||||
|
||||
AbstractButton*
|
||||
RadioButtonGroup::ButtonAt(int32 index) const
|
||||
{
|
||||
return (AbstractButton*)fButtons.ItemAt(index);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
RadioButtonGroup::IndexOfButton(AbstractButton* button) const
|
||||
{
|
||||
return fButtons.IndexOf(button);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RadioButtonGroup::SelectButton(AbstractButton* button)
|
||||
{
|
||||
if (button && fButtons.HasItem(button))
|
||||
button->SetSelected(true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RadioButtonGroup::SelectButton(int32 index)
|
||||
{
|
||||
if (AbstractButton* button = ButtonAt(index))
|
||||
button->SetSelected(true);
|
||||
}
|
||||
|
||||
|
||||
AbstractButton*
|
||||
RadioButtonGroup::SelectedButton() const
|
||||
{
|
||||
return fSelected;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
RadioButtonGroup::SelectedIndex() const
|
||||
{
|
||||
return (fSelected ? IndexOfButton(fSelected) : -1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RadioButtonGroup::SelectionChanged(AbstractButton* button)
|
||||
{
|
||||
// We're only interested in a notification when one of our buttons that
|
||||
// has not been selected one before has become selected.
|
||||
if (!button || !fButtons.HasItem(button) || !button->IsSelected()
|
||||
|| button == fSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set the new selection
|
||||
AbstractButton* oldSelected = fSelected;
|
||||
fSelected = button;
|
||||
|
||||
// deselect the old selected button
|
||||
if (oldSelected)
|
||||
oldSelected->SetSelected(false);
|
||||
|
||||
// send out notifications
|
||||
_SelectionChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RadioButtonGroup::_SelectionChanged()
|
||||
{
|
||||
// send the message
|
||||
if (Message()) {
|
||||
BMessage message(*Message());
|
||||
message.AddPointer("button group", this);
|
||||
message.AddPointer("selected button", fSelected);
|
||||
message.AddInt32("selected index", SelectedIndex());
|
||||
InvokeNotify(&message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2007, Ingo Weinhold <[email protected]>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef WIDGET_LAYOUT_TEST_CHECK_BOX_H
|
||||
#define WIDGET_LAYOUT_TEST_CHECK_BOX_H
|
||||
|
||||
|
||||
#include <Invoker.h>
|
||||
#include <List.h>
|
||||
|
||||
#include "AbstractButton.h"
|
||||
#include "GroupView.h"
|
||||
|
||||
|
||||
// RadioButton
|
||||
class RadioButton : public AbstractButton {
|
||||
public:
|
||||
RadioButton(BMessage* message = NULL,
|
||||
BMessenger target = BMessenger());
|
||||
|
||||
virtual BSize MinSize();
|
||||
virtual BSize MaxSize();
|
||||
|
||||
virtual void Draw(BView* container, BRect updateRect);
|
||||
};
|
||||
|
||||
|
||||
// LabeledRadioButton
|
||||
class LabeledRadioButton : public GroupView {
|
||||
public:
|
||||
LabeledRadioButton(const char* label,
|
||||
BMessage* message = NULL,
|
||||
BMessenger target = BMessenger());
|
||||
|
||||
RadioButton* GetRadioButton() const { return fRadioButton; }
|
||||
|
||||
void SetTarget(BMessenger messenger);
|
||||
|
||||
void SetSelected(bool selected);
|
||||
bool IsSelected() const;
|
||||
|
||||
private:
|
||||
RadioButton* fRadioButton;
|
||||
};
|
||||
|
||||
|
||||
// RadioButtonGroup
|
||||
class RadioButtonGroup : public BInvoker, private AbstractButton::Listener {
|
||||
public:
|
||||
RadioButtonGroup(BMessage* message = NULL,
|
||||
BMessenger target = BMessenger());
|
||||
virtual ~RadioButtonGroup();
|
||||
|
||||
void AddButton(AbstractButton* button);
|
||||
bool RemoveButton(AbstractButton* button);
|
||||
AbstractButton* RemoveButton(int32 index);
|
||||
|
||||
int32 CountButtons() const;
|
||||
AbstractButton* ButtonAt(int32 index) const;
|
||||
int32 IndexOfButton(AbstractButton* button) const;
|
||||
|
||||
void SelectButton(AbstractButton* button);
|
||||
void SelectButton(int32 index);
|
||||
AbstractButton* SelectedButton() const;
|
||||
int32 SelectedIndex() const;
|
||||
|
||||
private:
|
||||
virtual void SelectionChanged(AbstractButton* button);
|
||||
|
||||
void _SelectionChanged();
|
||||
|
||||
private:
|
||||
BList fButtons;
|
||||
AbstractButton* fSelected;
|
||||
};
|
||||
|
||||
|
||||
#endif // WIDGET_LAYOUT_TEST_CHECK_BOX_H
|
||||
Reference in New Issue
Block a user