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 16RadioButton::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 23BSize 24RadioButton::MinSize() 25{ 26 return BSize(12, 12); 27} 28 29 30BSize 31RadioButton::MaxSize() 32{ 33 return MinSize(); 34} 35 36 37void 38RadioButton::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 59LabeledRadioButton::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 72void 73LabeledRadioButton::SetTarget(BMessenger messenger) 74{ 75 fRadioButton->SetTarget(messenger); 76} 77 78 79void 80LabeledRadioButton::SetSelected(bool selected) 81{ 82 fRadioButton->SetSelected(selected); 83} 84 85 86bool 87LabeledRadioButton::IsSelected() const 88{ 89 return fRadioButton->IsSelected(); 90} 91 92 93// #pragma mark - RadioButtonGroup 94 95 96RadioButtonGroup::RadioButtonGroup(BMessage* message, BMessenger target) 97 : BInvoker(message, target), 98 fButtons(10), 99 fSelected(NULL) 100{ 101} 102 103 104RadioButtonGroup::~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 112void 113RadioButtonGroup::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 133bool 134RadioButtonGroup::RemoveButton(AbstractButton* button) 135{ 136 return RemoveButton(IndexOfButton(button)); 137} 138 139 140AbstractButton* 141RadioButtonGroup::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 161int32 162RadioButtonGroup::CountButtons() const 163{ 164 return fButtons.CountItems(); 165} 166 167 168AbstractButton* 169RadioButtonGroup::ButtonAt(int32 index) const 170{ 171 return (AbstractButton*)fButtons.ItemAt(index); 172} 173 174 175int32 176RadioButtonGroup::IndexOfButton(AbstractButton* button) const 177{ 178 return fButtons.IndexOf(button); 179} 180 181 182void 183RadioButtonGroup::SelectButton(AbstractButton* button) 184{ 185 if (button && fButtons.HasItem(button)) 186 button->SetSelected(true); 187} 188 189 190void 191RadioButtonGroup::SelectButton(int32 index) 192{ 193 if (AbstractButton* button = ButtonAt(index)) 194 button->SetSelected(true); 195} 196 197 198AbstractButton* 199RadioButtonGroup::SelectedButton() const 200{ 201 return fSelected; 202} 203 204 205int32 206RadioButtonGroup::SelectedIndex() const 207{ 208 return (fSelected ? IndexOfButton(fSelected) : -1); 209} 210 211 212void 213RadioButtonGroup::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 235void 236RadioButtonGroup::_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