summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorjennb@chromium.org <jennb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-03 01:11:24 +0000
committerjennb@chromium.org <jennb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-03 01:11:24 +0000
commit21965e2a68ffb2d4107492e8f739e4391dbe7f38 (patch)
tree7054c0d00c48b333bae9d5e1ebe8f750b81cf244 /chrome/browser
parentfae1ecd61e45ced03f447a53674e4ba1cd9f77a0 (diff)
downloadchromium_src-21965e2a68ffb2d4107492e8f739e4391dbe7f38.zip
chromium_src-21965e2a68ffb2d4107492e8f739e4391dbe7f38.tar.gz
chromium_src-21965e2a68ffb2d4107492e8f739e4391dbe7f38.tar.bz2
Cleanup to keep panel from manipulating its panel strip assignment directly.
Only PanelManager adds/removes panels from panel strips. Only exception is in tests. BUG=None TEST=Existing tests. Review URL: http://codereview.chromium.org/9560002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124806 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/ui/panels/detached_panel_browsertest.cc23
-rw-r--r--chrome/browser/ui/panels/detached_panel_strip.cc15
-rw-r--r--chrome/browser/ui/panels/detached_panel_strip.h3
-rw-r--r--chrome/browser/ui/panels/docked_panel_strip.cc142
-rw-r--r--chrome/browser/ui/panels/docked_panel_strip.h17
-rw-r--r--chrome/browser/ui/panels/overflow_panel_strip.cc30
-rw-r--r--chrome/browser/ui/panels/overflow_panel_strip.h3
-rw-r--r--chrome/browser/ui/panels/panel.cc41
-rw-r--r--chrome/browser/ui/panels/panel.h5
-rw-r--r--chrome/browser/ui/panels/panel_manager.cc62
-rw-r--r--chrome/browser/ui/panels/panel_manager.h14
-rw-r--r--chrome/browser/ui/panels/panel_overflow_browsertest.cc4
-rw-r--r--chrome/browser/ui/panels/panel_strip.h5
13 files changed, 216 insertions, 148 deletions
diff --git a/chrome/browser/ui/panels/detached_panel_browsertest.cc b/chrome/browser/ui/panels/detached_panel_browsertest.cc
index b2b5e1b..24e22c1 100644
--- a/chrome/browser/ui/panels/detached_panel_browsertest.cc
+++ b/chrome/browser/ui/panels/detached_panel_browsertest.cc
@@ -12,8 +12,7 @@
class DetachedPanelBrowserTest : public BasePanelBrowserTest {
};
-IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
- DISABLED_CheckDetachedPanelProperties) {
+IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, CheckDetachedPanelProperties) {
PanelManager* panel_manager = PanelManager::GetInstance();
DetachedPanelStrip* detached_strip = panel_manager->detached_strip();
@@ -27,14 +26,13 @@ IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
// Move panels to detached strip.
EXPECT_EQ(2, panel_manager->num_panels());
EXPECT_EQ(0, detached_strip->num_panels());
- panel1->MoveToStrip(detached_strip);
- panel2->MoveToStrip(detached_strip);
+ panel_manager->MovePanelToStrip(panel1, PanelStrip::DETACHED);
+ panel_manager->MovePanelToStrip(panel2, PanelStrip::DETACHED);
EXPECT_EQ(2, panel_manager->num_panels());
EXPECT_EQ(2, detached_strip->num_panels());
- std::vector<Panel*> panels = panel_manager->panels();
- EXPECT_EQ(panel1, panels[0]);
- EXPECT_EQ(panel2, panels[1]);
+ EXPECT_TRUE(detached_strip->HasPanel(panel1));
+ EXPECT_TRUE(detached_strip->HasPanel(panel2));
EXPECT_TRUE(panel1->draggable());
EXPECT_TRUE(panel2->draggable());
@@ -44,11 +42,10 @@ IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest,
IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, DragDetachedPanel) {
PanelManager* panel_manager = PanelManager::GetInstance();
- DetachedPanelStrip* detached_strip = panel_manager->detached_strip();
// Create one detached panel.
Panel* panel = CreatePanelWithBounds("Panel1", gfx::Rect(0, 0, 250, 200));
- panel->MoveToStrip(detached_strip);
+ panel_manager->MovePanelToStrip(panel, PanelStrip::DETACHED);
// Test that the detached panel can be dragged anywhere.
scoped_ptr<NativePanelTesting> panel_testing(
@@ -101,10 +98,10 @@ IN_PROC_BROWSER_TEST_F(DetachedPanelBrowserTest, CloseDetachedPanelOnDrag) {
Panel* panel2 = CreatePanelWithBounds("Panel2", gfx::Rect(0, 0, 110, 110));
Panel* panel3 = CreatePanelWithBounds("Panel3", gfx::Rect(0, 0, 120, 120));
Panel* panel4 = CreatePanelWithBounds("Panel4", gfx::Rect(0, 0, 130, 130));
- panel1->MoveToStrip(detached_strip);
- panel2->MoveToStrip(detached_strip);
- panel3->MoveToStrip(detached_strip);
- panel4->MoveToStrip(detached_strip);
+ panel_manager->MovePanelToStrip(panel1, PanelStrip::DETACHED);
+ panel_manager->MovePanelToStrip(panel2, PanelStrip::DETACHED);
+ panel_manager->MovePanelToStrip(panel3, PanelStrip::DETACHED);
+ panel_manager->MovePanelToStrip(panel4, PanelStrip::DETACHED);
ASSERT_EQ(4, detached_strip->num_panels());
scoped_ptr<NativePanelTesting> panel1_testing(
diff --git a/chrome/browser/ui/panels/detached_panel_strip.cc b/chrome/browser/ui/panels/detached_panel_strip.cc
index c1c1a78..acc89a8 100644
--- a/chrome/browser/ui/panels/detached_panel_strip.cc
+++ b/chrome/browser/ui/panels/detached_panel_strip.cc
@@ -34,12 +34,15 @@ void DetachedPanelStrip::RefreshLayout() {
}
void DetachedPanelStrip::AddPanel(Panel* panel) {
- DCHECK_EQ(this, panel->panel_strip());
+ DCHECK_NE(this, panel->panel_strip());
+ panel->set_panel_strip(this);
panels_.insert(panel);
}
-bool DetachedPanelStrip::RemovePanel(Panel* panel) {
- return panels_.erase(panel) != 0;
+void DetachedPanelStrip::RemovePanel(Panel* panel) {
+ DCHECK_EQ(this, panel->panel_strip());
+ panel->set_panel_strip(NULL);
+ panels_.erase(panel);
}
void DetachedPanelStrip::CloseAll() {
@@ -77,6 +80,12 @@ void DetachedPanelStrip::RestorePanel(Panel* panel) {
NOTIMPLEMENTED();
}
+bool DetachedPanelStrip::IsPanelMinimized(const Panel* panel) const {
+ DCHECK_EQ(this, panel->panel_strip());
+ NOTIMPLEMENTED();
+ return false;
+}
+
bool DetachedPanelStrip::CanShowPanelAsActive(const Panel* panel) const {
// All detached panels can be shown as active.
return true;
diff --git a/chrome/browser/ui/panels/detached_panel_strip.h b/chrome/browser/ui/panels/detached_panel_strip.h
index 4ea0c4f..0beedf9 100644
--- a/chrome/browser/ui/panels/detached_panel_strip.h
+++ b/chrome/browser/ui/panels/detached_panel_strip.h
@@ -28,7 +28,7 @@ class DetachedPanelStrip : public PanelStrip {
virtual void SetDisplayArea(const gfx::Rect& display_area) OVERRIDE;
virtual void RefreshLayout() OVERRIDE;
virtual void AddPanel(Panel* panel) OVERRIDE;
- virtual bool RemovePanel(Panel* panel) OVERRIDE;
+ virtual void RemovePanel(Panel* panel) OVERRIDE;
virtual void CloseAll() OVERRIDE;
virtual void ResizePanelWindow(
Panel* panel,
@@ -37,6 +37,7 @@ class DetachedPanelStrip : public PanelStrip {
virtual void ActivatePanel(Panel* panel) OVERRIDE;
virtual void MinimizePanel(Panel* panel) OVERRIDE;
virtual void RestorePanel(Panel* panel) OVERRIDE;
+ virtual bool IsPanelMinimized(const Panel* panel) const OVERRIDE;
virtual bool CanShowPanelAsActive(const Panel* panel) const OVERRIDE;
virtual bool CanDragPanel(const Panel* panel) const OVERRIDE;
virtual void StartDraggingPanel(Panel* panel) OVERRIDE;
diff --git a/chrome/browser/ui/panels/docked_panel_strip.cc b/chrome/browser/ui/panels/docked_panel_strip.cc
index 4fa17f3..57a4bee 100644
--- a/chrome/browser/ui/panels/docked_panel_strip.cc
+++ b/chrome/browser/ui/panels/docked_panel_strip.cc
@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/panels/overflow_panel_strip.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
#include "chrome/common/chrome_notification_types.h"
@@ -59,7 +58,6 @@ DockedPanelStrip::DockedPanelStrip(PanelManager* panel_manager)
panel_manager_(panel_manager),
minimized_panel_count_(0),
are_titlebars_up_(false),
- disable_layout_refresh_(false),
delayed_titlebar_action_(NO_ACTION),
titlebar_action_factory_(this) {
dragging_panel_current_iterator_ = dragging_panel_original_iterator_ =
@@ -86,9 +84,10 @@ void DockedPanelStrip::SetDisplayArea(const gfx::Rect& display_area) {
}
void DockedPanelStrip::AddPanel(Panel* panel) {
- DCHECK_EQ(this, panel->panel_strip());
+ DCHECK_NE(this, panel->panel_strip());
+ panel->set_panel_strip(this);
- // Always update limits, even for exiting panels, in case the maximums changed
+ // Always update limits, even on existing panels, in case the limits changed
// while panel was out of the strip.
int max_panel_width = GetMaxPanelWidth();
int max_panel_height = GetMaxPanelHeight();
@@ -100,16 +99,7 @@ void DockedPanelStrip::AddPanel(Panel* panel) {
int width = restored_size.width();
if (panel->initialized()) {
- // Bump panels in the strip to make room for this panel.
- // Prevent layout refresh when panel is removed from this strip.
- disable_layout_refresh_ = true;
- PanelStrip* overflow_strip = panel_manager_->overflow_strip();
- int x;
- while ((x = GetRightMostAvailablePosition() - width) < display_area_.x()) {
- DCHECK(!panels_.empty());
- panels_.back()->MoveToStrip(overflow_strip);
- }
- disable_layout_refresh_ = false;
+ int x = FitPanelWithWidth(width);
Panel::ExpansionState expansion_state_to_restore;
if (panel->expansion_state() == Panel::EXPANDED) {
@@ -124,7 +114,6 @@ void DockedPanelStrip::AddPanel(Panel* panel) {
}
IncrementMinimizedPanels();
}
-
int y =
GetBottomPositionForExpansionState(expansion_state_to_restore) - height;
panel->SetPanelBounds(gfx::Rect(x, y, width, height));
@@ -203,45 +192,43 @@ int DockedPanelStrip::GetRightMostAvailablePosition() const {
(panels_.back()->GetBounds().x() - kPanelsHorizontalSpacing);
}
-bool DockedPanelStrip::RemovePanel(Panel* panel) {
- if (panel->has_temporary_layout()) {
- panels_in_temporary_layout_.erase(panel);
- return true;
- }
-
- Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
- if (iter == panels_.end())
- return false;
+void DockedPanelStrip::RemovePanel(Panel* panel) {
+ DCHECK_EQ(this, panel->panel_strip());
+ panel->set_panel_strip(NULL);
if (panel->expansion_state() != Panel::EXPANDED)
DecrementMinimizedPanels();
- // Removing an element from the list will invalidate the iterator that refers
- // to it. So we need to check if the dragging panel iterators are affected.
- bool update_original_dragging_iterator_after_erase = false;
- if (dragging_panel_original_iterator_ != panels_.end()) {
- if (dragging_panel_current_iterator_ == iter) {
- // If the dragging panel is being removed, set both dragging iterators to
- // the end of the list.
- dragging_panel_current_iterator_ = dragging_panel_original_iterator_ =
- panels_.end();
- } else if (dragging_panel_original_iterator_ == iter) {
- // If |dragging_panel_original_iterator_| refers to the element being
- // removed, set the flag so that the iterator can be updated to next
- // element.
- update_original_dragging_iterator_after_erase = true;
- }
+ if (panel->has_temporary_layout()) {
+ panels_in_temporary_layout_.erase(panel);
+ return;
}
- iter = panels_.erase(iter);
-
- if (update_original_dragging_iterator_after_erase)
- dragging_panel_original_iterator_ = iter;
-
- if (!disable_layout_refresh_)
+ // Removing an element from the list will invalidate the iterator that refers
+ // to it. We need to update the iterator in that case.
+ DCHECK(dragging_panel_current_iterator_ == panels_.end() ||
+ *dragging_panel_current_iterator_ != panel);
+ bool update_iterator_after_erase =
+ (dragging_panel_original_iterator_ != panels_.end() &&
+ *dragging_panel_original_iterator_ == panel);
+
+ // Optimize for the common case of removing the last panel.
+ DCHECK(!panels_.empty());
+ if (panels_.back() == panel) {
+ panels_.pop_back();
+ if (update_iterator_after_erase)
+ dragging_panel_original_iterator_ = panels_.end();
+ // No need to refresh layout as the remaining panels are unaffected.
+ // Just check if other panels can now fit in the freed up space.
+ panel_manager_->MovePanelsOutOfOverflowIfCanFit();
+ } else {
+ Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
+ DCHECK(iter != panels_.end());
+ iter = panels_.erase(iter);
+ if (update_iterator_after_erase)
+ dragging_panel_original_iterator_ = iter;
RefreshLayout();
-
- return true;
+ }
}
bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const {
@@ -443,6 +430,10 @@ void DockedPanelStrip::RestorePanel(Panel* panel) {
panel->SetExpansionState(Panel::EXPANDED);
}
+bool DockedPanelStrip::IsPanelMinimized(const Panel* panel) const {
+ return panel->expansion_state() != Panel::EXPANDED;
+}
+
void DockedPanelStrip::IncrementMinimizedPanels() {
minimized_panel_count_++;
if (minimized_panel_count_ == 1)
@@ -680,6 +671,29 @@ void DockedPanelStrip::OnFullScreenModeChanged(bool is_full_screen) {
}
}
+bool DockedPanelStrip::CanFitPanel(const Panel* panel) const {
+ int width = panel->GetRestoredBounds().width();
+ return GetRightMostAvailablePosition() - width >= display_area_.x();
+}
+
+int DockedPanelStrip::FitPanelWithWidth(int width) {
+ int x = GetRightMostAvailablePosition() - width;
+ if (x < display_area_.x()) {
+ // Insufficient space for the requested width. Bump panels to overflow.
+ Panel* last_panel_to_send_to_overflow;
+ for (Panels::reverse_iterator iter = panels_.rbegin();
+ iter != panels_.rend(); ++iter) {
+ last_panel_to_send_to_overflow = *iter;
+ x = last_panel_to_send_to_overflow->GetRestoredBounds().right() - width;
+ if (x >= display_area_.x()) {
+ panel_manager_->MovePanelsToOverflow(last_panel_to_send_to_overflow);
+ break;
+ }
+ }
+ }
+ return x;
+}
+
void DockedPanelStrip::RefreshLayout() {
int rightmost_position = StartingRightPosition();
@@ -706,40 +720,16 @@ void DockedPanelStrip::RefreshLayout() {
// Add/remove panels from/to overflow. A change in work area or the
// resize/removal of a panel may affect how many panels fit in the strip.
- OverflowPanelStrip* overflow_strip = panel_manager_->overflow_strip();
- if (panel_iter != panels_.end()) {
- // Prevent layout refresh when panel is removed from this strip.
- disable_layout_refresh_ = true;
-
- // Keep track of panels to move to overflow in a separate storage since
- // removing it from the list will invalidate the iterator.
- std::vector<Panel*> panels_to_move_to_overflow;
- for (; panel_iter != panels_.end(); ++panel_iter)
- panels_to_move_to_overflow.push_back(*panel_iter);
-
- // Move panels to overflow in reverse to maintain their order.
- for (std::vector<Panel*>::reverse_iterator iter =
- panels_to_move_to_overflow.rbegin();
- iter != panels_to_move_to_overflow.rend(); ++iter) {
- (*iter)->MoveToStrip(overflow_strip);
- }
-
- disable_layout_refresh_ = false;
- } else {
- // Attempt to add more panels from overflow to the strip.
- Panel* overflow_panel;
- while ((overflow_panel = overflow_strip->first_panel()) &&
- GetRightMostAvailablePosition() >=
- display_area_.x() + overflow_panel->restored_size().width()) {
- overflow_panel->MoveToStrip(this);
- }
- }
+ if (panel_iter != panels_.end())
+ panel_manager_->MovePanelsToOverflow(*panel_iter);
+ else
+ panel_manager_->MovePanelsOutOfOverflowIfCanFit();
}
void DockedPanelStrip::DelayedMovePanelToOverflow(Panel* panel) {
if (panels_in_temporary_layout_.erase(panel)) {
DCHECK(panel->has_temporary_layout());
- panel->MoveToStrip(panel_manager_->overflow_strip());
+ panel_manager_->MovePanelToStrip(panel, PanelStrip::IN_OVERFLOW);
}
}
diff --git a/chrome/browser/ui/panels/docked_panel_strip.h b/chrome/browser/ui/panels/docked_panel_strip.h
index 2fb0029..89cf565 100644
--- a/chrome/browser/ui/panels/docked_panel_strip.h
+++ b/chrome/browser/ui/panels/docked_panel_strip.h
@@ -43,7 +43,7 @@ class DockedPanelStrip : public PanelStrip,
// Adds a panel to the strip. The panel may be a newly created panel or one
// that is transitioning from another grouping of panels.
virtual void AddPanel(Panel* panel) OVERRIDE;
- virtual bool RemovePanel(Panel* panel) OVERRIDE;
+ virtual void RemovePanel(Panel* panel) OVERRIDE;
virtual void CloseAll() OVERRIDE;
virtual void ResizePanelWindow(
Panel* panel,
@@ -52,6 +52,7 @@ class DockedPanelStrip : public PanelStrip,
virtual void ActivatePanel(Panel* panel) OVERRIDE;
virtual void MinimizePanel(Panel* panel) OVERRIDE;
virtual void RestorePanel(Panel* panel) OVERRIDE;
+ virtual bool IsPanelMinimized(const Panel* panel) const OVERRIDE;
virtual bool CanShowPanelAsActive(const Panel* panel) const OVERRIDE;
virtual bool CanDragPanel(const Panel* panel) const OVERRIDE;
virtual void StartDraggingPanel(Panel* panel) OVERRIDE;
@@ -78,6 +79,7 @@ class DockedPanelStrip : public PanelStrip,
// do NOT have a temporary layout.
int num_panels() const { return panels_.size(); }
const Panels& panels() const { return panels_; }
+ Panel* last_panel() const { return panels_.empty() ? NULL : panels_.back(); }
gfx::Rect display_area() const { return display_area_; }
@@ -91,6 +93,9 @@ class DockedPanelStrip : public PanelStrip,
void OnFullScreenModeChanged(bool is_full_screen);
+ // Returns |true| if panel can fit in the dock strip.
+ bool CanFitPanel(const Panel* panel) const;
+
#ifdef UNIT_TEST
int num_temporary_layout_panels() const {
return panels_in_temporary_layout_.size();
@@ -123,6 +128,12 @@ class DockedPanelStrip : public PanelStrip,
int GetRightMostAvailablePosition() const;
+ // Determines position in strip where a panel of |width| will fit.
+ // Other panels in the strip may be moved to overflow to make room.
+ // Returns x position where a panel of |width| wide can fit.
+ // |width| is in screen coordinates.
+ int FitPanelWithWidth(int width);
+
// Called by AddPanel() after a delay to move a newly created panel from
// the panel strip to overflow because the panel could not fit
// within the bounds of the panel strip. New panels are first displayed
@@ -146,10 +157,6 @@ class DockedPanelStrip : public PanelStrip,
int minimized_panel_count_;
bool are_titlebars_up_;
- // |True| to temporarily prevent refreshing panel layout, e.g. while
- // moving panels to overflow area to make room for a panel in this strip.
- bool disable_layout_refresh_;
-
// Referring to current position in |panels_| where the dragging panel
// resides.
Panels::iterator dragging_panel_current_iterator_;
diff --git a/chrome/browser/ui/panels/overflow_panel_strip.cc b/chrome/browser/ui/panels/overflow_panel_strip.cc
index 2eeeb90..ce4505b 100644
--- a/chrome/browser/ui/panels/overflow_panel_strip.cc
+++ b/chrome/browser/ui/panels/overflow_panel_strip.cc
@@ -5,7 +5,6 @@
#include "chrome/browser/ui/panels/overflow_panel_strip.h"
#include "base/logging.h"
-#include "chrome/browser/ui/panels/docked_panel_strip.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
#include "chrome/browser/ui/panels/panel_overflow_indicator.h"
@@ -82,7 +81,9 @@ void OverflowPanelStrip::UpdateCurrentWidth() {
void OverflowPanelStrip::AddPanel(Panel* panel) {
// TODO(jianli): consider using other container to improve the perf for
// inserting to the front. http://crbug.com/106222
- DCHECK_EQ(this, panel->panel_strip());
+ DCHECK_NE(this, panel->panel_strip());
+ panel->set_panel_strip(this);
+
// Newly created panels that were temporarily in the panel strip
// are added to the back of the overflow, whereas panels that are
// bumped from the panel strip by other panels go to the front
@@ -115,14 +116,16 @@ void OverflowPanelStrip::AddPanel(Panel* panel) {
}
}
-bool OverflowPanelStrip::RemovePanel(Panel* panel) {
+void OverflowPanelStrip::RemovePanel(Panel* panel) {
+ DCHECK_EQ(this, panel->panel_strip());
+ panel->set_panel_strip(NULL);
+
size_t index = 0;
Panels::iterator iter = panels_.begin();
for (; iter != panels_.end(); ++iter, ++index)
if (*iter == panel)
break;
- if (iter == panels_.end())
- return false;
+ DCHECK(iter != panels_.end());
panels_.erase(iter);
DoRefresh(index, panels_.size() - 1);
@@ -136,8 +139,6 @@ bool OverflowPanelStrip::RemovePanel(Panel* panel) {
overflow_indicator_.reset();
else
UpdateOverflowIndicatorCount();
-
- return true;
}
void OverflowPanelStrip::CloseAll() {
@@ -164,9 +165,8 @@ void OverflowPanelStrip::OnPanelAttentionStateChanged(Panel* panel) {
void OverflowPanelStrip::ActivatePanel(Panel* panel) {
DCHECK_EQ(this, panel->panel_strip());
// Activating an overflow panel moves it to the docked panel strip.
- PanelStrip* docked_strip = panel_manager_->docked_strip();
- panel->MoveToStrip(docked_strip);
- docked_strip->ActivatePanel(panel);
+ panel_manager_->MovePanelToStrip(panel, PanelStrip::DOCKED);
+ panel->panel_strip()->ActivatePanel(panel);
}
void OverflowPanelStrip::MinimizePanel(Panel* panel) {
@@ -176,9 +176,13 @@ void OverflowPanelStrip::MinimizePanel(Panel* panel) {
void OverflowPanelStrip::RestorePanel(Panel* panel) {
DCHECK_EQ(this, panel->panel_strip());
- PanelStrip* docked_strip = panel_manager_->docked_strip();
- panel->MoveToStrip(docked_strip);
- docked_strip->RestorePanel(panel);
+ panel_manager_->MovePanelToStrip(panel, PanelStrip::DOCKED);
+ panel->panel_strip()->RestorePanel(panel);
+}
+
+bool OverflowPanelStrip::IsPanelMinimized(const Panel* panel) const {
+ // All overflow panels are considered minimized.
+ return true;
}
bool OverflowPanelStrip::CanShowPanelAsActive(const Panel* panel) const {
diff --git a/chrome/browser/ui/panels/overflow_panel_strip.h b/chrome/browser/ui/panels/overflow_panel_strip.h
index 3ffcf5a..511b8c2 100644
--- a/chrome/browser/ui/panels/overflow_panel_strip.h
+++ b/chrome/browser/ui/panels/overflow_panel_strip.h
@@ -33,7 +33,7 @@ class OverflowPanelStrip : public PanelStrip,
virtual void SetDisplayArea(const gfx::Rect& display_area) OVERRIDE;
virtual void RefreshLayout() OVERRIDE;
virtual void AddPanel(Panel* panel) OVERRIDE;
- virtual bool RemovePanel(Panel* panel) OVERRIDE;
+ virtual void RemovePanel(Panel* panel) OVERRIDE;
virtual void CloseAll() OVERRIDE;
virtual void ResizePanelWindow(
Panel* panel,
@@ -42,6 +42,7 @@ class OverflowPanelStrip : public PanelStrip,
virtual void ActivatePanel(Panel* panel) OVERRIDE;
virtual void MinimizePanel(Panel* panel) OVERRIDE;
virtual void RestorePanel(Panel* panel) OVERRIDE;
+ virtual bool IsPanelMinimized(const Panel* panel) const OVERRIDE;
virtual bool CanShowPanelAsActive(const Panel* panel) const OVERRIDE;
virtual bool CanDragPanel(const Panel* panel) const OVERRIDE;
virtual void StartDraggingPanel(Panel* panel) OVERRIDE;
diff --git a/chrome/browser/ui/panels/panel.cc b/chrome/browser/ui/panels/panel.cc
index 42917ce..a2e60a3 100644
--- a/chrome/browser/ui/panels/panel.cc
+++ b/chrome/browser/ui/panels/panel.cc
@@ -68,8 +68,8 @@ void Panel::Initialize(const gfx::Rect& bounds) {
void Panel::OnNativePanelClosed() {
if (auto_resizable_)
native_panel_->GetPanelBrowser()->tabstrip_model()->RemoveObserver(this);
- panel_strip_->RemovePanel(this);
manager()->OnPanelClosed(this);
+ DCHECK(!panel_strip_);
}
PanelManager* Panel::manager() const {
@@ -77,7 +77,7 @@ PanelManager* Panel::manager() const {
}
bool Panel::draggable() const {
- return panel_strip()->CanDragPanel(this);
+ return panel_strip_ && panel_strip_->CanDragPanel(this);
}
const Extension* Panel::GetExtension() const {
@@ -89,7 +89,7 @@ const Extension* Panel::GetExtension() const {
// being resized vs a change in current display bounds, e.g. from overflow
// size change. Change this when refactoring panel resize logic.
void Panel::SetPanelBounds(const gfx::Rect& bounds) {
- if (panel_strip_->type() == PanelStrip::DOCKED &&
+ if (panel_strip_ && panel_strip_->type() == PanelStrip::DOCKED &&
expansion_state_ == Panel::EXPANDED)
restored_size_ = bounds.size();
@@ -102,7 +102,7 @@ void Panel::SetPanelBounds(const gfx::Rect& bounds) {
}
void Panel::SetPanelBoundsInstantly(const gfx::Rect& bounds) {
- if (panel_strip_->type() == PanelStrip::DOCKED &&
+ if (panel_strip_ && panel_strip_->type() == PanelStrip::DOCKED &&
expansion_state_ == Panel::EXPANDED)
restored_size_ = bounds.size();
@@ -156,20 +156,6 @@ void Panel::SetAppIconVisibility(bool visible) {
native_panel_->SetPanelAppIconVisibility(visible);
}
-void Panel::MoveToStrip(PanelStrip* new_strip) {
- DCHECK_NE(panel_strip_, new_strip);
- if (panel_strip_)
- panel_strip_->RemovePanel(this);
-
- panel_strip_ = new_strip;
- panel_strip_->AddPanel(this);
-
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_PANEL_CHANGED_LAYOUT_MODE,
- content::Source<Panel>(this),
- content::NotificationService::NoDetails());
-}
-
void Panel::SetExpansionState(ExpansionState new_state) {
if (expansion_state_ == new_state)
return;
@@ -197,7 +183,7 @@ void Panel::FullScreenModeChanged(bool is_full_screen) {
}
void Panel::Show() {
- if (manager()->is_full_screen())
+ if (manager()->is_full_screen() || !panel_strip_)
return;
if (panel_strip_->CanShowPanelAsActive(this))
@@ -207,7 +193,7 @@ void Panel::Show() {
}
void Panel::ShowInactive() {
- if (manager()->is_full_screen())
+ if (manager()->is_full_screen() || !panel_strip_)
return;
native_panel_->ShowPanelInactive();
@@ -225,6 +211,9 @@ void Panel::Close() {
}
void Panel::Activate() {
+ if (!panel_strip_)
+ return;
+
panel_strip_->ActivatePanel(this);
native_panel_->ActivatePanel();
}
@@ -238,7 +227,7 @@ bool Panel::IsActive() const {
}
void Panel::FlashFrame(bool flash) {
- if (IsDrawingAttention() == flash)
+ if (IsDrawingAttention() == flash || !panel_strip_)
return;
// Don't draw attention for an active panel.
@@ -323,9 +312,7 @@ bool Panel::IsMaximized() const {
}
bool Panel::IsMinimized() const {
- PanelStrip::Type strip_type = panel_strip_->type();
- return strip_type == PanelStrip::IN_OVERFLOW ||
- (strip_type == PanelStrip::DOCKED && expansion_state_ != EXPANDED);
+ return !panel_strip_ || panel_strip()->IsPanelMinimized(this);
}
void Panel::Maximize() {
@@ -333,11 +320,13 @@ void Panel::Maximize() {
}
void Panel::Minimize() {
- panel_strip_->MinimizePanel(this);
+ if (panel_strip_)
+ panel_strip_->MinimizePanel(this);
}
void Panel::Restore() {
- panel_strip_->RestorePanel(this);
+ if (panel_strip_)
+ panel_strip_->RestorePanel(this);
}
void Panel::EnterFullscreen(
diff --git a/chrome/browser/ui/panels/panel.h b/chrome/browser/ui/panels/panel.h
index 96a5be9..495f05c 100644
--- a/chrome/browser/ui/panels/panel.h
+++ b/chrome/browser/ui/panels/panel.h
@@ -221,9 +221,8 @@ class Panel : public BrowserWindow,
// May be NULL if panel is newly created and has not been positioned yet.
PanelStrip* panel_strip() const { return panel_strip_; }
- // Moves the panel to the |new_strip|, removing the panel from its
- // current strip.
- void MoveToStrip(PanelStrip* new_strip);
+ // Sets the current panel strip that contains this panel.
+ void set_panel_strip(PanelStrip* new_strip) { panel_strip_ = new_strip; }
ExpansionState expansion_state() const { return expansion_state_; }
ExpansionState old_expansion_state() const { return old_expansion_state_; }
diff --git a/chrome/browser/ui/panels/panel_manager.cc b/chrome/browser/ui/panels/panel_manager.cc
index bb8323a..22195b6 100644
--- a/chrome/browser/ui/panels/panel_manager.cc
+++ b/chrome/browser/ui/panels/panel_manager.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/ui/panels/panel_manager.h"
+#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -64,7 +65,8 @@ bool PanelManager::ShouldUsePanels(const std::string& extension_id) {
PanelManager::PanelManager()
: panel_mouse_watcher_(PanelMouseWatcher::Create()),
auto_sizing_enabled_(true),
- is_full_screen_(false) {
+ is_full_screen_(false),
+ is_processing_overflow_(false) {
detached_strip_.reset(new DetachedPanelStrip(this));
docked_strip_.reset(new DockedPanelStrip(this));
overflow_strip_.reset(new OverflowPanelStrip(this));
@@ -117,7 +119,7 @@ Panel* PanelManager::CreatePanel(Browser* browser) {
int width = browser->override_bounds().width();
int height = browser->override_bounds().height();
Panel* panel = new Panel(browser, gfx::Size(width, height));
- panel->MoveToStrip(docked_strip_.get());
+ docked_strip_->AddPanel(panel);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PANEL_ADDED,
@@ -147,10 +149,11 @@ void PanelManager::CheckFullScreenMode() {
}
void PanelManager::OnPanelClosed(Panel* panel) {
- if (num_panels() == 0)
+ if (num_panels() == 1)
full_screen_mode_timer_.Stop();
drag_controller_->OnPanelClosed(panel);
+ panel->panel_strip()->RemovePanel(panel);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PANEL_CLOSED,
@@ -185,6 +188,59 @@ void PanelManager::ResizePanel(Panel* panel, const gfx::Size& new_size) {
panel->SetAutoResizable(false);
}
+void PanelManager::MovePanelToStrip(Panel* panel,
+ PanelStrip::Type new_layout) {
+ DCHECK(panel);
+ PanelStrip* current_strip = panel->panel_strip();
+ DCHECK(current_strip);
+ DCHECK_NE(current_strip->type(), new_layout);
+ current_strip->RemovePanel(panel);
+
+ PanelStrip* target_strip = NULL;
+ switch (new_layout) {
+ case PanelStrip::DETACHED:
+ target_strip = detached_strip_.get();
+ break;
+ case PanelStrip::DOCKED:
+ target_strip = docked_strip_.get();
+ break;
+ case PanelStrip::IN_OVERFLOW:
+ target_strip = overflow_strip_.get();
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ target_strip->AddPanel(panel);
+
+ content::NotificationService::current()->Notify(
+ chrome::NOTIFICATION_PANEL_CHANGED_LAYOUT_MODE,
+ content::Source<Panel>(panel),
+ content::NotificationService::NoDetails());
+}
+
+void PanelManager::MovePanelsToOverflow(Panel* last_panel_to_move) {
+ AutoReset<bool> processing_overflow(&is_processing_overflow_, true);
+ // Move panels to overflow in reverse to maintain their order.
+ Panel* bumped_panel;
+ while ((bumped_panel = docked_strip_->last_panel())) {
+ MovePanelToStrip(bumped_panel, PanelStrip::IN_OVERFLOW);
+ if (bumped_panel == last_panel_to_move)
+ break;
+ }
+ DCHECK(!docked_strip_->panels().empty());
+}
+
+void PanelManager::MovePanelsOutOfOverflowIfCanFit() {
+ if (is_processing_overflow_)
+ return;
+
+ Panel* overflow_panel;
+ while ((overflow_panel = overflow_strip_->first_panel()) &&
+ docked_strip_->CanFitPanel(overflow_panel))
+ MovePanelToStrip(overflow_panel, PanelStrip::DOCKED);
+}
+
bool PanelManager::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const {
return docked_strip_->ShouldBringUpTitlebars(mouse_x, mouse_y);
}
diff --git a/chrome/browser/ui/panels/panel_manager.h b/chrome/browser/ui/panels/panel_manager.h
index 73202a6..3194cf8 100644
--- a/chrome/browser/ui/panels/panel_manager.h
+++ b/chrome/browser/ui/panels/panel_manager.h
@@ -13,6 +13,7 @@
#include "base/timer.h"
#include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h"
#include "chrome/browser/ui/panels/panel.h"
+#include "chrome/browser/ui/panels/panel_strip.h"
#include "ui/gfx/rect.h"
class Browser;
@@ -61,6 +62,15 @@ class PanelManager : public AutoHidingDesktopBar::Observer {
// for panels that are auto-sized.
void ResizePanel(Panel* panel, const gfx::Size& new_size);
+ // Moves the |panel| to a different type of panel strip.
+ void MovePanelToStrip(Panel* panel, PanelStrip::Type new_layout);
+
+ // Move all panels up to, and including, the |last_panel_to_move| to overflow.
+ void MovePanelsToOverflow(Panel* last_panel_to_move);
+
+ // Moves as many panels out of overflow as space allows.
+ void MovePanelsOutOfOverflowIfCanFit();
+
// Returns true if we should bring up the titlebars, given the current mouse
// point.
bool ShouldBringUpTitlebars(int mouse_x, int mouse_y) const;
@@ -211,6 +221,10 @@ class PanelManager : public AutoHidingDesktopBar::Observer {
// True if current active app is in full screen mode.
bool is_full_screen_;
+ // True only while moving panels to overflow. Used to prevent moving panels
+ // out of overflow while in the process of moving panels to overflow.
+ bool is_processing_overflow_;
+
DISALLOW_COPY_AND_ASSIGN(PanelManager);
};
diff --git a/chrome/browser/ui/panels/panel_overflow_browsertest.cc b/chrome/browser/ui/panels/panel_overflow_browsertest.cc
index e5b9961..14699bd 100644
--- a/chrome/browser/ui/panels/panel_overflow_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_overflow_browsertest.cc
@@ -254,9 +254,9 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, UpdateDraggableStatus) {
PanelManager* panel_manager = PanelManager::GetInstance();
Panel* panel = CreatePanel("panel");
EXPECT_TRUE(panel->draggable());
- panel->MoveToStrip(panel_manager->overflow_strip());
+ panel_manager->MovePanelToStrip(panel, PanelStrip::IN_OVERFLOW);
EXPECT_FALSE(panel->draggable());
- panel->MoveToStrip(panel_manager->docked_strip());
+ panel_manager->MovePanelToStrip(panel, PanelStrip::DOCKED);
EXPECT_TRUE(panel->draggable());
panel->Close();
}
diff --git a/chrome/browser/ui/panels/panel_strip.h b/chrome/browser/ui/panels/panel_strip.h
index 7b0bced..c1da8f4 100644
--- a/chrome/browser/ui/panels/panel_strip.h
+++ b/chrome/browser/ui/panels/panel_strip.h
@@ -36,8 +36,7 @@ class PanelStrip {
// Removes |panel| from the collection of panels. Invoked asynchronously
// after a panel has been closed.
- // Returns |false| if the panel is not in the strip.
- virtual bool RemovePanel(Panel* panel) = 0;
+ virtual void RemovePanel(Panel* panel) = 0;
// Closes all panels in the collection. Panels will be removed after closing.
virtual void CloseAll() = 0;
@@ -62,6 +61,8 @@ class PanelStrip {
virtual void MinimizePanel(Panel* panel) = 0;
virtual void RestorePanel(Panel* panel) = 0;
+ virtual bool IsPanelMinimized(const Panel* panel) const = 0;
+
// Returns true if |panel| can be shown as active.
virtual bool CanShowPanelAsActive(const Panel* panel) const = 0;