15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabStripModelOrderController, public: 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabStripModelOrderController::TabStripModelOrderController( 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel* tabstrip) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : tabstrip_(tabstrip) { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabstrip_->AddObserver(this); 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabStripModelOrderController::~TabStripModelOrderController() { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabstrip_->RemoveObserver(this); 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabStripModelOrderController::DetermineInsertionIndex( 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool foreground) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_count = tabstrip_->count(); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab_count) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: TabStripModel enforces that all non-mini-tabs occur after mini-tabs, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so we don't have to check here too. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transition == content::PAGE_TRANSITION_LINK && 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabstrip_->active_index() != -1) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (foreground) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the page was opened in the foreground by a link click in another 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tab, insert it adjacent to the tab that opened that link. 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return tabstrip_->active_index() + 1; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* opener = tabstrip_->GetActiveWebContents(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the index of the next item opened by this tab, and insert after 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it... 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index = tabstrip_->GetIndexOfLastWebContentsOpenedBy( 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) opener, tabstrip_->active_index()); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != TabStripModel::kNoTab) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return index + 1; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise insert adjacent to opener... 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return tabstrip_->active_index() + 1; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In other cases, such as Ctrl+T, open at the end of the strip. 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return tabstrip_->count(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabStripModelOrderController::DetermineNewSelectedIndex( 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int removing_index) const { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_count = tabstrip_->count(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(removing_index >= 0 && removing_index < tab_count); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* parent_opener = 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabstrip_->GetOpenerOfWebContentsAt(removing_index); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First see if the index being removed has any "child" tabs. If it does, we 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to select the first in that child group, not the next tab in the same 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // group of the removed tab. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* removed_contents = 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabstrip_->GetWebContentsAt(removing_index); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The parent opener should never be the same as the controller being removed. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(parent_opener != removed_contents); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = tabstrip_->GetIndexOfNextWebContentsOpenedBy(removed_contents, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removing_index, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != TabStripModel::kNoTab) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetValidIndex(index, removing_index); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent_opener) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the tab was in a group, shift selection to the next tab in the group. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = tabstrip_->GetIndexOfNextWebContentsOpenedBy(parent_opener, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removing_index, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != TabStripModel::kNoTab) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetValidIndex(index, removing_index); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we can't find a subsequent group member, just fall back to the 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parent_opener itself. Note that we use "group" here since opener is 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reset by select operations.. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = tabstrip_->GetIndexOfWebContents(parent_opener); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != TabStripModel::kNoTab) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetValidIndex(index, removing_index); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No opener set, fall through to the default handler... 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_index = tabstrip_->active_index(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selected_index >= (tab_count - 1)) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return selected_index - 1; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return selected_index; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModelOrderController::ActiveTabChanged( 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* old_contents, 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* new_contents, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int reason) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* old_opener = NULL; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_contents) { 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index = tabstrip_->GetIndexOfWebContents(old_contents); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != TabStripModel::kNoTab) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_opener = tabstrip_->GetOpenerOfWebContentsAt(index); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Forget any group/opener relationships that need to be reset whenever 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // selection changes (see comment in TabStripModel::AddWebContentsAt). 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tabstrip_->ShouldResetGroupOnSelect(old_contents)) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabstrip_->ForgetGroup(old_contents); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::WebContents* new_opener = tabstrip_->GetOpenerOfWebContentsAt(index); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ((reason & CHANGE_REASON_USER_GESTURE) && new_opener != old_opener && 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((old_contents == NULL && new_opener == NULL) || 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_opener != old_contents) && 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((new_contents == NULL && old_opener == NULL) || 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) old_opener != new_contents)) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabstrip_->ForgetAllOpeners(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabStripModelOrderController, private: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabStripModelOrderController::GetValidIndex( 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, int removing_index) const { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (removing_index < index) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = std::max(0, index - 1); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 132