[Seaside] Brushes and state

Cédrick Béler cdrick65 at gmail.com
Fri Jun 19 08:54:06 UTC 2009


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


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


More information about the seaside mailing list