| Index: ios/chrome/browser/ui/history/tab_history_popup_controller.mm
|
| diff --git a/ios/chrome/browser/ui/history/tab_history_popup_controller.mm b/ios/chrome/browser/ui/history/tab_history_popup_controller.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ca1d9623e56d62078d2f121ca6f4f9afdafd4c9d
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/history/tab_history_popup_controller.mm
|
| @@ -0,0 +1,174 @@
|
| +// 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/ui/history/tab_history_popup_controller.h"
|
| +
|
| +#import <QuartzCore/QuartzCore.h>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/mac/bundle_locations.h"
|
| +#include "base/mac/objc_property_releaser.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#import "ios/chrome/browser/ui/history/tab_history_view_controller.h"
|
| +#import "ios/chrome/browser/ui/popup_menu/popup_menu_view.h"
|
| +#include "ios/chrome/browser/ui/rtl_geometry.h"
|
| +#include "ios/chrome/browser/ui/ui_util.h"
|
| +#import "ios/chrome/common/material_timing.h"
|
| +#import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoFontLoader.h"
|
| +#import "ios/web/navigation/crw_session_entry.h"
|
| +#include "ios/web/public/navigation_item.h"
|
| +#import "ui/gfx/ios/NSString+CrStringDrawing.h"
|
| +#include "ui/gfx/ios/uikit_util.h"
|
| +
|
| +namespace {
|
| +static const CGFloat kTabHistoryMinWidth = 250.0;
|
| +static const CGFloat kTabHistoryMaxWidthLandscapePhone = 350.0;
|
| +// x coordinate for the textLabel in a default table cell with an image.
|
| +static const CGFloat kCellTextXCoordinate = 60.0;
|
| +// Inset for the shadows of the contained views.
|
| +NS_INLINE UIEdgeInsets TabHistoryPopupMenuInsets() {
|
| + return UIEdgeInsetsMakeDirected(9, 11, 12, 11);
|
| +}
|
| +
|
| +// Layout for popup: shift twelve pixels towards the leading edge.
|
| +LayoutOffset kHistoryPopupLeadingOffset = -12;
|
| +CGFloat kHistoryPopupYOffset = 3;
|
| +// Occupation of the Tools Container as a percentage of the parent height.
|
| +static const CGFloat kHeightPercentage = 0.85;
|
| +} // anonymous namespace
|
| +
|
| +@interface TabHistoryPopupController () {
|
| + // TableViewController for the table displaying tab history entries.
|
| + TabHistoryViewController* tabHistoryTableViewController_;
|
| +
|
| + // Container view of the history entries table.
|
| + UIView* tabHistoryTableViewContainer_;
|
| +
|
| + base::mac::ObjCPropertyReleaser propertyReleaser_TabHistoryPopupController_;
|
| +}
|
| +
|
| +// Determines the width for the popup depending on the device, orientation, and
|
| +// CRWSessionEntrys to display.
|
| +- (CGFloat)calculatePopupWidth:(NSArray*)entries;
|
| +
|
| +@property(nonatomic, retain)
|
| + TabHistoryViewController* tabHistoryTableViewController;
|
| +@property(nonatomic, retain) UIView* tabHistoryTableViewContainer;
|
| +
|
| +@end
|
| +
|
| +@implementation TabHistoryPopupController
|
| +
|
| +@synthesize tabHistoryTableViewController = tabHistoryTableViewController_;
|
| +@synthesize tabHistoryTableViewContainer = tabHistoryTableViewContainer_;
|
| +
|
| +- (id)initWithOrigin:(CGPoint)origin
|
| + parentView:(UIView*)parent
|
| + entries:(NSArray*)entries {
|
| + DCHECK(parent);
|
| + self = [super initWithParentView:parent];
|
| + if (self) {
|
| + propertyReleaser_TabHistoryPopupController_.Init(
|
| + self, [TabHistoryPopupController class]);
|
| +
|
| + tabHistoryTableViewController_ = [[TabHistoryViewController alloc] init];
|
| + [tabHistoryTableViewController_ setSessionEntries:entries];
|
| +
|
| + UICollectionView* collectionView =
|
| + [tabHistoryTableViewController_ collectionView];
|
| + [collectionView setAccessibilityIdentifier:@"Tab History"];
|
| +
|
| + tabHistoryTableViewContainer_ = [[UIView alloc] initWithFrame:CGRectZero];
|
| + [tabHistoryTableViewContainer_ layer].cornerRadius = 2;
|
| + [tabHistoryTableViewContainer_ layer].masksToBounds = YES;
|
| + [tabHistoryTableViewContainer_ addSubview:collectionView];
|
| +
|
| + LayoutOffset originOffset =
|
| + kHistoryPopupLeadingOffset - TabHistoryPopupMenuInsets().left;
|
| + CGPoint newOrigin = CGPointLayoutOffset(origin, originOffset);
|
| + newOrigin.y += kHistoryPopupYOffset;
|
| +
|
| + CGFloat availableHeight =
|
| + (CGRectGetHeight([parent bounds]) - origin.y) * kHeightPercentage;
|
| + CGFloat optimalHeight =
|
| + [tabHistoryTableViewController_ optimalHeight:availableHeight];
|
| + CGFloat popupWidth = [self calculatePopupWidth:entries];
|
| + [self setOptimalSize:CGSizeMake(popupWidth, optimalHeight)
|
| + atOrigin:newOrigin];
|
| +
|
| + CGRect bounds = [[self popupContainer] bounds];
|
| + CGRect frame = UIEdgeInsetsInsetRect(bounds, TabHistoryPopupMenuInsets());
|
| +
|
| + [tabHistoryTableViewContainer_ setFrame:frame];
|
| + [collectionView setFrame:[tabHistoryTableViewContainer_ bounds]];
|
| +
|
| + [[self popupContainer] addSubview:tabHistoryTableViewContainer_];
|
| + CGRect containerFrame = [[self popupContainer] frame];
|
| + CGPoint destination = CGPointMake(CGRectGetLeadingEdge(containerFrame),
|
| + CGRectGetMinY(containerFrame));
|
| + [self fadeInPopupFromSource:origin toDestination:destination];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)fadeInPopupFromSource:(CGPoint)source
|
| + toDestination:(CGPoint)destination {
|
| + [tabHistoryTableViewContainer_ setAlpha:0];
|
| + [UIView animateWithDuration:ios::material::kDuration1
|
| + animations:^{
|
| + [tabHistoryTableViewContainer_ setAlpha:1];
|
| + }];
|
| + [super fadeInPopupFromSource:source toDestination:destination];
|
| +}
|
| +
|
| +- (void)dismissAnimatedWithCompletion:(void (^)(void))completion {
|
| + [tabHistoryTableViewContainer_ setAlpha:0];
|
| + [super dismissAnimatedWithCompletion:completion];
|
| +}
|
| +
|
| +- (CGFloat)calculatePopupWidth:(NSArray*)entries {
|
| + CGFloat maxWidth;
|
| +
|
| + // Determine the maximum width for the device and orientation.
|
| +
|
| + if (!IsIPadIdiom()) {
|
| + UIInterfaceOrientation orientation =
|
| + [[UIApplication sharedApplication] statusBarOrientation];
|
| + // Phone in portrait has constant width.
|
| + if (UIInterfaceOrientationIsPortrait(orientation))
|
| + return kTabHistoryMinWidth;
|
| + maxWidth = kTabHistoryMaxWidthLandscapePhone;
|
| + } else {
|
| + // On iPad use 85% of the available width.
|
| + maxWidth = ui::AlignValueToUpperPixel(
|
| + [UIApplication sharedApplication].keyWindow.frame.size.width * .85);
|
| + }
|
| + // Increase the width to fit the text to display but don't exceed maxWidth.
|
| + CGFloat cellWidth = kTabHistoryMinWidth;
|
| + UIFont* font = [[MDFRobotoFontLoader sharedInstance] regularFontOfSize:16];
|
| + for (CRWSessionEntry* sessionEntry in entries) {
|
| + web::NavigationItem* item = sessionEntry.navigationItem;
|
| + // TODO(rohitrao): Can this be replaced with GetTitleForDisplay()?
|
| + NSString* cellText = item->GetTitle().empty()
|
| + ? base::SysUTF8ToNSString(item->GetURL().spec())
|
| + : base::SysUTF16ToNSString(item->GetTitle());
|
| + CGFloat contentWidth = [cellText cr_pixelAlignedSizeWithFont:font].width +
|
| + kCellTextXCoordinate;
|
| +
|
| + // If contentWidth is larger than maxWidth, return maxWidth instead of
|
| + // checking the rest of the entries.
|
| + if (contentWidth > maxWidth)
|
| + return maxWidth;
|
| + if (contentWidth > cellWidth)
|
| + cellWidth = contentWidth;
|
| + }
|
| + return cellWidth;
|
| +}
|
| +
|
| +- (void)dealloc {
|
| + [tabHistoryTableViewContainer_ removeFromSuperview];
|
| + [super dealloc];
|
| +}
|
| +
|
| +@end
|
|
|