[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / ui / views / screen_capture_notification_ui_views.cc
blob7df47f44c92ba3ce54b5f8c0b39fa5356e9b296f
1 // Copyright 2013 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.
5 #include "chrome/browser/ui/screen_capture_notification_ui.h"
7 #include "ash/shell.h"
8 #include "chrome/app/chrome_dll_resource.h"
9 #include "chrome/browser/ui/views/chrome_views_export.h"
10 #include "grit/generated_resources.h"
11 #include "grit/theme_resources.h"
12 #include "ui/aura/window_event_dispatcher.h"
13 #include "ui/base/hit_test.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/views/bubble/bubble_border.h"
17 #include "ui/views/bubble/bubble_frame_view.h"
18 #include "ui/views/controls/button/blue_button.h"
19 #include "ui/views/controls/image_view.h"
20 #include "ui/views/controls/link.h"
21 #include "ui/views/controls/link_listener.h"
22 #include "ui/views/view.h"
23 #include "ui/views/widget/widget.h"
24 #include "ui/views/widget/widget_delegate.h"
25 #include "ui/wm/core/shadow_types.h"
27 #if defined(OS_WIN)
28 #include "ui/views/win/hwnd_util.h"
29 #endif
31 namespace {
33 const int kMinimumWidth = 460;
34 const int kMaximumWidth = 1000;
35 const int kHorizontalMargin = 10;
36 const float kWindowAlphaValue = 0.85f;
37 const int kPaddingVertical = 5;
38 const int kPaddingHorizontal = 10;
40 namespace {
42 // A ClientView that overrides NonClientHitTest() so that the whole window area
43 // acts as a window caption, except a rect specified using set_client_rect().
44 // ScreenCaptureNotificationUIViews uses this class to make the notification bar
45 // draggable.
46 class NotificationBarClientView : public views::ClientView {
47 public:
48 NotificationBarClientView(views::Widget* widget, views::View* view)
49 : views::ClientView(widget, view) {
51 virtual ~NotificationBarClientView() {}
53 void set_client_rect(const gfx::Rect& rect) { rect_ = rect; }
55 // views::ClientView overrides.
56 virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
57 if (!bounds().Contains(point))
58 return HTNOWHERE;
59 // The whole window is HTCAPTION, except the |rect_|.
60 if (rect_.Contains(gfx::PointAtOffsetFromOrigin(point - bounds().origin())))
61 return HTCLIENT;
63 return HTCAPTION;
66 private:
67 gfx::Rect rect_;
69 DISALLOW_COPY_AND_ASSIGN(NotificationBarClientView);
72 } // namespace
74 // ScreenCaptureNotificationUI implementation using Views.
75 class ScreenCaptureNotificationUIViews
76 : public ScreenCaptureNotificationUI,
77 public views::WidgetDelegateView,
78 public views::ButtonListener,
79 public views::LinkListener {
80 public:
81 explicit ScreenCaptureNotificationUIViews(const base::string16& text);
82 virtual ~ScreenCaptureNotificationUIViews();
84 // ScreenCaptureNotificationUI interface.
85 virtual gfx::NativeViewId OnStarted(const base::Closure& stop_callback)
86 OVERRIDE;
88 // views::View overrides.
89 virtual gfx::Size GetPreferredSize() const OVERRIDE;
90 virtual void Layout() OVERRIDE;
92 // views::WidgetDelegateView overrides.
93 virtual void DeleteDelegate() OVERRIDE;
94 virtual views::View* GetContentsView() OVERRIDE;
95 virtual views::ClientView* CreateClientView(views::Widget* widget) OVERRIDE;
96 virtual views::NonClientFrameView* CreateNonClientFrameView(
97 views::Widget* widget) OVERRIDE;
98 virtual base::string16 GetWindowTitle() const OVERRIDE;
99 virtual bool ShouldShowWindowTitle() const OVERRIDE;
100 virtual bool ShouldShowCloseButton() const OVERRIDE;
101 virtual bool CanActivate() const OVERRIDE;
103 // views::ButtonListener interface.
104 virtual void ButtonPressed(views::Button* sender,
105 const ui::Event& event) OVERRIDE;
107 // views::LinkListener interface.
108 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
110 private:
111 // Helper to call |stop_callback_|.
112 void NotifyStopped();
114 const base::string16 text_;
115 base::Closure stop_callback_;
116 NotificationBarClientView* client_view_;
117 views::ImageView* gripper_;
118 views::Label* label_;
119 views::BlueButton* stop_button_;
120 views::Link* hide_link_;
122 DISALLOW_COPY_AND_ASSIGN(ScreenCaptureNotificationUIViews);
125 ScreenCaptureNotificationUIViews::ScreenCaptureNotificationUIViews(
126 const base::string16& text)
127 : text_(text),
128 client_view_(NULL),
129 gripper_(NULL),
130 label_(NULL),
131 stop_button_(NULL),
132 hide_link_(NULL) {
133 set_owned_by_client();
135 gripper_ = new views::ImageView();
136 gripper_->SetImage(
137 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
138 IDR_SCREEN_CAPTURE_NOTIFICATION_GRIP));
139 AddChildView(gripper_);
141 label_ = new views::Label();
142 AddChildView(label_);
144 base::string16 stop_text =
145 l10n_util::GetStringUTF16(IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_STOP);
146 stop_button_ = new views::BlueButton(this, stop_text);
147 AddChildView(stop_button_);
149 // TODO(jiayl): IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON is used for the need to
150 // merge to M34. Change it to a new IDS_ after the merge.
151 hide_link_ = new views::Link(
152 l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON));
153 hide_link_->set_listener(this);
154 hide_link_->SetUnderline(false);
155 AddChildView(hide_link_);
158 ScreenCaptureNotificationUIViews::~ScreenCaptureNotificationUIViews() {
159 stop_callback_.Reset();
160 delete GetWidget();
163 gfx::NativeViewId ScreenCaptureNotificationUIViews::OnStarted(
164 const base::Closure& stop_callback) {
165 stop_callback_ = stop_callback;
167 label_->SetElideBehavior(views::Label::ELIDE_IN_MIDDLE);
168 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
169 label_->SetText(text_);
171 views::Widget* widget = new views::Widget;
173 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
174 params.delegate = this;
175 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
176 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
177 params.remove_standard_frame = true;
178 params.keep_on_top = true;
179 params.top_level = true;
181 #if defined(USE_ASH)
182 // TODO(sergeyu): The notification bar must be shown on the monitor that's
183 // being captured. Make sure it's always the case. Currently we always capture
184 // the primary monitor.
185 if (ash::Shell::HasInstance())
186 params.context = ash::Shell::GetPrimaryRootWindow();
187 #endif
189 widget->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM);
190 widget->Init(params);
191 widget->SetAlwaysOnTop(true);
193 set_background(views::Background::CreateSolidBackground(GetNativeTheme()->
194 GetSystemColor(ui::NativeTheme::kColorId_DialogBackground)));
196 gfx::Screen* screen = gfx::Screen::GetNativeScreen();
197 // TODO(sergeyu): Move the notification to the display being captured when
198 // per-display screen capture is supported.
199 gfx::Rect work_area = screen->GetPrimaryDisplay().work_area();
201 // Place the bar in the center of the bottom of the display.
202 gfx::Size size = widget->non_client_view()->GetPreferredSize();
203 gfx::Rect bounds(
204 work_area.x() + work_area.width() / 2 - size.width() / 2,
205 work_area.y() + work_area.height() - size.height(),
206 size.width(), size.height());
207 widget->SetBounds(bounds);
208 widget->Show();
209 // This has to be called after Show() to have effect.
210 widget->SetOpacity(0xFF * kWindowAlphaValue);
212 #if defined(OS_WIN)
213 return gfx::NativeViewId(views::HWNDForWidget(widget));
214 #else
215 return 0;
216 #endif
219 gfx::Size ScreenCaptureNotificationUIViews::GetPreferredSize() const {
220 gfx::Size grip_size = gripper_->GetPreferredSize();
221 gfx::Size label_size = label_->GetPreferredSize();
222 gfx::Size stop_button_size = stop_button_->GetPreferredSize();
223 gfx::Size hide_link_size = hide_link_->GetPreferredSize();
224 int width = kHorizontalMargin * 3 + grip_size.width() + label_size.width() +
225 stop_button_size.width() + hide_link_size.width();
226 width = std::max(width, kMinimumWidth);
227 width = std::min(width, kMaximumWidth);
228 return gfx::Size(width, std::max(label_size.height(),
229 std::max(hide_link_size.height(),
230 stop_button_size.height())));
233 void ScreenCaptureNotificationUIViews::Layout() {
234 gfx::Rect grip_rect(gripper_->GetPreferredSize());
235 grip_rect.set_y((bounds().height() - grip_rect.height()) / 2);
236 gripper_->SetBoundsRect(grip_rect);
238 gfx::Rect stop_button_rect(stop_button_->GetPreferredSize());
239 gfx::Rect hide_link_rect(hide_link_->GetPreferredSize());
241 hide_link_rect.set_x(bounds().width() - hide_link_rect.width());
242 hide_link_rect.set_y((bounds().height() - hide_link_rect.height()) / 2);
243 hide_link_->SetBoundsRect(hide_link_rect);
245 stop_button_rect.set_x(
246 hide_link_rect.x() - kHorizontalMargin - stop_button_rect.width());
247 stop_button_->SetBoundsRect(stop_button_rect);
249 gfx::Rect label_rect;
250 label_rect.set_x(grip_rect.right() + kHorizontalMargin);
251 label_rect.set_width(
252 stop_button_rect.x() - kHorizontalMargin - label_rect.x());
253 label_rect.set_height(bounds().height());
254 label_->SetBoundsRect(label_rect);
256 client_view_->set_client_rect(gfx::Rect(
257 stop_button_rect.x(), stop_button_rect.y(),
258 stop_button_rect.width() + kHorizontalMargin + hide_link_rect.width(),
259 std::max(stop_button_rect.height(), hide_link_rect.height())));
262 void ScreenCaptureNotificationUIViews::DeleteDelegate() {
263 NotifyStopped();
266 views::View* ScreenCaptureNotificationUIViews::GetContentsView() {
267 return this;
270 views::ClientView* ScreenCaptureNotificationUIViews::CreateClientView(
271 views::Widget* widget) {
272 DCHECK(!client_view_);
273 client_view_ = new NotificationBarClientView(widget, this);
274 return client_view_;
277 views::NonClientFrameView*
278 ScreenCaptureNotificationUIViews::CreateNonClientFrameView(
279 views::Widget* widget) {
280 views::BubbleFrameView* frame = new views::BubbleFrameView(
281 gfx::Insets(kPaddingVertical,
282 kPaddingHorizontal,
283 kPaddingVertical,
284 kPaddingHorizontal));
285 SkColor color = widget->GetNativeTheme()->GetSystemColor(
286 ui::NativeTheme::kColorId_DialogBackground);
287 frame->SetBubbleBorder(scoped_ptr<views::BubbleBorder>(
288 new views::BubbleBorder(views::BubbleBorder::NONE,
289 views::BubbleBorder::SMALL_SHADOW,
290 color)));
291 return frame;
294 base::string16 ScreenCaptureNotificationUIViews::GetWindowTitle() const {
295 return text_;
298 bool ScreenCaptureNotificationUIViews::ShouldShowWindowTitle() const {
299 return false;
302 bool ScreenCaptureNotificationUIViews::ShouldShowCloseButton() const {
303 return false;
306 bool ScreenCaptureNotificationUIViews::CanActivate() const {
307 // When the window is visible, it can be activated so the mouse clicks
308 // can be sent to the window; when the window is minimized, we don't want it
309 // to activate, otherwise it sometimes does not show properly on Windows.
310 return GetWidget() && GetWidget()->IsVisible();
313 void ScreenCaptureNotificationUIViews::ButtonPressed(views::Button* sender,
314 const ui::Event& event) {
315 NotifyStopped();
318 void ScreenCaptureNotificationUIViews::LinkClicked(views::Link* source,
319 int event_flags) {
320 GetWidget()->Minimize();
323 void ScreenCaptureNotificationUIViews::NotifyStopped() {
324 if (!stop_callback_.is_null()) {
325 base::Closure callback = stop_callback_;
326 stop_callback_.Reset();
327 callback.Run();
331 } // namespace
333 scoped_ptr<ScreenCaptureNotificationUI> ScreenCaptureNotificationUI::Create(
334 const base::string16& text) {
335 return scoped_ptr<ScreenCaptureNotificationUI>(
336 new ScreenCaptureNotificationUIViews(text));