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.
5 #include "ui/views/controls/button/radio_button.h"
7 #include "base/logging.h"
8 #include "ui/accessibility/ax_view_state.h"
9 #include "ui/base/resource/resource_bundle.h"
10 #include "ui/events/event_utils.h"
11 #include "ui/resources/grit/ui_resources.h"
12 #include "ui/views/resources/grit/views_resources.h"
13 #include "ui/views/widget/widget.h"
18 const char RadioButton::kViewClassName
[] = "RadioButton";
20 RadioButton::RadioButton(const base::string16
& label
, int group_id
)
24 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
26 // Unchecked/Unfocused images.
27 SetCustomImage(false, false, STATE_NORMAL
,
28 *rb
.GetImageSkiaNamed(IDR_RADIO
));
29 SetCustomImage(false, false, STATE_HOVERED
,
30 *rb
.GetImageSkiaNamed(IDR_RADIO_HOVER
));
31 SetCustomImage(false, false, STATE_PRESSED
,
32 *rb
.GetImageSkiaNamed(IDR_RADIO_PRESSED
));
33 SetCustomImage(false, false, STATE_DISABLED
,
34 *rb
.GetImageSkiaNamed(IDR_RADIO_DISABLED
));
36 // Checked/Unfocused images.
37 SetCustomImage(true, false, STATE_NORMAL
,
38 *rb
.GetImageSkiaNamed(IDR_RADIO_CHECKED
));
39 SetCustomImage(true, false, STATE_HOVERED
,
40 *rb
.GetImageSkiaNamed(IDR_RADIO_CHECKED_HOVER
));
41 SetCustomImage(true, false, STATE_PRESSED
,
42 *rb
.GetImageSkiaNamed(IDR_RADIO_CHECKED_PRESSED
));
43 SetCustomImage(true, false, STATE_DISABLED
,
44 *rb
.GetImageSkiaNamed(IDR_RADIO_CHECKED_DISABLED
));
46 // Unchecked/Focused images.
47 SetCustomImage(false, true, STATE_NORMAL
,
48 *rb
.GetImageSkiaNamed(IDR_RADIO_FOCUSED
));
49 SetCustomImage(false, true, STATE_HOVERED
,
50 *rb
.GetImageSkiaNamed(IDR_RADIO_FOCUSED_HOVER
));
51 SetCustomImage(false, true, STATE_PRESSED
,
52 *rb
.GetImageSkiaNamed(IDR_RADIO_FOCUSED_PRESSED
));
54 // Checked/Focused images.
55 SetCustomImage(true, true, STATE_NORMAL
,
56 *rb
.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED
));
57 SetCustomImage(true, true, STATE_HOVERED
,
58 *rb
.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED_HOVER
));
59 SetCustomImage(true, true, STATE_PRESSED
,
60 *rb
.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED_PRESSED
));
63 RadioButton::~RadioButton() {
66 void RadioButton::SetChecked(bool checked
) {
67 if (checked
== RadioButton::checked())
70 // We can't just get the root view here because sometimes the radio
71 // button isn't attached to a root view (e.g., if it's part of a tab page
72 // that is currently not active).
73 View
* container
= parent();
74 while (container
&& container
->parent())
75 container
= container
->parent();
78 container
->GetViewsInGroup(GetGroup(), &other
);
79 for (Views::iterator
i(other
.begin()); i
!= other
.end(); ++i
) {
81 if (strcmp((*i
)->GetClassName(), kViewClassName
)) {
82 NOTREACHED() << "radio-button-nt has same group as other non "
83 "radio-button-nt views.";
86 RadioButton
* peer
= static_cast<RadioButton
*>(*i
);
87 peer
->SetChecked(false);
92 Checkbox::SetChecked(checked
);
95 const char* RadioButton::GetClassName() const {
96 return kViewClassName
;
99 void RadioButton::GetAccessibleState(ui::AXViewState
* state
) {
100 Checkbox::GetAccessibleState(state
);
101 state
->role
= ui::AX_ROLE_RADIO_BUTTON
;
104 View
* RadioButton::GetSelectedViewForGroup(int group
) {
106 GetWidget()->GetRootView()->GetViewsInGroup(group
, &views
);
110 for (Views::const_iterator
i(views
.begin()); i
!= views
.end(); ++i
) {
111 // REVIEW: why don't we check the runtime type like is done above?
112 RadioButton
* radio_button
= static_cast<RadioButton
*>(*i
);
113 if (radio_button
->checked())
119 bool RadioButton::IsGroupFocusTraversable() const {
120 // When focusing a radio button with tab/shift+tab, only the selected button
121 // from the group should be focused.
125 void RadioButton::OnFocus() {
128 ui::MouseEvent
event(ui::ET_MOUSE_PRESSED
, gfx::Point(), gfx::Point(),
129 ui::EventTimeForNow(), 0, 0);
130 LabelButton::NotifyClick(event
);
133 void RadioButton::NotifyClick(const ui::Event
& event
) {
134 // Set the checked state to true only if we are unchecked, since we can't
135 // be toggled on and off like a checkbox.
139 LabelButton::NotifyClick(event
);
142 ui::NativeTheme::Part
RadioButton::GetThemePart() const {
143 return ui::NativeTheme::kRadio
;