Commit 31c6ec01 authored by Tim Song's avatar Tim Song Committed by Commit Bot

Ash Tray: Add new overflow tray button for the in-app tablet shelf.

This button will be shown when the number of tray items exceeds what can fit in
the shelf normally. Click on it will show/hide the trays.

This CL just introduces the button behind a flag and it is not integrated with
the rest of the status area. That will come in later CLs.

Screenshot:
https://screenshot.googleplex.com/no5btxNAAOw

TEST=manual + stub unit tests
BUG=982511

Change-Id: I813b3f24e1c7172ca6ce0d058cd1376bf22a6bf9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1825921
Commit-Queue: Tim Song <tengs@chromium.org>
Reviewed-by: default avatarTetsui Ohkubo <tetsui@chromium.org>
Reviewed-by: default avatarAhmed Mehfooz <amehfooz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701384}
parent a79912fb
......@@ -937,6 +937,8 @@ component("ash") {
"system/tray/interacted_by_tap_recorder.h",
"system/tray/size_range_layout.cc",
"system/tray/size_range_layout.h",
"system/tray/status_area_overflow_button_tray.cc",
"system/tray/status_area_overflow_button_tray.h",
"system/tray/system_menu_button.cc",
"system/tray/system_menu_button.h",
"system/tray/system_tray_item_uma_type.h",
......@@ -1852,6 +1854,7 @@ test("ash_unittests") {
"system/toast/toast_manager_unittest.cc",
"system/tracing_notification_controller_unittest.cc",
"system/tray/size_range_layout_unittest.cc",
"system/tray/status_area_overflow_button_tray_unittest.cc",
"system/tray/tray_event_filter_unittest.cc",
"system/tray/tray_info_label_unittest.cc",
"system/tray/tri_view_unittest.cc",
......
......@@ -739,6 +739,14 @@ This file contains the strings for ash.
Toggle dictation
</message>
<message name="IDS_ASH_STATUS_AREA_OVERFLOW_BUTTON_EXPAND" desc="The accessible name for the overflow button in the status area to expand width of the status area.">
Expand status area
</message>
<message name="IDS_ASH_STATUS_AREA_OVERFLOW_BUTTON_COLLAPSE" desc="The accessible name for the overflow button in the status area to expand width of the status area.">
Collapse status area
</message>
<!-- Overview Mode -->
<message name="IDS_ASH_OVERVIEW_BUTTON_ACCESSIBLE_NAME" desc="The accessible name for the Overview button in the system tray.">
Toggle window overview
......
dc9b43f6c6ac2d778ec5ff29ca6cb41cafcfacd1
\ No newline at end of file
dc9b43f6c6ac2d778ec5ff29ca6cb41cafcfacd1
\ No newline at end of file
......@@ -15,6 +15,7 @@
#include "ash/system/palette/palette_tray.h"
#include "ash/system/session/logout_button_tray.h"
#include "ash/system/status_area_widget_delegate.h"
#include "ash/system/tray/status_area_overflow_button_tray.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/system/virtual_keyboard/virtual_keyboard_tray.h"
#include "base/i18n/time_formatting.h"
......@@ -43,6 +44,10 @@ StatusAreaWidget::StatusAreaWidget(aura::Window* status_container, Shelf* shelf)
void StatusAreaWidget::Initialize() {
// Create the child views, left to right.
overflow_button_tray_ =
std::make_unique<StatusAreaOverflowButtonTray>(shelf_);
status_area_widget_delegate_->AddChildView(overflow_button_tray_.get());
logout_button_tray_ = std::make_unique<LogoutButtonTray>(shelf_);
status_area_widget_delegate_->AddChildView(logout_button_tray_.get());
......@@ -72,6 +77,7 @@ void StatusAreaWidget::Initialize() {
status_area_widget_delegate_->UpdateLayout();
// Initialize after all trays have been created.
overflow_button_tray_->Initialize();
unified_system_tray_->Initialize();
palette_tray_->Initialize();
virtual_keyboard_tray_->Initialize();
......@@ -89,6 +95,7 @@ void StatusAreaWidget::Initialize() {
}
StatusAreaWidget::~StatusAreaWidget() {
overflow_button_tray_.reset();
unified_system_tray_.reset();
ime_menu_tray_.reset();
select_to_speak_tray_.reset();
......@@ -103,6 +110,7 @@ StatusAreaWidget::~StatusAreaWidget() {
}
void StatusAreaWidget::UpdateAfterShelfAlignmentChange() {
overflow_button_tray_->UpdateAfterShelfAlignmentChange();
unified_system_tray_->UpdateAfterShelfAlignmentChange();
logout_button_tray_->UpdateAfterShelfAlignmentChange();
virtual_keyboard_tray_->UpdateAfterShelfAlignmentChange();
......@@ -167,6 +175,7 @@ bool StatusAreaWidget::IsMessageBubbleShown() const {
}
void StatusAreaWidget::SchedulePaint() {
overview_button_tray_->SchedulePaint();
status_area_widget_delegate_->SchedulePaint();
unified_system_tray_->SchedulePaint();
virtual_keyboard_tray_->SchedulePaint();
......
......@@ -18,6 +18,7 @@ class Window;
namespace ash {
class ImeMenuTray;
class LogoutButtonTray;
class StatusAreaOverflowButtonTray;
class OverviewButtonTray;
class DictationButtonTray;
class PaletteTray;
......@@ -68,6 +69,9 @@ class ASH_EXPORT StatusAreaWidget : public views::Widget {
DictationButtonTray* dictation_button_tray() {
return dictation_button_tray_.get();
}
StatusAreaOverflowButtonTray* overflow_button_tray() {
return overflow_button_tray_.get();
}
OverviewButtonTray* overview_button_tray() {
return overview_button_tray_.get();
}
......@@ -114,6 +118,7 @@ class ASH_EXPORT StatusAreaWidget : public views::Widget {
StatusAreaWidgetDelegate* status_area_widget_delegate_;
std::unique_ptr<StatusAreaOverflowButtonTray> overflow_button_tray_;
std::unique_ptr<OverviewButtonTray> overview_button_tray_;
std::unique_ptr<DictationButtonTray> dictation_button_tray_;
std::unique_ptr<UnifiedSystemTray> unified_system_tray_;
......
// Copyright 2019 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 "ash/system/tray/status_area_overflow_button_tray.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shelf/shelf.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_container.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/view.h"
namespace ash {
namespace {
constexpr int kAnimationDurationMs = 250;
} // namespace
StatusAreaOverflowButtonTray::IconView::IconView()
: slide_animation_(std::make_unique<gfx::SlideAnimation>(this)) {
slide_animation_->Reset(1.0);
slide_animation_->SetTweenType(gfx::Tween::EASE_OUT);
slide_animation_->SetSlideDuration(
base::TimeDelta::FromMilliseconds(kAnimationDurationMs));
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
gfx::ImageSkia image = gfx::CreateVectorIcon(
kOverflowShelfLeftIcon, ShelfConfig::Get()->shelf_icon_color());
SetImage(image);
const int vertical_padding = (kTrayItemSize - image.height()) / 2;
const int horizontal_padding = (kTrayItemSize - image.width()) / 2;
SetBorder(views::CreateEmptyBorder(
gfx::Insets(vertical_padding, horizontal_padding)));
UpdateRotation();
}
StatusAreaOverflowButtonTray::IconView::~IconView() {}
void StatusAreaOverflowButtonTray::IconView::ToggleState(State state) {
slide_animation_->End();
if (state == CLICK_TO_EXPAND)
slide_animation_->Show();
else if (state == CLICK_TO_COLLAPSE)
slide_animation_->Hide();
}
void StatusAreaOverflowButtonTray::IconView::AnimationEnded(
const gfx::Animation* animation) {
UpdateRotation();
}
void StatusAreaOverflowButtonTray::IconView::AnimationProgressed(
const gfx::Animation* animation) {
UpdateRotation();
}
void StatusAreaOverflowButtonTray::IconView::AnimationCanceled(
const gfx::Animation* animation) {
UpdateRotation();
}
void StatusAreaOverflowButtonTray::IconView::UpdateRotation() {
double progress = slide_animation_->GetCurrentValue();
gfx::Transform transform;
double center = kTrayItemSize / 2.0;
transform.Translate(gfx::Vector2d(center, center));
transform.RotateAboutZAxis(180.0 * progress);
transform.Translate(gfx::Vector2d(-center, -center));
SetTransform(transform);
}
StatusAreaOverflowButtonTray::StatusAreaOverflowButtonTray(Shelf* shelf)
: TrayBackgroundView(shelf), icon_(new IconView()) {
SetInkDropMode(InkDropMode::ON);
tray_container()->AddChildView(icon_);
}
StatusAreaOverflowButtonTray::~StatusAreaOverflowButtonTray() {}
void StatusAreaOverflowButtonTray::ClickedOutsideBubble() {}
base::string16 StatusAreaOverflowButtonTray::GetAccessibleNameForTray() {
return l10n_util::GetStringUTF16(
state_ == CLICK_TO_COLLAPSE ? IDS_ASH_STATUS_AREA_OVERFLOW_BUTTON_COLLAPSE
: IDS_ASH_STATUS_AREA_OVERFLOW_BUTTON_EXPAND);
}
void StatusAreaOverflowButtonTray::HideBubbleWithView(
const TrayBubbleView* bubble_view) {}
void StatusAreaOverflowButtonTray::Initialize() {
TrayBackgroundView::Initialize();
// TODO(tengs): Make this tray button visible when the device is in tablet
// mode and the status area width exceeds the maximum desirable width.
SetVisible(false);
}
bool StatusAreaOverflowButtonTray::PerformAction(const ui::Event& event) {
// TODO(tengs): Toggle the visibility of other trays based on the button state
// and the amount of available width in the shelf.
state_ = state_ == CLICK_TO_COLLAPSE ? CLICK_TO_EXPAND : CLICK_TO_COLLAPSE;
icon_->ToggleState(state_);
return false;
}
const char* StatusAreaOverflowButtonTray::GetClassName() const {
return "StatusAreaOverflowButtonTray";
}
} // namespace ash
// Copyright 2019 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.
#ifndef ASH_SYSTEM_TRAY_STATUS_AREA_OVERFLOW_BUTTON_TRAY_H_
#define ASH_SYSTEM_TRAY_STATUS_AREA_OVERFLOW_BUTTON_TRAY_H_
#include "ash/ash_export.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/tray/tray_background_view.h"
#include "ash/system/tray/tray_bubble_view.h"
#include "ash/system/tray/tray_bubble_wrapper.h"
#include "base/macros.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/transform.h"
#include "ui/views/controls/image_view.h"
namespace gfx {
class SlideAnimation;
} // namespace gfx
namespace ash {
// The collapse/expand tray button in tablet mode, which is shown when the
// status area contains more buttons than the maximum width. Tapping on this
// button will show/hide the overflown tray buttons.
class ASH_EXPORT StatusAreaOverflowButtonTray : public TrayBackgroundView {
public:
explicit StatusAreaOverflowButtonTray(Shelf* shelf);
~StatusAreaOverflowButtonTray() override;
enum State { CLICK_TO_EXPAND = 0, CLICK_TO_COLLAPSE };
// TrayBackgroundView:
void ClickedOutsideBubble() override;
base::string16 GetAccessibleNameForTray() override;
void HideBubbleWithView(const TrayBubbleView* bubble_view) override;
void Initialize() override;
bool PerformAction(const ui::Event& event) override;
const char* GetClassName() const override;
State state() const { return state_; }
private:
// The button icon of an animating arrow based on the collapse/expand state.
class IconView : public views::ImageView, public gfx::AnimationDelegate {
public:
IconView();
~IconView() override;
void ToggleState(State state);
private:
// gfx::AnimationDelegate:
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationCanceled(const gfx::Animation* animation) override;
void UpdateRotation();
const std::unique_ptr<gfx::SlideAnimation> slide_animation_;
};
State state_ = CLICK_TO_EXPAND;
IconView* const icon_;
DISALLOW_COPY_AND_ASSIGN(StatusAreaOverflowButtonTray);
};
} // namespace ash
#endif // ASH_SYSTEM_TRAY_STATUS_AREA_OVERFLOW_BUTTON_TRAY_H_
// Copyright 2019 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 "ash/system/tray/status_area_overflow_button_tray.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/status_area_widget_test_helper.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/ash_test_helper.h"
#include "base/run_loop.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/gestures/gesture_types.h"
namespace ash {
class StatusAreaOverflowButtonTrayTest : public AshTestBase {
public:
StatusAreaOverflowButtonTrayTest() = default;
~StatusAreaOverflowButtonTrayTest() override = default;
void SetUp() override { AshTestBase::SetUp(); }
void TapButton() {
ui::GestureEvent tap_event =
ui::GestureEvent(0, 0, 0, base::TimeTicks(),
ui::GestureEventDetails(ui::ET_GESTURE_TAP));
GetTray()->PerformAction(tap_event);
}
StatusAreaOverflowButtonTray* GetTray() {
return StatusAreaWidgetTestHelper::GetStatusAreaWidget()
->overflow_button_tray();
}
private:
DISALLOW_COPY_AND_ASSIGN(StatusAreaOverflowButtonTrayTest);
};
TEST_F(StatusAreaOverflowButtonTrayTest, ToggleExpanded) {
EXPECT_EQ(StatusAreaOverflowButtonTray::CLICK_TO_EXPAND, GetTray()->state());
TapButton();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(StatusAreaOverflowButtonTray::CLICK_TO_COLLAPSE,
GetTray()->state());
TapButton();
EXPECT_EQ(StatusAreaOverflowButtonTray::CLICK_TO_EXPAND, GetTray()->state());
}
} // namespace ash
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment