b91b34877dbe981cd9d4d6bd89ef17ddfa48cf16
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / tabs / tab_strip_model_order_controller.cc
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 }