システム環境設定 -> デスクトップ & スクリーン セーバー -> スクリーン セーバー -> スクリーン セーバーの開始でスライダーとまったく同じように動作するカスタム NSSlider を作成する方法:
NSSliderCell をオーバーライドした continueTracking: でサブクラス化しようとしましたが、期待どおりに動作しません。
システム環境設定 -> デスクトップ & スクリーン セーバー -> スクリーン セーバー -> スクリーン セーバーの開始でスライダーとまったく同じように動作するカスタム NSSlider を作成する方法:
NSSliderCell をオーバーライドした continueTracking: でサブクラス化しようとしましたが、期待どおりに動作しません。
私は少し遊んで、少なくともNSSliderCell
サブクラスでかなり良いスタートを切りました。
MDSliderCell.h
:
#import <Cocoa/Cocoa.h>
@interface MDSliderCell : NSSliderCell {
BOOL tracking;
}
@end
MDSliderCell.m
:
#import "MDSliderCell.h"
@implementation MDSliderCell
- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView {
if ([self numberOfTickMarks] > 0) tracking = YES;
return [super startTrackingAt:startPoint inView:controlView];
}
#define MD_SNAPPING 10.0
- (BOOL)continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint
inView:(NSView *)controlView {
if (tracking) {
NSUInteger count = [self numberOfTickMarks];
for (NSUInteger i = 0; i < count; i++) {
NSRect tickMarkRect = [self rectOfTickMarkAtIndex:i];
if (ABS(tickMarkRect.origin.x - currentPoint.x) <= MD_SNAPPING) {
[self setAllowsTickMarkValuesOnly:YES];
} else if (ABS(tickMarkRect.origin.x - currentPoint.x) >= MD_SNAPPING &&
ABS(tickMarkRect.origin.x - currentPoint.x) <= MD_SNAPPING *2) {
[self setAllowsTickMarkValuesOnly:NO];
}
}
}
return [super continueTracking:lastPoint at:currentPoint inView:controlView];
}
- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint
inView:(NSView *)controlView mouseIsUp:(BOOL)flag {
[super stopTracking:lastPoint at:stopPoint inView:controlView mouseIsUp:flag];
}
@end
基本的に、実行中に-continueTracking:at:inView:
目盛りにどれだけ近いかを確認し、十分に近い場合は、目盛り値のみを許可するオプションをオンにします。これにより、目盛りにスナップし、十分に離れたら、別の目盛りに十分近づくまで「目盛りのみ」オプションをオフにします。