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

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

Issue 8953040: Add overflow indicator count on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/panel_overflow_strip.h" 5 #include "chrome/browser/ui/panels/panel_overflow_strip.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "chrome/browser/ui/panels/panel_manager.h" 8 #include "chrome/browser/ui/panels/panel_manager.h"
9 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" 9 #include "chrome/browser/ui/panels/panel_mouse_watcher.h"
10 #include "chrome/browser/ui/panels/panel_overflow_indicator.h"
10 #include "chrome/browser/ui/panels/panel_strip.h" 11 #include "chrome/browser/ui/panels/panel_strip.h"
11 #include "chrome/common/chrome_notification_types.h" 12 #include "chrome/common/chrome_notification_types.h"
12 #include "content/public/browser/notification_service.h" 13 #include "content/public/browser/notification_service.h"
13 #include "ui/base/animation/slide_animation.h" 14 #include "ui/base/animation/slide_animation.h"
14 15
15 namespace { 16 namespace {
16 // The width of the overflow area that is expanded to show more info, i.e. 17 // The width of the overflow area that is expanded to show more info, i.e.
17 // titles, when the mouse hovers over the area. 18 // titles, when the mouse hovers over the area.
18 static const int kOverflowAreaHoverWidth = 200; 19 static const int kOverflowAreaHoverWidth = 200;
19 20
20 // Maximium number of overflow panels allowed to be shown. 21 // Maximium number of visible overflow panels when the overflow area is shrunk.
21 const size_t kMaxVisibleOverflowPanelsAllowed = 6; 22 const size_t kMaxVisibleOverflowPanelsOnShrunk = 6;
23
24 // Height to display-area ratio that maximium number of visible overflow panels
25 // cannot occupy more than when the overflow area is expanded.
26 const double kHeightRatioForMaxVisibleOverflowPanelsOnExpanded = 0.67;
22 27
23 // This value is experimental and subjective. 28 // This value is experimental and subjective.
24 const int kOverflowHoverAnimationMs = 180; 29 const int kOverflowHoverAnimationMs = 180;
25 } 30 }
26 31
27 PanelOverflowStrip::PanelOverflowStrip(PanelManager* panel_manager) 32 PanelOverflowStrip::PanelOverflowStrip(PanelManager* panel_manager)
28 : panel_manager_(panel_manager), 33 : panel_manager_(panel_manager),
29 current_display_width_(0), 34 current_display_width_(0),
30 max_visible_panels_(kMaxVisibleOverflowPanelsAllowed), 35 max_visible_panels_on_shrunk_(kMaxVisibleOverflowPanelsOnShrunk),
36 max_visible_panels_on_expanded_(kMaxVisibleOverflowPanelsOnShrunk),
31 are_overflow_titles_shown_(false), 37 are_overflow_titles_shown_(false),
32 overflow_hover_animator_start_width_(0), 38 overflow_hover_animator_start_width_(0),
33 overflow_hover_animator_end_width_(0) { 39 overflow_hover_animator_end_width_(0) {
40 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
41 content::NotificationService::AllSources());
34 } 42 }
35 43
36 PanelOverflowStrip::~PanelOverflowStrip() { 44 PanelOverflowStrip::~PanelOverflowStrip() {
37 DCHECK(panels_.empty()); 45 DCHECK(panels_.empty());
46 DCHECK(!overflow_indicator_.get());
38 } 47 }
39 48
40 void PanelOverflowStrip::SetDisplayArea(const gfx::Rect& display_area) { 49 void PanelOverflowStrip::SetDisplayArea(const gfx::Rect& display_area) {
41 if (display_area_ == display_area) 50 if (display_area_ == display_area)
42 return; 51 return;
52 display_area_ = display_area;
43 53
44 display_area_ = display_area; 54 UpdateMaxVisibkePanelsOnExpanded();
45 UpdateCurrentWidth(); 55 UpdateCurrentWidth();
46 56
47 Refresh(); 57 Refresh();
48 } 58 }
49 59
60 void PanelOverflowStrip::UpdateMaxVisibkePanelsOnExpanded() {
61 // The maximum number of visible overflow panels cannot occupy more than
62 // certain percentage of the display area height.
63 // Note that we need to delay the computation of this value if no overflow
64 // panel is added.
65 if (panels_.empty()) {
66 max_visible_panels_on_expanded_ = 0;
67 } else {
68 max_visible_panels_on_expanded_ =
69 kHeightRatioForMaxVisibleOverflowPanelsOnExpanded *
70 display_area_.height() /
71 panels_.front()->IconOnlySize().height();
72 }
73 }
74
50 void PanelOverflowStrip::UpdateCurrentWidth() { 75 void PanelOverflowStrip::UpdateCurrentWidth() {
51 current_display_width_ = are_overflow_titles_shown_ ? kOverflowAreaHoverWidth 76 current_display_width_ = are_overflow_titles_shown_ ? kOverflowAreaHoverWidth
52 : display_area_.width(); 77 : display_area_.width();
53 } 78 }
54 79
55 void PanelOverflowStrip::AddPanel(Panel* panel) { 80 void PanelOverflowStrip::AddPanel(Panel* panel) {
56 // TODO(jianli): consider using other container to improve the perf for 81 // TODO(jianli): consider using other container to improve the perf for
57 // inserting to the front. http://crbug.com/106222 82 // inserting to the front. http://crbug.com/106222
58 DCHECK_EQ(Panel::IN_OVERFLOW, panel->expansion_state()); 83 DCHECK_EQ(Panel::IN_OVERFLOW, panel->expansion_state());
59 // Newly created panels that were temporarily in the panel strip 84 // Newly created panels that were temporarily in the panel strip
60 // are added to the back of the overflow, whereas panels that are 85 // are added to the back of the overflow, whereas panels that are
61 // bumped from the panel strip by other panels go to the front 86 // bumped from the panel strip by other panels go to the front
62 // of overflow. 87 // of overflow.
63 if (panel->has_temporary_layout()) { 88 if (panel->has_temporary_layout()) {
64 panel->set_has_temporary_layout(false); 89 panel->set_has_temporary_layout(false);
65 panels_.push_back(panel); 90 panels_.push_back(panel);
66 DoRefresh(panels_.size() - 1, panels_.size() - 1); 91 DoRefresh(panels_.size() - 1, panels_.size() - 1);
67 } else { 92 } else {
68 panels_.insert(panels_.begin(), panel); 93 panels_.insert(panels_.begin(), panel);
69 Refresh(); 94 Refresh();
70 } 95 }
71 96
72 if (panels_.size() == 1) 97 if (panels_.size() == 1)
73 panel_manager_->mouse_watcher()->AddObserver(this); 98 panel_manager_->mouse_watcher()->AddObserver(this);
99
100 UpdateOverflowIndicator(current_display_width_);
74 } 101 }
75 102
76 bool PanelOverflowStrip::Remove(Panel* panel) { 103 bool PanelOverflowStrip::Remove(Panel* panel) {
77 size_t index = 0; 104 size_t index = 0;
78 for (Panels::iterator iter = panels_.begin(); iter != panels_.end(); 105 for (Panels::iterator iter = panels_.begin(); iter != panels_.end();
79 ++iter, ++index) { 106 ++iter, ++index) {
80 if (*iter == panel) { 107 if (*iter == panel) {
81 panels_.erase(iter); 108 panels_.erase(iter);
82 DoRefresh(index, panels_.size() - 1); 109 DoRefresh(index, panels_.size() - 1);
83 panel_manager_->OnPanelRemoved(panel); 110 panel_manager_->OnPanelRemoved(panel);
84 if (panels_.empty()) 111 if (panels_.empty()) {
85 panel_manager_->mouse_watcher()->RemoveObserver(this); 112 panel_manager_->mouse_watcher()->RemoveObserver(this);
113 overflow_indicator_.reset();
114 }
115 UpdateOverflowIndicator(current_display_width_);
86 return true; 116 return true;
87 } 117 }
88 } 118 }
89 return false; 119 return false;
90 } 120 }
91 121
92 void PanelOverflowStrip::RemoveAll() { 122 void PanelOverflowStrip::RemoveAll() {
93 // Make a copy of the iterator as closing panels can modify the vector. 123 // Make a copy of the iterator as closing panels can modify the vector.
94 Panels panels_copy = panels_; 124 Panels panels_copy = panels_;
95 125
96 // Start from the bottom to avoid reshuffling. 126 // Start from the bottom to avoid reshuffling.
97 for (Panels::reverse_iterator iter = panels_copy.rbegin(); 127 for (Panels::reverse_iterator iter = panels_copy.rbegin();
98 iter != panels_copy.rend(); ++iter) 128 iter != panels_copy.rend(); ++iter)
99 (*iter)->Close(); 129 (*iter)->Close();
100 } 130 }
101 131
102 void PanelOverflowStrip::OnPanelExpansionStateChanged( 132 void PanelOverflowStrip::OnPanelExpansionStateChanged(
103 Panel* panel, Panel::ExpansionState old_state) { 133 Panel* panel, Panel::ExpansionState old_state) {
104 DCHECK(panel->expansion_state() == Panel::IN_OVERFLOW); 134 DCHECK(panel->expansion_state() == Panel::IN_OVERFLOW);
105 panel_manager_->panel_strip()->Remove(panel); 135 panel_manager_->panel_strip()->Remove(panel);
106 AddPanel(panel); 136 AddPanel(panel);
107 panel->SetAppIconVisibility(false); 137 panel->SetAppIconVisibility(false);
108 } 138 }
109 139
140 void PanelOverflowStrip::OnPanelAttentionStateChanged(Panel* panel) {
141 DCHECK(panel->expansion_state() == Panel::IN_OVERFLOW);
142 UpdateOverflowIndicator(current_display_width_);
143 }
144
110 void PanelOverflowStrip::Refresh() { 145 void PanelOverflowStrip::Refresh() {
111 if (panels_.empty()) 146 if (panels_.empty())
112 return; 147 return;
113 DoRefresh(0, panels_.size() - 1); 148 DoRefresh(0, panels_.size() - 1);
114 } 149 }
115 150
116 void PanelOverflowStrip::DoRefresh(size_t start_index, size_t end_index) { 151 void PanelOverflowStrip::DoRefresh(size_t start_index, size_t end_index) {
117 if (panels_.empty() || start_index == panels_.size()) 152 if (panels_.empty() || start_index == panels_.size())
118 return; 153 return;
119 154
120 DCHECK(end_index < panels_.size()); 155 DCHECK(end_index < panels_.size());
121 156
122 for (size_t index = start_index; index <= end_index; ++index) { 157 for (size_t index = start_index; index <= end_index; ++index) {
123 Panel* panel = panels_[index]; 158 Panel* panel = panels_[index];
124 gfx::Rect new_bounds = ComputeLayout(index, 159 gfx::Rect new_bounds = ComputeLayout(index,
125 panel->IconOnlySize()); 160 panel->IconOnlySize());
126 panel->SetPanelBounds(new_bounds); 161 panel->SetPanelBounds(new_bounds);
127 } 162 }
128 } 163 }
129 164
165 void PanelOverflowStrip::UpdateOverflowIndicator(int width) {
166 if (!overflow_indicator_.get())
167 overflow_indicator_.reset(PanelOverflowIndicator::Create());
168
169 UpdateMaxVisibkePanelsOnExpanded();
170 int max_visible_panels = width > display_area_.width() ?
171 max_visible_panels_on_expanded_ : max_visible_panels_on_shrunk_;
172
173 // Setting the count to 0 will hide the indicator.
174 if (num_panels() <= max_visible_panels) {
175 overflow_indicator_->SetCount(0);
176 return;
177 }
178
179 // Update the bounds and count.
180 int height = overflow_indicator_->GetHeight();
181 overflow_indicator_->SetBounds(gfx::Rect(
182 display_area_.x(),
183 panels_[max_visible_panels - 1]->GetBounds().y() - height,
184 width,
185 height));
186 overflow_indicator_->SetCount(num_panels() - max_visible_panels);
187
188 // The overflow indicator is painted as drawing attention only when there is
189 // at least one hidden panel that is drawing attention.
190 bool is_drawing_attention = false;
191 for (int index = max_visible_panels; index < num_panels(); ++index) {
192 if (panels_[index]->IsDrawingAttention())
193 is_drawing_attention = true;
194 }
195 if (is_drawing_attention)
196 overflow_indicator_->DrawAttention();
197 else
198 overflow_indicator_->StopDrawingAttention();
199 }
200
130 gfx::Rect PanelOverflowStrip::ComputeLayout( 201 gfx::Rect PanelOverflowStrip::ComputeLayout(
131 size_t index, const gfx::Size& iconified_size) const { 202 size_t index, const gfx::Size& iconified_size) const {
132 DCHECK(index != kInvalidPanelIndex); 203 DCHECK(index != kInvalidPanelIndex);
133 204
134 gfx::Rect bounds; 205 gfx::Rect bounds;
135 int bottom = (index == 0) ? display_area_.bottom() : 206 int bottom = (index == 0) ? display_area_.bottom() :
136 panels_[index - 1]->GetBounds().y(); 207 panels_[index - 1]->GetBounds().y();
137 bounds.set_x(display_area_.x()); 208 bounds.set_x(display_area_.x());
138 bounds.set_y(bottom - iconified_size.height()); 209 bounds.set_y(bottom - iconified_size.height());
139 210
140 if (are_overflow_titles_shown_ || 211 if (static_cast<int>(index) < max_visible_panels()) {
141 static_cast<int>(index) < max_visible_panels_) {
142 bounds.set_width(current_display_width_); 212 bounds.set_width(current_display_width_);
143 bounds.set_height(iconified_size.height()); 213 bounds.set_height(iconified_size.height());
144 } else { 214 } else {
145 // Invisible for overflow-on-overflow. 215 // Invisible for overflow-on-overflow.
146 bounds.set_width(0); 216 bounds.set_width(0);
147 bounds.set_height(0); 217 bounds.set_height(0);
148 } 218 }
149 219
150 return bounds; 220 return bounds;
151 } 221 }
152 222
153 void PanelOverflowStrip::OnMouseMove(const gfx::Point& mouse_position) { 223 void PanelOverflowStrip::OnMouseMove(const gfx::Point& mouse_position) {
154 bool show_overflow_titles = ShouldShowOverflowTitles(mouse_position); 224 bool show_overflow_titles = ShouldShowOverflowTitles(mouse_position);
155 ShowOverflowTitles(show_overflow_titles); 225 ShowOverflowTitles(show_overflow_titles);
156 } 226 }
157 227
158 bool PanelOverflowStrip::ShouldShowOverflowTitles( 228 bool PanelOverflowStrip::ShouldShowOverflowTitles(
159 const gfx::Point& mouse_position) const { 229 const gfx::Point& mouse_position) const {
160 if (panels_.empty()) 230 if (panels_.empty())
161 return false; 231 return false;
162 232
163 Panel* top_visible_panel; 233 Panel* top_visible_panel;
164 if (are_overflow_titles_shown_) { 234 if (are_overflow_titles_shown_) {
165 top_visible_panel = panels_.back(); 235 top_visible_panel = panels_.back();
166 } else { 236 } else {
167 top_visible_panel = num_panels() >= max_visible_panels_ ? 237 top_visible_panel = num_panels() >= max_visible_panels_on_shrunk_ ?
168 panels_[max_visible_panels_ - 1] : panels_.back(); 238 panels_[max_visible_panels_on_shrunk_ - 1] : panels_.back();
169 } 239 }
170 return mouse_position.x() <= display_area_.x() + current_display_width_ && 240 return mouse_position.x() <= display_area_.x() + current_display_width_ &&
171 top_visible_panel->GetBounds().y() <= mouse_position.y() && 241 top_visible_panel->GetBounds().y() <= mouse_position.y() &&
172 mouse_position.y() <= display_area_.bottom(); 242 mouse_position.y() <= display_area_.bottom();
173 } 243 }
174 244
175 void PanelOverflowStrip::ShowOverflowTitles(bool show_overflow_titles) { 245 void PanelOverflowStrip::ShowOverflowTitles(bool show_overflow_titles) {
176 if (show_overflow_titles == are_overflow_titles_shown_) 246 if (show_overflow_titles == are_overflow_titles_shown_)
177 return; 247 return;
178 are_overflow_titles_shown_ = show_overflow_titles; 248 are_overflow_titles_shown_ = show_overflow_titles;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 content::NotificationService::current()->Notify( 281 content::NotificationService::current()->Notify(
212 chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED, 282 chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED,
213 content::Source<PanelOverflowStrip>(this), 283 content::Source<PanelOverflowStrip>(this),
214 content::NotificationService::NoDetails()); 284 content::NotificationService::NoDetails());
215 } 285 }
216 286
217 void PanelOverflowStrip::AnimationProgressed(const ui::Animation* animation) { 287 void PanelOverflowStrip::AnimationProgressed(const ui::Animation* animation) {
218 int current_display_width = overflow_hover_animator_->CurrentValueBetween( 288 int current_display_width = overflow_hover_animator_->CurrentValueBetween(
219 overflow_hover_animator_start_width_, overflow_hover_animator_end_width_); 289 overflow_hover_animator_start_width_, overflow_hover_animator_end_width_);
220 bool end_of_shrinking = current_display_width == display_area_.width(); 290 bool end_of_shrinking = current_display_width == display_area_.width();
291 int max_visible_panels = end_of_shrinking ?
292 max_visible_panels_on_shrunk_ : max_visible_panels_on_expanded_;
221 293
222 // Update each overflow panel. 294 // Update each overflow panel.
223 for (size_t i = 0; i < panels_.size(); ++i) { 295 for (int i = 0; i < num_panels(); ++i) {
224 Panel* overflow_panel = panels_[i]; 296 Panel* overflow_panel = panels_[i];
225 gfx::Rect bounds = overflow_panel->GetBounds(); 297 gfx::Rect bounds = overflow_panel->GetBounds();
226 298
227 if (static_cast<int>(i) >= max_visible_panels_ && end_of_shrinking) { 299 if (i >= max_visible_panels) {
228 bounds.set_width(0); 300 bounds.set_width(0);
229 bounds.set_height(0); 301 bounds.set_height(0);
230 } else { 302 } else {
231 bounds.set_width(current_display_width); 303 bounds.set_width(current_display_width);
232 bounds.set_height(overflow_panel->IconOnlySize().height()); 304 bounds.set_height(overflow_panel->IconOnlySize().height());
233 } 305 }
234 306
235 overflow_panel->SetPanelBoundsInstantly(bounds); 307 overflow_panel->SetPanelBoundsInstantly(bounds);
236 } 308 }
309
310 // Update the indicator.
311 UpdateOverflowIndicator(current_display_width);
312 }
313
314 void PanelOverflowStrip::Observe(
315 int type,
316 const content::NotificationSource& source,
317 const content::NotificationDetails& details) {
318 DCHECK(type == content::NOTIFICATION_APP_TERMINATING);
319
320 // The overflow indicator needs to be disposed when the last browser is
321 // closed. Our destructor is called too late in the shutdown sequence.
322 if (overflow_indicator_.get())
323 overflow_indicator_.reset();
237 } 324 }
238 325
239 void PanelOverflowStrip::OnFullScreenModeChanged(bool is_full_screen) { 326 void PanelOverflowStrip::OnFullScreenModeChanged(bool is_full_screen) {
240 for (size_t i = 0; i < panels_.size(); ++i) 327 for (size_t i = 0; i < panels_.size(); ++i)
241 panels_[i]->FullScreenModeChanged(is_full_screen); 328 panels_[i]->FullScreenModeChanged(is_full_screen);
242 } 329 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698