Index: ios/chrome/browser/tabs/tab_model_order_controller.mm |
diff --git a/ios/chrome/browser/tabs/tab_model_order_controller.mm b/ios/chrome/browser/tabs/tab_model_order_controller.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..215540b6c9312f9f7e333c033207985d7e76b909 |
--- /dev/null |
+++ b/ios/chrome/browser/tabs/tab_model_order_controller.mm |
@@ -0,0 +1,104 @@ |
+// Copyright 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "ios/chrome/browser/tabs/tab_model_order_controller.h" |
+ |
+#include "base/logging.h" |
+ |
+@implementation TabModelOrderController |
+ |
+@synthesize insertionPolicy = insertionPolicy_; |
+ |
+- (id)initWithTabModel:(TabModel*)model { |
+ DCHECK(model); |
+ self = [super init]; |
+ if (self) { |
+ model_ = model; |
+ insertionPolicy_ = TabModelOrderConstants::kInsertAfter; |
+ } |
+ return self; |
+} |
+ |
+- (NSUInteger)insertionIndexForTab:(Tab*)newTab |
+ transition:(ui::PageTransition)transition |
+ opener:(Tab*)parentTab |
+ adjacency:(TabModelOrderConstants::InsertionAdjacency) |
+ adjacency { |
+ if (model_.isEmpty) |
+ return 0; |
+ |
+ if (PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_LINK) && |
+ parentTab) { |
+ NSUInteger referenceIndex = [model_ indexOfTab:parentTab]; |
+ Tab* openLocation = nil; |
+ if (insertionPolicy_ == TabModelOrderConstants::kInsertAfter) { |
+ openLocation = [model_ lastTabWithOpener:parentTab]; |
+ } else { |
+ openLocation = [model_ firstTabWithOpener:parentTab]; |
+ } |
+ if (openLocation) |
+ referenceIndex = [model_ indexOfTab:openLocation]; |
+ |
+ // If the reference tab is no longer in the model (e.g., it was closed |
+ // before the open request was handled), fall through to default behavior. |
+ if (referenceIndex != NSNotFound) { |
+ BOOL insertAfter = |
+ insertionPolicy_ == TabModelOrderConstants::kInsertAfter || |
+ adjacency == TabModelOrderConstants::kAdjacentAfter; |
+ NSUInteger delta = insertAfter ? 1 : 0; |
+ return referenceIndex + delta; |
+ } |
+ } |
+ // In other cases, such as a normal new tab, open at the end. |
+ return [self insertionIndexForAppending]; |
+} |
+ |
+- (NSUInteger)insertionIndexForAppending { |
+ return insertionPolicy_ == TabModelOrderConstants::kInsertAfter ? model_.count |
+ : 0; |
+} |
+ |
+- (Tab*)determineNewSelectedTabFromRemovedTab:(Tab*)removedTab { |
+ // While the desktop version of this code deals in indices, this deals in |
+ // actual tabs. As a result, the tab only needs to change iff the selection |
+ // is the tab that's removed. |
+ if (removedTab != model_.currentTab) |
+ return model_.currentTab; |
+ |
+ const NSUInteger numberOfTabs = model_.count; |
+ if (numberOfTabs < 2) |
+ return nil; |
+ DCHECK(numberOfTabs >= 2); |
+ DCHECK(removedTab == model_.currentTab); |
+ |
+ // First see if the tab being removed has any "child" tabs. If it does, we |
+ // want to select the first in that child group, not the next tab in the same |
+ // group of the removed tab. |
+ Tab* firstChild = [model_ nextTabWithOpener:removedTab afterTab:nil]; |
+ if (firstChild) |
+ return firstChild; |
+ Tab* parentTab = [model_ openerOfTab:removedTab]; |
+ if (parentTab) { |
+ // If the tab was in a group, shift selection to the next tab in the group. |
+ Tab* nextTab = [model_ nextTabWithOpener:parentTab afterTab:removedTab]; |
+ if (nextTab) |
+ return nextTab; |
+ |
+ // If we can't find a subsequent group member, just fall back to the |
+ // parentTab itself. Note that we use "group" here since opener is |
+ // reset by select operations. |
+ return parentTab; |
+ } |
+ |
+ // No opener set, fall through to the default handler... |
+ NSUInteger selectedIndex = [model_ indexOfTab:removedTab]; |
+ DCHECK(selectedIndex <= numberOfTabs - 1); |
+ // Is the closing tab the last one? If so, return the penultimate tab. |
+ if (selectedIndex == numberOfTabs - 1) |
+ return [model_ tabAtIndex:selectedIndex - 1]; |
+ // Otherwise return the next tab after the current tab. |
+ return [model_ tabAtIndex:selectedIndex + 1]; |
+} |
+ |
+@end |