Chris
Thanks very much for the response.
Magma does support blocks and I just verified the #testBlocks tests three different BlockContexts with various characteristics, one includes a 'self' reference. So on the surface, it seems like it should work.
I must be doing something a little off-track somewhere.
Having said that, did you happen to ever save a change to that #initialize method in the debugger at some point? MethodContexts on the stack referring to the CompiledMethod being changed may undergo some transformation. An existing instance of that Morph was persisted in the db; for one its MethodContext on the stack at the time is suddenly not pointing to the CompiledMethod installed in the class.
That didn't make any difference. I thought it wouldn't because it's a fresh image and it happens on all the interactors on all components.
So you could try to resave the #initialize method and re-commit all your SDR1000Morphs to the db. That might get it working, but there is still the main caveat with storing BlockContext and MethodContexts in the database for "long-term behavior" such as this; they become stale as soon as the code changes because they refer to the old CompiledMethod object, not the current one. This could cause some real confusion much later if you have lots of stored instances not behaving as the current method source indicates; they are running the old CompiledMethod which now executes in a DoIt Context I think.
Thanks, yes I understand the problem.
This is such as simple block anyway that you may want to consider using a MessageSend instead. This is a standard object that can be used instead of the Block. Try changing your assignment to resetButton to something like this:
resetButton := (SDRButton newWithParams: 'Reset' actionSelector: #(#RESETHW) actionTarget: (MessageSend receiver: self selector: #buttonAction:).
Now, I see MessageSend answers to #value and #valueWithArguments: but I don't see #value: which may be required. So you may need to add MessageSend>>#value:.
value: anObject ^ self valueWithArguments: { anObject }
This might help solve your problem and you might be happier with a MessageSend in the long run anyway because it will stay "current" with the code.
Ok, I will think about doing that. There are two blocks involved here though as there is a level of indirection. The first one above calls a method which looks up #RESETHW in the server dictionary to get another block which calls the target method. In this simple case the target method is also in this component but in most cases it is on one or more of the connected components, the other end of the connector link (i.e. when the link is connected the maps get exchanged and in this case of course self is the target). Do you think I'm flogging a dead horse here? I will fabricate a simple case with message send and see if that works.
Thanks Bob
--- "Cowdery, Bob [UK]" Bob.Cowdery@CGI-Europe.com wrote:
Chris
Sorry, but I am going to have to ask for help again. I can now manage the lifetimes in the database and image. Although it took me a while to get the process repeatable and figure out where all the references were. However, it now works and connectors stay connected. Unfortunately now that I am really retrieving from the database a retrieved app does not work. At least none of the UI events work, but then I am using dynamic techniques to hook everything together. I have a taken a simple case which is one composite component with one button on it. The button fires a block which references self in this case. However, self appears to be nil. This is where it fails.
DoIt | t1 t2 t3 t4 t5 | super initialize. t2 := ImageMorph new. t3 := GraphicPath , 'sdr1000.gif'. t2 setNewImageFrom: (Form fromFileNamed: t3). t1 := SDRButton newWithParams: 'Reset' actionSelector: #(#RESETHW ) actionTarget: [:t6 | self buttonAction: t6]. self borderWidth: 2. self borderColor: #complexFramed. self color: Color gray. self addMorph: t2. self addMorph: t1. t4 := t2 extent. t5 := t1 extent. self extent: t4 x + t5 x + 8 @ (t4 y + 8)
MessageNotUnderstood Undefined object buttonAction. This method called DoIt seems to be my Initialize method with the variables replaced with generated names. GraphicPath refers to a pool dictionary which it also can't resolve, don't know if that's relevant.
I have attached the file. The button is set up in the SDR1000Morph Initialize. It is called through the block in the dictionary set up by SDR1000Controller createServerInterfaceMap at #RESETHW.
I know this is a lot to ask. If it's not obvious what I need to do please don't labour over it.
Thanks Bob
*** Confidentiality Notice *** Proprietary/Confidential Information belonging to CGI Group Inc. and its affiliates may be contained in this message. If you are not a recipient indicated or intended in this message (or responsible for delivery of this message to such person), or you think for any reason that this message may have been addressed to you in error, you may not use or copy or deliver this message to anyone else. In such case, you should destroy this message and are asked to notify the sender by reply email.
*** Confidentiality Notice *** Proprietary/Confidential Information belonging to CGI Group Inc. and its affiliates may be contained in this message. If you are not a recipient indicated or intended in this message (or responsible for delivery of this message to such person), or you think for any reason that this message may have been addressed to you in error, you may not use or copy or deliver this message to anyone else. In such case, you should destroy this message and are asked to notify the sender by reply email.
squeak-dev@lists.squeakfoundation.org