-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix 1351 wrong nsstringdrawer truncating text #28
base: master
Are you sure you want to change the base?
Fix 1351 wrong nsstringdrawer truncating text #28
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool; some comments below. In general, please watch out for memory leaks and for spacing. alignment.
Yes, perhaps my preferred objc style is slightly unconventional; it's closer to GNUstep's than to Apple's. Where Apple would write:
-(void)forwardInvocation:(NSInvocation*)anInvocation;
GNUstep would write:
- (void) forwardInvocation: (NSInvocation*)anInvocation;
I would write:
- (void) forwardInvocation: (NSInvocation*) anInvocation;
Hope this makes sense!
AppKit/NSStringDrawer.m
Outdated
[self _clipAndDrawInRect: rect | ||
lineBreakMode: NSLineBreakByTruncatingTail]; | ||
} else { | ||
[self _clipAndDrawInRect: rect | ||
lineBreakMode: NSLineBreakByClipping]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry in advance for nitpicking, but: code style!
Here in particular, the colons have to be vertically aligned:
[self _clipAndDrawInRect: rect | |
lineBreakMode: NSLineBreakByTruncatingTail]; | |
} else { | |
[self _clipAndDrawInRect: rect | |
lineBreakMode: NSLineBreakByClipping]; | |
[self _clipAndDrawInRect: rect | |
lineBreakMode: NSLineBreakByTruncatingTail]; | |
} else { | |
[self _clipAndDrawInRect: rect | |
lineBreakMode: NSLineBreakByClipping]; |
AppKit/NSStringDrawer.m
Outdated
[self _clipAndDrawInRect: rect truncatingTail: YES]; | ||
} | ||
|
||
- (void)_clipAndDrawInRect:(NSRect)rect lineBreakMode:(NSLineBreakMode)lineBreakMode { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- (void)_clipAndDrawInRect:(NSRect)rect lineBreakMode:(NSLineBreakMode)lineBreakMode { | |
- (void) _clipAndDrawInRect: (NSRect) rect lineBreakMode: (NSLineBreakMode) lineBreakMode { |
or probably even
- (void)_clipAndDrawInRect:(NSRect)rect lineBreakMode:(NSLineBreakMode)lineBreakMode { | |
- (void) _clipAndDrawInRect: (NSRect) rect | |
lineBreakMode: (NSLineBreakMode) lineBreakMode | |
{ |
AppKit/NSTableHeaderCell.m
Outdated
[[self attributedStringValue] | ||
_clipAndDrawInRect: [self titleRectForBounds: cellFrame] | ||
truncatingTail: (_lineBreakMode > NSLineBreakByClipping)]; | ||
lineBreakMode: _lineBreakMode]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lineBreakMode: _lineBreakMode]; | |
lineBreakMode: _lineBreakMode]; |
AppKit/NSStringDrawer.m
Outdated
NSDictionary *attributes = [string attributesAtIndex:[string length] - 1 effectiveRange:NULL]; | ||
NSAttributedString *ellipsis = [[NSAttributedString alloc] initWithString:@"..." attributes:attributes]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NSDictionary *attributes = [string attributesAtIndex:[string length] - 1 effectiveRange:NULL]; | |
NSAttributedString *ellipsis = [[NSAttributedString alloc] initWithString:@"..." attributes:attributes]; | |
NSDictionary *attributes = [string attributesAtIndex: [string length] - 1 | |
effectiveRange: NULL]; | |
NSAttributedString *ellipsis = [[NSAttributedString alloc] initWithString: @"..." | |
attributes: attributes]; |
Also, you're leaking the ellipsis
now, aren't you? It was autoreleased previously.
NSAttributedString *ellipsis = [[NSAttributedString alloc] initWithString:@"..." attributes:attributes]; | ||
|
||
NSInteger left = 0; | ||
NSInteger right = [string length]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When writing binary search-like algorithms, I find it helpful to explicitly spell out the invariant. For instance:
// INVARIANT: The string truncated to 'left' characters always fits,
// and truncated to 'right' characters always does not fit.
Note that your invariant seems to be different -- or is it? What's yours, exactly?
AppKit/NSStringDrawer.m
Outdated
NSMutableAttributedString *tmpString; | ||
|
||
while (left < right) { | ||
mid = (left + right) / 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I wonder if we could do better than the regular binary search here, by taking advantage of the fact that we're not only getting a boolean (fits / doesn't fit), but the actual width measurements. We could estimate mid
based on the measurements. It'd still be confined between left
and right
, and we'd still be converging towards the answer, but hopefully we can do it in fewer steps.
For instance if we know that at left
= 10 the string takes up 100 px, and at right
= 20 it takes up 200px, and our room for the string is 110 px wide, mid
= 11 would be a better estimate than 15. We only have to ensure that it's strictly greater than left
and less than right
, otherwise we'll loop endlessly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to do it this way but it didn't work and was very slow.
AppKit/NSStringDrawer.m
Outdated
switch (lineBreakMode) { | ||
case NSLineBreakByTruncatingHead: | ||
clippedTitle = [string attributedSubstringFromRange:NSMakeRange(mid, [string length] - mid)]; | ||
tmpString = [[[NSAttributedString alloc] initWithAttributedString:ellipsis] mutableCopy]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're leaking the pre-mutableCopy
string too. Are you perhaps used to programming with ARC?
|
||
case NSLineBreakByTruncatingMiddle: | ||
clippedTitle = [string attributedSubstringFromRange:NSMakeRange(0, mid)]; | ||
NSAttributedString *clippedTail = [string attributedSubstringFromRange:NSMakeRange([string length] - mid, mid)]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So here's an issue: if mid
is high enough, you're going to start duplicating parts of the string, e.g. if string = @"Hello world"
and mid
is 7, you'd get clippedTitle = @"Hello w", clippedTail = @"o world", tmpString = @"Hello w...o world"
.
This new string mostly likely wouldn't fit (considering the original didn't, since we're inside this if
), but better prevent this from happening in the first place, i.e. start from right = [string length] / 2
for the NSLineBreakByTruncatingMiddle
mode.
I have submitted a new version with some of the proposed changes. However, others, more complex, are beyond my knowledge." |
I merged the new AppKit code with this branch, is there a problem to merge now? |
What changes do you think are beyond your knowledge? If you elaborate a bit I'm sure myself or someone else may be able to help! Don't forget about the discord server, as the learning channel is a great place to gain knowledge. |
Any progress on this ? |
Not that I have seen, the remaining issues brought up by the reviewer still need addressed, and the commits squashed. I'm happy to provide help in any way I can |
This fix solves two problems:
This pull request is related with reported bug:
darlinghq/darling#1351
That can be closed after the merging