mirror of
https://github.com/joeblau/COSTouchVisualizer.git
synced 2024-09-11 12:36:58 +03:00
Refactor code to modern obj-c
This commit is contained in:
parent
ad729c993d
commit
b00850925c
15
Classes/COSOverlayVisualizerWindow.h
Normal file
15
Classes/COSOverlayVisualizerWindow.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// COSOverlayVisualizerWindow.h
|
||||||
|
// COSTouchVisualizer
|
||||||
|
//
|
||||||
|
// Created by Joseph Blau on 11/30/17.
|
||||||
|
// Copyright © 2017 conopsys. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface COSOverlayVisualizerWindow : UIWindow
|
||||||
|
|
||||||
|
- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
@end
|
31
Classes/COSOverlayVisualizerWindow.m
Normal file
31
Classes/COSOverlayVisualizerWindow.m
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// COSOverlayVisualizerWindow.m
|
||||||
|
// COSTouchVisualizer
|
||||||
|
//
|
||||||
|
// Created by Joseph Blau on 11/30/17.
|
||||||
|
// Copyright © 2017 conopsys. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "COSOverlayVisualizerWindow.h"
|
||||||
|
|
||||||
|
@implementation COSOverlayVisualizerWindow
|
||||||
|
|
||||||
|
// UIKit tries to get the rootViewController from the overlay window.
|
||||||
|
// Instead, try to find the rootViewController on some other
|
||||||
|
// application window.
|
||||||
|
// Fixes problems with status bar hiding, because it considers the
|
||||||
|
// overlay window a candidate for controlling the status bar.
|
||||||
|
- (UIViewController *)rootViewController {
|
||||||
|
|
||||||
|
for (UIWindow *window in [UIApplication sharedApplication].windows) {
|
||||||
|
if (self == window) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (window.rootViewController != nil) {
|
||||||
|
return window.rootViewController;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [super rootViewController];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
26
Classes/COSTouchConfig.h
Normal file
26
Classes/COSTouchConfig.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// COSTouchConfig.h
|
||||||
|
// COSTouchVisualizer
|
||||||
|
//
|
||||||
|
// Created by Joseph Blau on 12/2/17.
|
||||||
|
// Copyright © 2017 conopsys. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, COSTouchConfigTpye) {
|
||||||
|
COSTouchConfigTpyeContact,
|
||||||
|
COSTouchConfigTpyeRipple,
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface COSTouchConfig : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic) CGFloat alpha;
|
||||||
|
@property (nonatomic) NSTimeInterval fadeDuration;
|
||||||
|
@property (nonatomic, nullable) UIColor *strokeColor;
|
||||||
|
@property (nonatomic, nullable) UIColor *fillColor;
|
||||||
|
|
||||||
|
-(nonnull instancetype)initWithTouchConfigType:(COSTouchConfigTpye)configType NS_DESIGNATED_INITIALIZER;
|
||||||
|
-(nonnull instancetype)init NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
@end
|
49
Classes/COSTouchConfig.m
Normal file
49
Classes/COSTouchConfig.m
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// COSTouchConfig.m
|
||||||
|
// COSTouchVisualizer
|
||||||
|
//
|
||||||
|
// Created by Joseph Blau on 12/2/17.
|
||||||
|
// Copyright © 2017 conopsys. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "COSTouchConfig.h"
|
||||||
|
|
||||||
|
static const CGFloat COSTouchConfigContactAlpha = 0.5f;
|
||||||
|
static const CGFloat COSTouchConfigRippleAlpha = 0.2f;
|
||||||
|
static const NSTimeInterval COSTouchConfigContactFadeDuration = 0.3;
|
||||||
|
static const NSTimeInterval COSTouchConfigRippleFadeDuration = 0.2;
|
||||||
|
|
||||||
|
@implementation COSTouchConfig
|
||||||
|
|
||||||
|
-(instancetype)initWithTouchConfigType:(COSTouchConfigTpye)configType {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
switch (configType) {
|
||||||
|
case COSTouchConfigTpyeContact:
|
||||||
|
[self _configureContact];
|
||||||
|
break;
|
||||||
|
case COSTouchConfigTpyeRipple:
|
||||||
|
[self _configureRipple];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private
|
||||||
|
|
||||||
|
-(void)_configureContact {
|
||||||
|
self.strokeColor = [UIColor blackColor];
|
||||||
|
self.fillColor = [UIColor blackColor];
|
||||||
|
self.alpha = COSTouchConfigContactAlpha;
|
||||||
|
self.fadeDuration = COSTouchConfigContactFadeDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_configureRipple {
|
||||||
|
self.strokeColor = [UIColor whiteColor];
|
||||||
|
self.fillColor = [UIColor blueColor];
|
||||||
|
self.alpha = COSTouchConfigRippleAlpha;
|
||||||
|
self.fadeDuration = COSTouchConfigRippleFadeDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
19
Classes/COSTouchImageFactory.h
Normal file
19
Classes/COSTouchImageFactory.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// COSTouchImageFactory.h
|
||||||
|
// COSTouchVisualizer
|
||||||
|
//
|
||||||
|
// Created by Joseph Blau on 12/2/17.
|
||||||
|
// Copyright © 2017 conopsys. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@class COSTouchConfig;
|
||||||
|
|
||||||
|
@interface COSTouchImageFactory : NSObject
|
||||||
|
|
||||||
|
+(nonnull UIImage *)imageWithTouchConfig:(nonnull COSTouchConfig*)touchConfig;
|
||||||
|
|
||||||
|
-(nonnull instancetype)init NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
@end
|
48
Classes/COSTouchImageFactory.m
Normal file
48
Classes/COSTouchImageFactory.m
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// COSTouchImageFactory.m
|
||||||
|
// COSTouchVisualizer
|
||||||
|
//
|
||||||
|
// Created by Joseph Blau on 12/2/17.
|
||||||
|
// Copyright © 2017 conopsys. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "COSTouchImageFactory.h"
|
||||||
|
#import "COSTouchConfig.h"
|
||||||
|
|
||||||
|
static const CGFloat COSTouchImageFactorySideSize = 50.0f;
|
||||||
|
|
||||||
|
@implementation COSTouchImageFactory
|
||||||
|
|
||||||
|
+(UIImage *)imageWithTouchConfig:(COSTouchConfig *)touchConfig {
|
||||||
|
UIImage *touchImage = ({
|
||||||
|
UIImage *image = [UIImage new];
|
||||||
|
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0.0f,
|
||||||
|
0.0f,
|
||||||
|
COSTouchImageFactorySideSize,
|
||||||
|
COSTouchImageFactorySideSize)];
|
||||||
|
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
||||||
|
CGPoint center = CGPointMake(COSTouchImageFactorySideSize / 2.0f,
|
||||||
|
COSTouchImageFactorySideSize / 2.0f);
|
||||||
|
|
||||||
|
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:center
|
||||||
|
radius:22.0
|
||||||
|
startAngle:0
|
||||||
|
endAngle:2 * M_PI
|
||||||
|
clockwise:YES];
|
||||||
|
drawPath.lineWidth = 2.0;
|
||||||
|
|
||||||
|
[touchConfig.strokeColor setStroke];
|
||||||
|
[touchConfig.fillColor setFill];
|
||||||
|
|
||||||
|
[drawPath stroke];
|
||||||
|
[drawPath fill];
|
||||||
|
[clipPath addClip];
|
||||||
|
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
|
||||||
|
image;
|
||||||
|
});
|
||||||
|
return touchImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
17
Classes/COSTouchImageView.h
Normal file
17
Classes/COSTouchImageView.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// COSTouchSpotView.h
|
||||||
|
// COSTouchVisualizer
|
||||||
|
//
|
||||||
|
// Created by Joseph Blau on 11/30/17.
|
||||||
|
// Copyright © 2017 conopsys. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface COSTouchImageView : UIImageView
|
||||||
|
|
||||||
|
@property (nonatomic) NSTimeInterval timestamp;
|
||||||
|
@property (nonatomic) BOOL shouldAutomaticallyRemoveAfterTimeout;
|
||||||
|
@property (nonatomic, getter=isFadingOut) BOOL fadingOut;
|
||||||
|
|
||||||
|
@end
|
13
Classes/COSTouchImageView.m
Normal file
13
Classes/COSTouchImageView.m
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// COSTouchSpotView.m
|
||||||
|
// COSTouchVisualizer
|
||||||
|
//
|
||||||
|
// Created by Joseph Blau on 11/30/17.
|
||||||
|
// Copyright © 2017 conopsys. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "COSTouchImageView.h"
|
||||||
|
|
||||||
|
@implementation COSTouchImageView
|
||||||
|
|
||||||
|
@end
|
@ -12,6 +12,14 @@
|
|||||||
A71946C61C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */; };
|
A71946C61C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */; };
|
||||||
A71946C81C7EFB69003B7C4A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6F67FD018DE12B4001C954A /* UIKit.framework */; };
|
A71946C81C7EFB69003B7C4A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6F67FD018DE12B4001C954A /* UIKit.framework */; };
|
||||||
A71946C91C7EFB74003B7C4A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6F67FCC18DE12B4001C954A /* Foundation.framework */; };
|
A71946C91C7EFB74003B7C4A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6F67FCC18DE12B4001C954A /* Foundation.framework */; };
|
||||||
|
E6C633A91FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C633A71FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h */; };
|
||||||
|
E6C633AA1FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C633A81FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m */; };
|
||||||
|
E6C633AD1FD0FC8E000DA40C /* COSTouchImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C633AB1FD0FC8E000DA40C /* COSTouchImageView.h */; };
|
||||||
|
E6C633AE1FD0FC8E000DA40C /* COSTouchImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C633AC1FD0FC8E000DA40C /* COSTouchImageView.m */; };
|
||||||
|
E6C633B11FD2CCB2000DA40C /* COSTouchConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C633AF1FD2CCB2000DA40C /* COSTouchConfig.h */; };
|
||||||
|
E6C633B21FD2CCB2000DA40C /* COSTouchConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C633B01FD2CCB2000DA40C /* COSTouchConfig.m */; };
|
||||||
|
E6C633B51FD2D4FD000DA40C /* COSTouchImageFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C633B31FD2D4FD000DA40C /* COSTouchImageFactory.h */; };
|
||||||
|
E6C633B61FD2D4FD000DA40C /* COSTouchImageFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = E6C633B41FD2D4FD000DA40C /* COSTouchImageFactory.m */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@ -20,6 +28,14 @@
|
|||||||
A71946C11C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = COSTouchVisualizerWindow.h; sourceTree = "<group>"; };
|
A71946C11C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = COSTouchVisualizerWindow.h; sourceTree = "<group>"; };
|
||||||
A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = COSTouchVisualizerWindow.m; sourceTree = "<group>"; };
|
A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = COSTouchVisualizerWindow.m; sourceTree = "<group>"; };
|
||||||
A71946C31C7EFB1F003B7C4A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
A71946C31C7EFB1F003B7C4A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
E6C633A71FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = COSOverlayVisualizerWindow.h; sourceTree = "<group>"; };
|
||||||
|
E6C633A81FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = COSOverlayVisualizerWindow.m; sourceTree = "<group>"; };
|
||||||
|
E6C633AB1FD0FC8E000DA40C /* COSTouchImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = COSTouchImageView.h; sourceTree = "<group>"; };
|
||||||
|
E6C633AC1FD0FC8E000DA40C /* COSTouchImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = COSTouchImageView.m; sourceTree = "<group>"; };
|
||||||
|
E6C633AF1FD2CCB2000DA40C /* COSTouchConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = COSTouchConfig.h; sourceTree = "<group>"; };
|
||||||
|
E6C633B01FD2CCB2000DA40C /* COSTouchConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = COSTouchConfig.m; sourceTree = "<group>"; };
|
||||||
|
E6C633B31FD2D4FD000DA40C /* COSTouchImageFactory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = COSTouchImageFactory.h; sourceTree = "<group>"; };
|
||||||
|
E6C633B41FD2D4FD000DA40C /* COSTouchImageFactory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = COSTouchImageFactory.m; sourceTree = "<group>"; };
|
||||||
E6F67FCC18DE12B4001C954A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
E6F67FCC18DE12B4001C954A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||||
E6F67FD018DE12B4001C954A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
E6F67FD018DE12B4001C954A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
@ -44,6 +60,14 @@
|
|||||||
A71946C11C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h */,
|
A71946C11C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h */,
|
||||||
A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */,
|
A71946C21C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m */,
|
||||||
A71946C31C7EFB1F003B7C4A /* Info.plist */,
|
A71946C31C7EFB1F003B7C4A /* Info.plist */,
|
||||||
|
E6C633A71FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h */,
|
||||||
|
E6C633A81FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m */,
|
||||||
|
E6C633AB1FD0FC8E000DA40C /* COSTouchImageView.h */,
|
||||||
|
E6C633AC1FD0FC8E000DA40C /* COSTouchImageView.m */,
|
||||||
|
E6C633AF1FD2CCB2000DA40C /* COSTouchConfig.h */,
|
||||||
|
E6C633B01FD2CCB2000DA40C /* COSTouchConfig.m */,
|
||||||
|
E6C633B31FD2D4FD000DA40C /* COSTouchImageFactory.h */,
|
||||||
|
E6C633B41FD2D4FD000DA40C /* COSTouchImageFactory.m */,
|
||||||
);
|
);
|
||||||
name = Source;
|
name = Source;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -81,7 +105,11 @@
|
|||||||
isa = PBXHeadersBuildPhase;
|
isa = PBXHeadersBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
E6C633A91FD0FB9D000DA40C /* COSOverlayVisualizerWindow.h in Headers */,
|
||||||
|
E6C633B51FD2D4FD000DA40C /* COSTouchImageFactory.h in Headers */,
|
||||||
|
E6C633AD1FD0FC8E000DA40C /* COSTouchImageView.h in Headers */,
|
||||||
A71946C51C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h in Headers */,
|
A71946C51C7EFB1F003B7C4A /* COSTouchVisualizerWindow.h in Headers */,
|
||||||
|
E6C633B11FD2CCB2000DA40C /* COSTouchConfig.h in Headers */,
|
||||||
A71946C41C7EFB1F003B7C4A /* COSTouchVisualizer.h in Headers */,
|
A71946C41C7EFB1F003B7C4A /* COSTouchVisualizer.h in Headers */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
@ -155,6 +183,10 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
E6C633AA1FD0FB9D000DA40C /* COSOverlayVisualizerWindow.m in Sources */,
|
||||||
|
E6C633B61FD2D4FD000DA40C /* COSTouchImageFactory.m in Sources */,
|
||||||
|
E6C633B21FD2CCB2000DA40C /* COSTouchConfig.m in Sources */,
|
||||||
|
E6C633AE1FD0FC8E000DA40C /* COSTouchImageView.m in Sources */,
|
||||||
A71946C61C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m in Sources */,
|
A71946C61C7EFB1F003B7C4A /* COSTouchVisualizerWindow.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -7,36 +7,32 @@
|
|||||||
//
|
//
|
||||||
#include <UIKit/UIKit.h>
|
#include <UIKit/UIKit.h>
|
||||||
|
|
||||||
@protocol COSTouchVisualizerWindowDelegate;
|
typedef NS_ENUM(NSUInteger, COSTouchVisualizerWindowTouchVisibility) {
|
||||||
|
COSTouchVisualizerWindowTouchVisibilityNever,
|
||||||
|
COSTouchVisualizerWindowTouchVisibilityRemoteOnly,
|
||||||
|
COSTouchVisualizerWindowTouchVisibilityRemoteAndLocal,
|
||||||
|
};
|
||||||
|
|
||||||
|
@class COSTouchVisualizerWindow;
|
||||||
|
@class COSTouchConfig;
|
||||||
|
|
||||||
@interface COSTouchVisualizerWindow : UIWindow
|
@interface COSTouchVisualizerWindow : UIWindow
|
||||||
|
|
||||||
@property (nonatomic, readonly, getter=isActive) BOOL active;
|
@property (nonatomic, readonly, getter=isMorphEnabled) BOOL morphEnabled;
|
||||||
@property (nonatomic, weak) id<COSTouchVisualizerWindowDelegate> touchVisualizerWindowDelegate;
|
@property (nonatomic, readonly, nonnull) COSTouchConfig *touchContactConfig;
|
||||||
|
@property (nonatomic, readonly, nonnull) COSTouchConfig *touchRippleConfig;
|
||||||
|
@property (nonatomic, readonly) COSTouchVisualizerWindowTouchVisibility touchVisibility;
|
||||||
|
|
||||||
// Touch effects
|
-(nonnull instancetype)initWithFrame:(CGRect)frame
|
||||||
@property (nonatomic) UIImage *touchImage;
|
morphEnabled:(BOOL)morphEnabled
|
||||||
@property (nonatomic) CGFloat touchAlpha;
|
touchVisibility:(COSTouchVisualizerWindowTouchVisibility)touchVisibility
|
||||||
@property (nonatomic) NSTimeInterval fadeDuration;
|
contactConfig:(nullable COSTouchConfig*)contactConfig
|
||||||
@property (nonatomic) UIColor *strokeColor;
|
rippleConfig:(nullable COSTouchConfig*)rippleConfig NS_DESIGNATED_INITIALIZER;
|
||||||
@property (nonatomic) UIColor *fillColor;
|
-(nonnull instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
|
||||||
|
-(nonnull instancetype)init NS_UNAVAILABLE;
|
||||||
|
-(nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
|
||||||
|
|
||||||
// Ripple Effects
|
|
||||||
@property (nonatomic) UIImage *rippleImage;
|
|
||||||
@property (nonatomic) CGFloat rippleAlpha;
|
|
||||||
@property (nonatomic) NSTimeInterval rippleFadeDuration;
|
|
||||||
@property (nonatomic) UIColor *rippleStrokeColor;
|
|
||||||
@property (nonatomic) UIColor *rippleFillColor;
|
|
||||||
|
|
||||||
@property (nonatomic) BOOL stationaryMorphEnabled; // default: YES
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@protocol COSTouchVisualizerWindowDelegate <NSObject>
|
|
||||||
|
|
||||||
@optional
|
|
||||||
|
|
||||||
- (BOOL)touchVisualizerWindowShouldShowFingertip:(COSTouchVisualizerWindow *)window;
|
|
||||||
- (BOOL)touchVisualizerWindowShouldAlwaysShowFingertip:(COSTouchVisualizerWindow *)window;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
@ -7,46 +7,12 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "COSTouchVisualizerWindow.h"
|
#import "COSTouchVisualizerWindow.h"
|
||||||
|
#import "COSOverlayVisualizerWindow.h"
|
||||||
|
#import "COSTouchImageView.h"
|
||||||
|
#import "COSTouchConfig.h"
|
||||||
|
#import "COSTouchImageFactory.h"
|
||||||
|
|
||||||
#pragma mark - Touch Visualizer Window
|
static const NSTimeInterval COSTouchVisualizerWindowRemoveDelay = 0.2;
|
||||||
|
|
||||||
@interface TouchVisualizerWindow : UIWindow
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation TouchVisualizerWindow
|
|
||||||
|
|
||||||
// UIKit tries to get the rootViewController from the overlay window.
|
|
||||||
// Instead, try to find the rootViewController on some other
|
|
||||||
// application window.
|
|
||||||
// Fixes problems with status bar hiding, because it considers the
|
|
||||||
// overlay window a candidate for controlling the status bar.
|
|
||||||
- (UIViewController *)rootViewController {
|
|
||||||
for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
|
|
||||||
if (self == window)
|
|
||||||
continue;
|
|
||||||
UIViewController *realRootViewController = window.rootViewController;
|
|
||||||
if (realRootViewController != nil)
|
|
||||||
return realRootViewController;
|
|
||||||
}
|
|
||||||
return [super rootViewController];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
#pragma mark - Conopsys Touch Spot View
|
|
||||||
|
|
||||||
@interface COSTouchSpotView : UIImageView
|
|
||||||
|
|
||||||
@property (nonatomic) NSTimeInterval timestamp;
|
|
||||||
@property (nonatomic) BOOL shouldAutomaticallyRemoveAfterTimeout;
|
|
||||||
@property (nonatomic, getter=isFadingOut) BOOL fadingOut;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation COSTouchSpotView
|
|
||||||
@end
|
|
||||||
|
|
||||||
#pragma mark - Conopsys Touch Visualizer Window
|
|
||||||
|
|
||||||
@interface COSTouchVisualizerWindow ()
|
@interface COSTouchVisualizerWindow ()
|
||||||
|
|
||||||
@ -56,97 +22,43 @@
|
|||||||
@property (nonatomic) NSTimer *timer;
|
@property (nonatomic) NSTimer *timer;
|
||||||
@property (nonatomic) NSSet *allTouches;
|
@property (nonatomic) NSSet *allTouches;
|
||||||
|
|
||||||
- (void)COSTouchVisualizerWindow_commonInit;
|
@property (nonatomic) UIImage *touchImage;
|
||||||
- (void)scheduleFingerTipRemoval;
|
@property (nonatomic) UIImage *rippleImage;
|
||||||
- (void)cancelScheduledFingerTipRemoval;
|
|
||||||
- (void)removeInactiveFingerTips;
|
@property (nonatomic) COSTouchConfig *touchContactConfig;
|
||||||
- (void)removeFingerTipWithHash:(NSUInteger)hash animated:(BOOL)animated;
|
@property (nonatomic) COSTouchConfig *touchRippleConfig;
|
||||||
- (BOOL)shouldAutomaticallyRemoveFingerTipForTouch:(UITouch *)touch;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation COSTouchVisualizerWindow
|
@implementation COSTouchVisualizerWindow
|
||||||
|
|
||||||
- (id)initWithCoder:(NSCoder *)decoder {
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
// This covers NIB-loaded windows.
|
morphEnabled:(BOOL)morphEnabled
|
||||||
if (self = [super initWithCoder:decoder])
|
touchVisibility:(COSTouchVisualizerWindowTouchVisibility)touchVisibility
|
||||||
[self COSTouchVisualizerWindow_commonInit];
|
contactConfig:(COSTouchConfig *)contactConfig
|
||||||
|
rippleConfig:(COSTouchConfig *)rippleConfig {
|
||||||
|
self = [super initWithFrame:frame];
|
||||||
|
if (self) {
|
||||||
|
_morphEnabled = morphEnabled;
|
||||||
|
_touchVisibility = touchVisibility;
|
||||||
|
_touchContactConfig = contactConfig ?: [[COSTouchConfig alloc] initWithTouchConfigType:COSTouchConfigTpyeContact];
|
||||||
|
_touchRippleConfig = rippleConfig ?: [[COSTouchConfig alloc] initWithTouchConfigType:COSTouchConfigTpyeRipple];
|
||||||
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithFrame:(CGRect)rect {
|
|
||||||
// This covers programmatically-created windows.
|
|
||||||
if (self = [super initWithFrame:rect])
|
|
||||||
[self COSTouchVisualizerWindow_commonInit];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)COSTouchVisualizerWindow_commonInit {
|
|
||||||
self.strokeColor = [UIColor blackColor];
|
|
||||||
self.fillColor = [UIColor whiteColor];
|
|
||||||
self.rippleStrokeColor = [UIColor whiteColor];
|
|
||||||
self.rippleFillColor = [UIColor blueColor];
|
|
||||||
self.touchAlpha = 0.5;
|
|
||||||
self.fadeDuration = 0.3;
|
|
||||||
self.rippleAlpha = 0.2;
|
|
||||||
self.rippleFadeDuration = 0.2;
|
|
||||||
self.stationaryMorphEnabled = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Touch / Ripple and Images
|
#pragma mark - Touch / Ripple and Images
|
||||||
|
|
||||||
- (UIImage *)touchImage {
|
- (UIImage *)touchImage {
|
||||||
if (!_touchImage) {
|
if (!_touchImage) {
|
||||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
|
_touchImage = [COSTouchImageFactory imageWithTouchConfig:self.touchContactConfig];
|
||||||
|
|
||||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
|
||||||
|
|
||||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
|
|
||||||
radius:22.0
|
|
||||||
startAngle:0
|
|
||||||
endAngle:2 * M_PI
|
|
||||||
clockwise:YES];
|
|
||||||
|
|
||||||
drawPath.lineWidth = 2.0;
|
|
||||||
|
|
||||||
[self.strokeColor setStroke];
|
|
||||||
[self.fillColor setFill];
|
|
||||||
|
|
||||||
[drawPath stroke];
|
|
||||||
[drawPath fill];
|
|
||||||
|
|
||||||
[clipPath addClip];
|
|
||||||
|
|
||||||
_touchImage = UIGraphicsGetImageFromCurrentImageContext();
|
|
||||||
UIGraphicsEndImageContext();
|
|
||||||
}
|
}
|
||||||
return _touchImage;
|
return _touchImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIImage *)rippleImage {
|
- (UIImage *)rippleImage {
|
||||||
if (!_rippleImage) {
|
if (!_rippleImage) {
|
||||||
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 50.0, 50.0)];
|
_rippleImage = [COSTouchImageFactory imageWithTouchConfig:self.touchRippleConfig];
|
||||||
|
|
||||||
UIGraphicsBeginImageContextWithOptions(clipPath.bounds.size, NO, 0);
|
|
||||||
|
|
||||||
UIBezierPath *drawPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(25.0, 25.0)
|
|
||||||
radius:22.0
|
|
||||||
startAngle:0
|
|
||||||
endAngle:2 * M_PI
|
|
||||||
clockwise:YES];
|
|
||||||
|
|
||||||
drawPath.lineWidth = 2.0;
|
|
||||||
|
|
||||||
[self.rippleStrokeColor setStroke];
|
|
||||||
[self.rippleFillColor setFill];
|
|
||||||
|
|
||||||
[drawPath stroke];
|
|
||||||
[drawPath fill];
|
|
||||||
|
|
||||||
[clipPath addClip];
|
|
||||||
|
|
||||||
_rippleImage = UIGraphicsGetImageFromCurrentImageContext();
|
|
||||||
UIGraphicsEndImageContext();
|
|
||||||
}
|
}
|
||||||
return _rippleImage;
|
return _rippleImage;
|
||||||
}
|
}
|
||||||
@ -165,98 +77,94 @@
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isActive {
|
|
||||||
// should show fingertip or not
|
|
||||||
if (![self.touchVisualizerWindowDelegate respondsToSelector:@selector(touchVisualizerWindowShouldShowFingertip:)] ||
|
|
||||||
[self.touchVisualizerWindowDelegate touchVisualizerWindowShouldShowFingertip:self]) {
|
|
||||||
// should always show or only when any screen is mirrored.
|
|
||||||
return (([self.touchVisualizerWindowDelegate respondsToSelector:@selector(touchVisualizerWindowShouldAlwaysShowFingertip:)] &&
|
|
||||||
[self.touchVisualizerWindowDelegate touchVisualizerWindowShouldAlwaysShowFingertip:self]) ||
|
|
||||||
[self anyScreenIsMirrored]);
|
|
||||||
} else {
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - UIWindow overrides
|
#pragma mark - UIWindow overrides
|
||||||
|
|
||||||
- (void)sendEvent:(UIEvent *)event {
|
- (void)sendEvent:(UIEvent *)event {
|
||||||
if (self.active) {
|
[super sendEvent:event];
|
||||||
self.allTouches = [event allTouches];
|
|
||||||
for (UITouch *touch in [self.allTouches allObjects]) {
|
switch (self.touchVisibility) {
|
||||||
switch (touch.phase) {
|
case COSTouchVisualizerWindowTouchVisibilityNever:
|
||||||
case UITouchPhaseBegan:
|
return;
|
||||||
case UITouchPhaseMoved: {
|
break;
|
||||||
// Generate ripples
|
|
||||||
COSTouchSpotView *rippleView = [[COSTouchSpotView alloc] initWithImage:self.rippleImage];
|
case COSTouchVisualizerWindowTouchVisibilityRemoteOnly:
|
||||||
[self.overlayWindow addSubview:rippleView];
|
case COSTouchVisualizerWindowTouchVisibilityRemoteAndLocal: {
|
||||||
|
self.allTouches = [event allTouches];
|
||||||
rippleView.alpha = self.rippleAlpha;
|
for (UITouch *touch in [self.allTouches allObjects]) {
|
||||||
rippleView.center = [touch locationInView:self.overlayWindow];
|
switch (touch.phase) {
|
||||||
|
case UITouchPhaseBegan:
|
||||||
[UIView animateWithDuration:self.rippleFadeDuration
|
case UITouchPhaseMoved: {
|
||||||
delay:0.0
|
// Generate ripples
|
||||||
options:UIViewAnimationOptionCurveEaseIn // See other
|
COSTouchImageView *rippleView = [[COSTouchImageView alloc] initWithImage:self.rippleImage];
|
||||||
// options
|
[self.overlayWindow addSubview:rippleView];
|
||||||
animations:^{
|
|
||||||
[rippleView setAlpha:0.0];
|
rippleView.alpha = self.touchRippleConfig.alpha;
|
||||||
[rippleView setFrame:CGRectInset(rippleView.frame, 25, 25)];
|
rippleView.center = [touch locationInView:self.overlayWindow];
|
||||||
} completion:^(BOOL finished) {
|
|
||||||
[rippleView removeFromSuperview];
|
[UIView animateWithDuration:self.touchRippleConfig.fadeDuration
|
||||||
}];
|
delay:0.0
|
||||||
}
|
options:UIViewAnimationOptionCurveEaseIn
|
||||||
case UITouchPhaseStationary: {
|
animations:^{
|
||||||
COSTouchSpotView *touchView = (COSTouchSpotView *)[self.overlayWindow viewWithTag:touch.hash];
|
[rippleView setAlpha:0.0];
|
||||||
|
[rippleView setFrame:CGRectInset(rippleView.frame, 25, 25)];
|
||||||
if (touch.phase != UITouchPhaseStationary && touchView != nil && [touchView isFadingOut]) {
|
} completion:^(BOOL finished) {
|
||||||
[self.timer invalidate];
|
[rippleView removeFromSuperview];
|
||||||
[touchView removeFromSuperview];
|
}];
|
||||||
touchView = nil;
|
|
||||||
}
|
}
|
||||||
|
case UITouchPhaseStationary: {
|
||||||
if (touchView == nil && touch.phase != UITouchPhaseStationary) {
|
COSTouchImageView *touchView = (COSTouchImageView *)[self.overlayWindow viewWithTag:touch.hash];
|
||||||
touchView = [[COSTouchSpotView alloc] initWithImage:self.touchImage];
|
|
||||||
[self.overlayWindow addSubview:touchView];
|
if (touch.phase != UITouchPhaseStationary && touchView != nil && [touchView isFadingOut]) {
|
||||||
|
[self.timer invalidate];
|
||||||
if (self.stationaryMorphEnabled) {
|
[touchView removeFromSuperview];
|
||||||
if (self.timer) {
|
touchView = nil;
|
||||||
[self.timer invalidate];
|
|
||||||
}
|
|
||||||
|
|
||||||
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.6
|
|
||||||
target:self
|
|
||||||
selector:@selector(performMorph:)
|
|
||||||
userInfo:touchView
|
|
||||||
repeats:YES];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (touchView == nil && touch.phase != UITouchPhaseStationary) {
|
||||||
|
touchView = [[COSTouchImageView alloc] initWithImage:self.touchImage];
|
||||||
|
[self.overlayWindow addSubview:touchView];
|
||||||
|
|
||||||
|
if (self.morphEnabled) {
|
||||||
|
if (self.timer) {
|
||||||
|
[self.timer invalidate];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.6
|
||||||
|
target:self
|
||||||
|
selector:@selector(performMorphWithTouchView:)
|
||||||
|
userInfo:touchView
|
||||||
|
repeats:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (![touchView isFadingOut]) {
|
||||||
|
touchView.alpha = self.touchContactConfig.alpha;
|
||||||
|
touchView.center = [touch locationInView:self.overlayWindow];
|
||||||
|
touchView.tag = touch.hash;
|
||||||
|
touchView.timestamp = touch.timestamp;
|
||||||
|
touchView.shouldAutomaticallyRemoveAfterTimeout = [self shouldAutomaticallyRemoveFingerTipForTouch:touch];
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (![touchView isFadingOut]) {
|
case UITouchPhaseEnded:
|
||||||
touchView.alpha = self.touchAlpha;
|
case UITouchPhaseCancelled: {
|
||||||
touchView.center = [touch locationInView:self.overlayWindow];
|
[self removeFingerTipWithHash:touch.hash animated:YES];
|
||||||
touchView.tag = touch.hash;
|
break;
|
||||||
touchView.timestamp = touch.timestamp;
|
|
||||||
touchView.shouldAutomaticallyRemoveAfterTimeout = [self shouldAutomaticallyRemoveFingerTipForTouch:touch];
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case UITouchPhaseEnded:
|
|
||||||
case UITouchPhaseCancelled: {
|
|
||||||
[self removeFingerTipWithHash:touch.hash animated:YES];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[super sendEvent:event];
|
|
||||||
[self scheduleFingerTipRemoval]; // We may not see all UITouchPhaseEnded/UITouchPhaseCancelled events.
|
[self scheduleFingerTipRemoval]; // We may not see all UITouchPhaseEnded/UITouchPhaseCancelled events.
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Private
|
|
||||||
|
|
||||||
- (UIWindow *)overlayWindow {
|
- (UIWindow *)overlayWindow {
|
||||||
if (!_overlayWindow) {
|
if (!_overlayWindow) {
|
||||||
_overlayWindow = [[TouchVisualizerWindow alloc] initWithFrame:self.frame];
|
_overlayWindow = [[COSOverlayVisualizerWindow alloc] initWithFrame:self.frame];
|
||||||
_overlayWindow.userInteractionEnabled = NO;
|
_overlayWindow.userInteractionEnabled = NO;
|
||||||
_overlayWindow.windowLevel = UIWindowLevelStatusBar;
|
_overlayWindow.windowLevel = UIWindowLevelStatusBar;
|
||||||
_overlayWindow.backgroundColor = [UIColor clearColor];
|
_overlayWindow.backgroundColor = [UIColor clearColor];
|
||||||
@ -264,11 +172,12 @@
|
|||||||
}
|
}
|
||||||
return _overlayWindow;
|
return _overlayWindow;
|
||||||
}
|
}
|
||||||
|
#pragma mark - Private
|
||||||
|
|
||||||
- (void)scheduleFingerTipRemoval {
|
- (void)scheduleFingerTipRemoval {
|
||||||
|
if (self.fingerTipRemovalScheduled) {
|
||||||
if (self.fingerTipRemovalScheduled)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
self.fingerTipRemovalScheduled = YES;
|
self.fingerTipRemovalScheduled = YES;
|
||||||
[self performSelector:@selector(removeInactiveFingerTips)
|
[self performSelector:@selector(removeInactiveFingerTips)
|
||||||
withObject:nil
|
withObject:nil
|
||||||
@ -286,33 +195,34 @@
|
|||||||
self.fingerTipRemovalScheduled = NO;
|
self.fingerTipRemovalScheduled = NO;
|
||||||
|
|
||||||
NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime];
|
NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime];
|
||||||
const CGFloat REMOVAL_DELAY = 0.2;
|
|
||||||
for (COSTouchSpotView *touchView in [self.overlayWindow subviews]) {
|
for (COSTouchImageView *touchView in [self.overlayWindow subviews]) {
|
||||||
if (![touchView isKindOfClass:[COSTouchSpotView class]])
|
if (![touchView isKindOfClass:[COSTouchImageView class]]) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (touchView.shouldAutomaticallyRemoveAfterTimeout && now > touchView.timestamp + REMOVAL_DELAY)
|
if (touchView.shouldAutomaticallyRemoveAfterTimeout && now > touchView.timestamp + COSTouchVisualizerWindowRemoveDelay) {
|
||||||
[self removeFingerTipWithHash:touchView.tag animated:YES];
|
[self removeFingerTipWithHash:touchView.tag animated:YES];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([[self.overlayWindow subviews] count])
|
if ([[self.overlayWindow subviews] count]) {
|
||||||
[self scheduleFingerTipRemoval];
|
[self scheduleFingerTipRemoval];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)removeFingerTipWithHash:(NSUInteger)hash animated:(BOOL)animated {
|
- (void)removeFingerTipWithHash:(NSUInteger)hash animated:(BOOL)animated {
|
||||||
COSTouchSpotView *touchView = (COSTouchSpotView *)[self.overlayWindow viewWithTag:hash];
|
COSTouchImageView *touchView = (COSTouchImageView *)[self.overlayWindow viewWithTag:hash];
|
||||||
if (touchView == nil)
|
if (touchView == nil || [touchView isFadingOut]) {
|
||||||
return;
|
|
||||||
|
|
||||||
if ([touchView isFadingOut])
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL animationsWereEnabled = [UIView areAnimationsEnabled];
|
BOOL animationsWereEnabled = [UIView areAnimationsEnabled];
|
||||||
|
|
||||||
if (animated) {
|
if (animated) {
|
||||||
[UIView setAnimationsEnabled:YES];
|
[UIView setAnimationsEnabled:YES];
|
||||||
[UIView beginAnimations:nil context:nil];
|
[UIView beginAnimations:nil context:nil];
|
||||||
[UIView setAnimationDuration:self.fadeDuration];
|
[UIView setAnimationDuration:self.touchContactConfig.fadeDuration];
|
||||||
}
|
}
|
||||||
|
|
||||||
touchView.frame = CGRectMake(touchView.center.x - touchView.frame.size.width,
|
touchView.frame = CGRectMake(touchView.center.x - touchView.frame.size.width,
|
||||||
@ -329,7 +239,7 @@
|
|||||||
touchView.fadingOut = YES;
|
touchView.fadingOut = YES;
|
||||||
[touchView performSelector:@selector(removeFromSuperview)
|
[touchView performSelector:@selector(removeFromSuperview)
|
||||||
withObject:nil
|
withObject:nil
|
||||||
afterDelay:self.fadeDuration];
|
afterDelay:self.touchContactConfig.fadeDuration];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)shouldAutomaticallyRemoveFingerTipForTouch:(UITouch *)touch;
|
- (BOOL)shouldAutomaticallyRemoveFingerTipForTouch:(UITouch *)touch;
|
||||||
@ -346,40 +256,39 @@
|
|||||||
// don't use UITouchPhaseStationary touches for those. *sigh*). So we
|
// don't use UITouchPhaseStationary touches for those. *sigh*). So we
|
||||||
// end up with this more complicated setup.
|
// end up with this more complicated setup.
|
||||||
|
|
||||||
UIView *view = [touch view];
|
UIView *touchView = [touch view];
|
||||||
view = [view hitTest:[touch locationInView:view] withEvent:nil];
|
touchView = [touchView hitTest:[touch locationInView:touchView] withEvent:nil];
|
||||||
|
|
||||||
while (view != nil) {
|
while (touchView != nil) {
|
||||||
if ([view isKindOfClass:[UITableViewCell class]]) {
|
if ([touchView isKindOfClass:[UITableViewCell class]]) {
|
||||||
for (UIGestureRecognizer *recognizer in [touch gestureRecognizers]) {
|
for (UIGestureRecognizer *recognizer in [touch gestureRecognizers]) {
|
||||||
if ([recognizer isKindOfClass:[UISwipeGestureRecognizer class]])
|
if ([recognizer isKindOfClass:[UISwipeGestureRecognizer class]])
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([view isKindOfClass:[UITableView class]]) {
|
if ([touchView isKindOfClass:[UITableView class]] &&
|
||||||
if ([[touch gestureRecognizers] count] == 0)
|
[[touch gestureRecognizers] count] == 0) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
view = view.superview;
|
touchView = touchView.superview;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)performMorph:(NSTimer *)theTimer {
|
- (void)performMorphWithTouchView:(COSTouchImageView *)touchView {
|
||||||
UIView *view = (UIView *)[theTimer userInfo];
|
|
||||||
NSTimeInterval duration = .4;
|
NSTimeInterval duration = .4;
|
||||||
NSTimeInterval delay = 0;
|
NSTimeInterval delay = 0;
|
||||||
// Start
|
// Start
|
||||||
view.alpha = self.touchAlpha;
|
touchView.alpha = self.touchContactConfig.alpha;
|
||||||
view.transform = CGAffineTransformMakeScale(1, 1);
|
touchView.transform = CGAffineTransformMakeScale(1, 1);
|
||||||
[UIView animateWithDuration:duration / 4
|
[UIView animateWithDuration:duration / 4
|
||||||
delay:delay
|
delay:delay
|
||||||
options:0
|
options:0
|
||||||
animations:^{
|
animations:^{
|
||||||
// End
|
// End
|
||||||
view.transform = CGAffineTransformMakeScale(1, 1.2);
|
touchView.transform = CGAffineTransformMakeScale(1, 1.2);
|
||||||
}
|
}
|
||||||
completion:^(BOOL finished) {
|
completion:^(BOOL finished) {
|
||||||
[UIView animateWithDuration:duration / 4
|
[UIView animateWithDuration:duration / 4
|
||||||
@ -387,7 +296,7 @@
|
|||||||
options:0
|
options:0
|
||||||
animations:^{
|
animations:^{
|
||||||
// End
|
// End
|
||||||
view.transform = CGAffineTransformMakeScale(1.2, 0.9);
|
touchView.transform = CGAffineTransformMakeScale(1.2, 0.9);
|
||||||
}
|
}
|
||||||
completion:^(BOOL finished) {
|
completion:^(BOOL finished) {
|
||||||
[UIView animateWithDuration:duration / 4
|
[UIView animateWithDuration:duration / 4
|
||||||
@ -395,7 +304,7 @@
|
|||||||
options:0
|
options:0
|
||||||
animations:^{
|
animations:^{
|
||||||
// End
|
// End
|
||||||
view.transform = CGAffineTransformMakeScale(0.9, 0.9);
|
touchView.transform = CGAffineTransformMakeScale(0.9, 0.9);
|
||||||
}
|
}
|
||||||
completion:^(BOOL finished) {
|
completion:^(BOOL finished) {
|
||||||
[UIView animateWithDuration:duration / 4
|
[UIView animateWithDuration:duration / 4
|
||||||
@ -403,12 +312,13 @@
|
|||||||
options:0
|
options:0
|
||||||
animations:^{
|
animations:^{
|
||||||
// End
|
// End
|
||||||
view.transform = CGAffineTransformMakeScale(1, 1);
|
touchView.transform = CGAffineTransformMakeScale(1, 1);
|
||||||
}
|
}
|
||||||
completion:^(BOOL finished){
|
completion:^(BOOL finished){
|
||||||
// If there are no touches, remove this morping touch
|
// If there are no touches, remove this morping touch
|
||||||
if (self.allTouches.count == 0)
|
if (self.allTouches.count == 0) {
|
||||||
[view removeFromSuperview];
|
[touchView removeFromSuperview];
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
}];
|
}];
|
||||||
}];
|
}];
|
||||||
|
@ -13,4 +13,4 @@ SPEC CHECKSUMS:
|
|||||||
|
|
||||||
PODFILE CHECKSUM: 9c382a6853b1ccb79b91a8268f272eb3ffaff4be
|
PODFILE CHECKSUM: 9c382a6853b1ccb79b91a8268f272eb3ffaff4be
|
||||||
|
|
||||||
COCOAPODS: 1.1.1
|
COCOAPODS: 1.3.1
|
||||||
|
@ -314,13 +314,16 @@
|
|||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
);
|
);
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-TouchVisualizer-checkManifestLockResult.txt",
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
@ -8,9 +8,7 @@
|
|||||||
|
|
||||||
#import "COSAppDelegate.h"
|
#import "COSAppDelegate.h"
|
||||||
#import <COSTouchVisualizerWindow.h>
|
#import <COSTouchVisualizerWindow.h>
|
||||||
|
#import <COSTouchConfig.h>
|
||||||
@interface COSAppDelegate () <COSTouchVisualizerWindowDelegate>
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation COSAppDelegate
|
@implementation COSAppDelegate
|
||||||
|
|
||||||
@ -22,25 +20,29 @@
|
|||||||
- (COSTouchVisualizerWindow *)window {
|
- (COSTouchVisualizerWindow *)window {
|
||||||
static COSTouchVisualizerWindow *customWindow = nil;
|
static COSTouchVisualizerWindow *customWindow = nil;
|
||||||
if (!customWindow) {
|
if (!customWindow) {
|
||||||
customWindow = [[COSTouchVisualizerWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
COSTouchConfig *contactConfig = ({
|
||||||
|
COSTouchConfig *config = [[COSTouchConfig alloc] initWithTouchConfigType:COSTouchConfigTpyeContact];
|
||||||
|
config.fillColor = [UIColor purpleColor];
|
||||||
|
config.strokeColor = [UIColor blueColor];
|
||||||
|
config.alpha = 0.4;
|
||||||
|
config;
|
||||||
|
});
|
||||||
|
|
||||||
[customWindow setFillColor:[UIColor purpleColor]];
|
COSTouchConfig *riippleConfig = ({
|
||||||
[customWindow setStrokeColor:[UIColor blueColor]];
|
COSTouchConfig *config = [[COSTouchConfig alloc] initWithTouchConfigType:COSTouchConfigTpyeRipple];
|
||||||
[customWindow setTouchAlpha:0.4];
|
config.fillColor = [UIColor purpleColor];
|
||||||
|
config.strokeColor = [UIColor blueColor];
|
||||||
[customWindow setRippleFillColor:[UIColor purpleColor]];
|
config.alpha = 0.1;
|
||||||
[customWindow setRippleStrokeColor:[UIColor blueColor]];
|
config;
|
||||||
[customWindow setRippleAlpha:0.1];
|
});
|
||||||
|
|
||||||
[customWindow setTouchVisualizerWindowDelegate:self];
|
customWindow = [[COSTouchVisualizerWindow alloc] initWithFrame:[UIScreen mainScreen].bounds
|
||||||
|
morphEnabled:YES
|
||||||
|
touchVisibility:COSTouchVisualizerWindowTouchVisibilityRemoteAndLocal
|
||||||
|
contactConfig:contactConfig
|
||||||
|
rippleConfig:riippleConfig];
|
||||||
}
|
}
|
||||||
return customWindow;
|
return customWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - COSTouchVisualizerWindowDelegate
|
|
||||||
|
|
||||||
- (BOOL)touchVisualizerWindowShouldAlwaysShowFingertip:(COSTouchVisualizerWindow *)window {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
Loading…
Reference in New Issue
Block a user