11 #import "TouchPointerView.h"
14 #define RESET_DEFAULT_POINTER_IMAGE_DELAY 0.15
16 #define POINTER_ACTION_CURSOR 0
17 #define POINTER_ACTION_CLOSE 3
18 #define POINTER_ACTION_RCLICK 2
19 #define POINTER_ACTION_LCLICK 4
20 #define POINTER_ACTION_MOVE 4
21 #define POINTER_ACTION_SCROLL 5
22 #define POINTER_ACTION_KEYBOARD 7
23 #define POINTER_ACTION_EXTKEYBOARD 8
24 #define POINTER_ACTION_RESET 6
26 @interface TouchPointerView (Private)
27 - (void)setCurrentPointerImage:(UIImage *)image;
28 - (void)displayPointerActionImage:(UIImage *)image;
29 - (BOOL)pointInsidePointer:(CGPoint)point;
30 - (BOOL)pointInsidePointerArea:(
int)area point:(CGPoint)point;
31 - (CGPoint)getCursorPosition;
32 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
33 - (void)handleSingleTap:(UITapGestureRecognizer *)gesture;
34 - (void)handlerForGesture:(UIGestureRecognizer *)gesture sendClick:(BOOL)sendClick;
39 @synthesize delegate = _delegate;
46 [
self setContentMode:UIViewContentModeTopLeft];
49 _default_pointer_img = [[UIImage
50 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_default"
51 ofType:@"png"]] retain];
52 _active_pointer_img = [[UIImage
53 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_active"
54 ofType:@"png"]] retain];
55 _lclick_pointer_img = [[UIImage
56 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_lclick"
57 ofType:@"png"]] retain];
58 _rclick_pointer_img = [[UIImage
59 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_rclick"
60 ofType:@"png"]] retain];
61 _scroll_pointer_img = [[UIImage
62 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_scroll"
63 ofType:@"png"]] retain];
64 _extkeyboard_pointer_img = [[UIImage
65 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_ext_keyboard"
66 ofType:@"png"]] retain];
67 _keyboard_pointer_img = [[UIImage
68 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_keyboard"
69 ofType:@"png"]] retain];
70 _reset_pointer_img = [[UIImage
71 imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"touch_pointer_reset"
72 ofType:@"png"]] retain];
73 _cur_pointer_img = _default_pointer_img;
74 _pointer_transformation = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
78 _pointer_scrolling = NO;
81 CGFloat area_width = [_cur_pointer_img size].width / 3.0f;
82 CGFloat area_height = [_cur_pointer_img size].height / 3.0f;
83 for (
int i = 0; i < 3; i++)
85 for (
int j = 0; j < 3; j++)
87 _pointer_areas[j + i * 3] =
88 CGRectMake(j * area_width, i * area_height, area_width, area_height);
93 UITapGestureRecognizer *singleTapRecognizer =
94 [[[UITapGestureRecognizer alloc] initWithTarget:self
95 action:@selector(handleSingleTap:)] autorelease];
96 [singleTapRecognizer setNumberOfTouchesRequired:1];
97 [singleTapRecognizer setNumberOfTapsRequired:1];
99 UILongPressGestureRecognizer *dragDropRecognizer = [[[UILongPressGestureRecognizer alloc]
101 action:@selector(handleDragDrop:)] autorelease];
102 dragDropRecognizer.minimumPressDuration = 0.4;
105 UILongPressGestureRecognizer *pointerMoveScrollRecognizer =
106 [[[UILongPressGestureRecognizer alloc] initWithTarget:self
107 action:@selector(handlePointerMoveScroll:)]
109 pointerMoveScrollRecognizer.minimumPressDuration = 0.15;
110 pointerMoveScrollRecognizer.allowableMovement = 1000.0;
111 [pointerMoveScrollRecognizer requireGestureRecognizerToFail:dragDropRecognizer];
113 [
self addGestureRecognizer:singleTapRecognizer];
114 [
self addGestureRecognizer:dragDropRecognizer];
115 [
self addGestureRecognizer:pointerMoveScrollRecognizer];
121 [_default_pointer_img autorelease];
122 [_active_pointer_img autorelease];
123 [_lclick_pointer_img autorelease];
124 [_rclick_pointer_img autorelease];
125 [_scroll_pointer_img autorelease];
126 [_extkeyboard_pointer_img autorelease];
127 [_keyboard_pointer_img autorelease];
128 [_reset_pointer_img autorelease];
131 #pragma mark - Public interface
134 - (void)ensurePointerIsVisible
136 CGRect bounds = [
self bounds];
137 if (_pointer_transformation.tx > (bounds.size.width - _cur_pointer_img.size.width))
138 _pointer_transformation.tx = bounds.size.width - _cur_pointer_img.size.width;
139 if (_pointer_transformation.ty > (bounds.size.height - _cur_pointer_img.size.height))
140 _pointer_transformation.ty = bounds.size.height - _cur_pointer_img.size.height;
141 [
self setNeedsDisplay];
145 - (void)setHidden:(BOOL)hidden
147 [
super setHidden:hidden];
152 _pointer_transformation = CGAffineTransformMakeTranslation(
153 ([
self bounds].size.width - [_cur_pointer_img size].width) / 2,
154 ([
self bounds].size.height - [_cur_pointer_img size].height) / 2);
155 [
self setNeedsDisplay];
159 - (UIEdgeInsets)getEdgeInsets
161 return UIEdgeInsetsMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height);
164 - (CGPoint)getPointerPosition
166 return CGPointMake(_pointer_transformation.tx, _pointer_transformation.ty);
169 - (int)getPointerWidth
171 return [_cur_pointer_img size].width;
174 - (int)getPointerHeight
176 return [_cur_pointer_img size].height;
181 @implementation TouchPointerView (Private)
183 - (void)setCurrentPointerImage:(UIImage *)image
185 _cur_pointer_img = image;
186 [
self setNeedsDisplay];
189 - (void)displayPointerActionImage:(UIImage *)image
191 [
self setCurrentPointerImage:image];
192 [
self performSelector:@selector(setCurrentPointerImage:)
193 withObject:_default_pointer_img
194 afterDelay:RESET_DEFAULT_POINTER_IMAGE_DELAY];
199 - (void)drawRect:(CGRect)rect
202 CGContextRef context = UIGraphicsGetCurrentContext();
203 CGContextSaveGState(context);
204 CGContextConcatCTM(context, _pointer_transformation);
206 context, CGRectMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height),
207 [_cur_pointer_img CGImage]);
208 CGContextRestoreGState(context);
212 - (BOOL)pointInsidePointer:(CGPoint)point
214 CGRect rec = CGRectMake(0, 0, [_cur_pointer_img size].width, [_cur_pointer_img size].height);
215 return CGRectContainsPoint(CGRectApplyAffineTransform(rec, _pointer_transformation), point);
219 - (BOOL)pointInsidePointerArea:(
int)area point:(CGPoint)point
221 CGRect rec = _pointer_areas[area];
222 return CGRectContainsPoint(CGRectApplyAffineTransform(rec, _pointer_transformation), point);
226 - (CGPoint)getCursorPosition
228 CGRect transPointerArea =
229 CGRectApplyAffineTransform(_pointer_areas[POINTER_ACTION_CURSOR], _pointer_transformation);
230 return CGPointMake(CGRectGetMidX(transPointerArea), CGRectGetMidY(transPointerArea));
234 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
236 return [
self pointInsidePointer:point];
239 #pragma mark - Action handlers
242 - (void)handleSingleTap:(UITapGestureRecognizer *)gesture
245 CGPoint touchPos = [gesture locationInView:self];
248 if ([
self pointInsidePointerArea:POINTER_ACTION_CLOSE point:touchPos])
249 [[
self delegate] touchPointerClose];
250 else if ([
self pointInsidePointerArea:POINTER_ACTION_LCLICK point:touchPos])
252 [
self displayPointerActionImage:_lclick_pointer_img];
253 [[
self delegate] touchPointerLeftClick:[
self getCursorPosition] down:YES];
254 [[
self delegate] touchPointerLeftClick:[
self getCursorPosition] down:NO];
256 else if ([
self pointInsidePointerArea:POINTER_ACTION_RCLICK point:touchPos])
258 [
self displayPointerActionImage:_rclick_pointer_img];
259 [[
self delegate] touchPointerRightClick:[
self getCursorPosition] down:YES];
260 [[
self delegate] touchPointerRightClick:[
self getCursorPosition] down:NO];
262 else if ([
self pointInsidePointerArea:POINTER_ACTION_KEYBOARD point:touchPos])
264 [
self displayPointerActionImage:_keyboard_pointer_img];
265 [[
self delegate] touchPointerToggleKeyboard];
267 else if ([
self pointInsidePointerArea:POINTER_ACTION_EXTKEYBOARD point:touchPos])
269 [
self displayPointerActionImage:_extkeyboard_pointer_img];
270 [[
self delegate] touchPointerToggleExtendedKeyboard];
272 else if ([
self pointInsidePointerArea:POINTER_ACTION_RESET point:touchPos])
274 [
self displayPointerActionImage:_reset_pointer_img];
275 [[
self delegate] touchPointerResetSessionView];
279 - (void)handlerForGesture:(UIGestureRecognizer *)gesture sendClick:(BOOL)sendClick
281 if ([gesture state] == UIGestureRecognizerStateBegan)
283 CGPoint touchPos = [gesture locationInView:self];
284 if ([
self pointInsidePointerArea:POINTER_ACTION_LCLICK point:touchPos])
286 _prev_touch_location = touchPos;
287 _pointer_moving = YES;
288 if (sendClick == YES)
290 [[
self delegate] touchPointerLeftClick:[
self getCursorPosition] down:YES];
291 [
self setCurrentPointerImage:_active_pointer_img];
294 else if ([
self pointInsidePointerArea:POINTER_ACTION_SCROLL point:touchPos])
296 [
self setCurrentPointerImage:_scroll_pointer_img];
297 _prev_touch_location = touchPos;
298 _pointer_scrolling = YES;
301 else if ([gesture state] == UIGestureRecognizerStateChanged)
305 CGPoint touchPos = [gesture locationInView:self];
306 _pointer_transformation = CGAffineTransformTranslate(
307 _pointer_transformation, touchPos.x - _prev_touch_location.x,
308 touchPos.y - _prev_touch_location.y);
309 [[
self delegate] touchPointerMove:[
self getCursorPosition]];
310 _prev_touch_location = touchPos;
311 [
self setNeedsDisplay];
313 else if (_pointer_scrolling)
315 CGPoint touchPos = [gesture locationInView:self];
316 float delta = touchPos.y - _prev_touch_location.y;
317 if (delta > GetScrollGestureDelta())
319 [[
self delegate] touchPointerScrollDown:YES];
320 _prev_touch_location = touchPos;
322 else if (delta < -GetScrollGestureDelta())
324 [[
self delegate] touchPointerScrollDown:NO];
325 _prev_touch_location = touchPos;
329 else if ([gesture state] == UIGestureRecognizerStateEnded)
333 if (sendClick == YES)
334 [[
self delegate] touchPointerLeftClick:[
self getCursorPosition] down:NO];
335 _pointer_moving = NO;
336 [
self setCurrentPointerImage:_default_pointer_img];
339 if (_pointer_scrolling)
341 [
self setCurrentPointerImage:_default_pointer_img];
342 _pointer_scrolling = NO;
348 - (void)handleDragDrop:(UILongPressGestureRecognizer *)gesture
350 [
self handlerForGesture:gesture sendClick:YES];
353 - (void)handlePointerMoveScroll:(UILongPressGestureRecognizer *)gesture
355 [
self handlerForGesture:gesture sendClick:NO];