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.
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
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')
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
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')
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
}
#...
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
#...
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
#...
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
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.
Top comments (2)
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)
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.