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

Unified Diff: ui/message_center/cocoa/popup_collection.mm

Issue 14598015: [Mac][MC] Implement notification updates and relayouts. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: ui/message_center/cocoa/popup_collection.mm
diff --git a/ui/message_center/cocoa/popup_collection.mm b/ui/message_center/cocoa/popup_collection.mm
index e77c3abc24af3662a615be7fdab3c0d04ffcca3d..cf286f6cc60abc32be138ddd18daa5567c7e6fbd 100644
--- a/ui/message_center/cocoa/popup_collection.mm
+++ b/ui/message_center/cocoa/popup_collection.mm
@@ -4,7 +4,8 @@
#import "ui/message_center/cocoa/popup_collection.h"
-#include "ui/message_center/cocoa/popup_controller.h"
+#import "ui/message_center/cocoa/notification_controller.h"
+#import "ui/message_center/cocoa/popup_controller.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/message_center_constants.h"
#include "ui/message_center/message_center_observer.h"
@@ -17,12 +18,20 @@
// Returns YES if the notification was actually displayed.
- (BOOL)addNotification:(const message_center::Notification*)notification;
+// Updates the contents of the notification with the given ID.
+- (void)updateNotification:(const std::string&)notificationID;
+
// Removes a popup from the screen and lays out new notifications that can
// now potentially fit on the screen.
- (void)removeNotification:(const std::string&)notificationID;
// Closes all the popups.
- (void)removeAllNotifications;
+
+// Positions popup notifications for the |index|th notification in |popups_|.
+// This will put the proper amount of space between popup |index - 1| and
+// |index| and then any subsequent notifications.
+- (void)layoutNotificationsStartingAt:(NSUInteger)index;
@end
namespace {
@@ -58,7 +67,7 @@ class PopupCollectionObserver : public message_center::MessageCenterObserver {
virtual void OnNotificationUpdated(
const std::string& notification_id) OVERRIDE {
- // TODO(rsesek): Refactor MCNotificationController to support updating.
+ [popup_collection_ updateNotification:notification_id];
}
private:
@@ -130,52 +139,65 @@ class PopupCollectionObserver : public message_center::MessageCenterObserver {
return NO;
}
-- (void)removeNotification:(const std::string&)notificationID {
- // The set of notification IDs that are currently displayed.
- std::set<std::string> onScreen;
+- (void)updateNotification:(const std::string&)notificationID {
+ // Find the controller for this notification ID.
+ NSUInteger index = [popups_ indexOfObjectPassingTest:
+ ^BOOL(id popup, NSUInteger i, BOOL* stop) {
+ return [popup notificationID] == notificationID;
+ }];
+ // The notification may not be on screen.
+ if (index == NSNotFound)
+ return;
- // Find the popup for the given ID.
- NSUInteger index = 0;
- MCPopupController* popup = nil;
- for (MCPopupController* candidate in popups_.get()) {
- if ([candidate notificationID] == notificationID) {
- popup = candidate;
- } else {
- onScreen.insert([candidate notificationID]);
+ // Find the corresponding model object for the ID. This may be a replaced
+ // notification, so the controller's current model object may be stale.
+ const message_center::Notification* notification = NULL;
+ const auto& modelPopups = messageCenter_->GetPopupNotifications();
+ for (auto it = modelPopups.begin(); it != modelPopups.end(); ++it) {
sail 2013/05/03 21:42:32 nit, this seems like something we'd want to do on
Robert Sesek 2013/05/03 21:59:18 Justin: WDYT? NotificationList has this method but
dewittj 2013/05/03 22:31:37 sounds OK to me
+ if ((*it)->id() == notificationID) {
+ notification = *it;
+ break;
}
+ }
+ if (!notification) {
+ NOTREACHED();
sail 2013/05/03 21:42:32 I don't think this is a good use of NOTREACHED().
Robert Sesek 2013/05/03 21:59:18 Done.
+ return;
+ }
+
+ MCPopupController* popup = [popups_ objectAtIndex:index];
- // If the popup has not yet been found, increase the index.
- if (!popup)
- ++index;
+ CGFloat oldHeight =
+ NSHeight([[[popup notificationController] view] frame]);
+ CGFloat newHeight = NSHeight(
+ [[popup notificationController] updateNotification:notification]);
+
+ // The notification has changed height. This requires updating the popup
+ // window and any popups that come below it.
+ if (oldHeight != newHeight) {
+ NSRect popupFrame = [[popup window] frame];
+ popupFrame.size.height += newHeight - oldHeight;
+ [[popup window] setFrame:popupFrame display:YES];
+
+ // Start re-layout of notifications at this index, so that it readjusts
+ // the Y origin of this notification.
+ [self layoutNotificationsStartingAt:index];
}
+}
- if (!popup)
+- (void)removeNotification:(const std::string&)notificationID {
+ NSUInteger index = [popups_ indexOfObjectPassingTest:
+ ^BOOL(id popup, NSUInteger index, BOOL* stop) {
+ return [popup notificationID] == notificationID;
+ }];
+ // The notification may not be on screen.
+ if (index == NSNotFound)
return;
- // Calculate its height and then close it.
- CGFloat delta = NSHeight([[popup window] frame]) +
- message_center::kMarginBetweenItems;
- [popup close];
+ [[popups_ objectAtIndex:index] close];
[popups_ removeObjectAtIndex:index];
- // Shift all the popups up.
- for ( ; index < [popups_ count]; ++index) {
- NSWindow* window = [[popups_ objectAtIndex:index] window];
- NSPoint origin = [window frame].origin;
- origin.y += delta;
- [window setFrameOrigin:origin];
- }
-
- // Display any new popups that can now fit on screen.
- const auto& allPopups = messageCenter_->GetPopupNotifications();
- for (auto it = allPopups.begin(); it != allPopups.end(); ++it) {
- if (onScreen.find((*it)->id()) == onScreen.end()) {
- // If there's no room left on screen to display notifications, stop
- // trying.
- if (![self addNotification:*it])
- break;
- }
- }
+ if (index < [popups_ count])
+ [self layoutNotificationsStartingAt:index];
}
- (void)removeAllNotifications {
@@ -183,4 +205,65 @@ class PopupCollectionObserver : public message_center::MessageCenterObserver {
[popups_ removeAllObjects];
}
+- (void)layoutNotificationsStartingAt:(NSUInteger)index {
+ DCHECK_GE(index, 0u);
sail 2013/05/03 21:42:32 since this is unsigned, won't this always be true?
Robert Sesek 2013/05/03 21:59:18 Yes, |index| wasn't always unsigned in a previous
+
+ NSRect screenFrame = [self screenFrame];
+ std::set<std::string> onScreen;
+
+ // Calcluate the bottom edge of the |index - 1|th popup.
+ CGFloat maxY = 0;
+ if (index == 0)
+ maxY = NSMaxY(screenFrame);
+ else
+ maxY = NSMinY([[[popups_ objectAtIndex:index - 1] window] frame]);
+
+ // Collect the IDs of popups that are currently on screen.
+ for (NSUInteger i = 0; i < index; ++i)
+ onScreen.insert([[popups_ objectAtIndex:i] notificationID]);
+
+ // Iterate between [index, count) notifications and reposition each. If one
+ // does not fit on screen, close it and any other on-screen popups that come
+ // after it.
+ NSUInteger removeAt = NSNotFound;
+ for (NSUInteger i = index; i < [popups_ count]; ++i) {
+ MCPopupController* popup = [popups_ objectAtIndex:i];
+ NSRect frame = [[popup window] frame];
+ frame.origin.y = maxY - message_center::kMarginBetweenItems -
+ NSHeight(frame);
+
+ // If this popup does not fit on screen, stop repositioning and close this
+ // and subsequent popups.
+ if (NSMinY(frame) < NSMinY(screenFrame)) {
+ removeAt = i;
+ break;
+ }
+
+ [[popup window] setFrame:frame display:YES];
+ onScreen.insert([popup notificationID]);
+
+ // Set the new maximum Y to be the bottom of this notification.
+ maxY = NSMinY(frame);
+ }
+
+ if (removeAt != NSNotFound) {
+ // Remove any popups that are on screen but no longer fit.
+ while ([popups_ count] >= removeAt) {
+ [[popups_ lastObject] close];
+ [popups_ removeLastObject];
+ }
+ } else {
+ // Display any new popups that can now fit on screen.
+ const auto& allPopups = messageCenter_->GetPopupNotifications();
+ for (auto it = allPopups.begin(); it != allPopups.end(); ++it) {
+ if (onScreen.find((*it)->id()) == onScreen.end()) {
+ // If there's no room left on screen to display notifications, stop
+ // trying.
+ if (![self addNotification:*it])
+ break;
+ }
+ }
+ }
+}
+
@end
« no previous file with comments | « ui/message_center/cocoa/notification_controller_unittest.mm ('k') | ui/message_center/cocoa/popup_collection_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698