Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(393)

Side by Side Diff: chrome/browser/ui/panels/docked_panel_strip.cc

Issue 9560002: Cleanup to keep panel from manipulating its panel strip assignment directly. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more feedback changes Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/ui/panels/docked_panel_strip.h" 5 #include "chrome/browser/ui/panels/docked_panel_strip.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/message_loop.h" 12 #include "base/message_loop.h"
13 #include "chrome/browser/ui/browser.h" 13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/panels/overflow_panel_strip.h"
15 #include "chrome/browser/ui/panels/panel_manager.h" 14 #include "chrome/browser/ui/panels/panel_manager.h"
16 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" 15 #include "chrome/browser/ui/panels/panel_mouse_watcher.h"
17 #include "chrome/common/chrome_notification_types.h" 16 #include "chrome/common/chrome_notification_types.h"
18 #include "content/public/browser/notification_service.h" 17 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/notification_source.h"
20 19
21 namespace { 20 namespace {
22 // Width to height ratio is used to compute the default width or height 21 // Width to height ratio is used to compute the default width or height
23 // when only one value is provided. 22 // when only one value is provided.
24 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio 23 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio
(...skipping 27 matching lines...) Expand all
52 51
53 // static 52 // static
54 const int DockedPanelStrip::kPanelMinWidth = 100; 53 const int DockedPanelStrip::kPanelMinWidth = 100;
55 const int DockedPanelStrip::kPanelMinHeight = 20; 54 const int DockedPanelStrip::kPanelMinHeight = 20;
56 55
57 DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager) 56 DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager)
58 : PanelStrip(PanelStrip::DOCKED), 57 : PanelStrip(PanelStrip::DOCKED),
59 panel_manager_(panel_manager), 58 panel_manager_(panel_manager),
60 minimized_panel_count_(0), 59 minimized_panel_count_(0),
61 are_titlebars_up_(false), 60 are_titlebars_up_(false),
62 disable_layout_refresh_(false),
63 delayed_titlebar_action_(NO_ACTION), 61 delayed_titlebar_action_(NO_ACTION),
64 titlebar_action_factory_(this) { 62 titlebar_action_factory_(this) {
65 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ = 63 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ =
66 panels_.end(); 64 panels_.end();
67 } 65 }
68 66
69 DockedPanelStrip::~DockedPanelStrip() { 67 DockedPanelStrip::~DockedPanelStrip() {
70 DCHECK(panels_.empty()); 68 DCHECK(panels_.empty());
71 DCHECK(panels_in_temporary_layout_.empty()); 69 DCHECK(panels_in_temporary_layout_.empty());
72 DCHECK_EQ(0, minimized_panel_count_); 70 DCHECK_EQ(0, minimized_panel_count_);
73 } 71 }
74 72
75 void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) { 73 void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) {
76 if (display_area_ == display_area) 74 if (display_area_ == display_area)
77 return; 75 return;
78 76
79 gfx::Rect old_area = display_area_; 77 gfx::Rect old_area = display_area_;
80 display_area_ = display_area; 78 display_area_ = display_area;
81 79
82 if (panels_.empty()) 80 if (panels_.empty())
83 return; 81 return;
84 82
85 RefreshLayout(); 83 RefreshLayout();
86 } 84 }
87 85
88 void DockedPanelStrip::AddPanel(Panel* panel) { 86 void DockedPanelStrip::AddPanel(Panel* panel) {
89 DCHECK_EQ(this, panel->panel_strip()); 87 DCHECK_NE(this, panel->panel_strip());
88 panel->set_panel_strip(this);
90 89
91 // Always update limits, even for exiting panels, in case the maximums changed 90 // Always update limits, even on existing panels, in case the limits changed
92 // while panel was out of the strip. 91 // while panel was out of the strip.
93 int max_panel_width = GetMaxPanelWidth(); 92 int max_panel_width = GetMaxPanelWidth();
94 int max_panel_height = GetMaxPanelHeight(); 93 int max_panel_height = GetMaxPanelHeight();
95 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight), 94 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight),
96 gfx::Size(max_panel_width, max_panel_height)); 95 gfx::Size(max_panel_width, max_panel_height));
97 96
98 gfx::Size restored_size = panel->restored_size(); 97 gfx::Size restored_size = panel->restored_size();
99 int height = restored_size.height(); 98 int height = restored_size.height();
100 int width = restored_size.width(); 99 int width = restored_size.width();
101 100
102 if (panel->initialized()) { 101 if (panel->initialized()) {
103 // Bump panels in the strip to make room for this panel. 102 int x = FitPanelInStrip(width);
104 // Prevent layout refresh when panel is removed from this strip.
105 disable_layout_refresh_ = true;
106 PanelStrip* overflow_strip = panel_manager_->overflow_strip();
107 int x;
108 while ((x = GetRightMostAvailablePosition() - width) < display_area_.x()) {
109 DCHECK(!panels_.empty());
110 panels_.back()->MoveToStrip(overflow_strip);
111 }
112 disable_layout_refresh_ = false;
113 103
114 Panel::ExpansionState expansion_state_to_restore; 104 Panel::ExpansionState expansion_state_to_restore;
115 if (panel->expansion_state() == Panel::EXPANDED) { 105 if (panel->expansion_state() == Panel::EXPANDED) {
116 expansion_state_to_restore = Panel::EXPANDED; 106 expansion_state_to_restore = Panel::EXPANDED;
117 } else { 107 } else {
118 if (are_titlebars_up_ || panel->IsDrawingAttention()) { 108 if (are_titlebars_up_ || panel->IsDrawingAttention()) {
119 expansion_state_to_restore = Panel::TITLE_ONLY; 109 expansion_state_to_restore = Panel::TITLE_ONLY;
120 height = panel->TitleOnlyHeight(); 110 height = panel->TitleOnlyHeight();
121 } else { 111 } else {
122 expansion_state_to_restore = Panel::MINIMIZED; 112 expansion_state_to_restore = Panel::MINIMIZED;
123 height = Panel::kMinimizedPanelHeight; 113 height = Panel::kMinimizedPanelHeight;
124 } 114 }
125 IncrementMinimizedPanels(); 115 IncrementMinimizedPanels();
126 } 116 }
127
128 int y = 117 int y =
129 GetBottomPositionForExpansionState(expansion_state_to_restore) - height; 118 GetBottomPositionForExpansionState(expansion_state_to_restore) - height;
130 panel->SetPanelBounds(gfx::Rect(x, y, width, height)); 119 panel->SetPanelBounds(gfx::Rect(x, y, width, height));
131 120
132 // Update the minimized state to reflect current titlebar mode. 121 // Update the minimized state to reflect current titlebar mode.
133 // Do this AFTER setting panel bounds to avoid an extra bounds change. 122 // Do this AFTER setting panel bounds to avoid an extra bounds change.
134 if (panel->expansion_state() != Panel::EXPANDED) 123 if (panel->expansion_state() != Panel::EXPANDED)
135 panel->SetExpansionState(expansion_state_to_restore); 124 panel->SetExpansionState(expansion_state_to_restore);
136 125
137 } else { 126 } else {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 185
197 int DockedPanelStrip::StartingRightPosition() const { 186 int DockedPanelStrip::StartingRightPosition() const {
198 return display_area_.right(); 187 return display_area_.right();
199 } 188 }
200 189
201 int DockedPanelStrip::GetRightMostAvailablePosition() const { 190 int DockedPanelStrip::GetRightMostAvailablePosition() const {
202 return panels_.empty() ? StartingRightPosition() : 191 return panels_.empty() ? StartingRightPosition() :
203 (panels_.back()->GetBounds().x() - kPanelsHorizontalSpacing); 192 (panels_.back()->GetBounds().x() - kPanelsHorizontalSpacing);
204 } 193 }
205 194
206 bool DockedPanelStrip::RemovePanel(Panel* panel) { 195 void DockedPanelStrip::RemovePanel(Panel* panel) {
207 if (panel->has_temporary_layout()) { 196 DCHECK_EQ(this, panel->panel_strip());
208 panels_in_temporary_layout_.erase(panel); 197 panel->set_panel_strip(NULL);
209 return true;
210 }
211
212 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
213 if (iter == panels_.end())
214 return false;
215 198
216 if (panel->expansion_state() != Panel::EXPANDED) 199 if (panel->expansion_state() != Panel::EXPANDED)
217 DecrementMinimizedPanels(); 200 DecrementMinimizedPanels();
218 201
219 // Removing an element from the list will invalidate the iterator that refers 202 if (panel->has_temporary_layout()) {
220 // to it. So we need to check if the dragging panel iterators are affected. 203 panels_in_temporary_layout_.erase(panel);
221 bool update_original_dragging_iterator_after_erase = false; 204 return;
222 if (dragging_panel_original_iterator_ != panels_.end()) {
223 if (dragging_panel_current_iterator_ == iter) {
224 // If the dragging panel is being removed, set both dragging iterators to
225 // the end of the list.
226 dragging_panel_current_iterator_ = dragging_panel_original_iterator_ =
227 panels_.end();
228 } else if (dragging_panel_original_iterator_ == iter) {
229 // If |dragging_panel_original_iterator_| refers to the element being
230 // removed, set the flag so that the iterator can be updated to next
231 // element.
232 update_original_dragging_iterator_after_erase = true;
233 }
234 } 205 }
235 206
236 iter = panels_.erase(iter); 207 // Removing an element from the list will invalidate the iterator that refers
208 // to it. We need to update the iterator in that case.
209 DCHECK(dragging_panel_current_iterator_ == panels_.end() ||
210 *dragging_panel_current_iterator_ != panel);
211 bool update_iterator_after_erase =
212 (dragging_panel_original_iterator_ != panels_.end() &&
213 *dragging_panel_original_iterator_ == panel);
237 214
238 if (update_original_dragging_iterator_after_erase) 215 // Optimize for the common case of removing the last panel.
239 dragging_panel_original_iterator_ = iter; 216 DCHECK(!panels_.empty());
240 217 if (panels_.back() == panel) {
241 if (!disable_layout_refresh_) 218 panels_.pop_back();
219 if (update_iterator_after_erase)
220 dragging_panel_original_iterator_ = panels_.end();
221 // No need to refresh layout as the remaining panels are unaffected.
222 // Just check if other panels can now fit in the freed up space.
223 panel_manager_->MovePanelsOutOfOverflowIfCanFit();
224 } else {
225 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
226 DCHECK(iter != panels_.end());
227 iter = panels_.erase(iter);
228 if (update_iterator_after_erase)
229 dragging_panel_original_iterator_ = iter;
242 RefreshLayout(); 230 RefreshLayout();
243 231 }
244 return true;
245 } 232 }
246 233
247 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { 234 bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const {
248 // Panels with temporary layout cannot be shown as active. 235 // Panels with temporary layout cannot be shown as active.
249 return !panel->has_temporary_layout(); 236 return !panel->has_temporary_layout();
250 } 237 }
251 238
252 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const { 239 bool DockedPanelStrip::CanDragPanel(const Panel* panel) const {
253 // Only the panels having temporary layout can't be dragged. 240 // Only the panels having temporary layout can't be dragged.
254 return !panel->has_temporary_layout(); 241 return !panel->has_temporary_layout();
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 423
437 panel->SetExpansionState(panel->IsDrawingAttention() ? 424 panel->SetExpansionState(panel->IsDrawingAttention() ?
438 Panel::TITLE_ONLY : Panel::MINIMIZED); 425 Panel::TITLE_ONLY : Panel::MINIMIZED);
439 } 426 }
440 427
441 void DockedPanelStrip::RestorePanel(Panel* panel) { 428 void DockedPanelStrip::RestorePanel(Panel* panel) {
442 DCHECK_EQ(this, panel->panel_strip()); 429 DCHECK_EQ(this, panel->panel_strip());
443 panel->SetExpansionState(Panel::EXPANDED); 430 panel->SetExpansionState(Panel::EXPANDED);
444 } 431 }
445 432
433 bool DockedPanelStrip::IsPanelMinimized(const Panel* panel) const {
434 return panel->expansion_state() != Panel::EXPANDED;
435 }
436
446 void DockedPanelStrip::IncrementMinimizedPanels() { 437 void DockedPanelStrip::IncrementMinimizedPanels() {
447 minimized_panel_count_++; 438 minimized_panel_count_++;
448 if (minimized_panel_count_ == 1) 439 if (minimized_panel_count_ == 1)
449 panel_manager_->mouse_watcher()->AddObserver(this); 440 panel_manager_->mouse_watcher()->AddObserver(this);
450 DCHECK_LE(minimized_panel_count_, num_panels()); 441 DCHECK_LE(minimized_panel_count_, num_panels());
451 } 442 }
452 443
453 void DockedPanelStrip::DecrementMinimizedPanels() { 444 void DockedPanelStrip::DecrementMinimizedPanels() {
454 minimized_panel_count_--; 445 minimized_panel_count_--;
455 DCHECK_GE(minimized_panel_count_, 0); 446 DCHECK_GE(minimized_panel_count_, 0);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 delayed_titlebar_action_ = NO_ACTION; 663 delayed_titlebar_action_ = NO_ACTION;
673 } 664 }
674 665
675 void DockedPanelStrip::OnFullScreenModeChanged(bool is_full_screen) { 666 void DockedPanelStrip::OnFullScreenModeChanged(bool is_full_screen) {
676 for (Panels::const_iterator iter = panels_.begin(); 667 for (Panels::const_iterator iter = panels_.begin();
677 iter != panels_.end(); ++iter) { 668 iter != panels_.end(); ++iter) {
678 (*iter)->FullScreenModeChanged(is_full_screen); 669 (*iter)->FullScreenModeChanged(is_full_screen);
679 } 670 }
680 } 671 }
681 672
673 bool DockedPanelStrip::CanFitPanel(const Panel* panel) const {
674 int width = panel->GetRestoredBounds().width();
675 return GetRightMostAvailablePosition() - width >= display_area_.x();
676 }
677
678 int DockedPanelStrip::FitPanelInStrip(int width) {
679 int x = GetRightMostAvailablePosition() - width;
680 if (x < display_area_.x()) {
681 // Dock is too full.
jianli 2012/03/02 22:25:32 nit: Insufficient space for the requested width. B
jennb 2012/03/02 22:44:37 Done.
682 Panel* last_panel_to_send_to_overflow;
jianli 2012/03/02 22:25:32 nit: Seems not need to define this variable outsid
jennb 2012/03/02 22:44:37 Slight efficiency to avoid stack manipulation each
683 for (Panels::reverse_iterator iter = panels_.rbegin();
684 iter != panels_.rend(); ++iter) {
685 last_panel_to_send_to_overflow = *iter;
686 x = last_panel_to_send_to_overflow->GetRestoredBounds().right() - width;
687 if (x >= display_area_.x()) {
688 // Found where panel fits.
jianli 2012/03/02 22:25:32 nit: comment can be removed.
jennb 2012/03/02 22:44:37 Done.
689 panel_manager_->MovePanelsToOverflow(last_panel_to_send_to_overflow);
690 break;
691 }
692 }
693 }
694 return x;
695 }
696
682 void DockedPanelStrip::RefreshLayout() { 697 void DockedPanelStrip::RefreshLayout() {
683 int rightmost_position = StartingRightPosition(); 698 int rightmost_position = StartingRightPosition();
684 699
685 Panels::const_iterator panel_iter = panels_.begin(); 700 Panels::const_iterator panel_iter = panels_.begin();
686 for (; panel_iter != panels_.end(); ++panel_iter) { 701 for (; panel_iter != panels_.end(); ++panel_iter) {
687 Panel* panel = *panel_iter; 702 Panel* panel = *panel_iter;
688 gfx::Rect new_bounds(panel->GetBounds()); 703 gfx::Rect new_bounds(panel->GetBounds());
689 int x = rightmost_position - new_bounds.width(); 704 int x = rightmost_position - new_bounds.width();
690 705
691 if (x < display_area_.x()) 706 if (x < display_area_.x())
692 break; 707 break;
693 708
694 // Don't update the docked panel that is currently dragged. 709 // Don't update the docked panel that is currently dragged.
695 if (panel != dragging_panel()) { 710 if (panel != dragging_panel()) {
696 new_bounds.set_x(x); 711 new_bounds.set_x(x);
697 new_bounds.set_y( 712 new_bounds.set_y(
698 GetBottomPositionForExpansionState(panel->expansion_state()) - 713 GetBottomPositionForExpansionState(panel->expansion_state()) -
699 new_bounds.height()); 714 new_bounds.height());
700 panel->SetPanelBounds(new_bounds); 715 panel->SetPanelBounds(new_bounds);
701 } 716 }
702 717
703 rightmost_position = x - kPanelsHorizontalSpacing; 718 rightmost_position = x - kPanelsHorizontalSpacing;
704 } 719 }
705 720
706 // Add/remove panels from/to overflow. A change in work area or the 721 // Add/remove panels from/to overflow. A change in work area or the
707 // resize/removal of a panel may affect how many panels fit in the strip. 722 // resize/removal of a panel may affect how many panels fit in the strip.
708 OverflowPanelStrip* overflow_strip = panel_manager_->overflow_strip(); 723 if (panel_iter != panels_.end())
709 if (panel_iter != panels_.end()) { 724 panel_manager_->MovePanelsToOverflow(*panel_iter);
710 // Prevent layout refresh when panel is removed from this strip. 725 else
711 disable_layout_refresh_ = true; 726 panel_manager_->MovePanelsOutOfOverflowIfCanFit();
712
713 // Keep track of panels to move to overflow in a separate storage since
714 // removing it from the list will invalidate the iterator.
715 std::vector<Panel*> panels_to_move_to_overflow;
716 for (; panel_iter != panels_.end(); ++panel_iter)
717 panels_to_move_to_overflow.push_back(*panel_iter);
718
719 // Move panels to overflow in reverse to maintain their order.
720 for (std::vector<Panel*>::reverse_iterator iter =
721 panels_to_move_to_overflow.rbegin();
722 iter != panels_to_move_to_overflow.rend(); ++iter) {
723 (*iter)->MoveToStrip(overflow_strip);
724 }
725
726 disable_layout_refresh_ = false;
727 } else {
728 // Attempt to add more panels from overflow to the strip.
729 Panel* overflow_panel;
730 while ((overflow_panel = overflow_strip->first_panel()) &&
731 GetRightMostAvailablePosition() >=
732 display_area_.x() + overflow_panel->restored_size().width()) {
733 overflow_panel->MoveToStrip(this);
734 }
735 }
736 } 727 }
737 728
738 void DockedPanelStrip::DelayedMovePanelToOverflow(Panel* panel) { 729 void DockedPanelStrip::DelayedMovePanelToOverflow(Panel* panel) {
739 if (panels_in_temporary_layout_.erase(panel)) { 730 if (panels_in_temporary_layout_.erase(panel)) {
740 DCHECK(panel->has_temporary_layout()); 731 DCHECK(panel->has_temporary_layout());
741 panel->MoveToStrip(panel_manager_->overflow_strip()); 732 panel_manager_->MovePanelToStrip(panel, PanelStrip::IN_OVERFLOW);
742 } 733 }
743 } 734 }
744 735
745 void DockedPanelStrip::CloseAll() { 736 void DockedPanelStrip::CloseAll() {
746 // This should only be called at the end of tests to clean up. 737 // This should only be called at the end of tests to clean up.
747 DCHECK(panels_in_temporary_layout_.empty()); 738 DCHECK(panels_in_temporary_layout_.empty());
748 739
749 // Make a copy of the iterator as closing panels can modify the vector. 740 // Make a copy of the iterator as closing panels can modify the vector.
750 Panels panels_copy = panels_; 741 Panels panels_copy = panels_;
751 742
752 // Start from the bottom to avoid reshuffling. 743 // Start from the bottom to avoid reshuffling.
753 for (Panels::reverse_iterator iter = panels_copy.rbegin(); 744 for (Panels::reverse_iterator iter = panels_copy.rbegin();
754 iter != panels_copy.rend(); ++iter) 745 iter != panels_copy.rend(); ++iter)
755 (*iter)->Close(); 746 (*iter)->Close();
756 } 747 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698