Delphi-style VCL on WebAssembly Platform

As many of you know, our Elements development environment (Fire, Water in Visual Studio) recently introduced a new Island sub-platform called WebAssembly. Code is compiled to a standard byte code format (.wasm files) that the browser can run together with JavaScript code.

For Delphi peeps, that means you can use our Delphi RTL library (and Elements and Island RTL) in web applications, like:

var lList := TStringList.Create;
lList.Add('Option 1');

Of course once you have code running in the browser, it would be great to interact with JavaScript to get the best of the two worlds, which brings in our "JavaScript Bridge" that was developed by the team I'm part of. The bridge allows you to get JS objects and use them directly and natively from your favorite language (in this case, I'm going to use Oxygene):

var lOption := WebAssembly.CreateElement("OPTION");
lOption.text := lList[0];

In the first line we created an HTML element using JavaScript and DOM functions and returned this new object. Now we can manipulate it like any other, in this case changing its text property using the same Oxygene syntax. Putting all things together, we have a compiler that generates "browser friendly" byte code and we can play with JavaScript and DOM functions using the bridge, with the same syntax... why not create a visual controls library to deal with the HTML stuff?

Introducing Visual Controls

Coming from a Delphi background (and being deeply involved with our Delphi RTL), I thought it would be fun to create a VCL-like API in Delphi RTL to make this very easy. Let's have a look:

To create a blank new WebAssembly project, go to "New Project" and select the Island platform, then "WebAssembly Module". Add a reference to the Elements.fx and Delphi.fx libraries, and a uses clause:

uses
  RemObjects.Elements.RTL.Delphi;

Project ready, first of all we need a container for our components, this is done using:

var lForm := new TForm(nil); // sounds familiar, right? ?

Next step, setup the container and show it:

  lForm.Width := 800;
  lForm.Show(nil);

In case we have a specific place to show our form (i.e. an HTML div inside an existing page), we can first get a reference to this HTML element and pass it as parameter to the Show() method:

  var lDiv := WebAssembly.GetElementById('divId'); // just use the id property
  lForm.Show(lDiv);

Here we go. What's next? Maybe adding a button:

var lButton := new TButton(lForm);
lButton.Left := 100;
lButton.Top := 100;
lButton.Parent := lForm;

The code needed to add a button to our form is the same used in Delphi VCL, as you probably noticed. Events follow the same Delphi pattern:

lButton.OnClick := @ButtonOnClick;

where ButtonOnClick is a method defined somewhere in the unit:

method ButtonOnClick(Sender: TObject);
begin
  ShowMessage('You Clicked!'); // yes, ShowMessage works as well
end;

or you can even do it inline, using Oxygene's lambda syntax:

  lButton.OnClick := () -> begin ShowMessage('You Clicked!'); end;

As you would expect, font name, size and style of any control can be customized, using the Font property:

lButton.Font.Name := 'Verdana';
lButton.Font.Size := 24;
lButton.Font.Style := TFontStyle.Bold;

Initially, available components are: TForm, TPanel, TButton, TLabel, TEdit, TCheckBox, TRadioButton, TComboBox, TListBox, TMemo and TProgressBar, but many others will be added over time.

If you want check the two available demos on ElementsSamples/Oxygene/Island/GUI :

  • Basic WebAssembly GUI App
  • Basic WebAssembly GUI Controls App

Both are ready to run and perfect to start playing around with this amazing technology!