1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/tabs/tab_strip_selection_model.h" 6 7 #include <algorithm> 8 #include <valarray> 9 10 #include "base/logging.h" 11 12 // static 13 const int TabStripSelectionModel::kUnselectedIndex = -1; 14 15 static void IncrementFromImpl(int index, int* value) { 16 if (*value >= index) 17 (*value)++; 18 } 19 20 static bool DecrementFromImpl(int index, int* value) { 21 if (*value == index) { 22 *value = TabStripSelectionModel::kUnselectedIndex; 23 return true; 24 } 25 if (*value > index) 26 (*value)--; 27 return false; 28 } 29 30 TabStripSelectionModel::TabStripSelectionModel() 31 : active_(kUnselectedIndex), 32 anchor_(kUnselectedIndex) { 33 } 34 35 TabStripSelectionModel::~TabStripSelectionModel() { 36 } 37 38 void TabStripSelectionModel::IncrementFrom(int index) { 39 // Shift the selection to account for the newly inserted tab. 40 for (SelectedIndices::iterator i = selected_indices_.begin(); 41 i != selected_indices_.end(); ++i) { 42 IncrementFromImpl(index, &(*i)); 43 } 44 IncrementFromImpl(index, &anchor_); 45 IncrementFromImpl(index, &active_); 46 } 47 48 void TabStripSelectionModel::DecrementFrom(int index) { 49 for (SelectedIndices::iterator i = selected_indices_.begin(); 50 i != selected_indices_.end(); ) { 51 if (DecrementFromImpl(index, &(*i))) 52 i = selected_indices_.erase(i); 53 else 54 ++i; 55 } 56 DecrementFromImpl(index, &anchor_); 57 DecrementFromImpl(index, &active_); 58 } 59 60 void TabStripSelectionModel::SetSelectedIndex(int index) { 61 anchor_ = active_ = index; 62 SetSelectionFromAnchorTo(index); 63 } 64 65 bool TabStripSelectionModel::IsSelected(int index) const { 66 return std::find(selected_indices_.begin(), selected_indices_.end(), index) != 67 selected_indices_.end(); 68 } 69 70 void TabStripSelectionModel::AddIndexToSelection(int index) { 71 if (!IsSelected(index)) { 72 selected_indices_.push_back(index); 73 std::sort(selected_indices_.begin(), selected_indices_.end()); 74 } 75 } 76 77 void TabStripSelectionModel::RemoveIndexFromSelection(int index) { 78 SelectedIndices::iterator i = std::find(selected_indices_.begin(), 79 selected_indices_.end(), index); 80 if (i != selected_indices_.end()) 81 selected_indices_.erase(i); 82 } 83 84 void TabStripSelectionModel::SetSelectionFromAnchorTo(int index) { 85 if (anchor_ == kUnselectedIndex) { 86 SetSelectedIndex(index); 87 } else { 88 int delta = std::abs(index - anchor_); 89 SelectedIndices new_selection(delta + 1, 0); 90 for (int i = 0, min = std::min(index, anchor_); i <= delta; ++i) 91 new_selection[i] = i + min; 92 selected_indices_.swap(new_selection); 93 active_ = index; 94 } 95 } 96 97 void TabStripSelectionModel::AddSelectionFromAnchorTo(int index) { 98 if (anchor_ == kUnselectedIndex) { 99 SetSelectedIndex(index); 100 } else { 101 for (int i = std::min(index, anchor_), end = std::max(index, anchor_); 102 i <= end; ++i) { 103 if (!IsSelected(i)) 104 selected_indices_.push_back(i); 105 } 106 std::sort(selected_indices_.begin(), selected_indices_.end()); 107 active_ = index; 108 } 109 } 110 111 void TabStripSelectionModel::Move(int from, int to) { 112 DCHECK_NE(to, from); 113 bool was_anchor = from == anchor_; 114 bool was_active = from == active_; 115 bool was_selected = IsSelected(from); 116 if (to < from) { 117 IncrementFrom(to); 118 DecrementFrom(from + 1); 119 } else { 120 DecrementFrom(from); 121 IncrementFrom(to); 122 } 123 if (was_active) 124 active_ = to; 125 if (was_anchor) 126 anchor_ = to; 127 if (was_selected) 128 AddIndexToSelection(to); 129 } 130 131 void TabStripSelectionModel::Clear() { 132 anchor_ = active_ = kUnselectedIndex; 133 SelectedIndices empty_selection; 134 selected_indices_.swap(empty_selection); 135 } 136 137 void TabStripSelectionModel::Copy(const TabStripSelectionModel& source) { 138 selected_indices_ = source.selected_indices_; 139 active_ = source.active_; 140 anchor_ = source.anchor_; 141 } 142