pharo-users@lists.pharo.org

Any question about pharo is welcome

View all threads

Updating a Form after changing pixel values

MS
Mikael Svane
Fri, Mar 7, 2025 5:11 PM

I have a Form where I change pixel colours using Form>>pixelValueAt:put:.
The Form exists inside an SpImagePresenter. After having changed the pixels,
I want to redraw the Form in an #updatePresenters method to show the
changes, but I haven't been able to figure out how to do this. If I inspect
the Form it is clear that the pixels have been changed, so the problem is in
the #updatePresenters mwthod. I have tried different variations on this
theme without success:

updatePresenter

                       | canvas |

                       "Get the canvas of the Form:"

                       canvas := imagePresenter image form getCanvas.

                       

                       adapter widget drawSubmorphsOn: canvas

Any suggestions would be very welcome.

Kind regards,

Mikael

I have a Form where I change pixel colours using Form>>pixelValueAt:put:. The Form exists inside an SpImagePresenter. After having changed the pixels, I want to redraw the Form in an #updatePresenters method to show the changes, but I haven't been able to figure out how to do this. If I inspect the Form it is clear that the pixels have been changed, so the problem is in the #updatePresenters mwthod. I have tried different variations on this theme without success: updatePresenter | canvas | "Get the canvas of the Form:" canvas := imagePresenter image form getCanvas. adapter widget drawSubmorphsOn: canvas Any suggestions would be very welcome. Kind regards, Mikael
RD
Renaud de Villemeur
Sat, Mar 8, 2025 3:23 AM

Hi Mikael

If my understanding is correct, you're using SpImagePresenter to display a Form. 
You then have made some changes to  the Form and you want to show its new face. 

Why don't you set the image again in your presenter ?
Something like image image: yourUpdatedForm.

You can even update the Form of your presenter directly like:
image image: (image image pixelValueAt: 10@10 put: (image image  pixelValueFor: Color red))

image being an instance of SpImagePresenter.

Renaud

Mar 7, 2025, 13:53 by mikael.svane@fridhem.org:

I have a Form where I change pixel colours using Form>>pixelValueAt:put:. The Form exists inside an SpImagePresenter. After having changed the pixels, I want to redraw the Form in an #updatePresenters method to show the changes, but I haven’t been able to figure out how to do this. If I inspect the Form it is clear that the pixels have been changed, so the problem is in the #updatePresenters mwthod. I have tried different variations on this theme without success:

 

updatePresenter

                           | canvas |

                           “Get the canvas of the Form:”

                           canvas := imagePresenter image form getCanvas.

                          

                           adapter widget drawSubmorphsOn: canvas

 

Any suggestions would be very welcome.

 

Kind regards,

Mikael

Hi Mikael If my understanding is correct, you're using SpImagePresenter to display a Form.  You then have made some changes to  the Form and you want to show its new face.  Why don't you set the image again in your presenter ? Something like `image image: yourUpdatedForm`. You can even update the Form of your presenter directly like: `image image: (image image pixelValueAt: 10@10 put: (image image  pixelValueFor: Color red))` image being an instance of SpImagePresenter. Renaud Mar 7, 2025, 13:53 by mikael.svane@fridhem.org: > > I have a Form where I change pixel colours using Form>>pixelValueAt:put:. The Form exists inside an SpImagePresenter. After having changed the pixels, I want to redraw the Form in an #updatePresenters method to show the changes, but I haven’t been able to figure out how to do this. If I inspect the Form it is clear that the pixels have been changed, so the problem is in the #updatePresenters mwthod. I have tried different variations on this theme without success: > > >   > > > updatePresenter > > >                            | canvas | > > >                            “Get the canvas of the Form:” > > >                            canvas := imagePresenter image form getCanvas. > > >                            > > >                            adapter widget drawSubmorphsOn: canvas > > >   > > > > > > Any suggestions would be very welcome. > > >   > > > Kind regards, > > > Mikael > >
S
sducasseatwork@mailo.com
Sat, Mar 8, 2025 8:03 PM

Hi Mikael

I do not know the answer so I tried to find it.
Indeed the superclass>>updatePresenter is empty :(

Let us see what esteban will reply.
Now I tried to check the morphic back end.

Now writing directly on the canvas this way does not look the right way.
Did you try with
SpMorphPresenter
or
SpRoassalPresenter because you have access to the cairo canvas.

While browsing the code of the SpMorphicROassalAdapter I saw

widget sessionChanged.

SpAbstractMorphicAdapter I saw changed.

changed

^ self widgetDo: [ :w | w changed ]

I also saw in SpAbstractAdapter isRedrawable so I wonder if it should not be true on the Adapter corresponding to the SpImagePresenter (if any)

BTW the SpMorphicAthensAdapter defines a method redraw (Athens is the cairo wrapper used also in Roassal)

Reading the code of SpMorphicImageAdapter >> buildWidget

| alphaImage |
alphaImage := AlphaImageMorph new.
alphaImage model: self.
alphaImage
	getImageSelector: #getImage;
	vResizing: #spaceFill;
	hResizing: #spaceFill;
	layout: self layoutValue;
	dragEnabled: self dragEnabled;
	dropEnabled: self dropEnabled;
	setBalloonText: self help;
	update: #getImage.

self model
	whenImageChangeDo: [
		alphaImage image:
				(self getImage ifNil: [ Form extent: 1 @ 1 depth: 32 ]) ];
	whenAutoScaleChangeDo: [ widget layout: self layoutValue ].

^ alphaImage

It feels like we should reassign the image:

Did you try something like

updatePresenter

                       self image: self image?

On 7 Mar 2025, at 18:11, Mikael Svane mikael.svane@fridhem.org wrote:

I have a Form where I change pixel colours using Form>>pixelValueAt:put:. The Form exists inside an SpImagePresenter. After having changed the pixels, I want to redraw the Form in an #updatePresenters method to show the changes, but I haven’t been able to figure out how to do this. If I inspect the Form it is clear that the pixels have been changed, so the problem is in the #updatePresenters mwthod. I have tried different variations on this theme without success:

updatePresenter
| canvas |
“Get the canvas of the Form:”
canvas := imagePresenter image form getCanvas.

                        adapter widget drawSubmorphsOn: canvas

Any suggestions would be very welcome.

Kind regards,
Mikael

Hi Mikael I do not know the answer so I tried to find it. Indeed the superclass>>updatePresenter is empty :( Let us see what esteban will reply. Now I tried to check the morphic back end. Now writing directly on the canvas this way does not look the right way. Did you try with SpMorphPresenter or SpRoassalPresenter because you have access to the cairo canvas. While browsing the code of the SpMorphicROassalAdapter I saw widget sessionChanged. SpAbstractMorphicAdapter I saw changed. changed ^ self widgetDo: [ :w | w changed ] I also saw in SpAbstractAdapter isRedrawable so I wonder if it should not be true on the Adapter corresponding to the SpImagePresenter (if any) BTW the SpMorphicAthensAdapter defines a method redraw (Athens is the cairo wrapper used also in Roassal) Reading the code of SpMorphicImageAdapter >> buildWidget | alphaImage | alphaImage := AlphaImageMorph new. alphaImage model: self. alphaImage getImageSelector: #getImage; vResizing: #spaceFill; hResizing: #spaceFill; layout: self layoutValue; dragEnabled: self dragEnabled; dropEnabled: self dropEnabled; setBalloonText: self help; update: #getImage. self model whenImageChangeDo: [ alphaImage image: (self getImage ifNil: [ Form extent: 1 @ 1 depth: 32 ]) ]; whenAutoScaleChangeDo: [ widget layout: self layoutValue ]. ^ alphaImage It feels like we should reassign the image: Did you try something like > updatePresenter > > self image: self image? > On 7 Mar 2025, at 18:11, Mikael Svane <mikael.svane@fridhem.org> wrote: > > I have a Form where I change pixel colours using Form>>pixelValueAt:put:. The Form exists inside an SpImagePresenter. After having changed the pixels, I want to redraw the Form in an #updatePresenters method to show the changes, but I haven’t been able to figure out how to do this. If I inspect the Form it is clear that the pixels have been changed, so the problem is in the #updatePresenters mwthod. I have tried different variations on this theme without success: > > updatePresenter > | canvas | > “Get the canvas of the Form:” > canvas := imagePresenter image form getCanvas. > > adapter widget drawSubmorphsOn: canvas > > Any suggestions would be very welcome. > > Kind regards, > Mikael
EL
Esteban Lorenzano
Mon, Mar 10, 2025 10:09 AM

Hi,

This is a corner case that is not considered in Spec design: In fact
what you are doing is changing the content of the model and you need the
presenter to react to it.

Indeed, as Stef says the solution is to re-set the image to the image
presenter when performing the change:

myPresenter image: modifiedForm.

You may think something like that should be done in the
updatePresenter message (but updatePresenter does not has a mean in
"widget" presenters).... or like the refresh message for lists/tables,
and you would be right (I will add a refresh message to
SpImagePresenter). But at the end, it will end up doing exactly that, so
you are safe workaround it the thing :)

Esteban

On 3/8/25 21:03, sducasseatwork--- via Pharo-users wrote:

Hi Mikael

I do not know the answer so I tried to find it.
Indeed the superclass>>updatePresenter is empty :(

Let us see what esteban will reply.
Now I tried to check the morphic back end.

Now writing directly on the canvas this way does not look the right way.
Did you try with
SpMorphPresenter
or
SpRoassalPresenter because you have access to the cairo canvas.

While browsing the code of the SpMorphicROassalAdapter I saw

widget sessionChanged.

SpAbstractMorphicAdapter I saw changed.

changed

^ self widgetDo: [ :w | w changed ]

I also saw in SpAbstractAdapter isRedrawable so I wonder if it should
not be true on the Adapter corresponding to the SpImagePresenter (if any)

BTW the SpMorphicAthensAdapter defines a method redraw (Athens is the
cairo wrapper used also in Roassal)

Reading the code of SpMorphicImageAdapter >> buildWidget

| alphaImage |
alphaImage := AlphaImageMorph new.
alphaImage model: self.
alphaImage
getImageSelector: #getImage;
vResizing: #spaceFill;
hResizing: #spaceFill;
layout: self layoutValue;
dragEnabled: self dragEnabled;
dropEnabled: self dropEnabled;
setBalloonText: self help;
update: #getImage.

self model
whenImageChangeDo: [
alphaImage image:
(self getImage ifNil: [ Form extent: 1 @ 1 depth: 32 ]) ];
whenAutoScaleChangeDo: [ widget layout: self layoutValue ].

^ alphaImage

It feels like we should reassign the image:

Did you try something like

updatePresenter
                          self image: self image?

On 7 Mar 2025, at 18:11, Mikael Svane mikael.svane@fridhem.org wrote:

I have a Form where I change pixel colours using
Form>>pixelValueAt:put:. The Form exists inside an SpImagePresenter.
After having changed the pixels, I want to redraw the Form in an
#updatePresenters method to show the changes, but I haven’t been able
to figure out how to do this. If I inspect the Form it is clear that
the pixels have been changed, so the problem is in the
#updatePresenters mwthod. I have tried different variations on this
theme without success:
updatePresenter
                           | canvas |
                           “Get the canvas of the Form:”
                           canvas := imagePresenter image form getCanvas.
                           adapter widget drawSubmorphsOn: canvas
Any suggestions would be very welcome.
Kind regards,
Mikael

Hi, This is a corner case that is not considered in Spec design: In fact what you are doing is changing the content of the model and you need the presenter to react to it. Indeed, as Stef says the solution is to re-set the image to the image presenter when performing the change: myPresenter image: modifiedForm. You may think something like that should be done in the `updatePresenter` message (but updatePresenter does not has a mean in "widget" presenters).... or like the `refresh` message for lists/tables, and you would be right (I will add a refresh message to SpImagePresenter). But at the end, it will end up doing exactly that, so you are safe workaround it the thing :) Esteban On 3/8/25 21:03, sducasseatwork--- via Pharo-users wrote: > Hi Mikael > > I do not know the answer so I tried to find it. > Indeed the superclass>>updatePresenter is empty :( > > Let us see what esteban will reply. > Now I tried to check the morphic back end. > > Now writing directly on the canvas this way does not look the right way. > Did you try with > SpMorphPresenter > or > SpRoassalPresenter because you have access to the cairo canvas. > > While browsing the code of the SpMorphicROassalAdapter I saw > > widget sessionChanged. > > > SpAbstractMorphicAdapter I saw changed. > > changed > > ^ self widgetDo: [ :w | w changed ] > > I also saw in SpAbstractAdapter isRedrawable so I wonder if it should > not be true on the Adapter corresponding to the SpImagePresenter (if any) > > > BTW the SpMorphicAthensAdapter defines a method redraw (Athens is the > cairo wrapper used also in Roassal) > > Reading the code of SpMorphicImageAdapter >> buildWidget > > | alphaImage | > alphaImage := AlphaImageMorph new. > alphaImage model: self. > alphaImage > getImageSelector: #getImage; > vResizing: #spaceFill; > hResizing: #spaceFill; > layout: self layoutValue; > dragEnabled: self dragEnabled; > dropEnabled: self dropEnabled; > setBalloonText: self help; > update: #getImage. > > self model > whenImageChangeDo: [ > alphaImage image: > (self getImage ifNil: [ Form extent: 1 @ 1 depth: 32 ]) ]; > whenAutoScaleChangeDo: [ widget layout: self layoutValue ]. > > ^ alphaImage > > It feels like we should reassign the image: > > Did you try something like > >> updatePresenter >>                           self image: self image? > > >> On 7 Mar 2025, at 18:11, Mikael Svane <mikael.svane@fridhem.org> wrote: >> >> I have a Form where I change pixel colours using >> Form>>pixelValueAt:put:. The Form exists inside an SpImagePresenter. >> After having changed the pixels, I want to redraw the Form in an >> #updatePresenters method to show the changes, but I haven’t been able >> to figure out how to do this. If I inspect the Form it is clear that >> the pixels have been changed, so the problem is in the >> #updatePresenters mwthod. I have tried different variations on this >> theme without success: >> updatePresenter >>                            | canvas | >>                            “Get the canvas of the Form:” >>                            canvas := imagePresenter image form getCanvas. >>                            adapter widget drawSubmorphsOn: canvas >> Any suggestions would be very welcome. >> Kind regards, >> Mikael >