Home | History | Annotate | Download | only in tabs
      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