OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/cocoa/autocomplete_text_field_cell.h" | 5 #import "chrome/browser/cocoa/autocomplete_text_field_cell.h" |
6 | 6 |
7 #include "app/resource_bundle.h" | 7 #include "app/resource_bundle.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "gfx/font.h" | 9 #include "gfx/font.h" |
| 10 #include "grit/theme_resources.h" |
10 | 11 |
11 namespace { | 12 namespace { |
12 | 13 |
13 const CGFloat kBaselineAdjust = 2.0; | 14 const CGFloat kBaselineAdjust = 2.0; |
14 | 15 |
15 // How far to offset the keyword token into the field. | 16 // How far to offset the keyword token into the field. |
16 const NSInteger kKeywordXOffset = 3; | 17 const NSInteger kKeywordXOffset = 3; |
17 | 18 |
18 // How much width (beyond text) to add to the keyword token on each | 19 // How much width (beyond text) to add to the keyword token on each |
19 // side. | 20 // side. |
20 const NSInteger kKeywordTokenInset = 3; | 21 const NSInteger kKeywordTokenInset = 3; |
21 | 22 |
22 // Gap to leave between hint and right-hand-side of cell. | 23 // Gap to leave between hint and right-hand-side of cell. |
23 const NSInteger kHintXOffset = 4; | 24 const NSInteger kHintXOffset = 4; |
24 | 25 |
25 // How far to shift bounding box of hint down from top of field. | 26 // How far to shift bounding box of hint down from top of field. |
26 // Assumes -setFlipped:YES. | 27 // Assumes -setFlipped:YES. |
27 const NSInteger kHintYOffset = 4; | 28 const NSInteger kHintYOffset = 4; |
28 | 29 |
29 // How far to inset the keywork token from sides. | 30 // How far to inset the keywork token from sides. |
30 const NSInteger kKeywordYInset = 4; | 31 const NSInteger kKeywordYInset = 4; |
31 | 32 |
32 // TODO(shess): The keyword hint image wants to sit on the baseline. | 33 // TODO(shess): The keyword hint image wants to sit on the baseline. |
33 // This moves it down so that there is approximately as much image | 34 // This moves it down so that there is approximately as much image |
34 // above the lowercase ascender as below the baseline. A better | 35 // above the lowercase ascender as below the baseline. A better |
35 // technique would be nice to have, though. | 36 // technique would be nice to have, though. |
36 const NSInteger kKeywordHintImageBaseline = -6; | 37 const NSInteger kKeywordHintImageBaseline = -6; |
37 | 38 |
| 39 // Drops the magnifying glass icon so that it looks centered in the |
| 40 // keyword-search bubble. |
| 41 const NSInteger kKeywordSearchImageBaseline = -4; |
| 42 |
38 // The amount of padding on either side reserved for drawing an icon. | 43 // The amount of padding on either side reserved for drawing an icon. |
39 const NSInteger kIconHorizontalPad = 3; | 44 const NSInteger kIconHorizontalPad = 3; |
40 | 45 |
41 // How far to shift bounding box of hint icon label down from top of field. | 46 // How far to shift bounding box of hint icon label down from top of field. |
42 const NSInteger kIconLabelYOffset = 7; | 47 const NSInteger kIconLabelYOffset = 7; |
43 | 48 |
44 // How far the editor insets itself, for purposes of determining if | 49 // How far the editor insets itself, for purposes of determining if |
45 // decorations need to be trimmed. | 50 // decorations need to be trimmed. |
46 const CGFloat kEditorHorizontalInset = 3.0; | 51 const CGFloat kEditorHorizontalInset = 3.0; |
47 | 52 |
(...skipping 15 matching lines...) Expand all Loading... |
63 // If there is an image, make sure we calculated the target size | 68 // If there is an image, make sure we calculated the target size |
64 // correctly. | 69 // correctly. |
65 DCHECK(!image || NSEqualSizes([image size], rect.size)); | 70 DCHECK(!image || NSEqualSizes([image size], rect.size)); |
66 [image setFlipped:[view isFlipped]]; | 71 [image setFlipped:[view isFlipped]]; |
67 [image drawInRect:rect | 72 [image drawInRect:rect |
68 fromRect:NSZeroRect // Entire image | 73 fromRect:NSZeroRect // Entire image |
69 operation:NSCompositeSourceOver | 74 operation:NSCompositeSourceOver |
70 fraction:1.0]; | 75 fraction:1.0]; |
71 } | 76 } |
72 | 77 |
| 78 // Helper function to generate an attributed string containing |
| 79 // |anImage|. If |baselineAdjustment| is 0, the image sits on the |
| 80 // text baseline, positive values shift it up, negative values shift |
| 81 // it down. |
| 82 NSAttributedString* AttributedStringForImage(NSImage* anImage, |
| 83 CGFloat baselineAdjustment) { |
| 84 scoped_nsobject<NSTextAttachmentCell> attachmentCell( |
| 85 [[NSTextAttachmentCell alloc] initImageCell:anImage]); |
| 86 scoped_nsobject<NSTextAttachment> attachment( |
| 87 [[NSTextAttachment alloc] init]); |
| 88 [attachment setAttachmentCell:attachmentCell]; |
| 89 |
| 90 scoped_nsobject<NSMutableAttributedString> as( |
| 91 [[NSAttributedString attributedStringWithAttachment:attachment] |
| 92 mutableCopy]); |
| 93 [as addAttribute:NSBaselineOffsetAttributeName |
| 94 value:[NSNumber numberWithFloat:baselineAdjustment] |
| 95 range:NSMakeRange(0, [as length])]; |
| 96 |
| 97 return [[as copy] autorelease]; |
| 98 } |
| 99 |
73 } // namespace | 100 } // namespace |
74 | 101 |
75 @implementation AutocompleteTextFieldIcon | 102 @implementation AutocompleteTextFieldIcon |
76 | 103 |
77 @synthesize rect = rect_; | 104 @synthesize rect = rect_; |
78 @synthesize view = view_; | 105 @synthesize view = view_; |
79 | 106 |
80 // Private helper. | 107 // Private helper. |
81 - (id)initWithView:(LocationBarViewMac::LocationBarImageView*)view | 108 - (id)initWithView:(LocationBarViewMac::LocationBarImageView*)view |
82 isLabel:(BOOL)isLabel { | 109 isLabel:(BOOL)isLabel { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 - (void)setKeywordString:(NSString*)fullString | 171 - (void)setKeywordString:(NSString*)fullString |
145 partialString:(NSString*)partialString | 172 partialString:(NSString*)partialString |
146 availableWidth:(CGFloat)width { | 173 availableWidth:(CGFloat)width { |
147 DCHECK(fullString != nil); | 174 DCHECK(fullString != nil); |
148 | 175 |
149 hintString_.reset(); | 176 hintString_.reset(); |
150 | 177 |
151 // Adjust for space between editor and decorations. | 178 // Adjust for space between editor and decorations. |
152 width -= 2 * kEditorHorizontalInset; | 179 width -= 2 * kEditorHorizontalInset; |
153 | 180 |
154 // If |fullString| won't fit, choose |partialString|. | 181 // Get the magnifying glass to put at the front of the string. |
| 182 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 183 NSImage* image = rb.GetNSImageNamed(IDR_O2_SEARCH); |
| 184 const NSSize imageSize = [image size]; |
| 185 |
| 186 // Based on what fits, choose |fullString| with the image, |
| 187 // |fullString| without the image, or |partialString|. |
155 NSDictionary* attributes = | 188 NSDictionary* attributes = |
156 [NSDictionary dictionaryWithObject:[self font] | 189 [NSDictionary dictionaryWithObject:[self font] |
157 forKey:NSFontAttributeName]; | 190 forKey:NSFontAttributeName]; |
158 NSString* s = fullString; | 191 NSString* s = fullString; |
159 if ([s sizeWithAttributes:attributes].width > width) { | 192 const CGFloat sWidth = [s sizeWithAttributes:attributes].width; |
| 193 if (sWidth + imageSize.width > width) { |
| 194 image = nil; |
| 195 } |
| 196 if (sWidth > width) { |
160 if (partialString) { | 197 if (partialString) { |
161 s = partialString; | 198 s = partialString; |
162 } | 199 } |
163 } | 200 } |
164 keywordString_.reset( | 201 |
165 [[NSAttributedString alloc] initWithString:s attributes:attributes]); | 202 scoped_nsobject<NSMutableAttributedString> as( |
| 203 [[NSMutableAttributedString alloc] initWithString:s |
| 204 attributes:attributes]); |
| 205 |
| 206 // Insert the image at the front of the string if it didn't make |
| 207 // things too wide. |
| 208 if (image) { |
| 209 NSAttributedString* is = |
| 210 AttributedStringForImage(image, kKeywordSearchImageBaseline); |
| 211 [as insertAttributedString:is atIndex:0]; |
| 212 } |
| 213 |
| 214 keywordString_.reset([as copy]); |
166 } | 215 } |
167 | 216 |
168 // Convenience for the attributes used in the right-justified info | 217 // Convenience for the attributes used in the right-justified info |
169 // cells. | 218 // cells. |
170 - (NSDictionary*)hintAttributes { | 219 - (NSDictionary*)hintAttributes { |
171 scoped_nsobject<NSMutableParagraphStyle> style( | 220 scoped_nsobject<NSMutableParagraphStyle> style( |
172 [[NSMutableParagraphStyle alloc] init]); | 221 [[NSMutableParagraphStyle alloc] init]); |
173 [style setAlignment:NSRightTextAlignment]; | 222 [style setAlignment:NSRightTextAlignment]; |
174 | 223 |
175 return [NSDictionary dictionaryWithObjectsAndKeys: | 224 return [NSDictionary dictionaryWithObjectsAndKeys: |
(...skipping 27 matching lines...) Expand all Loading... |
203 ![[hintString_ string] hasSuffix:suffixString]) { | 252 ![[hintString_ string] hasSuffix:suffixString]) { |
204 | 253 |
205 // Build an attributed string with the concatenation of the prefix | 254 // Build an attributed string with the concatenation of the prefix |
206 // and suffix. | 255 // and suffix. |
207 NSString* s = [prefixString stringByAppendingString:suffixString]; | 256 NSString* s = [prefixString stringByAppendingString:suffixString]; |
208 scoped_nsobject<NSMutableAttributedString> as( | 257 scoped_nsobject<NSMutableAttributedString> as( |
209 [[NSMutableAttributedString alloc] | 258 [[NSMutableAttributedString alloc] |
210 initWithString:s attributes:[self hintAttributes]]); | 259 initWithString:s attributes:[self hintAttributes]]); |
211 | 260 |
212 // Build an attachment containing the hint image. | 261 // Build an attachment containing the hint image. |
213 scoped_nsobject<NSTextAttachmentCell> attachmentCell( | 262 NSAttributedString* is = |
214 [[NSTextAttachmentCell alloc] initImageCell:anImage]); | 263 AttributedStringForImage(anImage, kKeywordHintImageBaseline); |
215 scoped_nsobject<NSTextAttachment> attachment( | |
216 [[NSTextAttachment alloc] init]); | |
217 [attachment setAttachmentCell:attachmentCell]; | |
218 | |
219 // The attachment's baseline needs to be adjusted so the image | |
220 // doesn't sit on the same baseline as the text and make | |
221 // everything too tall. | |
222 scoped_nsobject<NSMutableAttributedString> is( | |
223 [[NSAttributedString attributedStringWithAttachment:attachment] | |
224 mutableCopy]); | |
225 [is addAttribute:NSBaselineOffsetAttributeName | |
226 value:[NSNumber numberWithFloat:kKeywordHintImageBaseline] | |
227 range:NSMakeRange(0, [is length])]; | |
228 | 264 |
229 // Stuff the image attachment between the prefix and suffix. | 265 // Stuff the image attachment between the prefix and suffix. |
230 [as insertAttributedString:is atIndex:[prefixString length]]; | 266 [as insertAttributedString:is atIndex:[prefixString length]]; |
231 | 267 |
232 // If too wide, just show the image. | 268 // If too wide, just show the image. |
233 hintString_.reset(WidthForHint(as) > width ? [is copy] : [as copy]); | 269 hintString_.reset(WidthForHint(as) > width ? [is copy] : [as copy]); |
234 } | 270 } |
235 } | 271 } |
236 | 272 |
237 - (void)setSearchHintString:(NSString*)aString | 273 - (void)setSearchHintString:(NSString*)aString |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 [[NSColor selectedControlColor] set]; | 460 [[NSColor selectedControlColor] set]; |
425 [path fill]; | 461 [path fill]; |
426 | 462 |
427 // Border around token rectangle, match focus ring's inner color. | 463 // Border around token rectangle, match focus ring's inner color. |
428 [[[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:0.5] set]; | 464 [[[NSColor keyboardFocusIndicatorColor] colorWithAlphaComponent:0.5] set]; |
429 [path setLineWidth:1.0]; | 465 [path setLineWidth:1.0]; |
430 [path stroke]; | 466 [path stroke]; |
431 | 467 |
432 // Draw text w/in the rectangle. | 468 // Draw text w/in the rectangle. |
433 infoFrame.origin.x += 4.0; | 469 infoFrame.origin.x += 4.0; |
434 infoFrame.origin.y += 1.0; | |
435 [keywordString_.get() drawInRect:infoFrame]; | 470 [keywordString_.get() drawInRect:infoFrame]; |
436 } | 471 } |
437 | 472 |
438 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { | 473 - (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView { |
439 if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) { | 474 if (!keywordString_ && locationIconView_ && locationIconView_->IsVisible()) { |
440 DrawImageInRect(locationIconView_->GetImage(), controlView, | 475 DrawImageInRect(locationIconView_->GetImage(), controlView, |
441 [self locationIconFrameForFrame:cellFrame]); | 476 [self locationIconFrameForFrame:cellFrame]); |
442 } | 477 } |
443 | 478 |
444 if (hintString_) { | 479 if (hintString_) { |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 icon = [self iconForEvent:theEvent inRect:cellFrame ofView:controlView]; | 592 icon = [self iconForEvent:theEvent inRect:cellFrame ofView:controlView]; |
558 if (icon) { | 593 if (icon) { |
559 [icon view]->OnMousePressed([icon rect]); | 594 [icon view]->OnMousePressed([icon rect]); |
560 return YES; | 595 return YES; |
561 } | 596 } |
562 | 597 |
563 return NO; | 598 return NO; |
564 } | 599 } |
565 | 600 |
566 @end | 601 @end |
OLD | NEW |