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

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

Issue 17774002: OmniboxPopupViewMac refactoring Part 3 (truncation) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 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 f1b47c7e467cb36811517ce947d5dcfb290e1466..212a603a86dd2197f40876a729d981e4110cd64f 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
@@ -4,8 +4,11 @@
#import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
+#include <algorithm>
#include <cmath>
+#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
+
namespace {
// How far to offset image column from the left.
@@ -14,14 +17,70 @@ const CGFloat kImageXOffset = 5.0;
// How far to offset the text column from the left.
const CGFloat kTextXOffset = 28.0;
+// Maximum fraction of the popup width that can be used to display match
+// contents.
+const CGFloat kMaxContentsFraction = 0.7;
+
// Rounding radius of selection and hover background on popup items.
const CGFloat kCellRoundingRadius = 2.0;
-NSColor* SelectedBackgroundColor() {
- return [NSColor selectedControlColor];
-}
-NSColor* HoveredBackgroundColor() {
- return [NSColor controlHighlightColor];
+void DrawFadeTruncatingTitle(NSAttributedString* title,
+ NSRect titleRect) {
+ NSSize size = [title size];
+
+ // Empirically, Cocoa will draw an extra 2 pixels past NSWidth(titleRect)
+ // before it clips the text.
+ const CGFloat kOverflowBeforeClip = 2;
Scott Hess - ex-Googler 2013/06/28 01:02:48 2.0
sail 2013/06/28 18:41:16 Done.
+ BOOL clipping =
+ std::floor(size.width) > NSWidth(titleRect) + kOverflowBeforeClip;
+
+ // Gradient is about twice our line height long.
+ CGFloat gradientWidth = MIN(size.height * 2, NSWidth(titleRect) / 4);
Scott Hess - ex-Googler 2013/06/28 01:02:48 std::min().
sail 2013/06/28 18:41:16 Done.
+
+ NSRect solidPart, gradientPart;
+ NSDivideRect(titleRect, &gradientPart, &solidPart, gradientWidth, NSMaxXEdge);
+
+ NSPoint textOffset;
+ textOffset.x = NSMinX(titleRect);
+ textOffset.y =
+ NSMinY(titleRect) + roundf((NSHeight(titleRect) - size.height) / 2.0) - 1;
Scott Hess - ex-Googler 2013/06/28 01:02:48 Sigh. No std::round until c++11.
+
+ // Draw non-gradient part without transparency layer, as light text on a dark
+ // background looks bad with a gradient layer.
+ {
+ gfx::ScopedNSGraphicsContextSaveGState scopedGState;
+ if (clipping)
+ [NSBezierPath clipRect:solidPart];
+ [title drawAtPoint:textOffset];
+ }
+
+ if (!clipping)
Scott Hess - ex-Googler 2013/06/28 01:02:48 Couldn't this result in incorrect drawing if the t
sail 2013/06/28 18:41:16 Done. This part is not relevant anymore now that I
+ return;
+
+ // Draw the gradient part with a transparency layer. This makes the text look
+ // suboptimal, but since it fades out, that's ok.
Scott Hess - ex-Googler 2013/06/28 01:02:48 This seems complicated. Something like this using
sail 2013/06/28 18:41:16 Done. Yep, I just draw the full string and then dr
+ gfx::ScopedNSGraphicsContextSaveGState scopedGState;
+ [NSBezierPath clipRect:gradientPart];
+ CGContextRef context = static_cast<CGContextRef>(
+ [[NSGraphicsContext currentContext] graphicsPort]);
+ CGContextBeginTransparencyLayerWithRect(context,
+ NSRectToCGRect(gradientPart), 0);
+ [title drawAtPoint:textOffset];
+
+ NSColor *color = [NSColor textColor];
+ NSColor *alphaColor = [color colorWithAlphaComponent:0.0];
+ NSGradient *mask = [[NSGradient alloc] initWithStartingColor:color
+ endingColor:alphaColor];
+
+ // Draw the gradient mask
+ CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
+ [mask drawFromPoint:NSMakePoint(NSMaxX(titleRect) - gradientWidth,
+ NSMinY(titleRect))
+ toPoint:NSMakePoint(NSMaxX(titleRect),
+ NSMinY(titleRect))
+ options:NSGradientDrawsBeforeStartingLocation];
+ [mask release];
Scott Hess - ex-Googler 2013/06/28 01:02:48 Why not scoped_ptr<>? Does the mask require speci
sail 2013/06/28 18:41:16 Done.
+ CGContextEndTransparencyLayer(context);
}
} // namespace
@@ -29,8 +88,7 @@ NSColor* HoveredBackgroundColor() {
@implementation OmniboxPopupCell
- (id)init {
- self = [super init];
- if (self) {
+ if ((self = [super init])) {
[self setImagePosition:NSImageLeft];
[self setBordered:NO];
[self setButtonType:NSRadioButton];
@@ -41,15 +99,28 @@ NSColor* HoveredBackgroundColor() {
return self;
}
-// 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.
+- (NSAttributedString*)contentText {
+ return contentText_;
+}
+
+- (void)setContentText:(NSAttributedString*)contentText {
+ contentText_.reset([contentText retain]);
+}
+
+- (NSAttributedString*)descriptionText {
+ return descriptionText_;
+}
+
+- (void)setDescriptionText:(NSAttributedString*)descriptionText {
+ descriptionText_.reset([descriptionText retain]);
+}
+
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
if ([self state] == NSOnState || [self isHighlighted]) {
if ([self state] == NSOnState)
- [SelectedBackgroundColor() set];
+ [[NSColor selectedControlColor] set];
else
- [HoveredBackgroundColor() set];
+ [[NSColor controlHighlightColor] set];
NSBezierPath* path =
[NSBezierPath bezierPathWithRoundedRect:cellFrame
xRadius:kCellRoundingRadius
@@ -74,12 +145,33 @@ NSColor* HoveredBackgroundColor() {
}
// Adjust the title position to be lined up under the field's text.
- NSAttributedString* title = [self attributedTitle];
- if (title && [title length]) {
- NSRect titleRect = cellFrame;
- titleRect.size.width -= kTextXOffset;
- titleRect.origin.x += kTextXOffset;
- [self drawTitle:title withFrame:titleRect inView:controlView];
+ if ([contentText_ length]) {
+ CGFloat availableWidth = NSWidth(cellFrame) - kTextXOffset;
+ CGFloat contentWidth = [contentText_ size].width;
+ CGFloat descriptionWidth = 0;
+ if ([descriptionText_ length])
+ descriptionWidth = [descriptionText_ size].width;
+
+ if (contentWidth + descriptionWidth > availableWidth) {
+ if (contentWidth > kMaxContentsFraction * availableWidth) {
+ if (descriptionWidth > (1.0 - kMaxContentsFraction) * availableWidth)
+ descriptionWidth = (1.0 - kMaxContentsFraction) * availableWidth;
Scott Hess - ex-Googler 2013/06/28 01:02:48 std::min?
sail 2013/06/28 18:41:16 Done.
+ contentWidth =
+ std::min(contentWidth, availableWidth - descriptionWidth);
+ } else {
+ descriptionWidth = availableWidth - contentWidth;
+ }
+ }
Scott Hess - ex-Googler 2013/06/28 01:02:48 I think this entire if() can be replaced with some
sail 2013/06/28 18:41:16 Done.
+
+ NSRect contentRect = cellFrame;
+ contentRect.origin.x = kTextXOffset;
+ contentRect.size.width = contentWidth;
+ DrawFadeTruncatingTitle(contentText_, contentRect);
+
+ NSRect descriptionRect = cellFrame;
Scott Hess - ex-Googler 2013/06/28 01:02:48 if ([descriptionText_ length]){...} around this?
sail 2013/06/28 18:41:16 Done.
+ descriptionRect.origin.x = NSMaxX(contentRect);
+ descriptionRect.size.width = descriptionWidth;
+ DrawFadeTruncatingTitle(descriptionText_, descriptionRect);
}
}

Powered by Google App Engine
This is Rietveld 408576698