[Seaside] Brushes and state

James Foster Smalltalk at JGFoster.net
Fri Jun 19 14:16:32 UTC 2009


On Jun 19, 2009, at 1:54 AM, Cédrick Béler wrote:

> Thanks all for the interesting experience feedback :)
> I think if implemented as a painter, this thread could br turned as a
> nice example/tutorial on how to use painter (instead of brush or
> compoenent).
>
> Just a question. If you want to embed a map with live points, overlay,
> etc...  say you want to dynamically follow a path... Would you use
> state to keep this information (and therefore component) or would you
> build a component that embed the painter ?
>
> Thanks

My preference (from where I am right now; as you can see I'm learning  
more every day) would be treat the map as a brush and have it inform  
your component of map events and keep the state in your component or  
(even better) in your domain objects. In general I'd try to use  
delegation rather than inheritance.

James
>
> 2009/6/19 Julian Fitzell <jfitzell at gmail.com>:
>> So, with the need to update the root, I think this would work  
>> equally well
>> as a simple renderable object in 2.8 but it wouldn't really be be  
>> much
>> better than a component or brush.
>> With a 2.9 Painter, you can implement #updateRoot: on the
>> Painter subclass itself so the map object would be able to  
>> encapsulate all of that. This does require, as you point out, that  
>> the Painter be added to #children, of course, but I think that's  
>> better than having to implement your own root updating behaviour  
>> and not unexpected for the user.
>> Your renderContentOn: would look basically the same as your version  
>> with
>> either a painter or a renderable object:
>> MyComponent>>#renderContentOn: html
>>        html render: (GoogleMap new
>>                class: 'myMap';
>>                setCenter: 45.5267 @ -122.8390 zoom: 11;
>>                "..."
>>                yourself)
>>
>> So I think the result is slightly better with a Painter in the  
>> sense of
>> implementing #children, rather then update root behaviour.
>> The other advantage is more theoretical and that is that a painter  
>> is not
>> dependent on the encapsulating component using Canvas as its  
>> renderer. I say
>> this is pretty theoretical because the only other renderer right  
>> now is the
>> RSS one. :) From an architectural point of view, though, components  
>> are able
>> to use any renderer they want and if they're using one that doesn't  
>> support
>> your brush, well they couldn't easily use your implementation.
>> This is all pretty subtle. Thus the debate. :)
>> Julian
>> On Thu, Jun 18, 2009 at 5:49 PM, James Foster  
>> <Smalltalk at jgfoster.net>
>> wrote:
>>>
>>> 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
>>>
>>> _______________________________________________
>>> 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
>>
>>
>
>
>
> -- 
> Cédrick
> _______________________________________________
> seaside mailing list
> seaside at lists.squeakfoundation.org
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>



More information about the seaside mailing list