Chromium Code Reviews| Index: chrome/browser/ui/panels/panel_strip.cc |
| diff --git a/chrome/browser/ui/panels/panel_strip.cc b/chrome/browser/ui/panels/panel_strip.cc |
| index e62e34bb5383011e9bebd6f733f7be8853f810f3..b146a682982daf442c9ff59845ba4909de90c4ed 100644 |
| --- a/chrome/browser/ui/panels/panel_strip.cc |
| +++ b/chrome/browser/ui/panels/panel_strip.cc |
| @@ -27,6 +27,10 @@ const double kPanelDefaultWidthToHeightRatio = 1.62; // golden ratio |
| // Maxmium width of a panel is based on a factor of the entire panel strip. |
| const double kPanelMaxWidthFactor = 0.35; |
| +// New panels that cannot fit in the panel strip are moved to overflow |
| +// after a brief delay. |
| +const int kMoveNewPanelToOverflowDelayMilliseconds = 1500; // arbitrary |
| + |
| // Occasionally some system, like Windows, might not bring up or down the bottom |
| // bar when the mouse enters or leaves the bottom screen area. This is the |
| // maximum time we will wait for the bottom bar visibility change notification. |
| @@ -53,7 +57,8 @@ PanelStrip::PanelStrip(PanelManager* panel_manager) |
| dragging_panel_original_x_(0), |
| delayed_titlebar_action_(NO_ACTION), |
| remove_delays_for_testing_(false), |
| - titlebar_action_factory_(this) { |
| + titlebar_action_factory_(this), |
| + overflow_action_factory_(this) { |
| } |
| PanelStrip::~PanelStrip() { |
| @@ -62,12 +67,21 @@ PanelStrip::~PanelStrip() { |
| DCHECK_EQ(0, minimized_panel_count_); |
| } |
| -void PanelStrip::SetBounds(const gfx::Rect bounds) { |
| - if (strip_bounds_ == bounds) |
| +void PanelStrip::SetDisplayArea(const gfx::Rect area) { |
| + if (display_area_ == area) |
| return; |
| - strip_bounds_ = bounds; |
| - Rearrange(panels_.begin(), StartingRightPosition()); |
| + // Check for overflow. |
| + if (!panels_.empty() && area.width() < display_area_.width()) { |
|
jianli
2011/12/01 21:36:28
Probably better to set new area 1st so that all la
|
| + int min_x = display_area_.right() - area.width(); |
|
jianli
2011/12/01 21:36:28
display_area_.right() => area.right()
It might be
|
| + while (panels_.back()->GetBounds().x() < min_x) { |
| + MovePanelToOverflow(panels_.back(), false); |
| + DCHECK(!panels_.empty()); // At least one panel must fit! |
|
jianli
2011/12/01 21:36:28
This might not be always true if the display area
|
| + } |
| + } |
| + |
| + display_area_ = area; |
| + Rearrange(); |
| } |
| void PanelStrip::AddPanel(Panel* panel) { |
| @@ -113,8 +127,20 @@ void PanelStrip::AddNewPanel(Panel* panel) { |
| panel->set_restored_size(gfx::Size(width, height)); |
| // Layout the new panel. |
| - int y = strip_bounds_.bottom() - height; |
| + int y = display_area_.bottom() - height; |
| int x = GetRightMostAvailablePosition() - width; |
| + |
| + // Keep panel visible in the strip even if overlap would occur. |
| + // Panel is moved to overflow from the strip after a delay. |
| + if (x < display_area_.x()) { |
| + x = display_area_.x(); |
| + MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&PanelStrip::MovePanelToOverflow, |
| + overflow_action_factory_.GetWeakPtr(), |
| + base::Unretained(panel), true), // new panel |
|
jianli
2011/12/01 21:36:28
There could be a case that the new panel is being
jennb
2011/12/01 23:10:17
When the delayed method is called, it checks wheth
|
| + kMoveNewPanelToOverflowDelayMilliseconds); |
| + } |
| panel->Initialize(gfx::Rect(x, y, width, height)); |
| } |
| @@ -122,21 +148,25 @@ void PanelStrip::AddExistingPanel(Panel* panel) { |
| gfx::Size restored_size = panel->restored_size(); |
| int height = restored_size.height(); |
| int width = restored_size.width(); |
| - int x = GetRightMostAvailablePosition() - width; |
| - int y = strip_bounds_.bottom() - height; |
| + int x; |
| + while ((x = GetRightMostAvailablePosition() - width) < display_area_.x()) { |
| + DCHECK(!panels_.empty()); |
| + MovePanelToOverflow(panels_.back(), false); |
| + } |
| + int y = display_area_.bottom() - height; |
| panel->SetPanelBounds(gfx::Rect(x, y, width, height)); |
| } |
| int PanelStrip::GetMaxPanelWidth() const { |
| - return static_cast<int>(strip_bounds_.width() * kPanelMaxWidthFactor); |
| + return static_cast<int>(display_area_.width() * kPanelMaxWidthFactor); |
| } |
| int PanelStrip::GetMaxPanelHeight() const { |
| - return strip_bounds_.height(); |
| + return display_area_.height(); |
| } |
| int PanelStrip::StartingRightPosition() const { |
| - return strip_bounds_.right(); |
| + return display_area_.right(); |
| } |
| int PanelStrip::GetRightMostAvailablePosition() const { |
| @@ -155,6 +185,7 @@ bool PanelStrip::Remove(Panel* panel) { |
| } |
| DoRemove(panel); |
| + Rearrange(); |
| return true; |
| } |
| @@ -162,19 +193,25 @@ void PanelStrip::DelayedRemove() { |
| for (size_t i = 0; i < panels_pending_to_remove_.size(); ++i) |
| DoRemove(panels_pending_to_remove_[i]); |
| panels_pending_to_remove_.clear(); |
| + Rearrange(); |
| } |
| -void PanelStrip::DoRemove(Panel* panel) { |
| +bool PanelStrip::DoRemove(Panel* panel) { |
| Panels::iterator iter = find(panels_.begin(), panels_.end(), panel); |
| if (iter == panels_.end()) |
| - return; |
| + return false; |
| if (panel->expansion_state() != Panel::EXPANDED) |
| DecrementMinimizedPanels(); |
| - gfx::Rect bounds = (*iter)->GetBounds(); |
| - Rearrange(panels_.erase(iter), bounds.right()); |
| - panel_manager_->OnPanelRemoved(panel); |
| + panels_.erase(iter); |
| + |
| + content::NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_PANEL_REMOVED, |
| + content::Source<Panel>(panel), |
| + content::NotificationService::NoDetails()); |
| + |
| + return true; |
| } |
| void PanelStrip::StartDragging(Panel* panel) { |
| @@ -351,28 +388,6 @@ void PanelStrip::OnPreferredWindowSizeChanged( |
| if (new_width < panel->min_size().width()) |
| new_width = panel->min_size().width(); |
| - if (new_width != bounds.width()) { |
| - int delta = bounds.width() - new_width; |
| - bounds.set_x(bounds.x() + delta); |
| - bounds.set_width(new_width); |
| - |
| - // Reposition all the panels on the left. |
| - int panel_index = -1; |
| - for (int i = 0; i < static_cast<int>(panels_.size()); ++i) { |
| - if (panels_[i] == panel) { |
| - panel_index = i; |
| - break; |
| - } |
| - } |
| - DCHECK(panel_index >= 0); |
| - for (int i = static_cast<int>(panels_.size()) -1; i > panel_index; |
| - --i) { |
| - gfx::Rect this_bounds = panels_[i]->GetBounds(); |
| - this_bounds.set_x(this_bounds.x() + delta); |
| - panels_[i]->SetPanelBounds(this_bounds); |
| - } |
| - } |
| - |
| // The panel height: |
| // * cannot grow or shrink to go beyond [min_height, max_height] |
| int new_height = preferred_window_size.height(); |
| @@ -381,19 +396,58 @@ void PanelStrip::OnPreferredWindowSizeChanged( |
| if (new_height < panel->min_size().height()) |
| new_height = panel->min_size().height(); |
| + // Update restored size. |
| + gfx::Size new_size(new_width, new_height); |
| + if (new_size != panel->restored_size()) |
| + panel->set_restored_size(preferred_window_size); |
| + |
| // Only need to adjust bounds height when panel is expanded. |
| - gfx::Size restored_size = panel->restored_size(); |
| - if (new_height != restored_size.height() && |
| + if (new_height != bounds.height() && |
| panel->expansion_state() == Panel::EXPANDED) { |
| - bounds.set_y(bounds.y() - new_height + bounds.height()); |
| + bounds.set_y(bounds.bottom() - new_height); |
| bounds.set_height(new_height); |
| } |
| - gfx::Size new_size = gfx::Size(new_width, new_height); |
| - if (new_size != restored_size) |
| - panel->set_restored_size(new_size); |
| + // Adjust bounds width. |
| + int delta_x = bounds.width() - new_width; |
| + if (delta_x != 0) { |
| + bounds.set_width(new_width); |
| + bounds.set_x(bounds.x() + delta_x); |
| + |
| + // Reposition all the panels to the left. |
|
jianli
2011/12/01 21:36:28
I think this logic could be folded into Rearrange
|
| + int panel_index = -1; |
| + for (int i = 0; i < static_cast<int>(panels_.size()); ++i) { |
| + if (panels_[i] == panel) { |
| + panel_index = i; |
| + break; |
| + } |
| + } |
| + DCHECK(panel_index >= 0); |
| + for (int i = static_cast<int>(panels_.size()) - 1; i > panel_index; |
|
jianli
2011/12/01 21:36:28
extra space after for.
|
| + --i) { |
| + Panel* this_panel = panels_[i]; |
| + gfx::Rect this_bounds = this_panel->GetBounds(); |
| + int shifted_x = this_bounds.x() + delta_x; |
| + if (delta_x < 0 && shifted_x < display_area_.x()) { |
| + MovePanelToOverflow(this_panel, false); // safe to erase from end |
| + } else { |
| + this_bounds.set_x(shifted_x); |
| + this_panel->SetPanelBounds(this_bounds); |
| + } |
| + } |
| + |
| + // Finally, check if size change caused current panel to overflow. |
| + if (bounds.x() < display_area_.x()) { |
| + MovePanelToOverflow(panel, false); |
| + return; |
| + } |
| + } |
| panel->SetPanelBounds(bounds); |
| + |
| + // Try to add more panels to the strip if size decreased. |
| + if (delta_x > 0) |
| + AddPanelsFromOverflow(); |
| } |
| bool PanelStrip::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const { |
| @@ -403,7 +457,7 @@ bool PanelStrip::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const { |
| if (desktop_bar->IsEnabled(AutoHidingDesktopBar::ALIGN_BOTTOM) && |
| desktop_bar->GetVisibility(AutoHidingDesktopBar::ALIGN_BOTTOM) == |
| AutoHidingDesktopBar::VISIBLE && |
| - mouse_y >= strip_bounds_.bottom()) |
| + mouse_y >= display_area_.bottom()) |
| return true; |
| for (Panels::const_iterator iter = panels_.begin(); |
| @@ -511,7 +565,7 @@ void PanelStrip::DoBringUpOrDownTitlebars(bool bring_up) { |
| int PanelStrip::GetBottomPositionForExpansionState( |
| Panel::ExpansionState expansion_state) const { |
| - int bottom = strip_bounds_.bottom(); |
| + int bottom = display_area_.bottom(); |
| // If there is an auto-hiding desktop bar aligned to the bottom edge, we need |
| // to move the title-only panel above the auto-hiding desktop bar. |
| AutoHidingDesktopBar* desktop_bar = panel_manager_->auto_hiding_desktop_bar(); |
| @@ -545,19 +599,42 @@ void PanelStrip::OnAutoHidingDesktopBarVisibilityChanged( |
| delayed_titlebar_action_ = NO_ACTION; |
| } |
| -void PanelStrip::Rearrange(Panels::iterator iter_to_start, |
| - int rightmost_position) { |
| - for (Panels::iterator iter = iter_to_start; iter != panels_.end(); ++iter) { |
| +void PanelStrip::Rearrange() { |
| + int rightmost_position = StartingRightPosition(); |
| + for (Panels::iterator iter = panels_.begin(); iter != panels_.end(); ++iter) { |
| Panel* panel = *iter; |
| gfx::Rect new_bounds(panel->GetBounds()); |
| new_bounds.set_x(rightmost_position - new_bounds.width()); |
| new_bounds.set_y( |
| GetBottomPositionForExpansionState(panel->expansion_state()) - |
| new_bounds.height()); |
| + DCHECK(new_bounds.x() >= display_area_.x()); // Should not overflow. |
| panel->SetPanelBounds(new_bounds); |
| rightmost_position = new_bounds.x() - kPanelsHorizontalSpacing; |
| } |
| + |
| + AddPanelsFromOverflow(); // Maybe there's more room now... |
| +} |
| + |
| +void PanelStrip::MovePanelToOverflow(Panel* panel, bool is_new) { |
| + if (!DoRemove(panel)) |
| + return; |
| + |
| + // TODO(jianli): Replace with the real code using overflow strip. |
| + // panel_manager_->panel_overflow_strip()->AddPanel(panel, is_new); |
| +} |
| + |
| +void PanelStrip::AddPanelsFromOverflow() { |
| + // TODO(jianli): Replace with the real code using overflow strip. |
| + // PanelOverflowStrip* overflow = panel_manager_->panel_overflow_strip(); |
| + // Panel* candidate; |
| + // while (candidate = overflow->FirstPanel() && |
| + // GetRightMostAvailablePosition - |
| + // candidate->GetRestoredSize().width() >= display_area_.x()) { |
| + // overflow->Remove(candidate); |
| + // AddExistingPanel(candidate); |
| + // } |
| } |
| void PanelStrip::RemoveAll() { |