DEV Community

Cover image for Ruby GUI with Glimmer
Mattias Velamsson
Mattias Velamsson

Posted on

11 1 1 1 1

Ruby GUI with Glimmer

From the very first time I started getting into development and programming, I always felt like I wanted to create my very own GUI. Whether it was for something as simple as cheating in a flash game πŸ¦ΉπŸ½β€β™‚οΈ or something more useful like setting a timer or calculating expenses, creating an app with an actual interface always interested me. Prior to this I had used PythonAutoGUI and others. However, a couple of weeks ago, I stumbled upon a Ruby library that makes creating a fully functional GUI super easy. Obvisouly, I had to try it out. So in this post, I'll walk through how I used this library to create a simple currency converter.

application preview
Code Walkthrough:
First, install installing and including the glimmer-dsl-libui gem, dotenv gem, and a few other standard libraries for handling URLs, HTTP requests, and JSON parsing. I'm using Dotenv and loading a local .env file in my project holding the API_KEY.



# Requirements
require 'glimmer-dsl-libui'
require 'dotenv'
require 'uri'
require 'net/http'
require 'json'

Dotenv.load
include Glimmer


Enter fullscreen mode Exit fullscreen mode

The next step was to define the currencies and base values I want to work with.



# DATA
currencies = ['USD', 'EUR', 'SEK', 'JPY', 'KRW']
base_values = ['USD', 'EUR', 'SEK', 'JPY', 'KRW']
currencies = currencies.join('%2C%20')



Enter fullscreen mode Exit fullscreen mode

Then I had to make sure to use the above values and create a method that fetches the values of these currencies from my selected API, and then use this data to create items for each currency that includes the symbol, rate and a place holder value of 0. These items are stored in an array, which is returned at the end.



def get_data(currency_array, base)
  data = []
  url = URI("https://api.apilayer.com/exchangerates_data/latest?symbols=#{currency_array}&base=USD")

  https = Net::HTTP.new(url.host, url.port)
  https.use_ssl = true

  request = Net::HTTP::Get.new(url)
  request['apikey'] = ENV['API_KEY']

  response = https.request(request)
  response_hash = JSON.parse(response.body)

  response_hash['rates'].each do |currency, rate|
    item = [currency, rate, 0]
    data.append(item)
  end
  data
end


Enter fullscreen mode Exit fullscreen mode

Now to the main code block. Here we call the get_data method, passing in the currencies array and USD as arguments. This retrieves the updated exchange rate data for the specified currencies relative to USD.



# Fetches the exchange rate for each currency to USD.
updated_data = get_data(currencies, 'USD')


Enter fullscreen mode Exit fullscreen mode

Next, the application window is created using the window method from the glimmer library. I've also named it and set the window dimensions.

Inside the window, we create a vertical box to hold the table and input field, basically like a "grid". The table is created using the table method and consists of three columns: "Currency," "Market Value," and "Converted Value."

Then using the cell_rows method, we pass in the updated_data_array.



window('Currency Converter', 1080, 800) {
  vertical_box {
    table {
      text_column('Currency')
      text_column('Market Value')
      text_column('Converted Value')

       cell_rows updated_data
    }
#...


Enter fullscreen mode Exit fullscreen mode

On the bottom of the app, I added an input field using the search_entry method. This input field enter a value to convert.

The stretch false is pretty much just a bool telling the input field not to stretch vertically.



 # Input Field
    search_entry { |value|
      stretchy false
#...


Enter fullscreen mode Exit fullscreen mode

To make the input field "responsive" to changes, I defined a on_changed block. In short the block takes the value in the input field, and copies the data array and replaces it with an updated one.



 # Action on input
      on_changed do
        new_value = value.text
        new_data ||= updated_data.dup
#...


Enter fullscreen mode Exit fullscreen mode

We then iterate over each currency item in new_data and update the converted value based on the new input. The converted value is calculated and rounded to two decimals. The updated values are then stored back in the new_data array, which is rendered in the app.



# Iterates over each of the currencies added, and replaces the default "0" with the actual value.
        new_data.each do |currency|
          currency[2] = 0
          new_total = (currency[2]) + new_value.to_i * currency[1]
          currency[2] = new_total.round(2)
        end
      end
    }
  }
}.show


Enter fullscreen mode Exit fullscreen mode

That's all there is to it really. It was fun trying a completely new library that I had no previous experience of, or heard about before and just figuring things out using the provided documentation.

You can find the full code here.

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo πŸ“Šβœ¨

Top comments (2)

Collapse
 
daddie888 profile image
daddie888 β€’

Hi, I'm a user of glimmer-dsl-libui but one thing that bothers me is that in a table it is not possible to set the width of the columns in code, you can adjust by hand but that is not what I want. Same thing when I run your code. In your demo the width is adjusted to the witdh of the data, is this recorded after the manual adjustment or is this because you use a Mac ? (I'm on Windows)

Collapse
 
smackdh profile image
Mattias Velamsson β€’

Hi,

You can nest your horizontal and vertical rows to make it position itself as you'd like, and you can also set them to be "stretchy" or not.

I've only tried running the app on WSL Linux / macOS so if you are experiencing different sizing on Windows I'm afraid I don't have any good answer for that.

Other than this I think that the positioning and resizing of the columns is unfortunately not available in the APIs of the library yet.

πŸ‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay