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