ViewController.swift 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. //
  2. // ViewController.swift
  3. // MacTerminal
  4. //
  5. // Created by Miguel de Icaza on 3/11/20.
  6. // Copyright © 2020 Miguel de Icaza. All rights reserved.
  7. //
  8. import Cocoa
  9. import SwiftTerm
  10. class ViewController: NSViewController, LocalProcessTerminalViewDelegate, NSUserInterfaceValidations {
  11. @IBOutlet var loggingMenuItem: NSMenuItem?
  12. var changingSize = false
  13. var logging: Bool = false
  14. var zoomGesture: NSMagnificationGestureRecognizer?
  15. func sizeChanged(source: LocalProcessTerminalView, newCols: Int, newRows: Int) {
  16. if changingSize {
  17. return
  18. }
  19. changingSize = true
  20. //var border = view.window!.frame - view.frame
  21. var newFrame = terminal.getOptimalFrameSize ()
  22. let windowFrame = view.window!.frame
  23. newFrame = CGRect (x: windowFrame.minX, y: windowFrame.minY, width: newFrame.width, height: windowFrame.height - view.frame.height + newFrame.height)
  24. view.window?.setFrame(newFrame, display: true, animate: true)
  25. changingSize = false
  26. }
  27. func setTerminalTitle(source: LocalProcessTerminalView, title: String) {
  28. view.window?.title = title
  29. }
  30. func processTerminated(source: TerminalView, exitCode: Int32?) {
  31. view.window?.close()
  32. if let e = exitCode {
  33. print ("Process terminated with code: \(e)")
  34. } else {
  35. print ("Process vanished")
  36. }
  37. }
  38. var terminal: LocalProcessTerminalView!
  39. static var lastTerminal: LocalProcessTerminalView!
  40. func updateLogging ()
  41. {
  42. let path = logging ? "/Users/miguel/Downloads/Logs" : nil
  43. terminal.setHostLogging (directory: path)
  44. NSUserDefaultsController.shared.defaults.set (logging, forKey: "LogHostOutput")
  45. }
  46. override func viewDidLoad() {
  47. super.viewDidLoad()
  48. terminal = LocalProcessTerminalView(frame: view.frame)
  49. zoomGesture = NSMagnificationGestureRecognizer(target: self, action: #selector(zoomGestureHandler))
  50. terminal.addGestureRecognizer(zoomGesture!)
  51. ViewController.lastTerminal = terminal
  52. terminal.processDelegate = self
  53. terminal.feed(text: "Welcome to SwiftTerm")
  54. terminal.startProcess ()
  55. view.addSubview(terminal)
  56. logging = NSUserDefaultsController.shared.defaults.bool(forKey: "LogHostOutput")
  57. updateLogging ()
  58. }
  59. @objc
  60. func zoomGestureHandler (_ sender: NSMagnificationGestureRecognizer) {
  61. if sender.magnification > 0 {
  62. biggerFont (sender)
  63. } else {
  64. smallerFont(sender)
  65. }
  66. }
  67. override func viewDidLayout() {
  68. super.viewDidLayout()
  69. changingSize = true
  70. terminal.frame = view.frame
  71. changingSize = false
  72. terminal.needsLayout = true
  73. }
  74. @objc @IBAction
  75. func set80x25 (_ source: AnyObject)
  76. {
  77. terminal.resize(cols: 80, rows: 25)
  78. }
  79. var lowerCol = 80
  80. var lowerRow = 25
  81. var higherCol = 160
  82. var higherRow = 60
  83. func queueNextSize ()
  84. {
  85. // If they requested a stop
  86. if resizificating == 0 {
  87. return
  88. }
  89. var next = terminal.getTerminal().getDims ()
  90. if resizificating > 0 {
  91. if next.cols < higherCol {
  92. next.cols += 1
  93. }
  94. if next.rows < higherRow {
  95. next.rows += 1
  96. }
  97. } else {
  98. if next.cols > lowerCol {
  99. next.cols -= 1
  100. }
  101. if next.rows > lowerRow {
  102. next.rows -= 1
  103. }
  104. }
  105. terminal.resize (cols: next.cols, rows: next.rows)
  106. var direction = resizificating
  107. if next.rows == higherRow && next.cols == higherCol {
  108. direction = -1
  109. }
  110. if next.rows == lowerRow && next.cols == lowerCol {
  111. direction = 1
  112. }
  113. DispatchQueue.main.asyncAfter(deadline: .now() + 0.03) {
  114. self.resizificating = direction
  115. self.queueNextSize()
  116. }
  117. }
  118. var resizificating = 0
  119. @objc @IBAction
  120. func resizificator (_ source: AnyObject)
  121. {
  122. if resizificating != 1 {
  123. resizificating = 1
  124. queueNextSize ()
  125. } else {
  126. resizificating = 0
  127. }
  128. }
  129. @objc @IBAction
  130. func resizificatorDown (_ source: AnyObject)
  131. {
  132. if resizificating != -1 {
  133. resizificating = -1
  134. queueNextSize ()
  135. } else {
  136. resizificating = 0
  137. }
  138. }
  139. @objc @IBAction
  140. func allowMouseReporting (_ source: AnyObject)
  141. {
  142. terminal.allowMouseReporting.toggle ()
  143. }
  144. @objc @IBAction
  145. func softReset (_ source: AnyObject)
  146. {
  147. terminal.getTerminal().softReset ()
  148. terminal.setNeedsDisplay(terminal.frame)
  149. }
  150. @objc @IBAction
  151. func hardReset (_ source: AnyObject)
  152. {
  153. terminal.getTerminal().resetToInitialState ()
  154. terminal.setNeedsDisplay(terminal.frame)
  155. }
  156. @objc @IBAction
  157. func toggleOptionAsMetaKey (_ source: AnyObject)
  158. {
  159. terminal.optionAsMetaKey.toggle ()
  160. }
  161. @objc @IBAction
  162. func biggerFont (_ source: AnyObject)
  163. {
  164. let size = terminal.font.pointSize
  165. guard size < 72 else {
  166. return
  167. }
  168. terminal.font = NSFont.monospacedSystemFont(ofSize: size+1, weight: .regular)
  169. }
  170. @objc @IBAction
  171. func smallerFont (_ source: AnyObject)
  172. {
  173. let size = terminal.font.pointSize
  174. guard size > 5 else {
  175. return
  176. }
  177. terminal.font = NSFont.monospacedSystemFont(ofSize: size-1, weight: .regular)
  178. }
  179. @objc @IBAction
  180. func defaultFontSize (_ source: AnyObject)
  181. {
  182. terminal.font = NSFont.monospacedSystemFont(ofSize: NSFont.systemFontSize, weight: .regular)
  183. }
  184. @objc @IBAction
  185. func addTab (_ source: AnyObject)
  186. {
  187. // if let win = view.window {
  188. // win.tabbingMode = .preferred
  189. // if let wc = win.windowController {
  190. // if let d = wc.document as? Document {
  191. // do {
  192. // let x = Document()
  193. // x.makeWindowControllers()
  194. //
  195. // try NSDocumentController.shared.newDocument(self)
  196. // } catch {}
  197. // print ("\(d.debugDescription)")
  198. // }
  199. // }
  200. // }
  201. // win.tabbingMode = .preferred
  202. // win.addTabbedWindow(win, ordered: .above)
  203. //
  204. // if let wc = win.windowController {
  205. // wc.newWindowForTab(self()
  206. // wc.showWindow(source)
  207. // }
  208. // }
  209. }
  210. func validateUserInterfaceItem(_ item: NSValidatedUserInterfaceItem) -> Bool
  211. {
  212. if item.action == #selector(debugToggleHostLogging(_:)) {
  213. if let m = item as? NSMenuItem {
  214. m.state = logging ? NSControl.StateValue.on : NSControl.StateValue.off
  215. }
  216. }
  217. if item.action == #selector(resizificator(_:)) {
  218. if let m = item as? NSMenuItem {
  219. m.state = resizificating == 1 ? NSControl.StateValue.on : NSControl.StateValue.off
  220. }
  221. }
  222. if item.action == #selector(resizificatorDown(_:)) {
  223. if let m = item as? NSMenuItem {
  224. m.state = resizificating == -1 ? NSControl.StateValue.on : NSControl.StateValue.off
  225. }
  226. }
  227. if item.action == #selector(allowMouseReporting(_:)) {
  228. if let m = item as? NSMenuItem {
  229. m.state = terminal.allowMouseReporting ? NSControl.StateValue.on : NSControl.StateValue.off
  230. }
  231. }
  232. if item.action == #selector(toggleOptionAsMetaKey(_:)) {
  233. if let m = item as? NSMenuItem {
  234. m.state = terminal.optionAsMetaKey ? NSControl.StateValue.on : NSControl.StateValue.off
  235. }
  236. }
  237. return true
  238. }
  239. @objc @IBAction
  240. func debugToggleHostLogging (_ source: AnyObject)
  241. {
  242. logging = !logging
  243. updateLogging()
  244. }
  245. }