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

Side by Side Diff: ui/message_center/cocoa/notification_controller.mm

Issue 23462005: Adds the contextMessage field to notifications. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
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"
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 196
197 // Initializes the closeButton_ ivar with the configured button. 197 // Initializes the closeButton_ ivar with the configured button.
198 - (void)configureCloseButtonInFrame:(NSRect)rootFrame; 198 - (void)configureCloseButtonInFrame:(NSRect)rootFrame;
199 199
200 // Initializes title_ in the given frame. 200 // Initializes title_ in the given frame.
201 - (void)configureTitleInFrame:(NSRect)rootFrame; 201 - (void)configureTitleInFrame:(NSRect)rootFrame;
202 202
203 // Initializes message_ in the given frame. 203 // Initializes message_ in the given frame.
204 - (void)configureBodyInFrame:(NSRect)rootFrame; 204 - (void)configureBodyInFrame:(NSRect)rootFrame;
205 205
206 // Initializes contextMessage_ in the given frame.
207 - (void)configureContextMessageInFrame:(NSRect)rootFrame;
208
206 // Creates a NSTextField that the caller owns configured as a label in a 209 // Creates a NSTextField that the caller owns configured as a label in a
207 // notification. 210 // notification.
208 - (NSTextField*)newLabelWithFrame:(NSRect)frame; 211 - (NSTextField*)newLabelWithFrame:(NSRect)frame;
209 212
210 // Gets the rectangle in which notification content should be placed. This 213 // Gets the rectangle in which notification content should be placed. This
211 // rectangle is to the right of the icon and left of the control buttons. 214 // rectangle is to the right of the icon and left of the control buttons.
212 // This depends on the icon_ and closeButton_ being initialized. 215 // This depends on the icon_ and closeButton_ being initialized.
213 - (NSRect)currentContentRect; 216 - (NSRect)currentContentRect;
214 217
215 // Returns the wrapped text that could fit within the given text field with not 218 // Returns the wrapped text that could fit within the given text field with not
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 [rootView addSubview:closeButton_]; 256 [rootView addSubview:closeButton_];
254 257
255 // Create the title. 258 // Create the title.
256 [self configureTitleInFrame:rootFrame]; 259 [self configureTitleInFrame:rootFrame];
257 [rootView addSubview:title_]; 260 [rootView addSubview:title_];
258 261
259 // Create the message body. 262 // Create the message body.
260 [self configureBodyInFrame:rootFrame]; 263 [self configureBodyInFrame:rootFrame];
261 [rootView addSubview:message_]; 264 [rootView addSubview:message_];
262 265
266 // Create the context message body.
267 [self configureContextMessageInFrame:rootFrame];
268 [rootView addSubview:contextMessage_];
269
263 // Populate the data. 270 // Populate the data.
264 [self updateNotification:notification_]; 271 [self updateNotification:notification_];
265 } 272 }
266 273
267 - (NSRect)updateNotification:(const message_center::Notification*)notification { 274 - (NSRect)updateNotification:(const message_center::Notification*)notification {
268 DCHECK_EQ(notification->id(), notificationID_); 275 DCHECK_EQ(notification->id(), notificationID_);
269 notification_ = notification; 276 notification_ = notification;
270 277
271 NSRect rootFrame = NSMakeRect(0, 0, 278 NSRect rootFrame = NSMakeRect(0, 0,
272 message_center::kNotificationPreferredImageSize, 279 message_center::kNotificationPreferredImageSize,
273 message_center::kNotificationIconSize); 280 message_center::kNotificationIconSize);
274 281
275 // Update the icon. 282 // Update the icon.
276 [icon_ setImage:notification_->icon().AsNSImage()]; 283 [icon_ setImage:notification_->icon().AsNSImage()];
277 284
278 // The message_center:: constants are relative to capHeight at the top and 285 // The message_center:: constants are relative to capHeight at the top and
279 // relative to the baseline at the bottom, but NSTextField uses the full line 286 // relative to the baseline at the bottom, but NSTextField uses the full line
280 // height for its height. 287 // height for its height.
281 CGFloat titleTopGap = 288 CGFloat titleTopGap =
282 roundf([[title_ font] ascender] - [[title_ font] capHeight]); 289 roundf([[title_ font] ascender] - [[title_ font] capHeight]);
283 CGFloat titleBottomGap = roundf(fabs([[title_ font] descender])); 290 CGFloat titleBottomGap = roundf(fabs([[title_ font] descender]));
284 CGFloat titlePadding = message_center::kTextTopPadding - titleTopGap; 291 CGFloat titlePadding = message_center::kTextTopPadding - titleTopGap;
285 292
286 CGFloat messageTopGap = 293 CGFloat messageTopGap =
287 roundf([[message_ font] ascender] - [[message_ font] capHeight]); 294 roundf([[message_ font] ascender] - [[message_ font] capHeight]);
295 CGFloat messageBottomGap = roundf(fabs([[message_ font] descender]));
288 CGFloat messagePadding = 296 CGFloat messagePadding =
289 message_center::kTextTopPadding - titleBottomGap - messageTopGap; 297 message_center::kTextTopPadding - titleBottomGap - messageTopGap;
290 298
299 CGFloat contextMessageTopGap = roundf(
300 [[contextMessage_ font] ascender] - [[contextMessage_ font] capHeight]);
301 CGFloat contextMessagePadding =
302 message_center::kTextTopPadding - messageBottomGap - contextMessageTopGap;
303
291 // Set the title and recalculate the frame. 304 // Set the title and recalculate the frame.
292 [title_ setStringValue:base::SysUTF16ToNSString( 305 [title_ setStringValue:base::SysUTF16ToNSString(
293 [self wrapText:notification_->title() 306 [self wrapText:notification_->title()
294 forField:title_ 307 forField:title_
295 maxNumberOfLines:message_center::kTitleLineLimit])]; 308 maxNumberOfLines:message_center::kTitleLineLimit])];
296 [title_ sizeToFit]; 309 [title_ sizeToFit];
297 NSRect titleFrame = [title_ frame]; 310 NSRect titleFrame = [title_ frame];
298 titleFrame.origin.y = NSMaxY(rootFrame) - titlePadding - NSHeight(titleFrame); 311 titleFrame.origin.y = NSMaxY(rootFrame) - titlePadding - NSHeight(titleFrame);
299 312
300 // Set the message and recalculate the frame. 313 // Set the message and recalculate the frame.
301 [message_ setStringValue:base::SysUTF16ToNSString( 314 [message_ setStringValue:base::SysUTF16ToNSString(
302 [self wrapText:notification_->message() 315 [self wrapText:notification_->message()
303 forField:title_ 316 forField:message_
304 maxNumberOfLines:message_center::kMessageExpandedLineLimit])]; 317 maxNumberOfLines:message_center::kMessageExpandedLineLimit])];
305 [message_ setHidden:NO];
306 [message_ sizeToFit]; 318 [message_ sizeToFit];
307 NSRect messageFrame = [message_ frame]; 319 NSRect messageFrame = [message_ frame];
308 messageFrame.origin.y =
309 NSMinY(titleFrame) - messagePadding - NSHeight(messageFrame);
310 messageFrame.size.height = NSHeight([message_ frame]);
311 320
312 // Create the list item views (up to a maximum). 321 // Need to hide the message if there are items.
jianli 2013/08/28 21:30:54 Do we also do this on views?
dewittj 2013/08/29 17:40:10 Yes. This isn't new, just added a comment for fun
313 [listItemView_ removeFromSuperview];
314 const std::vector<message_center::NotificationItem>& items = 322 const std::vector<message_center::NotificationItem>& items =
315 notification->items(); 323 notification->items();
316 NSRect listFrame = NSZeroRect;
317 if (items.size() > 0) { 324 if (items.size() > 0) {
318 // If there are list items, then the message_ view should not be displayed. 325 // If there are list items, then the message_ view should not be displayed.
319 [message_ setHidden:YES]; 326 [message_ setHidden:YES];
320 messageFrame.origin.y = titleFrame.origin.y; 327 messageFrame.origin.y = titleFrame.origin.y;
321 messageFrame.size.height = 0; 328 messageFrame.size.height = 0;
329 } else {
330 [message_ setHidden:NO];
331 messageFrame.origin.y =
332 NSMinY(titleFrame) - messagePadding - NSHeight(messageFrame);
333 messageFrame.size.height = NSHeight([message_ frame]);
334 }
322 335
336 // Set the context message and recalculate the frame.
337 [contextMessage_ setStringValue:base::SysUTF16ToNSString(
338 [self wrapText:notification_->context_message()
339 forField:contextMessage_
340 maxNumberOfLines:message_center::kContextMessageLineLimit])];
341 [contextMessage_ sizeToFit];
342 NSRect contextMessageFrame = [contextMessage_ frame];
343
344 if (notification_->context_message().length() == 0) {
jianli 2013/08/28 21:30:54 nit: empty()
dewittj 2013/08/29 17:40:10 Done.
345 [contextMessage_ setHidden:YES];
346 contextMessageFrame.origin.y = messageFrame.origin.y;
347 contextMessageFrame.size.height = 0;
348 } else {
349 [contextMessage_ setHidden:NO];
350 contextMessageFrame.origin.y =
351 NSMinY(messageFrame) -
352 contextMessagePadding -
353 NSHeight(contextMessageFrame);
354 contextMessageFrame.size.height = NSHeight([contextMessage_ frame]);
355 }
356
357 // Create the list item views (up to a maximum).
358 [listItemView_ removeFromSuperview];
359 NSRect listFrame = NSZeroRect;
360 if (items.size() > 0) {
323 listFrame = [self currentContentRect]; 361 listFrame = [self currentContentRect];
324 listFrame.origin.y = 0; 362 listFrame.origin.y = 0;
325 listFrame.size.height = 0; 363 listFrame.size.height = 0;
326 listItemView_.reset([[NSView alloc] initWithFrame:listFrame]); 364 listItemView_.reset([[NSView alloc] initWithFrame:listFrame]);
327 [listItemView_ accessibilitySetOverrideValue:NSAccessibilityListRole 365 [listItemView_ accessibilitySetOverrideValue:NSAccessibilityListRole
328 forAttribute:NSAccessibilityRoleAttribute]; 366 forAttribute:NSAccessibilityRoleAttribute];
329 [listItemView_ 367 [listItemView_
330 accessibilitySetOverrideValue:NSAccessibilityContentListSubrole 368 accessibilitySetOverrideValue:NSAccessibilityContentListSubrole
331 forAttribute:NSAccessibilitySubroleAttribute]; 369 forAttribute:NSAccessibilitySubroleAttribute];
332 CGFloat y = 0; 370 CGFloat y = 0;
333 371
334 NSFont* font = [NSFont systemFontOfSize:message_center::kMessageFontSize]; 372 NSFont* font = [NSFont systemFontOfSize:message_center::kMessageFontSize];
335 CGFloat lineHeight = roundf(NSHeight([font boundingRectForFont])); 373 CGFloat lineHeight = roundf(NSHeight([font boundingRectForFont]));
336 374
337 const int kNumNotifications = 375 const int kNumNotifications =
338 std::min(items.size(), message_center::kNotificationMaximumItems); 376 std::min(items.size(), message_center::kNotificationMaximumItems);
339 for (int i = kNumNotifications - 1; i >= 0; --i) { 377 for (int i = kNumNotifications - 1; i >= 0; --i) {
340 NSTextField* field = [self newLabelWithFrame: 378 NSTextField* field = [self newLabelWithFrame:
341 NSMakeRect(0, y, NSWidth(listFrame), lineHeight)]; 379 NSMakeRect(0, y, NSWidth(listFrame), lineHeight)];
342 [[field cell] setUsesSingleLineMode:YES]; 380 [[field cell] setUsesSingleLineMode:YES];
343 [field setAttributedStringValue: 381 [field setAttributedStringValue:
344 [MCNotificationController attributedStringForItem:items[i] 382 [MCNotificationController attributedStringForItem:items[i]
345 font:font]]; 383 font:font]];
346 [listItemView_ addSubview:field]; 384 [listItemView_ addSubview:field];
347 y += lineHeight; 385 y += lineHeight;
348 } 386 }
349 // TODO(thakis): The spacing is not completely right. 387 // TODO(thakis): The spacing is not completely right.
350 CGFloat listTopPadding = 388 CGFloat listTopPadding =
351 message_center::kTextTopPadding - messageTopGap; 389 message_center::kTextTopPadding - contextMessageTopGap;
352 listFrame.size.height = y; 390 listFrame.size.height = y;
353 listFrame.origin.y = 391 listFrame.origin.y =
354 NSMinY(titleFrame) - listTopPadding - NSHeight(listFrame); 392 NSMinY(contextMessageFrame) - listTopPadding - NSHeight(listFrame);
355 [listItemView_ setFrame:listFrame]; 393 [listItemView_ setFrame:listFrame];
356 [[self view] addSubview:listItemView_]; 394 [[self view] addSubview:listItemView_];
357 } 395 }
358 396
359 // Create the progress bar view if needed. 397 // Create the progress bar view if needed.
360 [progressBarView_ removeFromSuperview]; 398 [progressBarView_ removeFromSuperview];
361 NSRect progressBarFrame = NSZeroRect; 399 NSRect progressBarFrame = NSZeroRect;
362 if (notification->type() == message_center::NOTIFICATION_TYPE_PROGRESS) { 400 if (notification->type() == message_center::NOTIFICATION_TYPE_PROGRESS) {
363 progressBarFrame = [self currentContentRect]; 401 progressBarFrame = [self currentContentRect];
364 progressBarFrame.origin.y = NSMinY(messageFrame) - 402 progressBarFrame.origin.y = NSMinY(contextMessageFrame) -
365 message_center::kProgressBarTopPadding - 403 message_center::kProgressBarTopPadding -
366 message_center::kProgressBarThickness; 404 message_center::kProgressBarThickness;
367 progressBarFrame.size.height = message_center::kProgressBarThickness; 405 progressBarFrame.size.height = message_center::kProgressBarThickness;
368 progressBarView_.reset( 406 progressBarView_.reset(
369 [[MCNotificationProgressBar alloc] initWithFrame:progressBarFrame]); 407 [[MCNotificationProgressBar alloc] initWithFrame:progressBarFrame]);
370 // Setting indeterminate to NO does not work with custom drawRect. 408 // Setting indeterminate to NO does not work with custom drawRect.
371 [progressBarView_ setIndeterminate:YES]; 409 [progressBarView_ setIndeterminate:YES];
372 [progressBarView_ setStyle:NSProgressIndicatorBarStyle]; 410 [progressBarView_ setStyle:NSProgressIndicatorBarStyle];
373 [progressBarView_ setDoubleValue:notification->progress()]; 411 [progressBarView_ setDoubleValue:notification->progress()];
374 [[self view] addSubview:progressBarView_]; 412 [[self view] addSubview:progressBarView_];
375 } 413 }
376 414
377 // If the bottom-most element so far is out of the rootView's bounds, resize 415 // If the bottom-most element so far is out of the rootView's bounds, resize
378 // the view. 416 // the view.
379 CGFloat minY = NSMinY(messageFrame); 417 CGFloat minY = NSMinY(contextMessageFrame);
380 if (listItemView_ && NSMinY(listFrame) < minY) 418 if (listItemView_ && NSMinY(listFrame) < minY)
381 minY = NSMinY(listFrame); 419 minY = NSMinY(listFrame);
382 if (progressBarView_ && NSMinY(progressBarFrame) < minY) 420 if (progressBarView_ && NSMinY(progressBarFrame) < minY)
383 minY = NSMinY(progressBarFrame); 421 minY = NSMinY(progressBarFrame);
384 if (minY < messagePadding) { 422 if (minY < messagePadding) {
385 CGFloat delta = messagePadding - minY; 423 CGFloat delta = messagePadding - minY;
386 rootFrame.size.height += delta; 424 rootFrame.size.height += delta;
387 titleFrame.origin.y += delta; 425 titleFrame.origin.y += delta;
388 messageFrame.origin.y += delta; 426 messageFrame.origin.y += delta;
427 contextMessageFrame.origin.y += delta;
389 listFrame.origin.y += delta; 428 listFrame.origin.y += delta;
390 progressBarFrame.origin.y += delta; 429 progressBarFrame.origin.y += delta;
391 } 430 }
392 431
393 // Add the bottom container view. 432 // Add the bottom container view.
394 NSRect frame = rootFrame; 433 NSRect frame = rootFrame;
395 frame.size.height = 0; 434 frame.size.height = 0;
396 [bottomView_ removeFromSuperview]; 435 [bottomView_ removeFromSuperview];
397 bottomView_.reset([[NSView alloc] initWithFrame:frame]); 436 bottomView_.reset([[NSView alloc] initWithFrame:frame]);
398 CGFloat y = 0; 437 CGFloat y = 0;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 frame.size.height += NSHeight(imageFrame); 488 frame.size.height += NSHeight(imageFrame);
450 [bottomView_ addSubview:imageView]; 489 [bottomView_ addSubview:imageView];
451 } 490 }
452 491
453 [bottomView_ setFrame:frame]; 492 [bottomView_ setFrame:frame];
454 [[self view] addSubview:bottomView_]; 493 [[self view] addSubview:bottomView_];
455 494
456 rootFrame.size.height += NSHeight(frame); 495 rootFrame.size.height += NSHeight(frame);
457 titleFrame.origin.y += NSHeight(frame); 496 titleFrame.origin.y += NSHeight(frame);
458 messageFrame.origin.y += NSHeight(frame); 497 messageFrame.origin.y += NSHeight(frame);
498 contextMessageFrame.origin.y += NSHeight(frame);
459 listFrame.origin.y += NSHeight(frame); 499 listFrame.origin.y += NSHeight(frame);
460 progressBarFrame.origin.y += NSHeight(frame); 500 progressBarFrame.origin.y += NSHeight(frame);
461 501
462 // Make sure that there is a minimum amount of spacing below the icon and 502 // Make sure that there is a minimum amount of spacing below the icon and
463 // the edge of the frame. 503 // the edge of the frame.
464 CGFloat bottomDelta = NSHeight(rootFrame) - NSHeight([icon_ frame]); 504 CGFloat bottomDelta = NSHeight(rootFrame) - NSHeight([icon_ frame]);
465 if (bottomDelta > 0 && bottomDelta < message_center::kIconBottomPadding) { 505 if (bottomDelta > 0 && bottomDelta < message_center::kIconBottomPadding) {
466 CGFloat bottomAdjust = message_center::kIconBottomPadding - bottomDelta; 506 CGFloat bottomAdjust = message_center::kIconBottomPadding - bottomDelta;
467 rootFrame.size.height += bottomAdjust; 507 rootFrame.size.height += bottomAdjust;
468 titleFrame.origin.y += bottomAdjust; 508 titleFrame.origin.y += bottomAdjust;
469 messageFrame.origin.y += bottomAdjust; 509 messageFrame.origin.y += bottomAdjust;
510 contextMessageFrame.origin.y += bottomAdjust;
470 listFrame.origin.y += bottomAdjust; 511 listFrame.origin.y += bottomAdjust;
471 progressBarFrame.origin.y += bottomAdjust; 512 progressBarFrame.origin.y += bottomAdjust;
472 } 513 }
473 514
474 [[self view] setFrame:rootFrame]; 515 [[self view] setFrame:rootFrame];
475 [title_ setFrame:titleFrame]; 516 [title_ setFrame:titleFrame];
476 [message_ setFrame:messageFrame]; 517 [message_ setFrame:messageFrame];
518 [contextMessage_ setFrame:contextMessageFrame];
477 [listItemView_ setFrame:listFrame]; 519 [listItemView_ setFrame:listFrame];
478 [progressBarView_ setFrame:progressBarFrame]; 520 [progressBarView_ setFrame:progressBarFrame];
479 521
480 return rootFrame; 522 return rootFrame;
481 } 523 }
482 524
483 - (void)close:(id)sender { 525 - (void)close:(id)sender {
484 [closeButton_ setTarget:nil]; 526 [closeButton_ setTarget:nil];
485 messageCenter_->RemoveNotification([self notificationID], /*by_user=*/true); 527 messageCenter_->RemoveNotification([self notificationID], /*by_user=*/true);
486 } 528 }
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 NSRect frame = [self currentContentRect]; 651 NSRect frame = [self currentContentRect];
610 frame.size.height = 0; 652 frame.size.height = 0;
611 message_.reset([self newLabelWithFrame:frame]); 653 message_.reset([self newLabelWithFrame:frame]);
612 [message_ setAutoresizingMask:NSViewMinYMargin]; 654 [message_ setAutoresizingMask:NSViewMinYMargin];
613 [message_ setTextColor:gfx::SkColorToCalibratedNSColor( 655 [message_ setTextColor:gfx::SkColorToCalibratedNSColor(
614 message_center::kDimTextColor)]; 656 message_center::kDimTextColor)];
615 [message_ setFont: 657 [message_ setFont:
616 [NSFont messageFontOfSize:message_center::kMessageFontSize]]; 658 [NSFont messageFontOfSize:message_center::kMessageFontSize]];
617 } 659 }
618 660
661 - (void)configureContextMessageInFrame:(NSRect)rootFrame {
662 NSRect frame = [self currentContentRect];
663 frame.size.height = 0;
664 contextMessage_.reset([self newLabelWithFrame:frame]);
665 [contextMessage_ setAutoresizingMask:NSViewMinYMargin];
666 [contextMessage_ setTextColor:gfx::SkColorToCalibratedNSColor(
667 message_center::kContextTextColor)];
668 NSFont* messageFont =
669 [NSFont messageFontOfSize:message_center::kMessageFontSize];
670 [contextMessage_ setFont:
671 [[NSFontManager sharedFontManager] convertFont:messageFont
672 toHaveTrait:NSBoldFontMask]];
673 }
674
619 - (NSTextField*)newLabelWithFrame:(NSRect)frame { 675 - (NSTextField*)newLabelWithFrame:(NSRect)frame {
620 NSTextField* label = [[NSTextField alloc] initWithFrame:frame]; 676 NSTextField* label = [[NSTextField alloc] initWithFrame:frame];
621 [label setDrawsBackground:NO]; 677 [label setDrawsBackground:NO];
622 [label setBezeled:NO]; 678 [label setBezeled:NO];
623 [label setEditable:NO]; 679 [label setEditable:NO];
624 [label setSelectable:NO]; 680 [label setSelectable:NO];
625 return label; 681 return label;
626 } 682 }
627 683
628 - (NSRect)currentContentRect { 684 - (NSRect)currentContentRect {
(...skipping 26 matching lines...) Expand all
655 if (font.GetStringWidth(last) > width) 711 if (font.GetStringWidth(last) > width)
656 last = ui::ElideText(last, font, width, ui::ELIDE_AT_END); 712 last = ui::ElideText(last, font, width, ui::ELIDE_AT_END);
657 wrapped.resize(lines - 1); 713 wrapped.resize(lines - 1);
658 wrapped.push_back(last); 714 wrapped.push_back(last);
659 } 715 }
660 716
661 return JoinString(wrapped, '\n'); 717 return JoinString(wrapped, '\n');
662 } 718 }
663 719
664 @end 720 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698