<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2017-09-29 18:12 GMT+02:00 H. Hirzel <span dir="ltr"><<a href="mailto:hannes.hirzel@gmail.com" target="_blank">hannes.hirzel@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">For the question<br>
<span class="gmail-">   "Do we really want to do that, have a stream of Morphs (or other<br>
graphical objects)?"<br>
</span>I think an interesting article to read is<br>
<a href="https://smalltalkrenaissance.wordpress.com/2015/06/29/silk-is-just-too-flexible/" rel="noreferrer" target="_blank">https://smalltalkrenaissance.<wbr>wordpress.com/2015/06/29/silk-<wbr>is-just-too-flexible/</a><br>
<br>
A hierarchy of morphs (elements) may be regarded as well as a stream.<br>
<br>
<br></blockquote><div><br></div><div>Sorry, my question was bad. If streaming consist of a simple do: loop, an Encoder isn't really necessary.<br></div><div>The right question is why would we need a generic stream transform pattern like Encoder is?</div><div><br></div><div>The canvas other than PostscriptCanvas don't use the target, they are sinks.</div><div>So there's no reason to use an Encoder pattern here.</div><div><br></div><div>But PostscriptCanvas uses a different filterSelector.</div><div>That means that we can differentiate drawing commands for some specific morph.</div><div>And indeed, a BookMorph has a specific way to render on a PostscriptCanvas: it will render all the pages.</div><div><br></div><div>And a DSCPostscriptCanvas yet another: it will produces those Document Structuring Conventions</div><div>which are meta informations on contents such as chapters, page numbers etc... encoded after double comments '%%'.<br></div><div><br></div><div>Thus using an Encoder permits a differentiation in rendering.</div><br><div>But I'm not at all convinced by this Encoder usage. It's not composable.</div><div>What if I embed 1 or several BookMorph into another Morph? Won't the rendering and DSC be kind of broken?</div><div><br></div><div>What if we want to render this BookMorph with a specific target layout? Won't we need to recompose?</div><div>Composing is more than rendering, so a Canvas would not be the right abstraction...<br></div><div><br></div><div>Rendering the whole book contents is a different operation specific to a BookMorph.<br><div>It's not be a problem to have a specific menu/halo for this specific operation.</div><div>This specific rendering is not composable. And maybe not the Canvas responsibility.<br></div><div>So I don't see the point in using this Encoder pattern here.<br></div></div><div class="gmail_quote"><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Canvas has a useful class comment [3]<br>
<br>
It could be that<br>
    NullEncoder<br>
        FlattenEncoder<br>
are just helper classes to structure the code.<br>
<br>
<br>
<br>
FlattenEncoder has the comment<br>
<span class="gmail-"><br>
    "The simplest possible encoding:  leave the objects as is."<br>
<br>
<br>
</span>Maybe the simplest thing for the class comment of NullEncoder is just<br>
to refer to the class comment of FlattenEncoder and Canvas.<br>
<br>
[3] Class comment of 'Canvas'<br>
A canvas is a two-dimensional medium on which morphs are drawn in a<br>
device-independent manner. Canvases keep track of the origin and<br>
clipping rectangle, as well as the underlying drawing medium (such as<br>
a window, pixmap, or postscript script).<br>
<br>
Subclasses must implement (at least) the following methods:<br>
        * Drawing:<br>
                #fillOval:color:borderWidth:<wbr>borderColor:<br>
                #frameAndFillRectangle:<wbr>fillColor:borderWidth:<wbr>borderColor:<br>
                #drawPolygon:color:<wbr>borderWidth:borderColor:<br>
                #image:at:sourceRect:rule:<br>
                #stencil:at:sourceRect:rule:<br>
                #line:to:width:color:<br>
                #paragraph:bounds:color:<br>
                #text:bounds:font:color:<br>
        * Support<br>
                #clipBy:during:<br>
                #translateBy:during:<br>
                #translateBy:clippingTo:<wbr>during:<br>
                #transformBy:clippingTo:<wbr>during:<br>
<div class="gmail-HOEnZb"><div class="gmail-h5"><br>
On 9/29/17, Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@<wbr>gmail.com</a>> wrote:<br>
> The target inst. var. is used exclusively by the PostscriptCanvas.<br>
> And IMO it is a classical mistake of inheritance versus composition.<br>
><br>
> A PostScript canvas will have to encode the sequence of graphics<br>
> instruction into a stream of PostScript instructions written into a<br>
> PostScript file.<br>
> For this purpose, it has a target PostscriptEncoder, which is itself an<br>
> encoder already.<br>
><br>
> An Encoder implements a processing unit that transform a stream by using a<br>
> kind of generic double dispatching.<br>
><br>
> Why the PostscriptCanvas has to be considered as an Encoder itself is very<br>
> suspect, unless we ask<br>
><br>
>     canvas write: aMorph.<br>
><br>
> Do we really want to do that, have a stream of Morphs (or other graphical<br>
> objects)?<br>
><br>
> 2017-09-29 17:33 GMT+02:00 H. Hirzel <<a href="mailto:hannes.hirzel@gmail.com">hannes.hirzel@gmail.com</a>>:<br>
><br>
>> Tobias<br>
>><br>
>> You write that NullEncoder and subclasses could be summarized as<br>
>><br>
>>     "Put objects onto another thing with encoding inbetween".<br>
>><br>
>> which I think is helpful for understanding.<br>
>><br>
>> Maybe we consider for the class comment of NullEncoder<br>
>><br>
>>     "Put objects onto another thing with encoding/transformation<br>
>> inbetween".<br>
>><br>
>><br>
>> But also note that this is not only related to PostscriptCanvas as we<br>
>> have<br>
>><br>
>><br>
>> NullEncoder<br>
>>     FlattenEncoder<br>
>>          Canvas<br>
>>              FormCanvas<br>
>><br>
>> FormCanvas has some nice usage examples.<br>
>><br>
>> #test1 is<br>
>><br>
>> test1<br>
>>         "FormCanvas test1"<br>
>><br>
>>         | canvas |<br>
>>         canvas := FormCanvas extent: 200@200.<br>
>>         canvas fillColor: (Color black).<br>
>>         canvas line: 10@10 to: 50@30 width: 1 color: (Color red).<br>
>>         canvas frameRectangle: ((20@20) corner: (120@120)) width: 4<br>
>> color:<br>
>> (Color green).<br>
>>         canvas point: 100@100 color: (Color black).<br>
>>         canvas drawString: 'Hello, World!' at: 40@40 font: nil color:<br>
>> (Color cyan).<br>
>>         canvas fillRectangle: ((10@80) corner: (31@121)) color: (Color<br>
>> magenta).<br>
>>         canvas fillOval: ((10@80) corner: (31@121)) color: (Color cyan).<br>
>>         canvas frameOval: ((40@80) corner: (61@121)) color: (Color blue).<br>
>>         canvas frameOval: ((70@80) corner: (91@121)) width: 3 color:<br>
>> (Color<br>
>> red alpha: 0.2).<br>
>>         canvas fillRectangle: ((130@30) corner: (170@80)) color: (Color<br>
>> lightYellow).<br>
>>         canvas showAt: 0@0.<br>
>><br>
>><br>
>> This works fine in an MVC project<br>
>><br>
>> --Hannes<br>
>><br>
>> On 9/29/17, Tobias Pape <<a href="mailto:Das.Linux@gmx.de">Das.Linux@gmx.de</a>> wrote:<br>
>> > Hi Hannes<br>
>> ><br>
>> >> On 29.09.2017, at 15:21, H. Hirzel <<a href="mailto:hannes.hirzel@gmail.com">hannes.hirzel@gmail.com</a>> wrote:<br>
>> >><br>
>> >> And there is no 'FlattenEncoder' in Pharo 6<br>
>> ><br>
>> >><br>
>> >><br>
>> >> On 9/29/17, H. Hirzel <<a href="mailto:hannes.hirzel@gmail.com">hannes.hirzel@gmail.com</a>> wrote:<br>
>> >>> We have<br>
>> >>><br>
>> >>> NullEncoder<br>
>> >>>    FlattenEncoder<br>
>> >>>        Canvas<br>
>> ><br>
>> > So here's the Thing: I looked in 3.8, and there's:<br>
>> ><br>
>> > Object<br>
>> >  NullEncoder          - Morphic-Postscript Filters<br>
>> >   FlattenEncoder      - Morphic-Postscript Filters<br>
>> >    Canvas             - Morphic-Support<br>
>> >     PostscriptCanvas  - Morphic-Postscript Canvases<br>
>> ><br>
>> > But also note that they all have a callback via class>>filterSelector:<br>
>> ><br>
>> > NullEncoder>>filterSelector           ^ #writeOnFilterStream:<br>
>> > FlattenEncoder>>filterSelector                ^ #flattenOnStream:<br>
>> > Canvas>>filterSelector                        ^ #drawOnCanvas:<br>
>> > PostscriptCanvas>><wbr>filterSelector      ^ #fullDrawPostscriptOn:<br>
>> ><br>
>> > I think part of that happened because this all shared common<br>
>> functionallity,<br>
>> > In the sense that all those things "Put objects onto another thing with<br>
>> > encoding inbetween".<br>
>> > Thinking of things like a n-dimensonal stream or so…<br>
>> ><br>
>> > I checked and It is like that even in Squeak 3.6, 3.0, 2.8.<br>
>> > Squeak 1.13 does not have any of those, and it has no Morphic.<br>
>> ><br>
>> > Self Morphic does not have such Encoders, tho.<br>
>> ><br>
>> > In the end it all seems to be related to the PostScript Canvas, which,<br>
>> > understandably, has to have access to certain objects and actually has<br>
>> > to<br>
>> > "encode" them into a file.<br>
>> ><br>
>> > Best regards<br>
>> >       -Tobias<br>
>> ><br>
>> ><br>
>> ><br>
>> >>><br>
>> >>> there are no direct users of NullEncoder and FlattenEncoder.<br>
>> >>><br>
>> >>> FlattenEncoder class comment is just<br>
>> >>><br>
>> >>>    'The simplest possible encoding:  leave the objects as is.'<br>
>> >>><br>
>> >>> a bit terse. Does not really say what the issue is about.<br>
>> >>><br>
>> >>><br>
>> >>><br>
>> >>> On 9/29/17, H. Hirzel <<a href="mailto:hannes.hirzel@gmail.com">hannes.hirzel@gmail.com</a>> wrote:<br>
>> >>>> P.S.<br>
>> >>>><br>
>> >>>> There is no NullEncoder in Pharo.<br>
>> >>>><br>
>> >>>> The class Canvas is not in a package 'Morphic-Support' but in a<br>
>> >>>> package 'Graphics-Canvas'.<br>
>> >>>><br>
>> >>>> There is no 'Graphics-Canvas' package in Squeak. [2]<br>
>> >>>><br>
>> >>>> Seems like a good idea to move Canvas and subclasses to a package<br>
>> >>>> 'Graphics-Canvas' as well.<br>
>> >>>><br>
>> >>>><br>
>> >>>> [2] Graphics package in Squeak 6.0a-17405<br>
>> >>>><br>
>> >>>> Graphics-Display Objects<br>
>> >>>> Graphics-External-Ffenestri<br>
>> >>>> Graphics-Files<br>
>> >>>> Graphics-Fonts<br>
>> >>>> Graphics-Primitives<br>
>> >>>> Graphics-Text<br>
>> >>>> Graphics-Transformations<br>
>> >>>> GraphicsTests-Files<br>
>> >>>> GraphicsTests-Primitives<br>
>> >>>> GraphicsTests-Text<br>
>> >>>><br>
>> >>>> On 9/29/17, H. Hirzel <<a href="mailto:hannes.hirzel@gmail.com">hannes.hirzel@gmail.com</a>> wrote:<br>
>> >>>>> Hello<br>
>> >>>>><br>
>> >>>>> NullEncoder is subclass of object ([1] for full hierachy). It is a<br>
>> >>>>> superclass of Canvas.<br>
>> >>>>><br>
>> >>>>> What is the function of NullEncoder. No class comment so far?<br>
>> >>>>><br>
>> >>>>> Regards<br>
>> >>>>> Hannes<br>
>> >>>>><br>
>> >>>>><br>
>> >>>>> ------------------------------<wbr>------------------------------<br>
>> ------------------------------<wbr>------------------------------<wbr>-------<br>
>> >>>>><br>
>> >>>>> [1] NullEncoder printHierarchy '<br>
>> >>>>> ProtoObject #()<br>
>> >>>>>   Object #()<br>
>> >>>>>           NullEncoder #(''target'' ''filterSelector'')<br>
>> >>>>>                   FlattenEncoder #()<br>
>> >>>>>                           ByteEncoder #()<br>
>> >>>>>                                   PrintableEncoder #()<br>
>> >>>>>                                           PostscriptEncoder #()<br>
>> >>>>><br>
>>  PostscriptEncoderToDisk #()<br>
>> >>>>>                                           PropertyListEncoder #()<br>
>> >>>>>                           Canvas #()<br>
>> >>>>>                                   ColorMappingCanvas<br>
>> >>>>> #(''myCanvas'')<br>
>> >>>>>                                           AlphaBlendingCanvas<br>
>> #(''alpha'')<br>
>> >>>>>                                           ShadowDrawingCanvas<br>
>> #(''shadowColor'')<br>
>> >>>>>                                   FormCanvas #(''origin''<br>
>> ''clipRect'' ''form'' ''port''<br>
>> >>>>> ''shadowColor'')<br>
>> >>>>>                                           BalloonCanvas<br>
>> #(''transform'' ''colorTransform'' ''engine''<br>
>> >>>>> ''aaLevel'' ''deferred'')<br>
>> >>>>>                                           BlueFormCanvas #()<br>
>> >>>>>                                           ColorPatchCanvas<br>
>> #(''stopMorph'' ''foundMorph'' ''doStop'')<br>
>> >>>>>                                           MultiResolutionCanvas<br>
>> #(''deferredMorphs'')<br>
>> >>>>>                                   PluggableCanvas #()<br>
>> >>>>>                                           BufferedCanvas<br>
>> #(''remote'' ''previousVersion'' ''lastTick''<br>
>> >>>>> ''dirtyRect'' ''mirrorOfScreen'')<br>
>> >>>>>                                           CachingCanvas<br>
>> #(''cacheCanvas'' ''mainCanvas'')<br>
>> >>>>>                                           ClippingCanvas<br>
>> #(''canvas'' ''clipRect'')<br>
>> >>>>>                                           MultiCanvas<br>
>> >>>>> #(''canvases''<br>
>> ''extent'' ''depth'')<br>
>> >>>>>                                           NullCanvas #()<br>
>> >>>>>                                   PostscriptCanvas #(''origin''<br>
>> ''clipRect'' ''currentColor''<br>
>> >>>>> ''shadowColor'' ''currentFont'' ''morphLevel'' ''gstateStack''<br>
>> >>>>> ''fontMap'' ''usedFonts'' ''psBounds'' ''topLevelMorph''<br>
>> >>>>> ''initialScale'' ''savedMorphExtent'' ''currentTransformation''<br>
>> >>>>> ''printSpecs'' ''pages'')<br>
>> >>>>>                                           DSCPostscriptCanvas #()<br>
>> >>>>><br>
>>  DSCPostscriptCanvasToDisk #()<br>
>> >>>>>                                           EPSCanvas #()<br>
>> >>>>>                                   RemoteCanvas #(''innerClipRect''<br>
>> ''outerClipRect'' ''transform''<br>
>> >>>>> ''connection'' ''shadowColor'')'<br>
>> >>>>><br>
>> >>>><br>
>> >>><br>
>> >><br>
>> ><br>
>> ><br>
>> ><br>
>><br>
>><br>
><br>
<br>
</div></div></blockquote></div></div><br></div></div>