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

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: addressed the comment 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
« no previous file with comments | « ash/system/toast/toast_overlay.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/screen_util.h"
8 #include "ash/shelf/shelf.h"
9 #include "ash/shelf/shelf_layout_manager.h"
10 #include "ash/shell.h"
11 #include "ash/shell_window_ids.h"
12 #include "ash/wm/window_animations.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "grit/ash_strings.h"
17 #include "third_party/skia/include/core/SkColor.h"
18 #include "ui/base/l10n/l10n_util.h"
19 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/gfx/canvas.h"
21 #include "ui/gfx/font_list.h"
22 #include "ui/views/border.h"
23 #include "ui/views/controls/button/label_button.h"
24 #include "ui/views/controls/label.h"
25 #include "ui/views/layout/box_layout.h"
26 #include "ui/views/view.h"
27 #include "ui/views/widget/widget.h"
28 #include "ui/views/widget/widget_delegate.h"
29
30 namespace ash {
31
32 namespace {
33
34 // Horizontal offset of the overlay from the bottom of the screen.
35 const int kVerticalOffset = 5;
36
37 // Font style used for modifier key labels.
38 const ui::ResourceBundle::FontStyle kTextFontStyle =
39 ui::ResourceBundle::MediumFont;
40
41 // Duration of slide animation when overlay is shown or hidden.
42 const int kSlideAnimationDurationMs = 100;
43
44 // Colors for the dismiss button.
45 const SkColor kButtonBackgroundColor = SkColorSetARGB(0xFF, 0x32, 0x32, 0x32);
46 const SkColor kNormalButtonColor = SkColorSetARGB(0xFF, 0x64, 0xA5, 0xF5);
47 const SkColor kHoveredButtonColor = SkColorSetARGB(0xFF, 0xE3, 0xF2, 0xFD);
48 const SkColor kPressedButtonColor = SkColorSetARGB(0xFF, 0x64, 0xA5, 0xF5);
49
50 } // anonymous namespace
51
52 ///////////////////////////////////////////////////////////////////////////////
53 // ToastOverlayLabel
54 class ToastOverlayLabel : public views::Label {
55 public:
56 explicit ToastOverlayLabel(const std::string& label);
57 ~ToastOverlayLabel() override;
58
59 private:
60 DISALLOW_COPY_AND_ASSIGN(ToastOverlayLabel);
61 };
62
63 ToastOverlayLabel::ToastOverlayLabel(const std::string& label) {
64 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
65
66 SetText(base::UTF8ToUTF16(label));
67 SetHorizontalAlignment(gfx::ALIGN_LEFT);
68 SetFontList(rb->GetFontList(kTextFontStyle));
69 SetAutoColorReadabilityEnabled(false);
70 SetFocusable(false);
71 SetEnabledColor(SK_ColorWHITE);
72 SetDisabledColor(SK_ColorWHITE);
73 SetSubpixelRenderingEnabled(false);
74 }
75
76 ToastOverlayLabel::~ToastOverlayLabel() {}
77
78 ///////////////////////////////////////////////////////////////////////////////
79 // ToastOverlayButton
80 class ToastOverlayButton : public views::LabelButton {
81 public:
82 explicit ToastOverlayButton(views::ButtonListener* listener,
83 const base::string16& label);
84 ~ToastOverlayButton() override {}
85
86 private:
87 friend class ToastOverlay; // for ToastOverlay::ClickDismissButtonForTesting.
88
89 DISALLOW_COPY_AND_ASSIGN(ToastOverlayButton);
90 };
91
92 ToastOverlayButton::ToastOverlayButton(views::ButtonListener* listener,
93 const base::string16& label)
94 : views::LabelButton(listener, label) {
95 ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
96
97 SetTextColor(STATE_NORMAL, kNormalButtonColor);
98 SetTextColor(STATE_HOVERED, kHoveredButtonColor);
99 SetTextColor(STATE_PRESSED, kPressedButtonColor);
100 SetFontList(rb->GetFontList(kTextFontStyle));
101 SetBorder(views::Border::NullBorder());
102 }
103
104 ///////////////////////////////////////////////////////////////////////////////
105 // ToastOverlayView
106 class ToastOverlayView : public views::View, public views::ButtonListener {
107 public:
108 // This object is not owned by the views hiearchy or by the widget.
109 ToastOverlayView(ToastOverlay* overlay, const std::string& text);
110 ~ToastOverlayView() override;
111
112 // views::View overrides:
113 void OnPaint(gfx::Canvas* canvas) override;
114
115 ToastOverlayButton* button() { return button_; }
116
117 private:
118 ToastOverlay* overlay_; // weak
119 ToastOverlayButton* button_; // weak
120
121 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
122
123 DISALLOW_COPY_AND_ASSIGN(ToastOverlayView);
124 };
125
126 ToastOverlayView::ToastOverlayView(ToastOverlay* overlay,
127 const std::string& text)
128 : overlay_(overlay),
129 button_(new ToastOverlayButton(
130 this,
131 l10n_util::GetStringUTF16(IDS_ASH_TOAST_DISMISS_BUTTON))) {
132 const gfx::Font& font =
133 ui::ResourceBundle::GetSharedInstance().GetFont(kTextFontStyle);
134 int font_size = font.GetFontSize();
135
136 // Text should have a margin of 0.5 times the font size on each side, so
137 // the spacing between two labels will be the same as the font size.
138 int horizontal_spacing = font_size * 2;
139 int vertical_spacing = font_size;
140 int child_spacing = font_size * 4;
141
142 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
143 horizontal_spacing, vertical_spacing,
144 child_spacing));
145
146 ToastOverlayLabel* label = new ToastOverlayLabel(text);
147 AddChildView(label);
148 label->SetVisible(true);
149
150 AddChildView(button_);
151 }
152
153 ToastOverlayView::~ToastOverlayView() {}
154
155 void ToastOverlayView::OnPaint(gfx::Canvas* canvas) {
156 SkPaint paint;
157 paint.setStyle(SkPaint::kFill_Style);
158 paint.setColor(kButtonBackgroundColor);
159 canvas->DrawRoundRect(GetLocalBounds(), 2, paint);
160 views::View::OnPaint(canvas);
161 }
162
163 void ToastOverlayView::ButtonPressed(views::Button* sender,
164 const ui::Event& event) {
165 overlay_->Show(false);
166 }
167
168 ///////////////////////////////////////////////////////////////////////////////
169 // ToastOverlay
170 ToastOverlay::ToastOverlay(Delegate* delegate, const std::string& text)
171 : delegate_(delegate),
172 text_(text),
173 overlay_view_(new ToastOverlayView(this, text)),
174 widget_size_(overlay_view_->GetPreferredSize()) {
175 views::Widget::InitParams params;
176 params.type = views::Widget::InitParams::TYPE_POPUP;
177 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
178 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
179 params.accept_events = true;
180 params.keep_on_top = true;
181 params.remove_standard_frame = true;
182 params.bounds = CalculateOverlayBounds();
183 // Show toasts above the app list and below the lock screen.
184 params.parent = Shell::GetContainer(Shell::GetTargetRootWindow(),
185 kShellWindowId_SystemModalContainer);
186 overlay_widget_.reset(new views::Widget);
187 overlay_widget_->Init(params);
188 overlay_widget_->SetVisibilityChangedAnimationsEnabled(true);
189 overlay_widget_->SetContentsView(overlay_view_.get());
190 overlay_widget_->SetBounds(CalculateOverlayBounds());
191 overlay_widget_->GetNativeView()->SetName("ToastOverlay");
192
193 gfx::NativeWindow native_view = overlay_widget_->GetNativeView();
194 wm::SetWindowVisibilityAnimationType(
195 native_view, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL);
196 wm::SetWindowVisibilityAnimationDuration(
197 native_view,
198 base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs));
199 }
200
201 ToastOverlay::~ToastOverlay() {
202 gfx::NativeWindow native_view = overlay_widget_->GetNativeView();
203 wm::SetWindowVisibilityAnimationTransition(native_view, wm::ANIMATE_NONE);
204
205 // Remove ourself from the animator to avoid being re-entrantly called in
206 // |overlay_widget_|'s destructor.
207 ui::Layer* layer = overlay_widget_->GetLayer();
208 if (layer) {
209 ui::LayerAnimator* animator = layer->GetAnimator();
210 if (animator)
211 animator->RemoveObserver(this);
212 }
213
214 overlay_widget_->Close();
215 }
216
217 void ToastOverlay::Show(bool visible) {
218 if (is_visible_ == visible)
219 return;
220
221 is_visible_ = visible;
222
223 overlay_widget_->GetLayer()->GetAnimator()->AddObserver(this);
224
225 if (is_visible_)
226 overlay_widget_->Show();
227 else
228 overlay_widget_->Hide();
229 }
230
231 gfx::Rect ToastOverlay::CalculateOverlayBounds() {
232 ShelfLayoutManager* shelf_layout_manager =
233 Shelf::ForPrimaryDisplay()->shelf_layout_manager();
234 gfx::Rect work_area_bounds = shelf_layout_manager->user_work_area_bounds();
235
236 gfx::Rect bounds = shelf_layout_manager->user_work_area_bounds();
237 int target_y = bounds.bottom() - widget_size_.height() - kVerticalOffset;
238 bounds.ClampToCenteredSize(widget_size_);
239 bounds.set_y(target_y);
240 return bounds;
241 }
242
243 void ToastOverlay::OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) {
244 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
245 if (animator)
246 animator->RemoveObserver(this);
247 if (!is_visible_) {
248 // Acync operation, since delegate may remove this instance and removing
249 // this here causes crash.
250 base::ThreadTaskRunnerHandle::Get()->PostTask(
251 FROM_HERE,
252 base::Bind(&Delegate::OnClosed,
253 base::Unretained(delegate_) /* |delegate| lives longer */));
254 }
255 }
256
257 void ToastOverlay::OnLayerAnimationAborted(
258 ui::LayerAnimationSequence* sequence) {
259 ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
260 if (animator)
261 animator->RemoveObserver(this);
262 }
263
264 void ToastOverlay::OnLayerAnimationScheduled(
265 ui::LayerAnimationSequence* sequence) {}
266
267 views::Widget* ToastOverlay::widget_for_testing() {
268 return overlay_widget_.get();
269 }
270
271 void ToastOverlay::ClickDismissButtonForTesting(const ui::Event& event) {
272 overlay_view_->button()->NotifyClick(event);
273 }
274
275 } // namespace ash
OLDNEW
« no previous file with comments | « ash/system/toast/toast_overlay.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698