xref: /haiku/src/tests/kits/interface/layout/widget_layout_test/RadioButton.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright 2007, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3  * All rights reserved. Distributed under the terms of the MIT License.
4  */
5 
6 #include "RadioButton.h"
7 
8 #include <View.h>
9 
10 #include "StringView.h"
11 
12 
13 // #pragma mark - RadioButton
14 
15 
16 RadioButton::RadioButton(BMessage* message, BMessenger target)
17 	: AbstractButton(BUTTON_POLICY_SELECT_ON_RELEASE, message, target)
18 {
19 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
20 }
21 
22 
23 BSize
24 RadioButton::MinSize()
25 {
26 	return BSize(12, 12);
27 }
28 
29 
30 BSize
31 RadioButton::MaxSize()
32 {
33 	return MinSize();
34 }
35 
36 
37 void
38 RadioButton::Draw(BView* container, BRect updateRect)
39 {
40 	BRect rect(Bounds());
41 
42 	if (IsPressed())
43 		container->SetHighColor((rgb_color){ 120, 0, 0, 255 });
44 	else
45 		container->SetHighColor((rgb_color){ 0, 0, 0, 255 });
46 
47 	container->StrokeRect(rect);
48 
49 	if (IsSelected()) {
50 		rect.InsetBy(4, 4);
51 		container->FillRect(rect);
52 	}
53 }
54 
55 
56 // #pragma mark - LabeledRadioButton
57 
58 
59 LabeledRadioButton::LabeledRadioButton(const char* label, BMessage* message,
60 	BMessenger target)
61 	: GroupView(B_HORIZONTAL),
62 	  fRadioButton(new RadioButton(message, target))
63 {
64 	SetSpacing(8, 0);
65 
66 	AddChild(fRadioButton);
67 	if (label)
68 		AddChild(new StringView(label));
69 }
70 
71 
72 void
73 LabeledRadioButton::SetTarget(BMessenger messenger)
74 {
75 	fRadioButton->SetTarget(messenger);
76 }
77 
78 
79 void
80 LabeledRadioButton::SetSelected(bool selected)
81 {
82 	fRadioButton->SetSelected(selected);
83 }
84 
85 
86 bool
87 LabeledRadioButton::IsSelected() const
88 {
89 	return fRadioButton->IsSelected();
90 }
91 
92 
93 // #pragma mark - RadioButtonGroup
94 
95 
96 RadioButtonGroup::RadioButtonGroup(BMessage* message, BMessenger target)
97 	: BInvoker(message, target),
98 	  fButtons(10),
99 	  fSelected(NULL)
100 {
101 }
102 
103 
104 RadioButtonGroup::~RadioButtonGroup()
105 {
106 	// remove as listener from buttons
107 	for (int32 i = 0; AbstractButton* button = ButtonAt(i); i++)
108 		button->RemoveListener(this);
109 }
110 
111 
112 void
113 RadioButtonGroup::AddButton(AbstractButton* button)
114 {
115 	if (!button || fButtons.HasItem(button))
116 		return;
117 
118 	// force radio button policy
119 	button->SetPolicy(BUTTON_POLICY_SELECT_ON_RELEASE);
120 
121 	// deselect the button, if we do already have a selected one
122 	if (fSelected)
123 		button->SetSelected(false);
124 
125 	// add ourselves as listener
126 	button->AddListener(this);
127 
128 	// add the button to our list
129 	fButtons.AddItem(button);
130 }
131 
132 
133 bool
134 RadioButtonGroup::RemoveButton(AbstractButton* button)
135 {
136 	return RemoveButton(IndexOfButton(button));
137 }
138 
139 
140 AbstractButton*
141 RadioButtonGroup::RemoveButton(int32 index)
142 {
143 	// remove the button from our list
144 	AbstractButton* button = (AbstractButton*)fButtons.RemoveItem(index);
145 	if (!button)
146 		return NULL;
147 
148 	// remove ourselves as listener
149 	button->RemoveListener(this);
150 
151 	// if it was the selected one, we don't have a selection anymore
152 	if (button == fSelected) {
153 		fSelected = NULL;
154 		_SelectionChanged();
155 	}
156 
157 	return button;
158 }
159 
160 
161 int32
162 RadioButtonGroup::CountButtons() const
163 {
164 	return fButtons.CountItems();
165 }
166 
167 
168 AbstractButton*
169 RadioButtonGroup::ButtonAt(int32 index) const
170 {
171 	return (AbstractButton*)fButtons.ItemAt(index);
172 }
173 
174 
175 int32
176 RadioButtonGroup::IndexOfButton(AbstractButton* button) const
177 {
178 	return fButtons.IndexOf(button);
179 }
180 
181 
182 void
183 RadioButtonGroup::SelectButton(AbstractButton* button)
184 {
185 	if (button && fButtons.HasItem(button))
186 		button->SetSelected(true);
187 }
188 
189 
190 void
191 RadioButtonGroup::SelectButton(int32 index)
192 {
193 	if (AbstractButton* button = ButtonAt(index))
194 		button->SetSelected(true);
195 }
196 
197 
198 AbstractButton*
199 RadioButtonGroup::SelectedButton() const
200 {
201 	return fSelected;
202 }
203 
204 
205 int32
206 RadioButtonGroup::SelectedIndex() const
207 {
208 	return (fSelected ? IndexOfButton(fSelected) : -1);
209 }
210 
211 
212 void
213 RadioButtonGroup::SelectionChanged(AbstractButton* button)
214 {
215 	// We're only interested in a notification when one of our buttons that
216 	// has not been selected one before has become selected.
217 	if (!button || !fButtons.HasItem(button) || !button->IsSelected()
218 		|| button == fSelected) {
219 		return;
220 	}
221 
222 	// set the new selection
223 	AbstractButton* oldSelected = fSelected;
224 	fSelected = button;
225 
226 	// deselect the old selected button
227 	if (oldSelected)
228 		oldSelected->SetSelected(false);
229 
230 	// send out notifications
231 	_SelectionChanged();
232 }
233 
234 
235 void
236 RadioButtonGroup::_SelectionChanged()
237 {
238 	// send the message
239 	if (Message()) {
240 		BMessage message(*Message());
241 		message.AddPointer("button group", this);
242 		message.AddPointer("selected button", fSelected);
243 		message.AddInt32("selected index", SelectedIndex());
244 		InvokeNotify(&message);
245 	}
246 }
247