Trapped-Processors.st 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. Smalltalk current createPackage: 'Trapped-Processors'!
  2. TrappedDataExpectingProcessor subclass: #TrappedProcessorAttribute
  3. instanceVariableNames: 'attrName'
  4. package: 'Trapped-Processors'!
  5. !TrappedProcessorAttribute commentStamp!
  6. I set the data into an attribute speciried when creating me.
  7. No observing and sending back, atm.!
  8. !TrappedProcessorAttribute methodsFor: 'accessing'!
  9. attrName: aString
  10. attrName := aString
  11. ! !
  12. !TrappedProcessorAttribute methodsFor: 'data transformation'!
  13. toView: aDataCarrier
  14. aDataCarrier falseAsNilValue
  15. ifNil: [ aDataCarrier target removeAt: attrName ]
  16. ifNotNil: [ :value | aDataCarrier target at: attrName put: value ]
  17. ! !
  18. !TrappedProcessorAttribute class methodsFor: 'instance creation'!
  19. new: aString
  20. ^self new
  21. attrName: aString;
  22. yourself
  23. ! !
  24. TrappedDataExpectingProcessor subclass: #TrappedProcessorDataAdhoc
  25. instanceVariableNames: 'toViewBlock'
  26. package: 'Trapped-Processors'!
  27. !TrappedProcessorDataAdhoc commentStamp!
  28. I put data into target via contents: in toView:!
  29. !TrappedProcessorDataAdhoc methodsFor: 'accessing'!
  30. toViewBlock: aBlock
  31. toViewBlock := aBlock
  32. ! !
  33. !TrappedProcessorDataAdhoc methodsFor: 'data transformation'!
  34. toView: aDataCarrier
  35. toViewBlock value: aDataCarrier
  36. ! !
  37. !TrappedProcessorDataAdhoc class methodsFor: 'instance creation'!
  38. newToView: aBlock
  39. ^self new
  40. toViewBlock: aBlock;
  41. yourself
  42. ! !
  43. TrappedProcessor subclass: #TrappedProcessorDescend
  44. instanceVariableNames: ''
  45. package: 'Trapped-Processors'!
  46. !TrappedProcessorDescend commentStamp!
  47. I intepret data-trap in descendants of my brush.!
  48. !TrappedProcessorDescend methodsFor: 'data transformation'!
  49. toView: aDataCarrier
  50. Trapped current injectToJQuery: aDataCarrier target asJQuery children
  51. ! !
  52. TrappedProcessor subclass: #TrappedProcessorGuardBase
  53. instanceVariableNames: 'guardPath'
  54. package: 'Trapped-Processors'!
  55. !TrappedProcessorGuardBase commentStamp!
  56. I serve as base class for brush-guarding processors.
  57. I cover instantiation and subclasses have to provide
  58. implementation of toVIew: that react appropriately to guard releasing.!
  59. !TrappedProcessorGuardBase methodsFor: 'accessing'!
  60. guardPath: anArray
  61. guardPath := anArray
  62. ! !
  63. !TrappedProcessorGuardBase methodsFor: 'data transformation'!
  64. toModel: aDataCarrier
  65. "stop"
  66. !
  67. toView: aDataCarrier
  68. self subclassResponsibility
  69. ! !
  70. !TrappedProcessorGuardBase class methodsFor: 'instance creation'!
  71. new: anArray
  72. ^ self new
  73. guardPath: anArray;
  74. yourself
  75. ! !
  76. TrappedProcessorGuardBase subclass: #TrappedProcessorGuardContents
  77. instanceVariableNames: ''
  78. package: 'Trapped-Processors'!
  79. !TrappedProcessorGuardContents commentStamp!
  80. I am used to guard contents of the brush I am installed on.
  81. I save the brush contents, then I observe guard expression in the model,
  82. and when it changes to nil or false, I delete the brush contents;
  83. on the other hand, when it changes to non-nil and non-false,
  84. I restore it from remembered state and interpret all contained
  85. data-trap attributes inside.!
  86. !TrappedProcessorGuardContents methodsFor: 'data transformation'!
  87. toView: aDataCarrier
  88. | frozen contents |
  89. frozen := aDataCarrier copy.
  90. contents := frozen target asJQuery contents detach.
  91. frozen target trapGuard: guardPath contents: [ :html |
  92. html root asJQuery append: contents.
  93. Trapped current injectToJQuery: html root asJQuery ]
  94. ! !
  95. TrappedProcessorGuardBase subclass: #TrappedProcessorGuardProc
  96. instanceVariableNames: ''
  97. package: 'Trapped-Processors'!
  98. !TrappedProcessorGuardProc commentStamp!
  99. I am used to guard contents filling process of the brush I am installed on.
  100. I observe guard expression in the model,
  101. and when it changes to nil or false, I delete the brush contents;
  102. on the other hand, when it changes to non-nil and non-false,
  103. I run the rest on the chain, which should be one-time
  104. that sets up the contents,!
  105. !TrappedProcessorGuardProc methodsFor: 'data transformation'!
  106. toView: aDataCarrier
  107. | frozen |
  108. frozen := aDataCarrier copy.
  109. frozen target trapGuard: guardPath contents: [ frozen copy proceed ]
  110. ! !
  111. TrappedDataExpectingProcessor subclass: #TrappedProcessorInputChecked
  112. instanceVariableNames: ''
  113. package: 'Trapped-Processors'!
  114. !TrappedProcessorInputChecked commentStamp!
  115. I bind to checkbox checked attribute.!
  116. !TrappedProcessorInputChecked methodsFor: 'data transformation'!
  117. toView: aDataCarrier
  118. aDataCarrier toTargetAttr: 'checked'
  119. ! !
  120. !TrappedProcessorInputChecked methodsFor: 'installation'!
  121. installToView: aDataCarrier toModel: anotherDataCarrier
  122. | brush |
  123. brush := aDataCarrier target.
  124. brush onChange: [ anotherDataCarrier copy value: (brush asJQuery attr: 'checked') notNil; proceed ]
  125. ! !
  126. TrappedDataExpectingProcessor subclass: #TrappedProcessorInputValue
  127. instanceVariableNames: ''
  128. package: 'Trapped-Processors'!
  129. !TrappedProcessorInputValue commentStamp!
  130. I bind to input value.!
  131. !TrappedProcessorInputValue methodsFor: 'data transformation'!
  132. toView: aDataCarrier
  133. aDataCarrier toTargetValue
  134. ! !
  135. !TrappedProcessorInputValue methodsFor: 'installation'!
  136. installToView: aDataCarrier toModel: anotherDataCarrier
  137. | brush |
  138. brush := aDataCarrier target.
  139. brush onChange: [ anotherDataCarrier copy value: brush asJQuery val; proceed ]
  140. ! !
  141. TrappedProcessor subclass: #TrappedProcessorLoopBase
  142. instanceVariableNames: ''
  143. package: 'Trapped-Processors'!
  144. !TrappedProcessorLoopBase commentStamp!
  145. I serve as base class for looping processors.
  146. I cover instantiation and subclasses have to provide
  147. implementation of toVIew: that loops appropriately.!
  148. !TrappedProcessorLoopBase methodsFor: 'data transformation'!
  149. toModel: aDataCarrier
  150. "stop"
  151. !
  152. toView: aDataCarrier
  153. self subclassResponsibility
  154. ! !
  155. TrappedProcessorLoopBase subclass: #TrappedProcessorLoopContents
  156. instanceVariableNames: ''
  157. package: 'Trapped-Processors'!
  158. !TrappedProcessorLoopContents commentStamp!
  159. I am used to loop over data and repeat the contents
  160. of the brush I am installed on.
  161. I save the brush contents, then I observe the data in the model,
  162. and when it changes, I loop over it
  163. and restore the contents from remembered state
  164. and interpret all contained data-trap attributes inside
  165. for each element, putting the result _after_ my brush.
  166. My brush itself should be as least visible as possible,
  167. as it only serve as a position flag (use for example
  168. noscript, ins or del).!
  169. !TrappedProcessorLoopContents methodsFor: 'data transformation'!
  170. toView: aDataCarrier
  171. | frozen contents |
  172. frozen := aDataCarrier copy.
  173. contents := frozen target asJQuery contents detach.
  174. frozen target trapIter: #() after: [ :html |
  175. html root asJQuery append: contents clone.
  176. Trapped current injectToJQuery: html root asJQuery ]
  177. ! !
  178. TrappedProcessorLoopBase subclass: #TrappedProcessorLoopProc
  179. instanceVariableNames: ''
  180. package: 'Trapped-Processors'!
  181. !TrappedProcessorLoopProc commentStamp!
  182. I am used to loop over data and repeat the contents filling process
  183. of the brush I am installed on.
  184. I observe the data in the model,
  185. and when it changes, I loop over it
  186. and run the rest of the processing chain
  187. for each element, putting the result _after_ my brush.
  188. My brush itself should be as least visible as possible,
  189. as it only serve as a position flag (use for example
  190. noscript, ins or del).!
  191. !TrappedProcessorLoopProc methodsFor: 'data transformation'!
  192. toView: aDataCarrier
  193. | frozen |
  194. frozen := aDataCarrier copy.
  195. frozen target trapIter: #() after: [ :html | frozen copy target: html root; proceed ]
  196. ! !
  197. TrappedProcessor subclass: #TrappedProcessorReplace
  198. instanceVariableNames: 'left right'
  199. package: 'Trapped-Processors'!
  200. !TrappedProcessorReplace commentStamp!
  201. I convert data to string representation and do a regex replace.
  202. I get two parameters, in toView:, first is replaced with second,
  203. and in toModel:, the second is replaced with first.
  204. I remove leading '^' and ending '$' from the string used as replacement,
  205. so it safe to replace ^to with ^To, for example.!
  206. !TrappedProcessorReplace methodsFor: 'accessing'!
  207. left: aString
  208. left := aString
  209. !
  210. right: aString
  211. right := aString
  212. ! !
  213. !TrappedProcessorReplace methodsFor: 'data transformation'!
  214. toModel: aDataCarrier
  215. | replacement old |
  216. replacement := (left replace: '^\^' with: '') replace: '\$$' with: ''.
  217. old := aDataCarrier value asString.
  218. aDataCarrier
  219. value: (old replace: right with: replacement) whenDifferentFrom: old;
  220. proceed
  221. !
  222. toView: aDataCarrier
  223. | replacement old |
  224. replacement := (right replace: '^\^' with: '') replace: '\$$' with: ''.
  225. old := aDataCarrier value asString.
  226. aDataCarrier
  227. value: (old replace: left with: replacement) whenDifferentFrom: old;
  228. proceed
  229. ! !
  230. !TrappedProcessorReplace class methodsFor: 'instance creation'!
  231. new: aString with: anotherString
  232. ^ self new
  233. left: aString asString;
  234. right: anotherString asString;
  235. yourself
  236. ! !
  237. TrappedProcessor subclass: #TrappedProcessorSignal
  238. instanceVariableNames: 'selector'
  239. package: 'Trapped-Processors'!
  240. !TrappedProcessorSignal commentStamp!
  241. Instead of writing data directly to model,
  242. I instead modify it by sending a message specified when instantiating me.!
  243. !TrappedProcessorSignal methodsFor: 'accessing'!
  244. selector: aString
  245. selector := aString
  246. ! !
  247. !TrappedProcessorSignal methodsFor: 'data transformation'!
  248. toModel: aDataCarrier
  249. aDataCarrier modifyTargetByPerforming: selector
  250. !
  251. toView: aDataCarrier
  252. "stop"
  253. ! !
  254. !TrappedProcessorSignal class methodsFor: 'instance creation'!
  255. new: aString
  256. ^self new
  257. selector: aString;
  258. yourself
  259. ! !
  260. TrappedDataExpectingProcessor subclass: #TrappedProcessorToBlackboard
  261. instanceVariableNames: ''
  262. package: 'Trapped-Processors'!
  263. !TrappedProcessorToBlackboard commentStamp!
  264. I save the data to blackboard in toModel:, to position specified by path.!
  265. !TrappedProcessorToBlackboard methodsFor: 'data transformation'!
  266. toModel: aDataCarrier
  267. aDataCarrier target modify: [ aDataCarrier value ]
  268. ! !
  269. TrappedProcessor subclass: #TrappedProcessorWhenClicked
  270. instanceVariableNames: ''
  271. package: 'Trapped-Processors'!
  272. !TrappedProcessorWhenClicked commentStamp!
  273. I bind to an element and send true to blackboard when clicked.!
  274. !TrappedProcessorWhenClicked methodsFor: 'installation'!
  275. installToView: aDataCarrier toModel: anotherDataCarrier
  276. aDataCarrier target onClick: [ anotherDataCarrier copy proceed. false ]
  277. ! !
  278. TrappedProcessor subclass: #TrappedProcessorWhenSubmitted
  279. instanceVariableNames: ''
  280. package: 'Trapped-Processors'!
  281. !TrappedProcessorWhenSubmitted commentStamp!
  282. I bind to a form and send true to blackboard when submitted.!
  283. !TrappedProcessorWhenSubmitted methodsFor: 'installation'!
  284. installToView: aDataCarrier toModel: anotherDataCarrier
  285. aDataCarrier target onSubmit: [ anotherDataCarrier copy proceed. false ]
  286. ! !
  287. TrappedProcessor subclass: #TrappedProcessorWidget
  288. instanceVariableNames: 'viewName'
  289. package: 'Trapped-Processors'!
  290. !TrappedProcessorWidget commentStamp!
  291. I insert a widget instance of the class specified when creating me.!
  292. !TrappedProcessorWidget methodsFor: 'accessing'!
  293. viewName: aString
  294. viewName := aString
  295. ! !
  296. !TrappedProcessorWidget methodsFor: 'data transformation'!
  297. toView: aDataCarrier
  298. aDataCarrier target with: (Smalltalk current at: viewName) new
  299. ! !
  300. !TrappedProcessorWidget class methodsFor: 'instance creation'!
  301. new: aString
  302. ^self new
  303. viewName: aString;
  304. yourself
  305. ! !
  306. !TrappedDataCarrier methodsFor: '*Trapped-Processors'!
  307. modifyTarget
  308. self target modify: [ self value ]
  309. !
  310. modifyTargetByPerforming: aString
  311. self target modify: [ :m | m perform: aString ]
  312. !
  313. toTargetAttr: aString
  314. self target asJQuery attr: aString put: (self value ifNotNil: [ :o | o value ] ifNil: [[]])
  315. !
  316. toTargetContents
  317. self target contents: self value
  318. !
  319. toTargetValue
  320. self target asJQuery val: (self value ifNotNil: [ :o | o value ] ifNil: [[]])
  321. ! !
  322. !TrappedProcessor class methodsFor: '*Trapped-Processors'!
  323. attr: aString
  324. ^TrappedProcessorAttribute new: aString
  325. !
  326. dataToView: aBlock
  327. ^TrappedProcessorDataAdhoc newToView: aBlock
  328. !
  329. guardContents: anArray
  330. ^TrappedProcessorGuardContents new: anArray
  331. !
  332. guardProc: anArray
  333. ^TrappedProcessorGuardProc new: anArray
  334. !
  335. inputChecked
  336. ^TrappedProcessorInputChecked new
  337. !
  338. inputValue
  339. ^TrappedProcessorInputValue new
  340. !
  341. loopContents
  342. ^TrappedProcessorLoopContents new
  343. !
  344. loopProc
  345. ^TrappedProcessorLoopProc new
  346. !
  347. path
  348. ^TrappedProcessorDescend new
  349. !
  350. replace: aString with: anotherString
  351. ^TrappedProcessorReplace new: aString with: anotherString
  352. !
  353. signal: aString
  354. ^TrappedProcessorSignal new: aString
  355. !
  356. toBlackboard
  357. ^TrappedProcessorToBlackboard new
  358. !
  359. whenClicked
  360. ^TrappedProcessorWhenClicked new
  361. !
  362. whenSubmitted
  363. ^TrappedProcessorWhenSubmitted new
  364. !
  365. widget: aString
  366. ^TrappedProcessorWidget new: aString
  367. ! !