Add ICU message format support
[chromium-blink-merge.git] / ui / message_center / views / message_view.cc
blob62e29935c689f59185345e52683602dc96a30c04
1 // Copyright (c) 2012 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 "ui/message_center/views/message_view.h"
7 #include "ui/accessibility/ax_view_state.h"
8 #include "ui/base/l10n/l10n_util.h"
9 #include "ui/base/models/simple_menu_model.h"
10 #include "ui/base/ui_base_switches_util.h"
11 #include "ui/compositor/scoped_layer_animation_settings.h"
12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/shadow_value.h"
14 #include "ui/message_center/message_center.h"
15 #include "ui/message_center/message_center_style.h"
16 #include "ui/message_center/views/padded_button.h"
17 #include "ui/resources/grit/ui_resources.h"
18 #include "ui/strings/grit/ui_strings.h"
19 #include "ui/views/background.h"
20 #include "ui/views/controls/button/image_button.h"
21 #include "ui/views/controls/image_view.h"
22 #include "ui/views/controls/scroll_view.h"
23 #include "ui/views/focus/focus_manager.h"
24 #include "ui/views/painter.h"
25 #include "ui/views/shadow_border.h"
27 namespace {
29 const int kCloseIconTopPadding = 5;
30 const int kCloseIconRightPadding = 5;
32 const int kShadowOffset = 1;
33 const int kShadowBlur = 4;
35 } // namespace
37 namespace message_center {
39 MessageView::MessageView(MessageViewController* controller,
40 const std::string& notification_id,
41 const NotifierId& notifier_id,
42 const gfx::ImageSkia& small_image,
43 const base::string16& display_source)
44 : controller_(controller),
45 notification_id_(notification_id),
46 notifier_id_(notifier_id),
47 background_view_(NULL),
48 scroller_(NULL),
49 display_source_(display_source) {
50 SetFocusable(true);
52 // Create the opaque background that's above the view's shadow.
53 background_view_ = new views::View();
54 background_view_->set_background(
55 views::Background::CreateSolidBackground(kNotificationBackgroundColor));
56 AddChildView(background_view_);
58 views::ImageView* small_image_view = new views::ImageView();
59 small_image_view->SetImage(small_image);
60 small_image_view->SetImageSize(gfx::Size(kSmallImageSize, kSmallImageSize));
61 // The small image view should be added to view hierarchy by the derived
62 // class. This ensures that it is on top of other views.
63 small_image_view->set_owned_by_client();
64 small_image_view_.reset(small_image_view);
66 PaddedButton *close = new PaddedButton(this);
67 close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding);
68 close->SetNormalImage(IDR_NOTIFICATION_CLOSE);
69 close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER);
70 close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED);
71 close->set_animate_on_state_change(false);
72 close->SetAccessibleName(l10n_util::GetStringUTF16(
73 IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
74 // The close button should be added to view hierarchy by the derived class.
75 // This ensures that it is on top of other views.
76 close->set_owned_by_client();
77 close_button_.reset(close);
79 focus_painter_ = views::Painter::CreateSolidFocusPainter(
80 kFocusBorderColor,
81 gfx::Insets(0, 1, 3, 2)).Pass();
84 MessageView::~MessageView() {
87 void MessageView::UpdateWithNotification(const Notification& notification) {
88 small_image_view_->SetImage(notification.small_image().AsImageSkia());
89 display_source_ = notification.display_source();
92 // static
93 gfx::Insets MessageView::GetShadowInsets() {
94 return gfx::Insets(kShadowBlur / 2 - kShadowOffset,
95 kShadowBlur / 2,
96 kShadowBlur / 2 + kShadowOffset,
97 kShadowBlur / 2);
100 void MessageView::CreateShadowBorder() {
101 SetBorder(scoped_ptr<views::Border>(new views::ShadowBorder(
102 gfx::ShadowValue(gfx::Vector2d(0, kShadowOffset), kShadowBlur,
103 message_center::kShadowColor))));
106 bool MessageView::IsCloseButtonFocused() {
107 views::FocusManager* focus_manager = GetFocusManager();
108 return focus_manager && focus_manager->GetFocusedView() == close_button();
111 void MessageView::RequestFocusOnCloseButton() {
112 close_button_->RequestFocus();
115 void MessageView::GetAccessibleState(ui::AXViewState* state) {
116 state->role = ui::AX_ROLE_BUTTON;
117 state->name = accessible_name_;
120 bool MessageView::OnMousePressed(const ui::MouseEvent& event) {
121 if (!event.IsOnlyLeftMouseButton())
122 return false;
124 controller_->ClickOnNotification(notification_id_);
125 return true;
128 bool MessageView::OnKeyPressed(const ui::KeyEvent& event) {
129 if (event.flags() != ui::EF_NONE)
130 return false;
132 if (event.key_code() == ui::VKEY_RETURN) {
133 controller_->ClickOnNotification(notification_id_);
134 return true;
135 } else if ((event.key_code() == ui::VKEY_DELETE ||
136 event.key_code() == ui::VKEY_BACK)) {
137 controller_->RemoveNotification(notification_id_, true); // By user.
138 return true;
141 return false;
144 bool MessageView::OnKeyReleased(const ui::KeyEvent& event) {
145 // Space key handling is triggerred at key-release timing. See
146 // ui/views/controls/buttons/custom_button.cc for why.
147 if (event.flags() != ui::EF_NONE || event.flags() != ui::VKEY_SPACE)
148 return false;
150 controller_->ClickOnNotification(notification_id_);
151 return true;
154 void MessageView::OnPaint(gfx::Canvas* canvas) {
155 DCHECK_EQ(this, close_button_->parent());
156 DCHECK_EQ(this, small_image_view_->parent());
157 SlideOutView::OnPaint(canvas);
158 views::Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
161 void MessageView::OnFocus() {
162 SlideOutView::OnFocus();
163 // We paint a focus indicator.
164 SchedulePaint();
167 void MessageView::OnBlur() {
168 SlideOutView::OnBlur();
169 // We paint a focus indicator.
170 SchedulePaint();
173 void MessageView::Layout() {
174 gfx::Rect content_bounds = GetContentsBounds();
176 // Background.
177 background_view_->SetBoundsRect(content_bounds);
179 // Close button.
180 gfx::Size close_size(close_button_->GetPreferredSize());
181 gfx::Rect close_rect(content_bounds.right() - close_size.width(),
182 content_bounds.y(),
183 close_size.width(),
184 close_size.height());
185 close_button_->SetBoundsRect(close_rect);
187 gfx::Size small_image_size(small_image_view_->GetPreferredSize());
188 gfx::Rect small_image_rect(small_image_size);
189 small_image_rect.set_origin(gfx::Point(
190 content_bounds.right() - small_image_size.width() - kSmallImagePadding,
191 content_bounds.bottom() - small_image_size.height() -
192 kSmallImagePadding));
193 small_image_view_->SetBoundsRect(small_image_rect);
196 void MessageView::OnGestureEvent(ui::GestureEvent* event) {
197 switch (event->type()) {
198 case ui::ET_GESTURE_TAP_DOWN: {
199 SetDrawBackgroundAsActive(true);
200 break;
202 case ui::ET_GESTURE_TAP_CANCEL:
203 case ui::ET_GESTURE_END: {
204 SetDrawBackgroundAsActive(false);
205 break;
207 case ui::ET_GESTURE_TAP: {
208 SetDrawBackgroundAsActive(false);
209 controller_->ClickOnNotification(notification_id_);
210 event->SetHandled();
211 return;
213 default: {
214 // Do nothing
218 SlideOutView::OnGestureEvent(event);
219 // Do not return here by checking handled(). SlideOutView calls SetHandled()
220 // even though the scroll gesture doesn't make no (or little) effects on the
221 // slide-out behavior. See http://crbug.com/172991
223 if (!event->IsScrollGestureEvent() && !event->IsFlingScrollEvent())
224 return;
226 if (scroller_)
227 scroller_->OnGestureEvent(event);
228 event->SetHandled();
231 void MessageView::ButtonPressed(views::Button* sender,
232 const ui::Event& event) {
233 if (sender == close_button()) {
234 controller_->RemoveNotification(notification_id_, true); // By user.
238 void MessageView::OnSlideOut() {
239 controller_->RemoveNotification(notification_id_, true); // By user.
242 void MessageView::SetDrawBackgroundAsActive(bool active) {
243 if (!switches::IsTouchFeedbackEnabled())
244 return;
245 background_view_->background()->
246 SetNativeControlColor(active ? kHoveredButtonBackgroundColor :
247 kNotificationBackgroundColor);
248 SchedulePaint();
251 } // namespace message_center