From c967ec0e09ccf24b4d492fada0db706be459a081 Mon Sep 17 00:00:00 2001 From: "flackr@chromium.org" Date: Sat, 16 Mar 2013 15:53:39 +0000 Subject: Reland 187876 - Reorder panels in the launcher when dragging the panel window. BUG=172254 TEST=PanelWindowResizerTest.DragReordersPanels* Review URL: https://chromiumcodereview.appspot.com/12434007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188580 0039d316-1c4b-4281-b951-d872f2087c98 --- ash/launcher/launcher.cc | 8 ++- ash/launcher/launcher.h | 4 ++ ash/launcher/launcher_view.cc | 26 +++++++ ash/launcher/launcher_view.h | 3 + ash/test/test_launcher_delegate.cc | 5 +- ash/wm/panels/panel_layout_manager.cc | 2 - ash/wm/panels/panel_layout_manager_unittest.cc | 7 +- ash/wm/panels/panel_window_resizer.cc | 7 ++ ash/wm/panels/panel_window_resizer.h | 3 + ash/wm/panels/panel_window_resizer_unittest.cc | 98 ++++++++++++++++++++------ 10 files changed, 134 insertions(+), 29 deletions(-) diff --git a/ash/launcher/launcher.cc b/ash/launcher/launcher.cc index 54c8e0c..51f68c1 100644 --- a/ash/launcher/launcher.cc +++ b/ash/launcher/launcher.cc @@ -48,7 +48,7 @@ Launcher::Launcher(LauncherModel* launcher_model, LauncherDelegate* launcher_delegate, ShelfWidget* shelf_widget) : launcher_view_(NULL), - alignment_(SHELF_ALIGNMENT_BOTTOM), + alignment_(shelf_widget->GetAlignment()), delegate_(launcher_delegate), shelf_widget_(shelf_widget) { launcher_view_ = new internal::LauncherView( @@ -95,6 +95,12 @@ gfx::Rect Launcher::GetScreenBoundsOfItemIconForWindow(aura::Window* window) { bounds.height()); } +void Launcher::UpdateIconPositionForWindow(aura::Window* window) { + launcher_view_->UpdatePanelIconPosition( + delegate_->GetIDByWindow(window), + window->bounds().CenterPoint()); +} + void Launcher::ActivateLauncherItem(int index) { const ash::LauncherItems& items = launcher_view_->model()->items(); diff --git a/ash/launcher/launcher.h b/ash/launcher/launcher.h index a90f23a..8c61ce3 100644 --- a/ash/launcher/launcher.h +++ b/ash/launcher/launcher.h @@ -61,6 +61,10 @@ class ASH_EXPORT Launcher { // no item for the specified window an empty rect is returned. gfx::Rect GetScreenBoundsOfItemIconForWindow(aura::Window* window); + // Updates the icon position given the current window bounds. This is used + // when dragging panels to reposition them with respect to the other panels. + void UpdateIconPositionForWindow(aura::Window* window); + // Activates the the launcher item specified by the index in the list // of launcher items. void ActivateLauncherItem(int index); diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc index 3433e0b..7ea9650 100644 --- a/ash/launcher/launcher_view.cc +++ b/ash/launcher/launcher_view.cc @@ -432,6 +432,32 @@ gfx::Rect LauncherView::GetIdealBoundsOfItemIcon(LauncherID id) { icon_bounds.width(), icon_bounds.height()); } +void LauncherView::UpdatePanelIconPosition(LauncherID id, + const gfx::Point& midpoint) { + int current_index = model_->ItemIndexByID(id); + int first_panel_index = model_->FirstPanelIndex(); + if (current_index < first_panel_index) + return; + + ShelfLayoutManager* shelf = tooltip_->shelf_layout_manager(); + int target_index = current_index; + while (target_index > first_panel_index && + shelf->PrimaryAxisValue(view_model_->ideal_bounds(target_index).x(), + view_model_->ideal_bounds(target_index).y()) > + shelf->PrimaryAxisValue(midpoint.x(), midpoint.y())) { + --target_index; + } + while (target_index < view_model_->view_size() - 1 && + shelf->PrimaryAxisValue( + view_model_->ideal_bounds(target_index).right(), + view_model_->ideal_bounds(target_index).bottom()) < + shelf->PrimaryAxisValue(midpoint.x(), midpoint.y())) { + ++target_index; + } + if (current_index != target_index) + model_->Move(current_index, target_index); +} + bool LauncherView::IsShowingMenu() const { #if !defined(OS_MACOSX) return (launcher_menu_runner_.get() && diff --git a/ash/launcher/launcher_view.h b/ash/launcher/launcher_view.h index dc024dc..2207a3e 100644 --- a/ash/launcher/launcher_view.h +++ b/ash/launcher/launcher_view.h @@ -69,6 +69,9 @@ class ASH_EXPORT LauncherView : public views::View, // isn't know. gfx::Rect GetIdealBoundsOfItemIcon(LauncherID id); + // Repositions the icon for the specified item by the midpoint of the window. + void UpdatePanelIconPosition(LauncherID id, const gfx::Point& midpoint); + void AddIconObserver(LauncherIconObserver* observer); void RemoveIconObserver(LauncherIconObserver* observer); diff --git a/ash/test/test_launcher_delegate.cc b/ash/test/test_launcher_delegate.cc index 30a49f5..3f40849 100644 --- a/ash/test/test_launcher_delegate.cc +++ b/ash/test/test_launcher_delegate.cc @@ -34,7 +34,10 @@ void TestLauncherDelegate::AddLauncherItem( aura::Window* window, LauncherItemStatus status) { ash::LauncherItem item; - item.type = ash::TYPE_TABBED; + if (window->type() == aura::client::WINDOW_TYPE_PANEL) + item.type = ash::TYPE_APP_PANEL; + else + item.type = ash::TYPE_TABBED; DCHECK(window_to_id_.find(window) == window_to_id_.end()); window_to_id_[window] = model_->next_id(); item.status = status; diff --git a/ash/wm/panels/panel_layout_manager.cc b/ash/wm/panels/panel_layout_manager.cc index 3bd7036..b268f5b 100644 --- a/ash/wm/panels/panel_layout_manager.cc +++ b/ash/wm/panels/panel_layout_manager.cc @@ -244,8 +244,6 @@ void PanelLayoutManager::StartDragging(aura::Window* panel) { } void PanelLayoutManager::FinishDragging() { - // Note, dragged panel may be null if the panel was just attached to the - // panel layout. dragged_panel_ = NULL; Relayout(); } diff --git a/ash/wm/panels/panel_layout_manager_unittest.cc b/ash/wm/panels/panel_layout_manager_unittest.cc index 0ab3022..a9c624a 100644 --- a/ash/wm/panels/panel_layout_manager_unittest.cc +++ b/ash/wm/panels/panel_layout_manager_unittest.cc @@ -208,6 +208,7 @@ class PanelLayoutManagerTest : public test::AshTestBase { aura::Window* window) { test::LauncherViewTestAPI test_api(launcher_view); test_api.SetAnimationDuration(1); + test_api.RunMessageLoopUntilAnimationsDone(); LauncherModel* model = test::ShellTestApi(Shell::GetInstance()).launcher_model(); @@ -477,13 +478,13 @@ TEST_F(PanelLayoutManagerTest, MinimizeRestorePanel) { TEST_F(PanelLayoutManagerTest, MAYBE_PanelMoveBetweenMultipleDisplays) { // Keep the displays wide so that launchers have enough // spaces for launcher buttons. - UpdateDisplay("500x400,500x400"); + UpdateDisplay("600x400,600x400"); Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); scoped_ptr p1_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50))); scoped_ptr p2_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50))); - scoped_ptr p1_d2(CreatePanelWindow(gfx::Rect(500, 0, 50, 50))); - scoped_ptr p2_d2(CreatePanelWindow(gfx::Rect(500, 0, 50, 50))); + scoped_ptr p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50))); + scoped_ptr p2_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50))); LauncherView* launcher_view_1st = Launcher::ForPrimaryDisplay()->GetLauncherViewForTest(); diff --git a/ash/wm/panels/panel_window_resizer.cc b/ash/wm/panels/panel_window_resizer.cc index e306f29..60044c3 100644 --- a/ash/wm/panels/panel_window_resizer.cc +++ b/ash/wm/panels/panel_window_resizer.cc @@ -53,6 +53,8 @@ void PanelWindowResizer::Drag(const gfx::Point& location, int event_flags) { did_move_or_resize_ = true; should_attach_ = AttachToLauncher(&bounds); details_.window->SetBounds(bounds); + if (should_attach_) + UpdateLauncherPosition(); } } @@ -149,4 +151,9 @@ void PanelWindowResizer::FinishDragging() { panel_layout_manager_->FinishDragging(); } +void PanelWindowResizer::UpdateLauncherPosition() { + panel_layout_manager_->launcher()->UpdateIconPositionForWindow( + details_.window); +} + } // namespace aura diff --git a/ash/wm/panels/panel_window_resizer.h b/ash/wm/panels/panel_window_resizer.h index 76657d3..5f3cc16 100644 --- a/ash/wm/panels/panel_window_resizer.h +++ b/ash/wm/panels/panel_window_resizer.h @@ -63,6 +63,9 @@ class ASH_EXPORT PanelWindowResizer : public WindowResizer { // of the drag start. void FinishDragging(); + // Updates the dragged panel's index in the launcher. + void UpdateLauncherPosition(); + const Details details_; // Panel container window. diff --git a/ash/wm/panels/panel_window_resizer_unittest.cc b/ash/wm/panels/panel_window_resizer_unittest.cc index 4be4645..785254d 100644 --- a/ash/wm/panels/panel_window_resizer_unittest.cc +++ b/ash/wm/panels/panel_window_resizer_unittest.cc @@ -5,6 +5,7 @@ #include "ash/wm/panels/panel_window_resizer.h" #include "ash/launcher/launcher.h" +#include "ash/launcher/launcher_model.h" #include "ash/root_window_controller.h" #include "ash/shelf/shelf_types.h" #include "ash/shelf/shelf_widget.h" @@ -12,12 +13,12 @@ #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ash/test/cursor_manager_test_api.h" +#include "ash/test/shell_test_api.h" #include "ash/test/test_launcher_delegate.h" #include "ash/wm/panels/panel_layout_manager.h" #include "ash/wm/window_properties.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/root_window.h" -#include "ui/aura/test/test_window_delegate.h" #include "ui/base/hit_test.h" #include "ui/base/ui_base_types.h" #include "ui/views/widget/widget.h" @@ -27,12 +28,13 @@ namespace internal { class PanelWindowResizerTest : public test::AshTestBase { public: - PanelWindowResizerTest() : window_(NULL) {} + PanelWindowResizerTest() {} virtual ~PanelWindowResizerTest() {} virtual void SetUp() OVERRIDE { AshTestBase::SetUp(); - window_.reset(CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); + test::ShellTestApi test_api(Shell::GetInstance()); + model_ = test_api.launcher_model(); panel_layout_manager_ = static_cast( GetPanelContainer()->layout_manager()); @@ -41,7 +43,6 @@ class PanelWindowResizerTest : public test::AshTestBase { } virtual void TearDown() OVERRIDE { - window_.reset(); AshTestBase::TearDown(); } @@ -84,9 +85,8 @@ class PanelWindowResizerTest : public test::AshTestBase { window, point_in_parent, window_component).release()); } - void DragStart() { - resizer_.reset(CreatePanelWindowResizer(window_.get(), gfx::Point(), - HTCAPTION)); + void DragStart(aura::Window* window) { + resizer_.reset(CreatePanelWindowResizer(window, gfx::Point(), HTCAPTION)); ASSERT_TRUE(resizer_.get()); } @@ -102,45 +102,89 @@ class PanelWindowResizerTest : public test::AshTestBase { // Test dragging the panel slightly, then detaching, and then reattaching // dragging out by the vector (dx, dy). void DetachReattachTest(int dx, int dy) { - EXPECT_TRUE(window_->GetProperty(kPanelAttachedKey)); - DragStart(); - gfx::Rect initial_bounds = window_->bounds(); + scoped_ptr window( + CreatePanelWindow(gfx::Rect(0, 0, 201, 201))); + EXPECT_TRUE(window->GetProperty(kPanelAttachedKey)); + DragStart(window.get()); + gfx::Rect initial_bounds = window->bounds(); // Drag the panel slightly. The window should still be snapped to the // launcher. DragMove(dx * 5, dy * 5); - EXPECT_EQ(initial_bounds.x(), window_->bounds().x()); - EXPECT_EQ(initial_bounds.y(), window_->bounds().y()); + EXPECT_EQ(initial_bounds.x(), window->bounds().x()); + EXPECT_EQ(initial_bounds.y(), window->bounds().y()); // Drag further out and the window should now move to the cursor. DragMove(dx * 100, dy * 100); - EXPECT_EQ(initial_bounds.x() + dx * 100, window_->bounds().x()); - EXPECT_EQ(initial_bounds.y() + dy * 100, window_->bounds().y()); + EXPECT_EQ(initial_bounds.x() + dx * 100, window->bounds().x()); + EXPECT_EQ(initial_bounds.y() + dy * 100, window->bounds().y()); // The panel should be detached when the drag completes. DragEnd(); - EXPECT_FALSE(window_->GetProperty(kPanelAttachedKey)); + EXPECT_FALSE(window->GetProperty(kPanelAttachedKey)); - DragStart(); + DragStart(window.get()); // Drag the panel down. DragMove(dx * -95, dy * -95); // Release the mouse and the panel should be reattached. DragEnd(); // The panel should be reattached and have snapped to the launcher. - EXPECT_TRUE(window_->GetProperty(kPanelAttachedKey)); - EXPECT_EQ(initial_bounds.x(), window_->bounds().x()); - EXPECT_EQ(initial_bounds.y(), window_->bounds().y()); + EXPECT_TRUE(window->GetProperty(kPanelAttachedKey)); + EXPECT_EQ(initial_bounds.x(), window->bounds().x()); + EXPECT_EQ(initial_bounds.y(), window->bounds().y()); } - aura::test::TestWindowDelegate delegate_; - scoped_ptr window_; + void TestWindowOrder(const std::vector& window_order) { + Launcher* launcher = Launcher::ForPrimaryDisplay(); + int panel_index = model_->FirstPanelIndex(); + EXPECT_EQ((int)(panel_index + window_order.size()), model_->item_count()); + for (std::vector::const_iterator iter = + window_order.begin(); iter != window_order.end(); + ++iter, ++panel_index) { + LauncherID id = launcher->delegate()->GetIDByWindow(*iter); + EXPECT_EQ(id, model_->items()[panel_index].id); + } + } + + // Test dragging panel window along the shelf and verify that panel icons + // are reordered appropriately. + void DragAlongShelfReorder(int dx, int dy) { + gfx::Rect bounds(0, 0, 201, 201); + scoped_ptr w1(CreatePanelWindow(bounds)); + scoped_ptr w2(CreatePanelWindow(bounds)); + std::vector window_order_original; + std::vector window_order_swapped; + window_order_original.push_back(w1.get()); + window_order_original.push_back(w2.get()); + window_order_swapped.push_back(w2.get()); + window_order_swapped.push_back(w1.get()); + TestWindowOrder(window_order_original); + + // Drag window #2 to the beginning of the shelf. + DragStart(w2.get()); + DragMove(400 * dx, 400 * dy); + DragEnd(); + + // Expect swapped window order. + TestWindowOrder(window_order_swapped); + + // Drag window #2 back to the end. + DragStart(w2.get()); + DragMove(-400 * dx, -400 * dy); + DragEnd(); + + // Expect original order. + TestWindowOrder(window_order_original); + } + + private: scoped_ptr resizer_; aura::Window* panel_container_; internal::PanelLayoutManager* panel_layout_manager_; gfx::Rect launcher_bounds_; + LauncherModel* model_; - private: DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTest); }; @@ -177,5 +221,15 @@ TEST_F(PanelWindowResizerTest, PanelDetachReattachTop) { DetachReattachTest(0, 1); } +TEST_F(PanelWindowResizerTest, DragReordersPanelsHorizontal) { + DragAlongShelfReorder(-1, 0); +} + +TEST_F(PanelWindowResizerTest, DragReordersPanelsVertical) { + ash::Shell* shell = ash::Shell::GetInstance(); + shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow()); + DragAlongShelfReorder(0, -1); +} + } // namespace internal } // namespace ash -- cgit v1.1