giraffe

Elm-style declarative UI framework for MoonBit, built on GTK4

gtk
gui
elm
declarative
ui
framework
moon add tonyfettes/giraffe@0.2.0
Download zip
Version
0.2.0
License
Apache-2.0
Last updated
23 days ago
Downloads
32
README

#giraffe

An Elm-architecture declarative UI framework for MoonBit, built on the GTK bindings.

#Overview

Giraffe lets you build GTK4 applications using the Model-Update-View pattern (also known as The Elm Architecture):

  1. Define a Model (application state)
  2. Define a Message type (events that change state)
  3. Write an update function (Model, Message) -> Model
  4. Write a render function that produces a virtual widget tree

Giraffe handles widget creation, diffing, and reconciliation automatically.

#Example

fn main {
@giraffe.app(
model={ count: 0 },
update=(model, message) => {
match message {
Increment => { count: model.count + 1 }
Decrement => { count: model.count - 1 }
}
},
render=(model, dispatch) => {
@giraffe.window(
title="Counter",
@giraffe.box(spacing=12) [
@giraffe.label(text="\{model.count}"),
@giraffe.button(label="+", on_clicked=dispatch(Increment)),
@giraffe.button(label="-", on_clicked=dispatch(Decrement)),
],
)
},
)
}

#Supported widgets

  • window — top-level window
  • box — horizontal/vertical container (children as Array or Map)
  • button — clickable button with on_clicked callback
  • label — text display
  • entry — text input with on_changed callback

#Architecture

ModuleRole
app.mbtState management, dispatch loop, idle-based re-rendering
widget.mbtVirtual widget tree definition and children types
iwidget.mbtInternal GTK widget wrappers
reconcile.mbtWidget tree diffing and patching
cmd.mbtCommand type for dispatching side effects

#
Align

pub(all) enum Align {
Fill
Start
End
Center
}

#
Orientation

pub(all) enum Orientation {
Horizontal
Vertical
}

#
Update

type Update[Model, Message]

#
VWidget

type VWidget[Message]

#
adw_action_row

fn[Message] adw_action_row(title? : String, subtitle? : String, prefix? : Array[VWidget[Message]], suffix? : Array[VWidget[Message]]) -> VWidget[Message]

#
adw_app

fn[Model, Message] adw_app(id? : String, model~ : Model, init? : Message, update~ : Update[Model, Message], render~ : (Model) -> VWidget[Message], subscribe? :
Subscribe
[Model, Message]) -> Unit

#
adw_application_window

fn[Message] adw_application_window(title? : String, default_width? : Int, default_height? : Int, content : VWidget[Message]) -> VWidget[Message]

#
adw_clamp

fn[Message] adw_clamp(maximum_size? : Int, child : VWidget[Message]) -> VWidget[Message]

#
adw_header_bar

fn[Message] adw_header_bar(title_widget? : VWidget[Message], start? : Array[VWidget[Message]], end? : Array[VWidget[Message]]) -> VWidget[Message]

#
adw_navigation_split_view

fn[Message] adw_navigation_split_view(sidebar~ : VWidget[Message], sidebar_title? : String, content~ : VWidget[Message], content_title? : String, min_sidebar_width? : Double, max_sidebar_width? : Double, sidebar_width_fraction? : Double) -> VWidget[Message]

#
adw_toolbar_view

fn[Message] adw_toolbar_view(top_bar? : VWidget[Message], bottom_bar? : VWidget[Message], content : VWidget[Message]) -> VWidget[Message]

#
app

fn[Model, Message] app(id? : String, model~ : Model, init? : Message, update~ : Update[Model, Message], render~ : (Model) -> VWidget[Message], subscribe? :
Subscribe
[Model, Message]) -> Unit

#
box

fn[Message] box(orientation? : Orientation, spacing? : Int, margin? : Int, margin_top? : Int, margin_bottom? : Int, margin_start? : Int, margin_end? : Int, halign? : Align, css_classes? : Array[String], children : Array[VWidget[Message]]) -> VWidget[Message]

#
button

fn[Message] button(label? : String, icon_name? : String, css_classes? : Array[String], on_clicked~ : Message) -> VWidget[Message]

#
check_button

fn[Message] check_button(active? : Bool, on_toggled~ : (Bool) -> Message) -> VWidget[Message]

#
effect

fn[Model, Message, Effect] effect(update : (Model, Message) -> (Model, Effect), handle : (Effect, (Message) -> Unit) -> Unit) -> Update[Model, Message]

#
entry

fn[Message] entry(text? : String, placeholder? : String, hexpand? : Bool, on_changed~ : (String) -> Message, on_activate? : Message) -> VWidget[Message]

#
label

fn[Message] label(text? : String, markup? : Bool, wrap? : Bool, selectable? : Bool, xalign? : Double, max_width_chars? : Int, css_classes? : Array[String]) -> VWidget[Message]

#
list_box

fn[Message] list_box(css_classes? : Array[String], children : Map[String, VWidget[Message]]) -> VWidget[Message]

#
scrolled_window

fn[Message] scrolled_window(hscrollbar_policy? :
PolicyType
, vscrollbar_policy? :
PolicyType
, vexpand? : Bool, child : VWidget[Message]) -> VWidget[Message]

#
separator

fn[Message] separator(orientation? : Orientation) -> VWidget[Message]

#
update

fn[Model, Message] update(f : (Model, Message) -> Model) -> Update[Model, Message]

#
window

fn[Message] window(title? : String, default_width? : Int, default_height? : Int, child : VWidget[Message]) -> VWidget[Message]