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

Unified Diff: chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm

Issue 1099403005: [AiS] changing mac omnibox suggestions form NSMatrix to NSTableView (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: moved description access to test code Created 5 years, 6 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
index 67d7c2239e23dd8aa5759ec2147f5047702d38e6..75e7b062364ec930effb2066ec01285644a08870 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
@@ -24,6 +24,13 @@
namespace {
+// How much to adjust the cell sizing up from the default determined
+// by the font.
+const CGFloat kCellHeightAdjust = 6.0;
+
+// How large the icon should be when displayed.
+const CGFloat kImageSize = 19.0;
+
// How far to offset image column from the left.
const CGFloat kImageXOffset = 5.0;
@@ -279,67 +286,105 @@ NSAttributedString* CreateClassifiedAttributedString(
} // namespace
-@implementation OmniboxPopupCell
+@interface OmniboxPopupCell ()
+- (CGFloat)drawMatchPart:(NSAttributedString*)attributedString
+ withFrame:(NSRect)cellFrame
+ atOffset:(CGFloat)offset
+ withMaxWidth:(int)maxWidth
+ inView:(NSView*)controlView;
+@end
-- (id)init {
- self = [super init];
- if (self) {
- [self setImagePosition:NSImageLeft];
- [self setBordered:NO];
- [self setButtonType:NSRadioButton];
+@implementation OmniboxPopupCellData
- // Without this highlighting messes up white areas of images.
- [self setHighlightsBy:NSNoCellMask];
+- (instancetype)initWithMatch:(const AutocompleteMatch&)match
+ image:(NSImage*)image {
+ if ((self = [super init])) {
+ image_.reset([image retain]);
- const base::string16& raw_separator =
+ base::string16 raw_separator =
l10n_util::GetStringUTF16(IDS_AUTOCOMPLETE_MATCH_DESCRIPTION_SEPARATOR);
separator_.reset(
[CreateAttributedString(raw_separator, DimTextColor()) retain]);
+
+ isContentsRTL_ =
+ (base::i18n::RIGHT_TO_LEFT ==
+ base::i18n::GetFirstStrongCharacterDirection(match.contents));
+ matchType_ = match.type;
+
+ // Prefix may not have any characters with strong directionality, and may
+ // take the UI directionality. But prefix needs to appear in continuation
+ // of the contents so we force the directionality.
+ NSTextAlignment textAlignment =
+ isContentsRTL_ ? NSRightTextAlignment : NSLeftTextAlignment;
+ prefix_.reset(
+ [CreateAttributedString(base::UTF8ToUTF16(match.GetAdditionalInfo(
+ kACMatchPropertyContentsPrefix)),
+ ContentTextColor(), textAlignment) retain]);
+
+ contents_.reset([CreateClassifiedAttributedString(
+ match.contents, ContentTextColor(), match.contents_class) retain]);
+
+ if (match.answer) {
+ base::scoped_nsobject<NSMutableAttributedString> answerString(
+ [[NSMutableAttributedString alloc] init]);
+ DCHECK(!match.answer->second_line().text_fields().empty());
+ for (const SuggestionAnswer::TextField& textField :
+ match.answer->second_line().text_fields()) {
+ [answerString
+ appendAttributedString:CreateAnswerString(textField.text(),
+ textField.type())];
+ }
+ const base::string16 space(base::ASCIIToUTF16(" "));
+ // const base::char16 space(' ');
+ const SuggestionAnswer::TextField* textField =
+ match.answer->second_line().additional_text();
+ if (textField) {
+ [answerString
+ appendAttributedString:CreateAnswerString(space + textField->text(),
+ textField->type())];
+ }
+ textField = match.answer->second_line().status_text();
+ if (textField) {
+ [answerString
+ appendAttributedString:CreateAnswerString(space + textField->text(),
+ textField->type())];
+ }
+ description_.reset(answerString.release());
+ } else if (match.description.empty()) {
+ description_.reset();
+ } else {
+ description_.reset([CreateClassifiedAttributedString(
+ match.description, DimTextColor(), match.description_class) retain]);
+ }
}
return self;
}
-- (void)setAnswerImage:(NSImage*)image {
- answerImage_.reset([image retain]);
+- (id)copyWithZone:(NSZone*)zone {
groby-ooo-7-16 2015/06/05 01:28:47 Why does the cellData need copyWithZone?
dschuyler 2015/06/09 01:30:46 copyWithZone is called by setObjectValue. Maybe I
+ OmniboxPopupCellData* copy = [[OmniboxPopupCellData alloc] init];
+ copy->contents_.reset([contents_ retain]);
+ copy->separator_.reset([separator_ retain]);
+ copy->description_.reset([description_ retain]);
+ copy->prefix_.reset([prefix_ retain]);
+ copy->image_.reset([image_ retain]);
+ copy->answerImage_.reset([answerImage_ retain]);
+ copy->maxMatchContentsWidth_ = maxMatchContentsWidth_;
+ copy->contentsOffset_ = contentsOffset_;
+ copy->isContentsRTL_ = isContentsRTL_;
+ copy->matchType_ = matchType_;
+ return copy;
}
-- (void)setMatch:(const AutocompleteMatch&)match {
- match_ = match;
- NSAttributedString *contents = CreateClassifiedAttributedString(
- match_.contents, ContentTextColor(), match_.contents_class);
- [self setAttributedTitle:contents];
- [self setAnswerImage:nil];
- if (match_.answer) {
- base::scoped_nsobject<NSMutableAttributedString> answerString(
- [[NSMutableAttributedString alloc] init]);
- DCHECK(!match_.answer->second_line().text_fields().empty());
- for (const SuggestionAnswer::TextField& textField :
- match_.answer->second_line().text_fields()) {
- NSAttributedString* as =
- CreateAnswerString(textField.text(), textField.type());
- [answerString appendAttributedString:as];
- }
- const base::char16 space(' ');
- const SuggestionAnswer::TextField* textField =
- match_.answer->second_line().additional_text();
- if (textField) {
- [answerString
- appendAttributedString:CreateAnswerString(space + textField->text(),
- textField->type())];
- }
- textField = match_.answer->second_line().status_text();
- if (textField) {
- [answerString
- appendAttributedString:CreateAnswerString(space + textField->text(),
- textField->type())];
- }
- description_.reset(answerString.release());
- } else if (match_.description.empty()) {
- description_.reset();
- } else {
- description_.reset([CreateClassifiedAttributedString(
- match_.description, DimTextColor(), match_.description_class) retain]);
- }
+- (void)setContents:(NSAttributedString*)contents {
+ contents_.reset([contents retain]);
+}
+
+- (void)setImage:(NSImage*)image {
+ image_.reset([image retain]);
+}
+
+- (void)setAnswerImage:(NSImage*)image {
+ answerImage_.reset([image retain]);
}
- (NSAttributedString*)description {
@@ -354,74 +399,59 @@ NSAttributedString* CreateClassifiedAttributedString(
contentsOffset_ = contentsOffset;
}
-// The default NSButtonCell drawing leaves the image flush left and
-// the title next to the image. This spaces things out to line up
-// with the star button and autocomplete field.
-- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
- if ([self state] == NSOnState || [self isHighlighted]) {
- if ([self state] == NSOnState)
- [SelectedBackgroundColor() set];
- else
- [HoveredBackgroundColor() set];
- NSBezierPath* path =
- [NSBezierPath bezierPathWithRoundedRect:cellFrame
- xRadius:kCellRoundingRadius
- yRadius:kCellRoundingRadius];
- [path fill];
- }
-
- // Put the image centered vertically but in a fixed column.
- NSImage* image = [self image];
- if (image) {
- NSRect imageRect = cellFrame;
- imageRect.size = [image size];
- imageRect.origin.y +=
- std::floor((NSHeight(cellFrame) - NSHeight(imageRect)) / 2.0);
- imageRect.origin.x += kImageXOffset;
- [image drawInRect:FlipIfRTL(imageRect, cellFrame)
- fromRect:NSZeroRect // Entire image
- operation:NSCompositeSourceOver
- fraction:1.0
- respectFlipped:YES
- hints:nil];
- }
-
- [self drawMatchWithFrame:cellFrame inView:controlView];
+- (CGFloat)getMatchContentsWidth {
+ return [contents_ size].width;
}
-- (void)drawMatchWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
- NSAttributedString* contents = [self attributedTitle];
+- (CGFloat)rowHeight {
+ return kImageSize + kCellHeightAdjust;
+}
+- (void)drawMatchWithFrame:(NSRect)cellFrame
groby-ooo-7-16 2015/06/05 01:28:47 Draw routines really belong on the cell, not the d
dschuyler 2015/06/09 01:30:46 Done.
+ inCell:(OmniboxPopupCell*)cell
+ inView:(NSView*)controlView {
CGFloat remainingWidth = GetContentAreaWidth(cellFrame);
CGFloat contentsWidth = [self getMatchContentsWidth];
CGFloat separatorWidth = [separator_ size].width;
- CGFloat descriptionWidth = description_.get() ? [description_ size].width : 0;
+ CGFloat descriptionWidth = description_ ? [description_ size].width : 0;
int contentsMaxWidth, descriptionMaxWidth;
OmniboxPopupModel::ComputeMatchMaxWidths(
- ceilf(contentsWidth),
- ceilf(separatorWidth),
- ceilf(descriptionWidth),
- ceilf(remainingWidth),
- !AutocompleteMatch::IsSearchType(match_.type),
- &contentsMaxWidth,
- &descriptionMaxWidth);
+ ceilf(contentsWidth), ceilf(separatorWidth), ceilf(descriptionWidth),
+ ceilf(remainingWidth), !AutocompleteMatch::IsSearchType(matchType_),
+ &contentsMaxWidth, &descriptionMaxWidth);
+
+ // Put the image centered vertically but in a fixed column.
+ if (image_) {
+ NSRect imageRect = cellFrame;
+ imageRect.size = [image_ size];
+ imageRect.origin.y +=
+ std::floor((NSHeight(cellFrame) - NSHeight(imageRect)) / 2.0);
+ imageRect.origin.x += kImageXOffset;
+ [image_ drawInRect:FlipIfRTL(imageRect, cellFrame)
+ fromRect:NSZeroRect
+ operation:NSCompositeSourceOver
+ fraction:1.0
+ respectFlipped:YES
+ hints:nil];
+ }
CGFloat offset = kTextStartOffset;
- if (match_.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) {
+ if (matchType_ == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) {
// Infinite suggestions are rendered with a prefix (usually ellipsis), which
// appear vertically stacked.
offset += [self drawMatchPrefixWithFrame:cellFrame
+ inCell:cell
inView:controlView
withContentsMaxWidth:&contentsMaxWidth];
}
- offset += [self drawMatchPart:contents
+ offset += [cell drawMatchPart:contents_
withFrame:cellFrame
atOffset:offset
withMaxWidth:contentsMaxWidth
inView:controlView];
if (descriptionMaxWidth != 0) {
- offset += [self drawMatchPart:separator_
+ offset += [cell drawMatchPart:separator_
withFrame:cellFrame
atOffset:offset
withMaxWidth:separatorWidth
@@ -437,7 +467,7 @@ NSAttributedString* CreateClassifiedAttributedString(
hints:nil];
offset += NSWidth(imageRect);
}
- offset += [self drawMatchPart:description_
+ offset += [cell drawMatchPart:description_
withFrame:cellFrame
atOffset:offset
withMaxWidth:descriptionMaxWidth
@@ -446,25 +476,15 @@ NSAttributedString* CreateClassifiedAttributedString(
}
- (CGFloat)drawMatchPrefixWithFrame:(NSRect)cellFrame
+ inCell:(OmniboxPopupCell*)cell
inView:(NSView*)controlView
withContentsMaxWidth:(int*)contentsMaxWidth {
CGFloat offset = 0.0f;
CGFloat remainingWidth = GetContentAreaWidth(cellFrame);
- bool isRTL = base::i18n::IsRTL();
- bool isContentsRTL = (base::i18n::RIGHT_TO_LEFT ==
- base::i18n::GetFirstStrongCharacterDirection(match_.contents));
- // Prefix may not have any characters with strong directionality, and may take
- // the UI directionality. But prefix needs to appear in continuation of the
- // contents so we force the directionality.
- NSTextAlignment textAlignment = isContentsRTL ?
- NSRightTextAlignment : NSLeftTextAlignment;
- prefix_.reset([CreateAttributedString(base::UTF8ToUTF16(
- match_.GetAdditionalInfo(kACMatchPropertyContentsPrefix)),
- ContentTextColor(), textAlignment) retain]);
CGFloat prefixWidth = [prefix_ size].width;
CGFloat prefixOffset = 0.0f;
- if (isRTL != isContentsRTL) {
+ if (base::i18n::IsRTL() != isContentsRTL_) {
// The contents is rendered between the contents offset extending towards
// the start edge, while prefix is rendered in opposite direction. Ideally
// the prefix should be rendered at |contentsOffset_|. If that is not
@@ -481,13 +501,14 @@ NSAttributedString* CreateClassifiedAttributedString(
// |remainingWidth|, then we shift the offset to the left , so that all
// postfix suggestions are visible.
// We have to render the prefix, so offset has to be at least |prefixWidth|.
- offset = std::max(prefixWidth,
+ offset = std::max(
+ prefixWidth,
std::min(remainingWidth - maxMatchContentsWidth_, contentsOffset_));
prefixOffset = offset - prefixWidth;
}
*contentsMaxWidth = std::min((int)ceilf(remainingWidth - prefixWidth),
*contentsMaxWidth);
- [self drawMatchPart:prefix_
+ [cell drawMatchPart:prefix_
withFrame:cellFrame
atOffset:prefixOffset + kTextStartOffset
withMaxWidth:prefixWidth
@@ -495,7 +516,29 @@ NSAttributedString* CreateClassifiedAttributedString(
return offset;
}
-- (CGFloat)drawMatchPart:(NSAttributedString*)as
+@end
+
+@implementation OmniboxPopupCell
+
+- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
+ if ([self state] == NSOnState || [self isHighlighted]) {
+ if ([self state] == NSOnState)
+ [SelectedBackgroundColor() set];
+ else
+ [HoveredBackgroundColor() set];
+ NSBezierPath* path =
+ [NSBezierPath bezierPathWithRoundedRect:cellFrame
+ xRadius:kCellRoundingRadius
+ yRadius:kCellRoundingRadius];
+ [path fill];
+ }
+
+ [[self objectValue] drawMatchWithFrame:cellFrame
+ inCell:self
+ inView:controlView];
+}
+
+- (CGFloat)drawMatchPart:(NSAttributedString*)attributedString
withFrame:(NSRect)cellFrame
atOffset:(CGFloat)offset
withMaxWidth:(int)maxWidth
@@ -505,20 +548,15 @@ NSAttributedString* CreateClassifiedAttributedString(
NSRect renderRect = ShiftRect(cellFrame, offset);
renderRect.size.width =
std::min(NSWidth(renderRect), static_cast<CGFloat>(maxWidth));
- if (renderRect.size.width != 0) {
- [self drawTitle:as
- withFrame:FlipIfRTL(renderRect, cellFrame)
- inView:controlView];
- }
+ NSRect textRect =
+ [attributedString boundingRectWithSize:renderRect.size options:nil];
+ renderRect.origin.y +=
+ std::floor((NSHeight(cellFrame) - NSHeight(textRect)) / 2.0);
+ if (NSWidth(renderRect) > 0.0)
+ [attributedString drawInRect:FlipIfRTL(renderRect, cellFrame)];
return NSWidth(renderRect);
}
-- (CGFloat)getMatchContentsWidth {
- NSAttributedString* contents = [self attributedTitle];
- return contents ? [contents size].width : 0;
-}
-
-
+ (CGFloat)computeContentsOffset:(const AutocompleteMatch&)match {
const base::string16& inputText = base::UTF8ToUTF16(
match.GetAdditionalInfo(kACMatchPropertyInputText));
@@ -537,9 +575,10 @@ NSAttributedString* CreateClassifiedAttributedString(
base::i18n::GetFirstStrongCharacterDirection(match.contents));
// Color does not matter.
- NSAttributedString* as = CreateAttributedString(inputText, DimTextColor());
- base::scoped_nsobject<NSTextStorage> textStorage([[NSTextStorage alloc]
- initWithAttributedString:as]);
+ NSAttributedString* attributedString =
+ CreateAttributedString(inputText, DimTextColor());
+ base::scoped_nsobject<NSTextStorage> textStorage(
+ [[NSTextStorage alloc] initWithAttributedString:attributedString]);
base::scoped_nsobject<NSLayoutManager> layoutManager(
[[NSLayoutManager alloc] init]);
base::scoped_nsobject<NSTextContainer> textContainer(
@@ -555,7 +594,7 @@ NSAttributedString* CreateClassifiedAttributedString(
// left edge of the string, irrespective of the directionality of UI or text.
CGFloat glyphOffset = [layoutManager locationForGlyphAtIndex:glyphIndex].x;
- CGFloat inputWidth = [as size].width;
+ CGFloat inputWidth = [attributedString size].width;
// The offset obtained above may need to be corrected because the left-most
// glyph may not have 0 offset. So we find the offset of left-most glyph, and
@@ -569,7 +608,7 @@ NSAttributedString* CreateClassifiedAttributedString(
// we are looking for.
CGFloat glyphWidth = inputWidth;
- for (NSUInteger i = 0; i < [as length]; i++) {
+ for (NSUInteger i = 0; i < [attributedString length]; i++) {
if (i == charIndex) continue;
glyphIndex = [layoutManager glyphIndexForCharacterAtIndex:i];
CGFloat offset = [layoutManager locationForGlyphAtIndex:glyphIndex].x;

Powered by Google App Engine
This is Rietveld 408576698