Skip to content

Commit 488eedb

Browse files
committed
initial release
0 parents  commit 488eedb

File tree

4 files changed

+261
-0
lines changed

4 files changed

+261
-0
lines changed

DSFingerTipWindow.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// DSFingerTipWindow.h
3+
//
4+
// Created by Justin R. Miller on 3/29/11.
5+
// Copyright 2011 Development Seed. All rights reserved.
6+
//
7+
8+
#import <UIKit/UIKit.h>
9+
10+
@interface DSFingerTipWindow : UIWindow
11+
{
12+
UIWindow *overlay;
13+
NSMutableDictionary *touches;
14+
BOOL active;
15+
UIImage *touchImage;
16+
CGFloat touchAlpha;
17+
NSTimeInterval fadeDuration;
18+
}
19+
20+
@property (nonatomic, retain) UIImage *touchImage;
21+
@property (nonatomic, assign) CGFloat touchAlpha;
22+
@property (nonatomic, assign) NSTimeInterval fadeDuration;
23+
24+
@end

DSFingerTipWindow.m

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
//
2+
// DSFingerTipWindow.m
3+
//
4+
// Created by Justin R. Miller on 3/29/11.
5+
// Copyright 2011 Development Seed. All rights reserved.
6+
//
7+
8+
#import "DSFingerTipWindow.h"
9+
10+
@interface DSFingerTipWindow (DSFingerTipWindowPrivate)
11+
12+
- (void)setup;
13+
14+
@end
15+
16+
#pragma mark -
17+
18+
@implementation DSFingerTipWindow
19+
20+
@synthesize touchImage;
21+
@synthesize touchAlpha;
22+
@synthesize fadeDuration;
23+
24+
- (id)initWithCoder:(NSCoder *)decoder
25+
{
26+
// this covers NIB-loaded windows
27+
//
28+
self = [super initWithCoder:decoder];
29+
30+
if (self != nil)
31+
[self setup];
32+
33+
return self;
34+
}
35+
36+
- (id)initWithFrame:(CGRect)rect
37+
{
38+
// this covers programmatically-created windows
39+
//
40+
self = [super initWithFrame:rect];
41+
42+
if (self != nil)
43+
[self setup];
44+
45+
return self;
46+
}
47+
48+
- (void)setup
49+
{
50+
overlay = [[UIWindow alloc] initWithFrame:self.frame];
51+
52+
overlay.userInteractionEnabled = NO;
53+
overlay.windowLevel = UIWindowLevelStatusBar;
54+
overlay.backgroundColor = [UIColor clearColor];
55+
56+
[overlay makeKeyAndVisible];
57+
58+
touches = [[NSMutableDictionary dictionary] retain];
59+
active = [[UIScreen screens] count] > 1 ? YES : NO;
60+
touchAlpha = 0.5;
61+
fadeDuration = 0.3;
62+
63+
[[NSNotificationCenter defaultCenter] addObserver:self
64+
selector:@selector(screenConnect:)
65+
name:UIScreenDidConnectNotification
66+
object:nil];
67+
68+
[[NSNotificationCenter defaultCenter] addObserver:self
69+
selector:@selector(screenDisconnect:)
70+
name:UIScreenDidDisconnectNotification
71+
object:nil];
72+
}
73+
74+
- (void)dealloc
75+
{
76+
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenDidConnectNotification object:nil];
77+
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIScreenDidDisconnectNotification object:nil];
78+
79+
[overlay release];
80+
[touches release];
81+
[touchImage release];
82+
83+
[super dealloc];
84+
}
85+
86+
#pragma mark -
87+
88+
- (UIImage *)touchImage
89+
{
90+
if ( ! touchImage)
91+
{
92+
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
93+
94+
UIGraphicsBeginImageContext(clipPath.bounds.size);
95+
96+
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
97+
radius:22.0
98+
startAngle:0
99+
endAngle:2 * M_PI
100+
clockwise:YES];
101+
102+
drawPath.lineWidth = 2.0;
103+
104+
[[UIColor blackColor] setStroke];
105+
[[UIColor whiteColor] setFill];
106+
107+
[drawPath stroke];
108+
[drawPath fill];
109+
110+
[clipPath addClip];
111+
112+
touchImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
113+
114+
UIGraphicsEndImageContext();
115+
}
116+
117+
return touchImage;
118+
}
119+
120+
#pragma mark -
121+
122+
- (void)screenConnect:(NSNotification *)notification
123+
{
124+
active = YES;
125+
}
126+
127+
- (void)screenDisconnect:(NSNotification *)notification
128+
{
129+
active = [[UIScreen screens] count] > 1 ? YES : NO;
130+
}
131+
132+
#pragma mark -
133+
134+
- (void)sendEvent:(UIEvent *)event
135+
{
136+
if (active)
137+
{
138+
NSSet *allTouches = [event allTouches];
139+
140+
for (UITouch *touch in [allTouches allObjects])
141+
{
142+
NSNumber *hash = [NSNumber numberWithUnsignedInteger:[touch hash]];
143+
144+
if ([touches objectForKey:hash])
145+
{
146+
UIImageView *touchView = [touches objectForKey:hash];
147+
148+
if ([touch phase] == UITouchPhaseEnded || [touch phase] == UITouchPhaseCancelled)
149+
{
150+
[UIView beginAnimations:nil context:nil];
151+
[UIView setAnimationDuration:self.fadeDuration];
152+
153+
touchView.frame = CGRectMake(touchView.center.x - touchView.frame.size.width,
154+
touchView.center.y - touchView.frame.size.height,
155+
touchView.frame.size.width * 2,
156+
touchView.frame.size.height * 2);
157+
158+
touchView.alpha = 0.0;
159+
160+
[UIView commitAnimations];
161+
162+
[touchView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:self.fadeDuration];
163+
164+
[touches removeObjectForKey:hash];
165+
}
166+
else if ([touch phase] == UITouchPhaseMoved)
167+
{
168+
touchView.center = [touch locationInView:overlay];
169+
}
170+
}
171+
else if ([touch phase] == UITouchPhaseBegan)
172+
{
173+
UIImageView *touchView = [[[UIImageView alloc] initWithImage:self.touchImage] autorelease];
174+
175+
touchView.alpha = self.touchAlpha;
176+
177+
[overlay addSubview:touchView];
178+
179+
touchView.center = [touch locationInView:overlay];
180+
181+
[touches setObject:touchView forKey:hash];
182+
}
183+
}
184+
}
185+
186+
[super sendEvent:event];
187+
}
188+
189+
@end

LICENSE.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Copyright (c) 2011, Development Seed, Inc.
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without
5+
modification, are permitted provided that the following conditions are met:
6+
7+
* Redistributions of source code must retain the above copyright
8+
notice, this list of conditions and the following disclaimer.
9+
10+
* Redistributions in binary form must reproduce the above copyright
11+
notice, this list of conditions and the following disclaimer in the
12+
documentation and/or other materials provided with the distribution.
13+
14+
* Neither the name of Development Seed, Inc., nor the names of its
15+
contributors may be used to endorse or promote products derived from
16+
this software without specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Fingertips: Presentation mode for your iOS app
2+
3+
Fingertips is a small library (currently, one class) that gives you automatic presentation mode in your iOS app. Note that currently, this is only designed for the iPad 2, which features [hardware video mirroring](http://www.apple.com/ipad/features/mirroring.html) support. **This library does not do the mirroring for you!**
4+
5+
Just drop in our replacement `UIWindow` subclass and your app will automatically determine when an external screen is available. It will show every touch on-screen with a nice partially-transparent graphic that automatically fades out when the touch ends.
6+
7+
Here's a [demo video](http://vimeo.com/22136667).
8+
9+
## Configuration
10+
11+
You shouldn't need to configure anything, but if you want to tweak some knobs:
12+
13+
* `touchImage`: pass a `UIImage` to use for showing touches
14+
* `touchAlpha`: change the visible-touch alpha transparency
15+
* `fadeDuration`: change how long lifted touches fade out
16+
17+
## License
18+
19+
Copyright (c) 2011 Development Seed, Inc.
20+
21+
The Fingertips library should be accompanied by a LICENSE file. This file contains the license relevant to this distribution. If no license exists, please contact [Development Seed](http://developmentseed.org).

0 commit comments

Comments
 (0)