diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-27 00:54:18 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-27 00:54:18 +0000 |
commit | e25a71ed5aa15c11c2a6fdeeae22413235b8f914 (patch) | |
tree | 0f88732ba20a720d837246606c5871a3f824a514 | |
parent | ec139f4d357a8966194178f6a0f18fcf46d512b1 (diff) | |
download | chromium_src-e25a71ed5aa15c11c2a6fdeeae22413235b8f914.zip chromium_src-e25a71ed5aa15c11c2a6fdeeae22413235b8f914.tar.gz chromium_src-e25a71ed5aa15c11c2a6fdeeae22413235b8f914.tar.bz2 |
Improves semantics for changing set of visible tabs on the touch tab
strip. Stills needs a bunch of work, but this is at least some what
usable.
BUG=123274
TEST=none
R=ben@chromium.org
Review URL: http://codereview.chromium.org/10231014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134194 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/ui/views/tabs/default_tab_drag_controller.cc | 60 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/default_tab_drag_controller.h | 16 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_controller.h | 2 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_drag_controller.h | 11 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_strip.cc | 33 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/tab_strip.h | 9 | ||||
-rw-r--r-- | chrome/browser/ui/views/tabs/touch_tab_strip_layout.cc | 2 | ||||
-rw-r--r-- | ui/views/view_model_utils.cc | 10 | ||||
-rw-r--r-- | ui/views/view_model_utils.h | 3 |
9 files changed, 109 insertions, 37 deletions
diff --git a/chrome/browser/ui/views/tabs/default_tab_drag_controller.cc b/chrome/browser/ui/views/tabs/default_tab_drag_controller.cc index 9ee3bb7..02132c6 100644 --- a/chrome/browser/ui/views/tabs/default_tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/default_tab_drag_controller.cc @@ -21,6 +21,7 @@ #include "chrome/browser/ui/views/tabs/native_view_photobooth.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" +#include "chrome/browser/ui/views/tabs/touch_tab_strip_layout.h" #include "chrome/common/chrome_switches.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" @@ -320,8 +321,7 @@ DefaultTabDragController::DefaultTabDragController() active_(true), source_tab_index_(std::numeric_limits<size_t>::max()), initial_move_(true), - // TODO: remove. - stacking_(false) { + move_only_(false) { instance_ = this; } @@ -348,13 +348,21 @@ void DefaultTabDragController::Init( const std::vector<BaseTab*>& tabs, const gfx::Point& mouse_offset, int source_tab_offset, - const TabStripSelectionModel& initial_selection_model) { + const TabStripSelectionModel& initial_selection_model, + bool move_only) { DCHECK(!tabs.empty()); DCHECK(std::find(tabs.begin(), tabs.end(), source_tab) != tabs.end()); source_tabstrip_ = source_tabstrip; source_tab_offset_ = source_tab_offset; start_screen_point_ = GetCursorScreenPoint(); mouse_offset_ = mouse_offset; + move_only_ = move_only; + + if (move_only_) { + last_move_screen_loc_ = + MajorAxisValue(start_screen_point_, attached_tabstrip_); + initial_tab_positions_ = source_tabstrip->GetTabXCoordinates(); + } drag_data_.resize(tabs.size()); for (size_t i = 0; i < tabs.size(); ++i) @@ -645,19 +653,14 @@ void DefaultTabDragController::ContinueDragging() { // guaranteed to be correct regardless of monitor config. gfx::Point screen_point = GetCursorScreenPoint(); + // TODO(sky): this file shouldn't be built on chromeos. #if defined(OS_WIN) && !defined(USE_AURA) - // Currently only allowed on windows (and not aura). - // Determine whether or not we have dragged over a compatible TabStrip in - // another browser window. If we have, we should attach to it and start - // dragging within it. - // TODO(scottmg): Determine design for when tabs should actually detach when - // in stacking mode. - TabStrip* target_tabstrip = stacking_ ? - source_tabstrip_ : - GetTabStripForPoint(screen_point); + TabStrip* target_tabstrip = move_only_ ? + source_tabstrip_ : GetTabStripForPoint(screen_point); #else TabStrip* target_tabstrip = source_tabstrip_; #endif + if (target_tabstrip != attached_tabstrip_) { // Make sure we're fully detached from whatever TabStrip we're attached to // (if any). @@ -674,10 +677,24 @@ void DefaultTabDragController::ContinueDragging() { UpdateDockInfo(screen_point); - if (attached_tabstrip_) - MoveAttached(screen_point); - else + if (attached_tabstrip_) { + if (move_only_) + MoveAttachedStacked(screen_point); + else + MoveAttached(screen_point); + } else { MoveDetached(screen_point); + } +} + +void DefaultTabDragController::MoveAttachedStacked( + const gfx::Point& screen_point) { + if (attached_tabstrip_->tab_count() != + static_cast<int>(initial_tab_positions_.size())) + return; // TODO: should cancel drag if this happens. + + int delta = screen_point.x() - start_screen_point_.x(); + attached_tabstrip_->DragActiveTab(initial_tab_positions_, delta); } void DefaultTabDragController::MoveAttached(const gfx::Point& screen_point) { @@ -704,7 +721,7 @@ void DefaultTabDragController::MoveAttached(const gfx::Point& screen_point) { // Update the model, moving the WebContents from one index to another. Do this // only if we have moved a minimum distance since the last reorder (to prevent // jitter) or if this the first move and the tabs are not consecutive. - if (!stacking_ && (abs(MajorAxisValue(screen_point, attached_tabstrip_) - + if ((abs(MajorAxisValue(screen_point, attached_tabstrip_) - last_move_screen_loc_) > threshold || (initial_move_ && !AreTabsConsecutive()))) { TabStripModel* attached_model = GetModel(attached_tabstrip_); @@ -1033,11 +1050,6 @@ gfx::Point DefaultTabDragController::GetAttachedDragPoint( attached_tabstrip_->GetMirroredXInView(tab_loc.x()) - mouse_offset_.x(); int y = tab_loc.y() - mouse_offset_.y(); - // Don't limit the edge of tab strip when stacking so tabs can be pulled past - // the edge to stack. - if (stacking_) - return gfx::Point(x, 0); - // TODO: consider caching this. std::vector<BaseTab*> attached_tabs; for (size_t i = 0; i < drag_data_.size(); ++i) @@ -1447,10 +1459,12 @@ TabDragController* TabDragController::Create( const std::vector<BaseTab*>& tabs, const gfx::Point& mouse_offset, int source_tab_offset, - const TabStripSelectionModel& initial_selection_model) { + const TabStripSelectionModel& initial_selection_model, + bool move_only) { #if defined(USE_AURA) || defined(OS_WIN) if (ShouldCreateTabDragController2()) { TabDragController2* controller = new TabDragController2; + // TODO: get TabDragController2 working with move_only. controller->Init(source_tabstrip, source_tab, tabs, mouse_offset, source_tab_offset, initial_selection_model); return controller; @@ -1458,7 +1472,7 @@ TabDragController* TabDragController::Create( #endif DefaultTabDragController* controller = new DefaultTabDragController; controller->Init(source_tabstrip, source_tab, tabs, mouse_offset, - source_tab_offset, initial_selection_model); + source_tab_offset, initial_selection_model, move_only); return controller; } diff --git a/chrome/browser/ui/views/tabs/default_tab_drag_controller.h b/chrome/browser/ui/views/tabs/default_tab_drag_controller.h index 33e909b..6be30e7 100644 --- a/chrome/browser/ui/views/tabs/default_tab_drag_controller.h +++ b/chrome/browser/ui/views/tabs/default_tab_drag_controller.h @@ -48,12 +48,14 @@ class DefaultTabDragController : public TabDragController, // for a horizontal tab strip, and the vertical distance for a vertical tab // strip. |initial_selection_model| is the selection model before the drag // started and is only non-empty if |source_tab| was not initially selected. + // TODO(sky): clean up move_only. void Init(TabStrip* source_tabstrip, BaseTab* source_tab, const std::vector<BaseTab*>& tabs, const gfx::Point& mouse_offset, int source_tab_offset, - const TabStripSelectionModel& initial_selection_model); + const TabStripSelectionModel& initial_selection_model, + bool move_only); // See description above fields for details on these. bool active() const { return active_; } @@ -167,6 +169,10 @@ class DefaultTabDragController : public TabDragController, // potentially updating the source and other TabStrips. void ContinueDragging(); + // Handles dragging for a touch tabstrip when the tabs are stacked. Doesn't + // actually reorder the tabs in anyway, just changes what's visible. + void MoveAttachedStacked(const gfx::Point& screen_point); + // Handles dragging tabs while the tabs are attached. void MoveAttached(const gfx::Point& screen_point); @@ -361,8 +367,12 @@ class DefaultTabDragController : public TabDragController, // The selection model of |attached_tabstrip_| before the tabs were attached. TabStripSelectionModel selection_model_before_attach_; - // Are we operating with tabs stacking/scrolling? - bool stacking_; + // Initial x-coordinates of the tabs when the drag started. Only used for + // touch mode. + std::vector<int> initial_tab_positions_; + + // TODO(sky): clean up. + bool move_only_; DISALLOW_COPY_AND_ASSIGN(DefaultTabDragController); }; diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index 0e2583f..054fd2d 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h @@ -58,7 +58,7 @@ class TabController { // Potentially starts a drag for the specified Tab. virtual void MaybeStartDrag( BaseTab* tab, - const views::MouseEvent& event, + const views::LocatedEvent& event, const TabStripSelectionModel& original_selection) = 0; // Continues dragging a Tab. diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h index 68e9211..7d0df87 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.h +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h @@ -35,17 +35,18 @@ class TabDragController { // the drag (the one the user pressed the moused down on) and is contained in // |tabs|. |mouse_offset| is the distance of the mouse pointer from the // origin of the first tab in |tabs| and |source_tab_offset| the offset from - // |source_tab|. |source_tab_offset| is the horizontal distant for a - // horizontal tab strip, and the vertical distance for a vertical tab - // strip. |initial_selection_model| is the selection model before the drag - // started and is only non-empty if |source_tab| was not initially selected. + // |source_tab| (along the horizontal axis). |initial_selection_model| is the + // selection model before the drag started and is only non-empty if + // |source_tab| was not initially selected. |move_only| is true if the drag + // is the result of a touch event. static TabDragController* Create( TabStrip* source_tabstrip, BaseTab* source_tab, const std::vector<BaseTab*>& tabs, const gfx::Point& mouse_offset, int source_tab_offset, - const TabStripSelectionModel& initial_selection_model); + const TabStripSelectionModel& initial_selection_model, + bool move_only); // Returns true if there is a drag underway and the drag is attached to // |tab_strip|. diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 6ded840..449fe44 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc @@ -590,8 +590,12 @@ void TabStrip::SetSelection(const TabStripSelectionModel& old_selection, const TabStripSelectionModel& new_selection) { if (touch_layout_.get()) { touch_layout_->SetActiveIndex(new_selection.active()); + // Only start an animation if we need to. Otherwise clicking on an + // unselected tab and dragging won't work because dragging is only allowed + // if not animating. + if (!views::ViewModelUtils::IsAtIdealBounds(tabs_)) + AnimateToIdealBounds(); SchedulePaint(); - AnimateToIdealBounds(); } else { // We have "tiny tabs" if the tabs are so tiny that the unselected ones are // a different size to the selected ones. @@ -749,7 +753,7 @@ bool TabStrip::IsTabCloseable(const BaseTab* tab) const { void TabStrip::MaybeStartDrag( BaseTab* tab, - const views::MouseEvent& event, + const views::LocatedEvent& event, const TabStripSelectionModel& original_selection) { // Don't accidentally start any drag operations during animations if the // mouse is down... during an animation tabs are being resized automatically, @@ -791,7 +795,10 @@ void TabStrip::MaybeStartDrag( drag_controller_.reset(); drag_controller_.reset(TabDragController::Create( this, tab, tabs, gfx::Point(x, y), tab->GetMirroredXInView(event.x()), - selection_model)); + selection_model, touch_layout_.get() != NULL)); + // TODO: Instead of touch layout need to look at event type, eg + // event.type() == ui::ET_TOUCH_PRESSED)), and need to plumb through long + // press and touch stuff. } void TabStrip::ContinueDrag(const views::MouseEvent& event) { @@ -1290,6 +1297,19 @@ void TabStrip::DoLayout() { newtab_button_->SetBoundsRect(newtab_button_bounds_); } +void TabStrip::DragActiveTab(const std::vector<int>& initial_positions, + int delta) { + DCHECK(touch_layout_.get()); + DCHECK_EQ(tab_count(), static_cast<int>(initial_positions.size())); + for (int i = 0; i < tab_count(); ++i) { + gfx::Rect bounds(ideal_bounds(i)); + bounds.set_x(initial_positions[i]); + set_ideal_bounds(i, bounds); + } + touch_layout_->DragActiveTab(delta); + DoLayout(); +} + void TabStrip::LayoutDraggedTabsAt(const std::vector<BaseTab*>& tabs, BaseTab* active_tab, const gfx::Point& location, @@ -1917,3 +1937,10 @@ Tab* TabStrip::FindTabForEvent(const gfx::Point& point, int start, int delta) { } return NULL; } + +std::vector<int> TabStrip::GetTabXCoordinates() { + std::vector<int> results; + for (int i = 0; i < tab_count(); ++i) + results.push_back(ideal_bounds(i).x()); + return results; +} diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 80fab67..27e8168 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h @@ -147,7 +147,7 @@ class TabStrip : public AbstractTabStripView, virtual bool IsTabCloseable(const BaseTab* tab) const OVERRIDE; virtual void MaybeStartDrag( BaseTab* tab, - const views::MouseEvent& event, + const views::LocatedEvent& event, const TabStripSelectionModel& original_selection) OVERRIDE; virtual void ContinueDrag(const views::MouseEvent& event) OVERRIDE; virtual bool EndDrag(bool canceled) OVERRIDE; @@ -271,6 +271,10 @@ class TabStrip : public AbstractTabStripView, // Invoked from Layout if the size changes or layout is really needed. void DoLayout(); + // Drags the active tab by |delta|. |initial_positions| is the x-coordinates + // of the tabs when the drag started. + void DragActiveTab(const std::vector<int>& initial_positions, int delta); + // Invoked during drag to layout the tabs being dragged in |tabs| at // |location|. If |initial_drag| is true, this is the initial layout after the // user moved the mouse far enough to trigger a drag. @@ -418,6 +422,9 @@ class TabStrip : public AbstractTabStripView, // iterating by |delta|. Tab* FindTabForEvent(const gfx::Point& point, int start, int delta); + // Returns the x-coordinates of the tabs. + std::vector<int> GetTabXCoordinates(); + // -- Member Variables ------------------------------------------------------ // There is a one-to-one mapping between each of the tabs in the diff --git a/chrome/browser/ui/views/tabs/touch_tab_strip_layout.cc b/chrome/browser/ui/views/tabs/touch_tab_strip_layout.cc index 3cfda68..c96c37f 100644 --- a/chrome/browser/ui/views/tabs/touch_tab_strip_layout.cc +++ b/chrome/browser/ui/views/tabs/touch_tab_strip_layout.cc @@ -60,7 +60,7 @@ void TouchTabStripLayout::SetActiveIndex(int index) { } void TouchTabStripLayout::DragActiveTab(int delta) { - if (delta == 0 && !requires_stacking()) + if (delta == 0 || !requires_stacking()) return; int initial_x = ideal_x(active_index()); // If we're at a particular edge and start dragging, reset to ideal state. diff --git a/ui/views/view_model_utils.cc b/ui/views/view_model_utils.cc index a49fbcd..addeee7 100644 --- a/ui/views/view_model_utils.cc +++ b/ui/views/view_model_utils.cc @@ -18,6 +18,16 @@ void ViewModelUtils::SetViewBoundsToIdealBounds(const ViewModel& model) { } // static +bool ViewModelUtils::IsAtIdealBounds(const ViewModel& model) { + for (int i = 0; i < model.view_size(); ++i) { + View* view = model.view_at(i); + if (view->bounds() != model.ideal_bounds(i)) + return false; + } + return true; +} + +// static int ViewModelUtils::DetermineMoveIndex(const ViewModel& model, View* view, int x) { diff --git a/ui/views/view_model_utils.h b/ui/views/view_model_utils.h index 5219ff8..d7f8bd3 100644 --- a/ui/views/view_model_utils.h +++ b/ui/views/view_model_utils.h @@ -19,6 +19,9 @@ class VIEWS_EXPORT ViewModelUtils { // Sets the bounds of each view to its ideal bounds. static void SetViewBoundsToIdealBounds(const ViewModel& model); + // Returns true if the Views in |model| are at their ideal bounds. + static bool IsAtIdealBounds(const ViewModel& model); + // Returns the index to move |view| to based on a x-coordinate of |x|. static int DetermineMoveIndex(const ViewModel& model, View* view, |