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

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: Fix per feedback 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.
jennb 2011/12/20 02:08:23 Still using shrunk?
jianli 2011/12/20 22:08:10 Done.
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
jennb 2011/12/20 02:08:23 Lumpy sentence. Phrasing it like the comment you w
jianli 2011/12/20 22:08:10 Done.
25 // cannot occupy more than when the mouse hovers over the overflow area.
26 const double kHeightRatioForMaxVisibleOverflowPanelsOnHover = 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_(kMaxVisibleOverflowPanelsOnShrunk),
36 max_visible_panels_on_hover_(0),
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,
jennb 2011/12/20 02:08:23 Comment here about why we register for this.
jianli 2011/12/20 22:08:10 Not needed since we do not need observer now.
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 UpdateMaxVisibkePanelsOnHover();
45 UpdateCurrentWidth(); 55 UpdateCurrentWidth();
46 56
47 Refresh(); 57 Refresh();
48 } 58 }
49 59
60 void PanelOverflowStrip::UpdateMaxVisibkePanelsOnHover() {
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_hover_ = 0;
67 } else if (!max_visible_panels_on_hover_) {
68 max_visible_panels_on_hover_ =
69 kHeightRatioForMaxVisibleOverflowPanelsOnHover *
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();
jennb 2011/12/20 02:08:23 Seems odd to reset the indicator only to recreate
jianli 2011/12/20 22:08:10 Changed to create the overflow indicator on a as-n
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 panel->set_draggable(false); 138 panel->set_draggable(false);
109 } 139 }
110 140
141 void PanelOverflowStrip::OnPanelAttentionStateChanged(Panel* panel) {
142 DCHECK(panel->expansion_state() == Panel::IN_OVERFLOW);
143 UpdateOverflowIndicator(current_display_width_);
144 }
145
111 void PanelOverflowStrip::Refresh() { 146 void PanelOverflowStrip::Refresh() {
112 if (panels_.empty()) 147 if (panels_.empty())
113 return; 148 return;
114 DoRefresh(0, panels_.size() - 1); 149 DoRefresh(0, panels_.size() - 1);
115 } 150 }
116 151
117 void PanelOverflowStrip::DoRefresh(size_t start_index, size_t end_index) { 152 void PanelOverflowStrip::DoRefresh(size_t start_index, size_t end_index) {
118 if (panels_.empty() || start_index == panels_.size()) 153 if (panels_.empty() || start_index == panels_.size())
119 return; 154 return;
120 155
121 DCHECK(end_index < panels_.size()); 156 DCHECK(end_index < panels_.size());
122 157
123 for (size_t index = start_index; index <= end_index; ++index) { 158 for (size_t index = start_index; index <= end_index; ++index) {
124 Panel* panel = panels_[index]; 159 Panel* panel = panels_[index];
125 gfx::Rect new_bounds = ComputeLayout(index, 160 gfx::Rect new_bounds = ComputeLayout(index,
126 panel->IconOnlySize()); 161 panel->IconOnlySize());
127 panel->SetPanelBounds(new_bounds); 162 panel->SetPanelBounds(new_bounds);
128 } 163 }
129 } 164 }
130 165
166 void PanelOverflowStrip::UpdateOverflowIndicator(int width) {
167 if (!overflow_indicator_.get())
168 overflow_indicator_.reset(PanelOverflowIndicator::Create());
169
170 UpdateMaxVisibkePanelsOnHover();
jennb 2011/12/20 02:08:23 Shouldn't need to recompute this every time a pane
jianli 2011/12/20 22:08:10 Updated. When display area is changed, we might no
171 int max_visible_panels = width > display_area_.width() ?
172 max_visible_panels_on_hover_ : max_visible_panels_;
173
174 // Setting the count to 0 will hide the indicator.
175 if (num_panels() <= max_visible_panels) {
176 overflow_indicator_->SetCount(0);
177 return;
178 }
179
180 // Update the bounds and count.
181 int height = overflow_indicator_->GetHeight();
182 overflow_indicator_->SetBounds(gfx::Rect(
183 display_area_.x(),
184 panels_[max_visible_panels - 1]->GetBounds().y() - height,
185 width,
186 height));
187 overflow_indicator_->SetCount(num_panels() - max_visible_panels);
188
189 // The overflow indicator is painted as drawing attention only when there is
190 // at least one hidden panel that is drawing attention.
191 bool is_drawing_attention = false;
192 for (int index = max_visible_panels; index < num_panels(); ++index) {
193 if (panels_[index]->IsDrawingAttention())
194 is_drawing_attention = true;
jennb 2011/12/20 02:08:23 break out of loop as soon as you find one drawing
jianli 2011/12/20 22:08:10 Done.
195 }
196 if (is_drawing_attention)
197 overflow_indicator_->DrawAttention();
198 else
199 overflow_indicator_->StopDrawingAttention();
200 }
201
131 gfx::Rect PanelOverflowStrip::ComputeLayout( 202 gfx::Rect PanelOverflowStrip::ComputeLayout(
132 size_t index, const gfx::Size& iconified_size) const { 203 size_t index, const gfx::Size& iconified_size) const {
133 DCHECK(index != kInvalidPanelIndex); 204 DCHECK(index != kInvalidPanelIndex);
134 205
135 gfx::Rect bounds; 206 gfx::Rect bounds;
136 int bottom = (index == 0) ? display_area_.bottom() : 207 int bottom = (index == 0) ? display_area_.bottom() :
137 panels_[index - 1]->GetBounds().y(); 208 panels_[index - 1]->GetBounds().y();
138 bounds.set_x(display_area_.x()); 209 bounds.set_x(display_area_.x());
139 bounds.set_y(bottom - iconified_size.height()); 210 bounds.set_y(bottom - iconified_size.height());
140 211
141 if (are_overflow_titles_shown_ || 212 if (static_cast<int>(index) < max_visible_panels()) {
142 static_cast<int>(index) < max_visible_panels_) {
143 bounds.set_width(current_display_width_); 213 bounds.set_width(current_display_width_);
144 bounds.set_height(iconified_size.height()); 214 bounds.set_height(iconified_size.height());
145 } else { 215 } else {
146 // Invisible for overflow-on-overflow. 216 // Invisible for overflow-on-overflow.
147 bounds.set_width(0); 217 bounds.set_width(0);
148 bounds.set_height(0); 218 bounds.set_height(0);
149 } 219 }
150 220
151 return bounds; 221 return bounds;
152 } 222 }
153 223
154 void PanelOverflowStrip::OnMouseMove(const gfx::Point& mouse_position) { 224 void PanelOverflowStrip::OnMouseMove(const gfx::Point& mouse_position) {
155 bool show_overflow_titles = ShouldShowOverflowTitles(mouse_position); 225 bool show_overflow_titles = ShouldShowOverflowTitles(mouse_position);
156 ShowOverflowTitles(show_overflow_titles); 226 ShowOverflowTitles(show_overflow_titles);
157 } 227 }
158 228
159 bool PanelOverflowStrip::ShouldShowOverflowTitles( 229 bool PanelOverflowStrip::ShouldShowOverflowTitles(
160 const gfx::Point& mouse_position) const { 230 const gfx::Point& mouse_position) const {
161 if (panels_.empty()) 231 if (panels_.empty())
162 return false; 232 return false;
163 233
164 Panel* top_visible_panel; 234 Panel* top_visible_panel = num_panels() >= max_visible_panels() ?
165 if (are_overflow_titles_shown_) { 235 panels_[max_visible_panels() - 1] : panels_.back();
166 top_visible_panel = panels_.back();
167 } else {
168 top_visible_panel = num_panels() >= max_visible_panels_ ?
169 panels_[max_visible_panels_ - 1] : panels_.back();
170 }
171 return mouse_position.x() <= display_area_.x() + current_display_width_ && 236 return mouse_position.x() <= display_area_.x() + current_display_width_ &&
172 top_visible_panel->GetBounds().y() <= mouse_position.y() && 237 top_visible_panel->GetBounds().y() <= mouse_position.y() &&
173 mouse_position.y() <= display_area_.bottom(); 238 mouse_position.y() <= display_area_.bottom();
174 } 239 }
175 240
176 void PanelOverflowStrip::ShowOverflowTitles(bool show_overflow_titles) { 241 void PanelOverflowStrip::ShowOverflowTitles(bool show_overflow_titles) {
177 if (show_overflow_titles == are_overflow_titles_shown_) 242 if (show_overflow_titles == are_overflow_titles_shown_)
178 return; 243 return;
179 are_overflow_titles_shown_ = show_overflow_titles; 244 are_overflow_titles_shown_ = show_overflow_titles;
180 245
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 content::NotificationService::current()->Notify( 277 content::NotificationService::current()->Notify(
213 chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED, 278 chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED,
214 content::Source<PanelOverflowStrip>(this), 279 content::Source<PanelOverflowStrip>(this),
215 content::NotificationService::NoDetails()); 280 content::NotificationService::NoDetails());
216 } 281 }
217 282
218 void PanelOverflowStrip::AnimationProgressed(const ui::Animation* animation) { 283 void PanelOverflowStrip::AnimationProgressed(const ui::Animation* animation) {
219 int current_display_width = overflow_hover_animator_->CurrentValueBetween( 284 int current_display_width = overflow_hover_animator_->CurrentValueBetween(
220 overflow_hover_animator_start_width_, overflow_hover_animator_end_width_); 285 overflow_hover_animator_start_width_, overflow_hover_animator_end_width_);
221 bool end_of_shrinking = current_display_width == display_area_.width(); 286 bool end_of_shrinking = current_display_width == display_area_.width();
287 int max_visible_panels = end_of_shrinking ?
288 max_visible_panels_ : max_visible_panels_on_hover_;
222 289
223 // Update each overflow panel. 290 // Update each overflow panel.
224 for (size_t i = 0; i < panels_.size(); ++i) { 291 for (int i = 0; i < num_panels(); ++i) {
225 Panel* overflow_panel = panels_[i]; 292 Panel* overflow_panel = panels_[i];
226 gfx::Rect bounds = overflow_panel->GetBounds(); 293 gfx::Rect bounds = overflow_panel->GetBounds();
227 294
228 if (static_cast<int>(i) >= max_visible_panels_ && end_of_shrinking) { 295 if (i >= max_visible_panels) {
229 bounds.set_width(0); 296 bounds.set_width(0);
230 bounds.set_height(0); 297 bounds.set_height(0);
231 } else { 298 } else {
232 bounds.set_width(current_display_width); 299 bounds.set_width(current_display_width);
233 bounds.set_height(overflow_panel->IconOnlySize().height()); 300 bounds.set_height(overflow_panel->IconOnlySize().height());
234 } 301 }
235 302
236 overflow_panel->SetPanelBoundsInstantly(bounds); 303 overflow_panel->SetPanelBoundsInstantly(bounds);
237 } 304 }
305
306 // Update the indicator.
307 UpdateOverflowIndicator(current_display_width);
jennb 2011/12/20 02:08:23 Count won't be changing during animation. Maybe Up
jianli 2011/12/20 22:08:10 Separated the logic as suggested.
308 }
309
310 void PanelOverflowStrip::Observe(
311 int type,
312 const content::NotificationSource& source,
313 const content::NotificationDetails& details) {
314 DCHECK(type == content::NOTIFICATION_APP_TERMINATING);
315
316 // The overflow indicator needs to be disposed when the last browser is
jennb 2011/12/20 02:08:23 Don't need this if you destroy the indicator when
jianli 2011/12/20 22:08:10 Removed.
317 // closed. Our destructor is called too late in the shutdown sequence.
318 if (overflow_indicator_.get())
319 overflow_indicator_.reset();
238 } 320 }
239 321
240 void PanelOverflowStrip::OnFullScreenModeChanged(bool is_full_screen) { 322 void PanelOverflowStrip::OnFullScreenModeChanged(bool is_full_screen) {
241 for (size_t i = 0; i < panels_.size(); ++i) 323 for (size_t i = 0; i < panels_.size(); ++i)
242 panels_[i]->FullScreenModeChanged(is_full_screen); 324 panels_[i]->FullScreenModeChanged(is_full_screen);
243 } 325 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698