You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

549 lines
25 KiB

5 years ago
  1. //
  2. // M13ProgressViewSegmentedBar.m
  3. // M13ProgressView
  4. //
  5. /*Copyright (c) 2013 Brandon McQuilkin
  6. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  7. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  8. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  9. */
  10. #import "M13ProgressViewSegmentedBar.h"
  11. @interface M13ProgressViewSegmentedBar ()
  12. /**The start progress for the progress animation.*/
  13. @property (nonatomic, assign) CGFloat animationFromValue;
  14. /**The end progress for the progress animation.*/
  15. @property (nonatomic, assign) CGFloat animationToValue;
  16. /**The start time interval for the animaiton.*/
  17. @property (nonatomic, assign) CFTimeInterval animationStartTime;
  18. /**Link to the display to keep animations in sync.*/
  19. @property (nonatomic, strong) CADisplayLink *displayLink;
  20. /**Allow us to write to the progress.*/
  21. @property (nonatomic, readwrite) CGFloat progress;
  22. /**The layer that progress is shown on.*/
  23. @property (nonatomic, retain) CAShapeLayer *segmentsLayer;
  24. /**The action currently being performed.*/
  25. @property (nonatomic, assign) M13ProgressViewAction currentAction;
  26. @end
  27. @implementation M13ProgressViewSegmentedBar
  28. {
  29. NSInteger indeterminateIndex;
  30. NSTimer *indeterminateTimer;
  31. NSArray *segmentColorsPrimary;
  32. NSArray *segmentColorsBackground;
  33. }
  34. @dynamic progress;
  35. #pragma mark Initalization and setup
  36. - (id)init
  37. {
  38. self = [super init];
  39. if (self) {
  40. [self setup];
  41. }
  42. return self;
  43. }
  44. - (id)initWithFrame:(CGRect)frame
  45. {
  46. self = [super initWithFrame:frame];
  47. if (self) {
  48. [self setup];
  49. }
  50. return self;
  51. }
  52. - (id)initWithCoder:(NSCoder *)aDecoder
  53. {
  54. self = [super initWithCoder:aDecoder];
  55. if (self) {
  56. [self setup];
  57. }
  58. return self;
  59. }
  60. - (void)setup
  61. {
  62. //Set own background color
  63. self.backgroundColor = [UIColor clearColor];
  64. //Set default colors
  65. self.primaryColor = [UIColor colorWithRed:0 green:122/255.0 blue:1.0 alpha:1.0];
  66. self.secondaryColor = [UIColor colorWithRed:181/255.0 green:182/255.0 blue:183/255.0 alpha:1.0];
  67. _successColor = [UIColor colorWithRed:63.0f/255.0f green:226.0f/255.0f blue:80.0f/255.0f alpha:1];
  68. _failureColor = [UIColor colorWithRed:249.0f/255.0f green:37.0f/255.0f blue:0 alpha:1];
  69. //ProgressLayer
  70. _segmentsLayer = [CAShapeLayer layer];
  71. _segmentsLayer.frame = self.bounds;
  72. [self.layer addSublayer:_segmentsLayer];
  73. //Set defauts
  74. self.animationDuration = .3;
  75. _progressDirection = M13ProgressViewSegmentedBarProgressDirectionLeftToRight;
  76. self.numberOfSegments = 16;
  77. _segmentSeparation = 10.0;
  78. _cornerRadius = 2.0;
  79. //Layout
  80. [self layoutSubviews];
  81. }
  82. #pragma mark Appearance
  83. - (void)setPrimaryColor:(UIColor *)primaryColor
  84. {
  85. [super setPrimaryColor:primaryColor];
  86. [self resetColorsForSegments];
  87. [self setNeedsDisplay];
  88. }
  89. - (void)setSecondaryColor:(UIColor *)secondaryColor
  90. {
  91. [super setSecondaryColor:secondaryColor];
  92. [self resetColorsForSegments];
  93. [self setNeedsDisplay];
  94. }
  95. - (void)setSuccessColor:(UIColor *)successColor
  96. {
  97. _successColor = successColor;
  98. [self setNeedsDisplay];
  99. }
  100. - (void)setFailureColor:(UIColor *)failureColor
  101. {
  102. _failureColor = failureColor;
  103. [self setNeedsDisplay];
  104. }
  105. - (void)setProgressDirection:(M13ProgressViewSegmentedBarProgressDirection)progressDirection
  106. {
  107. _progressDirection = progressDirection;
  108. [self layoutSubviews];
  109. [self setNeedsDisplay];
  110. }
  111. - (void)setNumberOfSegments:(NSInteger)numberOfSegments
  112. {
  113. _numberOfSegments = numberOfSegments;
  114. //First remove all the sub layers
  115. _segmentsLayer.sublayers = nil;
  116. //Then add sub layers equal to the number of segments
  117. for (int i = 0; i < numberOfSegments; i++) {
  118. CAShapeLayer *segment = [CAShapeLayer layer];
  119. segment.frame = self.bounds;
  120. [_segmentsLayer addSublayer:segment];
  121. }
  122. //Reset the colors for the segements
  123. [self resetColorsForSegments];
  124. [self setNeedsDisplay];
  125. }
  126. - (void)setSegmentSeparation:(CGFloat)segmentSeparation
  127. {
  128. _segmentSeparation = segmentSeparation;
  129. [self setNeedsDisplay];
  130. }
  131. - (void)setSegmentShape:(M13ProgressViewSegmentedBarSegmentShape)segmentShape
  132. {
  133. _segmentShape = segmentShape;
  134. [self setNeedsDisplay];
  135. }
  136. - (void)setPrimaryColors:(NSArray *)primaryColors
  137. {
  138. _primaryColors = primaryColors;
  139. [self resetColorsForSegments];
  140. }
  141. - (void)setSecondaryColors:(NSArray *)secondaryColors
  142. {
  143. _secondaryColors = secondaryColors;
  144. [self resetColorsForSegments];
  145. }
  146. #pragma mark Actions
  147. - (void)setProgress:(CGFloat)progress animated:(BOOL)animated
  148. {
  149. if (animated == NO) {
  150. if (_displayLink) {
  151. //Kill running animations
  152. [_displayLink invalidate];
  153. _displayLink = nil;
  154. }
  155. [super setProgress:progress animated:NO];
  156. [self setNeedsDisplay];
  157. } else {
  158. _animationStartTime = CACurrentMediaTime();
  159. _animationFromValue = self.progress;
  160. _animationToValue = progress;
  161. if (!_displayLink) {
  162. //Create and setup the display link
  163. [self.displayLink invalidate];
  164. self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(animateProgress:)];
  165. [self.displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSRunLoopCommonModes];
  166. } /*else {
  167. //Reuse the current display link
  168. }*/
  169. }
  170. }
  171. - (void)animateProgress:(CADisplayLink *)displayLink
  172. {
  173. dispatch_async(dispatch_get_main_queue(), ^{
  174. CGFloat dt = (displayLink.timestamp - self.animationStartTime) / self.animationDuration;
  175. if (dt >= 1.0) {
  176. //Order is important! Otherwise concurrency will cause errors, because setProgress: will detect an animation in progress and try to stop it by itself. Once over one, set to actual progress amount. Animation is over.
  177. [self.displayLink invalidate];
  178. self.displayLink = nil;
  179. [super setProgress:self.animationToValue animated:NO];
  180. [self setNeedsDisplay];
  181. return;
  182. }
  183. //Set progress
  184. [super setProgress:self.animationFromValue + dt * (self.animationToValue - self.animationFromValue) animated:YES];
  185. [self setNeedsDisplay];
  186. });
  187. }
  188. - (void)performAction:(M13ProgressViewAction)action animated:(BOOL)animated
  189. {
  190. if (action == M13ProgressViewActionNone && _currentAction != M13ProgressViewActionNone) {
  191. _currentAction = action;
  192. [self setNeedsDisplay];
  193. [CATransaction begin];
  194. for (int i = 0; i < _numberOfSegments; i++) {
  195. CAShapeLayer *layer = (CAShapeLayer *)_segmentsLayer.sublayers[i];
  196. CABasicAnimation *barAnimation = [self barColorAnimation];
  197. barAnimation.fromValue = (id)layer.fillColor;
  198. barAnimation.toValue = (id)[self colorForSegment:i].CGColor;
  199. [layer addAnimation:barAnimation forKey:@"fillColor"];
  200. }
  201. [CATransaction commit];
  202. } else if (action == M13ProgressViewActionSuccess && _currentAction != M13ProgressViewActionSuccess) {
  203. _currentAction = action;
  204. [self setNeedsDisplay];
  205. [CATransaction begin];
  206. for (int i = 0; i < _numberOfSegments; i++) {
  207. CAShapeLayer *layer = (CAShapeLayer *)_segmentsLayer.sublayers[i];
  208. CABasicAnimation *barAnimation = [self barColorAnimation];
  209. barAnimation.fromValue = (id)layer.fillColor;
  210. barAnimation.toValue = (id)_successColor.CGColor;
  211. [layer addAnimation:barAnimation forKey:@"fillColor"];
  212. }
  213. [CATransaction commit];
  214. } else if (action == M13ProgressViewActionFailure && _currentAction != M13ProgressViewActionFailure) {
  215. _currentAction = action;
  216. [self setNeedsDisplay];
  217. [CATransaction begin];
  218. for (int i = 0; i < _numberOfSegments; i++) {
  219. CAShapeLayer *layer = (CAShapeLayer *)_segmentsLayer.sublayers[i];
  220. CABasicAnimation *barAnimation = [self barColorAnimation];
  221. barAnimation.fromValue = (id)layer.fillColor;
  222. barAnimation.toValue = (id)_failureColor.CGColor;
  223. [layer addAnimation:barAnimation forKey:@"fillColor"];
  224. }
  225. [CATransaction commit];
  226. }
  227. }
  228. - (CABasicAnimation *)barColorAnimation
  229. {
  230. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"fillColor"];
  231. animation.duration = 2 * self.animationDuration;
  232. animation.repeatCount = 1;
  233. //Prevent the animation from resetting
  234. animation.fillMode = kCAFillModeForwards;
  235. animation.removedOnCompletion = NO;
  236. return animation;
  237. }
  238. - (void)setIndeterminate:(BOOL)indeterminate
  239. {
  240. [super setIndeterminate:indeterminate];
  241. if (indeterminate) {
  242. indeterminateTimer = [NSTimer timerWithTimeInterval:(1.5 / (float)_numberOfSegments) target:self selector:@selector(drawIndeterminate) userInfo:Nil repeats:YES];
  243. [[NSRunLoop mainRunLoop] addTimer:indeterminateTimer forMode:NSRunLoopCommonModes];
  244. } else {
  245. [indeterminateTimer invalidate];
  246. [self setNeedsDisplay];
  247. }
  248. }
  249. #pragma mark Layout
  250. - (void)layoutSubviews
  251. {
  252. [super layoutSubviews];
  253. _segmentsLayer.frame = self.bounds;
  254. for (CAShapeLayer *layer in _segmentsLayer.sublayers) {
  255. layer.frame = self.bounds;
  256. }
  257. }
  258. - (CGSize)intrinsicContentSize
  259. {
  260. return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
  261. }
  262. #pragma mark Drawing
  263. - (void)resetColorsForSegments
  264. {
  265. if (_primaryColors == nil) {
  266. NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:_numberOfSegments];
  267. for (int i = 0; i < _numberOfSegments; i++) {
  268. [tempArray addObject:self.primaryColor];
  269. }
  270. segmentColorsPrimary = tempArray.copy;
  271. }
  272. if (_numberOfSegments == _primaryColors.count) {
  273. segmentColorsPrimary = _primaryColors;
  274. }
  275. if (_numberOfSegments != _primaryColors.count && _primaryColors.count != 0) {
  276. NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:_numberOfSegments];
  277. for (int i = 0; i < _numberOfSegments; i++) {
  278. if (_numberOfSegments > _primaryColors.count) {
  279. [tempArray addObject:_primaryColors[i]];
  280. } else {
  281. [tempArray addObject:_primaryColors[i % _primaryColors.count]];
  282. }
  283. }
  284. segmentColorsPrimary = tempArray.copy;
  285. }
  286. if (_secondaryColors == nil) {
  287. NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:_numberOfSegments];
  288. for (int i = 0; i < _numberOfSegments; i++) {
  289. [tempArray addObject:self.secondaryColor];
  290. }
  291. segmentColorsBackground = tempArray.copy;
  292. }
  293. if (_numberOfSegments == _secondaryColors.count) {
  294. segmentColorsBackground = _secondaryColors;
  295. }
  296. if (_numberOfSegments != _secondaryColors.count && _secondaryColors.count != 0) {
  297. NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:_numberOfSegments];
  298. for (int i = 0; i < _numberOfSegments; i++) {
  299. if (_numberOfSegments > _secondaryColors.count) {
  300. [tempArray addObject:_secondaryColors[i]];
  301. } else {
  302. [tempArray addObject:_secondaryColors[i % _secondaryColors.count]];
  303. }
  304. }
  305. segmentColorsBackground = tempArray.copy;
  306. }
  307. }
  308. - (NSInteger)numberOfFullSegments
  309. {
  310. return (NSInteger)floorf((float)self.progress * (float)_numberOfSegments);
  311. }
  312. - (UIColor *)colorForSegment:(NSUInteger)index
  313. {
  314. if (index < [self numberOfFullSegments]) {
  315. return segmentColorsPrimary[index];
  316. } else {
  317. return segmentColorsBackground[index];
  318. }
  319. }
  320. - (void)drawRect:(CGRect)rect
  321. {
  322. [super drawRect:rect];
  323. if (!self.indeterminate) {
  324. [self drawProgress];
  325. }
  326. }
  327. - (void)drawProgress
  328. {
  329. //Calculate the segment width (totalWidth - totalSeparationwidth / numberOfSegments
  330. CGFloat segmentWidth = 0;
  331. if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionLeftToRight || _progressDirection == M13ProgressViewSegmentedBarProgressDirectionRightToLeft) {
  332. segmentWidth = (self.bounds.size.width - ((_numberOfSegments - 1) * _segmentSeparation)) / _numberOfSegments;
  333. } else {
  334. segmentWidth = (self.bounds.size.height - ((_numberOfSegments - 1) * _segmentSeparation)) / _numberOfSegments;
  335. }
  336. //Calculate the corner radius
  337. CGFloat cornerRadius = 0;
  338. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  339. cornerRadius = _cornerRadius;
  340. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  341. cornerRadius = floorf(self.bounds.size.height < segmentWidth ? (float)self.bounds.size.height / 2.0f : (float)segmentWidth / 2.0f);
  342. }
  343. //Iterate through all the segments that are full.
  344. for (int i = 0; i < _numberOfSegments; i++) {
  345. UIBezierPath *path = [UIBezierPath bezierPath];
  346. //Move to top left of rectangle
  347. if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionLeftToRight) {
  348. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRectangle) {
  349. CGRect rect = CGRectMake(i * (segmentWidth + _segmentSeparation), 0, segmentWidth, self.bounds.size.height);
  350. path = [UIBezierPath bezierPathWithRect:rect];
  351. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  352. CGRect rect = CGRectMake(i * (segmentWidth + _segmentSeparation), 0, segmentWidth, self.bounds.size.height);
  353. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  354. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  355. CGRect rect = CGRectMake(i * (segmentWidth + _segmentSeparation), (self.bounds.size.height - (2 * cornerRadius)) / 2, 2 * cornerRadius, 2 * cornerRadius);
  356. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  357. }
  358. } else if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionRightToLeft) {
  359. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRectangle) {
  360. CGRect rect = CGRectMake(self.bounds.size.width - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, 0, segmentWidth, self.bounds.size.height);
  361. path = [UIBezierPath bezierPathWithRect:rect];
  362. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  363. CGRect rect = CGRectMake(self.bounds.size.width - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, 0, segmentWidth, self.bounds.size.height);
  364. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  365. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  366. CGRect rect = CGRectMake(self.bounds.size.width - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, (self.bounds.size.height - (2 * cornerRadius)) / 2, 2 * cornerRadius, 2 * cornerRadius);
  367. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  368. }
  369. } else if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionBottomToTop) {
  370. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRectangle) {
  371. CGRect rect = CGRectMake(0, self.bounds.size.height - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, self.bounds.size.width, segmentWidth);
  372. path = [UIBezierPath bezierPathWithRect:rect];
  373. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  374. CGRect rect = CGRectMake(0, self.bounds.size.height - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, self.bounds.size.width, segmentWidth);
  375. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  376. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  377. CGRect rect = CGRectMake((self.bounds.size.width - (2 * cornerRadius)) / 2, self.bounds.size.height - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, 2 * cornerRadius, 2 * cornerRadius);
  378. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  379. }
  380. } else if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionTopToBottom) {
  381. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRectangle) {
  382. CGRect rect = CGRectMake(0, (i * (segmentWidth + _segmentSeparation)), self.bounds.size.width, segmentWidth);
  383. path = [UIBezierPath bezierPathWithRect:rect];
  384. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  385. CGRect rect = CGRectMake(0, (i * (segmentWidth + _segmentSeparation)), self.bounds.size.width, segmentWidth);
  386. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  387. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  388. CGRect rect = CGRectMake((self.bounds.size.width - (2 * cornerRadius)) / 2, (i * (segmentWidth + _segmentSeparation)), 2 * cornerRadius, 2 * cornerRadius);
  389. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  390. }
  391. }
  392. //Add segment to the proper layer, and color it
  393. CAShapeLayer *layer = (CAShapeLayer *)_segmentsLayer.sublayers[i];
  394. layer.path = path.CGPath;
  395. layer.fillColor = [self colorForSegment:i].CGColor;
  396. }
  397. }
  398. - (void)drawIndeterminate
  399. {
  400. //Calculate the segment width (totalWidth - totalSeparationwidth / numberOfSegments
  401. CGFloat segmentWidth = 0;
  402. if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionLeftToRight || _progressDirection == M13ProgressViewSegmentedBarProgressDirectionRightToLeft) {
  403. segmentWidth = (self.bounds.size.width - ((_numberOfSegments - 1) * _segmentSeparation)) / _numberOfSegments;
  404. } else {
  405. segmentWidth = (self.bounds.size.height - ((_numberOfSegments - 1) * _segmentSeparation)) / _numberOfSegments;
  406. }
  407. //Calculate the corner radius
  408. CGFloat cornerRadius = 0;
  409. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  410. cornerRadius = _cornerRadius;
  411. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  412. cornerRadius = floorf(self.bounds.size.height < segmentWidth ? (float)self.bounds.size.height / 2.0f : (float)segmentWidth / 2.0f);
  413. }
  414. //What index will the segments be colored from.
  415. NSInteger numberOfSegmentsToBeColored = _numberOfSegments / 4;
  416. //Iterate through all the segments that are full.
  417. for (int i = 0; i < _numberOfSegments; i++) {
  418. UIBezierPath *path = [UIBezierPath bezierPath];
  419. //Move to top left of rectangle
  420. if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionLeftToRight) {
  421. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRectangle) {
  422. CGRect rect = CGRectMake(i * (segmentWidth + _segmentSeparation), 0, segmentWidth, self.bounds.size.height);
  423. path = [UIBezierPath bezierPathWithRect:rect];
  424. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  425. CGRect rect = CGRectMake(i * (segmentWidth + _segmentSeparation), 0, segmentWidth, self.bounds.size.height);
  426. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  427. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  428. CGRect rect = CGRectMake(i * (segmentWidth + _segmentSeparation), (self.bounds.size.height - (2 * cornerRadius)) / 2, 2 * cornerRadius, 2 * cornerRadius);
  429. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  430. }
  431. } else if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionRightToLeft) {
  432. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRectangle) {
  433. CGRect rect = CGRectMake(self.bounds.size.width - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, 0, segmentWidth, self.bounds.size.height);
  434. path = [UIBezierPath bezierPathWithRect:rect];
  435. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  436. CGRect rect = CGRectMake(self.bounds.size.width - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, 0, segmentWidth, self.bounds.size.height);
  437. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  438. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  439. CGRect rect = CGRectMake(self.bounds.size.width - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, (self.bounds.size.height - (2 * cornerRadius)) / 2, 2 * cornerRadius, 2 * cornerRadius);
  440. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  441. }
  442. } else if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionBottomToTop) {
  443. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRectangle) {
  444. CGRect rect = CGRectMake(0, self.bounds.size.height - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, self.bounds.size.width, segmentWidth);
  445. path = [UIBezierPath bezierPathWithRect:rect];
  446. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  447. CGRect rect = CGRectMake(0, self.bounds.size.height - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, self.bounds.size.width, segmentWidth);
  448. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  449. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  450. CGRect rect = CGRectMake((self.bounds.size.width - (2 * cornerRadius)) / 2, self.bounds.size.height - (i * (segmentWidth + _segmentSeparation)) - segmentWidth, 2 * cornerRadius, 2 * cornerRadius);
  451. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  452. }
  453. } else if (_progressDirection == M13ProgressViewSegmentedBarProgressDirectionTopToBottom) {
  454. if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRectangle) {
  455. CGRect rect = CGRectMake(0, (i * (segmentWidth + _segmentSeparation)), self.bounds.size.width, segmentWidth);
  456. path = [UIBezierPath bezierPathWithRect:rect];
  457. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeRoundedRect) {
  458. CGRect rect = CGRectMake(0, (i * (segmentWidth + _segmentSeparation)), self.bounds.size.width, segmentWidth);
  459. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  460. } else if (_segmentShape == M13ProgressViewSegmentedBarSegmentShapeCircle) {
  461. CGRect rect = CGRectMake((self.bounds.size.width - (2 * cornerRadius)) / 2, (i * (segmentWidth + _segmentSeparation)), 2 * cornerRadius, 2 * cornerRadius);
  462. path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
  463. }
  464. }
  465. //Add the segment to the proper path //Add segment to the proper layer, and color it
  466. CAShapeLayer *layer = (CAShapeLayer *)_segmentsLayer.sublayers[i];
  467. layer.path = path.CGPath;
  468. if (i >= indeterminateIndex && i < indeterminateIndex + numberOfSegmentsToBeColored) {
  469. layer.fillColor = ((UIColor *)segmentColorsPrimary[i]).CGColor;
  470. } else {
  471. layer.fillColor = ((UIColor *)segmentColorsBackground[i]).CGColor;
  472. }
  473. }
  474. //increase the index by one for movement
  475. indeterminateIndex += 1;
  476. if (indeterminateIndex == numberOfSegmentsToBeColored + _numberOfSegments) {
  477. indeterminateIndex = -numberOfSegmentsToBeColored;
  478. }
  479. }
  480. @end