blob: e86f9a7f7d7e22b9cd36d91309981437389a4a16 [file] [log] [blame]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#import "IvyController.h"
#import "mobile/Mobile.h"
@interface IvyController ()
@end
@implementation IvyController {
NSArray *demo_lines;
int demo_index;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.input.delegate = self;
self.input.autocorrectionType = UITextAutocorrectionTypeNo;
self.input.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
self.suggestionView = [[Suggestion alloc] init];
self.suggestionView.delegate = self;
self.tape.UIDelegate = self;
self->demo_lines = NULL;
[self.okButton setTitle:@"" forState:UIControlStateNormal];
[self.okButton setHidden:TRUE];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textDidChange:)
name:UITextFieldTextDidChangeNotification
object:self.input];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
[self.input becomeFirstResponder];
[self clear:NULL];
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if ([textField isEqual:self.input]) {
textField.inputAccessoryView = self.suggestionView;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
[textField reloadInputViews];
}
return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
if ([textField isEqual:self.input]) {
textField.inputAccessoryView = nil;
[textField reloadInputViews];
}
return YES;
}
- (void)textDidChange:(NSNotification *)notif {
[self.suggestionView suggestFor:self.input.text];
}
- (void)suggestionReplace:(NSString *)text {
self.input.text = text;
[self.suggestionView suggestFor:text];
}
- (void)keyboardWillShow:(NSNotification *)aNotification {
// Move the input text field up, as the keyboard has taken some of the screen.
NSDictionary *info = [aNotification userInfo];
CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSNumber *duration = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
UIViewAnimationCurve keyboardTransitionAnimationCurve;
[[info valueForKey:UIKeyboardAnimationCurveUserInfoKey]
getValue:&keyboardTransitionAnimationCurve];
UIViewAnimationOptions options =
keyboardTransitionAnimationCurve | keyboardTransitionAnimationCurve << 16;
[UIView animateWithDuration:duration.floatValue
delay:0
options:options
animations:^{
self.bottomConstraint.constant = 0 - kbFrame.size.height;
[self.view layoutIfNeeded];
}
completion:^(BOOL finished) {
[self scrollTapeToBottom];
}];
}
- (void)keyboardWillHide:(NSNotification *)aNotification {
// Move the input text field back down.
NSDictionary *info = [aNotification userInfo];
NSNumber *duration = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
UIViewAnimationCurve keyboardTransitionAnimationCurve;
[[info valueForKey:UIKeyboardAnimationCurveUserInfoKey]
getValue:&keyboardTransitionAnimationCurve];
UIViewAnimationOptions options =
keyboardTransitionAnimationCurve | keyboardTransitionAnimationCurve << 16;
int offset = self.input.inputAccessoryView != NULL ? self.suggestionView.frame.size.height : 0;
[UIView animateWithDuration:duration.floatValue
delay:0
options:options
animations:^{
self.bottomConstraint.constant = 0 - offset;
[self.view layoutIfNeeded];
}
completion:^(BOOL finished) {
[self scrollTapeToBottom];
}];
}
- (void)enterPressed {
NSString *text = self.input.text;
if ([text isEqual:@""]) {
if (self->demo_lines == NULL) {
return;
}
while (demo_index < self->demo_lines.count) {
NSString *line = self->demo_lines[self->demo_index++];
if ([line hasPrefix:@"#"]) {
[self appendTape:line tag:@"comment"];
} else {
self.input.text = line;
break;
}
}
} else if (self->demo_lines != NULL && [text isEqual:@"quit"]) {
[self unloadDemo];
} else {
[self appendTape:text tag:@"expr"];
NSString *expr = [text stringByAppendingString:@"\n"];
NSError *err;
NSString *result = MobileEval(expr, &err);
if (err != nil) {
result = err.description;
}
result = [result stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
result = [result stringByReplacingOccurrencesOfString:@"<" withString:@"&lt;"];
result = [result stringByReplacingOccurrencesOfString:@">" withString:@"&gt;"];
NSMutableArray *lines = (NSMutableArray *)[result componentsSeparatedByString:@"\n"];
for (NSMutableString *line in lines) {
if ([line hasPrefix:@"#"])
[self appendTape:line tag:@"comment"];
else
[self appendTape:line tag:@"result"];
}
self.input.text = @"";
}
[self.input becomeFirstResponder];
}
- (void)scrollTapeToBottom {
NSString *scroll = @"window.scrollBy(0, document.body.offsetHeight);";
[self.tape evaluateJavaScript:scroll completionHandler:nil];
}
- (void)appendTape:(NSString *)text tag:(NSString *)tag {
NSString *injectSrc = @"appendDiv('%@','%@');";
NSString *runToInject = [NSString stringWithFormat:injectSrc, text, tag];
[self.tape evaluateJavaScript:runToInject completionHandler:nil];
[self scrollTapeToBottom];
}
- (void)loadDemo {
[self.okButton setHidden:FALSE];
NSString *text = DemoText();
self->demo_lines =
[text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
self->demo_index = 0;
self.input.text = @"";
self.input.enablesReturnKeyAutomatically = TRUE;
[self enterPressed];
}
- (void)unloadDemo {
[self.okButton setHidden:TRUE];
self.input.enablesReturnKeyAutomatically = FALSE;
self->demo_lines = NULL;
self.input.text = @"";
}
- (IBAction)okPressed:(id)sender {
[self enterPressed];
}
- (IBAction)demo:(id)sender {
if (self->demo_lines) { // demo already running
[self enterPressed];
} else {
[self loadDemo];
}
}
- (IBAction)clear:(id)sender {
[self unloadDemo];
NSString *string = [NSString
stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"tape" ofType:@"html"]
encoding:NSUTF8StringEncoding
error:NULL];
[self.tape loadHTMLString:string baseURL:NULL];
}
@end