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

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

Issue 8744005: Refactor PanelManager to create PanelStrip. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove leftover override 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_manager.h" 5 #include "chrome/browser/ui/panels/panel_manager.h"
6 6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/logging.h" 7 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop.h"
13 #include "chrome/browser/ui/browser.h" 9 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_list.h" 10 #include "chrome/browser/ui/browser_list.h"
15 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" 11 #include "chrome/browser/ui/panels/panel_mouse_watcher.h"
12 #include "chrome/browser/ui/panels/panel_strip.h"
16 #include "chrome/browser/ui/window_sizer.h" 13 #include "chrome/browser/ui/window_sizer.h"
17 #include "chrome/common/chrome_notification_types.h" 14 #include "chrome/common/chrome_notification_types.h"
18 #include "content/public/browser/notification_service.h" 15 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h" 16 #include "content/public/browser/notification_source.h"
20 17
21 namespace { 18 namespace {
22 // Invalid panel index. 19 const int kOverflowStripThickness = 24;
23 const size_t kInvalidPanelIndex = static_cast<size_t>(-1);
24 20
25 // Width of spacing between first panel and the right edge of the screen. 21 // Width of spacing around panel strip and the left/right edges of the screen.
26 // Leaving a larger gap at the edge of the screen allows access to UI 22 const int kPanelStripLeftMargin = kOverflowStripThickness + 6;
27 // elements located on the bottom right of windows. 23 const int kPanelStripRightMargin = 24;
28 const int kRightScreenEdgeSpacingWidth = 24;
29 24
30 // Width to height ratio is used to compute the default width or height 25 // Height of panel strip is based on the factor of the working area.
31 // when only one value is provided. 26 const double kPanelStripHeightFactor = 0.5;
32 const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio
33 27
34 // Maxmium width and height of a panel based on the factor of the working
35 // area.
36 const double kPanelMaxWidthFactor = 0.35;
37 const double kPanelMaxHeightFactor = 0.5;
38
39 // Occasionally some system, like Windows, might not bring up or down the bottom
40 // bar when the mouse enters or leaves the bottom screen area. This is the
41 // maximum time we will wait for the bottom bar visibility change notification.
42 // After the time expires, we bring up/down the titlebars as planned.
43 const int kMaxMillisecondsWaitForBottomBarVisibilityChange = 1000;
44
45 // See usage below.
46 #if defined(TOOLKIT_GTK)
47 const int kMillisecondsBeforeCollapsingFromTitleOnlyState = 2000;
48 #else
49 const int kMillisecondsBeforeCollapsingFromTitleOnlyState = 0;
50 #endif
51 } // namespace 28 } // namespace
52 29
53 // static 30 // static
54 const int PanelManager::kPanelMinWidth = 100;
55 const int PanelManager::kPanelMinHeight = 20;
56
57 // static
58 PanelManager* PanelManager::GetInstance() { 31 PanelManager* PanelManager::GetInstance() {
59 static base::LazyInstance<PanelManager> instance = LAZY_INSTANCE_INITIALIZER; 32 static base::LazyInstance<PanelManager> instance = LAZY_INSTANCE_INITIALIZER;
60 return instance.Pointer(); 33 return instance.Pointer();
61 } 34 }
62 35
63 PanelManager::PanelManager() 36 PanelManager::PanelManager()
64 : minimized_panel_count_(0), 37 : ALLOW_THIS_IN_INITIALIZER_LIST(panel_strip_(new PanelStrip(this))),
65 are_titlebars_up_(false), 38 panel_mouse_watcher_(PanelMouseWatcher::Create()),
66 dragging_panel_index_(kInvalidPanelIndex), 39 ALLOW_THIS_IN_INITIALIZER_LIST(
67 dragging_panel_original_x_(0), 40 auto_hiding_desktop_bar_(AutoHidingDesktopBar::Create(this))),
Dmitry Titov 2011/11/30 20:38:45 why not just initialize those in the body of ctor,
68 delayed_titlebar_action_(NO_ACTION), 41 auto_sizing_enabled_(true) {
69 remove_delays_for_testing_(false),
70 titlebar_action_factory_(this),
71 auto_sizing_enabled_(true),
72 mouse_watching_disabled_(false) {
73 panel_mouse_watcher_.reset(PanelMouseWatcher::Create());
74 auto_hiding_desktop_bar_ = AutoHidingDesktopBar::Create(this);
75 OnDisplayChanged(); 42 OnDisplayChanged();
76 } 43 }
77 44
78 PanelManager::~PanelManager() { 45 PanelManager::~PanelManager() {
79 DCHECK(panels_.empty());
80 DCHECK(panels_pending_to_remove_.empty());
81 DCHECK_EQ(0, minimized_panel_count_);
82 } 46 }
83 47
84 void PanelManager::OnDisplayChanged() { 48 void PanelManager::OnDisplayChanged() {
85 scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider( 49 scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider(
86 WindowSizer::CreateDefaultMonitorInfoProvider()); 50 WindowSizer::CreateDefaultMonitorInfoProvider());
87 #if defined(OS_MACOSX) 51 #if defined(OS_MACOSX)
88 // On OSX, panels should be dropped all the way to the bottom edge of the 52 // On OSX, panels should be dropped all the way to the bottom edge of the
89 // screen (and overlap Dock). 53 // screen (and overlap Dock).
90 gfx::Rect work_area = info_provider->GetPrimaryMonitorBounds(); 54 gfx::Rect work_area = info_provider->GetPrimaryMonitorBounds();
91 #else 55 #else
92 gfx::Rect work_area = info_provider->GetPrimaryMonitorWorkArea(); 56 gfx::Rect work_area = info_provider->GetPrimaryMonitorWorkArea();
93 #endif 57 #endif
94 SetWorkArea(work_area); 58 SetWorkArea(work_area);
95 } 59 }
96 60
97 void PanelManager::SetWorkArea(const gfx::Rect& work_area) { 61 void PanelManager::SetWorkArea(const gfx::Rect& work_area) {
98 if (work_area == work_area_) 62 if (work_area == work_area_)
99 return; 63 return;
100 work_area_ = work_area; 64 work_area_ = work_area;
101 65
102 auto_hiding_desktop_bar_->UpdateWorkArea(work_area_); 66 auto_hiding_desktop_bar_->UpdateWorkArea(work_area_);
103 AdjustWorkAreaForAutoHidingDesktopBars(); 67 AdjustWorkAreaForAutoHidingDesktopBars();
68 Layout();
69 }
104 70
105 Rearrange(panels_.begin(), StartingRightPosition()); 71 void PanelManager::Layout() {
72 int height =
73 static_cast<int>(adjusted_work_area_.height() * kPanelStripHeightFactor);
74 gfx::Rect panel_strip_bounds;
75 panel_strip_bounds.set_x(adjusted_work_area_.x() + kPanelStripLeftMargin);
76 panel_strip_bounds.set_y(adjusted_work_area_.bottom() - height);
77 panel_strip_bounds.set_width(adjusted_work_area_.width() -
78 kPanelStripLeftMargin - kPanelStripRightMargin);
79 panel_strip_bounds.set_height(height);
80 panel_strip_->SetBounds(panel_strip_bounds);
106 } 81 }
107 82
108 Panel* PanelManager::CreatePanel(Browser* browser) { 83 Panel* PanelManager::CreatePanel(Browser* browser) {
109 int width = browser->override_bounds().width(); 84 int width = browser->override_bounds().width();
110 int height = browser->override_bounds().height(); 85 int height = browser->override_bounds().height();
111
112 Panel* panel = new Panel(browser, gfx::Size(width, height)); 86 Panel* panel = new Panel(browser, gfx::Size(width, height));
113 87 panel_strip_->AddPanel(panel);
114 int max_panel_width = GetMaxPanelWidth();
115 int max_panel_height = GetMaxPanelHeight();
116 panel->SetSizeRange(gfx::Size(kPanelMinWidth, kPanelMinHeight),
117 gfx::Size(max_panel_width, max_panel_height));
118
119 // Auto resizable is enabled only if no initial size is provided.
120 bool auto_resize = (width == 0 && height == 0);
121 panel->SetAutoResizable(auto_resize);
122
123 // Adjust the width and height to fit into our constraint.
124 if (!auto_resize) {
125 if (height == 0)
126 height = width / kPanelDefaultWidthToHeightRatio;
127 if (width == 0)
128 width = height * kPanelDefaultWidthToHeightRatio;
129 }
130
131 if (width < kPanelMinWidth)
132 width = kPanelMinWidth;
133 else if (width > max_panel_width)
134 width = max_panel_width;
135
136 if (height < kPanelMinHeight)
137 height = kPanelMinHeight;
138 else if (height > max_panel_height)
139 height = max_panel_height;
140
141 panel->set_restored_size(gfx::Size(width, height));
142
143 // Layout the new panel.
144 int y = adjusted_work_area_.bottom() - height;
145 int x = GetRightMostAvailablePosition() - width;
146 panel->Initialize(gfx::Rect(x, y, width, height));
147
148 panels_.push_back(panel);
149 88
150 content::NotificationService::current()->Notify( 89 content::NotificationService::current()->Notify(
151 chrome::NOTIFICATION_PANEL_ADDED, 90 chrome::NOTIFICATION_PANEL_ADDED,
152 content::Source<Panel>(panel), 91 content::Source<Panel>(panel),
153 content::NotificationService::NoDetails()); 92 content::NotificationService::NoDetails());
154 93
155 return panel; 94 return panel;
156 } 95 }
157 96
158 int PanelManager::GetMaxPanelWidth() const {
159 return static_cast<int>(adjusted_work_area_.width() * kPanelMaxWidthFactor);
160 }
161
162 int PanelManager::GetMaxPanelHeight() const {
163 return static_cast<int>(adjusted_work_area_.height() * kPanelMaxHeightFactor);
164 }
165
166 int PanelManager::StartingRightPosition() const { 97 int PanelManager::StartingRightPosition() const {
167 return adjusted_work_area_.right() - kRightScreenEdgeSpacingWidth; 98 return panel_strip_->StartingRightPosition();
168 }
169
170 int PanelManager::GetRightMostAvailablePosition() const {
171 return panels_.empty() ? StartingRightPosition() :
172 (panels_.back()->GetBounds().x() - kPanelsHorizontalSpacing);
173 } 99 }
174 100
175 void PanelManager::Remove(Panel* panel) { 101 void PanelManager::Remove(Panel* panel) {
176 // If we're in the process of dragging, delay the removal. 102 if (panel_strip_->Remove(panel))
177 if (dragging_panel_index_ != kInvalidPanelIndex) {
178 panels_pending_to_remove_.push_back(panel);
179 return; 103 return;
180 } 104 // TODO(jianli): else try removing from overflow strip
181
182 DoRemove(panel);
183 } 105 }
184 106
185 void PanelManager::DelayedRemove() { 107 void PanelManager::OnPanelRemoved(Panel* panel) {
186 for (size_t i = 0; i < panels_pending_to_remove_.size(); ++i)
187 DoRemove(panels_pending_to_remove_[i]);
188 panels_pending_to_remove_.clear();
189 }
190
191 void PanelManager::DoRemove(Panel* panel) {
192 Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
193 if (iter == panels_.end())
194 return;
195
196 if (panel->expansion_state() != Panel::EXPANDED)
197 DecrementMinimizedPanels();
198
199 gfx::Rect bounds = (*iter)->GetBounds();
200 Rearrange(panels_.erase(iter), bounds.right());
201
202 content::NotificationService::current()->Notify( 108 content::NotificationService::current()->Notify(
203 chrome::NOTIFICATION_PANEL_REMOVED, 109 chrome::NOTIFICATION_PANEL_REMOVED,
204 content::Source<Panel>(panel), 110 content::Source<Panel>(panel),
205 content::NotificationService::NoDetails()); 111 content::NotificationService::NoDetails());
206 } 112 }
207 113
208 void PanelManager::StartDragging(Panel* panel) { 114 void PanelManager::StartDragging(Panel* panel) {
209 for (size_t i = 0; i < panels_.size(); ++i) { 115 panel_strip_->StartDragging(panel);
210 if (panels_[i] == panel) {
211 dragging_panel_index_ = i;
212 dragging_panel_bounds_ = panel->GetBounds();
213 dragging_panel_original_x_ = dragging_panel_bounds_.x();
214 break;
215 }
216 }
217 } 116 }
218 117
219 void PanelManager::Drag(int delta_x) { 118 void PanelManager::Drag(int delta_x) {
220 DCHECK(dragging_panel_index_ != kInvalidPanelIndex); 119 panel_strip_->Drag(delta_x);
221
222 if (!delta_x)
223 return;
224
225 // Moves this panel to the dragging position.
226 Panel* dragging_panel = panels_[dragging_panel_index_];
227 gfx::Rect new_bounds(dragging_panel->GetBounds());
228 new_bounds.set_x(new_bounds.x() + delta_x);
229 dragging_panel->SetPanelBounds(new_bounds);
230
231 // Checks and processes other affected panels.
232 if (delta_x > 0)
233 DragRight();
234 else
235 DragLeft();
236 }
237
238 void PanelManager::DragLeft() {
239 Panel* dragging_panel = panels_[dragging_panel_index_];
240
241 // This is the left corner of the dragging panel. We use it to check against
242 // all the panels on its left.
243 int dragging_panel_left_boundary = dragging_panel->GetBounds().x();
244
245 // This is the right corner which a panel will be moved to.
246 int current_panel_right_boundary =
247 dragging_panel_bounds_.x() + dragging_panel_bounds_.width();
248
249 // Checks the panels to the left of the dragging panel.
250 size_t current_panel_index = dragging_panel_index_ + 1;
251 for (; current_panel_index < panels_.size(); ++current_panel_index) {
252 Panel* current_panel = panels_[current_panel_index];
253
254 // Current panel will only be affected if the left corner of dragging
255 // panel goes beyond the middle position of the current panel.
256 if (dragging_panel_left_boundary > current_panel->GetBounds().x() +
257 current_panel->GetBounds().width() / 2)
258 break;
259
260 // Moves current panel to the new position.
261 gfx::Rect bounds(current_panel->GetBounds());
262 bounds.set_x(current_panel_right_boundary - bounds.width());
263 current_panel_right_boundary -= bounds.width() + kPanelsHorizontalSpacing;
264 current_panel->SetPanelBounds(bounds);
265
266 // Updates the index of current panel since it has been moved to the
267 // position of previous panel.
268 panels_[current_panel_index - 1] = current_panel;
269 }
270
271 // Updates the position and index of dragging panel as the result of moving
272 // other affected panels.
273 if (current_panel_index != dragging_panel_index_ + 1) {
274 dragging_panel_bounds_.set_x(current_panel_right_boundary -
275 dragging_panel_bounds_.width());
276 dragging_panel_index_ = current_panel_index - 1;
277 panels_[dragging_panel_index_] = dragging_panel;
278 }
279 }
280
281 void PanelManager::DragRight() {
282 Panel* dragging_panel = panels_[dragging_panel_index_];
283
284 // This is the right corner of the dragging panel. We use it to check against
285 // all the panels on its right.
286 int dragging_panel_right_boundary = dragging_panel->GetBounds().x() +
287 dragging_panel->GetBounds().width() - 1;
288
289 // This is the left corner which a panel will be moved to.
290 int current_panel_left_boundary = dragging_panel_bounds_.x();
291
292 // Checks the panels to the right of the dragging panel.
293 int current_panel_index = static_cast<int>(dragging_panel_index_) - 1;
294 for (; current_panel_index >= 0; --current_panel_index) {
295 Panel* current_panel = panels_[current_panel_index];
296
297 // Current panel will only be affected if the right corner of dragging
298 // panel goes beyond the middle position of the current panel.
299 if (dragging_panel_right_boundary < current_panel->GetBounds().x() +
300 current_panel->GetBounds().width() / 2)
301 break;
302
303 // Moves current panel to the new position.
304 gfx::Rect bounds(current_panel->GetBounds());
305 bounds.set_x(current_panel_left_boundary);
306 current_panel_left_boundary += bounds.width() + kPanelsHorizontalSpacing;
307 current_panel->SetPanelBounds(bounds);
308
309 // Updates the index of current panel since it has been moved to the
310 // position of previous panel.
311 panels_[current_panel_index + 1] = current_panel;
312 }
313
314 // Updates the position and index of dragging panel as the result of moving
315 // other affected panels.
316 if (current_panel_index != static_cast<int>(dragging_panel_index_) - 1) {
317 dragging_panel_bounds_.set_x(current_panel_left_boundary);
318 dragging_panel_index_ = current_panel_index + 1;
319 panels_[dragging_panel_index_] = dragging_panel;
320 }
321 } 120 }
322 121
323 void PanelManager::EndDragging(bool cancelled) { 122 void PanelManager::EndDragging(bool cancelled) {
324 DCHECK(dragging_panel_index_ != kInvalidPanelIndex); 123 panel_strip_->EndDragging(cancelled);
325
326 if (cancelled) {
327 Drag(dragging_panel_original_x_ -
328 panels_[dragging_panel_index_]->GetBounds().x());
329 } else {
330 panels_[dragging_panel_index_]->SetPanelBounds(
331 dragging_panel_bounds_);
332 }
333
334 dragging_panel_index_ = kInvalidPanelIndex;
335
336 DelayedRemove();
337 } 124 }
338 125
339 void PanelManager::OnPanelExpansionStateChanged( 126 void PanelManager::OnPanelExpansionStateChanged(
340 Panel::ExpansionState old_state, Panel::ExpansionState new_state) { 127 Panel::ExpansionState old_state, Panel::ExpansionState new_state) {
341 DCHECK_NE(new_state, old_state); 128 panel_strip_->OnPanelExpansionStateChanged(old_state, new_state);
342 switch (new_state) {
343 case Panel::EXPANDED:
344 DecrementMinimizedPanels();
345 break;
346 case Panel::MINIMIZED:
347 case Panel::TITLE_ONLY:
348 if (old_state == Panel::EXPANDED)
349 IncrementMinimizedPanels();
350 break;
351 default:
352 break;
353 }
354 }
355
356 void PanelManager::IncrementMinimizedPanels() {
357 if (!mouse_watching_disabled_ && !minimized_panel_count_)
358 panel_mouse_watcher_->AddObserver(this);
359 minimized_panel_count_++;
360 DCHECK_LE(minimized_panel_count_, num_panels());
361 }
362
363 void PanelManager::DecrementMinimizedPanels() {
364 minimized_panel_count_--;
365 DCHECK_GE(minimized_panel_count_, 0);
366 if (!mouse_watching_disabled_ && !minimized_panel_count_)
367 panel_mouse_watcher_->RemoveObserver(this);
368 } 129 }
369 130
370 void PanelManager::OnPreferredWindowSizeChanged( 131 void PanelManager::OnPreferredWindowSizeChanged(
371 Panel* panel, const gfx::Size& preferred_window_size) { 132 Panel* panel, const gfx::Size& preferred_window_size) {
372 if (!auto_sizing_enabled_) 133 if (!auto_sizing_enabled_)
373 return; 134 return;
374 135 panel_strip_->OnPreferredWindowSizeChanged(panel, preferred_window_size);
375 gfx::Rect bounds = panel->GetBounds();
376
377 // The panel width:
378 // * cannot grow or shrink to go beyond [min_width, max_width]
379 int new_width = preferred_window_size.width();
380 if (new_width > panel->max_size().width())
381 new_width = panel->max_size().width();
382 if (new_width < panel->min_size().width())
383 new_width = panel->min_size().width();
384
385 if (new_width != bounds.width()) {
386 int delta = bounds.width() - new_width;
387 bounds.set_x(bounds.x() + delta);
388 bounds.set_width(new_width);
389
390 // Reposition all the panels on the left.
391 int panel_index = -1;
392 for (int i = 0; i < static_cast<int>(panels_.size()); ++i) {
393 if (panels_[i] == panel) {
394 panel_index = i;
395 break;
396 }
397 }
398 DCHECK(panel_index >= 0);
399 for (int i = static_cast<int>(panels_.size()) -1; i > panel_index;
400 --i) {
401 gfx::Rect this_bounds = panels_[i]->GetBounds();
402 this_bounds.set_x(this_bounds.x() + delta);
403 panels_[i]->SetPanelBounds(this_bounds);
404 }
405 }
406
407 // The panel height:
408 // * cannot grow or shrink to go beyond [min_height, max_height]
409 int new_height = preferred_window_size.height();
410 if (new_height > panel->max_size().height())
411 new_height = panel->max_size().height();
412 if (new_height < panel->min_size().height())
413 new_height = panel->min_size().height();
414
415 // Only need to adjust bounds height when panel is expanded.
416 gfx::Size restored_size = panel->restored_size();
417 if (new_height != restored_size.height() &&
418 panel->expansion_state() == Panel::EXPANDED) {
419 bounds.set_y(bounds.y() - new_height + bounds.height());
420 bounds.set_height(new_height);
421 }
422
423 gfx::Size new_size = gfx::Size(new_width, new_height);
424 if (new_size != restored_size)
425 panel->set_restored_size(new_size);
426
427 panel->SetPanelBounds(bounds);
428 } 136 }
429 137
430 bool PanelManager::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const { 138 bool PanelManager::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const {
431 // We should always bring up the titlebar if the mouse is over the 139 return panel_strip_->ShouldBringUpTitlebars(mouse_x, mouse_y);
432 // visible auto-hiding bottom bar.
433 if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_BOTTOM) &&
434 auto_hiding_desktop_bar_->GetVisibility(
435 AutoHidingDesktopBar::ALIGN_BOTTOM) ==
436 AutoHidingDesktopBar::VISIBLE &&
437 mouse_y >= adjusted_work_area_.bottom())
438 return true;
439
440 for (Panels::const_iterator iter = panels_.begin();
441 iter != panels_.end(); ++iter) {
442 if ((*iter)->ShouldBringUpTitlebar(mouse_x, mouse_y))
443 return true;
444 }
445 return false;
446 } 140 }
447 141
448 void PanelManager::BringUpOrDownTitlebars(bool bring_up) { 142 void PanelManager::BringUpOrDownTitlebars(bool bring_up) {
449 if (are_titlebars_up_ == bring_up) 143 panel_strip_->BringUpOrDownTitlebars(bring_up);
450 return;
451 are_titlebars_up_ = bring_up;
452
453 int task_delay_milliseconds = 0;
454
455 // If the auto-hiding bottom bar exists, delay the action until the bottom
456 // bar is fully visible or hidden. We do not want both bottom bar and panel
457 // titlebar to move at the same time but with different speeds.
458 if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_BOTTOM)) {
459 AutoHidingDesktopBar::Visibility visibility = auto_hiding_desktop_bar_->
460 GetVisibility(AutoHidingDesktopBar::ALIGN_BOTTOM);
461 if (visibility != (bring_up ? AutoHidingDesktopBar::VISIBLE
462 : AutoHidingDesktopBar::HIDDEN)) {
463 // Occasionally some system, like Windows, might not bring up or down the
464 // bottom bar when the mouse enters or leaves the bottom screen area.
465 // Thus, we schedule a delayed task to do the work if we do not receive
466 // the bottom bar visibility change notification within a certain period
467 // of time.
468 task_delay_milliseconds =
469 kMaxMillisecondsWaitForBottomBarVisibilityChange;
470 }
471 }
472
473 // On some OSes, the interaction with native Taskbars/Docks may be improved
474 // if the panels do not go back to minimized state too fast. For example,
475 // it makes it possible to hit the titlebar on OSX if Dock has Magnifying
476 // enabled - the panels stay up for a while after Dock magnification effect
477 // stops covering the panels.
478 //
479 // Another example would be taskbar in auto-hide mode on Linux. In this mode
480 // taskbar will cover the panel in title hover mode, leaving it up for a few
481 // seconds would allow the user to be able to click on it.
482 //
483 // Currently, no platforms use both delays.
484 DCHECK(task_delay_milliseconds == 0);
485 if (!bring_up)
486 task_delay_milliseconds = kMillisecondsBeforeCollapsingFromTitleOnlyState;
487
488 // OnAutoHidingDesktopBarVisibilityChanged will handle this.
489 delayed_titlebar_action_ = bring_up ? BRING_UP : BRING_DOWN;
490 if (remove_delays_for_testing_)
491 task_delay_milliseconds = 0;
492
493 // If user moves the mouse in and out of mouse tracking area, we might have
494 // previously posted but not yet dispatched task in the queue. New action
495 // should always 'reset' the delays so cancel any tasks that haven't run yet
496 // and post a new one.
497 titlebar_action_factory_.InvalidateWeakPtrs();
498 MessageLoop::current()->PostDelayedTask(
499 FROM_HERE,
500 base::Bind(&PanelManager::DelayedBringUpOrDownTitlebarsCheck,
501 titlebar_action_factory_.GetWeakPtr()),
502 task_delay_milliseconds);
503 }
504
505 void PanelManager::DelayedBringUpOrDownTitlebarsCheck() {
506 // Task was already processed or cancelled - bail out.
507 if (delayed_titlebar_action_ == NO_ACTION)
508 return;
509
510 bool need_to_bring_up_titlebars = (delayed_titlebar_action_ == BRING_UP);
511
512 delayed_titlebar_action_ = NO_ACTION;
513
514 // Check if the action is still needed based on the latest mouse position. The
515 // user could move the mouse into the tracking area and then quickly move it
516 // out of the area. In case of this, cancel the action.
517 if (are_titlebars_up_ != need_to_bring_up_titlebars)
518 return;
519
520 DoBringUpOrDownTitlebars(need_to_bring_up_titlebars);
521 }
522
523 void PanelManager::DoBringUpOrDownTitlebars(bool bring_up) {
524 for (Panels::const_iterator iter = panels_.begin();
525 iter != panels_.end(); ++iter) {
526 Panel* panel = *iter;
527
528 // Skip any panel that is drawing the attention.
529 if (panel->IsDrawingAttention())
530 continue;
531
532 if (bring_up) {
533 if (panel->expansion_state() == Panel::MINIMIZED)
534 panel->SetExpansionState(Panel::TITLE_ONLY);
535 } else {
536 if (panel->expansion_state() == Panel::TITLE_ONLY)
537 panel->SetExpansionState(Panel::MINIMIZED);
538 }
539 }
540 } 144 }
541 145
542 void PanelManager::AdjustWorkAreaForAutoHidingDesktopBars() { 146 void PanelManager::AdjustWorkAreaForAutoHidingDesktopBars() {
543 // Note that we do not care about the desktop bar aligned to the top edge 147 // Note that we do not care about the desktop bar aligned to the top edge
544 // since panels could not reach so high due to size constraint. 148 // since panels could not reach so high due to size constraint.
545 adjusted_work_area_ = work_area_; 149 adjusted_work_area_ = work_area_;
546 if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_LEFT)) { 150 if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_LEFT)) {
547 int space = auto_hiding_desktop_bar_->GetThickness( 151 int space = auto_hiding_desktop_bar_->GetThickness(
548 AutoHidingDesktopBar::ALIGN_LEFT); 152 AutoHidingDesktopBar::ALIGN_LEFT);
549 adjusted_work_area_.set_x(adjusted_work_area_.x() + space); 153 adjusted_work_area_.set_x(adjusted_work_area_.x() + space);
550 adjusted_work_area_.set_width(adjusted_work_area_.width() - space); 154 adjusted_work_area_.set_width(adjusted_work_area_.width() - space);
551 } 155 }
552 if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_RIGHT)) { 156 if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_RIGHT)) {
553 int space = auto_hiding_desktop_bar_->GetThickness( 157 int space = auto_hiding_desktop_bar_->GetThickness(
554 AutoHidingDesktopBar::ALIGN_RIGHT); 158 AutoHidingDesktopBar::ALIGN_RIGHT);
555 adjusted_work_area_.set_width(adjusted_work_area_.width() - space); 159 adjusted_work_area_.set_width(adjusted_work_area_.width() - space);
556 } 160 }
557 } 161 }
558 162
559 int PanelManager::GetBottomPositionForExpansionState( 163 int PanelManager::GetBottomPositionForExpansionState(
560 Panel::ExpansionState expansion_state) const { 164 Panel::ExpansionState expansion_state) const {
561 int bottom = adjusted_work_area_.bottom(); 165 return panel_strip_->GetBottomPositionForExpansionState(expansion_state);
562 // If there is an auto-hiding desktop bar aligned to the bottom edge, we need
563 // to move the title-only panel above the auto-hiding desktop bar.
564 if (expansion_state == Panel::TITLE_ONLY &&
565 auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_BOTTOM)) {
566 bottom -= auto_hiding_desktop_bar_->GetThickness(
567 AutoHidingDesktopBar::ALIGN_BOTTOM);
568 }
569
570 return bottom;
571 } 166 }
572 167
573 BrowserWindow* PanelManager::GetNextBrowserWindowToActivate( 168 BrowserWindow* PanelManager::GetNextBrowserWindowToActivate(
574 Panel* panel) const { 169 Panel* panel) const {
575 // Find the last active browser window that is not minimized. 170 // Find the last active browser window that is not minimized.
576 BrowserList::const_reverse_iterator iter = BrowserList::begin_last_active(); 171 BrowserList::const_reverse_iterator iter = BrowserList::begin_last_active();
577 BrowserList::const_reverse_iterator end = BrowserList::end_last_active(); 172 BrowserList::const_reverse_iterator end = BrowserList::end_last_active();
578 for (; (iter != end); ++iter) { 173 for (; (iter != end); ++iter) {
579 Browser* browser = *iter; 174 Browser* browser = *iter;
580 if (panel->browser() != browser && !browser->window()->IsMinimized()) 175 if (panel->browser() != browser && !browser->window()->IsMinimized())
581 return browser->window(); 176 return browser->window();
582 } 177 }
583 178
584 return NULL; 179 return NULL;
585 } 180 }
586 181
587 void PanelManager::MoveToPanelStrip(Panel* panel) {
588 // TODO(jennb) - implement.
589 }
590
591 void PanelManager::MoveToOverflowStrip(Panel* panel, bool is_new) { 182 void PanelManager::MoveToOverflowStrip(Panel* panel, bool is_new) {
592 // TODO(jianli) - implement. 183 // TODO(jianli) - implement.
593 } 184 }
594 185
595 void PanelManager::OnMouseMove(const gfx::Point& mouse_position) {
596 bool bring_up_titlebars = ShouldBringUpTitlebars(mouse_position.x(),
597 mouse_position.y());
598 BringUpOrDownTitlebars(bring_up_titlebars);
599 }
600
601 void PanelManager::OnAutoHidingDesktopBarThicknessChanged() { 186 void PanelManager::OnAutoHidingDesktopBarThicknessChanged() {
602 AdjustWorkAreaForAutoHidingDesktopBars(); 187 AdjustWorkAreaForAutoHidingDesktopBars();
603 Rearrange(panels_.begin(), StartingRightPosition()); 188 Layout();
604 } 189 }
605 190
606 void PanelManager::OnAutoHidingDesktopBarVisibilityChanged( 191 void PanelManager::OnAutoHidingDesktopBarVisibilityChanged(
607 AutoHidingDesktopBar::Alignment alignment, 192 AutoHidingDesktopBar::Alignment alignment,
608 AutoHidingDesktopBar::Visibility visibility) { 193 AutoHidingDesktopBar::Visibility visibility) {
609 if (delayed_titlebar_action_ == NO_ACTION) 194 panel_strip_->OnAutoHidingDesktopBarVisibilityChanged(alignment, visibility);
610 return;
611
612 AutoHidingDesktopBar::Visibility expected_visibility =
613 delayed_titlebar_action_ == BRING_UP ? AutoHidingDesktopBar::VISIBLE
614 : AutoHidingDesktopBar::HIDDEN;
615 if (visibility != expected_visibility)
616 return;
617
618 DoBringUpOrDownTitlebars(delayed_titlebar_action_ == BRING_UP);
619 delayed_titlebar_action_ = NO_ACTION;
620 }
621
622 void PanelManager::Rearrange(Panels::iterator iter_to_start,
623 int rightmost_position) {
624 for (Panels::iterator iter = iter_to_start; iter != panels_.end(); ++iter) {
625 Panel* panel = *iter;
626 gfx::Rect new_bounds(panel->GetBounds());
627 new_bounds.set_x(rightmost_position - new_bounds.width());
628 new_bounds.set_y(
629 GetBottomPositionForExpansionState(panel->expansion_state()) -
630 new_bounds.height());
631 if (new_bounds != panel->GetBounds())
632 panel->SetPanelBounds(new_bounds);
633
634 rightmost_position = new_bounds.x() - kPanelsHorizontalSpacing;
635 }
636 } 195 }
637 196
638 void PanelManager::RemoveAll() { 197 void PanelManager::RemoveAll() {
639 // This should not be called when we're in the process of dragging. 198 panel_strip_->RemoveAll();
640 DCHECK(dragging_panel_index_ == kInvalidPanelIndex); 199 // TODO(jianli): overflow_strip_->RemoveAll();
200 }
641 201
642 // Make a copy of the iterator as closing panels can modify the vector. 202 int PanelManager::num_panels() const {
643 Panels panels_copy = panels_; 203 return panel_strip_->num_panels();
644 204 // TODO(jianli): + overflow_strip_->num_panels();
645 // Start from the bottom to avoid reshuffling.
646 for (Panels::reverse_iterator iter = panels_copy.rbegin();
647 iter != panels_copy.rend(); ++iter)
648 (*iter)->Close();
649 } 205 }
650 206
651 bool PanelManager::is_dragging_panel() const { 207 bool PanelManager::is_dragging_panel() const {
652 return dragging_panel_index_ != kInvalidPanelIndex; 208 return panel_strip_->is_dragging_panel();
653 } 209 }
210
211 const PanelManager::Panels& PanelManager::panels() const {
212 return panel_strip_->panels();
213 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698