15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/checkbox.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/views/controls/button/label_button_border.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/views/painter.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char Checkbox::kViewClassName[] = "Checkbox";
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Checkbox::Checkbox(const base::string16& label)
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : LabelButton(NULL, label),
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checked_(false) {
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetHorizontalAlignment(gfx::ALIGN_LEFT);
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<LabelButtonBorder> button_border(new LabelButtonBorder(style()));
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  button_border->SetPainter(false, STATE_HOVERED, NULL);
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  button_border->SetPainter(false, STATE_PRESSED, NULL);
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Inset the trailing side by a couple pixels for the focus border.
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  button_border->set_insets(gfx::Insets(0, 0, 0, 2));
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBorder(button_border.PassAs<Border>());
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetFocusable(true);
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unchecked/Unfocused images.
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(false, false, STATE_NORMAL,
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX));
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(false, false, STATE_HOVERED,
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_HOVER));
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(false, false, STATE_PRESSED,
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_PRESSED));
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(false, false, STATE_DISABLED,
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_DISABLED));
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Checked/Unfocused images.
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(true, false, STATE_NORMAL,
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_CHECKED));
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(true, false, STATE_HOVERED,
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_CHECKED_HOVER));
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(true, false, STATE_PRESSED,
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_CHECKED_PRESSED));
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(true, false, STATE_DISABLED,
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_CHECKED_DISABLED));
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unchecked/Focused images.
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(false, true, STATE_NORMAL,
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_FOCUSED));
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(false, true, STATE_HOVERED,
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_FOCUSED_HOVER));
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(false, true, STATE_PRESSED,
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_FOCUSED_PRESSED));
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Checked/Focused images.
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(true, true, STATE_NORMAL,
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_FOCUSED_CHECKED));
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(true, true, STATE_HOVERED,
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_FOCUSED_CHECKED_HOVER));
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetCustomImage(true, true, STATE_PRESSED,
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 *rb.GetImageSkiaNamed(IDR_CHECKBOX_FOCUSED_CHECKED_PRESSED));
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Limit the checkbox height to match the legacy appearance.
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const gfx::Size preferred_size(LabelButton::GetPreferredSize());
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetMinSize(gfx::Size(0, preferred_size.height() + 4));
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Checkbox::~Checkbox() {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Checkbox::SetChecked(bool checked) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  checked_ = checked;
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UpdateImage();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Checkbox::Layout() {
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LabelButton::Layout();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Construct a focus painter that only surrounds the label area.
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gfx::Rect rect = label()->GetMirroredBounds();
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  rect.Inset(-2, 3);
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetFocusPainter(Painter::CreateDashedFocusPainterWithInsets(
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      gfx::Insets(rect.y(), rect.x(),
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  height() - rect.bottom(),
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  width() - rect.right())));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* Checkbox::GetClassName() const {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kViewClassName;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Checkbox::GetAccessibleState(ui::AXViewState* state) {
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LabelButton::GetAccessibleState(state);
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  state->role = ui::AX_ROLE_CHECK_BOX;
100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (checked())
101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    state->AddStateFlag(ui::AX_STATE_CHECKED);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Checkbox::OnFocus() {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LabelButton::OnFocus();
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UpdateImage();
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Checkbox::OnBlur() {
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  LabelButton::OnBlur();
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UpdateImage();
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const gfx::ImageSkia& Checkbox::GetImage(ButtonState for_state) {
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const size_t checked_index = checked_ ? 1 : 0;
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const size_t focused_index = HasFocus() ? 1 : 0;
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (for_state != STATE_NORMAL &&
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      images_[checked_index][focused_index][for_state].isNull())
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return images_[checked_index][focused_index][STATE_NORMAL];
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return images_[checked_index][focused_index][for_state];
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Checkbox::SetCustomImage(bool checked,
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              bool focused,
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              ButtonState for_state,
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              const gfx::ImageSkia& image) {
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const size_t checked_index = checked ? 1 : 0;
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const size_t focused_index = focused ? 1 : 0;
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  images_[checked_index][focused_index][for_state] = image;
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UpdateImage();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Checkbox::NotifyClick(const ui::Event& event) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetChecked(!checked());
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LabelButton::NotifyClick(event);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::NativeTheme::Part Checkbox::GetThemePart() const {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui::NativeTheme::kCheckbox;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Checkbox::GetExtraParams(ui::NativeTheme::ExtraParams* params) const {
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LabelButton::GetExtraParams(params);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  params->button.checked = checked_;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace views
148