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
IncrementFromImpl(int index,int * value)15 static void IncrementFromImpl(int index, int* value) {
16 if (*value >= index)
17 (*value)++;
18 }
19
DecrementFromImpl(int index,int * value)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
TabStripSelectionModel()30 TabStripSelectionModel::TabStripSelectionModel()
31 : active_(kUnselectedIndex),
32 anchor_(kUnselectedIndex) {
33 }
34
~TabStripSelectionModel()35 TabStripSelectionModel::~TabStripSelectionModel() {
36 }
37
IncrementFrom(int index)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
DecrementFrom(int index)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
SetSelectedIndex(int index)60 void TabStripSelectionModel::SetSelectedIndex(int index) {
61 anchor_ = active_ = index;
62 SetSelectionFromAnchorTo(index);
63 }
64
IsSelected(int index) const65 bool TabStripSelectionModel::IsSelected(int index) const {
66 return std::find(selected_indices_.begin(), selected_indices_.end(), index) !=
67 selected_indices_.end();
68 }
69
AddIndexToSelection(int index)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
RemoveIndexFromSelection(int index)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
SetSelectionFromAnchorTo(int index)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
AddSelectionFromAnchorTo(int index)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
Move(int from,int to)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
Clear()131 void TabStripSelectionModel::Clear() {
132 anchor_ = active_ = kUnselectedIndex;
133 SelectedIndices empty_selection;
134 selected_indices_.swap(empty_selection);
135 }
136
Copy(const TabStripSelectionModel & source)137 void TabStripSelectionModel::Copy(const TabStripSelectionModel& source) {
138 selected_indices_ = source.selected_indices_;
139 active_ = source.active_;
140 anchor_ = source.anchor_;
141 }
142