| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/views/controls/button/radio_button.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "ui/accessibility/ax_view_state.h" | |
| 9 #include "ui/base/resource/resource_bundle.h" | |
| 10 #include "ui/resources/grit/ui_resources.h" | |
| 11 #include "ui/views/widget/widget.h" | |
| 12 | |
| 13 namespace views { | |
| 14 | |
| 15 // static | |
| 16 const char RadioButton::kViewClassName[] = "RadioButton"; | |
| 17 | |
| 18 RadioButton::RadioButton(const base::string16& label, int group_id) | |
| 19 : Checkbox(label) { | |
| 20 SetGroup(group_id); | |
| 21 | |
| 22 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 23 | |
| 24 // Unchecked/Unfocused images. | |
| 25 SetCustomImage(false, false, STATE_NORMAL, | |
| 26 *rb.GetImageSkiaNamed(IDR_RADIO)); | |
| 27 SetCustomImage(false, false, STATE_HOVERED, | |
| 28 *rb.GetImageSkiaNamed(IDR_RADIO_HOVER)); | |
| 29 SetCustomImage(false, false, STATE_PRESSED, | |
| 30 *rb.GetImageSkiaNamed(IDR_RADIO_PRESSED)); | |
| 31 SetCustomImage(false, false, STATE_DISABLED, | |
| 32 *rb.GetImageSkiaNamed(IDR_RADIO_DISABLED)); | |
| 33 | |
| 34 // Checked/Unfocused images. | |
| 35 SetCustomImage(true, false, STATE_NORMAL, | |
| 36 *rb.GetImageSkiaNamed(IDR_RADIO_CHECKED)); | |
| 37 SetCustomImage(true, false, STATE_HOVERED, | |
| 38 *rb.GetImageSkiaNamed(IDR_RADIO_CHECKED_HOVER)); | |
| 39 SetCustomImage(true, false, STATE_PRESSED, | |
| 40 *rb.GetImageSkiaNamed(IDR_RADIO_CHECKED_PRESSED)); | |
| 41 SetCustomImage(true, false, STATE_DISABLED, | |
| 42 *rb.GetImageSkiaNamed(IDR_RADIO_CHECKED_DISABLED)); | |
| 43 | |
| 44 // Unchecked/Focused images. | |
| 45 SetCustomImage(false, true, STATE_NORMAL, | |
| 46 *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED)); | |
| 47 SetCustomImage(false, true, STATE_HOVERED, | |
| 48 *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_HOVER)); | |
| 49 SetCustomImage(false, true, STATE_PRESSED, | |
| 50 *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_PRESSED)); | |
| 51 | |
| 52 // Checked/Focused images. | |
| 53 SetCustomImage(true, true, STATE_NORMAL, | |
| 54 *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED)); | |
| 55 SetCustomImage(true, true, STATE_HOVERED, | |
| 56 *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED_HOVER)); | |
| 57 SetCustomImage(true, true, STATE_PRESSED, | |
| 58 *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED_PRESSED)); | |
| 59 } | |
| 60 | |
| 61 RadioButton::~RadioButton() { | |
| 62 } | |
| 63 | |
| 64 void RadioButton::SetChecked(bool checked) { | |
| 65 if (checked == RadioButton::checked()) | |
| 66 return; | |
| 67 if (checked) { | |
| 68 // We can't just get the root view here because sometimes the radio | |
| 69 // button isn't attached to a root view (e.g., if it's part of a tab page | |
| 70 // that is currently not active). | |
| 71 View* container = parent(); | |
| 72 while (container && container->parent()) | |
| 73 container = container->parent(); | |
| 74 if (container) { | |
| 75 Views other; | |
| 76 container->GetViewsInGroup(GetGroup(), &other); | |
| 77 for (Views::iterator i(other.begin()); i != other.end(); ++i) { | |
| 78 if (*i != this) { | |
| 79 if (strcmp((*i)->GetClassName(), kViewClassName)) { | |
| 80 NOTREACHED() << "radio-button-nt has same group as other non " | |
| 81 "radio-button-nt views."; | |
| 82 continue; | |
| 83 } | |
| 84 RadioButton* peer = static_cast<RadioButton*>(*i); | |
| 85 peer->SetChecked(false); | |
| 86 } | |
| 87 } | |
| 88 } | |
| 89 } | |
| 90 Checkbox::SetChecked(checked); | |
| 91 } | |
| 92 | |
| 93 const char* RadioButton::GetClassName() const { | |
| 94 return kViewClassName; | |
| 95 } | |
| 96 | |
| 97 void RadioButton::GetAccessibleState(ui::AXViewState* state) { | |
| 98 Checkbox::GetAccessibleState(state); | |
| 99 state->role = ui::AX_ROLE_RADIO_BUTTON; | |
| 100 } | |
| 101 | |
| 102 View* RadioButton::GetSelectedViewForGroup(int group) { | |
| 103 Views views; | |
| 104 GetWidget()->GetRootView()->GetViewsInGroup(group, &views); | |
| 105 if (views.empty()) | |
| 106 return NULL; | |
| 107 | |
| 108 for (Views::const_iterator i(views.begin()); i != views.end(); ++i) { | |
| 109 // REVIEW: why don't we check the runtime type like is done above? | |
| 110 RadioButton* radio_button = static_cast<RadioButton*>(*i); | |
| 111 if (radio_button->checked()) | |
| 112 return radio_button; | |
| 113 } | |
| 114 return NULL; | |
| 115 } | |
| 116 | |
| 117 bool RadioButton::IsGroupFocusTraversable() const { | |
| 118 // When focusing a radio button with tab/shift+tab, only the selected button | |
| 119 // from the group should be focused. | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 void RadioButton::OnFocus() { | |
| 124 Checkbox::OnFocus(); | |
| 125 SetChecked(true); | |
| 126 ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), 0, 0); | |
| 127 LabelButton::NotifyClick(event); | |
| 128 } | |
| 129 | |
| 130 void RadioButton::NotifyClick(const ui::Event& event) { | |
| 131 // Set the checked state to true only if we are unchecked, since we can't | |
| 132 // be toggled on and off like a checkbox. | |
| 133 if (!checked()) | |
| 134 SetChecked(true); | |
| 135 RequestFocus(); | |
| 136 LabelButton::NotifyClick(event); | |
| 137 } | |
| 138 | |
| 139 ui::NativeTheme::Part RadioButton::GetThemePart() const { | |
| 140 return ui::NativeTheme::kRadio; | |
| 141 } | |
| 142 | |
| 143 } // namespace views | |
| OLD | NEW |