diff options
Diffstat (limited to 'src/ui/ios/gf-ios-swift/ViewController.swift')
| -rw-r--r-- | src/ui/ios/gf-ios-swift/ViewController.swift | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/src/ui/ios/gf-ios-swift/ViewController.swift b/src/ui/ios/gf-ios-swift/ViewController.swift new file mode 100644 index 000000000..5766b340d --- /dev/null +++ b/src/ui/ios/gf-ios-swift/ViewController.swift @@ -0,0 +1,223 @@ +import UIKit +import AVFoundation + +class ViewController: UIViewController { + + // Set sizes used within the controller + let maxBoxWidth: CGFloat = 150 + let boxOffset: CGFloat = 10 + var scrollViewHeight: CGFloat = 0 + var scrollViewWidth: CGFloat = 0 + + // Translation properties + let translator = Translator() + let colors = Colors() + let synthesizer = AVSpeechSynthesizer() + let languages = allLanguages + var inLanguage: Language! + var outLanguage: Language! + + // Initiate picker views + let inPicker: UIPickerView = UIPickerView() + let outPicker: UIPickerView = UIPickerView() + + // UI connections + @IBOutlet weak var translationsView: UIScrollView! + @IBOutlet weak var inLanguageField: UITextField! + @IBOutlet weak var outLanguageField: UITextField! + + // Reverses to and from languages + @IBAction func switchLanguages(sender: UIButton) { + self.inLanguageField.text = self.outLanguage.name + self.outLanguageField.text = self.inLanguage.name + let tmpLanguage = self.inLanguage + self.inLanguage = self.outLanguage + self.outLanguage = tmpLanguage + self.translator.switchLanguages("from", to: "to") // to also switch concrete grammars + } + + // Creates a new translation field when the user clicks the keyboard icon + @IBAction func openKeyboard(sender: UIButton) { + let field = createFromView() + field.becomeFirstResponder() + } + + // Starts the speech recognition process when the user clicks the microphone icon + @IBAction func openMicrophone(sender: UIButton) { + self.createToView("microphone support is on its way") + } + + // Sums the heights of all translation boxes + margins + func calculateTranslationHeights() -> CGFloat { + var height = CGFloat(-29.5) // compensate for invisible scrollbars + for view in self.translationsView.subviews { + height += view.frame.height + self.boxOffset + } + height += self.boxOffset + return height + } + + // Creates a new "to translate" view and returns it for placement + func createFromView() -> UITextView { + let view = UITextView(frame: CGRect( + x: self.boxOffset, + y: self.calculateTranslationHeights(), + width: 20, + height: 30 + )) + view.backgroundColor = self.colors.backgroundColors["source"] + view.layer.cornerRadius = 5 + view.returnKeyType = UIReturnKeyType.Done + + view.delegate = self + self.translationsView.addSubview(view) + self.resizeTranslationsView() + return view + } + + // A UIScrollView doesn't know its own height; use this method to resize it + func resizeTranslationsView() -> Void { + var subviewHeights = self.calculateTranslationHeights() + if (subviewHeights > self.scrollViewHeight) { + self.translationsView.contentSize = CGSizeMake( + self.translationsView.frame.width, subviewHeights) + + // Also scroll to bottom + let offset = self.translationsView.contentSize.height - self.translationsView.bounds.size.height + let point = CGPointMake(0, offset) + self.translationsView.setContentOffset(point, animated: true) + + } + } + + // Creates and places a new "translated" view given the translated text + func createToView(translation: String) -> Void { + let view = UITextView(frame: CGRect( + x: 0, // we set the real value later a few lines down below + y: self.calculateTranslationHeights(), + width: self.maxBoxWidth, + height: 30 + )) + view.backgroundColor = self.colors.translationToUIColor(translation) + view.text = self.translator.formatTranslation(translation) + view.layer.cornerRadius = 5 + view.sizeToFit() + + // The view has been set, so we can now move it further to the right + view.frame.origin.x = self.scrollViewWidth - 10 - view.frame.width + self.translationsView.addSubview(view) + self.resizeTranslationsView() + } + + // Perform translation + func translate(phrase: String) -> Void { + var translation = self.translator.translate(phrase) + self.createToView(translation) + + // Run TTS except in simulator (because the simulator doesn't support it) + #if !arch(i386) && !arch(x86_64) + var utterance = AVSpeechUtterance(string: translation) + utterance.voice = AVSpeechSynthesisVoice(language: self.outLanguage.bcp) + self.synthesizer.speakUtterance(utterance) + #endif + + } + + override func viewDidLoad() { + super.viewDidLoad() + + // Set size variables (-162 for the height to compensate for the views above the scrollview) + self.scrollViewHeight = UIScreen.mainScreen().bounds.height - 162 + self.scrollViewWidth = UIScreen.mainScreen().bounds.width + + // Load view pickers + self.inPicker.delegate = self + self.inPicker.dataSource = self + + self.outPicker.delegate = self + self.outPicker.dataSource = self + + self.inLanguageField.inputView = inPicker + self.outLanguageField.inputView = outPicker + + // Load initial languages + self.inLanguage = self.languages[3] // English + self.outLanguage = self.languages[10] // Swedish + self.translator.loadGrammar("Eng", destination: "from") + self.translator.loadGrammar("Swe", destination: "to") + + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + } + +} + +// On selection functionality for the view pickers +extension ViewController: UIPickerViewDelegate { + + // Makes the picker views return a language rather than text + func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String + { + return self.languages[row].name + } + + // Row was selected: update buttons, load new grammar + func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + var language = self.languages[row] + + var fromTo: String + var textField = UITextField() + if (pickerView == self.inPicker) { + self.inLanguage = language + fromTo = "from" + textField = self.inLanguageField + } else { + self.outLanguage = language + fromTo = "to" + textField = self.outLanguageField + } + + self.translator.loadGrammar(language.abbreviation, destination: fromTo) + textField.text = language.name + textField.resignFirstResponder() + } + +} + +// View picker layout functionality +extension ViewController: UIPickerViewDataSource { + + func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { + return 1 + } + + func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + return self.languages.count + } + +} + +// Keyboard input functionality +extension ViewController: UITextViewDelegate { + + // Method is called on keypress + func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { + + // UITextViews lack a method to close keyboard on enter, so we use this slight hack + if (text == "\n") { + textView.resignFirstResponder() + self.translate(textView.text) + return false + } + + // But if it wasn't the enter key, we resize the UITextView dynamically + textView.sizeToFit() + if (textView.frame.size.width < self.maxBoxWidth) { + textView.frame.size.width += 10 + } + return true + } + +}
\ No newline at end of file |
