1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: RadioButton.cpp 23 // Author: Marc Flerackers (mflerackers@androme.be) 24 // Description: BRadioButton represents a single on/off button. All 25 // sibling BRadioButton objects comprise a single 26 // "multiple choice" control. 27 //------------------------------------------------------------------------------ 28 29 // Standard Includes ----------------------------------------------------------- 30 31 // System Includes ------------------------------------------------------------- 32 #include <RadioButton.h> 33 #include <Errors.h> 34 35 // Project Includes ------------------------------------------------------------ 36 37 // Local Includes -------------------------------------------------------------- 38 39 // Local Defines --------------------------------------------------------------- 40 41 // Globals --------------------------------------------------------------------- 42 43 //------------------------------------------------------------------------------ 44 BRadioButton::BRadioButton(BRect frame, const char *name, const char *label, 45 BMessage *message, uint32 resizMask, uint32 flags) 46 : BControl(frame, name, label, message, resizMask, flags), 47 fOutlined(false) 48 { 49 if (Bounds().Height() < 18.0f) 50 ResizeTo(Bounds().Width(), 18.0f); 51 } 52 //------------------------------------------------------------------------------ 53 BRadioButton::BRadioButton(BMessage *archive) 54 : BControl(archive), 55 fOutlined(false) 56 { 57 } 58 //------------------------------------------------------------------------------ 59 BRadioButton::~BRadioButton() 60 { 61 } 62 //------------------------------------------------------------------------------ 63 BArchivable *BRadioButton::Instantiate(BMessage *archive) 64 { 65 if (validate_instantiation(archive, "BRadioButton")) 66 return new BRadioButton(archive); 67 else 68 return NULL; 69 } 70 //------------------------------------------------------------------------------ 71 status_t BRadioButton::Archive(BMessage *archive, bool deep) const 72 { 73 return BControl::Archive(archive, deep); 74 } 75 //------------------------------------------------------------------------------ 76 void BRadioButton::Draw(BRect updateRect) 77 { 78 font_height fh; 79 GetFontHeight(&fh); 80 81 // If the focus is changing, just redraw the focus indicator 82 if (IsFocusChanging()) 83 { 84 float h = 8.0f + (float)ceil(fh.ascent / 2.0f) + 2.0f; 85 86 if (IsFocus()) 87 SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 88 else 89 SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 90 91 StrokeLine(BPoint(20.0f, h), BPoint(20.0f + StringWidth(Label()), h)); 92 93 return; 94 } 95 96 // Placeholder until sBitmaps is filled in 97 rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR), 98 lighten1 = tint_color(no_tint, B_LIGHTEN_1_TINT), 99 lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT), 100 darken1 = tint_color(no_tint, B_DARKEN_1_TINT), 101 darken2 = tint_color(no_tint, B_DARKEN_2_TINT), 102 darken3 = tint_color(no_tint, B_DARKEN_3_TINT), 103 darken4 = tint_color(no_tint, B_DARKEN_4_TINT), 104 darkenmax = tint_color(no_tint, B_DARKEN_MAX_TINT); 105 106 BRect rect(1.0, 3.0, 13.0, 15.0); 107 108 if (IsEnabled()) 109 { 110 // Dot 111 if (Value() == B_CONTROL_ON) 112 { 113 rgb_color kb_color = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 114 115 SetHighColor(tint_color(kb_color, B_DARKEN_3_TINT)); 116 FillEllipse(rect); 117 SetHighColor(kb_color); 118 FillEllipse(BRect(rect.left + 3, rect.top + 3, rect.right - 4, rect.bottom - 4)); 119 SetHighColor(tint_color(kb_color, B_DARKEN_3_TINT)); 120 StrokeLine(BPoint(rect.right - 5, rect.bottom - 4), 121 BPoint(rect.right - 4, rect.bottom - 5)); 122 SetHighColor(tint_color(kb_color, B_LIGHTEN_MAX_TINT)); 123 StrokeLine(BPoint(rect.left + 4, rect.top + 5), 124 BPoint(rect.left + 5, rect.top + 4)); 125 126 } 127 else 128 { 129 SetHighColor(lightenmax); 130 FillEllipse(rect); 131 } 132 133 // Outer circle 134 if (fOutlined) 135 { 136 SetHighColor(darken3); 137 StrokeEllipse(rect); 138 } 139 else 140 { 141 SetHighColor(darken1); 142 StrokeArc(rect, 45.0f, 180.0f); 143 SetHighColor(lightenmax); 144 StrokeArc(rect, 45.0f, -180.0f); 145 } 146 147 rect.InsetBy(1, 1); 148 149 // Inner circle 150 SetHighColor(darken3); 151 StrokeArc(rect, 45.0f, 180.0f); 152 StrokeLine(BPoint(rect.left + 1, rect.top + 1), 153 BPoint(rect.left + 1, rect.top + 1)); 154 SetHighColor(no_tint); 155 StrokeArc(rect, 45.0f, -180.0f); 156 StrokeLine(BPoint(rect.left + 1, rect.bottom - 1), 157 BPoint(rect.left + 1, rect.bottom - 1)); 158 StrokeLine(BPoint(rect.right - 1, rect.bottom - 1), 159 BPoint(rect.right - 1, rect.bottom - 1)); 160 StrokeLine(BPoint(rect.right - 1, rect.top + 1), 161 BPoint(rect.right - 1, rect.top + 1)); 162 163 // Label 164 SetHighColor(darkenmax); 165 DrawString(Label(), BPoint(20.0f, 8.0f + (float)ceil(fh.ascent / 2.0f))); 166 167 // Focus 168 if (IsFocus()) 169 { 170 float h = 8.0f + (float)ceil(fh.ascent / 2.0f) + 2.0f; 171 172 SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 173 StrokeLine(BPoint(20.0f, h), BPoint(20.0f + StringWidth(Label()), h)); 174 } 175 } 176 else 177 { 178 // Dot 179 if (Value() == B_CONTROL_ON) 180 { 181 rgb_color kb_color = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 182 183 SetHighColor(tint_color(kb_color, B_LIGHTEN_2_TINT)); 184 FillEllipse(rect); 185 SetHighColor(tint_color(kb_color, B_LIGHTEN_MAX_TINT)); 186 StrokeLine(BPoint(rect.left + 4, rect.top + 5), 187 BPoint(rect.left + 5, rect.top + 4)); 188 SetHighColor(tint_color(kb_color, B_DARKEN_3_TINT)); 189 StrokeArc(BRect(rect.left + 2, rect.top + 2, rect.right - 2, rect.bottom - 2), 190 45.0f, -180.0f); 191 } 192 else 193 { 194 SetHighColor(lighten1); 195 FillEllipse(rect); 196 } 197 198 // Outer circle 199 SetHighColor(no_tint); 200 StrokeArc(rect, 45.0f, 180.0f); 201 SetHighColor(lighten1); 202 StrokeArc(rect, 45.0f, -180.0f); 203 204 rect.InsetBy(1, 1); 205 206 // Inner circle 207 SetHighColor(darken2); 208 StrokeArc(rect, 45.0f, 180.0f); 209 StrokeLine(BPoint(rect.left + 1, rect.top + 1), 210 BPoint(rect.left + 1, rect.top + 1)); 211 SetHighColor(no_tint); 212 StrokeArc(rect, 45.0f, -180.0f); 213 StrokeLine(BPoint(rect.left + 1, rect.bottom - 1), 214 BPoint(rect.left + 1, rect.bottom - 1)); 215 StrokeLine(BPoint(rect.right - 1, rect.bottom - 1), 216 BPoint(rect.right - 1, rect.bottom - 1)); 217 StrokeLine(BPoint(rect.right - 1, rect.top + 1), 218 BPoint(rect.right - 1, rect.top + 1)); 219 220 // Label 221 SetHighColor(tint_color(no_tint, B_DISABLED_LABEL_TINT)); 222 DrawString(Label(), BPoint(20.0f, 8.0f + (float)ceil(fh.ascent / 2.0f))); 223 } 224 } 225 //------------------------------------------------------------------------------ 226 void BRadioButton::MouseDown(BPoint point) 227 { 228 if (!IsEnabled()) 229 { 230 BControl::MouseDown(point); 231 return; 232 } 233 234 SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY | 235 B_SUSPEND_VIEW_FOCUS); 236 237 SetTracking(true); 238 fOutlined = true; 239 Invalidate(); 240 } 241 //------------------------------------------------------------------------------ 242 void BRadioButton::AttachedToWindow() 243 { 244 BControl::AttachedToWindow(); 245 } 246 //------------------------------------------------------------------------------ 247 void BRadioButton::KeyDown(const char *bytes, int32 numBytes) 248 { 249 BControl::KeyDown(bytes, numBytes); 250 } 251 //------------------------------------------------------------------------------ 252 void BRadioButton::SetValue(int32 value) 253 { 254 if (BControl::Value() == value) 255 return; 256 257 if (!IsTracking() && value == B_CONTROL_ON) 258 { 259 BView *sibling; 260 261 for (sibling = PreviousSibling(); sibling != NULL; 262 sibling = sibling->PreviousSibling()) 263 { 264 BRadioButton* radio = dynamic_cast<BRadioButton*>(sibling); 265 266 if (radio != NULL) 267 radio->BControl::SetValue(B_CONTROL_OFF); 268 } 269 270 for (sibling = NextSibling(); sibling != NULL; 271 sibling = sibling->NextSibling()) 272 { 273 BRadioButton* radio = dynamic_cast<BRadioButton*>(sibling); 274 275 if (radio != NULL) 276 radio->BControl::SetValue(B_CONTROL_OFF); 277 } 278 } 279 280 BControl::SetValue(value); 281 } 282 //------------------------------------------------------------------------------ 283 void BRadioButton::GetPreferredSize(float *width, float *height) 284 { 285 font_height fh; 286 GetFontHeight(&fh); 287 288 *height = (float)ceil(fh.ascent + fh.descent + fh.leading) + 6.0f; 289 *width = 22.0f + (float)ceil(StringWidth(Label())); 290 } 291 //------------------------------------------------------------------------------ 292 void BRadioButton::ResizeToPreferred() 293 { 294 BControl::ResizeToPreferred(); 295 } 296 //------------------------------------------------------------------------------ 297 status_t BRadioButton::Invoke(BMessage *message) 298 { 299 return BControl::Invoke(message); 300 } 301 //------------------------------------------------------------------------------ 302 void BRadioButton::MessageReceived(BMessage *message) 303 { 304 BControl::MessageReceived(message); 305 } 306 //------------------------------------------------------------------------------ 307 void BRadioButton::WindowActivated(bool active) 308 { 309 BControl::WindowActivated(active); 310 } 311 //------------------------------------------------------------------------------ 312 void BRadioButton::MouseUp(BPoint point) 313 { 314 if (IsEnabled() && IsTracking()) 315 { 316 fOutlined = false; 317 SetTracking(false); 318 319 if (Bounds().Contains(point)) 320 { 321 SetValue(B_CONTROL_ON); 322 Invoke(); 323 } 324 } 325 else 326 { 327 BControl::MouseUp(point); 328 return; 329 } 330 331 Invalidate(); 332 } 333 //------------------------------------------------------------------------------ 334 void BRadioButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message) 335 { 336 if (IsEnabled() && IsTracking()) 337 { 338 if (transit == B_EXITED_VIEW) 339 fOutlined = false; 340 else if (transit == B_ENTERED_VIEW) 341 fOutlined = true; 342 343 Invalidate(); 344 } 345 else 346 BView::MouseMoved(point, transit, message); 347 } 348 //------------------------------------------------------------------------------ 349 void BRadioButton::DetachedFromWindow() 350 { 351 BControl::DetachedFromWindow(); 352 } 353 //------------------------------------------------------------------------------ 354 void BRadioButton::FrameMoved(BPoint newLocation) 355 { 356 BControl::FrameMoved(newLocation); 357 } 358 //------------------------------------------------------------------------------ 359 void BRadioButton::FrameResized(float width, float height) 360 { 361 BControl::FrameResized(width, height); 362 } 363 //------------------------------------------------------------------------------ 364 BHandler *BRadioButton::ResolveSpecifier(BMessage *message, int32 index, 365 BMessage *specifier, int32 what, 366 const char *property) 367 { 368 return ResolveSpecifier(message, index, specifier, what, property); 369 } 370 //------------------------------------------------------------------------------ 371 void BRadioButton::MakeFocus(bool focused) 372 { 373 BControl::MakeFocus(focused); 374 } 375 //------------------------------------------------------------------------------ 376 void BRadioButton::AllAttached() 377 { 378 BControl::AllAttached(); 379 } 380 //------------------------------------------------------------------------------ 381 void BRadioButton::AllDetached() 382 { 383 BControl::AllDetached(); 384 } 385 //------------------------------------------------------------------------------ 386 status_t BRadioButton::GetSupportedSuites(BMessage *message) 387 { 388 return GetSupportedSuites(message); 389 } 390 //------------------------------------------------------------------------------ 391 status_t BRadioButton::Perform(perform_code d, void *arg) 392 { 393 return B_ERROR; 394 } 395 //------------------------------------------------------------------------------ 396 void BRadioButton::_ReservedRadioButton1() {} 397 void BRadioButton::_ReservedRadioButton2() {} 398 //------------------------------------------------------------------------------ 399 BRadioButton &BRadioButton::operator=(const BRadioButton &) 400 { 401 return *this; 402 } 403 //------------------------------------------------------------------------------ 404 405 /* 406 * $Log $ 407 * 408 * $Id $ 409 * 410 */ 411