Skip to content

Commit

Permalink
[ash-md] Allows ToggleButton to have a border and adds focus rectangle
Browse files Browse the repository at this point in the history
- Allows ToggleButton to accept a border set externally.
- Allows ToggleButton to have a tooltip that includes ThumbView.
- Adds TrayPopupUtils::CreateToggleButton to set up ToggleButtons for
  use in system menu.
- Uses TrayPopupUtils::CreateToggleButton in IME, Bluetooth and Network
  pages.

BUG=652492
TEST=manual
  Bring focus using Tab to a toggle button in Network detailed page.
  (focus rectangle appears).
  Press Space (toggle switches)
  Press Enter (toggle switches)
  Tab (focus switches to the next row).

Review-Url: https://codereview.chromium.org/2506133003
Cr-Commit-Position: refs/heads/master@{#433386}
(cherry picked from commit 9bd7f8c)

Review URL: https://codereview.chromium.org/2520793002 .

Cr-Commit-Position: refs/branch-heads/2924@{#17}
Cr-Branched-From: 3a87aec-refs/heads/master@{#433059}
  • Loading branch information
Valery Arkhangorodsky committed Nov 21, 2016
1 parent 9144019 commit 7061f7f
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 47 deletions.
9 changes: 2 additions & 7 deletions ash/common/system/chromeos/bluetooth/tray_bluetooth.cc
Original file line number Diff line number Diff line change
Expand Up @@ -542,13 +542,8 @@ class BluetoothDetailedView : public TrayDetailsView {

tri_view()->SetContainerVisible(TriView::Container::END, true);

// TODO(tdanderson): Move common toggle-creation logic to TrayPopupUtils.
// See crbug.com/614453.
toggle_ = new views::ToggleButton(this);
toggle_->SetFocusForPlatform();
toggle_->SetAccessibleName(
ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
IDS_ASH_STATUS_TRAY_BLUETOOTH));
toggle_ = TrayPopupUtils::CreateToggleButton(
this, IDS_ASH_STATUS_TRAY_BLUETOOTH);
tri_view()->AddView(TriView::Container::END, toggle_);

settings_ = CreateSettingsButton(login_);
Expand Down
7 changes: 2 additions & 5 deletions ash/common/system/chromeos/ime_menu/ime_list_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -223,11 +223,8 @@ class MaterialKeyboardStatusRowView : public views::View {
tri_view->AddView(TriView::Container::CENTER, label_);

// The on-screen keyboard toggle button.
toggle_ = new views::ToggleButton(listener_);
toggle_->SetFocusForPlatform();
toggle_->SetAccessibleName(
ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD));
toggle_ = TrayPopupUtils::CreateToggleButton(
listener_, IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD);
tri_view->AddView(TriView::Container::END, toggle_);
}

Expand Down
16 changes: 5 additions & 11 deletions ash/common/system/chromeos/network/network_list_md.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ namespace {
const int kSectionHeaderRowSize = 48;
const int kSectionHeaderRowVerticalInset = 4;
const int kSectionHeaderRowLeftInset = 18;
const int kSectionHeaderRowRightInset = 14;
const int kSectionHeaderRowChildSpacing = 14;

bool IsProhibitedByPolicy(const chromeos::NetworkState* network) {
if (!NetworkTypePattern::WiFi().MatchesType(network->type()))
Expand Down Expand Up @@ -134,14 +132,14 @@ class NetworkListViewMd::SectionHeaderRowView : public views::View,
// https://crbug.com/614453.
TrayPopupUtils::ConfigureAsStickyHeader(this);
container_ = new views::View;
container_->SetBorder(views::CreateEmptyBorder(
0, kSectionHeaderRowLeftInset, 0, kSectionHeaderRowRightInset));
container_->SetBorder(
views::CreateEmptyBorder(0, kSectionHeaderRowLeftInset, 0, 0));
views::FillLayout* layout = new views::FillLayout;
SetLayoutManager(layout);
AddChildView(container_);

views::BoxLayout* container_layout = new views::BoxLayout(
views::BoxLayout::kHorizontal, 0, 0, kSectionHeaderRowChildSpacing);
views::BoxLayout* container_layout =
new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0);
container_layout->set_cross_axis_alignment(
views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
container_->SetLayoutManager(container_layout);
Expand All @@ -160,12 +158,8 @@ class NetworkListViewMd::SectionHeaderRowView : public views::View,
}

void AddToggleButton(bool enabled) {
toggle_ = new views::ToggleButton(this);
toggle_->SetAccessibleName(l10n_util::GetStringUTF16(title_id_));
toggle_ = TrayPopupUtils::CreateToggleButton(this, title_id_);
toggle_->SetIsOn(enabled, false);
// TODO(varkha): Implement focus painter for toggle. See
// https://crbug.com/652677 for context.
toggle_->SetFocusForPlatform();
container_->AddChildView(toggle_);
}

Expand Down
2 changes: 2 additions & 0 deletions ash/common/system/tray/tray_constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const SkColor kTrayPopupHoverBackgroundColor = SkColorSetRGB(0xe4, 0xe4, 0xe4);
const int kTrayPopupScrollSeparatorHeight = 15;
const int kTrayRoundedBorderRadius = 2;

const int kTrayToggleButtonWidth = 68;

const SkColor kBackgroundColor = SkColorSetRGB(0xfe, 0xfe, 0xfe);
const SkColor kHoverBackgroundColor = SkColorSetRGB(0xf3, 0xf3, 0xf3);
const SkColor kPublicAccountBackgroundColor = SkColorSetRGB(0xf8, 0xe5, 0xb6);
Expand Down
3 changes: 3 additions & 0 deletions ash/common/system/tray/tray_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ extern const int kTrayRoundedBorderRadius;
// The padding used on the left and right of labels.
extern const int kTrayPopupLabelHorizontalPadding;

// The width of ToggleButton views including any border padding.
extern const int kTrayToggleButtonWidth;

extern const SkColor kBackgroundColor;
extern const SkColor kHoverBackgroundColor;
extern const SkColor kPublicAccountBackgroundColor;
Expand Down
21 changes: 21 additions & 0 deletions ash/common/system/tray/tray_popup_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "ash/common/system/tray/tray_popup_label_button.h"
#include "ash/common/system/tray/tray_popup_label_button_border.h"
#include "ash/common/wm_shell.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
#include "ui/views/animation/ink_drop_highlight.h"
#include "ui/views/animation/ink_drop_impl.h"
Expand All @@ -25,12 +26,14 @@
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/button/toggle_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/separator.h"
#include "ui/views/controls/slider.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/painter.h"

namespace ash {

Expand Down Expand Up @@ -251,6 +254,24 @@ views::Slider* TrayPopupUtils::CreateSlider(views::SliderListener* listener) {
return slider;
}

views::ToggleButton* TrayPopupUtils::CreateToggleButton(
views::ButtonListener* listener,
int accessible_name_id) {
views::ToggleButton* toggle = new views::ToggleButton(listener);
const gfx::Size toggle_size(toggle->GetPreferredSize());
const int vertical_padding = (kMenuButtonSize - toggle_size.height()) / 2;
const int horizontal_padding =
(kTrayToggleButtonWidth - toggle_size.width()) / 2;
toggle->SetBorder(views::CreateEmptyBorder(
gfx::Insets(vertical_padding, horizontal_padding)));
// TODO(tdanderson): Update the focus rect color, border thickness, and
// location for material design.
toggle->SetFocusPainter(views::Painter::CreateSolidFocusPainter(
kFocusBorderColor, gfx::Insets(1)));
toggle->SetAccessibleName(l10n_util::GetStringUTF16(accessible_name_id));
return toggle;
}

void TrayPopupUtils::ConfigureAsStickyHeader(views::View* view) {
view->set_id(VIEW_ID_STICKY_HEADER);
view->set_background(
Expand Down
6 changes: 6 additions & 0 deletions ash/common/system/tray/tray_popup_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class LayoutManager;
class Separator;
class Slider;
class SliderListener;
class ToggleButton;
} // namespace views

namespace ash {
Expand Down Expand Up @@ -91,6 +92,11 @@ class TrayPopupUtils {
// with a FillLayout.
static views::Slider* CreateSlider(views::SliderListener* listener);

// Returns a ToggleButton that has been configured for system menu layout.
static views::ToggleButton* CreateToggleButton(
views::ButtonListener* listener,
int accessible_name_id);

// Sets up |view| to be a sticky header in a tray detail scroll view.
static void ConfigureAsStickyHeader(views::View* view);

Expand Down
72 changes: 52 additions & 20 deletions ui/views/controls/button/toggle_button.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/animation/ink_drop_ripple.h"
#include "ui/views/border.h"
#include "ui/views/painter.h"

namespace views {

Expand All @@ -24,11 +26,8 @@ const int kTrackWidth = 28;
// Margins from edge of track to edge of view.
const int kTrackVerticalMargin = 5;
const int kTrackHorizontalMargin = 6;
// Margin from edge of thumb to closest edge of view. Note that the thumb
// margins must be sufficiently large to allow space for the shadow.
const int kThumbHorizontalMargin = 4;
// Margin from top/bottom edge of thumb to top/bottom edge of view.
const int kThumbVerticalMargin = 3;
// Inset from the rounded edge of the thumb to the rounded edge of the track.
const int kThumbInset = 2;

} // namespace

Expand All @@ -51,6 +50,13 @@ class ToggleButton::ThumbView : public InkDropHostView {
.Offset(gfx::Vector2d(kShadowOffsetX, kShadowOffsetY));
}

protected:
// views::View:
bool CanProcessEventsWithinSubtree() const override {
// Make the thumb behave as part of the parent for event handling.
return false;
}

private:
static const int kShadowOffsetX = 0;
static const int kShadowOffsetY = 1;
Expand Down Expand Up @@ -108,10 +114,9 @@ ToggleButton::ToggleButton(ButtonListener* listener)
thumb_view_(new ThumbView()) {
slide_animation_.SetSlideDuration(80 /* ms */);
slide_animation_.SetTweenType(gfx::Tween::LINEAR);
SetBorder(CreateEmptyBorder(
gfx::Insets(kTrackVerticalMargin, kTrackHorizontalMargin)));
AddChildView(thumb_view_);
SetInkDropMode(InkDropMode::ON);
SetFocusForPlatform();
set_has_ink_drop_action_on_click(true);
}

Expand All @@ -136,9 +141,27 @@ void ToggleButton::SetIsOn(bool is_on, bool animate) {
}
}

void ToggleButton::SetFocusPainter(std::unique_ptr<Painter> focus_painter) {
focus_painter_ = std::move(focus_painter);
}

gfx::Size ToggleButton::GetPreferredSize() const {
gfx::Rect rect(kTrackWidth, kTrackHeight);
rect.Inset(gfx::Insets(-kTrackVerticalMargin, -kTrackHorizontalMargin));
if (border())
rect.Inset(-border()->GetInsets());
return rect.size();
}

gfx::Rect ToggleButton::GetTrackBounds() const {
gfx::Rect track_bounds(GetContentsBounds());
track_bounds.ClampToCenteredSize(gfx::Size(kTrackWidth, kTrackHeight));
return track_bounds;
}

gfx::Rect ToggleButton::GetThumbBounds() const {
gfx::Rect thumb_bounds = GetLocalBounds();
thumb_bounds.Inset(gfx::Insets(kThumbVerticalMargin, kThumbHorizontalMargin));
gfx::Rect thumb_bounds(GetTrackBounds());
thumb_bounds.Inset(gfx::Insets(-kThumbInset));
thumb_bounds.set_x(thumb_bounds.x() +
slide_animation_.GetCurrentValue() *
(thumb_bounds.width() - thumb_bounds.height()));
Expand All @@ -161,22 +184,16 @@ SkColor ToggleButton::GetTrackColor(bool is_on) const {
return SkColorSetA(GetNativeTheme()->GetSystemColor(color_id), kTrackAlpha);
}

gfx::Size ToggleButton::GetPreferredSize() const {
gfx::Rect rect(0, 0, kTrackWidth, kTrackHeight);
if (border())
rect.Inset(-border()->GetInsets());
return rect.size();
}

const char* ToggleButton::GetClassName() const {
return kViewClassName;
}

void ToggleButton::OnPaint(gfx::Canvas* canvas) {
// Paint the toggle track. To look sharp even at fractional scale factors,
// round up to pixel boundaries.
canvas->Save();
float dsf = canvas->UndoDeviceScaleFactor();
gfx::RectF track_rect(GetContentsBounds());
gfx::RectF track_rect(GetTrackBounds());
track_rect.Scale(dsf);
track_rect = gfx::RectF(gfx::ToEnclosingRect(track_rect));
SkPaint track_paint;
Expand All @@ -186,11 +203,21 @@ void ToggleButton::OnPaint(gfx::Canvas* canvas) {
GetTrackColor(true), GetTrackColor(false),
static_cast<SkAlpha>(SK_AlphaOPAQUE * color_ratio)));
canvas->DrawRoundRect(track_rect, track_rect.height() / 2, track_paint);
canvas->Restore();

Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
}

void ToggleButton::NotifyClick(const ui::Event& event) {
SetIsOn(!is_on(), true);
CustomButton::NotifyClick(event);
void ToggleButton::OnFocus() {
CustomButton::OnFocus();
if (focus_painter_)
SchedulePaint();
}

void ToggleButton::OnBlur() {
CustomButton::OnBlur();
if (focus_painter_)
SchedulePaint();
}

void ToggleButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
Expand All @@ -209,6 +236,11 @@ void ToggleButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->AddStateFlag(ui::AX_STATE_CHECKED);
}

void ToggleButton::NotifyClick(const ui::Event& event) {
SetIsOn(!is_on(), true);
CustomButton::NotifyClick(event);
}

void ToggleButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
thumb_view_->AddInkDropLayer(ink_drop_layer);
}
Expand Down
22 changes: 18 additions & 4 deletions ui/views/controls/button/toggle_button.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

namespace views {

class Painter;

// This view presents a button that has two states: on and off. This is similar
// to a checkbox but has no text and looks more like a two-state horizontal
// slider.
Expand All @@ -23,26 +25,37 @@ class VIEWS_EXPORT ToggleButton : public CustomButton {
void SetIsOn(bool is_on, bool animate);
bool is_on() const { return is_on_; }

void SetFocusPainter(std::unique_ptr<Painter> focus_painter);

// views::View:
gfx::Size GetPreferredSize() const override;

private:
friend class TestToggleButton;
class ThumbView;

// Calculates the bounding box for the thumb (the circle).
// Calculates and returns the bounding box for the track.
gfx::Rect GetTrackBounds() const;

// Calculates and returns the bounding box for the thumb (the circle).
gfx::Rect GetThumbBounds() const;

// Updates position and color of the thumb.
void UpdateThumb();

SkColor GetTrackColor(bool is_on) const;

// CustomButton:
gfx::Size GetPreferredSize() const override;
// views::View:
const char* GetClassName() const override;
void OnPaint(gfx::Canvas* canvas) override;
void NotifyClick(const ui::Event& event) override;
void OnFocus() override;
void OnBlur() override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;

// CustomButton:
void NotifyClick(const ui::Event& event) override;
void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
std::unique_ptr<InkDrop> CreateInkDrop() override;
Expand All @@ -55,6 +68,7 @@ class VIEWS_EXPORT ToggleButton : public CustomButton {
bool is_on_;
gfx::SlideAnimation slide_animation_;
ThumbView* thumb_view_;
std::unique_ptr<Painter> focus_painter_;

DISALLOW_COPY_AND_ASSIGN(ToggleButton);
};
Expand Down

0 comments on commit 7061f7f

Please sign in to comment.