Trapped-Processors.st 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. Smalltalk current createPackage: 'Trapped-Processors'!
  2. TrappedProcessor subclass: #TrappedDataExpectingProcessor
  3. instanceVariableNames: ''
  4. package: 'Trapped-Processors'!
  5. !TrappedDataExpectingProcessor commentStamp!
  6. I answer true to isExpectingModelData and serve as a base class
  7. for processor that present / change model data.
  8. When at least one of my instances is present in the chain,
  9. automatic databinding processor is added at the beginning
  10. (the data-binding scenario); otherwise, the chain
  11. is run immediately with true as data (run-once scenario).!
  12. !TrappedDataExpectingProcessor methodsFor: 'testing'!
  13. isExpectingModelData
  14. ^true
  15. ! !
  16. TrappedDataExpectingProcessor subclass: #TrappedProcessorContents
  17. instanceVariableNames: ''
  18. package: 'Trapped-Processors'!
  19. !TrappedProcessorContents commentStamp!
  20. I put data into target via contents: in toView:!
  21. !TrappedProcessorContents methodsFor: 'data transformation'!
  22. toView: aDataCarrier
  23. aDataCarrier toTargetContents
  24. ! !
  25. TrappedDataExpectingProcessor subclass: #TrappedProcessorInputChecked
  26. instanceVariableNames: ''
  27. package: 'Trapped-Processors'!
  28. !TrappedProcessorInputChecked commentStamp!
  29. I bind to checkbox checked attribute.!
  30. !TrappedProcessorInputChecked methodsFor: 'data transformation'!
  31. toView: aDataCarrier
  32. aDataCarrier toTargetAttr: 'checked'
  33. ! !
  34. !TrappedProcessorInputChecked methodsFor: 'installation'!
  35. installToView: aDataCarrier toModel: anotherDataCarrier
  36. | brush |
  37. brush := aDataCarrier target.
  38. brush onChange: [ anotherDataCarrier copy value: (brush asJQuery attr: 'checked') notNil; proceed ]
  39. ! !
  40. TrappedDataExpectingProcessor subclass: #TrappedProcessorInputValue
  41. instanceVariableNames: ''
  42. package: 'Trapped-Processors'!
  43. !TrappedProcessorInputValue commentStamp!
  44. I bind to input value.!
  45. !TrappedProcessorInputValue methodsFor: 'data transformation'!
  46. toView: aDataCarrier
  47. aDataCarrier toTargetValue
  48. ! !
  49. !TrappedProcessorInputValue methodsFor: 'installation'!
  50. installToView: aDataCarrier toModel: anotherDataCarrier
  51. | brush |
  52. brush := aDataCarrier target.
  53. brush onChange: [ anotherDataCarrier copy value: brush asJQuery val; proceed ]
  54. ! !
  55. TrappedProcessor subclass: #TrappedProcessorBlackboard
  56. instanceVariableNames: ''
  57. package: 'Trapped-Processors'!
  58. !TrappedProcessorBlackboard commentStamp!
  59. I am used internally to fetch data from blackboard
  60. or write it back.
  61. I am added to the beginning of the chain
  62. when the chain contains at least one element
  63. that isExpectingModelData (see TrappedDataExpectingProcessor).!
  64. !TrappedProcessorBlackboard methodsFor: 'data transformation'!
  65. toModel: aDataCarrier
  66. aDataCarrier modifyTarget
  67. ! !
  68. !TrappedProcessorBlackboard methodsFor: 'installation'!
  69. installToView: aDataCarrier toModel: anotherDataCarrier
  70. | snap |
  71. snap := anotherDataCarrier target.
  72. snap watch: [ :data |
  73. (aDataCarrier target asJQuery closest: 'html') toArray isEmpty ifTrue: [ KeyedPubSubUnsubscribe signal ].
  74. snap do: [ aDataCarrier copy value: data; proceed ] ].
  75. aDataCarrier value: false
  76. ! !
  77. TrappedProcessor subclass: #TrappedProcessorDescend
  78. instanceVariableNames: ''
  79. package: 'Trapped-Processors'!
  80. !TrappedProcessorDescend commentStamp!
  81. I intepret data-trap in descendants of my brush.!
  82. !TrappedProcessorDescend methodsFor: 'data transformation'!
  83. toView: aDataCarrier
  84. Trapped current injectToJQuery: aDataCarrier target asJQuery children
  85. ! !
  86. TrappedProcessor subclass: #TrappedProcessorGuardBase
  87. instanceVariableNames: 'guardPath'
  88. package: 'Trapped-Processors'!
  89. !TrappedProcessorGuardBase commentStamp!
  90. I serve as base class for brush-guarding processors.
  91. I cover instantiation and subclasses have to provide
  92. implementation of toVIew: that react appropriately to guard releasing.!
  93. !TrappedProcessorGuardBase methodsFor: 'accessing'!
  94. guardPath: anArray
  95. guardPath := anArray
  96. ! !
  97. !TrappedProcessorGuardBase methodsFor: 'data transformation'!
  98. toModel: aDataCarrier
  99. "stop"
  100. !
  101. toView: aDataCarrier
  102. self subclassResponsibility
  103. ! !
  104. !TrappedProcessorGuardBase class methodsFor: 'instance creation'!
  105. new: anArray
  106. ^ self new
  107. guardPath: anArray;
  108. yourself
  109. ! !
  110. TrappedProcessorGuardBase subclass: #TrappedProcessorGuardContents
  111. instanceVariableNames: ''
  112. package: 'Trapped-Processors'!
  113. !TrappedProcessorGuardContents commentStamp!
  114. I am used to guard contents of the brush I am installed on.
  115. I save the brush contents, then I observe guard expression in the model,
  116. and when it changes to nil or false, I delete the brush contents;
  117. on the other hand, when it changes to non-nil and non-false,
  118. I restore it from remembered state and interpret all contained
  119. data-trap attributes inside.!
  120. !TrappedProcessorGuardContents methodsFor: 'data transformation'!
  121. toView: aDataCarrier
  122. | frozen contents |
  123. frozen := aDataCarrier copy.
  124. contents := frozen target asJQuery contents detach.
  125. frozen target trapGuard: guardPath contents: [ :html |
  126. html root asJQuery append: contents.
  127. Trapped current injectToJQuery: html root asJQuery ]
  128. ! !
  129. TrappedProcessorGuardBase subclass: #TrappedProcessorGuardProc
  130. instanceVariableNames: ''
  131. package: 'Trapped-Processors'!
  132. !TrappedProcessorGuardProc commentStamp!
  133. I am used to guard contents filling process of the brush I am installed on.
  134. I observe guard expression in the model,
  135. and when it changes to nil or false, I delete the brush contents;
  136. on the other hand, when it changes to non-nil and non-false,
  137. I run the rest on the chain, which should be one-time
  138. that sets up the contents,!
  139. !TrappedProcessorGuardProc methodsFor: 'data transformation'!
  140. toView: aDataCarrier
  141. | frozen |
  142. frozen := aDataCarrier copy.
  143. frozen target trapGuard: guardPath contents: [ frozen copy proceed ]
  144. ! !
  145. TrappedProcessor subclass: #TrappedProcessorSignal
  146. instanceVariableNames: 'selector'
  147. package: 'Trapped-Processors'!
  148. !TrappedProcessorSignal commentStamp!
  149. Instead of writing data directly to model,
  150. I instead modify it by sending a message specified when instantiating me.!
  151. !TrappedProcessorSignal methodsFor: 'accessing'!
  152. selector: aString
  153. selector := aString
  154. ! !
  155. !TrappedProcessorSignal methodsFor: 'data transformation'!
  156. toModel: aDataCarrier
  157. aDataCarrier modifyTargetByPerforming: selector
  158. !
  159. toView: aDataCarrier
  160. "stop"
  161. ! !
  162. !TrappedProcessorSignal class methodsFor: 'instance creation'!
  163. new: aString
  164. ^self new
  165. selector: aString;
  166. yourself
  167. ! !
  168. TrappedProcessor subclass: #TrappedProcessorTerminator
  169. instanceVariableNames: ''
  170. package: 'Trapped-Processors'!
  171. !TrappedProcessorTerminator commentStamp!
  172. I do not proceed in toView:.
  173. I am added automatically to end of chain when it does not contain
  174. any element that isExpectingModelData (see TrappedDataExpectingProcessor).!
  175. !TrappedProcessorTerminator methodsFor: 'data transformation'!
  176. toView: aDataCarrier
  177. "stop"
  178. ! !
  179. TrappedProcessor subclass: #TrappedProcessorWhenClicked
  180. instanceVariableNames: ''
  181. package: 'Trapped-Processors'!
  182. !TrappedProcessorWhenClicked commentStamp!
  183. I bind to an element and send true to blackboard when clicked.!
  184. !TrappedProcessorWhenClicked methodsFor: 'installation'!
  185. installToView: aDataCarrier toModel: anotherDataCarrier
  186. aDataCarrier target onClick: [ anotherDataCarrier copy proceed. false ]
  187. ! !
  188. TrappedProcessor subclass: #TrappedProcessorWhenSubmitted
  189. instanceVariableNames: ''
  190. package: 'Trapped-Processors'!
  191. !TrappedProcessorWhenSubmitted commentStamp!
  192. I bind to a form and send true to blackboard when submitted.!
  193. !TrappedProcessorWhenSubmitted methodsFor: 'installation'!
  194. installToView: aDataCarrier toModel: anotherDataCarrier
  195. aDataCarrier target onSubmit: [ anotherDataCarrier copy proceed. false ]
  196. ! !
  197. TrappedProcessor subclass: #TrappedProcessorWidget
  198. instanceVariableNames: 'viewName'
  199. package: 'Trapped-Processors'!
  200. !TrappedProcessorWidget commentStamp!
  201. I insert a widget instance of the class specified when creating me.!
  202. !TrappedProcessorWidget methodsFor: 'accessing'!
  203. viewName: aString
  204. viewName := aString
  205. ! !
  206. !TrappedProcessorWidget methodsFor: 'data transformation'!
  207. toView: aDataCarrier
  208. aDataCarrier target with: (Smalltalk current at: viewName) new
  209. ! !
  210. !TrappedProcessorWidget class methodsFor: 'instance creation'!
  211. new: aString
  212. ^self new
  213. viewName: aString;
  214. yourself
  215. ! !
  216. !TrappedDataCarrier methodsFor: '*Trapped-Processors'!
  217. modifyTarget
  218. self target modify: [ self value ]
  219. !
  220. modifyTargetByPerforming: aString
  221. self target modify: [ :m | m perform: aString ]
  222. !
  223. toTargetAttr: aString
  224. self target asJQuery attr: aString put: (self value ifNotNil: [ :o | o value ] ifNil: [[]])
  225. !
  226. toTargetContents
  227. self target contents: self value
  228. !
  229. toTargetValue
  230. self target asJQuery val: (self value ifNotNil: [ :o | o value ] ifNil: [[]])
  231. ! !