[Seaside] Brushes and state

James Foster Smalltalk at JGFoster.net
Fri Jun 19 00:49:59 UTC 2009


Julian,

I did the GoogleMaps stuff several months ago and was only comparing  
component and brush; I didn't consider a Painter mostly from lack of  
knowledge (and being on a 2.8 environment). I wasn't aware that there  
was a debate about when to use brushes; I thought it was just me who  
couldn't figure it out!

I ended up with a Brush because it felt more like I was just defining  
a special <div> and I didn't want to require people to define a child  
component. I figured that until I needed something more complicated  
I'd stay with the simplest thing that could possibly work (tm), and  
the brush approach came together nicely. Once I started thinking about  
GoogleMaps as being little more than a fancy div/listbox/image,  
several things fell out quite cleanly. I discovered that I don't want  
to keep any state and that I want to treat the configuration as one  
does with other things. For example (where all of the messages to the  
brush are optional, but #setCenter:zoom: is most useful):

MyComponent>>#renderContentOn: html

	html googleMap
		class: 'myMap';
		setCenter: 45.5267 @ -122.8390 zoom: 11;
		enableGoogleBar;
		addType: GMapType physical;
		addControl: GControl largeMapControl;
		setUIToDefault;
		on: 'zoomEnd' do: [:x :y :z |
			'alert("Zoom from ' , x printString , ' to ' , y printString ,
			' (see GMUsingLatLong>>renderContentOn:)");'];
		yourself.

The only other requirement is that the component needs to allow some  
#updateRoot: behavior:

MyComponent>>#updateRoot: anHtmlRoot

	super updateRoot: anHtmlRoot.
	self updateRootWithGoogleMaps: anHtmlRoot.

The implementation involves creating various scripts and feeding them  
out, but it works fine in the brush.

GoogleMap>>#with: anObject

	self ensureId.
	super with: [
		anObject renderOn: canvas.
		canvas html: self mapScript.
	].
	self addLoadScript: self variable , 'Init()'.

Overall it seemed less intrusive for the library client to use a brush  
rather than a component. Other than #updateRoot:, there isn't really  
much to do. With a component there were so many things that were brush- 
like, including setting the class, id, style, etc., and more issues  
(does it need to be included as a child?). I was able to do so much  
without state, that it just seemed nice this way. It seemed like I got  
further than any of the other GoogleMaps packages I found, but I'd  
love to see another approach or get expert feedback on what I've done.

In general, while I'm heavily involved in Seaside from the GemStone  
point-of-view, there is still a great deal for me to learn about when  
to use different parts of the framework. This exercise was another  
opportunity to learn and I did learn something!

James

On Jun 18, 2009, at 5:15 PM, Julian Fitzell wrote:

> James,
>
> It's been a while since I looked at the google maps stuff so I don't  
> recall... what do you actually render to the page? If memory serves,  
> you only need to output stuff that can be generated by the standard  
> brushes (divs and JS or something, right?) and you don't need to put  
> content inside it.
>
> I have no memory of whether there is anything that requires a  
> component to keep state but it doesn't *seem* at first glance to me  
> like something that needs to be a brush either. I don't mean to  
> suggest you're wrong since you've obviously gone through the  
> exercise and I haven't but there's quite a bit of debate now and  
> then over when to use brushes. I'm just wondering whether you  
> considered a renderable object (a Painter in 2.9) as an option or  
> just component/brush. And if you ruled out the third option, is  
> there a particular reason you think a brush is more appropriate?
>
> Julian
>
> On Thu, Jun 18, 2009 at 4:00 PM, James Foster  
> <Smalltalk at jgfoster.net> wrote:
> Mariano,
>
> I'll be interested to see how this comes out. As I mentioned  
> earlier, I started with a component and switched to a brush. I came  
> to view the GoogleMap as a browser widget, something like a listbox,  
> where you give it some data and let it draw itself. Yes, you can  
> configure callbacks, but that isn't really different from other  
> brushes. What sort of 'state' do you envision keeping with the map?  
> Might that be better in a domain-specific component that wraps a  
> map? I was able to implement over 40 examples and have not yet found  
> a need to get more complex.
>
> James
>
> On Jun 18, 2009, at 2:58 PM, Mariano Montone wrote:
>
>> Thanks Julian. I think a component will be ok.
>>
>> Mariano
>>
>> On Thu, Jun 18, 2009 at 1:22 PM, Julian Fitzell  
>> <jfitzell at gmail.com> wrote:
>> Hi Mariano,
>>
>> Off the top of my head, if I were implementing a google maps  
>> package, I would do it as a component or a painter (see below).  
>> Brushes certainly aren't intended to be kept around so if you have  
>> state to persist between requests that's not the way to go.
>>
>> There are people who like implementing everything as brushes but  
>> the main functionality of brushes is that they can be selected in  
>> arbitrary orders to nest content within each other, e.g.:
>>
>> html div: [ html span: [ html paragraph: 'foo' ] ].
>>
>> Unless you plan to do be able to do:
>>
>> html div: [ html googleMap: [ html paragraph: 'foo' ] ]
>>
>> (i.e. unless the thing you are creating allows content to be put  
>> inside it) I don't think there's much advantage in making your own  
>> brush. (The other reason to consider using brushes of course is  
>> that they have more direct access to the document).
>>
>> Even if you don't need the benefits of components (see http://blog.fitzell.ca/2009/05/when-to-use-seaside-component.html 
>>  ), you can just create a renderable object by implementing  
>> #renderOn: and do:
>>
>> html render: (GoogleMaps new configSomeStuff; yourself)
>>
>> This process is made much clearer in 2.9 where you can subclass  
>> WAPainter, implement #rendererClass to control what kind of  
>> renderer you get passed (you might possibly implement the google  
>> maps thing *using* one or more custom brushes and have your own  
>> renderer for them), and implement #renderContentOn: as you would  
>> for a component.
>>
>> Hopefully that makes things clearer and not muddier. :)
>>
>> Julian
>>
>> On Thu, Jun 18, 2009 at 5:51 AM, Mariano Montone <marianomontone at gmail.com 
>> > wrote:
>> Hello!,
>>            I'm implementing an API for rendering Google Maps. I've  
>> decided to implement it as a brush. That's because I'm just  
>> generating javascript code. But now I have a problem: when adding  
>> support for callbacks, I need to hold some state; for example, the  
>> map the callback refers to. But I think brushes are not meant to  
>> hold state, that is something left for the components mechanism,  
>> isn't it? So I would like to know what would be the correct way of  
>> implementing it in the framework. Should I implement maps as  
>> components, or should I add state to my brushes; I may hold a state  
>> in the callback block too, but I don't think that's good.
>>
>> Thanks!
>>
>> Mariano
>>
>>
>>
>> _______________________________________________
>> seaside mailing list
>> seaside at lists.squeakfoundation.org
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>>
>>
>>
>> _______________________________________________
>> seaside mailing list
>> seaside at lists.squeakfoundation.org
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>>
>>
>> _______________________________________________
>> seaside mailing list
>> seaside at lists.squeakfoundation.org
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
>
> _______________________________________________
> seaside mailing list
> seaside at lists.squeakfoundation.org
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
>
> _______________________________________________
> seaside mailing list
> seaside at lists.squeakfoundation.org
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside



More information about the seaside mailing list