git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

iOS/GBSlider.m

      1 #import "GBSlider.h"
      2 #import <objc/runtime.h>
      3 
      4 #if !__has_include(<UIKit/UISliderTrackConfiguration.h>)
      5 /* Building with older SDKs */
      6 API_AVAILABLE(ios(19.0))
      7 @interface UISliderTrackConfiguration : NSObject
      8 @property (nonatomic, readwrite) bool allowsTickValuesOnly;
      9 @property (nonatomic, readwrite) float neutralValue;
     10 + (instancetype)configurationWithNumberOfTicks:(NSInteger)ticks;
     11 @end
     12 
     13 @interface UISlider (configuration)
     14 @property(nonatomic, copy) UISliderTrackConfiguration *trackConfiguration API_AVAILABLE(ios(19.0));
     15 @end
     16 #endif
     17 
     18 static inline void temperature_tint(double temperature, double *r, double *g, double *b)
     19 {
     20     if (temperature >= 0) {
     21         *r = 1;
     22         *g = pow(1 - temperature, 0.375);
     23         if (temperature >= 0.75) {
     24             *b = 0;
     25         }
     26         else {
     27             *b = sqrt(0.75 - temperature) / sqrt(0.75);
     28         }
     29     }
     30     else {
     31         *b = 1;
     32         double squared = pow(temperature, 2);
     33         *g = 0.125 * squared + 0.3 * temperature + 1.0;
     34         *r = 0.21875 * squared + 0.5 * temperature + 1.0;
     35     }
     36 }
     37 
     38 @implementation GBSlider
     39 {
     40     GBSliderStyle _style;
     41 }
     42 
     43 - (instancetype)initWithFrame:(CGRect)frame
     44 {
     45     self = [super initWithFrame:frame];
     46     [self addTarget:self action:@selector(valueChanged) forControlEvents:UIControlEventValueChanged];
     47     self.style = GBSliderStyleTemperature;
     48     return self;
     49 }
     50 
     51 - (void)updateTint
     52 {
     53     if (_style == GBSliderStyleTemperature) {
     54         double r, g, b;
     55         temperature_tint(self.value, &r, &g, &b);
     56         self.thumbTintColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0];
     57     }
     58     if (_style == GBSliderStyleHue) {
     59         double hue = (self.value - self.minimumValue) / (self.maximumValue - self.minimumValue);
     60         double r = 0, g = 0, b =0 ;
     61         double t = fmod(hue * 6, 1);
     62         switch ((int)(hue  * 6) % 6) {
     63             case 0:
     64                 r = 1;
     65                 g = t;
     66                 break;
     67             case 1:
     68                 r = 1 - t;
     69                 g = 1;
     70                 break;
     71             case 2:
     72                 g = 1;
     73                 b = t;
     74                 break;
     75             case 3:
     76                 g = 1 - t;
     77                 b = 1;
     78                 break;
     79             case 4:
     80                 b = 1;
     81                 r = t;
     82                 break;
     83             case 5:
     84                 b = 1 - t;
     85                 r = 1;
     86                 break;
     87         }
     88         self.thumbTintColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0];
     89     }
     90 }
     91 
     92 - (void)setValue:(float)value
     93 {
     94     [super setValue:value];
     95     [self updateTint];
     96 }
     97 
     98 - (void)valueChanged
     99 {
    100     if (fabsf(self.value) < 0.05 && self.value != 0 && _style != GBSliderStyleHue) {
    101         self.value = 0;
    102     }
    103     [self updateTint];
    104 }
    105 
    106 -(UIImage *)maximumTrackImageForState:(UIControlState)state
    107 {
    108     return [[UIImage alloc] init];
    109 }
    110 
    111 
    112 -(UIImage *)minimumTrackImageForState:(UIControlState)state
    113 {
    114     return [[UIImage alloc] init];
    115 }
    116 
    117 - (void)drawRect:(CGRect)rect
    118 {
    119     bool solarium = false;
    120     if (@available(iOS 19.0, *)) {
    121         solarium = true;
    122     }
    123     CGSize size = self.bounds.size;
    124     UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(2, round(size.height / 2 - 1.5), size.width - 4, 3) cornerRadius:4];
    125     if (_style != GBSliderStyleHue) {
    126         [path appendPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(round(size.width / 2 - 1.5), 12, 3, size.height - 24) cornerRadius:4]];
    127     }
    128     if (_style == GBSliderStyleTicks) {
    129         [path appendPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 12, 3, size.height - 24) cornerRadius:4]];
    130         [path appendPath:[UIBezierPath bezierPathWithRoundedRect:CGRectMake(size.width - 3, 12, 3, size.height - 24) cornerRadius:4]];
    131     }
    132     if (_style == GBSliderStyleHue) {
    133         UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(3, round(size.height / 2 - 1.5) + 1 - solarium, size.width - 6, solarium? 2 : 1) cornerRadius:8];
    134         CGContextRef context = UIGraphicsGetCurrentContext();
    135         CGContextSaveGState(context);
    136         [path addClip];
    137         
    138         CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    139         CGColorRef colors[] = {
    140             UIColor.redColor.CGColor,
    141             UIColor.yellowColor.CGColor,
    142             UIColor.greenColor.CGColor,
    143             UIColor.cyanColor.CGColor,
    144             UIColor.blueColor.CGColor,
    145             UIColor.magentaColor.CGColor,
    146             UIColor.redColor.CGColor,
    147         };
    148         CFArrayRef colorsArray = CFArrayCreate(NULL, (const void **)colors, 7, &kCFTypeArrayCallBacks);
    149         CGGradientRef gradient = CGGradientCreateWithColors(colorspace, colorsArray, NULL);
    150         unsigned spacing = solarium? 16 : 3;
    151         CGContextDrawLinearGradient(context,
    152                                     gradient,
    153                                     (CGPoint){spacing, 0},
    154                                     (CGPoint){size.width - spacing, 0},
    155                                     kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
    156         CFRelease(gradient);
    157         CFRelease(colorsArray);
    158         CFRelease(colorspace);
    159         CGContextRestoreGState(context);
    160 
    161     }
    162     [[UIColor colorWithRed:120 / 255.0
    163                      green:120 / 255.0
    164                       blue:130 / 255.0
    165                      alpha:70 / 255.0] set];
    166     if (!solarium) {
    167         [path fill];
    168     }
    169     
    170     [super drawRect:rect];
    171 }
    172 
    173 - (void)setStyle:(GBSliderStyle)style
    174 {
    175     _style = style;
    176     if (@available(iOS 19.0, *)) {
    177         switch (_style) {
    178             case GBSliderStyleTemperature:
    179             case GBSliderStyleTicks: {
    180                 UISliderTrackConfiguration *conf = [objc_getClass("UISliderTrackConfiguration") configurationWithNumberOfTicks:3];
    181                 conf.allowsTickValuesOnly = false;
    182                 conf.neutralValue = 0.5;
    183                 self.trackConfiguration = conf;
    184                 self.maximumTrackTintColor = nil;
    185                 self.minimumTrackTintColor = nil;
    186                 break;
    187             }
    188             case GBSliderStyleHue: {
    189                 UISliderTrackConfiguration *conf = [objc_getClass("UISliderTrackConfiguration") configurationWithNumberOfTicks:0];
    190                 conf.allowsTickValuesOnly = false;
    191                 self.trackConfiguration = conf;
    192                 self.minimumTrackTintColor = [UIColor clearColor];
    193                 break;
    194             }
    195         }
    196     }
    197 }
    198 
    199 - (GBSliderStyle)style
    200 {
    201     return _style;
    202 }
    203 
    204 - (void)setFrame:(CGRect)frame
    205 {
    206     [super setFrame:frame];
    207     [self setNeedsDisplay];
    208 }
    209 
    210 @end

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.