1
0

Helios-Workspace.st 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. Smalltalk current createPackage: 'Helios-Workspace'!
  2. Object subclass: #HLCodeModel
  3. instanceVariableNames: 'announcer environment receiver'
  4. package: 'Helios-Workspace'!
  5. !HLCodeModel methodsFor: 'accessing'!
  6. announcer
  7. ^ announcer ifNil: [ announcer := Announcer new ]
  8. !
  9. environment
  10. ^ environment ifNil: [ HLManager current environment ]
  11. !
  12. environment: anEnvironment
  13. environment := anEnvironment
  14. !
  15. receiver
  16. ^ receiver ifNil: [ receiver := self defaultReceiver ]
  17. !
  18. receiver: anObject
  19. receiver := anObject
  20. ! !
  21. !HLCodeModel methodsFor: 'actions'!
  22. doIt: someCode
  23. ^ self environment eval: someCode on: self receiver
  24. !
  25. subscribe: aWidget
  26. aWidget subscribeTo: self announcer
  27. ! !
  28. !HLCodeModel methodsFor: 'defaults'!
  29. defaultReceiver
  30. ^ DoIt new
  31. ! !
  32. !HLCodeModel class methodsFor: 'actions'!
  33. on: anEnvironment
  34. ^ self new
  35. environment: anEnvironment;
  36. yourself
  37. ! !
  38. HLWidget subclass: #HLCodeWidget
  39. instanceVariableNames: 'model wrapper code editor'
  40. package: 'Helios-Workspace'!
  41. !HLCodeWidget methodsFor: 'accessing'!
  42. announcer
  43. ^ self model announcer
  44. !
  45. contents
  46. ^ editor getValue
  47. !
  48. contents: aString
  49. editor setValue: aString
  50. !
  51. currentLine
  52. ^editor getLine: (editor getCursor line)
  53. !
  54. currentLineOrSelection
  55. ^editor somethingSelected
  56. ifFalse: [ self currentLine ]
  57. ifTrue: [ self selection ]
  58. !
  59. model
  60. ^ model ifNil: [
  61. self model: HLCodeModel new.
  62. model ]
  63. !
  64. model: aModel
  65. model := aModel
  66. !
  67. receiver
  68. ^ self model receiver
  69. !
  70. receiver: anObject
  71. self model receiver: anObject
  72. !
  73. selection
  74. ^editor getSelection
  75. !
  76. selectionEnd
  77. ^code element selectionEnd
  78. !
  79. selectionEnd: anInteger
  80. code element selectionEnd: anInteger
  81. !
  82. selectionStart
  83. ^code element selectionStart
  84. !
  85. selectionStart: anInteger
  86. code element selectionStart: anInteger
  87. ! !
  88. !HLCodeWidget methodsFor: 'actions'!
  89. clear
  90. self contents: ''
  91. !
  92. configureEditor
  93. self editor at: 'amberCodeWidget' put: self
  94. !
  95. doIt
  96. | result |
  97. self announcer announce: (HLDoItRequested on: model).
  98. result:= model doIt: self currentLineOrSelection.
  99. self announcer announce: (HLDoItExecuted on: model).
  100. ^ result
  101. !
  102. editor
  103. ^editor
  104. !
  105. focus
  106. editor focus
  107. !
  108. inspectIt
  109. | newInspector |
  110. self announcer announce: (HLInspectItRequested on: model).
  111. newInspector := self makeInspectorOn: self doIt.
  112. newInspector open
  113. !
  114. makeInspectorOn: anObject
  115. ^ HLInspector new
  116. inspect: anObject;
  117. yourself
  118. !
  119. print: aString
  120. | start stop currentLine |
  121. currentLine := (editor getCursor: false) line.
  122. start := HashedCollection new.
  123. start at: 'line' put: currentLine.
  124. start at: 'ch' put: (editor getCursor: false) ch.
  125. (editor getSelection) ifEmpty: [
  126. "select current line if selection is empty"
  127. start at: 'ch' put: (editor getLine: currentLine) size.
  128. editor setSelection: #{'line' -> currentLine. 'ch' -> 0} end: start.
  129. ].
  130. stop := HashedCollection new.
  131. stop at: 'line' put: currentLine.
  132. stop at: 'ch' put: ((start at: 'ch') + aString size + 2).
  133. editor replaceSelection: (editor getSelection, ' ', aString, ' ').
  134. editor setCursor: (editor getCursor: true).
  135. editor setSelection: stop end: start
  136. !
  137. printIt
  138. | result |
  139. result:= self doIt.
  140. self announcer announce: (HLPrintItRequested on: model).
  141. self print: result printString.
  142. self focus.
  143. !
  144. saveIt
  145. "I do not do anything"
  146. !
  147. setEditorOn: aTextarea
  148. <self['@editor'] = CodeMirror.fromTextArea(aTextarea, {
  149. theme: 'amber',
  150. lineNumbers: true,
  151. enterMode: 'flat',
  152. indentWithTabs: true,
  153. indentUnit: 4,
  154. matchBrackets: true,
  155. electricChars: false,
  156. keyMap: 'Amber'
  157. })>
  158. ! !
  159. !HLCodeWidget methodsFor: 'reactions'!
  160. onDoIt
  161. self doIt
  162. !
  163. onInspectIt
  164. self inspectIt
  165. !
  166. onPrintIt
  167. self printIt
  168. !
  169. onSaveIt
  170. "I do not do anything"
  171. ! !
  172. !HLCodeWidget methodsFor: 'rendering'!
  173. renderContentOn: html
  174. code := html textarea.
  175. self setEditorOn: code element.
  176. self configureEditor
  177. ! !
  178. !HLCodeWidget class methodsFor: 'accessing'!
  179. keyMap
  180. ^ HLManager current keyBinder systemIsMac
  181. ifTrue: [ self macKeyMap ]
  182. ifFalse: [ self pcKeyMap ]
  183. !
  184. macKeyMap
  185. ^ #{
  186. 'Alt-Backspace' -> 'delWordBefore'.
  187. 'Alt-Delete' -> 'delWordAfter'.
  188. 'Alt-Left' -> 'goWordBoundaryLeft'.
  189. 'Alt-Right' -> 'goWordBoundaryRight'.
  190. 'Cmd-A' -> 'selectAll'.
  191. 'Cmd-Alt-F' -> 'replace'.
  192. 'Cmd-D' -> 'doIt'.
  193. 'Cmd-Down' -> 'goDocEnd'.
  194. 'Cmd-End' -> 'goDocEnd'.
  195. 'Cmd-F' -> 'find'.
  196. 'Cmd-G' -> 'findNext'.
  197. 'Cmd-I' -> 'inspectIt'.
  198. 'Cmd-Left' -> 'goLineStart'.
  199. 'Cmd-P' -> 'printIt'.
  200. 'Cmd-Right' -> 'goLineEnd'.
  201. 'Cmd-S' -> 'saveIt'.
  202. 'Cmd-Up' -> 'goDocStart'.
  203. 'Cmd-Y' -> 'redo'.
  204. 'Cmd-Z' -> 'undo'.
  205. 'Cmd-[' -> 'indentLess'.
  206. 'Cmd-]' -> 'indentMore'.
  207. 'Ctrl-Alt-Backspace' -> 'delWordAfter'.
  208. 'Shift-Cmd-Alt-F' -> 'replaceAll'.
  209. 'Shift-Cmd-G' -> 'findPrev'.
  210. 'Shift-Cmd-Z' -> 'redo'.
  211. 'fallthrough' -> { 'basic' }
  212. }
  213. !
  214. pcKeyMap
  215. ^ {
  216. 'Alt-Left' -> 'goLineStart'.
  217. 'Alt-Right' -> 'goLineEnd'.
  218. 'Alt-Up' -> 'goDocStart'.
  219. 'Ctrl-A' -> 'selectAll'.
  220. 'Ctrl-Backspace' -> 'delWordBefore'.
  221. 'Ctrl-D' -> 'doIt'.
  222. 'Ctrl-Delete' -> 'delWordAfter'.
  223. 'Ctrl-Down' -> 'goDocEnd'.
  224. 'Ctrl-End' -> 'goDocEnd'.
  225. 'Ctrl-F' -> 'find'.
  226. 'Ctrl-G' -> 'findNext'.
  227. 'Ctrl-I' -> 'inspectIt'.
  228. 'Ctrl-Home' -> 'goDocStart'.
  229. 'Ctrl-Left' -> 'goWordBoundaryLeft'.
  230. 'Ctrl-P' -> 'printIt'.
  231. 'Ctrl-Right' -> 'goWordBoundaryRight'.
  232. 'Ctrl-S' -> 'saveIt'.
  233. 'Ctrl-Y' -> 'redo'.
  234. 'Ctrl-Z' -> 'undo'.
  235. 'Ctrl-[' -> 'indentLess'.
  236. 'Ctrl-]' -> 'indentMore'.
  237. 'Shift-Ctrl-F' -> 'replace'.
  238. 'Shift-Ctrl-G' -> 'findPrev'.
  239. 'Shift-Ctrl-R' -> 'replaceAll'.
  240. 'Shift-Ctrl-Z' -> 'redo'.
  241. 'fallthrough' -> #('basic')
  242. }
  243. ! !
  244. !HLCodeWidget class methodsFor: 'initialization'!
  245. initialize
  246. super initialize.
  247. self
  248. setupCodeMirror;
  249. setupCommands;
  250. setupKeyMaps.
  251. !
  252. setupCodeMirror
  253. < CodeMirror.keyMap.default.fallthrough = ["basic"] >
  254. !
  255. setupCommands
  256. (CodeMirror basicAt: 'commands')
  257. at: 'doIt' put: [ :cm | cm amberCodeWidget doIt ];
  258. at: 'inspectIt' put: [ :cm | cm amberCodeWidget inspectIt ];
  259. at: 'printIt' put: [ :cm | cm amberCodeWidget printIt ];
  260. at: 'saveIt' put: [ :cm | cm amberCodeWidget saveIt ]
  261. !
  262. setupKeyMaps
  263. <CodeMirror.keyMap['Amber'] = self._keyMap()>
  264. ! !
  265. HLCodeWidget subclass: #HLSourceCodeWidget
  266. instanceVariableNames: ''
  267. package: 'Helios-Workspace'!
  268. !HLSourceCodeWidget methodsFor: 'reactions'!
  269. onKeyDown: anEvent
  270. (super onKeyDown: anEvent) ifFalse: [ ^ false ].
  271. anEvent ctrlKey ifTrue: [
  272. anEvent keyCode = 83 ifTrue: [
  273. self onSave.
  274. anEvent preventDefault.
  275. ^ false ] ]
  276. !
  277. onSave
  278. ! !
  279. HLWidget subclass: #HLWorkspace
  280. instanceVariableNames: 'model codeWidget'
  281. package: 'Helios-Workspace'!
  282. !HLWorkspace methodsFor: 'accessing'!
  283. codeWidget
  284. ^ codeWidget ifNil: [
  285. codeWidget := HLCodeWidget new
  286. model: self model code;
  287. yourself ]
  288. !
  289. model
  290. ^ model ifNil: [
  291. self model: HLWorkspaceModel new.
  292. model ]
  293. !
  294. model: aModel
  295. model := aModel.
  296. self codeWidget model: aModel code.
  297. self observeCodeWidget.
  298. ! !
  299. !HLWorkspace methodsFor: 'actions'!
  300. observeCodeWidget
  301. ! !
  302. !HLWorkspace methodsFor: 'reactions'!
  303. onDoIt
  304. !
  305. onInspectIt
  306. !
  307. onPrintIt
  308. ! !
  309. !HLWorkspace methodsFor: 'rendering'!
  310. renderContentOn: html
  311. html with: self codeWidget
  312. ! !
  313. !HLWorkspace class methodsFor: 'accessing'!
  314. tabLabel
  315. ^ 'Workspace'
  316. !
  317. tabPriority
  318. ^ 10
  319. ! !
  320. !HLWorkspace class methodsFor: 'testing'!
  321. canBeOpenAsTab
  322. ^ true
  323. ! !
  324. Object subclass: #HLWorkspaceModel
  325. instanceVariableNames: 'announcer environment code'
  326. package: 'Helios-Workspace'!
  327. !HLWorkspaceModel methodsFor: 'accessing'!
  328. announcer
  329. ^ announcer ifNil: [ announcer := Announcer new ]
  330. !
  331. code
  332. "Answers the code model working for this workspace model"
  333. ^ code ifNil:[ HLCodeModel on: self environment ]
  334. !
  335. environment
  336. ^ environment ifNil: [ HLManager current environment ]
  337. !
  338. environment: anEnvironment
  339. environment := anEnvironment
  340. ! !
  341. !HLWorkspaceModel methodsFor: 'reactions'!
  342. onKeyDown: anEvent
  343. <if(anEvent.ctrlKey) {
  344. if(anEvent.keyCode === 80) { //ctrl+p
  345. self._printIt();
  346. anEvent.preventDefault();
  347. return false;
  348. }
  349. if(anEvent.keyCode === 68) { //ctrl+d
  350. self._doIt();
  351. anEvent.preventDefault();
  352. return false;
  353. }
  354. if(anEvent.keyCode === 73) { //ctrl+i
  355. self._inspectIt();
  356. anEvent.preventDefault();
  357. return false;
  358. }
  359. }>
  360. ! !
  361. !HLWorkspaceModel class methodsFor: 'actions'!
  362. on: anEnvironment
  363. ^ self new
  364. environment: anEnvironment;
  365. yourself
  366. ! !