Chromium Code Reviews| Index: chrome/browser/notifications/balloon_collection_impl.cc |
| diff --git a/chrome/browser/notifications/balloon_collection_impl.cc b/chrome/browser/notifications/balloon_collection_impl.cc |
| index 9d234c222aa41ebe7753061c00b7ec4f1c3bccbc..085767d89e4450c7d9e9c78d0cd8b4f4056086aa 100644 |
| --- a/chrome/browser/notifications/balloon_collection_impl.cc |
| +++ b/chrome/browser/notifications/balloon_collection_impl.cc |
| @@ -10,7 +10,13 @@ |
| #include "chrome/browser/notifications/balloon.h" |
| #include "chrome/browser/notifications/balloon_host.h" |
| #include "chrome/browser/notifications/notification.h" |
| +#include "chrome/browser/ui/browser.h" |
| +#include "chrome/browser/ui/panels/panel_manager.h" |
| +#include "chrome/browser/ui/panels/panel.h" |
| #include "chrome/browser/ui/window_sizer.h" |
| +#include "chrome/common/chrome_notification_types.h" |
| +#include "content/public/browser/notification_registrar.h" |
| +#include "content/public/browser/notification_service.h" |
| #include "ui/gfx/rect.h" |
| #include "ui/gfx/size.h" |
| @@ -35,6 +41,12 @@ BalloonCollectionImpl::BalloonCollectionImpl() |
| added_as_message_loop_observer_(false) |
| #endif |
| { |
| + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY, |
|
jennb
2011/11/10 19:17:13
Instead of these browser notifications, perhaps be
jianli
2011/11/11 00:38:30
Done.
|
| + content::NotificationService::AllSources()); |
| + registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED, |
| + content::NotificationService::AllSources()); |
| + registrar_.Add(this, chrome::NOTIFICATION_PANEL_CHANGED_BOUNDS, |
| + content::NotificationService::AllSources()); |
| SetPositionPreference(BalloonCollection::DEFAULT_POSITION); |
| } |
| @@ -153,6 +165,36 @@ const BalloonCollection::Balloons& BalloonCollectionImpl::GetActiveBalloons() { |
| return base_.balloons(); |
| } |
| +void BalloonCollectionImpl::Observe( |
| + int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + Browser* closed_browser = NULL; |
| + switch (type) { |
| + case chrome::NOTIFICATION_BROWSER_WINDOW_READY: { |
| + Browser* browser = content::Source<Browser>(source).ptr(); |
| + if (!browser->is_type_panel()) |
| + return; |
| + break; |
| + } |
| + case chrome::NOTIFICATION_BROWSER_CLOSED: { |
| + Browser* browser = content::Source<Browser>(source).ptr(); |
| + if (!browser->is_type_panel()) |
| + return; |
| + closed_browser = browser; |
|
Dmitry Titov
2011/11/10 18:35:45
Lets add a notification when panel is removed from
jianli
2011/11/11 00:38:30
Done.
|
| + break; |
| + } |
| + case chrome::NOTIFICATION_PANEL_CHANGED_BOUNDS: |
|
jennb
2011/11/10 19:17:13
Should you check the panel bounds here and only do
jianli
2011/11/11 00:38:30
Done.
|
| + break; |
| + default: |
| + NOTREACHED(); |
| + return; |
| + } |
| + |
| + if (layout_.ComputeOffsetsToMoveAbovePanels(closed_browser)) |
| + PositionBalloons(true); |
| +} |
| + |
| void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) { |
| const Balloons& balloons = base_.balloons(); |
| @@ -231,7 +273,10 @@ void BalloonCollectionImpl::HandleMouseMoveEvent() { |
| } |
| #endif |
| -BalloonCollectionImpl::Layout::Layout() : placement_(INVALID) { |
| +BalloonCollectionImpl::Layout::Layout() |
| + : placement_(INVALID), |
| + bottom_left_offset_to_move_above_panels_(0), |
| + bottom_right_offset_to_move_above_panels_(0) { |
| RefreshSystemMetrics(); |
| } |
| @@ -244,33 +289,6 @@ void BalloonCollectionImpl::Layout::GetMaxLinearSize(int* max_balloon_size, |
| *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 { |
| @@ -311,30 +329,21 @@ gfx::Point BalloonCollectionImpl::Layout::NextPosition( |
| } |
| gfx::Point BalloonCollectionImpl::Layout::OffScreenLocation() const { |
| - int x = 0; |
| - int y = 0; |
| + gfx::Point location = GetLayoutOrigin(); |
| 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(); |
| + location.Offset(0, kBalloonMaxHeight); |
| break; |
| + case VERTICALLY_FROM_TOP_RIGHT: |
| case VERTICALLY_FROM_BOTTOM_RIGHT: |
| - x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin(); |
| - y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin(); |
| + location.Offset(-kBalloonMaxWidth, kBalloonMaxHeight); |
| break; |
| default: |
| NOTREACHED(); |
| break; |
| } |
| - return gfx::Point(x, y); |
| + return location; |
| } |
| bool BalloonCollectionImpl::Layout::RequiresOffsets() const { |
| @@ -363,6 +372,67 @@ gfx::Size BalloonCollectionImpl::Layout::ConstrainToSizeLimits( |
| std::min(max_balloon_height(), size.height()))); |
| } |
| +bool BalloonCollectionImpl::Layout::ComputeOffsetsToMoveAbovePanels( |
| + Browser* closed_browser) { |
| + const PanelManager::Panels& panels = PanelManager::GetInstance()->panels(); |
| + |
| + // For balloons that are aligned vertically from bottom-right corner, the |
| + // offset is the maximum height of the right-most panels that could overlap |
| + // with the balloons. |
| + int bottom_right_offset_to_move_above_panels = 0; |
| + for (PanelManager::Panels::const_iterator iter = panels.begin(); |
| + iter != panels.end(); ++iter) { |
| + // No need to check panels beyond the area occupied by the balloons. |
| + if ((*iter)->GetBounds().right() <= |
| + work_area_.right() - max_balloon_width()) |
| + break; |
| + |
| + // Skip the panel that is currently being closed. We might not remove it |
| + // from the panel manager yet. |
| + if ((*iter)->browser() == closed_browser) |
| + continue; |
| + |
| + int current_height = (*iter)->GetBounds().height(); |
| + if (current_height > bottom_right_offset_to_move_above_panels) |
| + bottom_right_offset_to_move_above_panels = current_height; |
| + } |
| + |
| + // For balloons that are aligned vertically from bottom-left corner, the |
| + // offset is the maximum height of the left-most panels that could overlap |
| + // with the balloons. |
| + int bottom_left_offset_to_move_above_panels = 0; |
| + for (PanelManager::Panels::const_reverse_iterator iter = panels.rbegin(); |
| + iter != panels.rend(); ++iter) { |
| + // No need to check panels beyond the area occupied by the balloons. |
| + if ((*iter)->GetBounds().x() > work_area_.x() + max_balloon_width()) |
| + break; |
| + |
| + // Skip the panel that is currently being closed. We might not remove it |
| + // from the panel manager yet. |
| + if ((*iter)->browser() == closed_browser) |
| + continue; |
| + |
| + int current_height = (*iter)->GetBounds().height(); |
| + if (current_height > bottom_left_offset_to_move_above_panels) |
| + bottom_left_offset_to_move_above_panels = current_height; |
| + } |
| + |
| + // If no change is detected, return false to indicate that we do not need to |
| + // reposition balloons. |
| + if (bottom_right_offset_to_move_above_panels_ == |
| + bottom_right_offset_to_move_above_panels && |
| + bottom_left_offset_to_move_above_panels_ == |
| + bottom_left_offset_to_move_above_panels) { |
| + return false; |
| + } |
| + |
| + bottom_right_offset_to_move_above_panels_ = |
| + bottom_right_offset_to_move_above_panels; |
| + bottom_left_offset_to_move_above_panels_ = |
| + bottom_left_offset_to_move_above_panels; |
| + return true; |
| +} |
| + |
| bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() { |
| bool changed = false; |