Archive for HTML5

retrofitting Squeak Morphic for the web

Posted in Appsterdam, consulting, Context, Smalltalk, Spoon, SqueakJS with tags , , , , , , , , on 30 June 2017 by Craig Latta

Google ChromeScreenSnapz022

Last time, we explored a way to improve SqueakJS UI responsiveness by replacing Squeak Morphic entirely, with morphic.js. Now let’s look at a technique that reuses all the Squeak Morphic code we already have.

many worlds, many canvases

Traditionally, Squeak Morphic has a single “world” where morphs draw themselves. To be a coherent GUI, Morphic must provide all the top-level effects we’ve come to expect, like dragging windows and redrawing them in their new positions, and redrawing occluded windows when they are brought to the top. Today, this comes at an acceptable but noticeable cost. Until WebAssembly changes the equation again, we want to do all we can to shift UI work from Squeak Morphic to the HTML5 environment hosting it. This will also make the experience of using SqueakJS components more consistent with that of the other elements on the page.

Just as we created an HTML5 canvas for morphic.js to use in the last post, we can do so for individual morphs. This means we’ll need a new Canvas subclass, called HTML5FormCanvas:

Object
  ...
    Canvas
       FormCanvas
         HTML5FormCanvas

An HTML5FormCanvas draws onto a Form, as instances of its parent class do, but instead of flushing damage rectangle from the Form onto the Display, it flushes them to an HTML5 canvas. This is enabled by a primitive I added to the SqueakJS virtual machine, which reuses the normal canvas drawing code path.

Accompanying HTML5FormCanvas are new subclasses of PasteUpMorph and WorldState:

Object
  Morph
    ...
      PasteUpMorph
        HTML5PasteUpMorph

Object
  WorldState
    HTML5WorldState

HTML5PasteUpMorph provides a message interface for other Smalltalk objects to create HTML5 worlds, and access the HMTL5FormCanvas of each world and the underlying HTML5 canvas DOM element. An HTML5WorldState works on behalf of an HTML5PasteUpMorph, to establish event handlers for the HTML5 canvas (such as for keyboard and mouse events).

HTML5 Morphic in action

You don’t need to know all of that just to create an HTML5 Morphic world. You only need to know about HTML5PasteUpMorph. In particular, (HTML5PasteUpMorph class)>>newWorld. All of the traditional Squeak Morphic tools can use HTML5PasteUpMorph as a drop-in replacement for the usual PasteUpMorph class.

There are two examples of single-window Morphic worlds in the current Caffeine release, for a workspace and classes browser. I consider these two tools to be the “hello world” exercise for UI framework experimentation, since you can use them to implement all the other tools.

We get an immediate benefit from the web browser handling window movement and clipping for us, with opaque window moves rendering at 60+ frames per second. We can also interleave Squeak Morphic windows with other DOM elements on the page, which enables a more natural workflow when creating hybrid webpages. We can also style our Squeak Morphic windows with CSS, as we would any other DOM element, since as far as the web browser is concerned they are just HTML5 canvases. This makes effects like the rounded corners and window buttons trays that Caffeine uses very easy.

Now, we have flexible access to the traditional Morphic tools while we progress with adapting them to new worlds like morphic.js. What shall we build next?

SqueakJS changes its world with ThisWebpage

Posted in Appsterdam, consulting, Context, Naiad, Smalltalk, Spoon with tags , , , , , , , , , , , , on 28 October 2016 by Craig Latta

a new platform

Since becoming a virtual-machine-based app, Smalltalk has integrated well with other operating systems, providing the illusion of a consistent unified platform. With the ascendancy of JavaScript, the common execution environment provided by web browsers is effectively another host operating system. Smalltalk runs there too now, thanks to Bert Freudenberg’s SqueakJS. So in addition to macOS, Windows, and Linux, we now have the Web host platform.

While all platforms expose some of their functionality to apps through system calls, the Web exposes much more, through its Document Object Model API (DOM). This gives Smalltalk a special opportunity to enable livecoded apps on this platform. It also means that Smalltalk can interoperate more extensively with other Web platform apps, and participate in the ecosystem of JavaScript frameworks, both as a consumer and a producer.

to JavaScript and back

The part of SqueakJS which enables this is its bidirectional JavaScript bridge. This is implemented by class JSObjectProxy, and some special support in the SqueakJS virtual machine. One may set Smalltalk variables to JavaScript objects, send messages to JavaScript objects, and provide Smalltalk block closures as callback functions to JavaScript. One may interact with any JavaScript object in the Web environment. This means we can manipulate DOM objects as any other JavaScript framework would, to create new HTML5 user interfaces and modify existing ones.

In particular, we can embed SqueakJS in a web page, and modify that web page from SqueakJS processes. It would be very useful to have a Smalltalk object model of the host web page. I have created such a thing with the new class ThisWebpage.

reaching out with ThisWebpage

I chose the name of ThisWebpage to be reminiscent of “thisContext”, the traditional Smalltalk pseudo-variable used by an expression to access its method execution context. In a similar way, expressions can use ThisWebpage to access the DOM of the hosting Web environment. One simple example is adding a button:

ThisWebpage
  createButtonLabeled: 'fullscreen'
  evaluating: [Project current fullscreen: true]

Behind the scenes, ThisWebpage is doing this:

(JS document createElement: 'input')
  at: #type
  put: 'button';
  at: #onclick:
  put: [Project current fullscreen: true]

Class JSObjectProxy creates JS, an instance of itself, during installation of the JavaScript bridge. It corresponds to the JavaScript DOM object for the current web browser window, the top of the DOM object graph. By sending createElement:, the expression is invoking one of the DOM methods. The entire set of DOM methods is well-documented online (for example, here’s the documentation for Document.createElement).

So far, ThisWebpage has some basic behavior for adding buttons and frames, and for referring to the document elements in which SqueakJS is embedded. It can also create links and synthesize clicks on them. This is an important ability, which I use in making a Squeak object memory jump from SqueakJS in a web browser to a native Cog virtual machine on the desktop (the subject of tomorrow’s post).

The possibilities here are immense. ThisWebpage is waiting for you to make it do amazing front-end things! Check it out as part of the Context 7 alpha 1 release.

 

%d bloggers like this: