appjam 0.1.8.9 → 0.1.8.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.pbxproj +114 -0
  2. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/xcuserdata/eiffel.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  3. data/lib/appjam/generators/templates/blank/EiffelApplication/AppDelegate.m.tt +13 -1
  4. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/CustomBadge.h +52 -0
  5. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/CustomBadge.m +241 -0
  6. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherItem.h +58 -0
  7. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherItem.m +227 -0
  8. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherPageControl.h +37 -0
  9. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherPageControl.m +117 -0
  10. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherScrollView.h +23 -0
  11. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherScrollView.m +42 -0
  12. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherView.h +70 -0
  13. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherView.m +830 -0
  14. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherViewController.h +38 -0
  15. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MyLauncher/MyLauncherViewController.m +302 -0
  16. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/AESCrypt-ObjC/AESCrypt.h +37 -0
  17. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/AESCrypt-ObjC/AESCrypt.m +50 -0
  18. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/AESCrypt-ObjC/NSData+Base64.h +17 -0
  19. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/AESCrypt-ObjC/NSData+Base64.m +110 -0
  20. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/AESCrypt-ObjC/NSData+CommonCrypto.h +112 -0
  21. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/AESCrypt-ObjC/NSData+CommonCrypto.m +546 -0
  22. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/AESCrypt-ObjC/NSString+Base64.h +15 -0
  23. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/AESCrypt-ObjC/NSString+Base64.m +82 -0
  24. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCCrossHairView.h +16 -0
  25. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCCrossHairView.m +43 -0
  26. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCFrameView.h +55 -0
  27. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCFrameView.m +234 -0
  28. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCIntrospect.h +155 -0
  29. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCIntrospect.m +1654 -0
  30. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCIntrospectSettings.h +56 -0
  31. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCStatusBarOverlay.h +34 -0
  32. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/DCIntrospect/DCStatusBarOverlay.m +107 -0
  33. data/lib/appjam/version.rb +1 -1
  34. metadata +32 -3
@@ -0,0 +1,15 @@
1
+ //
2
+ // NSString+Base64.h
3
+ // Gurpartap Singh
4
+ //
5
+ // Created by Gurpartap Singh on 06/05/12.
6
+ // Copyright (c) 2012 Gurpartap Singh. All rights reserved.
7
+ //
8
+
9
+ #import <Foundation/NSString.h>
10
+
11
+ @interface NSString (Base64Additions)
12
+
13
+ + (NSString *)base64StringFromData:(NSData *)data length:(NSUInteger)length;
14
+
15
+ @end
@@ -0,0 +1,82 @@
1
+ //
2
+ // NSStringAdditions.m
3
+ // Gurpartap Singh
4
+ //
5
+ // Created by Gurpartap Singh on 06/05/12.
6
+ // Copyright (c) 2012 Gurpartap Singh. All rights reserved.
7
+ //
8
+
9
+ #import "NSString+Base64.h"
10
+
11
+ static char base64EncodingTable[64] = {
12
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
13
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
14
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
15
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
16
+ };
17
+
18
+ @implementation NSString (Base64Additions)
19
+
20
+ + (NSString *)base64StringFromData: (NSData *)data length: (NSUInteger)length {
21
+ unsigned long ixtext, lentext;
22
+ long ctremaining;
23
+ unsigned char input[3], output[4];
24
+ short i, charsonline = 0, ctcopy;
25
+ const unsigned char *raw;
26
+ NSMutableString *result;
27
+
28
+ lentext = [data length];
29
+ if (lentext < 1) {
30
+ return @"";
31
+ }
32
+ result = [NSMutableString stringWithCapacity: lentext];
33
+ raw = [data bytes];
34
+ ixtext = 0;
35
+
36
+ while (true) {
37
+ ctremaining = lentext - ixtext;
38
+ if (ctremaining <= 0) {
39
+ break;
40
+ }
41
+ for (i = 0; i < 3; i++) {
42
+ unsigned long ix = ixtext + i;
43
+ if (ix < lentext) {
44
+ input[i] = raw[ix];
45
+ }
46
+ else {
47
+ input[i] = 0;
48
+ }
49
+ }
50
+ output[0] = (input[0] & 0xFC) >> 2;
51
+ output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
52
+ output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
53
+ output[3] = input[2] & 0x3F;
54
+ ctcopy = 4;
55
+ switch (ctremaining) {
56
+ case 1:
57
+ ctcopy = 2;
58
+ break;
59
+ case 2:
60
+ ctcopy = 3;
61
+ break;
62
+ }
63
+
64
+ for (i = 0; i < ctcopy; i++) {
65
+ [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
66
+ }
67
+
68
+ for (i = ctcopy; i < 4; i++) {
69
+ [result appendString: @"="];
70
+ }
71
+
72
+ ixtext += 3;
73
+ charsonline += 4;
74
+
75
+ if ((length > 0) && (charsonline >= length)) {
76
+ charsonline = 0;
77
+ }
78
+ }
79
+ return result;
80
+ }
81
+
82
+ @end
@@ -0,0 +1,16 @@
1
+ //
2
+ // DCCrossHairView.h
3
+ //
4
+ // Created by Domestic Cat on 3/05/11.
5
+ //
6
+
7
+
8
+ @interface DCCrossHairView : UIView
9
+ {
10
+ }
11
+
12
+ @property (nonatomic, retain) UIColor *color;
13
+
14
+ - (id)initWithFrame:(CGRect)frame color:(UIColor *)aColor;
15
+
16
+ @end
@@ -0,0 +1,43 @@
1
+ //
2
+ // DCCrossHairView.m
3
+ //
4
+ // Created by Domestic Cat on 3/05/11.
5
+ //
6
+
7
+ #import "DCCrossHairView.h"
8
+
9
+ @implementation DCCrossHairView
10
+ @synthesize color;
11
+
12
+ - (void)dealloc
13
+ {
14
+ [color release];
15
+ [super dealloc];
16
+ }
17
+
18
+ - (id)initWithFrame:(CGRect)frame color:(UIColor *)aColor
19
+ {
20
+ if ((self = [super initWithFrame:frame]))
21
+ {
22
+ self.color = aColor;
23
+ self.backgroundColor = [UIColor clearColor];
24
+ self.opaque = NO;
25
+ }
26
+
27
+ return self;
28
+ }
29
+
30
+ - (void)drawRect:(CGRect)rect
31
+ {
32
+ CGContextRef context = UIGraphicsGetCurrentContext();
33
+ [self.color set];
34
+ CGContextMoveToPoint(context, floorf(self.bounds.size.width / 2.0f) + 0.5f, 0.0f);
35
+ CGContextAddLineToPoint(context, floorf(self.bounds.size.width / 2.0f) + 0.5f, self.bounds.size.height);
36
+ CGContextStrokePath(context);
37
+
38
+ CGContextMoveToPoint(context, 0, floorf(self.bounds.size.height / 2.0f) + 0.5f);
39
+ CGContextAddLineToPoint(context, self.bounds.size.width, floorf(self.bounds.size.height / 2.0f) + 0.5f);
40
+ CGContextStrokePath(context);
41
+ }
42
+
43
+ @end
@@ -0,0 +1,55 @@
1
+ //
2
+ // DCFrameView.h
3
+ //
4
+ // Created by Domestic Cat on 29/04/11.
5
+ //
6
+
7
+ #import <QuartzCore/QuartzCore.h>
8
+ #import "DCCrossHairView.h"
9
+
10
+ @protocol DCFrameViewDelegate <NSObject>
11
+
12
+ @required
13
+
14
+ - (void)touchAtPoint:(CGPoint)point;
15
+
16
+ @end
17
+
18
+ @interface DCFrameView : UIView
19
+ {
20
+
21
+ }
22
+
23
+ @property (nonatomic, assign) id<DCFrameViewDelegate> delegate;
24
+ @property (nonatomic) CGRect mainRect;
25
+ @property (nonatomic) CGRect superRect;
26
+ @property (nonatomic, retain) UILabel *touchPointLabel;
27
+ @property (nonatomic, retain) NSMutableArray *rectsToOutline;
28
+ @property (nonatomic, retain) DCCrossHairView *touchPointView;
29
+
30
+ ///////////
31
+ // Setup //
32
+ ///////////
33
+
34
+ - (id)initWithFrame:(CGRect)frame delegate:(id)aDelegate;
35
+
36
+ ////////////////////
37
+ // Custom Setters //
38
+ ////////////////////
39
+
40
+ - (void)setMainRect:(CGRect)newMainRect;
41
+ - (void)setSuperRect:(CGRect)newSuperRect;
42
+
43
+ /////////////////////
44
+ // Drawing/Display //
45
+ /////////////////////
46
+
47
+ - (void)drawRect:(CGRect)rect;
48
+
49
+ ////////////////////
50
+ // Touch Handling //
51
+ ////////////////////
52
+
53
+ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
54
+
55
+ @end
@@ -0,0 +1,234 @@
1
+ //
2
+ // DCFrameView.m
3
+ //
4
+ // Created by Domestic Cat on 29/04/11.
5
+ //
6
+
7
+ #import "DCFrameView.h"
8
+
9
+ @implementation DCFrameView
10
+ @synthesize delegate;
11
+ @synthesize mainRect, superRect;
12
+ @synthesize touchPointLabel;
13
+ @synthesize rectsToOutline;
14
+ @synthesize touchPointView;
15
+
16
+ - (void)dealloc
17
+ {
18
+ self.delegate = nil;
19
+ [touchPointLabel release];
20
+ [touchPointView release];
21
+
22
+ [super dealloc];
23
+ }
24
+
25
+ #pragma mark - Setup
26
+
27
+ - (id)initWithFrame:(CGRect)frame delegate:(id)aDelegate
28
+ {
29
+ self = [super initWithFrame:frame];
30
+ if (self)
31
+ {
32
+ self.delegate = aDelegate;
33
+ self.backgroundColor = [UIColor clearColor];
34
+ self.opaque = NO;
35
+
36
+ self.touchPointLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
37
+ self.touchPointLabel.text = @"X 320 Y 480";
38
+ self.touchPointLabel.font = [UIFont boldSystemFontOfSize:12.0f];
39
+ self.touchPointLabel.textAlignment = UITextAlignmentCenter;
40
+ self.touchPointLabel.textColor = [UIColor whiteColor];
41
+ self.touchPointLabel.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.65f];
42
+ self.touchPointLabel.layer.cornerRadius = 5.5f;
43
+ self.touchPointLabel.layer.masksToBounds = YES;
44
+ self.touchPointLabel.alpha = 0.0f;
45
+ [self addSubview:self.touchPointLabel];
46
+
47
+ self.rectsToOutline = [NSMutableArray array];
48
+
49
+ self.touchPointView = [[[DCCrossHairView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 17.0f, 17.0f) color:[UIColor blueColor]] autorelease];
50
+ self.touchPointView.alpha = 0.0f;
51
+ [self addSubview:self.touchPointView];
52
+ }
53
+ return self;
54
+ }
55
+
56
+ #pragma mark - Custom Setters
57
+
58
+ - (void)setMainRect:(CGRect)newMainRect
59
+ {
60
+ mainRect = newMainRect;
61
+ [self setNeedsDisplay];
62
+ }
63
+
64
+ - (void)setSuperRect:(CGRect)newSuperRect
65
+ {
66
+ superRect = newSuperRect;
67
+ [self setNeedsDisplay];
68
+ }
69
+
70
+ #pragma mark - Drawing/Display
71
+
72
+ - (void)drawRect:(CGRect)rect
73
+ {
74
+ CGContextRef context = UIGraphicsGetCurrentContext();
75
+
76
+ if (self.rectsToOutline.count > 0)
77
+ {
78
+ for (NSValue *value in self.rectsToOutline)
79
+ {
80
+ UIColor *randomColor = [UIColor colorWithRed:(arc4random() % 256) / 256.0f
81
+ green:(arc4random() % 256) / 256.0f
82
+ blue:(arc4random() % 256) / 256.0f
83
+ alpha:1.0f];
84
+ [randomColor set];
85
+ CGRect valueRect = [value CGRectValue];
86
+ valueRect = CGRectMake(valueRect.origin.x + 0.5f,
87
+ valueRect.origin.y + 0.5f,
88
+ valueRect.size.width - 1.0f,
89
+ valueRect.size.height - 1.0f);
90
+ CGContextStrokeRect(context, valueRect);
91
+ }
92
+ return;
93
+ }
94
+
95
+ if (CGRectIsEmpty(self.mainRect))
96
+ return;
97
+
98
+ CGRect mainRectOffset = CGRectOffset(mainRect, -superRect.origin.x, -superRect.origin.y);
99
+ BOOL showAntialiasingWarning = NO;
100
+ if (! CGRectIsEmpty(self.superRect))
101
+ {
102
+ if ((mainRectOffset.origin.x != floorf(mainRectOffset.origin.x) && mainRect.origin.x != 0) || (mainRectOffset.origin.y != floor(mainRectOffset.origin.y) && mainRect.origin.y != 0))
103
+ showAntialiasingWarning = YES;
104
+ }
105
+
106
+ if (showAntialiasingWarning)
107
+ {
108
+ [[UIColor redColor] set];
109
+ NSLog(@"DCIntrospect: *** WARNING: One or more values of this view's frame are non-integer values. This view will likely look blurry. ***");
110
+ }
111
+ else
112
+ {
113
+ [[UIColor blueColor] set];
114
+ }
115
+
116
+ CGRect adjustedMainRect = CGRectMake(self.mainRect.origin.x + 0.5f,
117
+ self.mainRect.origin.y + 0.5f,
118
+ self.mainRect.size.width - 1.0f,
119
+ self.mainRect.size.height - 1.0f);
120
+ CGContextStrokeRect(context, adjustedMainRect);
121
+
122
+ UIFont *font = [UIFont systemFontOfSize:10.0f];
123
+
124
+ float dash[2] = {3, 3};
125
+ CGContextSetLineDash(context, 0, dash, 2);
126
+
127
+ // edge->left side
128
+ CGContextMoveToPoint(context, CGRectGetMinX(self.superRect), floorf(CGRectGetMidY(adjustedMainRect)) + 0.5f);
129
+ CGContextAddLineToPoint(context, CGRectGetMinX(adjustedMainRect), floorf(CGRectGetMidY(adjustedMainRect)) + 0.5f);
130
+ CGContextStrokePath(context);
131
+
132
+ NSString *leftDistanceString = (showAntialiasingWarning) ? [NSString stringWithFormat:@"%.1f", CGRectGetMinX(mainRectOffset)] : [NSString stringWithFormat:@"%.0f", CGRectGetMinX(mainRectOffset)];
133
+ CGSize leftDistanceStringSize = [leftDistanceString sizeWithFont:font];
134
+ [leftDistanceString drawInRect:CGRectMake(CGRectGetMinX(superRect) + 1.0f,
135
+ floorf(CGRectGetMidY(adjustedMainRect)) - leftDistanceStringSize.height,
136
+ leftDistanceStringSize.width,
137
+ leftDistanceStringSize.height)
138
+ withFont:font];
139
+
140
+ // right side->edge
141
+ if (CGRectGetMaxX(self.mainRect) < CGRectGetMaxX(self.superRect))
142
+ {
143
+ CGContextMoveToPoint(context, CGRectGetMaxX(adjustedMainRect), floorf(CGRectGetMidY(adjustedMainRect)) + 0.5f);
144
+ CGContextAddLineToPoint(context, CGRectGetMaxX(self.superRect), floorf(CGRectGetMidY(adjustedMainRect)) + 0.5f);
145
+ CGContextStrokePath(context);
146
+ }
147
+ NSString *rightDistanceString = (showAntialiasingWarning) ? [NSString stringWithFormat:@"%.1f", CGRectGetMaxX(self.superRect) - CGRectGetMaxX(adjustedMainRect) - 0.5] : [NSString stringWithFormat:@"%.0f", CGRectGetMaxX(self.superRect) - CGRectGetMaxX(adjustedMainRect) - 0.5];
148
+ CGSize rightDistanceStringSize = [rightDistanceString sizeWithFont:font];
149
+ [rightDistanceString drawInRect:CGRectMake(CGRectGetMaxX(self.superRect) - rightDistanceStringSize.width - 1.0f,
150
+ floorf(CGRectGetMidY(adjustedMainRect)) - 0.5f - rightDistanceStringSize.height,
151
+ rightDistanceStringSize.width,
152
+ rightDistanceStringSize.height)
153
+ withFont:font];
154
+
155
+ // edge->top side
156
+ CGContextMoveToPoint(context, floorf(CGRectGetMidX(adjustedMainRect)) + 0.5f, self.superRect.origin.y);
157
+ CGContextAddLineToPoint(context, floorf(CGRectGetMidX(adjustedMainRect)) + 0.5f, CGRectGetMinY(adjustedMainRect));
158
+ CGContextStrokePath(context);
159
+ NSString *topDistanceString = (showAntialiasingWarning) ? [NSString stringWithFormat:@"%.1f", mainRectOffset.origin.y] : [NSString stringWithFormat:@"%.0f", mainRectOffset.origin.y];
160
+ CGSize topDistanceStringSize = [topDistanceString sizeWithFont:font];
161
+ [topDistanceString drawInRect:CGRectMake(floorf(CGRectGetMidX(adjustedMainRect)) + 3.0f,
162
+ floorf(CGRectGetMinY(self.superRect)),
163
+ topDistanceStringSize.width,
164
+ topDistanceStringSize.height)
165
+ withFont:font];
166
+
167
+ // bottom side->edge
168
+ if (CGRectGetMaxY(self.mainRect) < CGRectGetMaxY(self.superRect))
169
+ {
170
+ CGContextMoveToPoint(context, floorf(CGRectGetMidX(adjustedMainRect)) + 0.5f, CGRectGetMaxY(adjustedMainRect));
171
+ CGContextAddLineToPoint(context, floorf(CGRectGetMidX(adjustedMainRect)) + 0.5f, CGRectGetMaxY(self.superRect));
172
+ CGContextStrokePath(context);
173
+ }
174
+ NSString *bottomDistanceString = (showAntialiasingWarning) ? [NSString stringWithFormat:@"%.1f", CGRectGetMaxY(self.superRect) - CGRectGetMaxY(mainRectOffset)] : [NSString stringWithFormat:@"%.0f", self.superRect.size.height - mainRectOffset.origin.y - mainRectOffset.size.height];
175
+ CGSize bottomDistanceStringSize = [bottomDistanceString sizeWithFont:font];
176
+ [bottomDistanceString drawInRect:CGRectMake(floorf(CGRectGetMidX(adjustedMainRect)) + 3.0f,
177
+ floorf(CGRectGetMaxY(self.superRect)) - bottomDistanceStringSize.height - 1.0f,
178
+ bottomDistanceStringSize.width,
179
+ bottomDistanceStringSize.height)
180
+ withFont:font];
181
+
182
+ }
183
+
184
+ #pragma mark - Touch Handling
185
+
186
+ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
187
+ {
188
+ CGFloat labelDistance = 16.0f;
189
+ CGPoint touchPoint = [[touches anyObject] locationInView:self];
190
+
191
+ // adjust the point so it's exactly on the point of the mouse cursor
192
+ touchPoint.x -= 1;
193
+ touchPoint.y -= 2;
194
+
195
+ NSString *touchPontLabelString = [NSString stringWithFormat:@"%.0f, %.0f", touchPoint.x, touchPoint.y];
196
+ self.touchPointLabel.text = touchPontLabelString;
197
+
198
+ CGSize stringSize = [touchPontLabelString sizeWithFont:touchPointLabel.font];
199
+ CGRect frame = CGRectMake(touchPoint.x - floorf(stringSize.width / 2.0f) - 5.0f,
200
+ touchPoint.y - stringSize.height - labelDistance,
201
+ stringSize.width + 11.0f,
202
+ stringSize.height + 4.0f);
203
+
204
+ // make sure the label stays inside the frame
205
+ UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
206
+ CGFloat minY = UIInterfaceOrientationIsPortrait(orientation) ? [UIApplication sharedApplication].statusBarFrame.size.height : [UIApplication sharedApplication].statusBarFrame.size.width;
207
+ minY += 2.0f; // to keep it touching the top bar
208
+ if (frame.origin.x < 2.0f)
209
+ frame.origin.x = 2.0f;
210
+ else if (CGRectGetMaxX(frame) > self.bounds.size.width - 2.0f)
211
+ frame.origin.x = self.bounds.size.width - frame.size.width - 2.0f;
212
+ if (frame.origin.y < minY)
213
+ frame.origin.y = touchPoint.y + stringSize.height + 4.0f;
214
+
215
+ self.touchPointLabel.frame = frame;
216
+ self.touchPointView.center = CGPointMake(touchPoint.x + 0.5f, touchPoint.y + 0.5f);
217
+ self.touchPointView.alpha = self.touchPointLabel.alpha = 1.0f;
218
+
219
+ [self.delegate touchAtPoint:touchPoint];
220
+ }
221
+
222
+ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
223
+ {
224
+ [self touchesBegan:touches withEvent:event];
225
+ }
226
+
227
+ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
228
+ {
229
+ [UIView animateWithDuration:0.08 animations:^{
230
+ self.touchPointView.alpha = self.touchPointLabel.alpha = 0.0f;
231
+ }];
232
+ }
233
+
234
+ @end