Trapped-Backend.st 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. Smalltalk current createPackage: 'Trapped-Backend' properties: #{}!
  2. Object subclass: #EavModel
  3. instanceVariableNames: 'getBlock putBlock'
  4. package: 'Trapped-Backend'!
  5. !EavModel commentStamp!
  6. External actor value model.!
  7. !EavModel methodsFor: 'accessing'!
  8. getBlock: aBlock
  9. getBlock := aBlock
  10. !
  11. on: anObject
  12. "Returns value of model applied on object"
  13. ^getBlock value: anObject
  14. !
  15. on: anObject put: anObject2
  16. "Puts a value via model applied on object"
  17. ^putBlock value: anObject value: anObject2
  18. !
  19. putBlock: aBlock
  20. putBlock := aBlock
  21. ! !
  22. !EavModel methodsFor: 'initialization'!
  23. initialize
  24. super initialize.
  25. getBlock := [ self error: 'No getter block.' ].
  26. putBlock := [ self error: 'No putter block.' ].
  27. ! !
  28. Object subclass: #Isolator
  29. instanceVariableNames: 'root'
  30. package: 'Trapped-Backend'!
  31. !Isolator methodsFor: 'accessing'!
  32. root
  33. ^root
  34. !
  35. root: anObject
  36. root := anObject
  37. ! !
  38. !Isolator methodsFor: 'action'!
  39. model: anEavModel modify: aBlock
  40. | newValue |
  41. newValue := aBlock value: (anEavModel on: self).
  42. anEavModel on: self put: newValue deepCopy
  43. !
  44. model: anEavModel read: aBlock
  45. aBlock value: (anEavModel on: self) deepCopy
  46. ! !
  47. !Isolator class methodsFor: 'instance creation'!
  48. on: anObject
  49. ^self new root: anObject
  50. ! !
  51. Object subclass: #TrappedDispatcher
  52. instanceVariableNames: ''
  53. package: 'Trapped-Backend'!
  54. !TrappedDispatcher commentStamp!
  55. I am base class for change event dispatchers.
  56. I manage changed path - action block subscriptions.
  57. These subscription must be three-element arrays
  58. { dirty. path. block }
  59. My subclasses need to provide implementation for:
  60. add:
  61. do:
  62. (optionally) run!
  63. !TrappedDispatcher methodsFor: 'action'!
  64. changed: path
  65. | needsToRun |
  66. needsToRun := false.
  67. self do: [ :each |
  68. | aPath lesser |
  69. aPath := each second.
  70. lesser := aPath size min: path size.
  71. (path copyFrom: 1 to: lesser) = (aPath copyFrom: 1 to: lesser) ifTrue: [
  72. each at: 1 put: true.
  73. needsToRun := true.
  74. ]
  75. ].
  76. self dirty: needsToRun
  77. !
  78. dirty: aBoolean
  79. aBoolean ifTrue: [[ self run ] fork]
  80. !
  81. run
  82. self do: [ :each |
  83. each first ifTrue: [[ each third value ] ensure: [ each at: 1 put: false ]]
  84. ]
  85. ! !
  86. !Object methodsFor: '*Trapped-Backend'!
  87. reverseTrapAt: anObject
  88. ^nil
  89. !
  90. reverseTrapAt: anObject put: value
  91. self error: 'Trapped cannot put at ', self class name, ' type key.'
  92. ! !
  93. !SequenceableCollection methodsFor: '*Trapped-Backend'!
  94. asEavModel
  95. | model |
  96. model := EavModel new.
  97. model getBlock: [ :anObject |
  98. self inject: anObject into: [ :soFar :segment |
  99. soFar ifNotNil: [ segment reverseTrapAt: soFar ]]].
  100. self isEmpty ifFalse: [
  101. model putBlock: [ :anObject :value | | penultimate |
  102. penultimate := self allButLast inject: anObject into: [ :soFar :segment |
  103. soFar ifNotNil: [ segment reverseTrapAt: soFar ]].
  104. self last reverseTrapAt: penultimate put: value ]].
  105. ^model
  106. ! !
  107. !String methodsFor: '*Trapped-Backend'!
  108. reverseTrapAt: anObject
  109. ^anObject at: self ifAbsent: [nil]
  110. !
  111. reverseTrapAt: anObject put: value
  112. ^anObject at: self put: value
  113. ! !
  114. !Symbol methodsFor: '*Trapped-Backend'!
  115. reverseTrapAt: anObject
  116. ^[anObject perform: self] on: MessageNotUnderstood do: [^nil]
  117. !
  118. reverseTrapAt: anObject put: value
  119. ^anObject perform: (self, ':') asSymbol withArguments: { value }
  120. ! !
  121. !Number methodsFor: '*Trapped-Backend'!
  122. reverseTrapAt: anObject
  123. ^anObject at: self ifAbsent: [nil]
  124. !
  125. reverseTrapAt: anObject put: value
  126. ^anObject at: self put: value
  127. ! !