DrawView.m 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. #import "DrawView.h"
  19. #import "DrawPath.h"
  20. #import "SwatchesView.h"
  21. #import "CanvasView.h"
  22. #import "UIColor+Realm.h"
  23. #import <Realm/Realm.h>
  24. @interface DrawView ()
  25. @property DrawPath *drawPath;
  26. @property NSString *pathID;
  27. @property RLMResults *paths;
  28. @property RLMNotificationToken *notificationToken;
  29. @property CanvasView *canvasView;
  30. @property SwatchesView *swatchesView;
  31. @property NSString *currentColorName;
  32. @end
  33. @implementation DrawView
  34. - (instancetype)initWithFrame:(CGRect)frame
  35. {
  36. self = [super initWithFrame:frame];
  37. if (self) {
  38. typeof(self) __weak weakSelf = self;
  39. self.notificationToken = [[RLMRealm defaultRealm] addNotificationBlock:^(NSString *notification, RLMRealm *realm) {
  40. if (weakSelf.paths.count == 0) {
  41. [weakSelf.canvasView clearCanvas];
  42. }
  43. else {
  44. [weakSelf.canvasView setNeedsDisplay];
  45. }
  46. }];
  47. self.paths = [DrawPath allObjects];
  48. self.canvasView = [[CanvasView alloc] init];
  49. self.canvasView.paths = self.paths;
  50. [self addSubview:self.canvasView];
  51. self.swatchesView = [[SwatchesView alloc] initWithFrame:CGRectZero];
  52. [self addSubview:self.swatchesView];
  53. self.swatchesView.swatchColorChangedHandler = ^{
  54. weakSelf.currentColorName = weakSelf.swatchesView.selectedColor;
  55. };
  56. self.currentColorName = @"Black";
  57. }
  58. return self;
  59. }
  60. - (void)layoutSubviews
  61. {
  62. [super layoutSubviews];
  63. CGSize boundsSize = self.bounds.size;
  64. CGFloat maxDimension = MAX(boundsSize.width, boundsSize.height);
  65. CGRect frame = self.canvasView.frame;
  66. frame.size.width = maxDimension;
  67. frame.size.height = maxDimension;
  68. frame.origin.x = (boundsSize.width - maxDimension) * 0.5f;
  69. self.canvasView.frame = CGRectIntegral(frame);
  70. frame = self.swatchesView.frame;
  71. frame.size.width = CGRectGetWidth(self.frame);
  72. frame.origin.y = CGRectGetHeight(self.frame) - CGRectGetHeight(frame);
  73. self.swatchesView.frame = frame;
  74. [self.swatchesView setNeedsLayout];
  75. }
  76. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  77. {
  78. // Create a draw path object
  79. self.drawPath = [[DrawPath alloc] init];
  80. self.drawPath.color = self.currentColorName;
  81. // Create a draw point object
  82. CGPoint point = [[touches anyObject] locationInView:self.canvasView];
  83. DrawPoint *drawPoint = [[DrawPoint alloc] init];
  84. drawPoint.x = point.x;
  85. drawPoint.y = point.y;
  86. // Add the draw point to the draw path
  87. [self.drawPath.points addObject:drawPoint];
  88. // Add the draw path to the Realm
  89. RLMRealm *defaultRealm = [RLMRealm defaultRealm];
  90. [defaultRealm transactionWithBlock:^{
  91. [defaultRealm addObject:self.drawPath];
  92. }];
  93. [self.canvasView setNeedsDisplay];
  94. }
  95. - (void)addPoint:(CGPoint)point
  96. {
  97. [[RLMRealm defaultRealm] transactionWithBlock:^{
  98. if (self.drawPath.isInvalidated) {
  99. self.drawPath = [[DrawPath alloc] init];
  100. self.drawPath.color = self.currentColorName ?: @"Black";
  101. [[RLMRealm defaultRealm] addObject:self.drawPath];
  102. }
  103. DrawPoint *newPoint = [DrawPoint createInDefaultRealmWithValue:@[@(point.x), @(point.y)]];
  104. [self.drawPath.points addObject:newPoint];
  105. }];
  106. }
  107. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
  108. {
  109. CGPoint point = [[touches anyObject] locationInView:self.canvasView];
  110. [self addPoint:point];
  111. [self.canvasView setNeedsDisplay];
  112. }
  113. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
  114. {
  115. CGPoint point = [[touches anyObject] locationInView:self.canvasView];
  116. [self addPoint:point];
  117. [[RLMRealm defaultRealm] transactionWithBlock:^{ self.drawPath.completed = YES; }];
  118. self.drawPath = nil;
  119. }
  120. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
  121. {
  122. [self touchesEnded:touches withEvent:event];
  123. }
  124. - (BOOL)canBecomeFirstResponder
  125. {
  126. return YES;
  127. }
  128. - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
  129. {
  130. if (motion != UIEventSubtypeMotionShake) {
  131. return;
  132. }
  133. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Reset Canvas?"
  134. message:@"This will clear the Realm database and reset the canvas. Are you sure you wish to proceed?"
  135. preferredStyle:UIAlertControllerStyleAlert];
  136. typeof(self) __weak weakSelf = self;
  137. [alertController addAction:[UIAlertAction actionWithTitle:@"Reset"
  138. style:UIAlertActionStyleDefault
  139. handler:^(UIAlertAction *action) {
  140. [[RLMRealm defaultRealm] transactionWithBlock:^{
  141. [[RLMRealm defaultRealm] deleteAllObjects];
  142. }];
  143. [weakSelf.canvasView clearCanvas];
  144. }]];
  145. [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
  146. [[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:alertController animated:YES completion:nil];
  147. }
  148. @end