10ce9bc68SIngo Weinhold /*
20ce9bc68SIngo Weinhold * Copyright 2007, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
30ce9bc68SIngo Weinhold * All rights reserved. Distributed under the terms of the MIT License.
40ce9bc68SIngo Weinhold */
50ce9bc68SIngo Weinhold
60ce9bc68SIngo Weinhold #include "RadioButton.h"
70ce9bc68SIngo Weinhold
80ce9bc68SIngo Weinhold #include <View.h>
90ce9bc68SIngo Weinhold
100ce9bc68SIngo Weinhold #include "StringView.h"
110ce9bc68SIngo Weinhold
120ce9bc68SIngo Weinhold
130ce9bc68SIngo Weinhold // #pragma mark - RadioButton
140ce9bc68SIngo Weinhold
150ce9bc68SIngo Weinhold
RadioButton(BMessage * message,BMessenger target)160ce9bc68SIngo Weinhold RadioButton::RadioButton(BMessage* message, BMessenger target)
170ce9bc68SIngo Weinhold : AbstractButton(BUTTON_POLICY_SELECT_ON_RELEASE, message, target)
180ce9bc68SIngo Weinhold {
19*884412dfSAdrien Destugues SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
200ce9bc68SIngo Weinhold }
210ce9bc68SIngo Weinhold
220ce9bc68SIngo Weinhold
230ce9bc68SIngo Weinhold BSize
MinSize()240ce9bc68SIngo Weinhold RadioButton::MinSize()
250ce9bc68SIngo Weinhold {
260ce9bc68SIngo Weinhold return BSize(12, 12);
270ce9bc68SIngo Weinhold }
280ce9bc68SIngo Weinhold
290ce9bc68SIngo Weinhold
300ce9bc68SIngo Weinhold BSize
MaxSize()310ce9bc68SIngo Weinhold RadioButton::MaxSize()
320ce9bc68SIngo Weinhold {
330ce9bc68SIngo Weinhold return MinSize();
340ce9bc68SIngo Weinhold }
350ce9bc68SIngo Weinhold
360ce9bc68SIngo Weinhold
370ce9bc68SIngo Weinhold void
Draw(BView * container,BRect updateRect)380ce9bc68SIngo Weinhold RadioButton::Draw(BView* container, BRect updateRect)
390ce9bc68SIngo Weinhold {
400ce9bc68SIngo Weinhold BRect rect(Bounds());
410ce9bc68SIngo Weinhold
420ce9bc68SIngo Weinhold if (IsPressed())
430ce9bc68SIngo Weinhold container->SetHighColor((rgb_color){ 120, 0, 0, 255 });
440ce9bc68SIngo Weinhold else
450ce9bc68SIngo Weinhold container->SetHighColor((rgb_color){ 0, 0, 0, 255 });
460ce9bc68SIngo Weinhold
470ce9bc68SIngo Weinhold container->StrokeRect(rect);
480ce9bc68SIngo Weinhold
490ce9bc68SIngo Weinhold if (IsSelected()) {
500ce9bc68SIngo Weinhold rect.InsetBy(4, 4);
510ce9bc68SIngo Weinhold container->FillRect(rect);
520ce9bc68SIngo Weinhold }
530ce9bc68SIngo Weinhold }
540ce9bc68SIngo Weinhold
550ce9bc68SIngo Weinhold
560ce9bc68SIngo Weinhold // #pragma mark - LabeledRadioButton
570ce9bc68SIngo Weinhold
580ce9bc68SIngo Weinhold
LabeledRadioButton(const char * label,BMessage * message,BMessenger target)590ce9bc68SIngo Weinhold LabeledRadioButton::LabeledRadioButton(const char* label, BMessage* message,
600ce9bc68SIngo Weinhold BMessenger target)
610ce9bc68SIngo Weinhold : GroupView(B_HORIZONTAL),
620ce9bc68SIngo Weinhold fRadioButton(new RadioButton(message, target))
630ce9bc68SIngo Weinhold {
640ce9bc68SIngo Weinhold SetSpacing(8, 0);
650ce9bc68SIngo Weinhold
660ce9bc68SIngo Weinhold AddChild(fRadioButton);
670ce9bc68SIngo Weinhold if (label)
680ce9bc68SIngo Weinhold AddChild(new StringView(label));
690ce9bc68SIngo Weinhold }
700ce9bc68SIngo Weinhold
710ce9bc68SIngo Weinhold
720ce9bc68SIngo Weinhold void
SetTarget(BMessenger messenger)730ce9bc68SIngo Weinhold LabeledRadioButton::SetTarget(BMessenger messenger)
740ce9bc68SIngo Weinhold {
750ce9bc68SIngo Weinhold fRadioButton->SetTarget(messenger);
760ce9bc68SIngo Weinhold }
770ce9bc68SIngo Weinhold
780ce9bc68SIngo Weinhold
790ce9bc68SIngo Weinhold void
SetSelected(bool selected)800ce9bc68SIngo Weinhold LabeledRadioButton::SetSelected(bool selected)
810ce9bc68SIngo Weinhold {
820ce9bc68SIngo Weinhold fRadioButton->SetSelected(selected);
830ce9bc68SIngo Weinhold }
840ce9bc68SIngo Weinhold
850ce9bc68SIngo Weinhold
860ce9bc68SIngo Weinhold bool
IsSelected() const870ce9bc68SIngo Weinhold LabeledRadioButton::IsSelected() const
880ce9bc68SIngo Weinhold {
890ce9bc68SIngo Weinhold return fRadioButton->IsSelected();
900ce9bc68SIngo Weinhold }
910ce9bc68SIngo Weinhold
920ce9bc68SIngo Weinhold
930ce9bc68SIngo Weinhold // #pragma mark - RadioButtonGroup
940ce9bc68SIngo Weinhold
950ce9bc68SIngo Weinhold
RadioButtonGroup(BMessage * message,BMessenger target)960ce9bc68SIngo Weinhold RadioButtonGroup::RadioButtonGroup(BMessage* message, BMessenger target)
970ce9bc68SIngo Weinhold : BInvoker(message, target),
980ce9bc68SIngo Weinhold fButtons(10),
990ce9bc68SIngo Weinhold fSelected(NULL)
1000ce9bc68SIngo Weinhold {
1010ce9bc68SIngo Weinhold }
1020ce9bc68SIngo Weinhold
1030ce9bc68SIngo Weinhold
~RadioButtonGroup()1040ce9bc68SIngo Weinhold RadioButtonGroup::~RadioButtonGroup()
1050ce9bc68SIngo Weinhold {
1060ce9bc68SIngo Weinhold // remove as listener from buttons
1070ce9bc68SIngo Weinhold for (int32 i = 0; AbstractButton* button = ButtonAt(i); i++)
1080ce9bc68SIngo Weinhold button->RemoveListener(this);
1090ce9bc68SIngo Weinhold }
1100ce9bc68SIngo Weinhold
1110ce9bc68SIngo Weinhold
1120ce9bc68SIngo Weinhold void
AddButton(AbstractButton * button)1130ce9bc68SIngo Weinhold RadioButtonGroup::AddButton(AbstractButton* button)
1140ce9bc68SIngo Weinhold {
1150ce9bc68SIngo Weinhold if (!button || fButtons.HasItem(button))
1160ce9bc68SIngo Weinhold return;
1170ce9bc68SIngo Weinhold
1180ce9bc68SIngo Weinhold // force radio button policy
1190ce9bc68SIngo Weinhold button->SetPolicy(BUTTON_POLICY_SELECT_ON_RELEASE);
1200ce9bc68SIngo Weinhold
1210ce9bc68SIngo Weinhold // deselect the button, if we do already have a selected one
1220ce9bc68SIngo Weinhold if (fSelected)
1230ce9bc68SIngo Weinhold button->SetSelected(false);
1240ce9bc68SIngo Weinhold
1250ce9bc68SIngo Weinhold // add ourselves as listener
1260ce9bc68SIngo Weinhold button->AddListener(this);
1270ce9bc68SIngo Weinhold
1280ce9bc68SIngo Weinhold // add the button to our list
1290ce9bc68SIngo Weinhold fButtons.AddItem(button);
1300ce9bc68SIngo Weinhold }
1310ce9bc68SIngo Weinhold
1320ce9bc68SIngo Weinhold
1330ce9bc68SIngo Weinhold bool
RemoveButton(AbstractButton * button)1340ce9bc68SIngo Weinhold RadioButtonGroup::RemoveButton(AbstractButton* button)
1350ce9bc68SIngo Weinhold {
1360ce9bc68SIngo Weinhold return RemoveButton(IndexOfButton(button));
1370ce9bc68SIngo Weinhold }
1380ce9bc68SIngo Weinhold
1390ce9bc68SIngo Weinhold
1400ce9bc68SIngo Weinhold AbstractButton*
RemoveButton(int32 index)1410ce9bc68SIngo Weinhold RadioButtonGroup::RemoveButton(int32 index)
1420ce9bc68SIngo Weinhold {
1430ce9bc68SIngo Weinhold // remove the button from our list
1440ce9bc68SIngo Weinhold AbstractButton* button = (AbstractButton*)fButtons.RemoveItem(index);
1450ce9bc68SIngo Weinhold if (!button)
1460ce9bc68SIngo Weinhold return NULL;
1470ce9bc68SIngo Weinhold
1480ce9bc68SIngo Weinhold // remove ourselves as listener
1490ce9bc68SIngo Weinhold button->RemoveListener(this);
1500ce9bc68SIngo Weinhold
1510ce9bc68SIngo Weinhold // if it was the selected one, we don't have a selection anymore
1520ce9bc68SIngo Weinhold if (button == fSelected) {
1530ce9bc68SIngo Weinhold fSelected = NULL;
1540ce9bc68SIngo Weinhold _SelectionChanged();
1550ce9bc68SIngo Weinhold }
1560ce9bc68SIngo Weinhold
1570ce9bc68SIngo Weinhold return button;
1580ce9bc68SIngo Weinhold }
1590ce9bc68SIngo Weinhold
1600ce9bc68SIngo Weinhold
1610ce9bc68SIngo Weinhold int32
CountButtons() const1620ce9bc68SIngo Weinhold RadioButtonGroup::CountButtons() const
1630ce9bc68SIngo Weinhold {
1640ce9bc68SIngo Weinhold return fButtons.CountItems();
1650ce9bc68SIngo Weinhold }
1660ce9bc68SIngo Weinhold
1670ce9bc68SIngo Weinhold
1680ce9bc68SIngo Weinhold AbstractButton*
ButtonAt(int32 index) const1690ce9bc68SIngo Weinhold RadioButtonGroup::ButtonAt(int32 index) const
1700ce9bc68SIngo Weinhold {
1710ce9bc68SIngo Weinhold return (AbstractButton*)fButtons.ItemAt(index);
1720ce9bc68SIngo Weinhold }
1730ce9bc68SIngo Weinhold
1740ce9bc68SIngo Weinhold
1750ce9bc68SIngo Weinhold int32
IndexOfButton(AbstractButton * button) const1760ce9bc68SIngo Weinhold RadioButtonGroup::IndexOfButton(AbstractButton* button) const
1770ce9bc68SIngo Weinhold {
1780ce9bc68SIngo Weinhold return fButtons.IndexOf(button);
1790ce9bc68SIngo Weinhold }
1800ce9bc68SIngo Weinhold
1810ce9bc68SIngo Weinhold
1820ce9bc68SIngo Weinhold void
SelectButton(AbstractButton * button)1830ce9bc68SIngo Weinhold RadioButtonGroup::SelectButton(AbstractButton* button)
1840ce9bc68SIngo Weinhold {
1850ce9bc68SIngo Weinhold if (button && fButtons.HasItem(button))
1860ce9bc68SIngo Weinhold button->SetSelected(true);
1870ce9bc68SIngo Weinhold }
1880ce9bc68SIngo Weinhold
1890ce9bc68SIngo Weinhold
1900ce9bc68SIngo Weinhold void
SelectButton(int32 index)1910ce9bc68SIngo Weinhold RadioButtonGroup::SelectButton(int32 index)
1920ce9bc68SIngo Weinhold {
1930ce9bc68SIngo Weinhold if (AbstractButton* button = ButtonAt(index))
1940ce9bc68SIngo Weinhold button->SetSelected(true);
1950ce9bc68SIngo Weinhold }
1960ce9bc68SIngo Weinhold
1970ce9bc68SIngo Weinhold
1980ce9bc68SIngo Weinhold AbstractButton*
SelectedButton() const1990ce9bc68SIngo Weinhold RadioButtonGroup::SelectedButton() const
2000ce9bc68SIngo Weinhold {
2010ce9bc68SIngo Weinhold return fSelected;
2020ce9bc68SIngo Weinhold }
2030ce9bc68SIngo Weinhold
2040ce9bc68SIngo Weinhold
2050ce9bc68SIngo Weinhold int32
SelectedIndex() const2060ce9bc68SIngo Weinhold RadioButtonGroup::SelectedIndex() const
2070ce9bc68SIngo Weinhold {
2080ce9bc68SIngo Weinhold return (fSelected ? IndexOfButton(fSelected) : -1);
2090ce9bc68SIngo Weinhold }
2100ce9bc68SIngo Weinhold
2110ce9bc68SIngo Weinhold
2120ce9bc68SIngo Weinhold void
SelectionChanged(AbstractButton * button)2130ce9bc68SIngo Weinhold RadioButtonGroup::SelectionChanged(AbstractButton* button)
2140ce9bc68SIngo Weinhold {
2150ce9bc68SIngo Weinhold // We're only interested in a notification when one of our buttons that
2160ce9bc68SIngo Weinhold // has not been selected one before has become selected.
2170ce9bc68SIngo Weinhold if (!button || !fButtons.HasItem(button) || !button->IsSelected()
2180ce9bc68SIngo Weinhold || button == fSelected) {
2190ce9bc68SIngo Weinhold return;
2200ce9bc68SIngo Weinhold }
2210ce9bc68SIngo Weinhold
2220ce9bc68SIngo Weinhold // set the new selection
2230ce9bc68SIngo Weinhold AbstractButton* oldSelected = fSelected;
2240ce9bc68SIngo Weinhold fSelected = button;
2250ce9bc68SIngo Weinhold
2260ce9bc68SIngo Weinhold // deselect the old selected button
2270ce9bc68SIngo Weinhold if (oldSelected)
2280ce9bc68SIngo Weinhold oldSelected->SetSelected(false);
2290ce9bc68SIngo Weinhold
2300ce9bc68SIngo Weinhold // send out notifications
2310ce9bc68SIngo Weinhold _SelectionChanged();
2320ce9bc68SIngo Weinhold }
2330ce9bc68SIngo Weinhold
2340ce9bc68SIngo Weinhold
2350ce9bc68SIngo Weinhold void
_SelectionChanged()2360ce9bc68SIngo Weinhold RadioButtonGroup::_SelectionChanged()
2370ce9bc68SIngo Weinhold {
2380ce9bc68SIngo Weinhold // send the message
2390ce9bc68SIngo Weinhold if (Message()) {
2400ce9bc68SIngo Weinhold BMessage message(*Message());
2410ce9bc68SIngo Weinhold message.AddPointer("button group", this);
2420ce9bc68SIngo Weinhold message.AddPointer("selected button", fSelected);
2430ce9bc68SIngo Weinhold message.AddInt32("selected index", SelectedIndex());
2440ce9bc68SIngo Weinhold InvokeNotify(&message);
2450ce9bc68SIngo Weinhold }
2460ce9bc68SIngo Weinhold }
247