We need two key components.
The pin from which we srtart ("Pata") and the wire ("Cable") what "carry" or "have" the status through the circuit.
We start with the "Pata"
BorderedMorph subclass: #PataMorph
instanceVariableNames: 'connection state '
classVariableNames: ''
poolDictionaries: ''
category: 'LogicCircus'
In method categories panel, add a new category named initialization.
initialize
super initialize.
self color: Color yellow.
self extent: 7 @ 5.
self borderWidth: 2.
self openInWorld
I choose one little size for having more components in Screen.
In method categories panel, add a new category named accessing.
state
^ state.
state: aBoolean
state _ aBoolean
I follow the convention on having accesing methods with same name of instance variables, and writing what logical "type" that instance should be.
Remember , in Smalltalk not exist types, I use only because eras of Pascal code writing.
In method categories panel, add a new category named event handling
Clickling in this category , add the following code.
handlesMouseDown: evt
"We want start wiring when shift clik in Pata (this little
yellow thing ) ".
^ evt shiftPressed
mouseDown: evt
"with shift pressed creates a CableMorph from me"
| connectionEnd |
(evt shiftPressed and: [self hasConnection not])
ifTrue: [connectionEnd _ self class new.
self = self owner submorphs last
ifTrue: [CableMorph new from: self to: connectionEnd]
ifFalse: [CableMorph new from: connectionEnd to: self].
HandMorph attach: connectionEnd]
ifFalse: [^ evt hand waitForClicksOrDrag: self event: evt]
wantsToBeDroppedInto: aMorph
"I'm always want to be dropped anywhere"
^ true
justDroppedInto: aMorph event: evt
"I have been dropped into aMorph I'm going to attach me to him"
| potentialEmbedings m |
super justDroppedInto: aMorph event: evt.
potentialEmbedings _ self potentialEmbeddingTargets.
potentialEmbedings size <= 2
ifTrue: [^ self].
potentialEmbedings second == self connection
ifTrue: [^ self].
potentialEmbedings second class == PataMorph
ifTrue: [m _ potentialEmbedings second owner.
self center: potentialEmbedings second center.
m replaceSubmorph: potentialEmbedings second by: self]
ifFalse: [potentialEmbedings second class == CableMorph
ifTrue: [potentialEmbedings second addMorph: self]
ifFalse: [potentialEmbedings second addMorphCentered: self]].
potentialEmbedings second connection: self connection
With this four methods, we have a morph what when you shiflt click, start a new CableMorph and when you drop open end to Light, Cable or Pata, finish the secuence.
In method categories panel, add a new category named testing
hasConnection
"returns true if I'm connected "
^ connection notNil
Ending method categories , add a new category named connection
connection
^ connection
connection: aConnection
connection _ aConnection
isConnectionSet
"Answer whether the receiver is connected to an object that coordinates
updates among switches."
connection == nil
ifTrue: [state _ true.
^ false]
ifFalse: [^ true]
notifyConnection
"Send the receiver's connection (if it exists) the message 'changed:
self'
in order for the connection to broadcast the change to other objects
connected by the connection."
self isConnectionSet
ifTrue: [self connection remoteControl: self state]
notifyRemoveMe
"Send the receiver's connection (if it exists) the message 'changed:
self'
in order for the connection to broadcast the change to other objects
connected by the connection."
self connection removeMe: self.
self connection delete.
connection _ nil
remoteControl: aBoolean
state _ aBoolean.
aBoolean
ifTrue: [self color: Color red]
ifFalse: [self color: Color black].
(self owner isKindOf: CompuertaMorph)
ifTrue: [self owner doRemoteControl].
(self owner isKindOf: LightMorph)
ifTrue: [self owner remoteControl: aBoolean]
Dan Ingalls and others have the credit for Fabrik and Morphic Components , where I found the ideas for LogicCircus
,