Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,7 @@ build-iPhoneSimulator/

*.dll
*.so
*.exp
*.lib

.vscode
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/xframes-ruby.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added .ruby-version
Binary file not shown.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@

#### Windows

I recommend to install Ruby via [Scoop](https://scoop.sh/), then
I recommend to install Ruby via [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/):

`winget install RubyInstallerTeam.RubyWithDevKit.3.2`

The reason why you need the dev kit is that the event machine gem needs to be compiled on the target machine.

Then install the dependencies (you likely need to close all terminals first):

- `gem install ffi`
- `gem install eventmachine`
- `gem install rx`

`RUBY_DLL_PATH` must be set:

Expand All @@ -20,6 +27,7 @@ I recommend to install Ruby via [Scoop](https://scoop.sh/), then
- `sudo apt install ruby-full`
- `sudo gem install ffi`
- `sudo gem install eventmachine`
- `sudo gem install rx`

### Run the application

Expand All @@ -34,4 +42,3 @@ Windows 11
Raspberry Pi 5

![image](https://github.com/user-attachments/assets/190f8603-a6db-45c6-a5f0-cfd4dc1b87e2)

96 changes: 5 additions & 91 deletions main.rb
Original file line number Diff line number Diff line change
@@ -1,63 +1,11 @@
require 'ffi'
require 'json'
require 'eventmachine'

ImGuiCol = {
Text: 0,
TextDisabled: 1,
WindowBg: 2,
ChildBg: 3,
PopupBg: 4,
Border: 5,
BorderShadow: 6,
FrameBg: 7,
FrameBgHovered: 8,
FrameBgActive: 9,
TitleBg: 10,
TitleBgActive: 11,
TitleBgCollapsed: 12,
MenuBarBg: 13,
ScrollbarBg: 14,
ScrollbarGrab: 15,
ScrollbarGrabHovered: 16,
ScrollbarGrabActive: 17,
CheckMark: 18,
SliderGrab: 19,
SliderGrabActive: 20,
Button: 21,
ButtonHovered: 22,
ButtonActive: 23,
Header: 24,
HeaderHovered: 25,
HeaderActive: 26,
Separator: 27,
SeparatorHovered: 28,
SeparatorActive: 29,
ResizeGrip: 30,
ResizeGripHovered: 31,
ResizeGripActive: 32,
Tab: 33,
TabHovered: 34,
TabActive: 35,
TabUnfocused: 36,
TabUnfocusedActive: 37,
PlotLines: 38,
PlotLinesHovered: 39,
PlotHistogram: 40,
PlotHistogramHovered: 41,
TableHeaderBg: 42,
TableBorderStrong: 43,
TableBorderLight: 44,
TableRowBg: 45,
TableRowBgAlt: 46,
TextSelectedBg: 47,
DragDropTarget: 48,
NavHighlight: 49,
NavWindowingHighlight: 50,
NavWindowingDimBg: 51,
ModalWindowDimBg: 52,
COUNT: 53
}
require_relative 'theme'
require_relative 'sampleapp'
require_relative 'services'
require_relative 'treetraversal'
require_relative 'xframes'

# Colors for theme generation
theme2Colors = {
Expand Down Expand Up @@ -181,40 +129,6 @@ def to_json(*options)
end


module XFrames
extend FFI::Library
if RUBY_PLATFORM =~ /win32|mingw|cygwin/
ffi_lib './xframesshared.dll'
else
ffi_lib './libxframesshared.so'
end

# Define callback types
callback :OnInitCb, [:pointer], :void
callback :OnTextChangedCb, [:int, :string], :void
callback :OnComboChangedCb, [:int, :int], :void
callback :OnNumericValueChangedCb, [:int, :float], :void
callback :OnBooleanValueChangedCb, [:int, :int], :void
callback :OnMultipleNumericValuesChangedCb, [:int, :pointer, :int], :void
callback :OnClickCb, [:int], :void

attach_function :init, [
:string, # assetsBasePath
:string, # rawFontDefinitions
:string, # rawStyleOverrideDefinitions
:OnInitCb,
:OnTextChangedCb,
:OnComboChangedCb,
:OnNumericValueChangedCb,
:OnBooleanValueChangedCb,
:OnMultipleNumericValuesChangedCb,
:OnClickCb
], :void

attach_function :setElement, [:string], :void

attach_function :setChildren, [:int, :string], :void
end

on_init = FFI::Function.new(:void, []) do
puts "OnInit called!"
Expand Down
95 changes: 95 additions & 0 deletions sampleapp.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require 'rx'
require_relative 'theme'
require_relative 'widgetnode'

class TodoItem
attr_accessor :text, :done

def initialize(text, done)
@text = text
@done = done
end
end

class AppState
attr_accessor :todo_text, :todo_items

def initialize(todo_text, todo_items)
@todo_text = todo_text
@todo_items = todo_items
end
end

sample_app_state = Rx::BehaviorSubject.new(AppState.new("", []))

def on_click
new_todo_item = TodoItem.new("New Todo", false)

current_state = sample_app_state.value

new_state = AppState.new(
current_state.todo_text,
current_state.todo_items + [new_todo_item]
)

sample_app_state.on_next(new_state)
end

text_style = WidgetStyle.new(
style: WidgetStyleDef.new(
style_rules: StyleRules.new(
font: FontDef.new(name: "roboto-regular", size: 32)
)
)
)

button_style = WidgetStyle.new(
style: WidgetStyleDef.new(
style_rules: StyleRules.new(
font: FontDef.new(name: "roboto-regular", size: 32)
),
layout: YogaStyle.new(
width: "50%",
padding: {Edge[:Vertical] => 10},
margin: {Edge[:Left] => 140}
)
)
)

class App < BaseComponent
def initialize
super({})

@app_state_subscription = sample_app_state.subscribe do |latest_app_state|
props.on_next({
"todo_text" => latest_app_state.todo_text,
"todo_items" => latest_app_state.todo_items
})
end
end

def render
children = [button("Add todo", method(:on_click), button_style)]

props.value["todo_items"].each do |todo_item|
text = "#{todo_item.text} (#{todo_item.done ? 'done' : 'to do'})."
children << unformatted_text(text, text_style)
end

node(children)
end

def dispose
@app_state_subscription.dispose
end
end

class Root < BaseComponent
def initialize
super({})
end

def render
root_node([App.new])
end
end
Loading