Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1059)

Side by Side Diff: ios/chrome/browser/ui/omnibox/truncating_attributed_label.mm

Issue 2695413003: Change OmniboxPopupTruncatingLabel to be based on UILabel. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ios/chrome/browser/ui/omnibox/truncating_attributed_label.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ios/chrome/browser/ui/omnibox/truncating_attributed_label.h" 5 #import "ios/chrome/browser/ui/omnibox/truncating_attributed_label.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/mac/objc_property_releaser.h" 9 #include "base/mac/objc_property_releaser.h"
10 #include "base/mac/scoped_cftyperef.h" 10 #include "base/mac/scoped_cftyperef.h"
11 11
12 @interface OmniboxPopupTruncatingLabel () 12 @interface OmniboxPopupTruncatingLabel ()
13 - (void)setup; 13 - (void)setup;
14 - (UIImage*)getLinearGradient:(CGRect)rect; 14 - (UIImage*)getLinearGradient:(CGRect)rect;
15 @end 15 @end
16 16
17 @implementation OmniboxPopupTruncatingLabel { 17 @implementation OmniboxPopupTruncatingLabel {
18 // Attributed text.
19 base::scoped_nsobject<CATextLayer> textLayer_;
20 // Gradient used to create fade effect. Changes based on view.frame size.
21 base::scoped_nsobject<UIImage> gradient_;
22
23 base::mac::ObjCPropertyReleaser propertyReleaser_OmniboxPopupTruncatingLabel_; 18 base::mac::ObjCPropertyReleaser propertyReleaser_OmniboxPopupTruncatingLabel_;
24 } 19 }
25 20
26 @synthesize truncateMode = truncateMode_; 21 @synthesize truncateMode = truncateMode_;
27 @synthesize attributedText = attributedText_;
28 @synthesize highlighted = highlighted_;
29 @synthesize highlightedText = highlightedText_;
30 @synthesize textAlignment = textAlignment_;
31 22
32 - (void)setup { 23 - (void)setup {
33 self.backgroundColor = [UIColor clearColor]; 24 self.backgroundColor = [UIColor clearColor];
34 self.contentMode = UIViewContentModeRedraw;
35 truncateMode_ = OmniboxPopupTruncatingTail; 25 truncateMode_ = OmniboxPopupTruncatingTail;
36
37 // Disable animations in CATextLayer.
38 textLayer_.reset([[CATextLayer layer] retain]);
39 base::scoped_nsobject<NSDictionary> actions([[NSDictionary alloc]
40 initWithObjectsAndKeys:[NSNull null], @"contents", nil]);
41 [textLayer_ setActions:actions];
42 [textLayer_ setFrame:self.bounds];
43 [textLayer_ setContentsScale:[[UIScreen mainScreen] scale]];
44 } 26 }
45 27
46 - (id)initWithFrame:(CGRect)frame { 28 - (id)initWithFrame:(CGRect)frame {
47 self = [super initWithFrame:frame]; 29 self = [super initWithFrame:frame];
48 if (self) { 30 if (self) {
49 propertyReleaser_OmniboxPopupTruncatingLabel_.Init( 31 propertyReleaser_OmniboxPopupTruncatingLabel_.Init(
50 self, [OmniboxPopupTruncatingLabel class]); 32 self, [OmniboxPopupTruncatingLabel class]);
33 self.lineBreakMode = NSLineBreakByClipping;
51 [self setup]; 34 [self setup];
52 } 35 }
53 return self; 36 return self;
54 } 37 }
55 38
56 - (void)awakeFromNib { 39 - (void)awakeFromNib {
57 [super awakeFromNib]; 40 [super awakeFromNib];
58 [self setup]; 41 [self setup];
59 } 42 }
60 43
61 - (void)setFrame:(CGRect)frame { 44 // Draw fade gradient mask if text is wider than rect.
62 [super setFrame:frame]; 45 - (void)drawTextInRect:(CGRect)requestedRect {
63 [textLayer_ setFrame:self.bounds];
64
65 // Cache the fade gradient when the frame changes.
66 if (!CGRectIsEmpty(frame) &&
67 (!gradient_.get() || !CGSizeEqualToSize([gradient_ size], frame.size))) {
68 CGRect rect = CGRectMake(0, 0, frame.size.width, frame.size.height);
69 gradient_.reset([[self getLinearGradient:rect] retain]);
70 }
71 }
72
73 - (void)drawRect:(CGRect)rect {
74 if ([attributedText_ length] == 0)
75 return;
76
77 CGContextRef context = UIGraphicsGetCurrentContext(); 46 CGContextRef context = UIGraphicsGetCurrentContext();
78 CGContextSaveGState(context); 47 CGContextSaveGState(context);
79 [textLayer_ setString:highlighted_ ? highlightedText_ : attributedText_];
80 CGContextClipToMask(context, self.bounds, [gradient_ CGImage]);
81 [textLayer_ renderInContext:context];
82 48
49 CGSize size = CGSizeZero;
50 if (self.attributedText) {
51 size = [self.attributedText size];
52 } else if (self.font) {
53 size = [self.text sizeWithAttributes:@{NSFontAttributeName : self.font}];
54 // sizeWithAttributes: may return fractional values, so ceil the width and
55 // height to preserve the behavior of sizeWithFont:.
56 size = CGSizeMake(ceil(size.width), ceil(size.height));
57 }
58
59 if (size.width > requestedRect.size.width) {
60 UIImage* image = [self getLinearGradient:requestedRect];
justincohen 2017/02/20 20:07:24 Does it matter this isn't cached like it used to b
Justin Donnelly 2017/02/21 18:16:50 I don't think so. GTMFadeTruncatingLabel doesn't c
justincohen 2017/02/22 03:52:29 I had to go back to 2012 ( https://b.corp.google.c
Justin Donnelly 2017/02/22 17:17:42 I don't honestly know. Without the caching, there'
61 CGContextClipToMask(context, self.bounds, image.CGImage);
62 }
63
64 if (self.attributedText) {
65 NSMutableAttributedString* attributedString =
66 [[self.attributedText mutableCopy] autorelease];
67
68 NSMutableParagraphStyle* textStyle =
69 [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
70 textStyle.lineBreakMode = self.lineBreakMode;
71 textStyle.alignment = self.textAlignment;
72 [attributedString addAttribute:NSParagraphStyleAttributeName
73 value:textStyle
74 range:NSMakeRange(0, [self.text length])];
75
76 [attributedString drawInRect:requestedRect];
justincohen 2017/02/20 20:07:24 Is lineBreakMode and textAlignment different in se
Justin Donnelly 2017/02/21 18:16:50 No, they behave the same. Maybe it would be better
justincohen 2017/02/22 03:52:29 What's the default linebreakmode? If the client s
Justin Donnelly 2017/02/22 17:17:42 The default is NSLineBreakByTruncatingTail (traili
77 } else if (self.font) {
78 // The UILabel docs say the default textColor is black and experimentation
79 // shows that calling -textColor will return the cached [UIColor blackColor]
80 // when called on a freshly alloc/init-ed UILabel, or a UILabel whose
81 // textColor has been set to nil.
82 //
83 // @see
84 // https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UIL abel_Class/Reference/UILabel.html#//apple_ref/occ/instp/UILabel/textColor
85 // (NOTE(bgoodwin): interesting side-note. These docs also say setting
86 // textColor to nil will result in an exception. In my testing, that did not
87 // happen.)
88 NSMutableParagraphStyle* textStyle =
89 [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
90 textStyle.lineBreakMode = self.lineBreakMode;
91 textStyle.alignment = self.textAlignment;
92 NSDictionary* attributes = @{
93 NSFontAttributeName : self.font,
94 NSParagraphStyleAttributeName : textStyle,
95 NSForegroundColorAttributeName : self.textColor
96 };
97 [self.text drawInRect:requestedRect withAttributes:attributes];
justincohen 2017/02/20 20:07:24 Why not just create an attributed string from text
Justin Donnelly 2017/02/21 18:16:50 It seemed simpler and safer to me to just copy the
98 }
83 CGContextRestoreGState(context); 99 CGContextRestoreGState(context);
84 } 100 }
85 101
86 - (void)setTextAlignment:(NSTextAlignment)textAlignment {
87 if (textAlignment == NSTextAlignmentLeft) {
88 [textLayer_ setAlignmentMode:kCAAlignmentLeft];
89 self.truncateMode = OmniboxPopupTruncatingTail;
90 } else if (textAlignment == NSTextAlignmentRight) {
91 [textLayer_ setAlignmentMode:kCAAlignmentRight];
92 self.truncateMode = OmniboxPopupTruncatingHead;
93 } else if (textAlignment == NSTextAlignmentNatural) {
94 [textLayer_ setAlignmentMode:kCAAlignmentNatural];
95 self.truncateMode = OmniboxPopupTruncatingTail;
96 } else {
97 NOTREACHED();
98 }
99 if (textAlignment != textAlignment_)
100 gradient_.reset();
101 textAlignment_ = textAlignment;
102 }
103
104 // Create gradient opacity mask based on direction. 102 // Create gradient opacity mask based on direction.
105 - (UIImage*)getLinearGradient:(CGRect)rect { 103 - (UIImage*)getLinearGradient:(CGRect)rect {
106 // Create an opaque context. 104 // Create an opaque context.
107 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 105 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
108 CGContextRef context = 106 CGContextRef context =
109 CGBitmapContextCreate(NULL, rect.size.width, rect.size.height, 8, 107 CGBitmapContextCreate(NULL, rect.size.width, rect.size.height, 8,
110 4 * rect.size.width, colorSpace, kCGImageAlphaNone); 108 4 * rect.size.width, colorSpace, kCGImageAlphaNone);
111 109
112 // White background will mask opaque, black gradient will mask transparent. 110 // White background will mask opaque, black gradient will mask transparent.
113 CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); 111 CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
(...skipping 27 matching lines...) Expand all
141 139
142 // Clean up, return image. 140 // Clean up, return image.
143 CGImageRef ref = CGBitmapContextCreateImage(context); 141 CGImageRef ref = CGBitmapContextCreateImage(context);
144 UIImage* image = [UIImage imageWithCGImage:ref]; 142 UIImage* image = [UIImage imageWithCGImage:ref];
145 CGImageRelease(ref); 143 CGImageRelease(ref);
146 CGContextRelease(context); 144 CGContextRelease(context);
147 return image; 145 return image;
148 } 146 }
149 147
150 @end 148 @end
OLDNEW
« no previous file with comments | « ios/chrome/browser/ui/omnibox/truncating_attributed_label.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698