summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-03 00:54:56 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-03 00:54:56 +0000
commit5b7cb5670cb2a1f9154c39e0dea8a104b2293aa8 (patch)
treeecf3da721e02e1fbcbc438ae8782f27f242de139 /chrome/browser
parent8fe148521b21b213f9d32612bcebe515c47863f7 (diff)
downloadchromium_src-5b7cb5670cb2a1f9154c39e0dea8a104b2293aa8.zip
chromium_src-5b7cb5670cb2a1f9154c39e0dea8a104b2293aa8.tar.gz
chromium_src-5b7cb5670cb2a1f9154c39e0dea8a104b2293aa8.tar.bz2
Add PanelOverflowStrip to handle panel overflow.
BUG=none TEST=overflow test Review URL: http://codereview.chromium.org/8776035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112833 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/ui/panels/panel.cc55
-rw-r--r--chrome/browser/ui/panels/panel.h12
-rw-r--r--chrome/browser/ui/panels/panel_browser_frame_view.cc2
-rw-r--r--chrome/browser/ui/panels/panel_browser_frame_view.h2
-rw-r--r--chrome/browser/ui/panels/panel_browser_view.cc56
-rw-r--r--chrome/browser/ui/panels/panel_browser_view.h2
-rw-r--r--chrome/browser/ui/panels/panel_browser_view_browsertest.cc2
-rw-r--r--chrome/browser/ui/panels/panel_browsertest.cc41
-rw-r--r--chrome/browser/ui/panels/panel_manager.cc31
-rw-r--r--chrome/browser/ui/panels/panel_manager.h20
-rw-r--r--chrome/browser/ui/panels/panel_overflow_strip.cc220
-rw-r--r--chrome/browser/ui/panels/panel_overflow_strip.h101
-rw-r--r--chrome/browser/ui/panels/panel_strip.cc68
-rw-r--r--chrome/browser/ui/panels/panel_strip.h15
14 files changed, 520 insertions, 107 deletions
diff --git a/chrome/browser/ui/panels/panel.cc b/chrome/browser/ui/panels/panel.cc
index 401b71b..4667065 100644
--- a/chrome/browser/ui/panels/panel.cc
+++ b/chrome/browser/ui/panels/panel.cc
@@ -12,6 +12,8 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/panels/native_panel.h"
#include "chrome/browser/ui/panels/panel_manager.h"
+#include "chrome/browser/ui/panels/panel_overflow_strip.h"
+#include "chrome/browser/ui/panels/panel_strip.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/browser/web_applications/web_app.h"
@@ -121,34 +123,10 @@ void Panel::SetSizeRange(const gfx::Size& min_size, const gfx::Size& max_size) {
void Panel::SetExpansionState(ExpansionState new_state) {
if (expansion_state_ == new_state)
return;
-
ExpansionState old_state = expansion_state_;
expansion_state_ = new_state;
- int height;
- switch (expansion_state_) {
- case EXPANDED:
- height = restored_size_.height();
- break;
- case TITLE_ONLY:
- height = native_panel_->TitleOnlyHeight();
- break;
- case MINIMIZED:
- height = kMinimizedPanelHeight;
- break;
- default:
- NOTREACHED();
- height = restored_size_.height();
- break;
- }
-
- int bottom = manager()->GetBottomPositionForExpansionState(expansion_state_);
- gfx::Rect bounds = native_panel_->GetPanelBounds();
- bounds.set_y(bottom - height);
- bounds.set_height(height);
- SetPanelBounds(bounds);
-
- manager()->OnPanelExpansionStateChanged(old_state, new_state);
+ manager()->OnPanelExpansionStateChanged(this, old_state);
// The minimized panel should not get the focus.
if (expansion_state_ == MINIMIZED)
@@ -189,7 +167,11 @@ void Panel::FullScreenModeChanged(bool is_full_screen) {
}
void Panel::Show() {
- native_panel_->ShowPanel();
+ // Don't show panel as active if it is in overflow state.
+ if (expansion_state_ == IN_OVERFLOW)
+ ShowInactive();
+ else
+ native_panel_->ShowPanel();
}
void Panel::ShowInactive() {
@@ -207,7 +189,16 @@ void Panel::Close() {
native_panel_->ClosePanel();
}
+void Panel::MoveOutOfOverflow() {
+ if (expansion_state_ != Panel::IN_OVERFLOW)
+ return;
+ manager()->panel_overflow_strip()->Remove(this);
+ manager()->panel_strip()->AddPanel(this);
+}
+
void Panel::Activate() {
+ MoveOutOfOverflow();
+
// Make sure the panel is expanded when activated programmatically,
// so the user input does not go into collapsed window.
SetExpansionState(Panel::EXPANDED);
@@ -278,6 +269,18 @@ gfx::Rect Panel::GetBounds() const {
return native_panel_->GetPanelBounds();
}
+int Panel::TitleOnlyHeight() const {
+ return native_panel_->TitleOnlyHeight();
+}
+
+gfx::Size Panel::IconOnlySize() const {
+ return native_panel_->IconOnlySize();
+}
+
+void Panel::EnsureFullyVisible() {
+ native_panel_->EnsurePanelFullyVisible();
+}
+
bool Panel::IsMaximized() const {
// Size of panels is managed by PanelManager, they are never 'zoomed'.
return false;
diff --git a/chrome/browser/ui/panels/panel.h b/chrome/browser/ui/panels/panel.h
index 094e523..c9f4eab 100644
--- a/chrome/browser/ui/panels/panel.h
+++ b/chrome/browser/ui/panels/panel.h
@@ -69,6 +69,18 @@ class Panel : public BrowserWindow,
// b) it remains on top when an app exits full screen mode.
void FullScreenModeChanged(bool is_full_screen);
+ void MoveOutOfOverflow();
+
+ // Ensures that the panel is fully visible, that is, not obscured by other
+ // top-most windows.
+ void EnsureFullyVisible();
+
+ int TitleOnlyHeight() const;
+
+ // Returns the size of the panel when it is iconified, as shown on the
+ // overflow area.
+ gfx::Size IconOnlySize() const;
+
// BrowserWindow overrides.
virtual void Show() OVERRIDE;
virtual void ShowInactive() OVERRIDE;
diff --git a/chrome/browser/ui/panels/panel_browser_frame_view.cc b/chrome/browser/ui/panels/panel_browser_frame_view.cc
index e83cb46..442eea8 100644
--- a/chrome/browser/ui/panels/panel_browser_frame_view.cc
+++ b/chrome/browser/ui/panels/panel_browser_frame_view.cc
@@ -660,7 +660,7 @@ int PanelBrowserFrameView::IconOnlyWidth() const {
return kBorderThickness * 2 + kIconAndBorderSpacing * 2 + kIconSize;
}
-gfx::Size PanelBrowserFrameView::IconifiedSize() const {
+gfx::Size PanelBrowserFrameView::IconOnlySize() const {
return gfx::Size(IconOnlyWidth(), NonClientTopBorderHeight());
}
diff --git a/chrome/browser/ui/panels/panel_browser_frame_view.h b/chrome/browser/ui/panels/panel_browser_frame_view.h
index ab6ba76..f9e103b 100644
--- a/chrome/browser/ui/panels/panel_browser_frame_view.h
+++ b/chrome/browser/ui/panels/panel_browser_frame_view.h
@@ -56,7 +56,7 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView,
// Returns the size of the non-client area upon which only the title icon
// is drawn.
- gfx::Size IconifiedSize() const;
+ gfx::Size IconOnlySize() const;
protected:
// Overridden from BrowserNonClientFrameView:
diff --git a/chrome/browser/ui/panels/panel_browser_view.cc b/chrome/browser/ui/panels/panel_browser_view.cc
index 3b217ef..6bb2108 100644
--- a/chrome/browser/ui/panels/panel_browser_view.cc
+++ b/chrome/browser/ui/panels/panel_browser_view.cc
@@ -9,6 +9,8 @@
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_browser_frame_view.h"
#include "chrome/browser/ui/panels/panel_manager.h"
+#include "chrome/browser/ui/panels/panel_overflow_strip.h"
+#include "chrome/browser/ui/panels/panel_strip.h"
#include "chrome/browser/ui/views/frame/browser_frame.h"
#include "chrome/browser/ui/webui/task_manager_dialog.h"
#include "chrome/common/chrome_notification_types.h"
@@ -114,15 +116,25 @@ void PanelBrowserView::SetBounds(const gfx::Rect& bounds) {
SetBoundsInternal(bounds, true);
}
-void PanelBrowserView::SetBoundsInternal(const gfx::Rect& bounds,
+void PanelBrowserView::SetBoundsInternal(const gfx::Rect& new_bounds,
bool animate) {
- if (bounds_ == bounds)
+ if (bounds_ == new_bounds)
return;
- bounds_ = bounds;
+
+ // TODO(jianli): this is just a temporary hack to check if we need to show
+ // or hide the panel app icon in the taskbar. http://crbug.com/106227
+ int panel_strip_area_left =
+ panel()->manager()->panel_strip()->display_area().x();
+ bool app_icon_shown = bounds_.x() >= panel_strip_area_left;
+ bool app_icon_to_show = new_bounds.x() >= panel_strip_area_left;
+ if (app_icon_shown != app_icon_to_show)
+ ShowOrHidePanelAppIcon(app_icon_to_show);
+
+ bounds_ = new_bounds;
// No animation if the panel is being dragged.
if (!animate || mouse_dragging_state_ == DRAGGING_STARTED) {
- ::BrowserView::SetBounds(bounds);
+ ::BrowserView::SetBounds(new_bounds);
return;
}
@@ -398,12 +410,16 @@ void PanelBrowserView::DestroyPanelBrowser() {
}
gfx::Size PanelBrowserView::IconOnlySize() const {
- // TODO(jianli): to be implemented.
- return gfx::Size();
+ return GetFrameView()->IconOnlySize();
}
void PanelBrowserView::EnsurePanelFullyVisible() {
- // TODO(jianli): to be implemented.
+#if defined(OS_WIN) && !defined(USE_AURA)
+ ::SetWindowPos(GetNativeHandle(), HWND_TOP, 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+#else
+ NOTIMPLEMENTED();
+#endif
}
PanelBrowserFrameView* PanelBrowserView::GetFrameView() const {
@@ -426,6 +442,10 @@ bool PanelBrowserView::OnTitlebarMouseDragged(const gfx::Point& location) {
if (!mouse_pressed_)
return false;
+ // Dragging is not supported for overflow panel.
+ if (panel_->expansion_state() == Panel::IN_OVERFLOW)
+ return true;
+
gfx::Point last_mouse_location = mouse_location_;
// |location| is in the view's coordinate system. Convert it to the screen
@@ -466,6 +486,12 @@ bool PanelBrowserView::OnTitlebarMouseReleased() {
if (mouse_dragging_state_ != NO_DRAGGING)
return true;
+ // If the panel is in overflow, move it to the normal strip.
+ if (panel_->expansion_state() == Panel::IN_OVERFLOW) {
+ panel_->MoveOutOfOverflow();
+ return true;
+ }
+
// Do not minimize the panel when we just clear the attention state. This is
// a hack to prevent the panel from being minimized when the user clicks on
// the title-bar to clear the attention.
@@ -504,6 +530,22 @@ bool PanelBrowserView::EndDragging(bool cancelled) {
return true;
}
+void PanelBrowserView::ShowOrHidePanelAppIcon(bool show) {
+#if defined(OS_WIN) && !defined(USE_AURA)
+ gfx::NativeWindow native_window = GetNativeHandle();
+ ::ShowWindow(native_window, SW_HIDE);
+ int style = ::GetWindowLong(native_window, GWL_EXSTYLE);
+ if (show)
+ style &= (~WS_EX_TOOLWINDOW);
+ else
+ style |= WS_EX_TOOLWINDOW;
+ ::SetWindowLong(native_window, GWL_EXSTYLE, style);
+ ::ShowWindow(native_window, SW_SHOWNA);
+#else
+ NOTIMPLEMENTED();
+#endif
+}
+
// NativePanelTesting implementation.
class NativePanelTestingWin : public NativePanelTesting {
public:
diff --git a/chrome/browser/ui/panels/panel_browser_view.h b/chrome/browser/ui/panels/panel_browser_view.h
index 9873ed2..99506df 100644
--- a/chrome/browser/ui/panels/panel_browser_view.h
+++ b/chrome/browser/ui/panels/panel_browser_view.h
@@ -122,6 +122,8 @@ class PanelBrowserView : public BrowserView,
void SetBoundsInternal(const gfx::Rect& bounds, bool animate);
+ void ShowOrHidePanelAppIcon(bool show);
+
scoped_ptr<Panel> panel_;
gfx::Rect bounds_;
diff --git a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
index 100c548..2db40e9 100644
--- a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
@@ -616,7 +616,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, DISABLED_DrawAttention) {
}
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest,
- DISABLED_ChangeAutoHideTaskBarThickness) {
+ ChangeAutoHideTaskBarThickness) {
TestChangeAutoHideTaskBarThickness();
}
#endif
diff --git a/chrome/browser/ui/panels/panel_browsertest.cc b/chrome/browser/ui/panels/panel_browsertest.cc
index f7e12e4..63c15df 100644
--- a/chrome/browser/ui/panels/panel_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browsertest.cc
@@ -27,7 +27,9 @@
#include "chrome/browser/ui/panels/native_panel.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_manager.h"
+#include "chrome/browser/ui/panels/panel_overflow_strip.h"
#include "chrome/browser/ui/panels/panel_settings_menu_model.h"
+#include "chrome/browser/ui/panels/panel_strip.h"
#include "chrome/browser/ui/panels/test_panel_mouse_watcher.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_notification_types.h"
@@ -81,6 +83,9 @@ class PanelBrowserTest : public BasePanelBrowserTest {
void TestCreatePanelOnOverflow() {
PanelManager* panel_manager = PanelManager::GetInstance();
+ PanelStrip* panel_strip = panel_manager->panel_strip();
+ PanelOverflowStrip* panel_overflow_strip =
+ panel_manager->panel_overflow_strip();
EXPECT_EQ(0, panel_manager->num_panels()); // No panels initially.
// Create testing extensions.
@@ -106,42 +111,50 @@ class PanelBrowserTest : public BasePanelBrowserTest {
web_app::GenerateApplicationNameFromExtensionId(extension1->id()),
gfx::Rect(0, 0, 200, 200));
ASSERT_EQ(3, panel_manager->num_panels());
+ EXPECT_EQ(3, panel_strip->num_panels());
+ EXPECT_EQ(0, panel_overflow_strip->num_panels());
// Open a panel that would overflow.
Panel* panel4 = CreatePanelWithBounds(
web_app::GenerateApplicationNameFromExtensionId(extension2->id()),
gfx::Rect(0, 0, 280, 200));
ASSERT_EQ(4, panel_manager->num_panels());
- EXPECT_LT(panel4->GetBounds().right(), panel3->GetBounds().x());
- EXPECT_GT(0, panel4->GetBounds().x());
+ EXPECT_EQ(3, panel_strip->num_panels());
+ EXPECT_EQ(1, panel_overflow_strip->num_panels());
+ EXPECT_EQ(Panel::IN_OVERFLOW, panel4->expansion_state());
// Open another panel that would overflow.
Panel* panel5 = CreatePanelWithBounds(
web_app::GenerateApplicationNameFromExtensionId(extension3->id()),
gfx::Rect(0, 0, 300, 200));
ASSERT_EQ(5, panel_manager->num_panels());
- EXPECT_LT(panel5->GetBounds().right(), panel4->GetBounds().x());
- EXPECT_GT(0, panel5->GetBounds().x());
+ EXPECT_EQ(3, panel_strip->num_panels());
+ EXPECT_EQ(2, panel_overflow_strip->num_panels());
+ EXPECT_EQ(Panel::IN_OVERFLOW, panel4->expansion_state());
+ EXPECT_EQ(Panel::IN_OVERFLOW, panel5->expansion_state());
- // Close a visible panel. Expect an overflow panel to slide over.
+ // Close a visible panel. Expect an overflow panel to move over.
CloseWindowAndWait(panel2->browser());
ASSERT_EQ(4, panel_manager->num_panels());
- EXPECT_LT(panel4->GetBounds().right(), panel3->GetBounds().x());
- EXPECT_LE(0, panel4->GetBounds().x());
- EXPECT_GT(0, panel5->GetBounds().x());
+ EXPECT_EQ(3, panel_strip->num_panels());
+ EXPECT_EQ(1, panel_overflow_strip->num_panels());
+ EXPECT_NE(Panel::IN_OVERFLOW, panel4->expansion_state());
+ EXPECT_EQ(Panel::IN_OVERFLOW, panel5->expansion_state());
- // Close another visible panel. Remaining overflow panel should slide over
- // but still not enough room to be fully visible.
+ // Close another visible panel. Remaining overflow panel cannot move over
+ // due to not enough room.
CloseWindowAndWait(panel3->browser());
ASSERT_EQ(3, panel_manager->num_panels());
- EXPECT_LT(panel5->GetBounds().right(), panel4->GetBounds().x());
- EXPECT_GT(0, panel5->GetBounds().x());
+ EXPECT_EQ(2, panel_strip->num_panels());
+ EXPECT_EQ(1, panel_overflow_strip->num_panels());
+ EXPECT_EQ(Panel::IN_OVERFLOW, panel5->expansion_state());
// Closing one more panel makes room for all panels to fit on screen.
CloseWindowAndWait(panel4->browser());
ASSERT_EQ(2, panel_manager->num_panels());
- EXPECT_LT(panel5->GetBounds().right(), panel1->GetBounds().x());
- EXPECT_LE(0, panel5->GetBounds().x());
+ EXPECT_EQ(2, panel_strip->num_panels());
+ EXPECT_EQ(0, panel_overflow_strip->num_panels());
+ EXPECT_NE(Panel::IN_OVERFLOW, panel5->expansion_state());
panel1->Close();
panel5->Close();
diff --git a/chrome/browser/ui/panels/panel_manager.cc b/chrome/browser/ui/panels/panel_manager.cc
index 122381d..30eb6cd 100644
--- a/chrome/browser/ui/panels/panel_manager.cc
+++ b/chrome/browser/ui/panels/panel_manager.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
+#include "chrome/browser/ui/panels/panel_overflow_strip.h"
#include "chrome/browser/ui/panels/panel_strip.h"
#include "chrome/browser/ui/window_sizer.h"
#include "chrome/common/chrome_notification_types.h"
@@ -41,6 +42,7 @@ PanelManager::PanelManager()
auto_sizing_enabled_(true),
is_full_screen_(false) {
panel_strip_.reset(new PanelStrip(this));
+ panel_overflow_strip_.reset(new PanelOverflowStrip(this));
auto_hiding_desktop_bar_ = AutoHidingDesktopBar::Create(this);
OnDisplayChanged();
}
@@ -81,6 +83,10 @@ void PanelManager::Layout() {
kPanelStripLeftMargin - kPanelStripRightMargin);
panel_strip_bounds.set_height(height);
panel_strip_->SetDisplayArea(panel_strip_bounds);
+
+ gfx::Rect overflow_area(adjusted_work_area_);
+ overflow_area.set_width(kOverflowStripThickness);
+ panel_overflow_strip_->SetDisplayArea(overflow_area);
}
Panel* PanelManager::CreatePanel(Browser* browser) {
@@ -113,6 +119,7 @@ void PanelManager::CheckFullScreenMode() {
return;
is_full_screen_ = is_full_screen_new;
panel_strip_->OnFullScreenModeChanged(is_full_screen_);
+ panel_overflow_strip_->OnFullScreenModeChanged(is_full_screen_);
}
void PanelManager::Remove(Panel* panel) {
@@ -121,7 +128,8 @@ void PanelManager::Remove(Panel* panel) {
if (panel_strip_->Remove(panel))
return;
- // TODO(jianli): else try removing from overflow strip
+ bool removed = panel_overflow_strip_->Remove(panel);
+ DCHECK(removed);
}
void PanelManager::OnPanelRemoved(Panel* panel) {
@@ -144,8 +152,11 @@ void PanelManager::EndDragging(bool cancelled) {
}
void PanelManager::OnPanelExpansionStateChanged(
- Panel::ExpansionState old_state, Panel::ExpansionState new_state) {
- panel_strip_->OnPanelExpansionStateChanged(old_state, new_state);
+ Panel* panel, Panel::ExpansionState old_state) {
+ if (panel->expansion_state() == Panel::IN_OVERFLOW)
+ panel_overflow_strip_->OnPanelExpansionStateChanged(panel, old_state);
+ else
+ panel_strip_->OnPanelExpansionStateChanged(panel, old_state);
}
void PanelManager::OnPreferredWindowSizeChanged(
@@ -180,11 +191,6 @@ void PanelManager::AdjustWorkAreaForAutoHidingDesktopBars() {
}
}
-int PanelManager::GetBottomPositionForExpansionState(
- Panel::ExpansionState expansion_state) const {
- return panel_strip_->GetBottomPositionForExpansionState(expansion_state);
-}
-
BrowserWindow* PanelManager::GetNextBrowserWindowToActivate(
Panel* panel) const {
// Find the last active browser window that is not minimized.
@@ -199,10 +205,6 @@ BrowserWindow* PanelManager::GetNextBrowserWindowToActivate(
return NULL;
}
-void PanelManager::MoveToOverflowStrip(Panel* panel, bool is_new) {
- // TODO(jianli) - implement.
-}
-
void PanelManager::OnAutoHidingDesktopBarThicknessChanged() {
AdjustWorkAreaForAutoHidingDesktopBars();
Layout();
@@ -216,12 +218,11 @@ void PanelManager::OnAutoHidingDesktopBarVisibilityChanged(
void PanelManager::RemoveAll() {
panel_strip_->RemoveAll();
- // TODO(jianli): overflow_strip_->RemoveAll();
+ panel_overflow_strip_->RemoveAll();
}
int PanelManager::num_panels() const {
- return panel_strip_->num_panels();
- // TODO(jianli): + overflow_strip_->num_panels();
+ return panel_strip_->num_panels() + panel_overflow_strip_->num_panels();
}
bool PanelManager::is_dragging_panel() const {
diff --git a/chrome/browser/ui/panels/panel_manager.h b/chrome/browser/ui/panels/panel_manager.h
index 897a84e..b78cb9e 100644
--- a/chrome/browser/ui/panels/panel_manager.h
+++ b/chrome/browser/ui/panels/panel_manager.h
@@ -24,6 +24,7 @@
class Browser;
class PanelMouseWatcher;
+class PanelOverflowStrip;
class PanelStrip;
// This class manages a set of panels.
@@ -53,8 +54,8 @@ class PanelManager : public AutoHidingDesktopBar::Observer {
void EndDragging(bool cancelled);
// Invoked when a panel's expansion state changes.
- void OnPanelExpansionStateChanged(Panel::ExpansionState old_state,
- Panel::ExpansionState new_state);
+ void OnPanelExpansionStateChanged(Panel* panel,
+ Panel::ExpansionState old_state);
// Invoked when the preferred window size of the given panel might need to
// get changed.
@@ -68,12 +69,6 @@ class PanelManager : public AutoHidingDesktopBar::Observer {
// Brings up or down the titlebars for all minimized panels.
void BringUpOrDownTitlebars(bool bring_up);
- // Returns the bottom position for the panel per its expansion state. If auto-
- // hide bottom bar is present, we want to move the minimized panel to the
- // bottom of the screen, not the bottom of the work area.
- int GetBottomPositionForExpansionState(
- Panel::ExpansionState expansion_state) const;
-
// Returns the next browser window which could be either panel window or
// tabbed window, to switch to if the given panel is going to be deactivated.
// Returns NULL if such window cannot be found.
@@ -84,11 +79,6 @@ class PanelManager : public AutoHidingDesktopBar::Observer {
int StartingRightPosition() const;
const Panels& panels() const;
- // Moves a panel to the overflow strip. The panel does not currently
- // belong in any other strip.
- // |is_new| is true if the panel was just created.
- void MoveToOverflowStrip(Panel* panel, bool is_new);
-
AutoHidingDesktopBar* auto_hiding_desktop_bar() const {
return auto_hiding_desktop_bar_;
}
@@ -102,6 +92,9 @@ class PanelManager : public AutoHidingDesktopBar::Observer {
}
bool is_full_screen() const { return is_full_screen_; }
+ PanelOverflowStrip* panel_overflow_strip() const {
+ return panel_overflow_strip_.get();
+ }
#ifdef UNIT_TEST
static int horizontal_spacing() { return PanelStrip::horizontal_spacing(); }
@@ -162,6 +155,7 @@ class PanelManager : public AutoHidingDesktopBar::Observer {
void CheckFullScreenMode();
scoped_ptr<PanelStrip> panel_strip_;
+ scoped_ptr<PanelOverflowStrip> panel_overflow_strip_;
// Use a mouse watcher to know when to bring up titlebars to "peek" at
// minimized panels. Mouse movement is only tracked when there is a minimized
diff --git a/chrome/browser/ui/panels/panel_overflow_strip.cc b/chrome/browser/ui/panels/panel_overflow_strip.cc
new file mode 100644
index 0000000..ed7c8ed
--- /dev/null
+++ b/chrome/browser/ui/panels/panel_overflow_strip.cc
@@ -0,0 +1,220 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/panels/panel_overflow_strip.h"
+
+#include "base/logging.h"
+#include "chrome/browser/ui/panels/panel_manager.h"
+#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
+#include "chrome/browser/ui/panels/panel_strip.h"
+#include "ui/base/animation/slide_animation.h"
+
+namespace {
+// The width of the overflow area that is expanded to show more info, i.e.
+// titles, when the mouse hovers over the area.
+const int kOverflowAreaHoverWidth = 200;
+
+// Maximium number of overflow panels allowed to be shown.
+const size_t kMaxVisibleOverflowPanelsAllowed = 6;
+
+// This value is experimental and subjective.
+const int kOverflowHoverAnimationMs = 180;
+}
+
+PanelOverflowStrip::PanelOverflowStrip(PanelManager* panel_manager)
+ : panel_manager_(panel_manager),
+ are_overflow_titles_shown_(false),
+ overflow_hover_animator_start_width_(0),
+ overflow_hover_animator_end_width_(0) {
+}
+
+PanelOverflowStrip::~PanelOverflowStrip() {
+ DCHECK(panels_.empty());
+}
+
+void PanelOverflowStrip::SetDisplayArea(const gfx::Rect& display_area) {
+ if (display_area_ == display_area)
+ return;
+
+ display_area_ = display_area;
+ Refresh();
+}
+
+void PanelOverflowStrip::AddPanel(Panel* panel, bool is_new) {
+ // TODO(jianli): consider using other container to improve the perf for
+ // inserting to the front. http://crbug.com/106222
+ if (is_new)
+ panels_.push_back(panel);
+ else
+ panels_.insert(panels_.begin(), panel);
+
+ if (panels_.size() == 1)
+ panel_manager_->mouse_watcher()->AddObserver(this);
+
+ panel->SetExpansionState(Panel::IN_OVERFLOW);
+
+ if (is_new) {
+ // When the overflow panel is added to the back, only need to refresh
+ // itself.
+ DoRefresh(panels_.size() - 1, panels_.size() - 1);
+ } else {
+ // When the overflow panel is added to the front, refresh all.
+ Refresh();
+ }
+}
+
+bool PanelOverflowStrip::Remove(Panel* panel) {
+ size_t index = 0;
+ for (Panels::iterator iter = panels_.begin(); iter != panels_.end();
+ ++iter, ++index) {
+ if (*iter == panel) {
+ panels_.erase(iter);
+ DoRefresh(index, panels_.size() - 1);
+ panel_manager_->OnPanelRemoved(panel);
+ if (panels_.empty())
+ panel_manager_->mouse_watcher()->RemoveObserver(this);
+ return true;
+ }
+ }
+ return false;
+}
+
+void PanelOverflowStrip::RemoveAll() {
+ // Make a copy of the iterator as closing panels can modify the vector.
+ Panels panels_copy = panels_;
+
+ // Start from the bottom to avoid reshuffling.
+ for (Panels::reverse_iterator iter = panels_copy.rbegin();
+ iter != panels_copy.rend(); ++iter)
+ (*iter)->Close();
+}
+
+void PanelOverflowStrip::OnPanelExpansionStateChanged(
+ Panel* panel, Panel::ExpansionState old_state) {
+ DCHECK(panel->expansion_state() == Panel::IN_OVERFLOW);
+}
+
+void PanelOverflowStrip::Refresh() {
+ if (panels_.empty())
+ return;
+ DoRefresh(0, panels_.size() - 1);
+}
+
+void PanelOverflowStrip::DoRefresh(size_t start_index, size_t end_index) {
+ if (panels_.empty())
+ return;
+
+ DCHECK(start_index < panels_.size());
+ DCHECK(end_index < panels_.size());
+
+ for (size_t index = start_index; index <= end_index; ++index) {
+ Panel* panel = panels_[index];
+ gfx::Rect new_bounds = ComputeLayout(index,
+ panel->IconOnlySize());
+ DCHECK(!new_bounds.IsEmpty());
+ panel->SetPanelBounds(new_bounds);
+ }
+}
+
+gfx::Rect PanelOverflowStrip::ComputeLayout(
+ size_t index, const gfx::Size& iconified_size) const {
+ DCHECK(index != kInvalidPanelIndex);
+
+ gfx::Rect bounds;
+ int bottom = (index == 0) ? display_area_.bottom() :
+ panels_[index - 1]->GetBounds().y();
+ bounds.set_x(display_area_.x());
+ bounds.set_y(bottom - iconified_size.height());
+
+ if (are_overflow_titles_shown_) {
+ // Both icon and title are visible when the mouse hovers over the overflow
+ // area.
+ bounds.set_width(kOverflowAreaHoverWidth);
+ bounds.set_height(iconified_size.height());
+ } else if (index < kMaxVisibleOverflowPanelsAllowed) {
+ // Only the icon is visible.
+ bounds.set_width(iconified_size.width());
+ bounds.set_height(iconified_size.height());
+ } else {
+ // Invisible for overflow-on-overflow.
+ bounds.set_width(0);
+ bounds.set_height(0);
+ }
+
+ return bounds;
+}
+
+void PanelOverflowStrip::OnMouseMove(const gfx::Point& mouse_position) {
+ bool show_overflow_titles = ShouldShowOverflowTitles(mouse_position);
+ ShowOverflowTitles(show_overflow_titles);
+}
+
+bool PanelOverflowStrip::ShouldShowOverflowTitles(
+ const gfx::Point& mouse_position) const {
+ if (panels_.empty())
+ return false;
+
+ int width = are_overflow_titles_shown_ ? kOverflowAreaHoverWidth
+ : display_area_.width();
+ return display_area_.x() <= mouse_position.x() &&
+ mouse_position.x() <= display_area_.x() + width &&
+ panels_.back()->GetBounds().y() <= mouse_position.y() &&
+ mouse_position.y() <= display_area_.bottom();
+}
+
+void PanelOverflowStrip::ShowOverflowTitles(bool show_overflow_titles) {
+ if (show_overflow_titles == are_overflow_titles_shown_)
+ return;
+ are_overflow_titles_shown_ = show_overflow_titles;
+
+ if (show_overflow_titles) {
+ overflow_hover_animator_start_width_ = display_area_.width();
+ overflow_hover_animator_end_width_ = kOverflowAreaHoverWidth;
+
+ // We need to bring all overflow panels to the top of z-order since the
+ // active panel might obscure the expanded overflow panels.
+ for (Panels::iterator iter = panels_.begin();
+ iter != panels_.end(); ++iter) {
+ (*iter)->EnsureFullyVisible();
+ }
+ } else {
+ overflow_hover_animator_start_width_ = kOverflowAreaHoverWidth;
+ overflow_hover_animator_end_width_ = display_area_.width();
+ }
+
+ if (!overflow_hover_animator_.get())
+ overflow_hover_animator_.reset(new ui::SlideAnimation(this));
+ if (overflow_hover_animator_->IsShowing())
+ overflow_hover_animator_->Reset();
+ overflow_hover_animator_->SetSlideDuration(kOverflowHoverAnimationMs);
+
+ overflow_hover_animator_->Show();
+}
+
+void PanelOverflowStrip::AnimationProgressed(const ui::Animation* animation) {
+ int current_width = overflow_hover_animator_->CurrentValueBetween(
+ overflow_hover_animator_start_width_, overflow_hover_animator_end_width_);
+ bool end_of_shrinking = current_width == display_area_.width();
+
+ // Update each overflow panel.
+ for (size_t i = 0; i < panels_.size(); ++i) {
+ Panel* overflow_panel = panels_[i];
+ gfx::Rect bounds = overflow_panel->GetBounds();
+
+ if (i >= kMaxVisibleOverflowPanelsAllowed && end_of_shrinking) {
+ bounds.set_width(0);
+ bounds.set_height(0);
+ } else {
+ bounds.set_width(current_width);
+ bounds.set_height(overflow_panel->IconOnlySize().height());
+ }
+
+ overflow_panel->SetPanelBoundsInstantly(bounds);
+ }
+}
+
+void PanelOverflowStrip::OnFullScreenModeChanged(bool is_full_screen) {
+ for (size_t i = 0; i < panels_.size(); ++i)
+ panels_[i]->FullScreenModeChanged(is_full_screen);
+}
diff --git a/chrome/browser/ui/panels/panel_overflow_strip.h b/chrome/browser/ui/panels/panel_overflow_strip.h
new file mode 100644
index 0000000..0dab64d
--- /dev/null
+++ b/chrome/browser/ui/panels/panel_overflow_strip.h
@@ -0,0 +1,101 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_PANELS_PANEL_OVERFLOW_STRIP_H_
+#define CHROME_BROWSER_UI_PANELS_PANEL_OVERFLOW_STRIP_H_
+#pragma once
+
+#include <vector>
+#include "chrome/browser/ui/panels/panel.h"
+#include "chrome/browser/ui/panels/panel_mouse_watcher_observer.h"
+#include "ui/base/animation/animation_delegate.h"
+
+class Browser;
+class PanelManager;
+namespace ui {
+class SlideAnimation;
+}
+
+// Manipulates all the panels that are placed on the left-most overflow area.
+class PanelOverflowStrip : public PanelMouseWatcherObserver,
+ public ui::AnimationDelegate {
+ public:
+ typedef std::vector<Panel*> Panels;
+
+ explicit PanelOverflowStrip(PanelManager* panel_manager);
+ virtual ~PanelOverflowStrip();
+
+ // Sets the display area of the overflow strip.
+ // |display_area| is in screen coordinates.
+ void SetDisplayArea(const gfx::Rect& display_area);
+
+ // Adds a panel to the strip. |is_new| indicates if the panel is a newly
+ // created panel or one that is transitioning from another grouping of panels.
+ void AddPanel(Panel* panel, bool is_new);
+
+ // Returns |false| if the panel is not in the strip.
+ bool Remove(Panel* panel);
+ void RemoveAll();
+
+ // Called when a panel's expansion state changes.
+ void OnPanelExpansionStateChanged(
+ Panel* panel, Panel::ExpansionState old_state);
+
+ // Refreshes the layouts for all panels to reflect any possible changes.
+ void Refresh();
+
+ void OnFullScreenModeChanged(bool is_full_screen);
+
+ int num_panels() const { return static_cast<int>(panels_.size()); }
+ Panel* first_panel() const {
+ return panels_.empty() ? NULL : panels_.front();
+ }
+
+#ifdef UNIT_TEST
+ const Panels& panels() const { return panels_; }
+#endif
+
+ private:
+ // Overridden from PanelMouseWatcherObserver:
+ virtual void OnMouseMove(const gfx::Point& mouse_position) OVERRIDE;
+
+ // Overridden from AnimationDelegate:
+ virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
+
+ void DoRefresh(size_t start_index, size_t end_index);
+
+ // Computes the layout of the |index| panel to fit into the area.
+ // Empty bounds will be returned if this is not possible due to not enough
+ // space.
+ gfx::Rect ComputeLayout(size_t index,
+ const gfx::Size& iconified_size) const;
+
+ // Used to pop up the titles for overflow panels when the mouse hovers over
+ // the overflow area.
+ bool ShouldShowOverflowTitles(const gfx::Point& mouse_position) const;
+ void ShowOverflowTitles(bool show_overflow_titles);
+
+ // Weak pointer since PanelManager owns PanelOverflowStrip instance.
+ PanelManager* panel_manager_;
+
+ // The queue for storing all panels.
+ Panels panels_;
+
+ // The overflow area where panels are iconified due to insufficient space
+ // in the panel strip.
+ gfx::Rect display_area_;
+
+ // For mouse hover-over effect.
+ bool are_overflow_titles_shown_;
+ scoped_ptr<ui::SlideAnimation> overflow_hover_animator_;
+ int overflow_hover_animator_start_width_;
+ int overflow_hover_animator_end_width_;
+
+ // Invalid panel index.
+ static const size_t kInvalidPanelIndex = static_cast<size_t>(-1);
+
+ DISALLOW_COPY_AND_ASSIGN(PanelOverflowStrip);
+};
+
+#endif // CHROME_BROWSER_UI_PANELS_PANEL_OVERFLOW_STRIP_H_
diff --git a/chrome/browser/ui/panels/panel_strip.cc b/chrome/browser/ui/panels/panel_strip.cc
index e94c157..499516f 100644
--- a/chrome/browser/ui/panels/panel_strip.cc
+++ b/chrome/browser/ui/panels/panel_strip.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/ui/browser.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_strip.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
@@ -73,13 +74,10 @@ void PanelStrip::SetDisplayArea(const gfx::Rect& new_area) {
gfx::Rect old_area = display_area_;
display_area_ = new_area;
- if (panels_.empty() || new_area.width() == old_area.width())
+ if (panels_.empty())
return;
- if (new_area.width() < old_area.width())
- Rearrange();
- else
- MovePanelsFromOverflowIfNeeded();
+ Rearrange();
}
void PanelStrip::AddPanel(Panel* panel) {
@@ -132,6 +130,9 @@ void PanelStrip::AddPanel(Panel* panel) {
// Keep panel visible in the strip even if overlap would occur.
// Panel is moved to overflow from the strip after a delay.
+ // TODO(jianli): remove the guard when overflow support is enabled on other
+ // platforms. http://crbug.com/105073
+#if defined(OS_WIN)
if (x < display_area_.x()) {
x = display_area_.x();
int delay_ms = remove_delays_for_testing_ ? 0 :
@@ -144,6 +145,7 @@ void PanelStrip::AddPanel(Panel* panel) {
true), // new panel
delay_ms);
}
+#endif
panel->Initialize(gfx::Rect(x, y, width, height));
}
@@ -334,20 +336,36 @@ void PanelStrip::EndDragging(bool cancelled) {
}
void PanelStrip::OnPanelExpansionStateChanged(
- Panel::ExpansionState old_state, Panel::ExpansionState new_state) {
- DCHECK_NE(new_state, old_state);
- switch (new_state) {
+ Panel* panel, Panel::ExpansionState old_state) {
+ gfx::Size size = panel->restored_size();
+ Panel::ExpansionState expansion_state = panel->expansion_state();
+ switch (expansion_state) {
case Panel::EXPANDED:
- DecrementMinimizedPanels();
+ if (old_state == Panel::TITLE_ONLY || old_state == Panel::MINIMIZED)
+ DecrementMinimizedPanels();
break;
- case Panel::MINIMIZED:
case Panel::TITLE_ONLY:
+ size.set_height(panel->TitleOnlyHeight());
+ if (old_state == Panel::EXPANDED)
+ IncrementMinimizedPanels();
+ break;
+ case Panel::MINIMIZED:
+ size.set_height(Panel::kMinimizedPanelHeight);
if (old_state == Panel::EXPANDED)
IncrementMinimizedPanels();
break;
default:
+ NOTREACHED();
break;
}
+
+ int bottom = GetBottomPositionForExpansionState(expansion_state);
+ gfx::Rect bounds = panel->GetBounds();
+ panel->SetPanelBounds(
+ gfx::Rect(bounds.right() - size.width(),
+ bottom - size.height(),
+ size.width(),
+ size.height()));
}
void PanelStrip::IncrementMinimizedPanels() {
@@ -573,12 +591,16 @@ void PanelStrip::Rearrange() {
gfx::Rect new_bounds(panel->GetBounds());
int x = rightmost_position - new_bounds.width();
+ // TODO(jianli): remove the guard when overflow support is enabled on other
+ // platforms. http://crbug.com/105073
+#if defined(OS_WIN)
if (x < display_area_.x()) {
MovePanelsToOverflow(panel_index);
break;
}
+#endif
- new_bounds.set_x(rightmost_position - new_bounds.width());
+ new_bounds.set_x(x);
new_bounds.set_y(
GetBottomPositionForExpansionState(panel->expansion_state()) -
new_bounds.height());
@@ -587,8 +609,12 @@ void PanelStrip::Rearrange() {
rightmost_position = new_bounds.x() - kPanelsHorizontalSpacing;
}
+ // TODO(jianli): remove the guard when overflow support is enabled on other
+ // platforms. http://crbug.com/105073
+#if defined(OS_WIN)
if (panel_index == panels_.size())
MovePanelsFromOverflowIfNeeded();
+#endif
}
void PanelStrip::MovePanelsToOverflow(size_t overflow_point) {
@@ -602,20 +628,18 @@ 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);
+ 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);
- // }
+ PanelOverflowStrip* overflow_strip = panel_manager_->panel_overflow_strip();
+ Panel* overflow_panel;
+ while ((overflow_panel = overflow_strip->first_panel()) &&
+ GetRightMostAvailablePosition() -
+ overflow_panel->restored_size().width() >= display_area_.x()) {
+ overflow_strip->Remove(overflow_panel);
+ AddPanel(overflow_panel);
+ }
}
void PanelStrip::RemoveAll() {
diff --git a/chrome/browser/ui/panels/panel_strip.h b/chrome/browser/ui/panels/panel_strip.h
index bdf4655..992e565 100644
--- a/chrome/browser/ui/panels/panel_strip.h
+++ b/chrome/browser/ui/panels/panel_strip.h
@@ -10,8 +10,8 @@
#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h"
-#include "chrome/browser/ui/panels/panel_mouse_watcher_observer.h"
#include "chrome/browser/ui/panels/panel.h"
+#include "chrome/browser/ui/panels/panel_mouse_watcher_observer.h"
#include "ui/gfx/rect.h"
class Browser;
@@ -29,7 +29,7 @@ class PanelStrip : public PanelMouseWatcherObserver {
virtual ~PanelStrip();
// Sets the bounds of the panel strip.
- // |bounds| is in screen coordinates.
+ // |area| is in screen coordinates.
void SetDisplayArea(const gfx::Rect& area);
// Adds a panel to the strip. The panel may be a newly created panel or one
@@ -46,8 +46,8 @@ class PanelStrip : public PanelMouseWatcherObserver {
void EndDragging(bool cancelled);
// Invoked when a panel's expansion state changes.
- void OnPanelExpansionStateChanged(Panel::ExpansionState old_state,
- Panel::ExpansionState new_state);
+ void OnPanelExpansionStateChanged(Panel* panel,
+ Panel::ExpansionState old_state);
// Invoked when the preferred window size of the given panel might need to
// get changed.
@@ -70,14 +70,12 @@ class PanelStrip : public PanelMouseWatcherObserver {
int num_panels() const { return panels_.size(); }
bool is_dragging_panel() const;
const Panels& panels() const { return panels_; }
+ gfx::Rect display_area() const { return display_area_; }
int GetMaxPanelWidth() const;
int GetMaxPanelHeight() const;
int StartingRightPosition() const;
- // Overridden from PanelMouseWatcherObserver:
- virtual void OnMouseMove(const gfx::Point& mouse_position) OVERRIDE;
-
void OnAutoHidingDesktopBarVisibilityChanged(
AutoHidingDesktopBar::Alignment alignment,
AutoHidingDesktopBar::Visibility visibility);
@@ -103,6 +101,9 @@ class PanelStrip : public PanelMouseWatcherObserver {
BRING_DOWN
};
+ // Overridden from PanelMouseWatcherObserver:
+ virtual void OnMouseMove(const gfx::Point& mouse_position) OVERRIDE;
+
// Keep track of the minimized panels to control mouse watching.
void IncrementMinimizedPanels();
void DecrementMinimizedPanels();