xref: /haiku/src/tests/kits/interface/layout/widget_layout_test/RadioButton.cpp (revision 884412df8e67a4f2546b46722ab18868d7439202)
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