aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AppKit/GTMFadeTruncatingTextFieldCell.m89
-rw-r--r--AppKit/GTMFadeTruncatingTextFieldCellTest.m11
-rw-r--r--AppKit/TestData/GTMFadeTruncatingTextFieldCellTest5.tiffbin2188 -> 2136 bytes
-rw-r--r--AppKit/TestData/GTMFadeTruncatingTextFieldCellTest6.tiffbin2068 -> 2048 bytes
-rw-r--r--AppKit/TestData/GTMFadeTruncatingTextFieldCellTest8.tiffbin0 -> 2896 bytes
-rw-r--r--GTM.xcodeproj/project.pbxproj4
6 files changed, 76 insertions, 28 deletions
diff --git a/AppKit/GTMFadeTruncatingTextFieldCell.m b/AppKit/GTMFadeTruncatingTextFieldCell.m
index ec266a2..66e6874 100644
--- a/AppKit/GTMFadeTruncatingTextFieldCell.m
+++ b/AppKit/GTMFadeTruncatingTextFieldCell.m
@@ -43,26 +43,30 @@
// Draw the gradient part with a transparency layer. This makes the text look
// suboptimal, but since it fades out, that's ok.
[[NSGraphicsContext currentContext] saveGraphicsState];
- [NSBezierPath clipRect:clipRect];
+ [NSBezierPath clipRect:backgroundRect];
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
CGContextBeginTransparencyLayerWithRect(context,
- NSRectToCGRect(clipRect), 0);
+ NSRectToCGRect(backgroundRect), 0);
if ([self drawsBackground]) {
[[self backgroundColor] set];
- NSRectFillUsingOperation([self titleRectForBounds:backgroundRect],
+ NSRectFillUsingOperation(backgroundRect,
NSCompositeSourceOver);
}
+
+ [[NSGraphicsContext currentContext] saveGraphicsState];
+ [NSBezierPath clipRect:clipRect];
[attributedString drawInRect:titleRect];
+ [[NSGraphicsContext currentContext] restoreGraphicsState];
NSPoint startPoint;
NSPoint endPoint;
if (fadeToRight) {
- startPoint = clipRect.origin;
- endPoint = NSMakePoint(NSMaxX(clipRect), NSMinY(clipRect));
+ startPoint = backgroundRect.origin;
+ endPoint = NSMakePoint(NSMaxX(backgroundRect), NSMinY(backgroundRect));
} else {
- startPoint = NSMakePoint(NSMaxX(clipRect), NSMinY(clipRect));
- endPoint = clipRect.origin;
+ startPoint = NSMakePoint(NSMaxX(backgroundRect), NSMinY(backgroundRect));
+ endPoint = backgroundRect.origin;
}
// Draw the gradient mask
@@ -83,10 +87,10 @@
titleRect.size.width -= 2;
NSAttributedString *attributedString = [self attributedStringValue];
- NSSize size = [attributedString size];
+ NSSize stringSize = [attributedString size];
// Don't complicate drawing unless we need to clip
- if (size.width <= NSWidth(titleRect)) {
+ if (stringSize.width <= NSWidth(titleRect)) {
[super drawInteriorWithFrame:cellFrame inView:controlView];
return;
}
@@ -97,7 +101,7 @@
case GTMFadeTruncatingTail:
break;
case GTMFadeTruncatingHead:
- offsetX = size.width - titleRect.size.width;
+ offsetX = stringSize.width - titleRect.size.width;
break;
case GTMFadeTruncatingHeadAndTail: {
if (desiredCharactersToTruncateFromHead_ > 0) {
@@ -106,15 +110,24 @@
NSMakeRange(0, desiredCharactersToTruncateFromHead_)];
NSSize clippedHeadSize = [clippedHeadString size];
- // Clip the desired portion from the beginning of the string.
+ // This is the offset at which we start drawing. This causes the
+ // beginning of the string to get clipped.
offsetX = clippedHeadSize.width;
- CGFloat delta = size.width - titleRect.size.width;
+ // Due to the fade effect the first character is hard to see.
+ // We want to make sure the first character starting at
+ // |desiredCharactersToTruncateFromHead_| is readable so we reduce
+ // the offset by a little bit.
+ offsetX = MAX(0, offsetX - stringSize.height);
+
+ // If the offset is so large that there's empty space at the tail
+ // then reduce the offset so we can use up the empty space.
+ CGFloat delta = stringSize.width - titleRect.size.width;
if (offsetX > delta)
offsetX = delta;
} else {
// Center the string and clip equal portions of the head and tail.
- offsetX = round((size.width - titleRect.size.width) / 2.0);
+ offsetX = round((stringSize.width - titleRect.size.width) / 2.0);
}
break;
}
@@ -124,31 +137,48 @@
offsetTitleRect.origin.x -= offsetX;
offsetTitleRect.size.width += offsetX;
BOOL isTruncatingHead = offsetX > 0;
- BOOL isTruncatingTail = (size.width - titleRect.size.width) > offsetX;
+ BOOL isTruncatingTail = (stringSize.width - titleRect.size.width) > offsetX;
// Gradient is about twice our line height long
- CGFloat gradientWidth = MIN(size.height * 2, round(NSWidth(cellFrame) / 4));
- NSRect solidPart = cellFrame;
- NSRect headGradientPart = NSZeroRect;
- NSRect tailGradientPart = NSZeroRect;
+ CGFloat gradientWidth = MIN(stringSize.height * 2, round(NSWidth(cellFrame) / 4));
+
+ // Head, solid, and tail rects for drawing the background.
+ NSRect solidBackgroundPart = [self drawingRectForBounds:cellFrame];
+ NSRect headBackgroundPart = NSZeroRect;
+ NSRect tailBackgroundPart = NSZeroRect;
if (isTruncatingHead)
- NSDivideRect(solidPart, &headGradientPart, &solidPart,
+ NSDivideRect(solidBackgroundPart, &headBackgroundPart, &solidBackgroundPart,
gradientWidth, NSMinXEdge);
if (isTruncatingTail)
- NSDivideRect(solidPart, &tailGradientPart, &solidPart,
+ NSDivideRect(solidBackgroundPart, &tailBackgroundPart, &solidBackgroundPart,
gradientWidth, NSMaxXEdge);
+ // Head, solid and tail rects for clipping the title. This is slightly
+ // smaller than the background rects.
+ NSRect solidTitleClipPart = titleRect;
+ NSRect headTitleClipPart = NSZeroRect;
+ NSRect tailTitleClipPart = NSZeroRect;
+ if (isTruncatingHead) {
+ CGFloat width = NSMinX(solidBackgroundPart) - NSMinX(solidTitleClipPart);
+ NSDivideRect(solidTitleClipPart, &headTitleClipPart, &solidTitleClipPart,
+ width, NSMinXEdge);
+ }
+ if (isTruncatingTail) {
+ CGFloat width = NSMaxX(solidTitleClipPart) - NSMaxX(solidBackgroundPart);
+ NSDivideRect(solidTitleClipPart, &tailTitleClipPart, &solidTitleClipPart,
+ width, NSMaxXEdge);
+ }
+
// Draw non-gradient part without transparency layer, as light text on a dark
// background looks bad with a gradient layer.
- NSRect backgroundRect = [self drawingRectForBounds:cellFrame];
[[NSGraphicsContext currentContext] saveGraphicsState];
- [NSBezierPath clipRect:solidPart];
if ([self drawsBackground]) {
[[self backgroundColor] set];
- NSRectFillUsingOperation(backgroundRect, NSCompositeSourceOver);
+ NSRectFillUsingOperation(solidBackgroundPart, NSCompositeSourceOver);
}
// We draw the text ourselves because [super drawInteriorWithFrame:inView:]
// doesn't draw correctly if the cell draws its own background.
+ [NSBezierPath clipRect:solidTitleClipPart];
[attributedString drawInRect:offsetTitleRect];
[[NSGraphicsContext currentContext] restoreGraphicsState];
@@ -160,15 +190,15 @@
if (isTruncatingHead)
[self drawTextGradientPart:attributedString
titleRect:offsetTitleRect
- backgroundRect:backgroundRect
- clipRect:headGradientPart
+ backgroundRect:headBackgroundPart
+ clipRect:headTitleClipPart
mask:mask
fadeToRight:NO];
if (isTruncatingTail)
[self drawTextGradientPart:attributedString
titleRect:offsetTitleRect
- backgroundRect:backgroundRect
- clipRect:tailGradientPart
+ backgroundRect:tailBackgroundPart
+ clipRect:tailTitleClipPart
mask:mask
fadeToRight:YES];
@@ -197,6 +227,11 @@
return desiredCharactersToTruncateFromHead_;
}
+// The faded ends of the cell are not opaque.
+- (BOOL)isOpaque {
+ return NO;
+}
+
@end
#endif
diff --git a/AppKit/GTMFadeTruncatingTextFieldCellTest.m b/AppKit/GTMFadeTruncatingTextFieldCellTest.m
index a1bf937..c201d27 100644
--- a/AppKit/GTMFadeTruncatingTextFieldCellTest.m
+++ b/AppKit/GTMFadeTruncatingTextFieldCellTest.m
@@ -75,7 +75,7 @@
@"GTMFadeTruncatingTextFieldCellTest5",
nil);
- [field setStringValue:@"Fade on left only AA"];
+ [field setStringValue:@"Fade on left only A"];
GTMAssertObjectImageEqualToImageNamed(field,
@"GTMFadeTruncatingTextFieldCellTest6",
nil);
@@ -92,6 +92,15 @@
GTMAssertObjectImageEqualToImageNamed(field,
@"GTMFadeTruncatingTextFieldCellTest7",
nil);
+
+ // Border with a solid background color.
+ [field setTextColor:[NSColor whiteColor]];
+ [field setDrawsBackground:YES];
+ [field setBackgroundColor:[NSColor blackColor]];
+ [field setBordered:YES];
+ GTMAssertObjectImageEqualToImageNamed(field,
+ @"GTMFadeTruncatingTextFieldCellTest8",
+ nil);
}
@end
diff --git a/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest5.tiff b/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest5.tiff
index f360479..4d4635f 100644
--- a/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest5.tiff
+++ b/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest5.tiff
Binary files differ
diff --git a/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest6.tiff b/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest6.tiff
index d704a81..c8b435d 100644
--- a/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest6.tiff
+++ b/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest6.tiff
Binary files differ
diff --git a/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest8.tiff b/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest8.tiff
new file mode 100644
index 0000000..47d70bd
--- /dev/null
+++ b/AppKit/TestData/GTMFadeTruncatingTextFieldCellTest8.tiff
Binary files differ
diff --git a/GTM.xcodeproj/project.pbxproj b/GTM.xcodeproj/project.pbxproj
index db294ea..9cbed35 100644
--- a/GTM.xcodeproj/project.pbxproj
+++ b/GTM.xcodeproj/project.pbxproj
@@ -314,6 +314,7 @@
B71B91E21332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest5.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B71B91E01332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest5.tiff */; };
B71B91E31332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest6.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B71B91E11332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest6.tiff */; };
B71B92371332DA380039B2CB /* GTMFadeTruncatingTextFieldCellTest7.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B71B92361332DA380039B2CB /* GTMFadeTruncatingTextFieldCellTest7.tiff */; };
+ B7764E80133906B600AFDC7D /* GTMFadeTruncatingTextFieldCellTest8.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B7764E7F133906B600AFDC7D /* GTMFadeTruncatingTextFieldCellTest8.tiff */; };
F413908F0D75F63C00F72B31 /* GTMNSFileManager+Path.h in Headers */ = {isa = PBXBuildFile; fileRef = F413908C0D75F63C00F72B31 /* GTMNSFileManager+Path.h */; settings = {ATTRIBUTES = (Public, ); }; };
F41390900D75F63C00F72B31 /* GTMNSFileManager+Path.m in Sources */ = {isa = PBXBuildFile; fileRef = F413908D0D75F63C00F72B31 /* GTMNSFileManager+Path.m */; };
F41711350ECDFBD500B9B276 /* GTMLightweightProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = F41711320ECDFBD500B9B276 /* GTMLightweightProxy.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -790,6 +791,7 @@
B71B91E01332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest5.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMFadeTruncatingTextFieldCellTest5.tiff; sourceTree = "<group>"; };
B71B91E11332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest6.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMFadeTruncatingTextFieldCellTest6.tiff; sourceTree = "<group>"; };
B71B92361332DA380039B2CB /* GTMFadeTruncatingTextFieldCellTest7.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMFadeTruncatingTextFieldCellTest7.tiff; sourceTree = "<group>"; };
+ B7764E7F133906B600AFDC7D /* GTMFadeTruncatingTextFieldCellTest8.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = GTMFadeTruncatingTextFieldCellTest8.tiff; sourceTree = "<group>"; };
F413908C0D75F63C00F72B31 /* GTMNSFileManager+Path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNSFileManager+Path.h"; sourceTree = "<group>"; };
F413908D0D75F63C00F72B31 /* GTMNSFileManager+Path.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSFileManager+Path.m"; sourceTree = "<group>"; };
F413908E0D75F63C00F72B31 /* GTMNSFileManager+PathTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNSFileManager+PathTest.m"; sourceTree = "<group>"; };
@@ -1203,6 +1205,7 @@
B71B91E01332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest5.tiff */,
B71B91E11332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest6.tiff */,
B71B92361332DA380039B2CB /* GTMFadeTruncatingTextFieldCellTest7.tiff */,
+ B7764E7F133906B600AFDC7D /* GTMFadeTruncatingTextFieldCellTest8.tiff */,
8B1802410E25592200280961 /* GTMLargeTypeWindowMediumTextTest.gtmUTState */,
8BA9FBAC119CB08200E264C3 /* GTMLargeTypeWindowMediumTextTest.10.6.gtmUTState */,
8B1801A80E25341B00280961 /* GTMLargeTypeWindowImageTest.gtmUTState */,
@@ -2130,6 +2133,7 @@
B71B91E21332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest5.tiff in Resources */,
B71B91E31332CD680039B2CB /* GTMFadeTruncatingTextFieldCellTest6.tiff in Resources */,
B71B92371332DA380039B2CB /* GTMFadeTruncatingTextFieldCellTest7.tiff in Resources */,
+ B7764E80133906B600AFDC7D /* GTMFadeTruncatingTextFieldCellTest8.tiff in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};