Home | History | Annotate | Download | only in tabs
      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 "chrome/browser/ui/tabs/tab_strip_model_order_controller.h"
      6 
      7 #include "content/public/browser/web_contents.h"
      8 
      9 ///////////////////////////////////////////////////////////////////////////////
     10 // TabStripModelOrderController, public:
     11 
     12 TabStripModelOrderController::TabStripModelOrderController(
     13     TabStripModel* tabstrip)
     14     : tabstrip_(tabstrip) {
     15   tabstrip_->AddObserver(this);
     16 }
     17 
     18 TabStripModelOrderController::~TabStripModelOrderController() {
     19   tabstrip_->RemoveObserver(this);
     20 }
     21 
     22 int TabStripModelOrderController::DetermineInsertionIndex(
     23     ui::PageTransition transition,
     24     bool foreground) {
     25   int tab_count = tabstrip_->count();
     26   if (!tab_count)
     27     return 0;
     28 
     29   // NOTE: TabStripModel enforces that all non-mini-tabs occur after mini-tabs,
     30   // so we don't have to check here too.
     31   if (transition == ui::PAGE_TRANSITION_LINK &&
     32       tabstrip_->active_index() != -1) {
     33     if (foreground) {
     34       // If the page was opened in the foreground by a link click in another
     35       // tab, insert it adjacent to the tab that opened that link.
     36       return tabstrip_->active_index() + 1;
     37     }
     38     content::WebContents* opener = tabstrip_->GetActiveWebContents();
     39     // Get the index of the next item opened by this tab, and insert after
     40     // it...
     41     int index = tabstrip_->GetIndexOfLastWebContentsOpenedBy(
     42         opener, tabstrip_->active_index());
     43     if (index != TabStripModel::kNoTab)
     44       return index + 1;
     45     // Otherwise insert adjacent to opener...
     46     return tabstrip_->active_index() + 1;
     47   }
     48   // In other cases, such as Ctrl+T, open at the end of the strip.
     49   return tabstrip_->count();
     50 }
     51 
     52 int TabStripModelOrderController::DetermineNewSelectedIndex(
     53     int removing_index) const {
     54   int tab_count = tabstrip_->count();
     55   DCHECK(removing_index >= 0 && removing_index < tab_count);
     56   content::WebContents* parent_opener =
     57       tabstrip_->GetOpenerOfWebContentsAt(removing_index);
     58   // First see if the index being removed has any "child" tabs. If it does, we
     59   // want to select the first in that child group, not the next tab in the same
     60   // group of the removed tab.
     61   content::WebContents* removed_contents =
     62       tabstrip_->GetWebContentsAt(removing_index);
     63   // The parent opener should never be the same as the controller being removed.
     64   DCHECK(parent_opener != removed_contents);
     65   int index = tabstrip_->GetIndexOfNextWebContentsOpenedBy(removed_contents,
     66                                                            removing_index,
     67                                                            false);
     68   if (index != TabStripModel::kNoTab)
     69     return GetValidIndex(index, removing_index);
     70 
     71   if (parent_opener) {
     72     // If the tab was in a group, shift selection to the next tab in the group.
     73     int index = tabstrip_->GetIndexOfNextWebContentsOpenedBy(parent_opener,
     74                                                              removing_index,
     75                                                              false);
     76     if (index != TabStripModel::kNoTab)
     77       return GetValidIndex(index, removing_index);
     78 
     79     // If we can't find a subsequent group member, just fall back to the
     80     // parent_opener itself. Note that we use "group" here since opener is
     81     // reset by select operations..
     82     index = tabstrip_->GetIndexOfWebContents(parent_opener);
     83     if (index != TabStripModel::kNoTab)
     84       return GetValidIndex(index, removing_index);
     85   }
     86 
     87   // No opener set, fall through to the default handler...
     88   int selected_index = tabstrip_->active_index();
     89   if (selected_index >= (tab_count - 1))
     90     return selected_index - 1;
     91 
     92   return selected_index;
     93 }
     94 
     95 void TabStripModelOrderController::ActiveTabChanged(
     96     content::WebContents* old_contents,
     97     content::WebContents* new_contents,
     98     int index,
     99     int reason) {
    100   content::WebContents* old_opener = NULL;
    101   if (old_contents) {
    102     int index = tabstrip_->GetIndexOfWebContents(old_contents);
    103     if (index != TabStripModel::kNoTab) {
    104       old_opener = tabstrip_->GetOpenerOfWebContentsAt(index);
    105 
    106       // Forget any group/opener relationships that need to be reset whenever
    107       // selection changes (see comment in TabStripModel::AddWebContentsAt).
    108       if (tabstrip_->ShouldResetGroupOnSelect(old_contents))
    109         tabstrip_->ForgetGroup(old_contents);
    110     }
    111   }
    112   content::WebContents* new_opener = tabstrip_->GetOpenerOfWebContentsAt(index);
    113 
    114   if ((reason & CHANGE_REASON_USER_GESTURE) && new_opener != old_opener &&
    115       ((old_contents == NULL && new_opener == NULL) ||
    116           new_opener != old_contents) &&
    117       ((new_contents == NULL && old_opener == NULL) ||
    118           old_opener != new_contents)) {
    119     tabstrip_->ForgetAllOpeners();
    120   }
    121 }
    122 
    123 ///////////////////////////////////////////////////////////////////////////////
    124 // TabStripModelOrderController, private:
    125 
    126 int TabStripModelOrderController::GetValidIndex(
    127     int index, int removing_index) const {
    128   if (removing_index < index)
    129     index = std::max(0, index - 1);
    130   return index;
    131 }
    132