Горячее создание пользовательского NSSlider, такого как стартовая заставка: ползунок в Системных настройках

Как создать собственный NSSlider, который работает точно так же, как слайдер в «Системных настройках» -> «Рабочий стол и заставка» -> «Экранная заставка» -> «Начать заставку»:

Я попытался создать подкласс NSSliderCell с переопределенным continueTracking: но он не работает должным образом.


person andron    schedule 30.04.2011    source источник
comment
На вкладке заставки «Мои системные настройки» нет эзотерического ползунка. Не могли бы вы сделать скриншот и сказать нам, что именно вы хотите воспроизвести?   -  person zneak    schedule 30.04.2011
comment
Ползунок останавливается на отметках, но вы также можете установить положение между отметками. Если вы перетащите ползунок, вы увидите, что я имею в виду.   -  person andron    schedule 30.04.2011


Ответы (1)


Я немного поиграл и, по крайней мере, неплохо начал с подкласса 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: он проверяет, насколько он близок к отметке, и если он достаточно близок, он включает опцию, разрешающую только значения отметок. Это приводит к тому, что он привязывается к отметке, а затем, как только вы отойдете достаточно далеко, вы отключите опцию «только отметка», пока не подойдете достаточно близко к другой отметке.

person NSGod    schedule 30.04.2011