Electron Adventures: Episode 82: Glimmer DSL
Tags: ruby, java, jruby
Published: 2021-10-29 23:31:06

I went through all the promising Electron alternatives, but there's still bottom of the barrel to scrape. So for this episode - [Glimmer DSL](https://github.com/AndyObtiva/glimmer).

Glimmer DSL is a Ruby DSL for creating UIs. As a warning sign, it doesn't try to be good DSL for one UI library, it tries to do 6. Now three of them are just Opal HTML, CSS, and XML, and we can do that stuff in Electron already, so let's look at the other three.

### `glimmer-dsl-tk`

As far as I can tell, it's not possible to install Tk on Mac in any sensible way. I have `tcl-tk` installed in `brew`, but `gem install glimmer-dsl-tk` doesn't see it.

Here's the `Gemfile` that crashes:

```ruby
source "https://rubygems.org"

gem "glimmer-dsl-tk", "~> 0.0.32"
```

If you're on Linux, you could probably give it a try.

### `glimmer-dsl-libui`

[LibUI](https://github.com/andlabs/libui) is a "portable GUI library for C". It comes with so many disclaimers that it's an incomplete alpha version.

So we prepare the following `Gemfile` and then run `bundle install`:

```ruby
source "https://rubygems.org"

gem "glimmer-dsl-libui", "~> 0.2.16"
```

Hello World isn't too bad:

```ruby
#!/usr/bin/env ruby

require "glimmer-dsl-libui"

include Glimmer

window("Hello, world!", 800, 600).show
```

![Episode 82 Screenshot A](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/orrauytl9q01es9gu68e.png)

Except it refuses to activate that window on OSX, so it's in the background.

I proceeded to try to write a simple counter app with `+1` and `-1` buttons and showing a total, but libui segfaulted if I looked at it funny. Between no documentation, no feedback in REPL, constant segfaults, and library itself being open about being really incomplete, I just dropped it at this point.

### `glimmer-dsl-swt`

Well, there's one more thing to try. The final supported library is Java SWT, for which we'll need to use JRuby. This is already problematic, as JRuby has very slow startup, and supports a lot fewer libraries than the regular Ruby, but it could be good enough.

We can start by this `.rubyversion` (if you use `rbenv` to manage multiple Ruby versions:)

```
jruby-9.3.1.0
```

And this `Gemfile`:

```ruby
source "https://rubygems.org"

gem "glimmer-dsl-swt", "~> 4.21"
```

Installation took a while, and didn't tell me that I need to pass special options to jruby or I'd get a crash. With special option `-J-XstartOnFirstThread`, here's the Hello World:

```ruby
#!/usr/bin/env ruby -J-XstartOnFirstThread

require "glimmer-dsl-swt"

include Glimmer

shell {
  text "Glimmer"
  label {
    text "Hello, World!"
  }
}.open
```

As you might have noticed, it has nothing in common with Glimmer LibUI version. It's really unclear to me why Glimmer tries to be one project with multiple UI libraries that have so little in common, but I guess the DSL concept might be somewhat similar.

![Episode 82 Screenshot B](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bl4cweteyo2mulq1x7yo.png)

### Counter app in `glimmer-dsl-swt`

After digging through the examples in documentation, I managed to do this:

```ruby
#!/usr/bin/env ruby -J-XstartOnFirstThread

require 'glimmer-dsl-swt'

class CounterApp
  include Glimmer::UI::CustomShell

  attr_accessor :count

  before_body do
    @count = 0
  end

  body {
    shell {
      text "Hello, Button!"
      row_layout :vertical

      label {
        text <= [self, :count, on_read: lambda{|v| "Count: #{v}" }]
      }

      group {
        row_layout :horizontal

        button {
          text "+1"
          on_widget_selected { self.count += 1 }
        }

        button {
          text "-1"
          on_widget_selected { self.count -= 1 }
        }
      }
    }
  }
end

CounterApp.launch
```

All reactivity needs to be explicit. We do `[self, :count, on_read: lambda{|v| "Count: #{v}" }]` to tell it to observe changes in `self.count`, and may them with a lambda given.

And we need to to update `self.count` rather than `@count`, so observer code is notified.

It starts OK, unfortunately then things go bad when count exceeds one digit:

![Episode 82 Screenshot C](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/el5kjre3bwyp7j3qr5rp.png)

Did you notice that cut "18"? The label size is only determined when we create the label. Updates change label contents, but they don't change label size. It's possible to work around it by including extra spaces at the end, but honestly, is this what we left HTML+CSS world for? I don't think so.

### Results

In case it's not obvious yet, do not use any of this. It's a strong contender for the world one yet.

In the next episode we'll try JavaFX for JRuby, and see if that's better than Glimmer and SWT.

As usual, [all the code for the episode is here](https://github.com/taw/electron-adventures/tree/master/episode-82-glimmer-dsl).