| // 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/tabs/tab_strip_selection_model.h" |
| |
| #include <algorithm> |
| #include <valarray> |
| |
| #include "base/logging.h" |
| |
| // static |
| const int TabStripSelectionModel::kUnselectedIndex = -1; |
| |
| static void IncrementFromImpl(int index, int* value) { |
| if (*value >= index) |
| (*value)++; |
| } |
| |
| static bool DecrementFromImpl(int index, int* value) { |
| if (*value == index) { |
| *value = TabStripSelectionModel::kUnselectedIndex; |
| return true; |
| } |
| if (*value > index) |
| (*value)--; |
| return false; |
| } |
| |
| TabStripSelectionModel::TabStripSelectionModel() |
| : active_(kUnselectedIndex), |
| anchor_(kUnselectedIndex) { |
| } |
| |
| TabStripSelectionModel::~TabStripSelectionModel() { |
| } |
| |
| void TabStripSelectionModel::IncrementFrom(int index) { |
| // Shift the selection to account for the newly inserted tab. |
| for (SelectedIndices::iterator i = selected_indices_.begin(); |
| i != selected_indices_.end(); ++i) { |
| IncrementFromImpl(index, &(*i)); |
| } |
| IncrementFromImpl(index, &anchor_); |
| IncrementFromImpl(index, &active_); |
| } |
| |
| void TabStripSelectionModel::DecrementFrom(int index) { |
| for (SelectedIndices::iterator i = selected_indices_.begin(); |
| i != selected_indices_.end(); ) { |
| if (DecrementFromImpl(index, &(*i))) |
| i = selected_indices_.erase(i); |
| else |
| ++i; |
| } |
| DecrementFromImpl(index, &anchor_); |
| DecrementFromImpl(index, &active_); |
| } |
| |
| void TabStripSelectionModel::SetSelectedIndex(int index) { |
| anchor_ = active_ = index; |
| SetSelectionFromAnchorTo(index); |
| } |
| |
| bool TabStripSelectionModel::IsSelected(int index) const { |
| return std::find(selected_indices_.begin(), selected_indices_.end(), index) != |
| selected_indices_.end(); |
| } |
| |
| void TabStripSelectionModel::AddIndexToSelection(int index) { |
| if (!IsSelected(index)) { |
| selected_indices_.push_back(index); |
| std::sort(selected_indices_.begin(), selected_indices_.end()); |
| } |
| } |
| |
| void TabStripSelectionModel::RemoveIndexFromSelection(int index) { |
| SelectedIndices::iterator i = std::find(selected_indices_.begin(), |
| selected_indices_.end(), index); |
| if (i != selected_indices_.end()) |
| selected_indices_.erase(i); |
| } |
| |
| void TabStripSelectionModel::SetSelectionFromAnchorTo(int index) { |
| if (anchor_ == kUnselectedIndex) { |
| SetSelectedIndex(index); |
| } else { |
| int delta = std::abs(index - anchor_); |
| SelectedIndices new_selection(delta + 1, 0); |
| for (int i = 0, min = std::min(index, anchor_); i <= delta; ++i) |
| new_selection[i] = i + min; |
| selected_indices_.swap(new_selection); |
| active_ = index; |
| } |
| } |
| |
| void TabStripSelectionModel::AddSelectionFromAnchorTo(int index) { |
| if (anchor_ == kUnselectedIndex) { |
| SetSelectedIndex(index); |
| } else { |
| for (int i = std::min(index, anchor_), end = std::max(index, anchor_); |
| i <= end; ++i) { |
| if (!IsSelected(i)) |
| selected_indices_.push_back(i); |
| } |
| std::sort(selected_indices_.begin(), selected_indices_.end()); |
| active_ = index; |
| } |
| } |
| |
| void TabStripSelectionModel::Move(int from, int to) { |
| DCHECK_NE(to, from); |
| bool was_anchor = from == anchor_; |
| bool was_active = from == active_; |
| bool was_selected = IsSelected(from); |
| if (to < from) { |
| IncrementFrom(to); |
| DecrementFrom(from + 1); |
| } else { |
| DecrementFrom(from); |
| IncrementFrom(to); |
| } |
| if (was_active) |
| active_ = to; |
| if (was_anchor) |
| anchor_ = to; |
| if (was_selected) |
| AddIndexToSelection(to); |
| } |
| |
| void TabStripSelectionModel::Clear() { |
| anchor_ = active_ = kUnselectedIndex; |
| SelectedIndices empty_selection; |
| selected_indices_.swap(empty_selection); |
| } |
| |
| void TabStripSelectionModel::Copy(const TabStripSelectionModel& source) { |
| selected_indices_ = source.selected_indices_; |
| active_ = source.active_; |
| anchor_ = source.anchor_; |
| } |