Home | History | Annotate | Download | only in models
      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 
     17 static void IncrementFromImpl(int index, int* value) {
     18   if (*value >= index)
     19     (*value)++;
     20 }
     21 
     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 
     32 ListSelectionModel::ListSelectionModel()
     33     : active_(kUnselectedIndex),
     34       anchor_(kUnselectedIndex) {
     35 }
     36 
     37 ListSelectionModel::~ListSelectionModel() {
     38 }
     39 
     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 
     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 
     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 
     69 bool ListSelectionModel::IsSelected(int index) const {
     70   return std::find(selected_indices_.begin(), selected_indices_.end(), index) !=
     71       selected_indices_.end();
     72 }
     73 
     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 
     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 
     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 
    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 
    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 
    135 void ListSelectionModel::Clear() {
    136   anchor_ = active_ = kUnselectedIndex;
    137   SelectedIndices empty_selection;
    138   selected_indices_.swap(empty_selection);
    139 }
    140 
    141 void ListSelectionModel::Copy(const ListSelectionModel& source) {
    142   selected_indices_ = source.selected_indices_;
    143   active_ = source.active_;
    144   anchor_ = source.anchor_;
    145 }
    146 
    147 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