OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ui/message_center/cocoa/notification_controller.h" | 5 #import "ui/message_center/cocoa/notification_controller.h" |
6 | 6 |
7 #include "base/mac/foundation_util.h" | 7 #include "base/mac/foundation_util.h" |
8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
11 #include "grit/ui_resources.h" | 11 #include "grit/ui_resources.h" |
12 #include "grit/ui_strings.h" | |
12 #include "skia/ext/skia_utils_mac.h" | 13 #include "skia/ext/skia_utils_mac.h" |
13 #import "ui/base/cocoa/hover_image_button.h" | 14 #import "ui/base/cocoa/hover_image_button.h" |
15 #include "ui/base/l10n/l10n_util_mac.h" | |
14 #include "ui/base/resource/resource_bundle.h" | 16 #include "ui/base/resource/resource_bundle.h" |
15 #include "ui/base/text/text_elider.h" | 17 #include "ui/base/text/text_elider.h" |
16 #include "ui/message_center/message_center.h" | 18 #include "ui/message_center/message_center.h" |
17 #include "ui/message_center/message_center_style.h" | 19 #include "ui/message_center/message_center_style.h" |
18 #include "ui/message_center/notification.h" | 20 #include "ui/message_center/notification.h" |
19 | 21 |
20 @interface MCNotificationButtonCell : NSButtonCell { | 22 @interface MCNotificationButtonCell : NSButtonCell { |
21 BOOL hovered_; | 23 BOOL hovered_; |
22 } | 24 } |
23 @end | 25 @end |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 // Else the cell won't be repainted on hover. | 84 // Else the cell won't be repainted on hover. |
83 [super mouseEntered:event]; | 85 [super mouseEntered:event]; |
84 } | 86 } |
85 | 87 |
86 - (void)mouseExited:(NSEvent*)event { | 88 - (void)mouseExited:(NSEvent*)event { |
87 hovered_ = NO; | 89 hovered_ = NO; |
88 [super mouseExited:event]; | 90 [super mouseExited:event]; |
89 } | 91 } |
90 @end | 92 @end |
91 | 93 |
94 //////////////////////////////////////////////////////////////////////////////// | |
95 | |
92 @interface MCNotificationView : NSBox { | 96 @interface MCNotificationView : NSBox { |
93 @private | 97 @private |
94 MCNotificationController* controller_; | 98 MCNotificationController* controller_; |
95 } | 99 } |
96 | 100 |
97 - (id)initWithController:(MCNotificationController*)controller | 101 - (id)initWithController:(MCNotificationController*)controller |
98 frame:(NSRect)frame; | 102 frame:(NSRect)frame; |
99 @end | 103 @end |
100 | 104 |
101 @implementation MCNotificationView | 105 @implementation MCNotificationView |
102 - (id)initWithController:(MCNotificationController*)controller | 106 - (id)initWithController:(MCNotificationController*)controller |
103 frame:(NSRect)frame { | 107 frame:(NSRect)frame { |
104 if ((self = [super initWithFrame:frame])) | 108 if ((self = [super initWithFrame:frame])) |
105 controller_ = controller; | 109 controller_ = controller; |
106 return self; | 110 return self; |
107 } | 111 } |
108 | 112 |
109 - (void)mouseDown:(NSEvent*)event { | 113 - (void)mouseDown:(NSEvent*)event { |
110 if ([event type] != NSLeftMouseDown) { | 114 if ([event type] != NSLeftMouseDown) { |
111 [super mouseDown:event]; | 115 [super mouseDown:event]; |
112 return; | 116 return; |
113 } | 117 } |
114 [controller_ notificationClicked]; | 118 [controller_ notificationClicked]; |
115 } | 119 } |
120 | |
121 - (BOOL)accessibilityIsIgnored { | |
122 return NO; | |
123 } | |
124 | |
125 - (NSArray*)accessibilityActionNames { | |
126 return @[ NSAccessibilityPressAction ]; | |
127 } | |
128 | |
129 - (void)accessibilityPerformAction:(NSString*)action { | |
130 if ([action isEqualToString:NSAccessibilityPressAction]) { | |
131 [controller_ notificationClicked]; | |
132 return; | |
133 } | |
134 [super accessibilityPerformAction:action]; | |
135 } | |
116 @end | 136 @end |
117 | 137 |
138 //////////////////////////////////////////////////////////////////////////////// | |
139 | |
140 @interface AccessibilityIgnoredBox : NSBox | |
141 @end | |
142 | |
143 @implementation AccessibilityIgnoredBox | |
144 - (BOOL)accessibilityIsIgnored { | |
145 return YES; | |
146 } | |
147 @end | |
Nico
2013/06/20 21:03:23
Huh, this looks like something that should already
Robert Sesek
2013/06/22 01:56:00
I couldn't find it. There's some other Accessibili
| |
148 | |
149 //////////////////////////////////////////////////////////////////////////////// | |
150 | |
118 @interface MCNotificationController (Private) | 151 @interface MCNotificationController (Private) |
119 // Returns a string with item's title in title color and item's message in | 152 // Returns a string with item's title in title color and item's message in |
120 // message color. | 153 // message color. |
121 + (NSAttributedString*) | 154 + (NSAttributedString*) |
122 attributedStringForItem:(const message_center::NotificationItem&)item | 155 attributedStringForItem:(const message_center::NotificationItem&)item |
123 font:(NSFont*)font; | 156 font:(NSFont*)font; |
124 | 157 |
125 // Configures a NSBox to be borderless, titleless, and otherwise appearance- | 158 // Configures a NSBox to be borderless, titleless, and otherwise appearance- |
126 // free. | 159 // free. |
127 - (void)configureCustomBox:(NSBox*)box; | 160 - (void)configureCustomBox:(NSBox*)box; |
(...skipping 20 matching lines...) Expand all Loading... | |
148 - (NSRect)currentContentRect; | 181 - (NSRect)currentContentRect; |
149 | 182 |
150 // Returns the wrapped text that could fit within the given text field with not | 183 // Returns the wrapped text that could fit within the given text field with not |
151 // more than the given number of lines. The Ellipsis could be added at the end | 184 // more than the given number of lines. The Ellipsis could be added at the end |
152 // of the last line if it is too long. | 185 // of the last line if it is too long. |
153 - (string16)wrapText:(const string16&)text | 186 - (string16)wrapText:(const string16&)text |
154 forField:(NSTextField*)field | 187 forField:(NSTextField*)field |
155 maxNumberOfLines:(size_t)lines; | 188 maxNumberOfLines:(size_t)lines; |
156 @end | 189 @end |
157 | 190 |
191 //////////////////////////////////////////////////////////////////////////////// | |
192 | |
158 @implementation MCNotificationController | 193 @implementation MCNotificationController |
159 | 194 |
160 - (id)initWithNotification:(const message_center::Notification*)notification | 195 - (id)initWithNotification:(const message_center::Notification*)notification |
161 messageCenter:(message_center::MessageCenter*)messageCenter { | 196 messageCenter:(message_center::MessageCenter*)messageCenter { |
162 if ((self = [super initWithNibName:nil bundle:nil])) { | 197 if ((self = [super initWithNibName:nil bundle:nil])) { |
163 notification_ = notification; | 198 notification_ = notification; |
164 notificationID_ = notification_->id(); | 199 notificationID_ = notification_->id(); |
165 messageCenter_ = messageCenter; | 200 messageCenter_ = messageCenter; |
166 } | 201 } |
167 return self; | 202 return self; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 // Create the list item views (up to a maximum). | 280 // Create the list item views (up to a maximum). |
246 [listItemView_ removeFromSuperview]; | 281 [listItemView_ removeFromSuperview]; |
247 const std::vector<message_center::NotificationItem>& items = | 282 const std::vector<message_center::NotificationItem>& items = |
248 notification->items(); | 283 notification->items(); |
249 NSRect listFrame = NSZeroRect; | 284 NSRect listFrame = NSZeroRect; |
250 if (items.size() > 0) { | 285 if (items.size() > 0) { |
251 listFrame = [self currentContentRect]; | 286 listFrame = [self currentContentRect]; |
252 listFrame.origin.y = 0; | 287 listFrame.origin.y = 0; |
253 listFrame.size.height = 0; | 288 listFrame.size.height = 0; |
254 listItemView_.reset([[NSView alloc] initWithFrame:listFrame]); | 289 listItemView_.reset([[NSView alloc] initWithFrame:listFrame]); |
290 [listItemView_ accessibilitySetOverrideValue:NSAccessibilityListRole | |
dmazzoni
2013/06/20 23:05:10
This is a little confusing to me - is listItemView
Robert Sesek
2013/06/22 01:56:00
listItemView is a container for list items.
| |
291 forAttribute:NSAccessibilityRoleAttribute]; | |
292 [listItemView_ | |
293 accessibilitySetOverrideValue:NSAccessibilityContentListSubrole | |
294 forAttribute:NSAccessibilitySubroleAttribute]; | |
255 CGFloat y = 0; | 295 CGFloat y = 0; |
256 | 296 |
257 NSFont* font = [NSFont systemFontOfSize:message_center::kMessageFontSize]; | 297 NSFont* font = [NSFont systemFontOfSize:message_center::kMessageFontSize]; |
258 CGFloat lineHeight = roundf(NSHeight([font boundingRectForFont])); | 298 CGFloat lineHeight = roundf(NSHeight([font boundingRectForFont])); |
259 | 299 |
260 const int kNumNotifications = | 300 const int kNumNotifications = |
261 std::min(items.size(), message_center::kNotificationMaximumItems); | 301 std::min(items.size(), message_center::kNotificationMaximumItems); |
262 for (int i = kNumNotifications - 1; i >= 0; --i) { | 302 for (int i = kNumNotifications - 1; i >= 0; --i) { |
263 NSTextField* field = [self newLabelWithFrame: | 303 NSTextField* field = [self newLabelWithFrame: |
264 NSMakeRect(0, y, NSWidth(listFrame), lineHeight)]; | 304 NSMakeRect(0, y, NSWidth(listFrame), lineHeight)]; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
320 [button setTarget:self]; | 360 [button setTarget:self]; |
321 [button setAction:@selector(buttonClicked:)]; | 361 [button setAction:@selector(buttonClicked:)]; |
322 y += NSHeight(buttonFrame); | 362 y += NSHeight(buttonFrame); |
323 frame.size.height += NSHeight(buttonFrame); | 363 frame.size.height += NSHeight(buttonFrame); |
324 [bottomView_ addSubview:button]; | 364 [bottomView_ addSubview:button]; |
325 | 365 |
326 NSRect separatorFrame = frame; | 366 NSRect separatorFrame = frame; |
327 separatorFrame.origin = NSMakePoint(0, y); | 367 separatorFrame.origin = NSMakePoint(0, y); |
328 separatorFrame.size.height = 1; | 368 separatorFrame.size.height = 1; |
329 scoped_nsobject<NSBox> separator( | 369 scoped_nsobject<NSBox> separator( |
330 [[NSBox alloc] initWithFrame:separatorFrame]); | 370 [[AccessibilityIgnoredBox alloc] initWithFrame:separatorFrame]); |
331 [self configureCustomBox:separator]; | 371 [self configureCustomBox:separator]; |
332 [separator setFillColor:gfx::SkColorToCalibratedNSColor( | 372 [separator setFillColor:gfx::SkColorToCalibratedNSColor( |
333 message_center::kButtonSeparatorColor)]; | 373 message_center::kButtonSeparatorColor)]; |
334 y += NSHeight(separatorFrame); | 374 y += NSHeight(separatorFrame); |
335 frame.size.height += NSHeight(separatorFrame); | 375 frame.size.height += NSHeight(separatorFrame); |
336 [bottomView_ addSubview:separator]; | 376 [bottomView_ addSubview:separator]; |
337 } | 377 } |
338 | 378 |
339 // Create the image view if appropriate. | 379 // Create the image view if appropriate. |
340 if (!notification->image().IsEmpty()) { | 380 if (!notification->image().IsEmpty()) { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 [box setTitlePosition:NSNoTitle]; | 474 [box setTitlePosition:NSNoTitle]; |
435 [box setContentViewMargins:NSZeroSize]; | 475 [box setContentViewMargins:NSZeroSize]; |
436 } | 476 } |
437 | 477 |
438 - (NSView*)createImageView { | 478 - (NSView*)createImageView { |
439 // Create another box that shows a background color when the icon is not | 479 // Create another box that shows a background color when the icon is not |
440 // big enough to fill the space. | 480 // big enough to fill the space. |
441 NSRect imageFrame = NSMakeRect(0, 0, | 481 NSRect imageFrame = NSMakeRect(0, 0, |
442 message_center::kNotificationIconSize, | 482 message_center::kNotificationIconSize, |
443 message_center::kNotificationIconSize); | 483 message_center::kNotificationIconSize); |
444 scoped_nsobject<NSBox> imageBox([[NSBox alloc] initWithFrame:imageFrame]); | 484 scoped_nsobject<NSBox> imageBox( |
485 [[AccessibilityIgnoredBox alloc] initWithFrame:imageFrame]); | |
445 [self configureCustomBox:imageBox]; | 486 [self configureCustomBox:imageBox]; |
446 [imageBox setFillColor:gfx::SkColorToCalibratedNSColor( | 487 [imageBox setFillColor:gfx::SkColorToCalibratedNSColor( |
447 message_center::kLegacyIconBackgroundColor)]; | 488 message_center::kLegacyIconBackgroundColor)]; |
448 [imageBox setAutoresizingMask:NSViewMinYMargin]; | 489 [imageBox setAutoresizingMask:NSViewMinYMargin]; |
449 | 490 |
450 // Inside the image box put the actual icon view. | 491 // Inside the image box put the actual icon view. |
451 icon_.reset([[NSImageView alloc] initWithFrame:imageFrame]); | 492 icon_.reset([[NSImageView alloc] initWithFrame:imageFrame]); |
452 [imageBox setContentView:icon_]; | 493 [imageBox setContentView:icon_]; |
453 | 494 |
454 return imageBox.autorelease(); | 495 return imageBox.autorelease(); |
(...skipping 11 matching lines...) Expand all Loading... | |
466 [closeButton_ setHoverImage: | 507 [closeButton_ setHoverImage: |
467 rb.GetNativeImageNamed(IDR_NOTIFICATION_CLOSE_HOVER).ToNSImage()]; | 508 rb.GetNativeImageNamed(IDR_NOTIFICATION_CLOSE_HOVER).ToNSImage()]; |
468 [closeButton_ setPressedImage: | 509 [closeButton_ setPressedImage: |
469 rb.GetNativeImageNamed(IDR_NOTIFICATION_CLOSE_PRESSED).ToNSImage()]; | 510 rb.GetNativeImageNamed(IDR_NOTIFICATION_CLOSE_PRESSED).ToNSImage()]; |
470 [[closeButton_ cell] setHighlightsBy:NSOnState]; | 511 [[closeButton_ cell] setHighlightsBy:NSOnState]; |
471 [closeButton_ setTrackingEnabled:YES]; | 512 [closeButton_ setTrackingEnabled:YES]; |
472 [closeButton_ setBordered:NO]; | 513 [closeButton_ setBordered:NO]; |
473 [closeButton_ setAutoresizingMask:NSViewMinYMargin]; | 514 [closeButton_ setAutoresizingMask:NSViewMinYMargin]; |
474 [closeButton_ setTarget:self]; | 515 [closeButton_ setTarget:self]; |
475 [closeButton_ setAction:@selector(close:)]; | 516 [closeButton_ setAction:@selector(close:)]; |
517 [[closeButton_ cell] | |
518 accessibilitySetOverrideValue:NSAccessibilityCloseButtonSubrole | |
519 forAttribute:NSAccessibilitySubroleAttribute]; | |
520 [[closeButton_ cell] | |
521 accessibilitySetOverrideValue: | |
522 l10n_util::GetNSString(IDS_APP_ACCNAME_CLOSE) | |
523 forAttribute:NSAccessibilityTitleAttribute]; | |
476 } | 524 } |
477 | 525 |
478 - (void)configureTitleInFrame:(NSRect)rootFrame { | 526 - (void)configureTitleInFrame:(NSRect)rootFrame { |
479 NSRect frame = [self currentContentRect]; | 527 NSRect frame = [self currentContentRect]; |
480 frame.size.height = 0; | 528 frame.size.height = 0; |
481 title_.reset([self newLabelWithFrame:frame]); | 529 title_.reset([self newLabelWithFrame:frame]); |
482 [title_ setAutoresizingMask:NSViewMinYMargin]; | 530 [title_ setAutoresizingMask:NSViewMinYMargin]; |
483 [title_ setTextColor:gfx::SkColorToCalibratedNSColor( | 531 [title_ setTextColor:gfx::SkColorToCalibratedNSColor( |
484 message_center::kRegularTextColor)]; | 532 message_center::kRegularTextColor)]; |
485 [title_ setFont:[NSFont messageFontOfSize:message_center::kTitleFontSize]]; | 533 [title_ setFont:[NSFont messageFontOfSize:message_center::kTitleFontSize]]; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
535 if (font.GetStringWidth(last) > width) | 583 if (font.GetStringWidth(last) > width) |
536 last = ui::ElideText(last, font, width, ui::ELIDE_AT_END); | 584 last = ui::ElideText(last, font, width, ui::ELIDE_AT_END); |
537 wrapped.resize(lines - 1); | 585 wrapped.resize(lines - 1); |
538 wrapped.push_back(last); | 586 wrapped.push_back(last); |
539 } | 587 } |
540 | 588 |
541 return JoinString(wrapped, '\n'); | 589 return JoinString(wrapped, '\n'); |
542 } | 590 } |
543 | 591 |
544 @end | 592 @end |
OLD | NEW |