Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / ui / views / controls / button / radio_button.cc
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 "grit/ui_resources.h"
9 #include "ui/base/accessibility/accessible_view_state.h"
10 #include "ui/base/resource/resource_bundle.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::AccessibleViewState* state) {
98   Checkbox::GetAccessibleState(state);
99   state->role = ui::AccessibilityTypes::ROLE_RADIOBUTTON;
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