Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: ash/system/toast/toast_overlay.cc

Issue 1782793002: Ash: Implement Toasts (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/system/toast/toast_overlay.h"
6
7 #include "ash/shelf/shelf.h"
8 #include "ash/shelf/shelf_layout_manager.h"
9 #include "ash/shell.h"
10 #include "ash/shell_window_ids.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "grit/ash_strings.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/compositor/scoped_layer_animation_settings.h"
17 #include "ui/gfx/canvas.h"
18 #include "ui/gfx/font_list.h"
19 #include "ui/views/border.h"
20 #include "ui/views/controls/button/label_button.h"
21 #include "ui/views/controls/label.h"
22 #include "ui/views/layout/box_layout.h"
23 #include "ui/views/view.h"
24 #include "ui/views/widget/widget.h"
25 #include "ui/views/widget/widget_delegate.h"
26
27 namespace ash {
28
29 namespace {
30
31 // Horizontal offset of the overlay from the bottom of the screen.
32 const int kVerticalOffset = 5;
33
34 // Font style used for modifier key labels.
35 const ui::ResourceBundle::FontStyle kTextFontStyle =
36 ui::ResourceBundle::MediumFont;
37
38 // Duration of slide animation when overlay is shown or hidden.
39 const int kSlideAnimationDurationMs = 100;
40
41 } // anonymous namespace
42
43 ///////////////////////////////////////////////////////////////////////////////
44 // ToastOverlayLabel
45 class ToastOverlayLabel : public views::Label {
46 public:
47 explicit ToastOverlayLabel(const std::string& label);
48 ~ToastOverlayLabel() override;
49
50 private:
51 DISALLOW_COPY_AND_ASSIGN(ToastOverlayLabel);
52 };
53
54 ToastOverlayLabel::ToastOverlayLabel(const std::string& label) {
55 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
56
57 SetText(base::UTF8ToUTF16(label));
58 SetHorizontalAlignment(gfx::ALIGN_LEFT);
59 SetFontList(rb->GetFontList(kTextFontStyle));
60 SetAutoColorReadabilityEnabled(false);
61 SetFocusable(false);
62 SetEnabledColor(SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF));
63 SetDisabledColor(SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF));
64 SetSubpixelRenderingEnabled(false);
65 }
66
67 ToastOverlayLabel::~ToastOverlayLabel() {}
68
69 ///////////////////////////////////////////////////////////////////////////////
70 // ToastOverlayButton
71 class ToastOverlayButton : public views::LabelButton {
72 public:
73 explicit ToastOverlayButton(const base::string16& label,
74 views::ButtonListener* listener);
75 ~ToastOverlayButton() override {}
76
77 private:
78 DISALLOW_COPY_AND_ASSIGN(ToastOverlayButton);
79 };
80
81 ToastOverlayButton::ToastOverlayButton(const base::string16& label,
82 views::ButtonListener* listener)
83 : views::LabelButton(listener, label) {
84 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
85
86 SetTextColor(STATE_NORMAL, SkColorSetARGB(0xFF, 0x64, 0xA5, 0xF5));
yoshiki 2016/03/11 08:40:56 FYI: These color values might be changed (I'm aski
87 SetTextColor(STATE_HOVERED, SkColorSetARGB(0xFF, 0xE3, 0xF2, 0xFD));
88 SetTextColor(STATE_PRESSED, SkColorSetARGB(0xFF, 0x64, 0xA5, 0xF5));
89 SetFontList(rb->GetFontList(kTextFontStyle));
90 SetBorder(views::Border::NullBorder());
91 }
92
93 ///////////////////////////////////////////////////////////////////////////////
94 // ToastOverlayView
95 class ToastOverlayView : public views::View, public views::ButtonListener {
96 public:
97 // This object is not owned by the views hiearchy or by the widget.
98 ToastOverlayView(ToastOverlay* overlay, const std::string& text);
99 ~ToastOverlayView() override;
100
101 // views::View overrides:
102 void OnPaint(gfx::Canvas* canvas) override;
103
104 private:
105 ToastOverlay* overlay_; // weak
106
107 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
108
109 DISALLOW_COPY_AND_ASSIGN(ToastOverlayView);
110 };
111
112 ToastOverlayView::ToastOverlayView(ToastOverlay* overlay,
113 const std::string& text)
114 : overlay_(overlay) {
115 // The parent ToastOverlay object owns this view.
116 set_owned_by_client();
117
118 const gfx::Font& font =
119 ui::ResourceBundle::GetSharedInstance().GetFont(kTextFontStyle);
120 int font_size = font.GetFontSize();
121
122 // Text should have a margin of 0.5 times the font size on each side, so
123 // the spacing between two labels will be the same as the font size.
124 int horizontal_spacing = font_size * 2;
125 int vertical_spacing = font_size;
126 int child_spacing = font_size * 4;
127
128 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
129 horizontal_spacing, vertical_spacing,
130 child_spacing));
131
132 ToastOverlayLabel* label = new ToastOverlayLabel(text);
133 AddChildView(label);
134 label->SetVisible(true);
135
136 AddChildView(new ToastOverlayButton(
137 l10n_util::GetStringUTF16(IDS_ASH_TOAST_DISMISS_BUTTON), this));
138 }
139
140 ToastOverlayView::~ToastOverlayView() {}
141
142 void ToastOverlayView::OnPaint(gfx::Canvas* canvas) {
143 SkPaint paint;
144 paint.setStyle(SkPaint::kFill_Style);
145 paint.setColor(SkColorSetARGB(0xFF, 0x32, 0x32, 0x32));
146 canvas->DrawRoundRect(GetLocalBounds(), 2, paint);
147 views::View::OnPaint(canvas);
148 }
149
150 void ToastOverlayView::ButtonPressed(views::Button* sender,
151 const ui::Event& event) {
152 overlay_->Show(false);
153 }
154
155 ///////////////////////////////////////////////////////////////////////////////
156 // ToastOverlay
157 ToastOverlay::ToastOverlay(Delegate* delegate, const std::string& text)
158 : delegate_(delegate),
159 overlay_view_(new ToastOverlayView(this, text)),
160 widget_size_(overlay_view_->GetPreferredSize()) {
161 views::Widget::InitParams params;
162 params.type = views::Widget::InitParams::TYPE_POPUP;
163 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
164 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
165 params.accept_events = true;
166 params.keep_on_top = true;
167 params.remove_standard_frame = true;
168 params.bounds = CalculateOverlayBounds();
169 // Show toasts above the app list and below the lock screen.
170 params.parent = Shell::GetContainer(Shell::GetTargetRootWindow(),
171 kShellWindowId_SystemModalContainer);
172 overlay_widget_.reset(new views::Widget);
173 overlay_widget_->Init(params);
174 overlay_widget_->SetVisibilityChangedAnimationsEnabled(false);
175 overlay_widget_->SetContentsView(overlay_view_.get());
176 overlay_widget_->GetNativeView()->SetName("ToastOverlay");
177 }
178
179 ToastOverlay::~ToastOverlay() {
180 // Remove ourself from the animator to avoid being re-entrantly called in
181 // |overlay_widget_|'s destructor.
182 ui::Layer* layer = overlay_widget_->GetLayer();
183 if (layer) {
184 ui::LayerAnimator* animator = layer->GetAnimator();
185 if (animator)
186 animator->RemoveObserver(this);
187 }
188 }
189
190 void ToastOverlay::Show(bool visible) {
191 if (is_visible_ == visible)
192 return;
193
194 is_visible_ = visible;
195 if (is_visible_)
196 overlay_widget_->Show();
197 overlay_widget_->SetBounds(CalculateOverlayBounds());
198
199 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
200 animator->AddObserver(this);
201
202 gfx::Transform hidden_transform;
203 hidden_transform.Translate(0, (widget_size_.height() + kVerticalOffset));
204
205 // Ensure transform is correct before beginning animation.
206 if (!animator->is_animating()) {
207 if (visible)
208 overlay_widget_->GetLayer()->SetTransform(hidden_transform);
209 else
210 overlay_widget_->GetLayer()->SetTransform(gfx::Transform());
211 }
212
213 ui::ScopedLayerAnimationSettings settings(animator);
214 settings.SetPreemptionStrategy(
215 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
216 settings.SetTweenType(visible ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN);
217 settings.SetTransitionDuration(
218 base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs));
219
220 if (visible)
221 overlay_widget_->GetLayer()->SetTransform(gfx::Transform());
222 else
223 overlay_widget_->GetLayer()->SetTransform(hidden_transform);
224 }
225
226 gfx::Rect ToastOverlay::CalculateOverlayBounds() {
227 ShelfLayoutManager* shelf_layout_manager =
228 Shelf::ForPrimaryDisplay()->shelf_layout_manager();
229 gfx::Rect root_bounds = Shell::GetPrimaryRootWindow()->bounds();
230 int bottom = (shelf_layout_manager->GetAlignment() == SHELF_ALIGNMENT_BOTTOM)
231 ? shelf_layout_manager->GetIdealBounds().y()
232 : root_bounds.height();
233
234 return gfx::Rect(gfx::Point((root_bounds.width() - widget_size_.width()) / 2,
235 bottom - widget_size_.height() - kVerticalOffset),
236 widget_size_);
237 }
238
239 void ToastOverlay::OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) {
240 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
241 if (animator)
242 animator->RemoveObserver(this);
243 if (!is_visible_) {
244 overlay_widget_->Hide();
245 delegate_->OnClosed();
246 }
247 }
248
249 void ToastOverlay::OnLayerAnimationAborted(
250 ui::LayerAnimationSequence* sequence) {
251 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
252 if (animator)
253 animator->RemoveObserver(this);
254 }
255
256 void ToastOverlay::OnLayerAnimationScheduled(
257 ui::LayerAnimationSequence* sequence) {}
258
259 } // namespace ash
OLDNEW
« ash/system/toast/toast_manager.cc ('K') | « ash/system/toast/toast_overlay.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698