summaryrefslogtreecommitdiffstats
path: root/chrome/browser/notifications/balloon_collection.cc
diff options
context:
space:
mode:
authorjohnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-29 17:51:36 +0000
committerjohnnyg@chromium.org <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-29 17:51:36 +0000
commitc8173315b15ccf58d8062900fd25eebfd56eb327 (patch)
treea73c01e3f081369ec15cc91fefb80b2baf8eb94f /chrome/browser/notifications/balloon_collection.cc
parent276aa6a60396329c7fb4a988bd0be7f7d0895651 (diff)
downloadchromium_src-c8173315b15ccf58d8062900fd25eebfd56eb327.zip
chromium_src-c8173315b15ccf58d8062900fd25eebfd56eb327.tar.gz
chromium_src-c8173315b15ccf58d8062900fd25eebfd56eb327.tar.bz2
Adds UI components for desktop notifications, including balloon view classes to display toasts on the screen, and manager for controlling the layout of the balloons.
BUG=none TEST=none yet (part of larger patch) Review URL: http://codereview.chromium.org/338051 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30471 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/notifications/balloon_collection.cc')
-rw-r--r--chrome/browser/notifications/balloon_collection.cc172
1 files changed, 172 insertions, 0 deletions
diff --git a/chrome/browser/notifications/balloon_collection.cc b/chrome/browser/notifications/balloon_collection.cc
new file mode 100644
index 0000000..d979ddd
--- /dev/null
+++ b/chrome/browser/notifications/balloon_collection.cc
@@ -0,0 +1,172 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/balloon_collection.h"
+
+#include "base/gfx/rect.h"
+#include "base/logging.h"
+#include "base/stl_util-inl.h"
+#include "chrome/browser/notifications/balloon.h"
+
+namespace {
+
+// Portion of the screen allotted for notifications. When notification balloons
+// extend over this, no new notifications are shown until some are closed.
+const double kPercentBalloonFillFactor = 0.7;
+
+// Allow at least this number of balloons on the screen.
+const int kMinAllowedBalloonCount = 2;
+
+} // namespace
+
+// static
+BalloonCollectionImpl::Layout::Placement
+ BalloonCollectionImpl::Layout::placement_ =
+ Layout::VERTICALLY_FROM_BOTTOM_RIGHT;
+
+BalloonCollectionImpl::BalloonCollectionImpl()
+ : space_change_listener_(NULL) {
+}
+
+BalloonCollectionImpl::~BalloonCollectionImpl() {
+ STLDeleteElements(&balloons_);
+}
+
+void BalloonCollectionImpl::Add(const Notification& notification,
+ Profile* profile) {
+ Balloon* new_balloon = MakeBalloon(notification, profile);
+ balloons_.push_back(new_balloon);
+ PositionBalloons(false);
+ new_balloon->Show();
+
+ // There may be no listener in a unit test.
+ if (space_change_listener_)
+ space_change_listener_->OnBalloonSpaceChanged();
+}
+
+bool BalloonCollectionImpl::HasSpace() const {
+ if (count() < kMinAllowedBalloonCount)
+ return true;
+
+ int max_balloon_size = 0;
+ int total_size = 0;
+ layout_.GetMaxLinearSize(&max_balloon_size, &total_size);
+
+ int current_max_size = max_balloon_size * count();
+ int max_allowed_size = static_cast<int>(total_size *
+ kPercentBalloonFillFactor);
+ return current_max_size < max_allowed_size - max_balloon_size;
+}
+
+void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
+ // We want to free the balloon when finished.
+ scoped_ptr<Balloon> closed(source);
+ for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) {
+ if (*it == source) {
+ balloons_.erase(it);
+ break;
+ }
+ }
+ PositionBalloons(true);
+
+ // There may be no listener in a unit test.
+ if (space_change_listener_)
+ space_change_listener_->OnBalloonSpaceChanged();
+}
+
+void BalloonCollectionImpl::PositionBalloons(bool reposition) {
+ gfx::Point origin = layout_.GetLayoutOrigin();
+ for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) {
+ gfx::Point upper_left = layout_.NextPosition((*it)->size(), &origin);
+ (*it)->SetPosition(upper_left, reposition);
+ }
+}
+
+BalloonCollectionImpl::Layout::Layout() {
+ RefreshSystemMetrics();
+}
+
+const void BalloonCollectionImpl::Layout::GetMaxLinearSize(
+ int* max_balloon_size,
+ int* total_size) const {
+ DCHECK(max_balloon_size && total_size);
+
+ switch (placement_) {
+ case HORIZONTALLY_FROM_BOTTOM_LEFT:
+ case HORIZONTALLY_FROM_BOTTOM_RIGHT:
+ *total_size = work_area_.width();
+ *max_balloon_size = max_balloon_width();
+ break;
+ case VERTICALLY_FROM_TOP_RIGHT:
+ case VERTICALLY_FROM_BOTTOM_RIGHT:
+ *total_size = work_area_.height();
+ *max_balloon_size = max_balloon_height();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const {
+ int x = 0;
+ int y = 0;
+ switch (placement_) {
+ case HORIZONTALLY_FROM_BOTTOM_LEFT:
+ x = work_area_.x();
+ y = work_area_.bottom();
+ break;
+ case HORIZONTALLY_FROM_BOTTOM_RIGHT:
+ x = work_area_.right();
+ y = work_area_.bottom();
+ break;
+ case VERTICALLY_FROM_TOP_RIGHT:
+ x = work_area_.right();
+ y = work_area_.y();
+ break;
+ case VERTICALLY_FROM_BOTTOM_RIGHT:
+ x = work_area_.right();
+ y = work_area_.bottom();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return gfx::Point(x, y);
+}
+
+gfx::Point BalloonCollectionImpl::Layout::NextPosition(
+ const gfx::Size& balloon_size,
+ gfx::Point* position_iterator) const {
+ DCHECK(position_iterator);
+
+ int x = 0;
+ int y = 0;
+ switch (placement_) {
+ case HORIZONTALLY_FROM_BOTTOM_LEFT:
+ x = position_iterator->x();
+ y = position_iterator->y() - balloon_size.height();
+ position_iterator->set_x(position_iterator->x() + balloon_size.width());
+ break;
+ case HORIZONTALLY_FROM_BOTTOM_RIGHT:
+ position_iterator->set_x(position_iterator->x() - balloon_size.width());
+ x = position_iterator->x();
+ y = position_iterator->y() - balloon_size.height();
+ break;
+ case VERTICALLY_FROM_TOP_RIGHT:
+ x = position_iterator->x() - balloon_size.width();
+ y = position_iterator->y();
+ position_iterator->set_y(position_iterator->y() + balloon_size.height());
+ break;
+ case VERTICALLY_FROM_BOTTOM_RIGHT:
+ position_iterator->set_y(position_iterator->y() - balloon_size.height());
+ x = position_iterator->x() - balloon_size.width();
+ y = position_iterator->y();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return gfx::Point(x, y);
+}