Commit a5294d6a authored by jennb@chromium.org's avatar jennb@chromium.org

Add panel overflow logic to panel strip.

* Renamed strip_bounds_ to display_area_ to avoid confusion
thinking it was a flag to remove info.

Overflow not functional until jianli uncomments the overflow
strip code after he implements an overflow strip.

BUG=None
TEST=Disabled PanelBrowserTest.CreatePanelOnOverflow. jianli will fix.

Review URL: http://codereview.chromium.org/8774013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112572 0039d316-1c4b-4281-b951-d872f2087c98
parent 33047f18
......@@ -533,7 +533,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, FindBar) {
panel->Close();
}
IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CreatePanelOnOverflow) {
IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DISABLED_CreatePanelOnOverflow) {
TestCreatePanelOnOverflow();
}
......
......@@ -76,7 +76,7 @@ void PanelManager::Layout() {
panel_strip_bounds.set_width(adjusted_work_area_.width() -
kPanelStripLeftMargin - kPanelStripRightMargin);
panel_strip_bounds.set_height(height);
panel_strip_->SetBounds(panel_strip_bounds);
panel_strip_->SetDisplayArea(panel_strip_bounds);
}
Panel* PanelManager::CreatePanel(Browser* browser) {
......
......@@ -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,20 @@ 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& new_area) {
if (display_area_ == new_area)
return;
strip_bounds_ = bounds;
Rearrange(panels_.begin(), StartingRightPosition());
gfx::Rect old_area = display_area_;
display_area_ = new_area;
if (panels_.empty() || new_area.width() == old_area.width())
return;
if (new_area.width() < old_area.width())
Rearrange();
else
MovePanelsFromOverflowIfNeeded();
}
void PanelStrip::AddPanel(Panel* panel) {
......@@ -113,8 +126,21 @@ 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(),
panel,
true), // new panel
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,19 @@ 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);
return true;
}
void PanelStrip::StartDragging(Panel* panel) {
......@@ -351,28 +382,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 +390,30 @@ 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);
}
panel->SetPanelBounds(bounds);
// Only need to rearrange if panel's width changed.
if (delta_x != 0)
Rearrange();
}
bool PanelStrip::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const {
......@@ -403,7 +423,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 +531,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,11 +565,20 @@ 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) {
Panel* panel = *iter;
void PanelStrip::Rearrange() {
int rightmost_position = StartingRightPosition();
size_t panel_index = 0;
for (; panel_index < panels_.size(); ++panel_index) {
Panel* panel = panels_[panel_index];
gfx::Rect new_bounds(panel->GetBounds());
int x = rightmost_position - new_bounds.width();
if (x < display_area_.x()) {
MovePanelsToOverflow(panel_index);
break;
}
new_bounds.set_x(rightmost_position - new_bounds.width());
new_bounds.set_y(
GetBottomPositionForExpansionState(panel->expansion_state()) -
......@@ -558,6 +587,36 @@ void PanelStrip::Rearrange(Panels::iterator iter_to_start,
rightmost_position = new_bounds.x() - kPanelsHorizontalSpacing;
}
if (panel_index == panels_.size())
MovePanelsFromOverflowIfNeeded();
}
void PanelStrip::MovePanelsToOverflow(size_t overflow_point) {
DCHECK(overflow_point >= 0);
// Move panels in reverse to maintain their order.
for (size_t i = panels_.size() - 1; i >= overflow_point; --i)
MovePanelToOverflow(panels_[i], false);
}
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::MovePanelsFromOverflowIfNeeded() {
// 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);
// AddPanel(candidate);
// }
}
void PanelStrip::RemoveAll() {
......
......@@ -30,7 +30,7 @@ class PanelStrip : public PanelMouseWatcherObserver {
// Sets the bounds of the panel strip.
// |bounds| is in screen coordinates.
void SetBounds(const gfx::Rect bounds);
void SetDisplayArea(const gfx::Rect& area);
// Adds a panel to the strip. The panel may be a newly created panel or one
// that is transitioning from another grouping of panels.
......@@ -112,13 +112,16 @@ class PanelStrip : public PanelMouseWatcherObserver {
// Handles all the panels that're delayed to be removed.
void DelayedRemove();
// Does the remove. Called from Remove and DelayedRemove.
void DoRemove(Panel* panel);
// Does the actual remove. Caller is responsible for rearranging
// the panel strip if necessary.
// Returns |false| if panel is not in the strip.
bool DoRemove(Panel* panel);
// Rearranges the positions of the panels starting from the given iterator.
// Rearranges the positions of the panels in the strip.
// Handles moving panels to/from overflow area as needed.
// This is called when the display space has been changed, i.e. working
// area being changed or a panel being closed.
void Rearrange(Panels::iterator iter_to_start, int rightmost_position);
void Rearrange();
// Help functions to drag the given panel.
void DragLeft();
......@@ -132,10 +135,24 @@ class PanelStrip : public PanelMouseWatcherObserver {
int GetRightMostAvailablePosition() const;
// Moves the panel from the panel strip to the overflow area because
// the panel will not fit within the bounds of the panel strip.
// Overflow may occur when new panels are added, the bounds of the strip
// changes, a panel's size grows, a panel is moved from overflow into
// the strip, etc.
void MovePanelToOverflow(Panel* panel, bool is_new);
// Moves panels to the overflow area, starting from the last panel.
// |overflow_point| is the index of the first panel to oveflow.
void MovePanelsToOverflow(size_t overflow_point);
// Adds zero or more panels from overflow as will fit in the panel strip.
void MovePanelsFromOverflowIfNeeded();
PanelManager* panel_manager_; // Weak, owns us.
// All panels in the panel strip must fit within this area.
gfx::Rect strip_bounds_;
gfx::Rect display_area_;
Panels panels_;
......@@ -165,6 +182,9 @@ class PanelStrip : public PanelMouseWatcherObserver {
// Owned by MessageLoop after posting.
base::WeakPtrFactory<PanelStrip> titlebar_action_factory_;
// Factory used for moving new panels to overflow after a delay.
base::WeakPtrFactory<PanelStrip> overflow_action_factory_;
static const int kPanelsHorizontalSpacing = 4;
// Absolute minimum width and height for panels, including non-client area.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment