[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: SMDoubleSlider usability on GNUstep
From: |
David Chisnall |
Subject: |
Re: SMDoubleSlider usability on GNUstep |
Date: |
Tue, 20 Feb 2018 14:55:04 +0000 |
On 20 Feb 2018, at 14:30, Yavor Doganov <yavor@gnu.org> wrote:
>
> I think this condition is always false. _cell.has_valid_object_value
> is NO and _object_value is nil. So it jumps to NSCell.m:269 and
> SMDoubleSliderCell's -stringValue is called which calls -stringHiValue
> which in turn calls -doubleHiValue and from there the infinite
> recursion is in place.
>
> At least this is what I observe in the debugger.
Ah, that makes sense - I’d missed that in the trace. So now the question is
what happens when you call -doubleValue on an NSCell in Cocoa when it has a
string value? Here’s a little test program that finds out:
#import <Cocoa/Cocoa.h>
@interface Proxy : NSProxy
{
@public
id obj;
}
@end
@implementation Proxy
- (BOOL)respondsToSelector: (SEL)aSelector
{
return [obj respondsToSelector: aSelector];
}
- (NSMethodSignature*)methodSignatureForSelector: (SEL)aSelector
{
return [obj methodSignatureForSelector: aSelector];
}
- (void)forwardInvocation: (NSInvocation*)anInvocation
{
NSLog(@"%@ set to proxy", anInvocation);
[anInvocation invokeWithTarget: obj];
}
@end
@interface Test : NSActionCell @end
@implementation Test
- (float)floatValue
{
NSLog(@"-floatValue called\n");
return [super floatValue];
}
- (NSString*)stringValue
{
NSLog(@"-stringValue called\n");
return [super stringValue];
}
@end
int main(void)
{
@autoreleasepool
{
Test *t = [Test new];
Proxy *p = [Proxy alloc];
p->obj = @"0.23";
[t setObjectValue: t];
NSLog(@"Querying");
NSLog(@"%f", [t floatValue]);
}
}
The output is:
2018-02-20 14:46:39.917 a.out[85231:11731363] Querying
2018-02-20 14:46:39.917 a.out[85231:11731363] -floatValue called
2018-02-20 14:46:39.917 a.out[85231:11731363] 0.000000
So, from this we learn that Cocoa’s NSCell implementation doesn’t call any
methods on either itself or the object to find the floating point value. This
is a bit odd, but at the very least we should fix GNUstep’s NSCell to query the
object and not itself to find the string value. The correct fix is probably:
- (float) floatValue
{
if (_cell.has_valid_object_value == YES)
{
if ([_object_value respondsToSelector: @selector(floatValue)]))
{
return [_object_value floatValue];
}
if ([_object_value respondsToSelector: @selector(stringValue)]))
{
return [[_object_value stringValue] floatValue];
}
}
return 0;
}
And apply similar fixes to the other *Value methods in NSCell.
You can hack around this brokenness by including the above method in a category
on NSCell in your application (though please remember to remove it once GNUstep
is fixed!).
David