170 lines
4.7 KiB
Mathematica
170 lines
4.7 KiB
Mathematica
|
|
//
|
||
|
|
// KSIRingView.m
|
||
|
|
// Kisai
|
||
|
|
//
|
||
|
|
// Created by Charles Magahern on 2/28/15.
|
||
|
|
// Copyright (c) 2015 zanneth. All rights reserved.
|
||
|
|
//
|
||
|
|
|
||
|
|
#import "KSIRingView.h"
|
||
|
|
|
||
|
|
@implementation KSIRingPattern {
|
||
|
|
@protected
|
||
|
|
UIColor *_color;
|
||
|
|
CGFloat _beginSegmentAngle;
|
||
|
|
CGFloat _segmentWidth;
|
||
|
|
CGFloat _segmentLengthRadians;
|
||
|
|
CGFloat _segmentIntervalRadians;
|
||
|
|
NSUInteger _segmentsCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
- (instancetype)initWithColor:(UIColor *)color
|
||
|
|
segmentLength:(CGFloat)segmentLengthInRadians
|
||
|
|
segmentsCount:(NSUInteger)segmentsCount
|
||
|
|
{
|
||
|
|
self = [super init];
|
||
|
|
if (self) {
|
||
|
|
_color = color;
|
||
|
|
_beginSegmentAngle = 0.0;
|
||
|
|
_segmentWidth = 5.0;
|
||
|
|
_segmentLengthRadians = segmentLengthInRadians;
|
||
|
|
_segmentIntervalRadians = 0.0;
|
||
|
|
_segmentsCount = segmentsCount;
|
||
|
|
}
|
||
|
|
return self;
|
||
|
|
}
|
||
|
|
|
||
|
|
- (instancetype)init
|
||
|
|
{
|
||
|
|
return [self initWithColor:[UIColor whiteColor] segmentLength:(2.0 * M_PI) segmentsCount:1];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (id)copyWithZone:(NSZone *)zone
|
||
|
|
{
|
||
|
|
return [self _copyWithZone:zone usingConcreteClass:[KSIRingPattern class]];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (id)mutableCopyWithZone:(NSZone *)zone
|
||
|
|
{
|
||
|
|
return [self _copyWithZone:zone usingConcreteClass:[KSIMutableRingPattern class]];
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - Internal
|
||
|
|
|
||
|
|
- (id)_copyWithZone:(NSZone *)zone usingConcreteClass:(Class)concreteClass
|
||
|
|
{
|
||
|
|
KSIRingPattern *copy = [[concreteClass allocWithZone:zone] init];
|
||
|
|
copy->_color = _color;
|
||
|
|
copy->_beginSegmentAngle = _beginSegmentAngle;
|
||
|
|
copy->_segmentWidth = _segmentWidth;
|
||
|
|
copy->_segmentLengthRadians = _segmentLengthRadians;
|
||
|
|
copy->_segmentIntervalRadians = _segmentIntervalRadians;
|
||
|
|
copy->_segmentsCount = _segmentsCount;
|
||
|
|
return copy;
|
||
|
|
}
|
||
|
|
|
||
|
|
@end
|
||
|
|
|
||
|
|
// -----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
@implementation KSIMutableRingPattern
|
||
|
|
@dynamic color;
|
||
|
|
@dynamic beginSegmentAngle;
|
||
|
|
@dynamic segmentWidth;
|
||
|
|
@dynamic segmentLengthRadians;
|
||
|
|
@dynamic segmentIntervalRadians;
|
||
|
|
@dynamic segmentsCount;
|
||
|
|
|
||
|
|
|
||
|
|
- (void)setColor:(UIColor *)color { _color = color; }
|
||
|
|
- (void)setBeginSegmentAngle:(CGFloat)beginSegmentAngle { _beginSegmentAngle = beginSegmentAngle; }
|
||
|
|
- (void)setSegmentWidth:(CGFloat)segmentWidth { _segmentWidth = segmentWidth; }
|
||
|
|
- (void)setSegmentLengthRadians:(CGFloat)segmentLengthRadians { _segmentLengthRadians = segmentLengthRadians; }
|
||
|
|
- (void)setSegmentIntervalRadians:(CGFloat)segmentIntervalRadians { _segmentIntervalRadians = segmentIntervalRadians; }
|
||
|
|
- (void)setSegmentsCount:(NSUInteger)segmentsCount { _segmentsCount = segmentsCount; }
|
||
|
|
|
||
|
|
@end
|
||
|
|
|
||
|
|
// -----------------------------------------------------------------------------
|
||
|
|
|
||
|
|
@implementation KSIRingView {
|
||
|
|
NSMutableArray *_ringPatterns;
|
||
|
|
}
|
||
|
|
|
||
|
|
- (instancetype)initWithFrame:(CGRect)frame
|
||
|
|
{
|
||
|
|
self = [super initWithFrame:frame];
|
||
|
|
if (self) {
|
||
|
|
_ringPatterns = [[NSMutableArray alloc] init];
|
||
|
|
}
|
||
|
|
return self;
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - Accessors
|
||
|
|
|
||
|
|
- (NSArray *)ringPatterns
|
||
|
|
{
|
||
|
|
return _ringPatterns;
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - API
|
||
|
|
|
||
|
|
- (void)addRingPattern:(KSIRingPattern *)pattern
|
||
|
|
{
|
||
|
|
[_ringPatterns addObject:[pattern copy]];
|
||
|
|
[self setNeedsDisplay];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (void)insertRingPattern:(KSIRingPattern *)pattern atIndex:(NSUInteger)index
|
||
|
|
{
|
||
|
|
[_ringPatterns insertObject:[pattern copy] atIndex:index];
|
||
|
|
[self setNeedsDisplay];
|
||
|
|
}
|
||
|
|
|
||
|
|
- (void)removeAllRingPatterns
|
||
|
|
{
|
||
|
|
[_ringPatterns removeAllObjects];
|
||
|
|
[self setNeedsDisplay];
|
||
|
|
}
|
||
|
|
|
||
|
|
#pragma mark - Drawing
|
||
|
|
|
||
|
|
- (void)drawRect:(CGRect)rect
|
||
|
|
{
|
||
|
|
const CGFloat radius = rint(rect.size.height / 2.0 - 1.0);
|
||
|
|
const CGPoint center = {
|
||
|
|
.x = rint(rect.size.width / 2.0),
|
||
|
|
.y = rint(rect.size.height / 2.0)
|
||
|
|
};
|
||
|
|
|
||
|
|
CGContextRef ctx = UIGraphicsGetCurrentContext();
|
||
|
|
CGFloat currentRadius = radius;
|
||
|
|
|
||
|
|
for (KSIRingPattern *ringPattern in _ringPatterns) {
|
||
|
|
if (![ringPattern.color isEqual:[UIColor clearColor]]) {
|
||
|
|
NSUInteger segmentsCount = ringPattern.segmentsCount;
|
||
|
|
CGFloat currentAngle = ringPattern.beginSegmentAngle;
|
||
|
|
CGFloat segmentWidth = ringPattern.segmentWidth;
|
||
|
|
|
||
|
|
[ringPattern.color setStroke];
|
||
|
|
|
||
|
|
for (unsigned i = 0; i < segmentsCount; ++i) {
|
||
|
|
CGFloat beginAngle = currentAngle;
|
||
|
|
CGFloat endAngle = beginAngle + ringPattern.segmentLengthRadians;
|
||
|
|
CGContextAddArc(ctx, center.x, center.y, currentRadius - (segmentWidth / 2.0), beginAngle, endAngle, NO);
|
||
|
|
|
||
|
|
if (i < segmentsCount - 1) {
|
||
|
|
currentAngle += ringPattern.segmentIntervalRadians;
|
||
|
|
}
|
||
|
|
|
||
|
|
CGContextSetLineWidth(ctx, segmentWidth);
|
||
|
|
CGContextStrokePath(ctx);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
currentRadius -= ringPattern.segmentWidth - 1.0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@end
|