Commit 21965e2a authored by jennb@chromium.org's avatar jennb@chromium.org

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
parent fae1ecd6
......@@ -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(
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);
}
}
......
......@@ -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_;
......
......@@ -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 {
......
......@@ -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;
......
......@@ -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(
......
......@@ -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_; }
......
......@@ -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);
}
......
......@@ -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);
};
......
......@@ -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();
}
......
......@@ -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;
......
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