I&#39;m not sure exactly what the issue with #children is, but I know (or at least think I know) that what I posted should work (conceptually) in 2.9. It&#39;s possible that stuff isn&#39;t quite factored correctly in 2.8 somehow... or it&#39;s possible the code I wrote in the email just wasn&#39;t quite right.<div>
<br></div><div>There&#39;s definitely some extra grayness in this case because what you&#39;re rendering is *largely* a div, even though it&#39;s more than that and I can see your point about tag attributes. One thing that comes to mind here (don&#39;t try this at home, kids, it may yet be a terrible idea) is to give GoogleMap a block that gets passed the div brush during rendering. Would look something like:</div>
<div><br></div><div>renderContentOn: html</div><div>  html render:</div><div>    (GoogleMap new</div><div>      <span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px; border-collapse: collapse; ">setCenter: 45.5267 @ -122.8390 zoom: 11;</span></div>
<span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px; border-collapse: collapse; ">      enableGoogleBar;<br>      addType: GMapType physical;<br>      addControl: GControl largeMapControl;</span><div>
<span class="Apple-style-span" style="font-size: 13px; "></span><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">      divBlock: [ :div | div class: &#39;foo&#39;; style: &#39;bar&#39; ])</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">And then GoogleMap would have</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">renderContentOn: html</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">  div := html div;</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">  div</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">    doSomeStuff;</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">    someMoreStuff.</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">  self divBlock value: div.</span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">  div with: [&quot;you probably don&#39;t need this since your div is empty&quot;]</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;"><br></span></font></div><div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">Now I don&#39;t know that this is a good idea nor am I even 100% sure it works but it seems like it should and *could* be a solution to this problem. The problem is of course no different than any other component that has a top-level div that somebody might want to customize the attributes of so it&#39;s not unique to your case. Of course, somebody could also just subclass GoogleMap to do that kind of custom styling (as long as it is well-factored) and that may actually be the best option.</span></font></div>
<div><font class="Apple-style-span" face="arial, sans-serif"><span class="Apple-style-span" style="border-collapse: collapse;">     <br></span></font><div>I&#39;m not sure that brushes literally need to only represent HTML spec tags, though TagBrushes certainly lean that way and it may be a good principle to keep an mind as a starting point.</div>
<div><br></div><div>If you want to provide a walkback on the #children problem I can try to see if it is solvable in 2.8.</div><div><br></div><div>Julian</div><div><br><div class="gmail_quote">On Mon, Jun 22, 2009 at 3:44 PM, James Foster <span dir="ltr">&lt;<a href="mailto:Smalltalk@jgfoster.net">Smalltalk@jgfoster.net</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div style="word-wrap:break-word">Julian,<div><br></div><div>I&#39;ve gotten things going with GoogleMap as something other than a Brush or Component (see GoogleMaps-jgf.22.mcz in <span style="font-family:Geneva, Arial, Helvetica, sans-serif;font-size:11px;line-height:12px"><a href="http://seaside.gemstone.com/ss/GoogleMaps.html" title="static project url" style="color:rgb(54, 29, 132);text-decoration:none" target="_blank">http://seaside.gemstone.com/ss/GoogleMaps.html</a>). As an exercise in rendering a generic object, it was certainly useful (I knew of the capability, but hadn&#39;t ever done it). My immediate reaction is that it is cleaner in that it _uses_ a brush rather than _is_ a brush. On the other hand, there are some complications. </span></div>
<div><font face="Geneva, Arial, Helvetica, sans-serif" size="3"><span style="font-size:11px;line-height:12px"><br></span></font></div><div><span style="font-family:Geneva, Arial, Helvetica, sans-serif;font-size:11px;line-height:12px">With the Brush implementation, there are a number of inherited &quot;features&quot; that just come along. Specifically, I now need to cache any tag-related attributes that the programmer might want to set (such as ID, CLASS, etc.) and put them out. If there were a need for a full implementation, then this could get awkward (for example, I didn&#39;t do STYLE, and I don&#39;t support generic attributes).</span></div>
<div><font face="Geneva, Arial, Helvetica, sans-serif" size="3"><span style="font-size:11px;line-height:12px"><br></span></font></div><div><font face="Geneva, Arial, Helvetica, sans-serif" size="3"><span style="font-size:11px;line-height:12px">Also, when I create my own canvas in #&#39;renderOn:&#39; (as suggested by your code just below), callbacks fail because the implementation of #&#39;children&#39; is incomplete. My work-around was to just use the passed-in Renderer, assuming that it supports HTML. </span></font></div>
<div><font face="Geneva, Arial, Helvetica, sans-serif" size="3"><span style="font-size:11px;line-height:12px"><br></span></font></div><div><font face="Geneva, Arial, Helvetica, sans-serif" size="3"><span style="font-size:11px;line-height:12px">If the design philosophy is that Brushes represent only things defined in the official HTML spec (which seems reasonable), then the new approach is good enough. I do like this better than making a full Component (which seems heavy-weight).</span></font></div>
<div><font face="Geneva, Arial, Helvetica, sans-serif" size="3"><span style="font-size:11px;line-height:12px"><br></span></font></div><div><font face="Geneva, Arial, Helvetica, sans-serif" size="3"><span style="font-size:11px;line-height:12px">Comments?</span></font></div>
<div><br></div><font color="#888888"><div>James</div></font><div><div></div><div class="h5"><div><br><div><div>On Jun 19, 2009, at 7:51 PM, Julian Fitzell wrote:</div><br><blockquote type="cite">That should provide a good comparison.<div>
<br></div><div>Looking at the 2.9 code now I realize it may be hard for you to simply lift the code because of the refactoring in the way walking the component tree happens.</div> <div><br></div><div>As a starting point for 2.8, try making GoogleMap subclass Object and implement something like:</div>
<div><br></div><div>renderOn: aRenderer</div><div><div>  |html|</div><div>  html := WAHtmlCanvas</div> <div>    context: aRenderer context</div><div>    callbacks: (aRenderer context callbacksFor: self).</div><div>  self renderContentOn: html.</div>
<div><br></div><div>I think you should then be able to implement #renderContentOn: to output your content and allow a GoogleMap to be passed to the #render: method.</div> <div><br></div><div>That code is untested, just typed into gmail, but it should be something like that. :)</div>
<div><br></div><div>Julian</div><br><div class="gmail_quote">On Fri, Jun 19, 2009 at 4:43 PM, James Foster <span dir="ltr">&lt;<a href="mailto:Smalltalk@jgfoster.net" target="_blank">Smalltalk@jgfoster.net</a>&gt;</span> wrote:<br>
 <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Julian,<div><br></div><div>I think the only think I&#39;m equipped to give even a weak opinion on is that as I was doing this some months ago I found a Brush to be more natural to use (as a client) than a Canvas. As to the relative merits of Painter and Renderer, I&#39;m just not sufficiently informed to venture an educated opinion (though that isn&#39;t usually an impediment ;-). </div>
 <div><br></div><div>I like your point that a Brush can be embedded in another Brush and this is a feature that the GoogleMap does not need. Given that sending #with: to a GoogleMap does not make sense, I&#39;ll agree that making it a Brush is a bit awkward. Also, there is a sense in which subclassing from WADivTag comes back to the question of delegation vs. inheritance, and in principal I&#39;d prefer delegation. </div>
 <div><br></div><div>In an effort to contribute more intelligently to this discussion, I&#39;d like to try refactoring my library using a Painter. I&#39;ll fire up a Seaside 2.9 environment and look at WAPainter with an eye toward what would be required to refactor my GoogleMap in a Seaside 2.8 environment. </div>
 <div><br></div><font color="#888888"><div>James</div><div><br></div></font><div><div><div><div></div><div><div>On Jun 19, 2009, at 12:20 PM, Julian Fitzell wrote:</div><br></div></div><blockquote type="cite"><div> <div></div>
<div><div class="gmail_quote">On Fri, Jun 19, 2009 at 10:50 AM, James Foster <span dir="ltr">&lt;<a href="mailto:Smalltalk@jgfoster.net" target="_blank">Smalltalk@jgfoster.net</a>&gt;</span> wrote:<br> <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 <div style="word-wrap:break-word">Julian,<div><br></div><div>As you were going through this my thought was eventually expressed when you said that the painter approach &quot;works essentially the same as the brush&quot; approach. And Yes, my updateRoot: code was simply an extension to WAComponent that adds some JavaScript. Switching it to a class-side method on GoogleMaps as you describe would be equivalent and perhaps more obvious and less intrusive. </div>
 <div><br></div><div>The part I&#39;m not yet following or seeing much value in is the idea that using a different renderer would be desirable. I don&#39;t see much point of rendering a GoogleMap on anything other than an HTML canvas. Or are you envisioning two renderers (HTML for the GoogleMap thing and something else for the rest)? At the moment, my understanding of the alternate renderers is so shallow that I don&#39;t see the use/value. For my purposes, at least, I&#39;ll probably leave my implementation as a Brush subclass since it seems to work for all use cases I understand. Which is not to say that I mind the discussion!</div>
 </div></blockquote><div><br></div><div>James,</div><div><br></div><div>The discussion is clarifying for me as well so let&#39;s carry on... :)</div><div><br></div><div>First, I do think your design would be improved slightly by putting that method on the class side of GoogleMap.</div>
 <div><br></div><div>The idea of having different Renderers is that, for example, somebody might eventually decide they&#39;d really like to have templates in Seaside and that would probably be implemented as a different Renderer. Or maybe they want to embed a google map in a Component that is using the RSS Renderer (actually, that Renderer still uses Brushes, so it may not be the best example). As I said, this is relatively theoretical at the moment given the lack of other Renderers but I&#39;m interested in it from the architectural angle.</div>
 <div><br></div><div>I believe (and this is where I may be wrong) that an implementation using Brushes is (slightly) less flexible and, while there are things that would be easier using Brushes, I don&#39;t see that this problem does any of those things.</div>
 <div><br></div><div>Or to look at it another way, just as you say that GoogleMap doesn&#39;t need to *be* a Component but can be rather *used by* a Component, I don&#39;t think it needs to *be* a Brush but can instead *use* a Brush; there&#39;s nothing you need to output to the Document that can&#39;t easily be done with the existing Brushes.</div>
 <div><br></div><div>So you might end up with</div><div><br></div><div>MyComponent</div><div>  (uses)</div><div>any Renderer</div><div>  (to render a)</div><div>GoogleMap (a Painter)</div><div>  (which uses its)</div><div>
 HtmlCanvas (a Renderer)</div><div>  (to get a)</div><div>DivTag (a Brush)</div><div>  (which writes to)</div><div>HtmlDocument (a Document)</div><div>  (which writes to)</div><div>Stream</div><div><br></div><div>When I say it &quot;works essentially the same as the brush&quot;, what I mean is, the Painter implementation is equally convenient to use and no harder to implement but provides added flexibility. It also requires no class method extensions and means you can leverage WAScriptTag instead of duplicating stuff to make sure the CDATA is added and so on. Since I can&#39;t (yet) see an advantage to the Brush implementation, my suggestion is that the Painter implementation is &quot;more correct&quot; architecturally.</div>
 <div><br></div><div>I still think &quot;uses a Brush&quot; (actually two) is a clearer relationship for this than &quot;is a Brush&quot; even in 2.8, but without Painter there&#39;s really no added benefit (though you could easily duplicate the very limited amount of functionality Painter has in its #renderOn: method and you&#39;d be in the same shape as 2.9).</div>
 <div><br></div><div>So the architectural question for me comes down to (sorry for the long message), is there an additional benefit to doing it as a Brush over a Painter that I&#39;m missing?</div><div><br></div><div>Julian</div>
 </div></div></div><div> _______________________________________________<br>seaside mailing list<br><a href="mailto:seaside@lists.squeakfoundation.org" target="_blank">seaside@lists.squeakfoundation.org</a><br> <a href="http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside" target="_blank">http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside</a><br>
</div></blockquote></div><br></div></div><br>_______________________________________________<br> seaside mailing list<br> <a href="mailto:seaside@lists.squeakfoundation.org" target="_blank">seaside@lists.squeakfoundation.org</a><br>
 <a href="http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside" target="_blank">http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside</a><br> <br></blockquote></div><br></div> _______________________________________________<br>
seaside mailing list<br><a href="mailto:seaside@lists.squeakfoundation.org" target="_blank">seaside@lists.squeakfoundation.org</a><br><a href="http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside" target="_blank">http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside</a><br>
</blockquote></div><br></div></div></div></div><br>_______________________________________________<br>
seaside mailing list<br>
<a href="mailto:seaside@lists.squeakfoundation.org">seaside@lists.squeakfoundation.org</a><br>
<a href="http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside" target="_blank">http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside</a><br>
<br></blockquote></div><br></div></div>