blob: ecac33fb4e19ccd88ca65ee9f8a8c2cf66a3633e [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;
}
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)str
{
if ([str isEqualToString:@"\n"]) {
[self enterPressed];
return NO;
}
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 = @"";
}
}
- (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 enterPressed];
}
- (void)unloadDemo
{
[self.okButton setHidden:TRUE];
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