uing

Bindings for libui-ng libui libui-ng
0.0.0 released
kojix2/uing
27 3
kojix2

UIng

test Lines of Code Ask DeepWiki

UIng is a Crystal binding for libui-ng.

libui-ng uses the native APIs of each platform: Win32 API and GDI+ on Windows, Cocoa on macOS, and GTK3 and Cairo on Linux. You get windows, buttons, text boxes, menus, dialogs, drawing areas, and other standard widgets with the look and feel of each OS. The binary size is small.

Windows Mac Linux

Quick Start

Clone the repository and try the examples:

git clone https://github.com/kojix2/uing
cd uing
crystal run download.cr
crystal run examples/control_gallery.cr

Windows MSVC Setup

For Windows users using MSVC, use Developer Command Prompt or add Windows Kits path:

$env:Path += ";C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64"

Installation

Add the dependency to your shard.yml:

dependencies:
  uing:
    github: kojix2/uing

The required libui-ng binary is automatically downloaded from the kojix2/libui-ng GitHub Releases via postinstall.

Supported Platforms

  • macOS: x86_64 (64-bit), ARM64 (Apple Silicon)
  • Linux: x86_64 (64-bit), ARM64, ARM (32-bit)
  • Windows: x86_64 (64-bit, MSVC and MinGW), x86 (32-bit, MSVC only)

Usage

require "uing"

UIng.init

window = UIng::Window.new("Hello World", 300, 200)
window.on_closing do
  UIng.quit
  true
end

button = UIng::Button.new("Click me")
button.on_clicked do
  UIng.msg_box(window, "Info", "Button clicked!")
end

window.set_child(button)
window.show

UIng.main
UIng.uninit

DSL style

require "uing"

UIng.init do
  UIng::Window.new("Hello World", 300, 200) { |win|
    on_closing { UIng.quit; true }
    set_child {
      UIng::Button.new("Click me") {
        on_clicked {
          UIng.msg_box(win, "Info", "Button clicked!")
        }
      }
    }
    show
  }

  UIng.main
end

Note: The DSL style is implemented using Crystal's with ... yield syntax internally.

Examples

The examples/control_gallery.cr script shows most of the available controls and features in one window.
You can run it with:

crystal run examples/control_gallery.cr

For more examples, see the examples directory.

API Levels

Level Defined in Example Description
High-Level src/uing/*.cr button.on_clicked { }, etc. Object-oriented API
Low-Level src/uing/lib_ui/lib_ui.cr UIng::LibUI.new_button, etc. Direct bindings to libui
  • Almost all basic control functions such as Window, Label, and Button are covered.
  • APIs for advanced controls such as Table and Area are also provided. However, these are still under development and there may still be memory management issues.

Memory Safety

  • Most callbacks are stored as instance variables of their respective controls, which protects them from garbage collection (GC). Some callbacks are stored as UIng class variables, which serves the same purpose.

  • Instances of a control are passed as arguments to a parent control's append or set_child method. This establishes a reference from the parent to the child, creating a reference chain such as Window -> Box -> Button. This chain prevents the Garbage Collector (GC) from collecting the Button object (and its callbacks), thus avoiding a segmentation fault as long as the Window is present.

  • Some root components, such as Window and Menu, are stored as class variables to ensure protection from GC. This may cause memory leaks, but is acceptable for now.

  • The use of finalize is intentionally avoided in certain cases because the non-deterministic timing of memory deallocation by the GC is often incompatible with libui. Instead, RAII-style API is provided that automatically calls the free method upon exiting a block, relieving users of the need to call free manually.

Windows Setup

Hide Console Window

MinGW:

crystal build app.cr --link-flags "-mwindows"

MSVC:

crystal build app.cr --link-flags=/SUBSYSTEM:WINDOWS

Closures in Low-Level Contexts

  • Many methods support Crystal closures because the underlying libui-ng functions accept a data parameter.

  • In some low-level APIs, such as function pointers assigned to struct members, no data can be passed. UIng works around this by using struct inheritance and boxed data to support closures in these cases.

  • This approach is used in controls like Table and Area.

Development

  • UIng::LibUI is the module for direct C bindings
  • Initially, crystal_lib was used to generate low-level bindings   - However, it required many manual conversions, such as changing LibC::Int to Bool. Currently, it is better to use AI.
  • When adding new UI components, follow the established callback management patterns
  • libui libraries are generated using GitHub Actions at kojix2/libui-ng in the pre-build branch.

Note:
This project was developed with the assistance of generative AI.
While kojix2 prefers Vibe Coding, this library is not a product of Vibe Coding. it has been created with a good amount of manual work and human review.

Contributing

  • Fork this repository
  • Report bugs and submit pull requests
  • Improve documentation
  • Test memory safety improvements

License

MIT License

uing:
  github: kojix2/uing
  version: ~> 0.0.0
License MIT
Crystal none

Authors

Dependencies 0

Development Dependencies 0

Dependents 0

Last synced .
search fire star recently