// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/views/controls/button/radio_button.h" #include "base/logging.h" #include "grit/ui_resources.h" #include "ui/base/accessibility/accessible_view_state.h" #include "ui/base/resource/resource_bundle.h" #include "ui/views/widget/widget.h" namespace views { // static const char RadioButton::kViewClassName[] = "RadioButton"; RadioButton::RadioButton(const string16& label, int group_id) : Checkbox(label) { SetGroup(group_id); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); // Unchecked/Unfocused images. SetCustomImage(false, false, STATE_NORMAL, *rb.GetImageSkiaNamed(IDR_RADIO)); SetCustomImage(false, false, STATE_HOVERED, *rb.GetImageSkiaNamed(IDR_RADIO_HOVER)); SetCustomImage(false, false, STATE_PRESSED, *rb.GetImageSkiaNamed(IDR_RADIO_PRESSED)); SetCustomImage(false, false, STATE_DISABLED, *rb.GetImageSkiaNamed(IDR_RADIO_DISABLED)); // Checked/Unfocused images. SetCustomImage(true, false, STATE_NORMAL, *rb.GetImageSkiaNamed(IDR_RADIO_CHECKED)); SetCustomImage(true, false, STATE_HOVERED, *rb.GetImageSkiaNamed(IDR_RADIO_CHECKED_HOVER)); SetCustomImage(true, false, STATE_PRESSED, *rb.GetImageSkiaNamed(IDR_RADIO_CHECKED_PRESSED)); SetCustomImage(true, false, STATE_DISABLED, *rb.GetImageSkiaNamed(IDR_RADIO_CHECKED_DISABLED)); // Unchecked/Focused images. SetCustomImage(false, true, STATE_NORMAL, *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED)); SetCustomImage(false, true, STATE_HOVERED, *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_HOVER)); SetCustomImage(false, true, STATE_PRESSED, *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_PRESSED)); // Checked/Focused images. SetCustomImage(true, true, STATE_NORMAL, *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED)); SetCustomImage(true, true, STATE_HOVERED, *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED_HOVER)); SetCustomImage(true, true, STATE_PRESSED, *rb.GetImageSkiaNamed(IDR_RADIO_FOCUSED_CHECKED_PRESSED)); } RadioButton::~RadioButton() { } void RadioButton::SetChecked(bool checked) { if (checked == RadioButton::checked()) return; if (checked) { // We can't just get the root view here because sometimes the radio // button isn't attached to a root view (e.g., if it's part of a tab page // that is currently not active). View* container = parent(); while (container && container->parent()) container = container->parent(); if (container) { Views other; container->GetViewsInGroup(GetGroup(), &other); for (Views::iterator i(other.begin()); i != other.end(); ++i) { if (*i != this) { if (strcmp((*i)->GetClassName(), kViewClassName)) { NOTREACHED() << "radio-button-nt has same group as other non " "radio-button-nt views."; continue; } RadioButton* peer = static_cast(*i); peer->SetChecked(false); } } } } Checkbox::SetChecked(checked); } const char* RadioButton::GetClassName() const { return kViewClassName; } void RadioButton::GetAccessibleState(ui::AccessibleViewState* state) { Checkbox::GetAccessibleState(state); state->role = ui::AccessibilityTypes::ROLE_RADIOBUTTON; } View* RadioButton::GetSelectedViewForGroup(int group) { Views views; GetWidget()->GetRootView()->GetViewsInGroup(group, &views); if (views.empty()) return NULL; for (Views::const_iterator i(views.begin()); i != views.end(); ++i) { // REVIEW: why don't we check the runtime type like is done above? RadioButton* radio_button = static_cast(*i); if (radio_button->checked()) return radio_button; } return NULL; } bool RadioButton::IsGroupFocusTraversable() const { // When focusing a radio button with tab/shift+tab, only the selected button // from the group should be focused. return false; } void RadioButton::OnFocus() { Checkbox::OnFocus(); SetChecked(true); ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), 0); LabelButton::NotifyClick(event); } void RadioButton::NotifyClick(const ui::Event& event) { // Set the checked state to true only if we are unchecked, since we can't // be toggled on and off like a checkbox. if (!checked()) SetChecked(true); RequestFocus(); LabelButton::NotifyClick(event); } ui::NativeTheme::Part RadioButton::GetThemePart() const { return ui::NativeTheme::kRadio; } } // namespace views