| 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 // Draws the view for the balloons. | 5 // Draws the view for the balloons. |
| 6 | 6 |
| 7 #include "chrome/browser/chromeos/notifications/notification_panel.h" | 7 #include "chrome/browser/chromeos/notifications/notification_panel.h" |
| 8 | 8 |
| 9 #include "app/gfx/canvas.h" | 9 #include "app/gfx/canvas.h" |
| 10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 class PanelWidget : public views::WidgetGtk { | 35 class PanelWidget : public views::WidgetGtk { |
| 36 public: | 36 public: |
| 37 explicit PanelWidget(chromeos::NotificationPanel* panel) | 37 explicit PanelWidget(chromeos::NotificationPanel* panel) |
| 38 : WidgetGtk(views::WidgetGtk::TYPE_WINDOW), | 38 : WidgetGtk(views::WidgetGtk::TYPE_WINDOW), |
| 39 panel_(panel) { | 39 panel_(panel) { |
| 40 } | 40 } |
| 41 | 41 |
| 42 // views::WidgetGtk overrides. | 42 // views::WidgetGtk overrides. |
| 43 virtual gboolean OnMotionNotify(GtkWidget* widget, GdkEventMotion* event) { | 43 virtual gboolean OnMotionNotify(GtkWidget* widget, GdkEventMotion* event) { |
| 44 gboolean result = WidgetGtk::OnMotionNotify(widget, event); | 44 gboolean result = WidgetGtk::OnMotionNotify(widget, event); |
| 45 panel_->DontUpdatePanelOnStale(); | 45 panel_->OnMouseMotion(); |
| 46 return result; | 46 return result; |
| 47 } | 47 } |
| 48 | 48 |
| 49 virtual gboolean OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event) { | 49 virtual gboolean OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event) { |
| 50 gboolean result = views::WidgetGtk::OnLeaveNotify(widget, event); | 50 gboolean result = views::WidgetGtk::OnLeaveNotify(widget, event); |
| 51 // Leave notify can happen if the mouse moves into the child gdk window. | 51 // Leave notify can happen if the mouse moves into the child gdk window. |
| 52 // Make sure the mouse is outside of the panel. | 52 // Make sure the mouse is outside of the panel. |
| 53 gfx::Point p(event->x_root, event->y_root); | 53 gfx::Point p(event->x_root, event->y_root); |
| 54 gfx::Rect bounds; | 54 gfx::Rect bounds; |
| 55 GetBounds(&bounds, true); | 55 GetBounds(&bounds, true); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 72 | 72 |
| 73 virtual ~BalloonSubContainer() {} | 73 virtual ~BalloonSubContainer() {} |
| 74 | 74 |
| 75 // views::View overrides. | 75 // views::View overrides. |
| 76 virtual gfx::Size GetPreferredSize() { | 76 virtual gfx::Size GetPreferredSize() { |
| 77 return preferred_size_; | 77 return preferred_size_; |
| 78 } | 78 } |
| 79 | 79 |
| 80 virtual void Layout() { | 80 virtual void Layout() { |
| 81 // Layout bottom up | 81 // Layout bottom up |
| 82 int count = GetChildViewCount(); | |
| 83 int height = 0; | 82 int height = 0; |
| 84 for (int i = count - 1; i >= 0; --i) { | 83 for (int i = GetChildViewCount() - 1; i >= 0; --i) { |
| 85 views::View* child = GetChildViewAt(i); | 84 views::View* child = GetChildViewAt(i); |
| 86 child->SetBounds(0, height, child->width(), child->height()); | 85 child->SetBounds(0, height, child->width(), child->height()); |
| 87 height += child->height() + margin_; | 86 height += child->height() + margin_; |
| 88 } | 87 } |
| 89 SchedulePaint(); | 88 SchedulePaint(); |
| 90 } | 89 } |
| 91 | 90 |
| 92 // Updates the bound so that it can show all balloons. | 91 // Updates the bound so that it can show all balloons. |
| 93 void UpdateBounds() { | 92 void UpdateBounds() { |
| 94 int height = 0; | 93 int height = 0; |
| 95 int max_width = 0; | 94 int max_width = 0; |
| 96 for (int i = GetChildViewCount() - 1; i >= 0; --i) { | 95 for (int i = GetChildViewCount() - 1; i >= 0; --i) { |
| 97 views::View* c = GetChildViewAt(i); | 96 views::View* child = GetChildViewAt(i); |
| 98 height += c->height() + margin_; | 97 height += child->height() + margin_; |
| 99 max_width = std::max(max_width, c->width()); | 98 max_width = std::max(max_width, child->width()); |
| 100 } | 99 } |
| 101 if (height > 0) | 100 if (height > 0) |
| 102 height -= margin_; | 101 height -= margin_; |
| 103 preferred_size_.set_width(max_width); | 102 preferred_size_.set_width(max_width); |
| 104 preferred_size_.set_height(height); | 103 preferred_size_.set_height(height); |
| 105 SizeToPreferredSize(); | 104 SizeToPreferredSize(); |
| 106 } | 105 } |
| 107 | 106 |
| 108 // Returns the bounds that covers new notifications. | 107 // Returns the bounds that covers new notifications. |
| 109 gfx::Rect GetNewBounds() { | 108 gfx::Rect GetNewBounds() { |
| 110 gfx::Rect rect; | 109 gfx::Rect rect; |
| 111 for (int i = GetChildViewCount() - 1; i >= 0; --i) { | 110 for (int i = GetChildViewCount() - 1; i >= 0; --i) { |
| 112 BalloonViewImpl* view = | 111 BalloonViewImpl* view = |
| 113 static_cast<BalloonViewImpl*>(GetChildViewAt(i)); | 112 static_cast<BalloonViewImpl*>(GetChildViewAt(i)); |
| 114 if (!view->stale()) { | 113 if (!view->stale()) { |
| 115 if (rect.IsEmpty()) { | 114 if (rect.IsEmpty()) { |
| 116 rect = view->bounds(); | 115 rect = view->bounds(); |
| 117 } else { | 116 } else { |
| 118 rect = rect.Union(bounds()); | 117 rect = rect.Union(view->bounds()); |
| 119 } | 118 } |
| 120 } | 119 } |
| 121 } | 120 } |
| 122 return gfx::Rect(x(), y(), rect.width(), rect.height()); | 121 return gfx::Rect(x(), y(), rect.width(), rect.height()); |
| 123 } | 122 } |
| 124 | 123 |
| 125 // Returns # of new notifications. | 124 // Returns # of new notifications. |
| 126 int GetNewCount() { | 125 int GetNewCount() { |
| 127 int count = 0; | 126 int count = 0; |
| 128 for (int i = GetChildViewCount() - 1; i >= 0; --i) { | 127 for (int i = GetChildViewCount() - 1; i >= 0; --i) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 0, sticky_container_->bounds().bottom() + margin, | 175 0, sticky_container_->bounds().bottom() + margin, |
| 177 width(), non_sticky_container_->height()); | 176 width(), non_sticky_container_->height()); |
| 178 } | 177 } |
| 179 | 178 |
| 180 virtual gfx::Size GetPreferredSize() { | 179 virtual gfx::Size GetPreferredSize() { |
| 181 return preferred_size_; | 180 return preferred_size_; |
| 182 } | 181 } |
| 183 | 182 |
| 184 // Returns the size that covers sticky and new notifications. | 183 // Returns the size that covers sticky and new notifications. |
| 185 gfx::Size GetStickyNewSize() { | 184 gfx::Size GetStickyNewSize() { |
| 186 gfx::Rect new_sticky = sticky_container_->bounds(); | 185 gfx::Rect sticky = sticky_container_->bounds(); |
| 187 gfx::Rect new_non_sticky = non_sticky_container_->GetNewBounds(); | 186 gfx::Rect new_non_sticky = non_sticky_container_->GetNewBounds(); |
| 188 if (new_sticky.IsEmpty()) | 187 if (sticky.IsEmpty()) |
| 189 return new_non_sticky.size(); | 188 return new_non_sticky.size(); |
| 190 if (new_non_sticky.IsEmpty()) | 189 if (new_non_sticky.IsEmpty()) |
| 191 return new_sticky.size(); | 190 return sticky.size(); |
| 192 return new_sticky.Union(new_non_sticky).size(); | 191 return sticky.Union(new_non_sticky).size(); |
| 193 } | 192 } |
| 194 | 193 |
| 195 // Adds a ballon to the panel. | 194 // Adds a ballon to the panel. |
| 196 void Add(Balloon* balloon) { | 195 void Add(Balloon* balloon) { |
| 197 BalloonViewImpl* view = | 196 BalloonViewImpl* view = |
| 198 static_cast<BalloonViewImpl*>(balloon->view()); | 197 static_cast<BalloonViewImpl*>(balloon->view()); |
| 199 GetContainerFor(balloon)->AddChildView(view); | 198 GetContainerFor(balloon)->AddChildView(view); |
| 200 } | 199 } |
| 201 | 200 |
| 202 // Updates the position of the |balloon|. | 201 // Updates the position of the |balloon|. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 225 GetContainerFor(balloon)->RemoveChildView(view); | 224 GetContainerFor(balloon)->RemoveChildView(view); |
| 226 } | 225 } |
| 227 | 226 |
| 228 // Returns the number of notifications added to the panel. | 227 // Returns the number of notifications added to the panel. |
| 229 int GetNotificationCount() { | 228 int GetNotificationCount() { |
| 230 return sticky_container_->GetChildViewCount() + | 229 return sticky_container_->GetChildViewCount() + |
| 231 non_sticky_container_->GetChildViewCount(); | 230 non_sticky_container_->GetChildViewCount(); |
| 232 } | 231 } |
| 233 | 232 |
| 234 // Returns the # of new notifications. | 233 // Returns the # of new notifications. |
| 235 bool GetNewNotificationCount() { | 234 int GetNewNotificationCount() { |
| 236 return sticky_container_->GetNewCount() + | 235 return sticky_container_->GetNewCount() + |
| 237 non_sticky_container_->GetNewCount(); | 236 non_sticky_container_->GetNewCount(); |
| 238 } | 237 } |
| 239 | 238 |
| 239 // Returns the # of sticky and new notifications. |
| 240 int GetStickyNewNotificationCount() { |
| 241 return sticky_container_->GetChildViewCount() + |
| 242 non_sticky_container_->GetNewCount(); |
| 243 } |
| 244 |
| 240 // Returns the # of sticky notifications. | 245 // Returns the # of sticky notifications. |
| 241 bool GetStickyNotificationCount() { | 246 int GetStickyNotificationCount() { |
| 242 return sticky_container_->GetChildViewCount(); | 247 return sticky_container_->GetChildViewCount(); |
| 243 } | 248 } |
| 244 | 249 |
| 245 // Returns true if the |view| is contained in the panel. | 250 // Returns true if the |view| is contained in the panel. |
| 246 bool HasBalloonView(View* view) { | 251 bool HasBalloonView(View* view) { |
| 247 return sticky_container_->HasChildView(view) || | 252 return sticky_container_->HasChildView(view) || |
| 248 non_sticky_container_->HasChildView(view); | 253 non_sticky_container_->HasChildView(view); |
| 249 } | 254 } |
| 250 | 255 |
| 251 // Updates the bounds so that all notifications are visible. | 256 // Updates the bounds so that all notifications are visible. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 BalloonSubContainer* non_sticky_container_; | 289 BalloonSubContainer* non_sticky_container_; |
| 285 gfx::Size preferred_size_; | 290 gfx::Size preferred_size_; |
| 286 | 291 |
| 287 DISALLOW_COPY_AND_ASSIGN(BalloonContainer); | 292 DISALLOW_COPY_AND_ASSIGN(BalloonContainer); |
| 288 }; | 293 }; |
| 289 | 294 |
| 290 NotificationPanel::NotificationPanel() | 295 NotificationPanel::NotificationPanel() |
| 291 : balloon_container_(NULL), | 296 : balloon_container_(NULL), |
| 292 state_(CLOSED), | 297 state_(CLOSED), |
| 293 task_factory_(this), | 298 task_factory_(this), |
| 294 update_panel_on_mouse_leave_(false), | 299 min_bounds_(0, 0, kBalloonMinWidth, kBalloonMinHeight) { |
| 295 latest_token_(0), | |
| 296 stale_token_(0) { | |
| 297 Init(); | 300 Init(); |
| 298 } | 301 } |
| 299 | 302 |
| 300 NotificationPanel::~NotificationPanel() { | 303 NotificationPanel::~NotificationPanel() { |
| 301 Hide(); | 304 Hide(); |
| 302 } | 305 } |
| 303 | 306 |
| 304 //////////////////////////////////////////////////////////////////////////////// | 307 //////////////////////////////////////////////////////////////////////////////// |
| 305 // NottificationPanel public. | 308 // NottificationPanel public. |
| 306 | 309 |
| 307 void NotificationPanel::Show() { | 310 void NotificationPanel::Show() { |
| 308 if (!panel_widget_.get()) { | 311 if (!panel_widget_.get()) { |
| 309 // TODO(oshima): Using window because Popup widget behaves weird | 312 // TODO(oshima): Using window because Popup widget behaves weird |
| 310 // when resizing. This needs to be investigated. | 313 // when resizing. This needs to be investigated. |
| 311 panel_widget_.reset(new PanelWidget(this)); | 314 panel_widget_.reset(new PanelWidget(this)); |
| 312 gfx::Rect bounds = GetPreferredBounds(); | 315 gfx::Rect bounds = GetPreferredBounds(); |
| 313 if (bounds.width() < kBalloonMinWidth || | 316 bounds = bounds.Union(min_bounds_); |
| 314 bounds.height() < kBalloonMinHeight) { | |
| 315 // Gtk uses its own default size when the size is empty. | |
| 316 // Use the minimum size as a default. | |
| 317 bounds.SetRect(0, 0, kBalloonMinWidth, kBalloonMinHeight); | |
| 318 } | |
| 319 panel_widget_->Init(NULL, bounds); | 317 panel_widget_->Init(NULL, bounds); |
| 320 // TODO(oshima): I needed the following code in order to get sizing | 318 // TODO(oshima): I needed the following code in order to get sizing |
| 321 // reliably. Investigate and fix it in WidgetGtk. | 319 // reliably. Investigate and fix it in WidgetGtk. |
| 322 gtk_widget_set_size_request(GTK_WIDGET(panel_widget_->GetNativeView()), | 320 gtk_widget_set_size_request(GTK_WIDGET(panel_widget_->GetNativeView()), |
| 323 bounds.width(), bounds.height()); | 321 bounds.width(), bounds.height()); |
| 324 panel_widget_->SetContentsView(scroll_view_.get()); | 322 panel_widget_->SetContentsView(scroll_view_.get()); |
| 325 panel_controller_.reset( | 323 panel_controller_.reset( |
| 326 new PanelController(this, | 324 new PanelController(this, |
| 327 GTK_WINDOW(panel_widget_->GetNativeView()), | 325 GTK_WINDOW(panel_widget_->GetNativeView()), |
| 328 gfx::Rect(0, 0, kBalloonMinWidth, 1))); | 326 gfx::Rect(0, 0, kBalloonMinWidth, 1))); |
| 329 } | 327 } |
| 330 panel_widget_->Show(); | 328 panel_widget_->Show(); |
| 331 } | 329 } |
| 332 | 330 |
| 333 void NotificationPanel::Hide() { | 331 void NotificationPanel::Hide() { |
| 334 if (panel_widget_.get()) { | 332 if (panel_widget_.get()) { |
| 335 // We need to remove & detach the scroll view from hierarchy to | 333 // We need to remove & detach the scroll view from hierarchy to |
| 336 // avoid GTK deleting child. | 334 // avoid GTK deleting child. |
| 337 // TODO(oshima): handle this details in WidgetGtk. | 335 // TODO(oshima): handle this details in WidgetGtk. |
| 338 panel_widget_->GetRootView()->RemoveChildView(scroll_view_.get()); | 336 panel_widget_->GetRootView()->RemoveChildView(scroll_view_.get()); |
| 339 panel_widget_.release()->Close(); | 337 panel_widget_.release()->Close(); |
| 340 panel_controller_.release()->Close(); | 338 panel_controller_.release()->Close(); |
| 341 } | 339 } |
| 342 } | 340 } |
| 343 | 341 |
| 344 int NotificationPanel::GetStickyNotificationCount() const { | |
| 345 return balloon_container_->GetStickyNotificationCount(); | |
| 346 } | |
| 347 | |
| 348 int NotificationPanel::GetNewNotificationCount() const { | |
| 349 return balloon_container_->GetNewNotificationCount(); | |
| 350 } | |
| 351 | |
| 352 //////////////////////////////////////////////////////////////////////////////// | 342 //////////////////////////////////////////////////////////////////////////////// |
| 353 // BalloonCollectionImpl::NotificationUI overrides. | 343 // BalloonCollectionImpl::NotificationUI overrides. |
| 354 | 344 |
| 355 void NotificationPanel::Add(Balloon* balloon) { | 345 void NotificationPanel::Add(Balloon* balloon) { |
| 356 balloon_container_->Add(balloon); | 346 balloon_container_->Add(balloon); |
| 357 if (state_ == CLOSED || state_ == MINIMIZED) | 347 if (state_ == CLOSED || state_ == MINIMIZED || state_ == KEEP_SIZE) |
| 358 state_ = STICKY_AND_NEW; | 348 state_ = STICKY_AND_NEW; |
| 359 Show(); | 349 Show(); |
| 360 UpdatePanel(true); | 350 UpdatePanel(true); |
| 361 StartStaleTimer(balloon); | 351 StartStaleTimer(balloon); |
| 362 } | 352 } |
| 363 | 353 |
| 364 bool NotificationPanel::Update(Balloon* balloon) { | 354 bool NotificationPanel::Update(Balloon* balloon) { |
| 365 if (balloon_container_->Update(balloon)) { | 355 if (balloon_container_->Update(balloon)) { |
| 366 if (state_ == CLOSED || state_ == MINIMIZED) | 356 if (state_ == CLOSED || state_ == MINIMIZED) |
| 367 state_ = STICKY_AND_NEW; | 357 state_ = STICKY_AND_NEW; |
| 368 Show(); | 358 Show(); |
| 369 UpdatePanel(true); | 359 UpdatePanel(true); |
| 370 StartStaleTimer(balloon); | 360 StartStaleTimer(balloon); |
| 371 return true; | 361 return true; |
| 372 } else { | 362 } else { |
| 373 return false; | 363 return false; |
| 374 } | 364 } |
| 375 } | 365 } |
| 376 | 366 |
| 377 void NotificationPanel::Remove(Balloon* balloon) { | 367 void NotificationPanel::Remove(Balloon* balloon) { |
| 378 balloon_container_->Remove(balloon); | 368 balloon_container_->Remove(balloon); |
| 379 // no change to the state | 369 // no change to the state |
| 380 if (balloon_container_->GetNotificationCount() == 0) | 370 if (balloon_container_->GetNotificationCount() == 0) |
| 381 state_ = CLOSED; | 371 state_ = CLOSED; |
| 382 if (static_cast<BalloonViewImpl*>(balloon->view())->closed_by_user()) { | 372 if (state_ == KEEP_SIZE) { |
| 383 DontUpdatePanelOnStale(); | 373 // Just update the content. |
| 384 balloon_container_->UpdateBounds(); | 374 balloon_container_->UpdateBounds(); |
| 385 scroll_view_->Layout(); | 375 scroll_view_->Layout(); |
| 386 } else { | 376 } else { |
| 387 UpdatePanel(true); | 377 UpdatePanel(true); |
| 388 } | 378 } |
| 389 } | 379 } |
| 390 | 380 |
| 391 void NotificationPanel::ResizeNotification( | 381 void NotificationPanel::ResizeNotification( |
| 392 Balloon* balloon, const gfx::Size& size) { | 382 Balloon* balloon, const gfx::Size& size) { |
| 393 // restrict to the min & max sizes | 383 // restrict to the min & max sizes |
| (...skipping 19 matching lines...) Expand all Loading... |
| 413 } | 403 } |
| 414 | 404 |
| 415 void NotificationPanel::ClosePanel() { | 405 void NotificationPanel::ClosePanel() { |
| 416 state_ = CLOSED; | 406 state_ = CLOSED; |
| 417 UpdatePanel(false); | 407 UpdatePanel(false); |
| 418 } | 408 } |
| 419 | 409 |
| 420 void NotificationPanel::OnPanelStateChanged(PanelController::State state) { | 410 void NotificationPanel::OnPanelStateChanged(PanelController::State state) { |
| 421 switch (state) { | 411 switch (state) { |
| 422 case PanelController::EXPANDED: | 412 case PanelController::EXPANDED: |
| 423 // Geting expanded in STICKY_AND_NEW state means that a new | 413 // Geting expanded in STICKY_AND_NEW or in KEEP_SIZE state means |
| 424 // notification is added, so just leave the state. Otherwise, | 414 // that a new notification is added, so just leave the |
| 425 // expand to full. | 415 // state. Otherwise, expand to full. |
| 426 if (state_ != STICKY_AND_NEW) | 416 if (state_ != STICKY_AND_NEW && state_ != KEEP_SIZE) |
| 427 state_ = FULL; | 417 state_ = FULL; |
| 428 // When the panel is to be expanded, we either show all, or | 418 // When the panel is to be expanded, we either show all, or |
| 429 // show only sticky/new, depending on the state. | 419 // show only sticky/new, depending on the state. |
| 430 UpdatePanel(false); | 420 UpdatePanel(false); |
| 431 break; | 421 break; |
| 432 case PanelController::MINIMIZED: | 422 case PanelController::MINIMIZED: |
| 433 state_ = MINIMIZED; | 423 state_ = MINIMIZED; |
| 434 // Make all notifications stale when a user minimize the panel. | 424 // Make all notifications stale when a user minimize the panel. |
| 435 balloon_container_->MakeAllStale(); | 425 balloon_container_->MakeAllStale(); |
| 436 break; | 426 break; |
| 437 } | 427 } |
| 438 } | 428 } |
| 439 | 429 |
| 440 void NotificationPanel::OnMouseLeave() { | 430 void NotificationPanel::OnMouseLeave() { |
| 441 if (update_panel_on_mouse_leave_) { | 431 if (balloon_container_->GetNotificationCount() == 0) { |
| 442 // TODO(oshima): We need "AS_IS" state, which simply | 432 state_ = CLOSED; |
| 443 // keeps the current panel size unless it has less notifications | |
| 444 // than it can show. | |
| 445 if (balloon_container_->GetStickyNotificationCount() > 0 || | |
| 446 balloon_container_->GetNewNotificationCount() > 0) { | |
| 447 state_ = STICKY_AND_NEW; | |
| 448 } else { | |
| 449 state_ = MINIMIZED; | |
| 450 } | |
| 451 UpdatePanel(true); | |
| 452 } | 433 } |
| 434 UpdatePanel(true); |
| 435 } |
| 436 |
| 437 void NotificationPanel::OnMouseMotion() { |
| 438 state_ = KEEP_SIZE; |
| 439 } |
| 440 |
| 441 NotificationPanelTester* NotificationPanel::GetTester() { |
| 442 if (!tester_.get()) { |
| 443 tester_.reset(new NotificationPanelTester(this)); |
| 444 } |
| 445 return tester_.get(); |
| 453 } | 446 } |
| 454 | 447 |
| 455 //////////////////////////////////////////////////////////////////////////////// | 448 //////////////////////////////////////////////////////////////////////////////// |
| 456 // NotificationPanel private. | 449 // NotificationPanel private. |
| 457 | 450 |
| 458 void NotificationPanel::Init() { | 451 void NotificationPanel::Init() { |
| 459 DCHECK(!panel_widget_.get()); | 452 DCHECK(!panel_widget_.get()); |
| 460 balloon_container_ = new BalloonContainer(1); | 453 balloon_container_ = new BalloonContainer(1); |
| 461 balloon_container_->set_background( | 454 balloon_container_->set_background( |
| 462 views::Background::CreateSolidBackground(ResourceBundle::frame_color)); | 455 views::Background::CreateSolidBackground(ResourceBundle::frame_color)); |
| 463 | 456 |
| 464 scroll_view_.reset(new views::ScrollView()); | 457 scroll_view_.reset(new views::ScrollView()); |
| 465 scroll_view_->set_parent_owned(false); | 458 scroll_view_->set_parent_owned(false); |
| 466 scroll_view_->SetContents(balloon_container_); | 459 scroll_view_->SetContents(balloon_container_); |
| 467 scroll_view_->set_background( | 460 scroll_view_->set_background( |
| 468 views::Background::CreateSolidBackground(SK_ColorWHITE)); | 461 views::Background::CreateSolidBackground(SK_ColorWHITE)); |
| 469 } | 462 } |
| 470 | 463 |
| 471 void NotificationPanel::UpdatePanel(bool contents_changed) { | 464 void NotificationPanel::UpdatePanel(bool contents_changed) { |
| 472 update_panel_on_mouse_leave_ = false; | |
| 473 if (contents_changed) { | 465 if (contents_changed) { |
| 474 balloon_container_->UpdateBounds(); | 466 balloon_container_->UpdateBounds(); |
| 475 scroll_view_->Layout(); | 467 scroll_view_->Layout(); |
| 476 } | 468 } |
| 477 switch(state_) { | 469 switch(state_) { |
| 470 case KEEP_SIZE: { |
| 471 gfx::Rect min_bounds = GetPreferredBounds(); |
| 472 gfx::Rect panel_bounds; |
| 473 panel_widget_->GetBounds(&panel_bounds, true); |
| 474 if (min_bounds.height() < panel_bounds.height()) |
| 475 panel_widget_->SetBounds(min_bounds); |
| 476 // no change. |
| 477 break; |
| 478 } |
| 478 case CLOSED: | 479 case CLOSED: |
| 479 balloon_container_->MakeAllStale(); | 480 balloon_container_->MakeAllStale(); |
| 480 Hide(); | 481 Hide(); |
| 481 break; | 482 break; |
| 482 case MINIMIZED: | 483 case MINIMIZED: |
| 483 balloon_container_->MakeAllStale(); | 484 balloon_container_->MakeAllStale(); |
| 484 if (panel_controller_.get()) | 485 if (panel_controller_.get()) |
| 485 panel_controller_->SetState(PanelController::MINIMIZED); | 486 panel_controller_->SetState(PanelController::MINIMIZED); |
| 486 break; | 487 break; |
| 487 case FULL: | 488 case FULL: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 499 } | 500 } |
| 500 } | 501 } |
| 501 | 502 |
| 502 gfx::Rect NotificationPanel::GetPreferredBounds() { | 503 gfx::Rect NotificationPanel::GetPreferredBounds() { |
| 503 gfx::Size pref_size = balloon_container_->GetPreferredSize(); | 504 gfx::Size pref_size = balloon_container_->GetPreferredSize(); |
| 504 int new_height = std::min(pref_size.height(), kMaxPanelHeight); | 505 int new_height = std::min(pref_size.height(), kMaxPanelHeight); |
| 505 int new_width = pref_size.width(); | 506 int new_width = pref_size.width(); |
| 506 // Adjust the width to avoid showing a horizontal scroll bar. | 507 // Adjust the width to avoid showing a horizontal scroll bar. |
| 507 if (new_height != pref_size.height()) | 508 if (new_height != pref_size.height()) |
| 508 new_width += scroll_view_->GetScrollBarWidth(); | 509 new_width += scroll_view_->GetScrollBarWidth(); |
| 509 return gfx::Rect(0, 0, new_width, new_height); | 510 return gfx::Rect(0, 0, new_width, new_height).Union(min_bounds_); |
| 510 } | 511 } |
| 511 | 512 |
| 512 gfx::Rect NotificationPanel::GetStickyNewBounds() { | 513 gfx::Rect NotificationPanel::GetStickyNewBounds() { |
| 513 gfx::Size pref_size = balloon_container_->GetPreferredSize(); | 514 gfx::Size pref_size = balloon_container_->GetPreferredSize(); |
| 514 gfx::Size sticky_size = balloon_container_->GetStickyNewSize(); | 515 gfx::Size sticky_size = balloon_container_->GetStickyNewSize(); |
| 515 int new_height = std::min(sticky_size.height(), kMaxPanelHeight); | 516 int new_height = std::min(sticky_size.height(), kMaxPanelHeight); |
| 516 int new_width = pref_size.width(); | 517 int new_width = pref_size.width(); |
| 517 // Adjust the width to avoid showing a horizontal scroll bar. | 518 // Adjust the width to avoid showing a horizontal scroll bar. |
| 518 if (new_height != pref_size.height()) | 519 if (new_height != pref_size.height()) |
| 519 new_width += scroll_view_->GetScrollBarWidth(); | 520 new_width += scroll_view_->GetScrollBarWidth(); |
| 520 return gfx::Rect(0, 0, new_width, new_height); | 521 return gfx::Rect(0, 0, new_width, new_height).Union(min_bounds_); |
| 521 } | |
| 522 | |
| 523 void NotificationPanel::DontUpdatePanelOnStale() { | |
| 524 if (stale_token_ != latest_token_) { | |
| 525 stale_token_ = latest_token_; | |
| 526 } | |
| 527 update_panel_on_mouse_leave_ = true; | |
| 528 } | 522 } |
| 529 | 523 |
| 530 void NotificationPanel::StartStaleTimer(Balloon* balloon) { | 524 void NotificationPanel::StartStaleTimer(Balloon* balloon) { |
| 531 BalloonViewImpl* view = static_cast<BalloonViewImpl*>(balloon->view()); | 525 BalloonViewImpl* view = static_cast<BalloonViewImpl*>(balloon->view()); |
| 532 MessageLoop::current()->PostDelayedTask( | 526 MessageLoop::current()->PostDelayedTask( |
| 533 FROM_HERE, | 527 FROM_HERE, |
| 534 task_factory_.NewRunnableMethod( | 528 task_factory_.NewRunnableMethod( |
| 535 &NotificationPanel::OnStale, view, latest_token_++), | 529 &NotificationPanel::OnStale, view), |
| 536 1000 * kStaleTimeoutInSeconds); | 530 1000 * kStaleTimeoutInSeconds); |
| 537 } | 531 } |
| 538 | 532 |
| 539 void NotificationPanel::OnStale(BalloonViewImpl* view, int token) { | 533 void NotificationPanel::OnStale(BalloonViewImpl* view) { |
| 540 if (balloon_container_->HasBalloonView(view) && !view->stale()) { | 534 if (balloon_container_->HasBalloonView(view) && !view->stale()) { |
| 541 view->set_stale(); | 535 view->set_stale(); |
| 542 // don't update panel on stale | 536 // don't update panel on stale |
| 543 if (token < stale_token_) { | 537 if (state_ == KEEP_SIZE) |
| 544 return; | 538 return; |
| 545 } | 539 if (balloon_container_->GetStickyNewNotificationCount() > 0) { |
| 546 if (balloon_container_->GetStickyNotificationCount() > 0) { | |
| 547 state_ = STICKY_AND_NEW; | 540 state_ = STICKY_AND_NEW; |
| 548 } else { | 541 } else { |
| 549 state_ = MINIMIZED; | 542 state_ = MINIMIZED; |
| 550 } | 543 } |
| 551 UpdatePanel(false); | 544 UpdatePanel(false); |
| 552 } | 545 } |
| 553 } | 546 } |
| 554 | 547 |
| 548 //////////////////////////////////////////////////////////////////////////////// |
| 549 // NotificationPanelTester public. |
| 550 |
| 551 int NotificationPanelTester::GetNotificationCount() const { |
| 552 return panel_->balloon_container_->GetNotificationCount(); |
| 553 } |
| 554 |
| 555 int NotificationPanelTester::GetStickyNotificationCount() const { |
| 556 return panel_->balloon_container_->GetStickyNotificationCount(); |
| 557 } |
| 558 |
| 559 int NotificationPanelTester::GetNewNotificationCount() const { |
| 560 return panel_->balloon_container_->GetNewNotificationCount(); |
| 561 } |
| 562 |
| 563 |
| 555 } // namespace chromeos | 564 } // namespace chromeos |
| OLD | NEW |