| 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 | 
|---|