| // 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:@"<"]; |
| result = [result stringByReplacingOccurrencesOfString:@">" withString:@">"]; |
| 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 |
| |