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