• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 "ui/base/models/list_selection_model.h"
6 
7 #include <algorithm>
8 #include <valarray>
9 
10 #include "base/logging.h"
11 
12 namespace ui {
13 
14 // static
15 const int ListSelectionModel::kUnselectedIndex = -1;
16 
IncrementFromImpl(int index,int * value)17 static void IncrementFromImpl(int index, int* value) {
18   if (*value >= index)
19     (*value)++;
20 }
21 
DecrementFromImpl(int index,int * value)22 static bool DecrementFromImpl(int index, int* value) {
23   if (*value == index) {
24     *value = ListSelectionModel::kUnselectedIndex;
25     return true;
26   }
27   if (*value > index)
28     (*value)--;
29   return false;
30 }
31 
ListSelectionModel()32 ListSelectionModel::ListSelectionModel()
33     : active_(kUnselectedIndex),
34       anchor_(kUnselectedIndex) {
35 }
36 
~ListSelectionModel()37 ListSelectionModel::~ListSelectionModel() {
38 }
39 
IncrementFrom(int index)40 void ListSelectionModel::IncrementFrom(int index) {
41   // Shift the selection to account for the newly inserted tab.
42   for (SelectedIndices::iterator i = selected_indices_.begin();
43        i != selected_indices_.end(); ++i) {
44     IncrementFromImpl(index, &(*i));
45   }
46   IncrementFromImpl(index, &anchor_);
47   IncrementFromImpl(index, &active_);
48 }
49 
DecrementFrom(int index)50 void ListSelectionModel::DecrementFrom(int index) {
51   for (SelectedIndices::iterator i = selected_indices_.begin();
52        i != selected_indices_.end(); ) {
53     if (DecrementFromImpl(index, &(*i)))
54       i = selected_indices_.erase(i);
55     else
56       ++i;
57   }
58   DecrementFromImpl(index, &anchor_);
59   DecrementFromImpl(index, &active_);
60 }
61 
SetSelectedIndex(int index)62 void ListSelectionModel::SetSelectedIndex(int index) {
63   anchor_ = active_ = index;
64   selected_indices_.clear();
65   if (index != kUnselectedIndex)
66     selected_indices_.push_back(index);
67 }
68 
IsSelected(int index) const69 bool ListSelectionModel::IsSelected(int index) const {
70   return std::find(selected_indices_.begin(), selected_indices_.end(), index) !=
71       selected_indices_.end();
72 }
73 
AddIndexToSelection(int index)74 void ListSelectionModel::AddIndexToSelection(int index) {
75   if (!IsSelected(index)) {
76     selected_indices_.push_back(index);
77     std::sort(selected_indices_.begin(), selected_indices_.end());
78   }
79 }
80 
RemoveIndexFromSelection(int index)81 void ListSelectionModel::RemoveIndexFromSelection(int index) {
82   SelectedIndices::iterator i = std::find(selected_indices_.begin(),
83                                           selected_indices_.end(), index);
84   if (i != selected_indices_.end())
85     selected_indices_.erase(i);
86 }
87 
SetSelectionFromAnchorTo(int index)88 void ListSelectionModel::SetSelectionFromAnchorTo(int index) {
89   if (anchor_ == kUnselectedIndex) {
90     SetSelectedIndex(index);
91   } else {
92     int delta = std::abs(index - anchor_);
93     SelectedIndices new_selection(delta + 1, 0);
94     for (int i = 0, min = std::min(index, anchor_); i <= delta; ++i)
95       new_selection[i] = i + min;
96     selected_indices_.swap(new_selection);
97     active_ = index;
98   }
99 }
100 
AddSelectionFromAnchorTo(int index)101 void ListSelectionModel::AddSelectionFromAnchorTo(int index) {
102   if (anchor_ == kUnselectedIndex) {
103     SetSelectedIndex(index);
104   } else {
105     for (int i = std::min(index, anchor_), end = std::max(index, anchor_);
106          i <= end; ++i) {
107       if (!IsSelected(i))
108         selected_indices_.push_back(i);
109     }
110     std::sort(selected_indices_.begin(), selected_indices_.end());
111     active_ = index;
112   }
113 }
114 
Move(int from,int to)115 void ListSelectionModel::Move(int from, int to) {
116   DCHECK_NE(to, from);
117   bool was_anchor = from == anchor_;
118   bool was_active = from == active_;
119   bool was_selected = IsSelected(from);
120   if (to < from) {
121     IncrementFrom(to);
122     DecrementFrom(from + 1);
123   } else {
124     DecrementFrom(from);
125     IncrementFrom(to);
126   }
127   if (was_active)
128     active_ = to;
129   if (was_anchor)
130     anchor_ = to;
131   if (was_selected)
132     AddIndexToSelection(to);
133 }
134 
Clear()135 void ListSelectionModel::Clear() {
136   anchor_ = active_ = kUnselectedIndex;
137   SelectedIndices empty_selection;
138   selected_indices_.swap(empty_selection);
139 }
140 
Copy(const ListSelectionModel & source)141 void ListSelectionModel::Copy(const ListSelectionModel& source) {
142   selected_indices_ = source.selected_indices_;
143   active_ = source.active_;
144   anchor_ = source.anchor_;
145 }
146 
Equals(const ListSelectionModel & rhs) const147 bool ListSelectionModel::Equals(const ListSelectionModel& rhs) const {
148   return active_ == rhs.active() &&
149       anchor_ == rhs.anchor() &&
150       selected_indices() == rhs.selected_indices();
151 }
152 
153 }  // namespace ui
154