| Index: ios/chrome/browser/ui/omnibox/truncating_attributed_label.mm
|
| diff --git a/ios/chrome/browser/ui/omnibox/truncating_attributed_label.mm b/ios/chrome/browser/ui/omnibox/truncating_attributed_label.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c4a13e49895e5c9e4f4fb2d622700fc8b1bbc867
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/ui/omnibox/truncating_attributed_label.mm
|
| @@ -0,0 +1,150 @@
|
| +// Copyright (c) 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/omnibox/truncating_attributed_label.h"
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include "base/mac/objc_property_releaser.h"
|
| +#include "base/mac/scoped_cftyperef.h"
|
| +
|
| +@interface OmniboxPopupTruncatingLabel ()
|
| +- (void)setup;
|
| +- (UIImage*)getLinearGradient:(CGRect)rect;
|
| +@end
|
| +
|
| +@implementation OmniboxPopupTruncatingLabel {
|
| + // Attributed text.
|
| + base::scoped_nsobject<CATextLayer> textLayer_;
|
| + // Gradient used to create fade effect. Changes based on view.frame size.
|
| + base::scoped_nsobject<UIImage> gradient_;
|
| +
|
| + base::mac::ObjCPropertyReleaser propertyReleaser_OmniboxPopupTruncatingLabel_;
|
| +}
|
| +
|
| +@synthesize truncateMode = truncateMode_;
|
| +@synthesize attributedText = attributedText_;
|
| +@synthesize highlighted = highlighted_;
|
| +@synthesize highlightedText = highlightedText_;
|
| +@synthesize textAlignment = textAlignment_;
|
| +
|
| +- (void)setup {
|
| + self.backgroundColor = [UIColor clearColor];
|
| + self.contentMode = UIViewContentModeRedraw;
|
| + truncateMode_ = OmniboxPopupTruncatingTail;
|
| +
|
| + // Disable animations in CATextLayer.
|
| + textLayer_.reset([[CATextLayer layer] retain]);
|
| + base::scoped_nsobject<NSDictionary> actions([[NSDictionary alloc]
|
| + initWithObjectsAndKeys:[NSNull null], @"contents", nil]);
|
| + [textLayer_ setActions:actions];
|
| + [textLayer_ setFrame:self.bounds];
|
| + [textLayer_ setContentsScale:[[UIScreen mainScreen] scale]];
|
| +}
|
| +
|
| +- (id)initWithFrame:(CGRect)frame {
|
| + self = [super initWithFrame:frame];
|
| + if (self) {
|
| + propertyReleaser_OmniboxPopupTruncatingLabel_.Init(
|
| + self, [OmniboxPopupTruncatingLabel class]);
|
| + [self setup];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)awakeFromNib {
|
| + [super awakeFromNib];
|
| + [self setup];
|
| +}
|
| +
|
| +- (void)setFrame:(CGRect)frame {
|
| + [super setFrame:frame];
|
| + [textLayer_ setFrame:self.bounds];
|
| +
|
| + // Cache the fade gradient when the frame changes.
|
| + if (!CGRectIsEmpty(frame) &&
|
| + (!gradient_.get() || !CGSizeEqualToSize([gradient_ size], frame.size))) {
|
| + CGRect rect = CGRectMake(0, 0, frame.size.width, frame.size.height);
|
| + gradient_.reset([[self getLinearGradient:rect] retain]);
|
| + }
|
| +}
|
| +
|
| +- (void)drawRect:(CGRect)rect {
|
| + if ([attributedText_ length] == 0)
|
| + return;
|
| +
|
| + CGContextRef context = UIGraphicsGetCurrentContext();
|
| + CGContextSaveGState(context);
|
| + [textLayer_ setString:highlighted_ ? highlightedText_ : attributedText_];
|
| + CGContextClipToMask(context, self.bounds, [gradient_ CGImage]);
|
| + [textLayer_ renderInContext:context];
|
| +
|
| + CGContextRestoreGState(context);
|
| +}
|
| +
|
| +- (void)setTextAlignment:(NSTextAlignment)textAlignment {
|
| + if (textAlignment == NSTextAlignmentLeft) {
|
| + [textLayer_ setAlignmentMode:kCAAlignmentLeft];
|
| + self.truncateMode = OmniboxPopupTruncatingTail;
|
| + } else if (textAlignment == NSTextAlignmentRight) {
|
| + [textLayer_ setAlignmentMode:kCAAlignmentRight];
|
| + self.truncateMode = OmniboxPopupTruncatingHead;
|
| + } else if (textAlignment == NSTextAlignmentNatural) {
|
| + [textLayer_ setAlignmentMode:kCAAlignmentNatural];
|
| + self.truncateMode = OmniboxPopupTruncatingTail;
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| + if (textAlignment != textAlignment_)
|
| + gradient_.reset();
|
| + textAlignment_ = textAlignment;
|
| +}
|
| +
|
| +// Create gradient opacity mask based on direction.
|
| +- (UIImage*)getLinearGradient:(CGRect)rect {
|
| + // Create an opaque context.
|
| + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
|
| + CGContextRef context =
|
| + CGBitmapContextCreate(NULL, rect.size.width, rect.size.height, 8,
|
| + 4 * rect.size.width, colorSpace, kCGImageAlphaNone);
|
| +
|
| + // White background will mask opaque, black gradient will mask transparent.
|
| + CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
|
| + CGContextFillRect(context, rect);
|
| +
|
| + // Create gradient from white to black.
|
| + CGFloat locs[2] = {0.0f, 1.0f};
|
| + CGFloat components[4] = {1.0f, 1.0f, 0.0f, 1.0f};
|
| + CGGradientRef gradient =
|
| + CGGradientCreateWithColorComponents(colorSpace, components, locs, 2);
|
| + CGColorSpaceRelease(colorSpace);
|
| +
|
| + // Draw head and/or tail gradient.
|
| + CGFloat fadeWidth =
|
| + std::min(rect.size.height * 2, (CGFloat)floor(rect.size.width / 4));
|
| + CGFloat minX = CGRectGetMinX(rect);
|
| + CGFloat maxX = CGRectGetMaxX(rect);
|
| + if (self.truncateMode & OmniboxPopupTruncatingTail) {
|
| + CGFloat startX = maxX - fadeWidth;
|
| + CGPoint startPoint = CGPointMake(startX, CGRectGetMidY(rect));
|
| + CGPoint endPoint = CGPointMake(maxX, CGRectGetMidY(rect));
|
| + CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
|
| + }
|
| + if (self.truncateMode & OmniboxPopupTruncatingHead) {
|
| + CGFloat startX = minX + fadeWidth;
|
| + CGPoint startPoint = CGPointMake(startX, CGRectGetMidY(rect));
|
| + CGPoint endPoint = CGPointMake(minX, CGRectGetMidY(rect));
|
| + CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
|
| + }
|
| + CGGradientRelease(gradient);
|
| +
|
| + // Clean up, return image.
|
| + CGImageRef ref = CGBitmapContextCreateImage(context);
|
| + UIImage* image = [UIImage imageWithCGImage:ref];
|
| + CGImageRelease(ref);
|
| + CGContextRelease(context);
|
| + return image;
|
| +}
|
| +
|
| +@end
|
|
|