You [Gerald Bauer¹] have been permanently banned [for life] from participating in r/ruby (because of your writing off / outside of r/ruby). I do not see your participation adding anything to this [ruby] community.

-- Richard Schneeman (r/ruby mod and fanatic illiberal ultra leftie on a cancel culture mission)

¹: I know. Who cares? Who is this Gerald Bauer anyway. A random nobody for sure. It just happens that I am the admin among other things of Planet Ruby.

Case Studies of Code of Conduct "Cancel Culture" Out-Of-Control Power Abuse - Ruby - A Call for Tolerance On Ruby-Talk Results In Ban On Reddit Ruby

« Ruby Glimmer Days 2021, January 26th to January 29th - 4 Days of Ruby (Desktop) Gems

Day 8 - glimmer-dsl-libui Gem - Prerequisite-Free Ruby Desktop Development Library

Written by AndyObtiva Andy Maleh

Software Engineering Expert from Montreal, Quebec. Creator of Glimmer and Abstract Feature Branch. Speaker at RailsConf, RubyConf, AgileConf, EclipseCon, EclipseWorld. Master in Software Engineering, DePaul University, Chicago. Blogs at Code Mastery Takes Commitment To Bold Coding Adventures. Snowboarder and Drummer.

What is Glimmer DSL for LibUI?

Glimmer DSL for LibUI is a prerequisite-free Ruby desktop development GUI (Graphical User Interface) library. LibUI is a thin Ruby wrapper around libui, a relatively new C GUI library that renders native desktop GUI controls on every platform (similar to SWT, but without the heavy weight of the Java Virtual Machine).

Glimmer DSL for LibUI is a good convenient choice for small simple applications due to having zero prerequisites beyond the dependencies included in the Ruby gem. Also, just like Glimmer DSL for Tk, its apps start instantly and have a small memory footprint. LibUI is a promising new GUI toolkit that might prove quite worthy in the future.

Mac Windows Linux

What makes Glimmer DSL for LibUI special?

No need to pre-install any prerequisites. Just install the gem and have platform-independent native GUI that just works!

Glimmer DSL for LibUI aims to provide a DSL (Domain Specific Language) that enables more productive desktop development in Ruby with:

The Glimmer GUI DSL Syntax

The Glimmer GUI DSL follows these simple concepts in mapping from LibUI syntax:

Example of an app written in Glimmer GUI DSL object-oriented declarative hierarchical syntax:

require 'glimmer-dsl-libui'

include Glimmer

window('hello world', 300, 200) {
  button('Button') {
    on_clicked do
      msg_box('Information', 'You clicked the button')
    end
  }
  
  on_closing do
    puts 'Bye Bye'
  end
}.show

Mac Screenshots

glimmer-dsl-libui-mac-basic-button.png glimmer-dsl-libui-mac-basic-button-msg-box.png

Windows Screenshots

glimmer-dsl-libui-windows-basic-button.png glimmer-dsl-libui-windows-basic-button-msg-box.png

Linux Screenshots

glimmer-dsl-libui-linux-basic-button.png glimmer-dsl-libui-linux-basic-button-msg-box.png

Hello, World!

require 'glimmer-dsl-libui'

include Glimmer

window('hello world').show

Mac Screenshot:

glimmer-dsl-libui-mac-basic-window.png

Windows Screenshot:

glimmer-dsl-libui-windows-basic-window.png

Linux Screenshot:

glimmer-dsl-libui-linux-basic-window.png

Basic Table Progress Bar

This is an example that demonstrates the table control in Glimmer DSL for LibUI.

The table cell_rows property declaration results in “implicit data-binding” between the table control and Array of Arrays; a new Glimmer DSL for LibUI innovation that provides convenience automatic support for:

require 'glimmer-dsl-libui'

include Glimmer

data = [
  ['task 1', 0],
  ['task 2', 15],
  ['task 3', 100],
  ['task 4', 75],
  ['task 5', -1],
]

window('Task Progress', 300, 200) {
  vertical_box {
    table {
      text_column('Task')
      progress_bar_column('Progress')

      cell_rows data # implicit data-binding
    }
    
    button('Mark All As Done') {
      stretchy false
      
      on_clicked do
        data.each_with_index do |row_data, row|
          data[row][1] = 100 # automatically updates table due to implicit data-binding
        end
      end
    }
  }
}.show

Mac

glimmer-dsl-libui-mac-basic-table-progress-bar.png

Windows

glimmer-dsl-libui-windows-basic-table-progress-bar.png

Linux

glimmer-dsl-libui-linux-basic-table-progress-bar.png

Snake

Snake provides an example of building a desktop application test-first following the MVP (Model / View / Presenter) architectural pattern.

examples/snake.rb

require 'glimmer-dsl-libui'
require 'glimmer/data_binding/observer'

require_relative 'snake/presenter/grid'

class Snake
  CELL_SIZE = 15
  SNAKE_MOVE_DELAY = 0.1
  include Glimmer
  
  def initialize
    @game = Model::Game.new
    @grid = Presenter::Grid.new(@game)
    @game.start
    create_gui
    register_observers
  end
  
  def launch
    @main_window.show
  end
  
  def register_observers
    @game.height.times do |row|
      @game.width.times do |column|
        Glimmer::DataBinding::Observer.proc do |new_color|
          @cell_grid[row][column].fill = new_color
        end.observe(@grid.cells[row][column], :color)
      end
    end
    
    Glimmer::DataBinding::Observer.proc do |game_over|
      Glimmer::LibUI.queue_main do
        if game_over
          msg_box('Game Over!', "Score: #{@game.score}")
          @game.start
        end
      end
    end.observe(@game, :over)
    
    Glimmer::LibUI.timer(SNAKE_MOVE_DELAY) do
      unless @game.over?
        @game.snake.move
        @main_window.title = "Glimmer Snake (Score: #{@game.score})"
      end
    end
  end
  
  def create_gui
    @cell_grid = []
    @main_window = window('Glimmer Snake', @game.width * CELL_SIZE, @game.height * CELL_SIZE) {
      resizable false
      
      vertical_box {
        padded false
        
        @game.height.times do |row|
          @cell_grid << []
          horizontal_box {
            padded false
            
            @game.width.times do |column|
              area {
                @cell_grid.last << path {
                  square(0, 0, CELL_SIZE)
                  
                  fill Presenter::Cell::COLOR_CLEAR
                }
                
                on_key_up do |area_key_event|
                  orientation_and_key = [@game.snake.head.orientation, area_key_event[:ext_key]]
                  case orientation_and_key
                  in [:north, :right] | [:east, :down] | [:south, :left] | [:west, :up]
                    @game.snake.turn_right
                  in [:north, :left] | [:west, :down] | [:south, :right] | [:east, :up]
                    @game.snake.turn_left
                  else
                    # No Op
                  end
                end
              }
            end
          }
        end
      }
    }
  end
end

Snake.new.launch

Mac

glimmer-dsl-libui-mac-snake.png

glimmer-dsl-libui-mac-snake-game-over.png

Windows

glimmer-dsl-libui-windows-snake.png

glimmer-dsl-libui-windows-snake-game-over.png

Linux

glimmer-dsl-libui-linux-snake.png

glimmer-dsl-libui-linux-snake-game-over.png

Find Out More

References

Built with Ruby (running Jekyll) on 2021-11-10 16:51:53 +0000 in 0.371 seconds.
Hosted on GitHub Pages. </> Source on GitHub. (0) Dedicated to the public domain.