Plug.st
changeset 2100 17cc7c9aa82d
parent 2041 fd1527246662
child 2101 58a78b51f78e
equal deleted inserted replaced
2099:306e2edb75bf 2100:17cc7c9aa82d
    11 "
    11 "
    12 
    12 
    13 "{ Package: 'stx:libview2' }"
    13 "{ Package: 'stx:libview2' }"
    14 
    14 
    15 Model subclass:#Plug
    15 Model subclass:#Plug
    16 	instanceVariableNames:'simulatedProtocol'
    16 	instanceVariableNames:'simulatedProtocol inheritedClasses'
    17 	classVariableNames:''
    17 	classVariableNames:''
    18 	poolDictionaries:''
    18 	poolDictionaries:''
    19 	category:'Kernel-Objects'
    19 	category:'Kernel-Objects'
    20 !
    20 !
    21 
    21 
    37 
    37 
    38 documentation
    38 documentation
    39 "
    39 "
    40     A Plug is an object which simulates a protocol and evaluates
    40     A Plug is an object which simulates a protocol and evaluates
    41     a corresponding block when receiving messages.
    41     a corresponding block when receiving messages.
    42     A plugs interface can be changed dynamically.
    42     A plug's interface can be changed dynamically.
       
    43     A plug can also be told to simulate inheriting messages from other classes,
       
    44     even multiple inheritance is possible.
    43 
    45 
    44     Its main use is for the demo doIts, to play the role of a model,
    46     Its main use is for the demo doIts, to play the role of a model,
    45     when no actual modelClass is available for the demonstration.
    47     when no actual modelClass is available for the demonstration.
    46     However, it can be used wherever some object is needed which responds to
    48     However, it can be used wherever some object is needed which responds to
    47     some protocol AND you do not want to add a class for it
    49     some protocol AND you do not want to add a class for it
    58 "
    60 "
    59 !
    61 !
    60 
    62 
    61 examples
    63 examples
    62 "
    64 "
       
    65   a simple plug:
    63                                                                         [exBegin]
    66                                                                         [exBegin]
    64     |plug|
    67         |plug|
    65 
    68 
    66     plug := Plug new.
    69         plug := Plug new.
    67     plug respondTo:#foo  with:[Transcript showCR:'received foo'].
    70         plug respondTo:#foo  with:[Transcript showCR:'Plug received foo'].
    68     plug respondTo:#foo: with:[:arg | Transcript showCR:'received foo: ', arg printString].
    71         plug respondTo:#foo: with:[:arg | Transcript showCR:'Plug received foo: ', arg printString].
    69 
    72 
    70     plug foo.
    73         plug foo.
    71     plug foo:'some argument'
    74         plug foo:'some argument'
    72                                                                         [exEnd]
    75                                                                         [exEnd]
    73 
    76 
    74   using a plug as a generator (simulates a readStream):
    77   using a plug as a generator (simulates a readStream):
    75                                                                         [exBegin]
    78                                                                         [exBegin]
    76     |generator num|
    79         |generator num|
    77 
    80 
    78     num := 0.
    81         num := 0.
    79     generator := Plug new.
    82         generator := Plug new.
    80     generator respondTo:#next
    83         generator respondTo:#next   with:[num := num + 1. num].
    81                    with:[num := num + 1. num].
    84         generator respondTo:#atEnd  with:[false].
    82     generator respondTo:#atEnd
    85 
    83                    with:[false].
    86         10 timesRepeat:[
    84 
    87             Transcript showCR:(generator next)
    85     10 timesRepeat:[
    88         ]
    86         Transcript showCR:(generator next)
       
    87     ]
       
    88                                                                         [exEnd]
    89                                                                         [exEnd]
    89 
    90 
    90   simulating ``instance variables'':
    91   simulating ``instance variables'':
    91   (actually, this is somewhat expensive - the contexts locals are used for them ...)
    92   (actually, this is somewhat expensive - the contexts locals are used for them ...)
    92   be careful with unintended variable sharing (if plugs are created in a loop ..)
    93   be careful with unintended variable sharing (if plugs are created in a loop ..)
    93                                                                         [exBegin]
    94                                                                         [exBegin]
    94     |plug1 plug2 local1 local2|
    95         |plug1 plug2 local1 local2|
    95 
    96 
    96     plug1 := Plug new.
    97         plug1 := Plug new.
    97     plug1 respondTo:#get  with:[local1].
    98         plug1 respondTo:#get  with:[local1].
    98     plug1 respondTo:#set: with:[:arg | local1 := arg].
    99         plug1 respondTo:#set: with:[:arg | local1 := arg].
    99 
   100 
   100     plug2 := Plug new.
   101         plug2 := Plug new.
   101     plug2 respondTo:#get  with:[local2].
   102         plug2 respondTo:#get  with:[local2].
   102     plug2 respondTo:#set: with:[:arg | local2 := arg].
   103         plug2 respondTo:#set: with:[:arg | local2 := arg].
   103 
   104 
   104     Transcript show:'plug1''s value: '; showCR:plug1 get.
   105         Transcript show:'plug1''s value: '; showCR:plug1 get.
   105     Transcript show:'plug2''s value: '; showCR:plug2 get.
   106         Transcript show:'plug2''s value: '; showCR:plug2 get.
   106 
   107 
   107     plug1 set:5.
   108         plug1 set:5.
   108     plug2 set:17.
   109         plug2 set:17.
   109 
   110 
   110     Transcript show:'plug1''s value: '; showCR:plug1 get.
   111         Transcript show:'plug1''s value: '; showCR:plug1 get.
   111     Transcript show:'plug2''s value: '; showCR:plug2 get.
   112         Transcript show:'plug2''s value: '; showCR:plug2 get.
       
   113                                                                         [exEnd]
       
   114 
       
   115   simulating a big list in a ListView 
       
   116   (real applications would read the lines from a database or file):
       
   117                                                                         [exBegin]
       
   118         |virtualList top lv|
       
   119 
       
   120         virtualList := Plug new.
       
   121         virtualList inheritFrom:SequenceableCollection.
       
   122         virtualList respondTo:#size with:[ 1000000 ].
       
   123         virtualList respondTo:#at:  with:[:lineNr | 'List line Nr. ' , lineNr printString ].
       
   124 
       
   125         top := StandardSystemView extent:200@200.
       
   126 
       
   127         lv := ScrollableView for:ListView in:top.
       
   128         lv origin:0.0 @ 0.0 corner:1.0 @ 1.0. 
       
   129         lv list:virtualList expandTabs:false scanForNonStrings:false includesNonStrings:false.
       
   130 
       
   131         top open.
   112                                                                         [exEnd]
   132                                                                         [exEnd]
   113 "
   133 "
   114 ! !
   134 ! !
   115 
   135 
   116 !Plug class methodsFor:'instance creation'!
   136 !Plug class methodsFor:'instance creation'!
   151      Otherwise, fall into the real doesNotUnderstand error."
   171      Otherwise, fall into the real doesNotUnderstand error."
   152 
   172 
   153     |block|
   173     |block|
   154 
   174 
   155     block := simulatedProtocol at:(aMessage selector) ifAbsent:[].
   175     block := simulatedProtocol at:(aMessage selector) ifAbsent:[].
   156     block isNil ifTrue:[
   176     block notNil ifTrue:[
   157         ^ super doesNotUnderstand:aMessage
   177         ^ block valueWithArguments:(aMessage arguments)
   158     ].
   178     ].
   159     ^ block valueWithArguments:(aMessage arguments)
   179     inheritedClasses notNil ifTrue:[
       
   180         inheritedClasses do:[:eachClass |
       
   181             |method|
       
   182 
       
   183             method := eachClass lookupMethodFor:(aMessage selector).
       
   184             method notNil ifTrue:[
       
   185                 ^ method valueWithReceiver:self arguments:(aMessage arguments).
       
   186             ].
       
   187         ].
       
   188     ].
       
   189     ^ super doesNotUnderstand:aMessage
   160 
   190 
   161     "Modified: 27.4.1996 / 16:15:34 / cg"
   191     "Modified: 27.4.1996 / 16:15:34 / cg"
       
   192 !
       
   193 
       
   194 size
       
   195     "catch this one - its so common"
       
   196 
       
   197     ^ self doesNotUnderstand:(Message selector:#size arguments:#())
   162 !
   198 !
   163 
   199 
   164 update:something with:aParameter from:changedObject
   200 update:something with:aParameter from:changedObject
   165     "catch unhandled messages by looking in my simulated protocol
   201     "catch unhandled messages by looking in my simulated protocol
   166      definition; if there is some block for it, return its value.
   202      definition; if there is some block for it, return its value.
   218      p foo.
   254      p foo.
   219     "
   255     "
   220 
   256 
   221     "Modified: 27.4.1996 / 16:14:19 / cg"
   257     "Modified: 27.4.1996 / 16:14:19 / cg"
   222     "Created: 27.4.1996 / 16:19:08 / cg"
   258     "Created: 27.4.1996 / 16:19:08 / cg"
       
   259 !
       
   260 
       
   261 inheritFrom:aClass
       
   262     "very tricky - change the inheritance.
       
   263      This cannot be done by changing my class directly, because the instance layout
       
   264      must still be correct for Plugs instance variables.
       
   265      Therefore, the inheritance is remembered, and done dynamically in the doesNotUnderstand
       
   266      implementation."
       
   267 
       
   268     self assert:(aClass instSize == 0).
       
   269     inheritedClasses isNil ifTrue:[
       
   270         inheritedClasses := Array with:aClass
       
   271     ] ifFalse:[
       
   272         inheritedClasses := inheritedClasses copyWith:aClass
       
   273     ].
   223 !
   274 !
   224 
   275 
   225 respondTo:aSelector with:aBlock
   276 respondTo:aSelector with:aBlock
   226     "tell the receiver to respond to a message given by selector,
   277     "tell the receiver to respond to a message given by selector,
   227      with evaluating aBlock. The number of arguments as defined by the 
   278      with evaluating aBlock. The number of arguments as defined by the 
   267 ! !
   318 ! !
   268 
   319 
   269 !Plug class methodsFor:'documentation'!
   320 !Plug class methodsFor:'documentation'!
   270 
   321 
   271 version
   322 version
   272     ^ '$Header: /cvs/stx/stx/libview2/Plug.st,v 1.21 2005-05-04 08:16:17 cg Exp $'
   323     ^ '$Header: /cvs/stx/stx/libview2/Plug.st,v 1.22 2006-02-14 11:05:34 cg Exp $'
   273 ! !
   324 ! !