forked from rpetrich/fonemonkey4
-
Notifications
You must be signed in to change notification settings - Fork 0
/
UITextView+FMReady.m
193 lines (165 loc) · 7.42 KB
/
UITextView+FMReady.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/* This file is part of FoneMonkey.
FoneMonkey is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FoneMonkey is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FoneMonkey. If not, see <http://www.gnu.org/licenses/>. */
//
// UITextView+FMReady.m
// FoneMonkey
//
// Created by Stuart Stern on 11/1/09.
// Copyright 2009 Gorilla Logic, Inc.. All rights reserved.
//
#import "UITextView+FMReady.h"
#import "FMUtils.h"
#import <objc/runtime.h>
#import "FoneMonkey.h"
#import "FMCommandEvent.h"
#import "UIView+FMReady.h"
#import "NSObject+FMReady.h"
@interface UITextView (FM_INTERCEPTOR)
// Stop the compiler from whining
- (BOOL)orig_textViewShouldEndEditing:(UITextView *)textView;
- (BOOL) orig_textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string;
- (void) orig_setDelegate:(NSObject <UITextViewDelegate>*) del;
@end
@interface FMDefaultTextViewDelegate : NSObject <UITextViewDelegate>
@end
@implementation FMDefaultTextViewDelegate
@end
@implementation UITextView (FMReady)
+ (void)load {
// if (self == [UITextView class]) {
//[self fmSwapImplementation:@selector(setDelegate:)];
[UIScrollView interceptMethod:@selector(setDelegate:) withClass:[UITextView class] types:"v@:@"];
// }
}
- (void) fmAssureAutomationInit {
[super fmAssureAutomationInit];
if (!self.delegate) {
self.delegate = [[[FMDefaultTextViewDelegate alloc] init] autorelease];
}
}
- (void) fm_setDelegate:(NSObject <UITextViewDelegate>*) del {
if ([self class] == [UITextView class]) {
// [del interceptMethod:@selector(textViewDidChangeSelection:) withClass:[self class] types:"v@:@"];
[del interceptMethod:@selector(textViewShouldEndEditing:) withClass:[self class] types:"c@:@"];
[del interceptMethod:@selector(textViewShouldBeginEditing:) withClass:[self class] types:"c@:@"];
// [del interceptMethod:@selector(textViewDidEndEditing:) withClass:[self class] types:"v@:@"];
[del interceptMethod:@selector(textView:shouldChangeTextInRange:replacementText:) withClass:[self class] types:"c@:@@@"];
// [del interceptMethod:@selector(textViewDidChange:) withClass:[self class] types:"v@:@"];
}
[self orig_setDelegate:del];
}
- (BOOL)fm_textViewShouldEndEditing:(UITextView *)textView {
if ([FoneMonkey isRecording]) {
FMCommandEvent* lastEvent = [[FoneMonkey sharedMonkey] lastCommand];
if (![lastEvent.command isEqualToString:FMCommandInputText]) {
[[FoneMonkey sharedMonkey] recordFrom:textView command:FMCommandInputText
args:[NSArray arrayWithObjects: textView.text, nil]
post:NO];
NSInteger index = [[FoneMonkey sharedMonkey].commands count] - 1;
FMCommandEvent* prevCommand = [[FoneMonkey sharedMonkey] commandAt:index - 2];
if ([prevCommand.command isEqualToString:FMCommandInputText] && [prevCommand.monkeyID isEqualToString:textView.monkeyID]) {
[[FoneMonkey sharedMonkey] deleteCommand:index -2 ];
index--;
}
[[FoneMonkey sharedMonkey] moveCommand:index to:index - 1];
} else {
if ([lastEvent.command isEqualToString:FMCommandInputText] && [lastEvent.monkeyID isEqualToString:[textView monkeyID]]) {
[[FoneMonkey sharedMonkey] popCommand];
}
[ [FoneMonkey sharedMonkey] recordFrom:textView command:FMCommandInputText
args:[NSArray arrayWithObjects: textView.text, nil]
post:NO];
}
}
if (class_getInstanceMethod([self class], @selector(orig_textViewShouldEndEditing:))) {
return ([self orig_textViewShouldEndEditing:textView]);
} else {
return YES;
}
}
- (BOOL) fm_textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string {
if ([FoneMonkey isRecording]) {
FMCommandEvent* lastEvent = [[FoneMonkey sharedMonkey] lastCommand];
if ([lastEvent.command isEqualToString:FMCommandInputText] && [lastEvent.monkeyID isEqualToString:[textView monkeyID]]) {
[[FoneMonkey sharedMonkey] popCommand];
}
NSString* newVal = [textView.text stringByReplacingCharactersInRange:range withString:string];
[ [FoneMonkey sharedMonkey] recordFrom:textView command:FMCommandInputText
args:[NSArray arrayWithObjects: newVal, nil]
post:NO];
}
if (class_getInstanceMethod([self class], @selector(orig_textView:shouldChangeTextInRange:replacementText:))) {
return [self orig_textView:textView shouldChangeTextInRange:range replacementText:string];
} else {
return YES;
}
}
//- (void) handleMonkeyTouchEvent:(NSSet*)touches withEvent:(UIEvent*)event {
// // [FoneMonkey suspend];
// //[super handleMonkeyTouchEvent:touches withEvent:event];
//// [[NSNotificationCenter defaultCenter] addObserver:self
//// selector:@selector(keyBoardDismissed:)
//// name:UIKeyboardWillHideNotification object:nil];
// [[FoneMonkey sharedMonkey] postCommandFrom:self command:FMCommandTouch args:nil];
// [[NSNotificationCenter defaultCenter] addObserver:self
// selector:@selector(keyBoardDismissed:)
// name:UITextViewTextDidEndEditingNotification object:nil];
//}
//- (void) keyBoardDismissed:(NSNotification*) notification {
//// [[NSNotificationCenter defaultCenter] removeObserver:self
//// name:UIKeyboardWillHideNotification object:nil];
// [[NSNotificationCenter defaultCenter] removeObserver:self
// name:UITextViewTextDidEndEditingNotification object:nil];
// [[FoneMonkey sharedMonkey] postCommandFrom:self command:FMCommandInputText args:[NSArray arrayWithObject:self.text]];
//}
//
//- (BOOL) shouldRecordMonkeyTouch:(UITouch*)touch {
// return (touch.phase == UITouchPhaseBegan);
//}
- (void) playbackMonkeyEvent:(FMCommandEvent*)event {
if ([event.command isEqualToString:FMCommandInputText]) {
NSString* newText = [event.args count] < 1 ? @"" : [event.args objectAtIndex:0];
NSRange range;
range.location = 0;
range.length = [self.text length];
//BOOL noInput = range.length == 0 && [newText length] == 0;
if ([self.delegate textView:self shouldChangeTextInRange:range replacementText:newText]) {
self.text = newText;
}
return;
}
if ([event.command isEqualToString:FMCommandTouch]) {
[self becomeFirstResponder];
return;
}
[super playbackMonkeyEvent:event];
// [self performSelectorOnMainThread:@selector(becomeFirstResponder) withObject:nil waitUntilDone:nil];
// if (event.args) {
// self.text = [[event args] objectAtIndex:0];
// }
}
+ (NSString*) uiAutomationCommand:(FMCommandEvent*)command {
NSMutableString* string = [[NSMutableString alloc] init];
if ([command.command isEqualToString:FMCommandInputText]) {
NSString* textValue = [command.args count] < 1 ? @"" : [command.args objectAtIndex:0];
[string appendFormat:@"FoneMonkey.elementNamed(\"%@\").setValue(\"%@\"); // UIATextView",
[FMUtils stringByJsEscapingQuotesAndNewlines:command.monkeyID],
[FMUtils stringByJsEscapingQuotesAndNewlines:textValue]];
} else {
[string appendString:[super uiAutomationCommand:command]];
}
return string;
}
- (BOOL) shouldRecordMonkeyTouch:(UITouch*)touch {
return (touch.phase == UITouchPhaseEnded);
}
@end