| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #include "chrome/browser/notifications/balloon_collection_impl.h" | 5 #include "chrome/browser/notifications/balloon_collection_impl.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/stl_util-inl.h" | 8 #include "base/stl_util-inl.h" |
| 9 #include "chrome/browser/notifications/balloon.h" | 9 #include "chrome/browser/notifications/balloon.h" |
| 10 #include "chrome/browser/notifications/balloon_host.h" | 10 #include "chrome/browser/notifications/balloon_host.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 | 38 |
| 39 BalloonCollectionImpl::BalloonCollectionImpl() | 39 BalloonCollectionImpl::BalloonCollectionImpl() |
| 40 #if USE_OFFSETS | 40 #if USE_OFFSETS |
| 41 : ALLOW_THIS_IN_INITIALIZER_LIST(reposition_factory_(this)), | 41 : ALLOW_THIS_IN_INITIALIZER_LIST(reposition_factory_(this)), |
| 42 added_as_message_loop_observer_(false) | 42 added_as_message_loop_observer_(false) |
| 43 #endif | 43 #endif |
| 44 { | 44 { |
| 45 } | 45 } |
| 46 | 46 |
| 47 BalloonCollectionImpl::~BalloonCollectionImpl() { | 47 BalloonCollectionImpl::~BalloonCollectionImpl() { |
| 48 STLDeleteElements(&balloons_); | |
| 49 } | 48 } |
| 50 | 49 |
| 51 void BalloonCollectionImpl::Add(const Notification& notification, | 50 void BalloonCollectionImpl::Add(const Notification& notification, |
| 52 Profile* profile) { | 51 Profile* profile) { |
| 53 Balloon* new_balloon = MakeBalloon(notification, profile); | 52 Balloon* new_balloon = MakeBalloon(notification, profile); |
| 54 // The +1 on width is necessary because width is fixed on notifications, | 53 // The +1 on width is necessary because width is fixed on notifications, |
| 55 // so since we always have the max size, we would always hit the scrollbar | 54 // so since we always have the max size, we would always hit the scrollbar |
| 56 // condition. We are only interested in comparing height to maximum. | 55 // condition. We are only interested in comparing height to maximum. |
| 57 new_balloon->set_min_scrollbar_size(gfx::Size(1 + layout_.max_balloon_width(), | 56 new_balloon->set_min_scrollbar_size(gfx::Size(1 + layout_.max_balloon_width(), |
| 58 layout_.max_balloon_height())); | 57 layout_.max_balloon_height())); |
| 59 new_balloon->SetPosition(layout_.OffScreenLocation(), false); | 58 new_balloon->SetPosition(layout_.OffScreenLocation(), false); |
| 60 new_balloon->Show(); | 59 new_balloon->Show(); |
| 61 #if USE_OFFSETS | 60 #if USE_OFFSETS |
| 62 if (balloons_.size() > 0) | 61 int count = base_.count(); |
| 63 new_balloon->set_offset(balloons_[balloons_.size() - 1]->offset()); | 62 if (count > 0) |
| 63 new_balloon->set_offset(base_.balloons()[count - 1]->offset()); |
| 64 #endif | 64 #endif |
| 65 balloons_.push_back(new_balloon); | 65 base_.Add(new_balloon); |
| 66 PositionBalloons(false); | 66 PositionBalloons(false); |
| 67 | 67 |
| 68 // There may be no listener in a unit test. | 68 // There may be no listener in a unit test. |
| 69 if (space_change_listener_) | 69 if (space_change_listener_) |
| 70 space_change_listener_->OnBalloonSpaceChanged(); | 70 space_change_listener_->OnBalloonSpaceChanged(); |
| 71 | 71 |
| 72 // This is used only for testing. | 72 // This is used only for testing. |
| 73 if (on_collection_changed_callback_.get()) | 73 if (on_collection_changed_callback_.get()) |
| 74 on_collection_changed_callback_->Run(); | 74 on_collection_changed_callback_->Run(); |
| 75 } | 75 } |
| 76 | 76 |
| 77 bool BalloonCollectionImpl::Remove(const Notification& notification) { | 77 bool BalloonCollectionImpl::RemoveById(const std::string& id) { |
| 78 Balloons::iterator iter; | 78 return base_.CloseById(id); |
| 79 for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) { | 79 } |
| 80 if (notification.IsSame((*iter)->notification())) { | 80 |
| 81 // Balloon.CloseByScript() will cause OnBalloonClosed() to be called on | 81 bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) { |
| 82 // this object, which will remove it from the collection and free it. | 82 return base_.CloseAllBySourceOrigin(origin); |
| 83 (*iter)->CloseByScript(); | |
| 84 return true; | |
| 85 } | |
| 86 } | |
| 87 return false; | |
| 88 } | 83 } |
| 89 | 84 |
| 90 bool BalloonCollectionImpl::HasSpace() const { | 85 bool BalloonCollectionImpl::HasSpace() const { |
| 91 if (count() < kMinAllowedBalloonCount) | 86 int count = base_.count(); |
| 87 if (count < kMinAllowedBalloonCount) |
| 92 return true; | 88 return true; |
| 93 | 89 |
| 94 int max_balloon_size = 0; | 90 int max_balloon_size = 0; |
| 95 int total_size = 0; | 91 int total_size = 0; |
| 96 layout_.GetMaxLinearSize(&max_balloon_size, &total_size); | 92 layout_.GetMaxLinearSize(&max_balloon_size, &total_size); |
| 97 | 93 |
| 98 int current_max_size = max_balloon_size * count(); | 94 int current_max_size = max_balloon_size * count; |
| 99 int max_allowed_size = static_cast<int>(total_size * | 95 int max_allowed_size = static_cast<int>(total_size * |
| 100 kPercentBalloonFillFactor); | 96 kPercentBalloonFillFactor); |
| 101 return current_max_size < max_allowed_size - max_balloon_size; | 97 return current_max_size < max_allowed_size - max_balloon_size; |
| 102 } | 98 } |
| 103 | 99 |
| 104 void BalloonCollectionImpl::ResizeBalloon(Balloon* balloon, | 100 void BalloonCollectionImpl::ResizeBalloon(Balloon* balloon, |
| 105 const gfx::Size& size) { | 101 const gfx::Size& size) { |
| 106 balloon->set_content_size(Layout::ConstrainToSizeLimits(size)); | 102 balloon->set_content_size(Layout::ConstrainToSizeLimits(size)); |
| 107 PositionBalloons(true); | 103 PositionBalloons(true); |
| 108 } | 104 } |
| 109 | 105 |
| 110 void BalloonCollectionImpl::DisplayChanged() { | 106 void BalloonCollectionImpl::DisplayChanged() { |
| 111 layout_.RefreshSystemMetrics(); | 107 layout_.RefreshSystemMetrics(); |
| 112 PositionBalloons(true); | 108 PositionBalloons(true); |
| 113 } | 109 } |
| 114 | 110 |
| 115 void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) { | 111 void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) { |
| 116 // We want to free the balloon when finished. | 112 // We want to free the balloon when finished. |
| 117 scoped_ptr<Balloon> closed(source); | 113 const Balloons& balloons = base_.balloons(); |
| 118 Balloons::iterator it = balloons_.begin(); | 114 Balloons::const_iterator it = balloons.begin(); |
| 119 | 115 |
| 120 #if USE_OFFSETS | 116 #if USE_OFFSETS |
| 121 gfx::Point offset; | 117 gfx::Point offset; |
| 122 bool apply_offset = false; | 118 bool apply_offset = false; |
| 123 while (it != balloons_.end()) { | 119 while (it != balloons.end()) { |
| 124 if (*it == source) { | 120 if (*it == source) { |
| 125 it = balloons_.erase(it); | 121 ++it; |
| 126 if (it != balloons_.end()) { | 122 if (it != balloons.end()) { |
| 127 apply_offset = true; | 123 apply_offset = true; |
| 128 offset.set_y((source)->offset().y() - (*it)->offset().y() + | 124 offset.set_y((source)->offset().y() - (*it)->offset().y() + |
| 129 (*it)->content_size().height() - source->content_size().height()); | 125 (*it)->content_size().height() - source->content_size().height()); |
| 130 } | 126 } |
| 131 } else { | 127 } else { |
| 132 if (apply_offset) | 128 if (apply_offset) |
| 133 (*it)->add_offset(offset); | 129 (*it)->add_offset(offset); |
| 134 ++it; | 130 ++it; |
| 135 } | 131 } |
| 136 } | 132 } |
| 137 // Start listening for UI events so we cancel the offset when the mouse | 133 // Start listening for UI events so we cancel the offset when the mouse |
| 138 // leaves the balloon area. | 134 // leaves the balloon area. |
| 139 if (apply_offset) | 135 if (apply_offset) |
| 140 AddMessageLoopObserver(); | 136 AddMessageLoopObserver(); |
| 141 #else | |
| 142 for (; it != balloons_.end(); ++it) { | |
| 143 if (*it == source) { | |
| 144 balloons_.erase(it); | |
| 145 break; | |
| 146 } | |
| 147 } | |
| 148 #endif | 137 #endif |
| 149 | 138 |
| 139 base_.Remove(source); |
| 150 PositionBalloons(true); | 140 PositionBalloons(true); |
| 151 | 141 |
| 152 // There may be no listener in a unit test. | 142 // There may be no listener in a unit test. |
| 153 if (space_change_listener_) | 143 if (space_change_listener_) |
| 154 space_change_listener_->OnBalloonSpaceChanged(); | 144 space_change_listener_->OnBalloonSpaceChanged(); |
| 155 | 145 |
| 156 // This is used only for testing. | 146 // This is used only for testing. |
| 157 if (on_collection_changed_callback_.get()) | 147 if (on_collection_changed_callback_.get()) |
| 158 on_collection_changed_callback_->Run(); | 148 on_collection_changed_callback_->Run(); |
| 159 } | 149 } |
| 160 | 150 |
| 161 void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) { | 151 void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) { |
| 152 const Balloons& balloons = base_.balloons(); |
| 153 |
| 162 layout_.RefreshSystemMetrics(); | 154 layout_.RefreshSystemMetrics(); |
| 163 gfx::Point origin = layout_.GetLayoutOrigin(); | 155 gfx::Point origin = layout_.GetLayoutOrigin(); |
| 164 for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) { | 156 for (Balloons::const_iterator it = balloons.begin(); |
| 157 it != balloons.end(); |
| 158 ++it) { |
| 165 gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin); | 159 gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin); |
| 166 (*it)->SetPosition(upper_left, reposition); | 160 (*it)->SetPosition(upper_left, reposition); |
| 167 } | 161 } |
| 168 } | 162 } |
| 169 | 163 |
| 170 #if USE_OFFSETS | 164 #if USE_OFFSETS |
| 171 void BalloonCollectionImpl::AddMessageLoopObserver() { | 165 void BalloonCollectionImpl::AddMessageLoopObserver() { |
| 172 if (!added_as_message_loop_observer_) { | 166 if (!added_as_message_loop_observer_) { |
| 173 MessageLoopForUI::current()->AddObserver(this); | 167 MessageLoopForUI::current()->AddObserver(this); |
| 174 added_as_message_loop_observer_ = true; | 168 added_as_message_loop_observer_ = true; |
| 175 } | 169 } |
| 176 } | 170 } |
| 177 | 171 |
| 178 void BalloonCollectionImpl::RemoveMessageLoopObserver() { | 172 void BalloonCollectionImpl::RemoveMessageLoopObserver() { |
| 179 if (added_as_message_loop_observer_) { | 173 if (added_as_message_loop_observer_) { |
| 180 MessageLoopForUI::current()->RemoveObserver(this); | 174 MessageLoopForUI::current()->RemoveObserver(this); |
| 181 added_as_message_loop_observer_ = false; | 175 added_as_message_loop_observer_ = false; |
| 182 } | 176 } |
| 183 } | 177 } |
| 184 | 178 |
| 185 void BalloonCollectionImpl::CancelOffsets() { | 179 void BalloonCollectionImpl::CancelOffsets() { |
| 186 reposition_factory_.RevokeAll(); | 180 reposition_factory_.RevokeAll(); |
| 187 | 181 |
| 188 // Unhook from listening to all UI events. | 182 // Unhook from listening to all UI events. |
| 189 RemoveMessageLoopObserver(); | 183 RemoveMessageLoopObserver(); |
| 190 | 184 |
| 191 for (Balloons::iterator it = balloons_.begin(); it != balloons_.end(); ++it) | 185 const Balloons& balloons = base_.balloons(); |
| 186 for (Balloons::const_iterator it = balloons.begin(); |
| 187 it != balloons.end(); |
| 188 ++it) |
| 192 (*it)->set_offset(gfx::Point(0, 0)); | 189 (*it)->set_offset(gfx::Point(0, 0)); |
| 193 | 190 |
| 194 PositionBalloons(true); | 191 PositionBalloons(true); |
| 195 } | 192 } |
| 196 | 193 |
| 197 void BalloonCollectionImpl::HandleMouseMoveEvent() { | 194 void BalloonCollectionImpl::HandleMouseMoveEvent() { |
| 198 if (!IsCursorInBalloonCollection()) { | 195 if (!IsCursorInBalloonCollection()) { |
| 199 // Mouse has left the region. Schedule a reposition after | 196 // Mouse has left the region. Schedule a reposition after |
| 200 // a short delay. | 197 // a short delay. |
| 201 if (reposition_factory_.empty()) { | 198 if (reposition_factory_.empty()) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea(); | 316 gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea(); |
| 320 #endif | 317 #endif |
| 321 if (!work_area_.Equals(new_work_area)) { | 318 if (!work_area_.Equals(new_work_area)) { |
| 322 work_area_.SetRect(new_work_area.x(), new_work_area.y(), | 319 work_area_.SetRect(new_work_area.x(), new_work_area.y(), |
| 323 new_work_area.width(), new_work_area.height()); | 320 new_work_area.width(), new_work_area.height()); |
| 324 changed = true; | 321 changed = true; |
| 325 } | 322 } |
| 326 | 323 |
| 327 return changed; | 324 return changed; |
| 328 } | 325 } |
| OLD | NEW |