{"id":16382470,"url":"https://github.com/andyobtiva/how-to-build-desktop-applications-in-ruby","last_synced_at":"2026-03-10T21:31:58.880Z","repository":{"id":207839902,"uuid":"715360554","full_name":"AndyObtiva/how-to-build-desktop-applications-in-ruby","owner":"AndyObtiva","description":"Code Exercises for RubyConf 2024 Workshop \"How To Build Basic Desktop Applications in Ruby\" \u0026 RubyConf 2023 Workshop \"How To Build Desktop Applications in Ruby\"","archived":false,"fork":false,"pushed_at":"2024-12-19T20:41:49.000Z","size":14319,"stargazers_count":227,"open_issues_count":1,"forks_count":4,"subscribers_count":4,"default_branch":"rubyconf2024","last_synced_at":"2025-08-01T07:43:16.492Z","etag":null,"topics":["desktop","desktop-app","desktop-development","ruby","tutorial","tutorials","workshop","workshops"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AndyObtiva.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-11-07T01:36:19.000Z","updated_at":"2025-07-11T01:15:41.000Z","dependencies_parsed_at":"2024-01-13T01:18:09.731Z","dependency_job_id":"ee9795ea-6fde-4f8a-b6c7-de943dc684c3","html_url":"https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby","commit_stats":{"total_commits":48,"total_committers":2,"mean_commits":24.0,"dds":"0.10416666666666663","last_synced_commit":"b861cb2d8aa4058dcbe22d5f835a053f3dad6c2c"},"previous_names":["andyobtiva/how-to-build-desktop-applications-in-ruby"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AndyObtiva/how-to-build-desktop-applications-in-ruby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fhow-to-build-desktop-applications-in-ruby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fhow-to-build-desktop-applications-in-ruby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fhow-to-build-desktop-applications-in-ruby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fhow-to-build-desktop-applications-in-ruby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AndyObtiva","download_url":"https://codeload.github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/tar.gz/refs/heads/rubyconf2024","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AndyObtiva%2Fhow-to-build-desktop-applications-in-ruby/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30355616,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T15:55:29.454Z","status":"ssl_error","status_checked_at":"2026-03-10T15:54:58.440Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["desktop","desktop-app","desktop-development","ruby","tutorial","tutorials","workshop","workshops"],"created_at":"2024-10-11T04:05:32.416Z","updated_at":"2026-03-10T21:31:58.861Z","avatar_url":"https://github.com/AndyObtiva.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# How To Build Basic Desktop Applications in Ruby\n## RubyConf 2024 Workshop Code Exercises by Andy Maleh\n\nMac | Windows | Linux\n----|---------|------\n![glimmer-dsl-libui-mac-control-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-control-gallery.png) | ![glimmer-dsl-libui-windows-control-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-windows-control-gallery.png) | ![glimmer-dsl-libui-linux-control-gallery.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-control-gallery.png)\n\nPlease star (\"⭐️\") this project and [Glimmer DSL for LibUI](https://github.com/AndyObtiva/glimmer-dsl-libui) to save for later reference with regards to Ruby Desktop Development. [Glimmer DSL for LibUI](https://github.com/AndyObtiva/glimmer-dsl-libui) was used in this workshop because it is the simplest and quickest to setup in standard Ruby (aka MRI / CRuby), but the lessons learned are applicable to other [Glimmer GUI DSLs](https://github.com/AndyObtiva/glimmer#glimmer-dsl-comparison-table) (with some syntax variations), including more mature ones like [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt), which might be better for more serious usage after finishing the workshop. If you discover any issues or get stuck while going through the material of this repo, please [report them in GitHub issues](https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/issues) or discuss in the [Glimmer Gitter Chat](https://app.gitter.im/#/room/#AndyObtiva_glimmer:gitter.im).\n\nYouTube Video Link:\n\n[https://www.youtube.com/watch?v=TTSqRdTVtDY](https://www.youtube.com/watch?v=TTSqRdTVtDY)\n\nPresentation Slides Online Short Link:\n\n[https://bit.ly/rubyconf2024desktop](https://bit.ly/rubyconf2024desktop)\n\nPresentation Slides Online Long Link:\n\n[https://docs.google.com/presentation/d/e/2PACX-1vSAaFLYeyolSy2Qe2tW0djv78tA-m120i4DJyaJ4qAHoWpv5Xppn_-yIpg4_IAGntetZkRDkkuT2zXN/pub?start=false\u0026loop=false\u0026delayms=60000\u0026slide=id.g140fe579a5a_0_0](https://docs.google.com/presentation/d/e/2PACX-1vSAaFLYeyolSy2Qe2tW0djv78tA-m120i4DJyaJ4qAHoWpv5Xppn_-yIpg4_IAGntetZkRDkkuT2zXN/pub?start=false\u0026loop=false\u0026delayms=60000\u0026slide=id.g140fe579a5a_0_0)\n\nPresentation Slides Offline Download Links:\n\n- PowerPoint: [https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/raw/refs/heads/rubyconf2024/RubyConf%202024%20-%20How%20To%20Build%20Basic%20Desktop%20Applications%20in%20Ruby%20-%20Andy%20Maleh.pptx](https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/raw/refs/heads/rubyconf2024/RubyConf%202024%20-%20How%20To%20Build%20Basic%20Desktop%20Applications%20in%20Ruby%20-%20Andy%20Maleh.pptx)\n- PDF: [https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/raw/refs/heads/rubyconf2024/RubyConf%202024%20-%20How%20To%20Build%20Basic%20Desktop%20Applications%20in%20Ruby%20-%20Andy%20Maleh.pdf](https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/raw/refs/heads/rubyconf2024/RubyConf%202024%20-%20How%20To%20Build%20Basic%20Desktop%20Applications%20in%20Ruby%20-%20Andy%20Maleh.pdf)\n\n[If you are looking for the RubyConf 2023 longer version of the workshop (\"How To Build Desktop Applications in Ruby\"), click here!](https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/tree/rubyconf2023)\n\n## Table of Contents\n\n- [How To Build Desktop Applications in Ruby](#how-to-build-desktop-applications-in-ruby)\n  * [Setup Glimmer DSL for LibUI](#setup-glimmer-dsl-for-libui)\n  * [Resources](#resources)\n  * [Exercises](#exercises)\n  * [Hack Day](#hack-day)\n\n## Setup Glimmer DSL for LibUI\n\nPlease make sure to follow these instructions on your laptop successfully before attending the workshop.\n\n1- Open Terminal (on Mac or Linux) or Command-Prompt/Git-Bash (on Windows) [do not use WSL or PowerShell]\n\n2- Install [glimmer-dsl-libui](https://github.com/AndyObtiva/glimmer-dsl-libui) gem\n\nRun:\n\n```\ngem install glimmer-dsl-libui -v0.12.5\n```\n\n3- Load Glimmer Meta-Example to test gem\n\nRun:\n\n```\nglimmer examples\n```\n\nYou should see the Glimmer Meta-Example (the example of examples).\n\nMac | Windows | Linux\n----|---------|------\n![glimmer-dsl-libui-mac-meta-example.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-meta-example.png) | ![glimmer-dsl-libui-windows-meta-example.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-windows-meta-example.png) | ![glimmer-dsl-libui-linux-meta-example.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-meta-example.png)\n\n4- Clone Repository\n\nClone the GitHub repository to avoid running into issues if WIFI service is unreliable at the event:\n\n```\ngit clone https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby.git\n```\n\nThis will download the [presentation slides](https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/raw/refs/heads/rubyconf2024/RubyConf%202024%20-%20How%20To%20Build%20Basic%20Desktop%20Applications%20in%20Ruby%20-%20Andy%20Maleh.pptx).\n\nOn the morning of day 2 (Thursday, Nov 14, 2024), pull the latest version of the repository before you go into the workshop to get all the code exercises and the latest version of the presentation slides.\n\n5- (Optional) Scaffold Application\n\nThis step is helpful for the Hack Day event that follows the 2-hour workshop, but is not necessary for the workshop itself and can be skipped till you get to the Hack Day event if you run into any issues with it.\n\nApplication Scaffolding relies on the juwelier Ruby gem, which expects a local Git config of:\n- `user.name` (`git config --global user.name \"FirstName LastName\"`)\n- `github.user` (`git config --global github.user githubusername`)\n\nScaffold Glimmer DSL for LibUI application with this command:\n\n```\nglimmer \"scaffold[hello_world]\"\n```\n\n## Resources\n\n- [Glimmer DSL for LibUI](https://github.com/AndyObtiva/glimmer-dsl-libui)\n- [Glimmer DSL for LibUI Supported Keywords](https://github.com/AndyObtiva/glimmer-dsl-libui#supported-keywords)\n\n## Exercises\n\n### Section 1 GUI Basics\n\n[section-01-gui-basics](/section-01-gui-basics)\n\n#### Section 1 Exercise 1 Empty Window\n\n[section-01-gui-basics/exercise-01/empty_window.rb](/section-01-gui-basics/exercise-01/empty_window.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-01/empty_window.rb\n```\n\nScreenshot(s):\n\n![empty window](/screenshots/section-01-exercise-01-screenshot-01-empty-window.png)\n\n#### Section 1 - Exercise 2 Hello, World! Window with Args\n\n[section-01-gui-basics/exercise-02/hello_world_window_with_args.rb](/section-01-gui-basics/exercise-02/hello_world_window_with_args.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-02/hello_world_window_with_args.rb\n```\n\nScreenshot(s):\n\n![hello world window with args](/screenshots/section-01-exercise-01-screenshot-02-hello-world-window-with-args.png)\n\n#### Section 1 - Exercise 3 Hello, World! Window with Props\n\n[section-01-gui-basics/exercise-03/hello_world_window_with_props.rb](/section-01-gui-basics/exercise-03/hello_world_window_with_props.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-03/hello_world_window_with_props.rb\n```\n\nScreenshot(s):\n\n![hello world window with props](/screenshots/section-01-exercise-01-screenshot-02-hello-world-window-with-args.png)\n\n#### Section 1 - Exercise 4 Hello, World! Window + Label with Args\n\n[section-01-gui-basics/exercise-04/hello_world_window_label_with_args.rb](/section-01-gui-basics/exercise-04/hello_world_window_label_with_args.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-04/hello_world_window_label_with_args.rb\n```\n\nScreenshot(s):\n\n![hello world window label with args](/screenshots/section-01-exercise-01-screenshot-03-hello-world-window-label-with-args.png)\n\n#### Section 1 - Exercise 5 Hello, World! Window + Label with Props\n\n[section-01-gui-basics/exercise-05/hello_world_window_label_with_props.rb](/section-01-gui-basics/exercise-05/hello_world_window_label_with_props.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-05/hello_world_window_label_with_props.rb\n```\n\nScreenshot(s):\n\n![hello world window label with args](/screenshots/section-01-exercise-01-screenshot-03-hello-world-window-label-with-args.png)\n\n#### Section 1 - Exercise 6 Hello, Button!\n\n[section-01-gui-basics/exercise-06/hello_button.rb](/section-01-gui-basics/exercise-06/hello_button.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-06/hello_button.rb\n```\n\nScreenshot(s):\n\n![hello button](/screenshots/section-01-exercise-01-screenshot-04-hello-button.png)\n\n![hello button clicked](/screenshots/section-01-exercise-01-screenshot-04-hello-button-clicked.png)\n\n#### Section 1 - Exercise 7 Hello, Layout! with Horizontal Box\n\n[section-01-gui-basics/exercise-07/hello_layout_with_horizontal_box.rb](/section-01-gui-basics/exercise-07/hello_layout_with_horizontal_box.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-07/hello_layout_with_horizontal_box.rb\n```\n\nScreenshot(s):\n\n![hello layout with horizontal box](/screenshots/section-01-exercise-01-screenshot-05-hello-layout-with-horizontal-box.png)\n\n#### Section 1 - Exercise 8 Hello, Layout! with Horizontal \u0026 Vertical Boxes\n\n[section-01-gui-basics/exercise-08/hello_layout_with_horizontal_and_vertical_boxes.rb](section-01-gui-basics/exercise-08/hello_layout_with_horizontal_and_vertical_boxes.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-08/hello_layout_with_horizontal_and_vertical_boxes.rb\n```\n\nScreenshot(s):\n\n![hello layout with horizontal and vertical boxes](/screenshots/section-01-exercise-01-screenshot-06-hello-layout-with-horizontal-and-vertical-boxes.png)\n\n#### Section 1 - Exercise 9 Hello, Layout! with Horizontal \u0026 Vertical Boxes (Stretchy)\n\n[section-01-gui-basics/exercise-09/hello_layout_with_horizontal_and_vertical_boxes_stretchy.rb](section-01-gui-basics/exercise-09/hello_layout_with_horizontal_and_vertical_boxes_stretchy.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-09/hello_layout_with_horizontal_and_vertical_boxes_stretchy.rb\n```\n\nScreenshot(s):\n\n![hello layout with horizontal and vertical boxes stretchy](/screenshots/section-01-exercise-01-screenshot-07-hello-layout-with-horizontal-and-vertical-boxes-stretchy.png)\n\n#### Section 1 - Exercise 10 Hello, Layout! Form\n\n[section-01-gui-basics/exercise-10/hello_layout_form.rb](section-01-gui-basics/exercise-10/hello_layout_form.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-10/hello_layout_form.rb\n```\n\nScreenshot(s):\n\n![hello layout form](/screenshots/section-01-exercise-01-screenshot-08-hello-layout-form.png)\n\n#### Section 1 - Exercise 11 Option Selector\n\n[section-01-gui-basics/exercise-11/option_selector.rb](/section-01-gui-basics/exercise-11/option_selector.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-01-gui-basics/exercise-11/option_selector.rb\n```\n\nScreenshot(s):\n\n![option selector screenshot 1](/screenshots/section-02-exercise-09-screenshot-01-option-selector.png)\n\n![option selector screenshot 2](/screenshots/section-02-exercise-09-screenshot-02-option-selector-options-checked.png)\n\nSee another version of the Option Selector in Section 2 Exercise 1.\n\n### Section 2 MVC Software Architecture\n\n[section-02-mvc-software-architecture](/section-02-mvc-software-architecture)\n\n#### Section 2 Exercise 01 Option Selector MVC Explicit Controller\n\n[section-02-mvc-software-architecture/exercise-01/option_selector_mvc_explicit_controller.rb](/section-02-mvc-software-architecture/exercise-01/option_selector_mvc_explicit_controller.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-02-mvc-software-architecture/exercise-01/option_selector_mvc_explicit_controller.rb\n```\n\nScreenshot(s):\n\n![option selector screenshot 1](/screenshots/section-02-exercise-09-screenshot-01-option-selector.png)\n\n![option selector screenshot 2](/screenshots/section-02-exercise-09-screenshot-02-option-selector-options-checked.png)\n\nSee another version of the Option Selector in Section 2 Exercise 02.\n\n#### Section 2 Exercise 02 Option Selector MVC Implicit Controller\n\n[section-02-mvc-software-architecture/exercise-02/option_selector_mvc_implicit_controller.rb](/section-02-mvc-software-architecture/exercise-02/option_selector_mvc_implicit_controller.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-02-mvc-software-architecture/exercise-02/option_selector_mvc_implicit_controller.rb\n```\n\nScreenshot(s):\n\n![option selector screenshot 1](/screenshots/section-02-exercise-09-screenshot-01-option-selector.png)\n\n![option selector screenshot 2](/screenshots/section-02-exercise-09-screenshot-02-option-selector-options-checked.png)\n\nSee another version of the Option Selector in Section 3 Exercise 01.\n\n### Section 3 MVP \u0026 Data-Binding\n\n[section-03-mvp-data-binding](/section-03-mvp-data-binding)\n\n#### Section 3 Exercise 01 Option Selector MVP and Data-Binding Attribute Writers\n\n[section-03-mvp-data-binding/exercise-01/option_selector_mvp_and_data_binding_model_attr_writers.rb](/section-03-mvp-data-binding/exercise-01/option_selector_mvp_and_data_binding_model_attr_writers.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-03-mvp-data-binding/exercise-01/option_selector_mvp_and_data_binding_model_attr_writers.rb\n```\n\nScreenshot(s):\n\n![option selector screenshot 1](/screenshots/section-02-exercise-09-screenshot-01-option-selector.png)\n\n![option selector screenshot 2](/screenshots/section-02-exercise-09-screenshot-02-option-selector-options-checked.png)\n\nSee another version of the Option Selector in Section 3 Exercise 02.\n\n#### Section 3 Exercise 02 Option Selector MVP and Data-Binding Model Observer\n\n[section-03-mvp-data-binding/exercise-02/option_selector_mvp_and_data_binding_model_observer.rb](/section-03-mvp-data-binding/exercise-02/option_selector_mvp_and_data_binding_model_observer.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-03-mvp-data-binding/exercise-02/option_selector_mvp_and_data_binding_model_observer.rb\n```\n\nScreenshot(s):\n\n![option selector screenshot 1](/screenshots/section-02-exercise-09-screenshot-01-option-selector.png)\n\n![option selector screenshot 2](/screenshots/section-02-exercise-09-screenshot-02-option-selector-options-checked.png)\n\nSee another version of the Option Selector in Section 3 Exercise 03.\n\n#### Section 3 Exercise 03 Option Selector MVP and Computed Data-Binding\n\n[section-03-mvp-data-binding/exercise-03/option_selector_mvp_and_data_binding_with_computed_by.rb](/section-03-mvp-data-binding/exercise-03/option_selector_mvp_and_data_binding_with_computed_by.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-03-mvp-data-binding/exercise-03/option_selector_mvp_and_data_binding_with_computed_by.rb\n```\n\nScreenshot(s):\n\n![option selector screenshot 1](/screenshots/section-02-exercise-09-screenshot-01-option-selector.png)\n\n![option selector screenshot 2](/screenshots/section-02-exercise-09-screenshot-02-option-selector-options-checked.png)\n\nSee another version of the Option Selector in Section 3 Exercise 04.\n\n#### Section 3 Exercise 04 Option Selector MVP and Computed Data-Binding with Reset\n\n[section-03-mvp-data-binding/exercise-04/option_selector_mvp_and_data_binding_with_reset.rb](/section-03-mvp-data-binding/exercise-04/option_selector_mvp_and_data_binding_with_reset.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-03-mvp-data-binding/exercise-04/option_selector_mvp_and_data_binding_with_reset.rb\n```\n\nScreenshot(s):\n\n![option selector screenshot 1](/screenshots/section-02-exercise-09-screenshot-01-option-selector.png)\n\n![option selector screenshot 2](/screenshots/section-02-exercise-09-screenshot-02-option-selector-options-checked.png)\n\n![option selector with reset](/screenshots/section-03-exercise-13-screenshot-01-option-selector-with-reset.png)\n\n#### Section 3 Exercise 05 Form Table\n\n[section-03-mvp-data-binding/exercise-05/form_table.rb](/section-03-mvp-data-binding/exercise-05/form_table.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-03-mvp-data-binding/exercise-05/form_table.rb\n```\n\nScreenshot(s):\n\nMac | Windows | Linux\n----|---------|------\n![glimmer-dsl-libui-mac-form-table.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-form-table.png) ![glimmer-dsl-libui-mac-form-table-contact-entered.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-form-table-contact-entered.png) ![glimmer-dsl-libui-mac-form-table-filtered.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-form-table-filtered.png) | ![glimmer-dsl-libui-windows-form-table.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-windows-form-table.png) ![glimmer-dsl-libui-windows-form-table-contact-entered.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-windows-form-table-contact-entered.png) ![glimmer-dsl-libui-windows-form-table-filtered.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-windows-form-table-filtered.png) | ![glimmer-dsl-libui-linux-form-table.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-form-table.png) ![glimmer-dsl-libui-linux-form-table-contact-entered.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-form-table-contact-entered.png) ![glimmer-dsl-libui-linux-form-table-filtered.png](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-linux-form-table-filtered.png)\n\n#### Section 3 Exercise 06 Dynamic Form\n\n[section-03-mvp-data-binding/exercise-06/dynamic_form.rb](/section-03-mvp-data-binding/exercise-06/dynamic_form.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-03-mvp-data-binding/exercise-06/dynamic_form.rb\n```\n\nScreenshot(s):\n\n![dynamic form 1](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-dynamic-form-filled.png)\n\n![dynamic form 2](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-dynamic-form-without-some-fields.png)\n\n### Section 4 Advanced Data-Binding\n\nNote: there are no exercises for this section as it is too advanced for this workshop, so it will only be covered briefly in the presentation slides.\n\n### Section 5 Custom Components (Bonus)\n\nNote: this section is an optional bonus section outside the original plan of the workshop, so it is only covered if workshop participants finished previous exercises early and had extra time.\n\n[section-05-custom-components](/section-05-custom-components)\n\n#### Section 5 Exercise 01 Address Form Custom Control\n\n[section-05-custom-components/exercise-01/address_form_custom_control.rb](/section-05-custom-components/exercise-01/address_form_custom_control.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-05-custom-components/exercise-01/address_form_custom_control.rb\n```\n\nScreenshot(s):\n\n![address form custom control](/screenshots/section-05-exercise-01-screenshot-01-address-form-custom-control.png)\n\nCompared to [Method-Based Custom Controls](https://github.com/AndyObtiva/glimmer-dsl-libui#method-based-custom-controls), [Class-Based Custom Controls](https://github.com/AndyObtiva/glimmer-dsl-libui#class-based-custom-components) provide the added benefit of dividing and conquering the complexity of component code into separate Ruby files, which can even be wrapped as [Ruby gems](https://guides.rubygems.org/what-is-a-gem/) for cross-project reuse if needed.\n\n#### Section 5 Exercise 02 User Manager\n\n[section-05-custom-components/exercise-02/user_manager.rb](/section-05-custom-components/exercise-02/user_manager.rb)\n\nRun this command from cloned repo directory:\n\n```\nglimmer section-05-custom-components/exercise-02/user_manager.rb\n```\n\nScreenshot(s):\n\n![user manager](/screenshots/section-05-exercise-02-screenshot-01-user-manager.png)\n\n![user manager add user](/screenshots/section-05-exercise-02-screenshot-02-user-manager-add-user.png)\n\n![user manager user added](/screenshots/section-05-exercise-02-screenshot-03-user-manager-user-added.png)\n\n![user manager select user](/screenshots/section-05-exercise-02-screenshot-04-user-manager-select-user.png)\n\n![user manager edit user](/screenshots/section-05-exercise-02-screenshot-05-user-manager-edit-user.png)\n\n### Section 6 Scaffolding (Bonus)\n\nNote: this section is an optional bonus section outside the original plan of the workshop, so it is only covered if workshop participants finished previous exercises early and had extra time.\n\n#### Section 6 Exercise 01 Application Scaffolding\n\n[Glimmer DSL for LibUI Application Scaffolding](https://github.com/AndyObtiva/glimmer-dsl-libui#scaffold-application) requires a Git configuration for `user.name` (`git config --global user.name \"FirstName LastName\"`) and `github.user` (`git config --global github.user githubusername`) as needed by the juwelier Ruby gem used for scaffolding.\n\nGo out of this GitHub repository directory:\n\n```\ncd ..\n```\n\nRun:\n\n```\ngem install glimmer-dsl-libui -v0.12.5\n```\n\nScaffold an application by running:\n\n```\nglimmer \"scaffold[hello_world]\"\n```\n\n[section-08-scaffolding/exercise-01/hello_world](/section-08-scaffolding/exercise-01/hello_world)\n\nThe following files are generated and reported by the `glimmer` command:\n\n```\nCreated hello_world/.gitignore\nCreated hello_world/.ruby-version\nCreated hello_world/.ruby-gemset\nCreated hello_world/VERSION\nCreated hello_world/LICENSE.txt\nCreated hello_world/Gemfile\nCreated hello_world/Rakefile\nCreated hello_world/app/hello_world.rb\nCreated hello_world/app/hello_world/view/hello_world.rb\nCreated hello_world/app/hello_world/model/greeting.rb\nCreated hello_world/icons/windows/Hello World.ico\nCreated hello_world/icons/macosx/Hello World.icns\nCreated hello_world/icons/linux/Hello World.png\nCreated hello_world/app/hello_world/launch.rb\nCreated hello_world/bin/hello_world\n```\n\nThey include a basic Hello, World! application with menus and about/preferences dialogs.\n\nViews live under `app/app_name/view` (e.g. `app/hello_world/view`)\n\nModels live under `app/app_name/model` (e.g. `app/hello_world/model`)\n\nThe application runs automatically once scaffolding is done.\n\nYou can run scaffolded application with this command from cloned repo directory:\n\n```\ncd section-06-application-scaffolding/exercise-01/hello_world\nglimmer run\n```\n\nor\n\n```\ncd section-06-application-scaffolding/exercise-01/hello_world\nbin/hello_world\n```\n\nScreenshot(s):\n\n![application scaffolding 1](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-scaffold-app-initial-screen.png)\n\n![application scaffolding 2](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-scaffold-app-preferences.png)\n\n![application scaffolding 3](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-scaffold-app-changed-greeting.png)\n\n![application scaffolding 4](https://raw.githubusercontent.com/AndyObtiva/glimmer-dsl-libui/master/images/glimmer-dsl-libui-mac-scaffold-app-about.png)\n\n## Hack Day\n\nThere will be 2 events associated with this workshop:\n- The Workshop: it takes place from 11:15pm-1:15pm\n- The Hack Day event: it takes place from 3:45pm-5:45pm\n\nEveryone is welcome to attend the Hack Day event for \"How To Build Basic Desktop Applications in Ruby\", including Software Developers who are missing the Workshop.\n\nTo participate in the Hack Day event, please make sure to [Setup Glimmer DSL for LibUI](#setup-glimmer-dsl-for-libui) beforehand.\n\nAftewrwards, you may engage in one of the following activities:\n- Go through the workshop exercises if you missed the workshop\n- Finish the workshop exercises if you attended the workshop, but did not get around to finishing all exercises\n- Do the additional exercises that are in the [RubyConf 2023](https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/tree/rubyconf2023) longer version of the workshop\n- Build an application that stores its data in memory (in Ruby variables)\n- Build an application that stores its data in flat files (e.g. CSV files)\n- Build an application that stores its data with a relational database (e.g. SQLite)\n- Build a board game or 2D game (e.g. Hangman). This requires advanced knowledge that is available in the [RubyConf 2023](https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby/tree/rubyconf2023) longer version of the workshop\n\nI will be availble at the Hack Day event to answer any questions or help with any problems.\n\nHappy hacking!!!\n\n## License\n\n[MIT](LICENSE.txt)\n\nCopyright (c) 2024 Andy Maleh\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandyobtiva%2Fhow-to-build-desktop-applications-in-ruby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandyobtiva%2Fhow-to-build-desktop-applications-in-ruby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandyobtiva%2Fhow-to-build-desktop-applications-in-ruby/lists"}