diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-01 18:35:08 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-01 18:35:08 +0000 |
commit | 7caf730c00f7fe2884ecd2643b5b8c045bd0270c (patch) | |
tree | 5b6d45e420547642407f5ebb10243be29692b4bc | |
parent | 4603fcfc8e491519e2131f0407908a31ec8fab42 (diff) | |
download | chromium_src-7caf730c00f7fe2884ecd2643b5b8c045bd0270c.zip chromium_src-7caf730c00f7fe2884ecd2643b5b8c045bd0270c.tar.gz chromium_src-7caf730c00f7fe2884ecd2643b5b8c045bd0270c.tar.bz2 |
Reapply and fix r73019. BalloonViewImpl has a different implemementation on
linux_gtk, linux_views, and chromeos, but everyone uses the same class
name. sizeof(linux_views BVI) > sizeof(linux_gtk BVI). Previously, the GTK
version allocated on object of linux_views BVI, and just had some uninitialized
memory at the end. Switching these around by changing the includes, the
linux_views implementation wrote past the sizeof the linux_gtk BVI. Fix by #ifdefing on TOOLKIT.
Fix style problems in the Balloon implementation on linux in preparation for
turning on chrome-style bot.
- Rename file that had all BalloonCollectionImpl code from
balloon_collection.cc to balloon_collection_impl.cc so I could add a real
balloon_collection.cc for deinlining.
- GTK implementation files shouldn't depend on views/ code.
BUG=none
TEST=compiles
Original Review URL: http://codereview.chromium.org/6400006
Review URL: http://codereview.chromium.org/6260040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73310 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/notifications/balloon_collection.cc | 376 | ||||
-rw-r--r-- | chrome/browser/notifications/balloon_collection.h | 8 | ||||
-rw-r--r-- | chrome/browser/notifications/balloon_collection_impl.cc | 382 | ||||
-rw-r--r-- | chrome/browser/notifications/balloon_collection_impl.h | 2 | ||||
-rw-r--r-- | chrome/browser/notifications/balloon_collection_linux.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/notifications/balloon_view_gtk.h | 2 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 3 |
7 files changed, 400 insertions, 380 deletions
diff --git a/chrome/browser/notifications/balloon_collection.cc b/chrome/browser/notifications/balloon_collection.cc index 0dc643d..48059f5 100644 --- a/chrome/browser/notifications/balloon_collection.cc +++ b/chrome/browser/notifications/balloon_collection.cc @@ -1,378 +1,12 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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_impl.h" +#include "chrome/browser/notifications/balloon_collection.h" -#include "base/logging.h" -#include "base/stl_util-inl.h" -#include "chrome/browser/notifications/balloon.h" -#include "chrome/browser/notifications/balloon_host.h" -#include "chrome/browser/notifications/notification.h" -#include "chrome/browser/ui/window_sizer.h" -#include "gfx/rect.h" -#include "gfx/size.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; - -// Delay from the mouse leaving the balloon collection before -// there is a relayout, in milliseconds. -const int kRepositionDelay = 300; - -} // namespace - -BalloonCollectionImpl::BalloonCollectionImpl() -#if USE_OFFSETS - : ALLOW_THIS_IN_INITIALIZER_LIST(reposition_factory_(this)), - added_as_message_loop_observer_(false) -#endif -{ - - SetPositionPreference(BalloonCollection::DEFAULT_POSITION); -} - -BalloonCollectionImpl::~BalloonCollectionImpl() { -} - -void BalloonCollectionImpl::Add(const Notification& notification, - Profile* profile) { - Balloon* new_balloon = MakeBalloon(notification, profile); - // The +1 on width is necessary because width is fixed on notifications, - // so since we always have the max size, we would always hit the scrollbar - // condition. We are only interested in comparing height to maximum. - new_balloon->set_min_scrollbar_size(gfx::Size(1 + layout_.max_balloon_width(), - layout_.max_balloon_height())); - new_balloon->SetPosition(layout_.OffScreenLocation(), false); - new_balloon->Show(); -#if USE_OFFSETS - int count = base_.count(); - if (count > 0 && layout_.RequiresOffsets()) - new_balloon->set_offset(base_.balloons()[count - 1]->offset()); -#endif - base_.Add(new_balloon); - PositionBalloons(false); - - // There may be no listener in a unit test. - if (space_change_listener_) - space_change_listener_->OnBalloonSpaceChanged(); - - // This is used only for testing. - if (on_collection_changed_callback_.get()) - on_collection_changed_callback_->Run(); -} - -bool BalloonCollectionImpl::RemoveById(const std::string& id) { - return base_.CloseById(id); -} - -bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) { - return base_.CloseAllBySourceOrigin(origin); -} - -void BalloonCollectionImpl::RemoveAll() { - base_.CloseAll(); -} - -bool BalloonCollectionImpl::HasSpace() const { - int count = base_.count(); - 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::ResizeBalloon(Balloon* balloon, - const gfx::Size& size) { - balloon->set_content_size(Layout::ConstrainToSizeLimits(size)); - PositionBalloons(true); -} - -void BalloonCollectionImpl::DisplayChanged() { - layout_.RefreshSystemMetrics(); - PositionBalloons(true); -} - -void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) { - // We want to free the balloon when finished. - const Balloons& balloons = base_.balloons(); - Balloons::const_iterator it = balloons.begin(); - -#if USE_OFFSETS - if (layout_.RequiresOffsets()) { - gfx::Point offset; - bool apply_offset = false; - while (it != balloons.end()) { - if (*it == source) { - ++it; - if (it != balloons.end()) { - apply_offset = true; - offset.set_y((source)->offset().y() - (*it)->offset().y() + - (*it)->content_size().height() - source->content_size().height()); - } - } else { - if (apply_offset) - (*it)->add_offset(offset); - ++it; - } - } - // Start listening for UI events so we cancel the offset when the mouse - // leaves the balloon area. - if (apply_offset) - AddMessageLoopObserver(); - } -#endif - - base_.Remove(source); - PositionBalloons(true); - - // There may be no listener in a unit test. - if (space_change_listener_) - space_change_listener_->OnBalloonSpaceChanged(); - - // This is used only for testing. - if (on_collection_changed_callback_.get()) - on_collection_changed_callback_->Run(); -} - -void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) { - const Balloons& balloons = base_.balloons(); - - layout_.RefreshSystemMetrics(); - gfx::Point origin = layout_.GetLayoutOrigin(); - for (Balloons::const_iterator it = balloons.begin(); - it != balloons.end(); - ++it) { - gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin); - (*it)->SetPosition(upper_left, reposition); - } +BalloonCollection::BalloonCollection() + : space_change_listener_(NULL) { } -gfx::Rect BalloonCollectionImpl::GetBalloonsBoundingBox() const { - // Start from the layout origin. - gfx::Rect bounds = gfx::Rect(layout_.GetLayoutOrigin(), gfx::Size(0, 0)); - - // For each balloon, extend the rectangle. This approach is indifferent to - // the orientation of the balloons. - const Balloons& balloons = base_.balloons(); - Balloons::const_iterator iter; - for (iter = balloons.begin(); iter != balloons.end(); ++iter) { - gfx::Rect balloon_box = gfx::Rect((*iter)->GetPosition(), - (*iter)->GetViewSize()); - bounds = bounds.Union(balloon_box); - } - - return bounds; -} - -#if USE_OFFSETS -void BalloonCollectionImpl::AddMessageLoopObserver() { - if (!added_as_message_loop_observer_) { - MessageLoopForUI::current()->AddObserver(this); - added_as_message_loop_observer_ = true; - } -} - -void BalloonCollectionImpl::RemoveMessageLoopObserver() { - if (added_as_message_loop_observer_) { - MessageLoopForUI::current()->RemoveObserver(this); - added_as_message_loop_observer_ = false; - } -} - -void BalloonCollectionImpl::CancelOffsets() { - reposition_factory_.RevokeAll(); - - // Unhook from listening to all UI events. - RemoveMessageLoopObserver(); - - const Balloons& balloons = base_.balloons(); - for (Balloons::const_iterator it = balloons.begin(); - it != balloons.end(); - ++it) - (*it)->set_offset(gfx::Point(0, 0)); - - PositionBalloons(true); -} - -void BalloonCollectionImpl::HandleMouseMoveEvent() { - if (!IsCursorInBalloonCollection()) { - // Mouse has left the region. Schedule a reposition after - // a short delay. - if (reposition_factory_.empty()) { - MessageLoop::current()->PostDelayedTask( - FROM_HERE, - reposition_factory_.NewRunnableMethod( - &BalloonCollectionImpl::CancelOffsets), - kRepositionDelay); - } - } else { - // Mouse moved back into the region. Cancel the reposition. - reposition_factory_.RevokeAll(); - } -} -#endif - -BalloonCollectionImpl::Layout::Layout() { - RefreshSystemMetrics(); -} - -void BalloonCollectionImpl::Layout::GetMaxLinearSize(int* max_balloon_size, - int* total_size) const { - DCHECK(max_balloon_size && total_size); - - // All placement schemes are vertical, so we only care about height. - *total_size = work_area_.height(); - *max_balloon_size = max_balloon_height(); -} - -gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const { - int x = 0; - int y = 0; - switch (placement_) { - case VERTICALLY_FROM_TOP_LEFT: - x = work_area_.x() + HorizontalEdgeMargin(); - y = work_area_.y() + VerticalEdgeMargin(); - break; - case VERTICALLY_FROM_TOP_RIGHT: - x = work_area_.right() - HorizontalEdgeMargin(); - y = work_area_.y() + VerticalEdgeMargin(); - break; - case VERTICALLY_FROM_BOTTOM_LEFT: - x = work_area_.x() + HorizontalEdgeMargin(); - y = work_area_.bottom() - VerticalEdgeMargin(); - break; - case VERTICALLY_FROM_BOTTOM_RIGHT: - x = work_area_.right() - HorizontalEdgeMargin(); - y = work_area_.bottom() - VerticalEdgeMargin(); - 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 VERTICALLY_FROM_TOP_LEFT: - x = position_iterator->x(); - y = position_iterator->y(); - position_iterator->set_y(position_iterator->y() + balloon_size.height() + - InterBalloonMargin()); - 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() + - InterBalloonMargin()); - break; - case VERTICALLY_FROM_BOTTOM_LEFT: - position_iterator->set_y(position_iterator->y() - balloon_size.height() - - InterBalloonMargin()); - x = position_iterator->x(); - y = position_iterator->y(); - break; - case VERTICALLY_FROM_BOTTOM_RIGHT: - position_iterator->set_y(position_iterator->y() - balloon_size.height() - - InterBalloonMargin()); - x = position_iterator->x() - balloon_size.width(); - y = position_iterator->y(); - break; - default: - NOTREACHED(); - break; - } - return gfx::Point(x, y); -} - -gfx::Point BalloonCollectionImpl::Layout::OffScreenLocation() const { - int x = 0; - int y = 0; - switch (placement_) { - case VERTICALLY_FROM_TOP_LEFT: - x = work_area_.x() + HorizontalEdgeMargin(); - y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin(); - break; - case VERTICALLY_FROM_TOP_RIGHT: - x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin(); - y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin(); - break; - case VERTICALLY_FROM_BOTTOM_LEFT: - x = work_area_.x() + HorizontalEdgeMargin(); - y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin(); - break; - case VERTICALLY_FROM_BOTTOM_RIGHT: - x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin(); - y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin(); - break; - default: - NOTREACHED(); - break; - } - return gfx::Point(x, y); -} - -bool BalloonCollectionImpl::Layout::RequiresOffsets() const { - // Layout schemes that grow up from the bottom require offsets; - // schemes that grow down do not require offsets. - bool offsets = (placement_ == VERTICALLY_FROM_BOTTOM_LEFT || - placement_ == VERTICALLY_FROM_BOTTOM_RIGHT); - -#if defined(OS_MACOSX) - // These schemes are in screen-coordinates, and top and bottom - // are inverted on Mac. - offsets = !offsets; -#endif - - return offsets; -} - -// static -gfx::Size BalloonCollectionImpl::Layout::ConstrainToSizeLimits( - const gfx::Size& size) { - // restrict to the min & max sizes - return gfx::Size( - std::max(min_balloon_width(), - std::min(max_balloon_width(), size.width())), - std::max(min_balloon_height(), - std::min(max_balloon_height(), size.height()))); -} - -bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() { - bool changed = false; - -#if defined(OS_MACOSX) - gfx::Rect new_work_area = GetMacWorkArea(); -#else - scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider( - WindowSizer::CreateDefaultMonitorInfoProvider()); - gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea(); -#endif - if (!work_area_.Equals(new_work_area)) { - work_area_.SetRect(new_work_area.x(), new_work_area.y(), - new_work_area.width(), new_work_area.height()); - changed = true; - } - - return changed; +BalloonCollection::~BalloonCollection() { } diff --git a/chrome/browser/notifications/balloon_collection.h b/chrome/browser/notifications/balloon_collection.h index 6909759..4cae9095 100644 --- a/chrome/browser/notifications/balloon_collection.h +++ b/chrome/browser/notifications/balloon_collection.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -48,11 +48,9 @@ class BalloonCollection { static BalloonCollection* Create(); - BalloonCollection() - : space_change_listener_(NULL) { - } + BalloonCollection(); - virtual ~BalloonCollection() {} + virtual ~BalloonCollection(); // Adds a new balloon for the specified notification. virtual void Add(const Notification& notification, diff --git a/chrome/browser/notifications/balloon_collection_impl.cc b/chrome/browser/notifications/balloon_collection_impl.cc new file mode 100644 index 0000000..4519922 --- /dev/null +++ b/chrome/browser/notifications/balloon_collection_impl.cc @@ -0,0 +1,382 @@ +// Copyright (c) 2010 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_impl.h" + +#include "base/logging.h" +#include "base/stl_util-inl.h" +#include "chrome/browser/notifications/balloon.h" +#include "chrome/browser/notifications/balloon_host.h" +#include "chrome/browser/notifications/notification.h" +#include "chrome/browser/ui/window_sizer.h" +#include "gfx/rect.h" +#include "gfx/size.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; + +// Delay from the mouse leaving the balloon collection before +// there is a relayout, in milliseconds. +const int kRepositionDelay = 300; + +} // namespace + +BalloonCollectionImpl::BalloonCollectionImpl() +#if USE_OFFSETS + : ALLOW_THIS_IN_INITIALIZER_LIST(reposition_factory_(this)), + added_as_message_loop_observer_(false) +#endif +{ + + SetPositionPreference(BalloonCollection::DEFAULT_POSITION); +} + +BalloonCollectionImpl::~BalloonCollectionImpl() { +} + +void BalloonCollectionImpl::Add(const Notification& notification, + Profile* profile) { + Balloon* new_balloon = MakeBalloon(notification, profile); + // The +1 on width is necessary because width is fixed on notifications, + // so since we always have the max size, we would always hit the scrollbar + // condition. We are only interested in comparing height to maximum. + new_balloon->set_min_scrollbar_size(gfx::Size(1 + layout_.max_balloon_width(), + layout_.max_balloon_height())); + new_balloon->SetPosition(layout_.OffScreenLocation(), false); + new_balloon->Show(); +#if USE_OFFSETS + int count = base_.count(); + if (count > 0 && layout_.RequiresOffsets()) + new_balloon->set_offset(base_.balloons()[count - 1]->offset()); +#endif + base_.Add(new_balloon); + PositionBalloons(false); + + // There may be no listener in a unit test. + if (space_change_listener_) + space_change_listener_->OnBalloonSpaceChanged(); + + // This is used only for testing. + if (on_collection_changed_callback_.get()) + on_collection_changed_callback_->Run(); +} + +bool BalloonCollectionImpl::RemoveById(const std::string& id) { + return base_.CloseById(id); +} + +bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) { + return base_.CloseAllBySourceOrigin(origin); +} + +void BalloonCollectionImpl::RemoveAll() { + base_.CloseAll(); +} + +bool BalloonCollectionImpl::HasSpace() const { + int count = base_.count(); + 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::ResizeBalloon(Balloon* balloon, + const gfx::Size& size) { + balloon->set_content_size(Layout::ConstrainToSizeLimits(size)); + PositionBalloons(true); +} + +void BalloonCollectionImpl::DisplayChanged() { + layout_.RefreshSystemMetrics(); + PositionBalloons(true); +} + +void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) { + // We want to free the balloon when finished. + const Balloons& balloons = base_.balloons(); + Balloons::const_iterator it = balloons.begin(); + +#if USE_OFFSETS + if (layout_.RequiresOffsets()) { + gfx::Point offset; + bool apply_offset = false; + while (it != balloons.end()) { + if (*it == source) { + ++it; + if (it != balloons.end()) { + apply_offset = true; + offset.set_y((source)->offset().y() - (*it)->offset().y() + + (*it)->content_size().height() - source->content_size().height()); + } + } else { + if (apply_offset) + (*it)->add_offset(offset); + ++it; + } + } + // Start listening for UI events so we cancel the offset when the mouse + // leaves the balloon area. + if (apply_offset) + AddMessageLoopObserver(); + } +#endif + + base_.Remove(source); + PositionBalloons(true); + + // There may be no listener in a unit test. + if (space_change_listener_) + space_change_listener_->OnBalloonSpaceChanged(); + + // This is used only for testing. + if (on_collection_changed_callback_.get()) + on_collection_changed_callback_->Run(); +} + +const BalloonCollection::Balloons& BalloonCollectionImpl::GetActiveBalloons() { + return base_.balloons(); +} + +void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) { + const Balloons& balloons = base_.balloons(); + + layout_.RefreshSystemMetrics(); + gfx::Point origin = layout_.GetLayoutOrigin(); + for (Balloons::const_iterator it = balloons.begin(); + it != balloons.end(); + ++it) { + gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin); + (*it)->SetPosition(upper_left, reposition); + } +} + +gfx::Rect BalloonCollectionImpl::GetBalloonsBoundingBox() const { + // Start from the layout origin. + gfx::Rect bounds = gfx::Rect(layout_.GetLayoutOrigin(), gfx::Size(0, 0)); + + // For each balloon, extend the rectangle. This approach is indifferent to + // the orientation of the balloons. + const Balloons& balloons = base_.balloons(); + Balloons::const_iterator iter; + for (iter = balloons.begin(); iter != balloons.end(); ++iter) { + gfx::Rect balloon_box = gfx::Rect((*iter)->GetPosition(), + (*iter)->GetViewSize()); + bounds = bounds.Union(balloon_box); + } + + return bounds; +} + +#if USE_OFFSETS +void BalloonCollectionImpl::AddMessageLoopObserver() { + if (!added_as_message_loop_observer_) { + MessageLoopForUI::current()->AddObserver(this); + added_as_message_loop_observer_ = true; + } +} + +void BalloonCollectionImpl::RemoveMessageLoopObserver() { + if (added_as_message_loop_observer_) { + MessageLoopForUI::current()->RemoveObserver(this); + added_as_message_loop_observer_ = false; + } +} + +void BalloonCollectionImpl::CancelOffsets() { + reposition_factory_.RevokeAll(); + + // Unhook from listening to all UI events. + RemoveMessageLoopObserver(); + + const Balloons& balloons = base_.balloons(); + for (Balloons::const_iterator it = balloons.begin(); + it != balloons.end(); + ++it) + (*it)->set_offset(gfx::Point(0, 0)); + + PositionBalloons(true); +} + +void BalloonCollectionImpl::HandleMouseMoveEvent() { + if (!IsCursorInBalloonCollection()) { + // Mouse has left the region. Schedule a reposition after + // a short delay. + if (reposition_factory_.empty()) { + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + reposition_factory_.NewRunnableMethod( + &BalloonCollectionImpl::CancelOffsets), + kRepositionDelay); + } + } else { + // Mouse moved back into the region. Cancel the reposition. + reposition_factory_.RevokeAll(); + } +} +#endif + +BalloonCollectionImpl::Layout::Layout() { + RefreshSystemMetrics(); +} + +void BalloonCollectionImpl::Layout::GetMaxLinearSize(int* max_balloon_size, + int* total_size) const { + DCHECK(max_balloon_size && total_size); + + // All placement schemes are vertical, so we only care about height. + *total_size = work_area_.height(); + *max_balloon_size = max_balloon_height(); +} + +gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const { + int x = 0; + int y = 0; + switch (placement_) { + case VERTICALLY_FROM_TOP_LEFT: + x = work_area_.x() + HorizontalEdgeMargin(); + y = work_area_.y() + VerticalEdgeMargin(); + break; + case VERTICALLY_FROM_TOP_RIGHT: + x = work_area_.right() - HorizontalEdgeMargin(); + y = work_area_.y() + VerticalEdgeMargin(); + break; + case VERTICALLY_FROM_BOTTOM_LEFT: + x = work_area_.x() + HorizontalEdgeMargin(); + y = work_area_.bottom() - VerticalEdgeMargin(); + break; + case VERTICALLY_FROM_BOTTOM_RIGHT: + x = work_area_.right() - HorizontalEdgeMargin(); + y = work_area_.bottom() - VerticalEdgeMargin(); + 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 VERTICALLY_FROM_TOP_LEFT: + x = position_iterator->x(); + y = position_iterator->y(); + position_iterator->set_y(position_iterator->y() + balloon_size.height() + + InterBalloonMargin()); + 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() + + InterBalloonMargin()); + break; + case VERTICALLY_FROM_BOTTOM_LEFT: + position_iterator->set_y(position_iterator->y() - balloon_size.height() - + InterBalloonMargin()); + x = position_iterator->x(); + y = position_iterator->y(); + break; + case VERTICALLY_FROM_BOTTOM_RIGHT: + position_iterator->set_y(position_iterator->y() - balloon_size.height() - + InterBalloonMargin()); + x = position_iterator->x() - balloon_size.width(); + y = position_iterator->y(); + break; + default: + NOTREACHED(); + break; + } + return gfx::Point(x, y); +} + +gfx::Point BalloonCollectionImpl::Layout::OffScreenLocation() const { + int x = 0; + int y = 0; + switch (placement_) { + case VERTICALLY_FROM_TOP_LEFT: + x = work_area_.x() + HorizontalEdgeMargin(); + y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin(); + break; + case VERTICALLY_FROM_TOP_RIGHT: + x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin(); + y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin(); + break; + case VERTICALLY_FROM_BOTTOM_LEFT: + x = work_area_.x() + HorizontalEdgeMargin(); + y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin(); + break; + case VERTICALLY_FROM_BOTTOM_RIGHT: + x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin(); + y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin(); + break; + default: + NOTREACHED(); + break; + } + return gfx::Point(x, y); +} + +bool BalloonCollectionImpl::Layout::RequiresOffsets() const { + // Layout schemes that grow up from the bottom require offsets; + // schemes that grow down do not require offsets. + bool offsets = (placement_ == VERTICALLY_FROM_BOTTOM_LEFT || + placement_ == VERTICALLY_FROM_BOTTOM_RIGHT); + +#if defined(OS_MACOSX) + // These schemes are in screen-coordinates, and top and bottom + // are inverted on Mac. + offsets = !offsets; +#endif + + return offsets; +} + +// static +gfx::Size BalloonCollectionImpl::Layout::ConstrainToSizeLimits( + const gfx::Size& size) { + // restrict to the min & max sizes + return gfx::Size( + std::max(min_balloon_width(), + std::min(max_balloon_width(), size.width())), + std::max(min_balloon_height(), + std::min(max_balloon_height(), size.height()))); +} + +bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() { + bool changed = false; + +#if defined(OS_MACOSX) + gfx::Rect new_work_area = GetMacWorkArea(); +#else + scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider( + WindowSizer::CreateDefaultMonitorInfoProvider()); + gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea(); +#endif + if (!work_area_.Equals(new_work_area)) { + work_area_.SetRect(new_work_area.x(), new_work_area.y(), + new_work_area.width(), new_work_area.height()); + changed = true; + } + + return changed; +} diff --git a/chrome/browser/notifications/balloon_collection_impl.h b/chrome/browser/notifications/balloon_collection_impl.h index bb4525d..9802280 100644 --- a/chrome/browser/notifications/balloon_collection_impl.h +++ b/chrome/browser/notifications/balloon_collection_impl.h @@ -50,7 +50,7 @@ class BalloonCollectionImpl : public BalloonCollection virtual void SetPositionPreference(PositionPreference position); virtual void DisplayChanged(); virtual void OnBalloonClosed(Balloon* source); - virtual const Balloons& GetActiveBalloons() { return base_.balloons(); } + virtual const Balloons& GetActiveBalloons(); // MessageLoopForUI::Observer interface. #if defined(OS_WIN) diff --git a/chrome/browser/notifications/balloon_collection_linux.cc b/chrome/browser/notifications/balloon_collection_linux.cc index 038746c..03f0de1 100644 --- a/chrome/browser/notifications/balloon_collection_linux.cc +++ b/chrome/browser/notifications/balloon_collection_linux.cc @@ -5,9 +5,14 @@ #include "chrome/browser/notifications/balloon_collection_impl.h" #include "chrome/browser/notifications/balloon.h" -#include "chrome/browser/ui/views/notifications/balloon_view.h" #include "gfx/size.h" +#if defined(TOOLKIT_VIEWS) +#include "chrome/browser/ui/views/notifications/balloon_view.h" +#else +#include "chrome/browser/ui/gtk/notifications/balloon_view_gtk.h" +#endif + Balloon* BalloonCollectionImpl::MakeBalloon(const Notification& notification, Profile* profile) { Balloon* balloon = new Balloon(notification, profile, this); diff --git a/chrome/browser/ui/gtk/notifications/balloon_view_gtk.h b/chrome/browser/ui/gtk/notifications/balloon_view_gtk.h index 0c504ff..d8a4efa 100644 --- a/chrome/browser/ui/gtk/notifications/balloon_view_gtk.h +++ b/chrome/browser/ui/gtk/notifications/balloon_view_gtk.h @@ -41,7 +41,7 @@ class BalloonViewImpl : public BalloonView, public ui::AnimationDelegate { public: explicit BalloonViewImpl(BalloonCollection* collection); - ~BalloonViewImpl(); + virtual ~BalloonViewImpl(); // BalloonView interface. virtual void Show(Balloon* balloon); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 7c33c93..3e72efe 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1646,6 +1646,7 @@ 'browser/notifications/balloon_collection.h', 'browser/notifications/balloon_collection_base.cc', 'browser/notifications/balloon_collection_base.h', + 'browser/notifications/balloon_collection_impl.cc', 'browser/notifications/balloon_collection_impl.h', 'browser/notifications/balloon_collection_linux.cc', 'browser/notifications/balloon_collection_mac.mm', @@ -4358,7 +4359,7 @@ ['exclude', '^browser/extensions/extension_tts_api_linux.cc'], ['exclude', '^browser/geolocation/wifi_data_provider_linux.cc'], ['exclude', '^browser/geolocation/wifi_data_provider_linux.h'], - ['exclude', '^browser/notifications/balloon_collection.cc'], + ['exclude', '^browser/notifications/balloon_collection_impl.cc'], ['exclude', '^browser/notifications/balloon_collection_impl.h'], ['exclude', '^browser/notifications/balloon_collection_linux.cc'], ], |