blob: a015d5e1da85e73caffc152e6a57e4f15d433057 [file] [log] [blame]
// 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/accessibility/ax_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 base::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<RadioButton*>(*i);
peer->SetChecked(false);
}
}
}
}
Checkbox::SetChecked(checked);
}
const char* RadioButton::GetClassName() const {
return kViewClassName;
}
void RadioButton::GetAccessibleState(ui::AXViewState* state) {
Checkbox::GetAccessibleState(state);
state->role = ui::AX_ROLE_RADIO_BUTTON;
}
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<RadioButton*>(*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, 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