citrine-native 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +46 -0
- data/GOALS.md +361 -0
- data/LICENSE +21 -0
- data/README.md +293 -0
- data/lib/citrine/native/app.rb +126 -0
- data/lib/citrine/native/area_handle.rb +49 -0
- data/lib/citrine/native/painter.rb +625 -0
- data/lib/citrine/native/pointer_event.rb +48 -0
- data/lib/citrine/native/renderer.rb +884 -0
- data/lib/citrine/native/style_matrix.rb +127 -0
- data/lib/citrine/native/timer.rb +88 -0
- data/lib/citrine/native/version.rb +9 -0
- data/lib/citrine/native/widgets/libui.rb +1022 -0
- data/lib/citrine/native/widgets/memory.rb +526 -0
- data/lib/citrine/native/widgets.rb +179 -0
- data/lib/citrine/native.rb +89 -0
- data/lib/citrine-native.rb +5 -0
- metadata +130 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Citrine
|
|
4
|
+
module Native
|
|
5
|
+
# 控件适配层(决策 N-1 的"接口预留"):渲染器只认这一层,不直接调 libui API——
|
|
6
|
+
# 未来加 GTK 第二后端时只替换本层实现(GOALS 第三节)。
|
|
7
|
+
#
|
|
8
|
+
# 句柄(handle)是**不透明对象**:Libui 后端下是 `Fiddle::Pointer`,
|
|
9
|
+
# Memory 后端下是 `Widgets::Memory::Widget`。渲染器只负责把它挂在
|
|
10
|
+
# `Node#dom` 上、再原样交回本层,不解读内容(与 DOM 渲染器对待元素同一口径)。
|
|
11
|
+
#
|
|
12
|
+
# libui 的能力缺口在**本层**吸收,渲染器不写 `if 后端 == libui`:
|
|
13
|
+
# - box 只有 append / delete-by-index,没有 insert:顺序由本层记账后重排
|
|
14
|
+
# (`uiBoxDelete` 只摘除不销毁,实测结论见 GOALS 变更日志 N1)
|
|
15
|
+
# - 每个控件每种事件只有一个回调位:本层做多订阅分发
|
|
16
|
+
# - 自绘面板(area)的事件也只有单回调位,且 libui 调用它们前不做 NULL 检查
|
|
17
|
+
# ——五个回调槽必须在创建时全部装上
|
|
18
|
+
module Widgets
|
|
19
|
+
class << self
|
|
20
|
+
# 默认后端:libui(决策 N-1)。测试注入 Memory 后端:
|
|
21
|
+
# Renderer.new(widgets: Widgets::Memory.new)
|
|
22
|
+
def default
|
|
23
|
+
require_relative "widgets/libui"
|
|
24
|
+
Libui.new
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# 内存打桩后端(CRuby 单测用;不加载 libui)
|
|
28
|
+
def memory
|
|
29
|
+
Memory.new
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# 后端协议。渲染器用到的每个方法都在此声明;后端没实现的直接抛
|
|
34
|
+
# NotImplementedError(能力缺口不许静默降级成"少画一块")。
|
|
35
|
+
#
|
|
36
|
+
# 线程模型(GOALS 4.4):所有控件操作都必须在主线程做——libui 的回调
|
|
37
|
+
# 本身在主线程触发,因此应用逻辑无需考虑跨线程;后台线程想更新 UI,
|
|
38
|
+
# 必须用 `queue_main` 把块排回主线程。
|
|
39
|
+
class Base
|
|
40
|
+
# 允许后端只实现自己有的能力:声明 required 方法,缺省实现即报错
|
|
41
|
+
def self.required(*names)
|
|
42
|
+
names.each do |name|
|
|
43
|
+
define_method(name) do |*_args, **_kwargs, &_block|
|
|
44
|
+
raise NotImplementedError, "#{self.class}##{name} 未实现(控件适配层协议,见 widgets.rb)"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# ── 工具包生命周期与主循环 ──────────────────────────────
|
|
50
|
+
# 初始化工具包(幂等;libui 后端每次调用都走 uiInit,可重复调用)
|
|
51
|
+
def init; end
|
|
52
|
+
|
|
53
|
+
# 反初始化(退出前调用;libui 后端在还有控件存活时会警告泄漏)
|
|
54
|
+
def shutdown; end
|
|
55
|
+
|
|
56
|
+
# 阻塞跑事件循环,直到 quit 被调用。所有控件回调都在这里面触发。
|
|
57
|
+
required :main_loop
|
|
58
|
+
|
|
59
|
+
# 请求退出主循环(可从回调内调用;libui 的 uiQuit 是线程安全的)
|
|
60
|
+
required :quit
|
|
61
|
+
|
|
62
|
+
# 把块排到主线程执行(后台线程更新 UI 的唯一合法通道)
|
|
63
|
+
required :queue_main
|
|
64
|
+
|
|
65
|
+
# 同 queue_main,但**块执行完就不该再被任何人引用**(可以 GC)。语义差别只在
|
|
66
|
+
# "闭包是否常驻",用于"反复排队且每次都是一次性闭包"的路径:定时器每次到点
|
|
67
|
+
# (timer.rb)、绘制期延后重绘(libui.rb 的 flush_deferred_redraws)。
|
|
68
|
+
# libui 后端覆写成真正不常驻的版本;缺省实现退化为 queue_main(桩后端等
|
|
69
|
+
# 没有常驻问题的后端不必关心它)。
|
|
70
|
+
def queue_main_once(&block)
|
|
71
|
+
queue_main(&block)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# ── 窗口 ────────────────────────────────────────────────
|
|
75
|
+
required :create_window, :window_set_child, :window_on_closing,
|
|
76
|
+
:window_show, :window_destroy
|
|
77
|
+
|
|
78
|
+
# ── 容器(box:libui 的横/竖排列容器,与 stack/row 同构)──
|
|
79
|
+
required :create_box, :box_append, :box_remove, :box_children
|
|
80
|
+
|
|
81
|
+
# 把 child 挪到 target 之前(target 为 nil → 挪到末尾)。
|
|
82
|
+
# 落位是平台钩子 `attach_before` 的底座,见 renderer.rb 的实现说明。
|
|
83
|
+
required :box_move_before
|
|
84
|
+
|
|
85
|
+
# 粗粒度内边距(citrine 的 gap 样式键只有 0/非 0 两档,GOALS 4.5)
|
|
86
|
+
required :set_padding
|
|
87
|
+
|
|
88
|
+
# ── 叶子控件 ────────────────────────────────────────────
|
|
89
|
+
required :create_label, :create_button, :create_entry, :create_checkbox,
|
|
90
|
+
:set_text, :get_text, :set_enabled, :destroy
|
|
91
|
+
|
|
92
|
+
# 受控值:entry 的文本、checkbox 的勾选态(双向绑定用;写入是静默的,
|
|
93
|
+
# 不会反过来触发 on_change/on_toggle——两个后端都保证这一点)
|
|
94
|
+
required :set_value, :get_value, :set_checked, :checked?
|
|
95
|
+
|
|
96
|
+
# ── 事件订阅(每个控件每种事件可挂多个订阅者)──────────
|
|
97
|
+
# 块在用户操作时触发;控件被销毁后不再触发。
|
|
98
|
+
def on_click(_control, &_block)
|
|
99
|
+
raise NotImplementedError, "#{self.class}#on_click 未实现:本后端不支持按钮点击"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# 输入变更(entry)/ 勾选变更(checkbox)都走这里——按控件种类落到原生回调
|
|
103
|
+
def on_change(_control, &_block)
|
|
104
|
+
raise NotImplementedError, "#{self.class}#on_change 未实现:本后端不支持变更事件"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# ── 自绘面板(area,设计 2.1 / 2.3 / 2.5)──────────────
|
|
108
|
+
# 面板把绘制与输入都交给应用:适配层只负责"建控件 → 装回调 → 把事件与
|
|
109
|
+
# Painter 转交订阅者",以及三个面板特有的操作(重绘/滚动/焦点)。
|
|
110
|
+
required :create_area, :area_queue_redraw
|
|
111
|
+
|
|
112
|
+
# 订阅面板事件(每个面板每种事件一个回调位 → 与控件订阅同一套多路分发)。
|
|
113
|
+
# 回调拿到的都是**平台无关**的形态:
|
|
114
|
+
# on_area_draw(area) { |painter| } painter 是 Painter 或 Painter::Recording
|
|
115
|
+
# on_area_pointer(area) { |event| } event = {kind: :down/:up/:move,
|
|
116
|
+
# x:, y:, button:, count:,
|
|
117
|
+
# modifiers: {shift:, ctrl:, alt:, meta:}}
|
|
118
|
+
# on_area_key(area) { |event| } event = {key: "ArrowUp", up: false, modifiers: {…}}
|
|
119
|
+
# 键名已归一成 DOM 风格(平台归一在适配层做);
|
|
120
|
+
# 块返回真值 = 已处理(libui 据此抑制系统提示音)
|
|
121
|
+
# on_area_crossed(area) { |left| } true = 鼠标离开面板
|
|
122
|
+
# on_area_drag_broken(area) { } 拖拽被系统打断
|
|
123
|
+
def on_area_draw(_area, &_block)
|
|
124
|
+
raise NotImplementedError, "#{self.class}#on_area_draw 未实现:本后端不支持自绘面板"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def on_area_pointer(_area, &_block)
|
|
128
|
+
raise NotImplementedError, "#{self.class}#on_area_pointer 未实现:本后端不支持自绘面板"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def on_area_key(_area, &_block)
|
|
132
|
+
raise NotImplementedError, "#{self.class}#on_area_key 未实现:本后端不支持自绘面板"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def on_area_crossed(_area, &_block)
|
|
136
|
+
raise NotImplementedError, "#{self.class}#on_area_crossed 未实现:本后端不支持自绘面板"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def on_area_drag_broken(_area, &_block)
|
|
140
|
+
raise NotImplementedError, "#{self.class}#on_area_drag_broken 未实现:本后端不支持自绘面板"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# 仅滚动面板:uiAreaScrollTo(非滚动面板上调它会 abort 进程,所以后端要拦住)
|
|
144
|
+
def area_scroll_to(_area, _x, _y, _w, _h)
|
|
145
|
+
raise NotImplementedError, "#{self.class}#area_scroll_to 未实现"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# 这个面板有没有滚动条(AreaHandle#scrollable? 用)
|
|
149
|
+
def area_scrollable?(_area) = false
|
|
150
|
+
|
|
151
|
+
# 把键盘焦点给面板(设计 2.3):返回 true/false,做不到就如实返回 false
|
|
152
|
+
def area_focus(_area) = false
|
|
153
|
+
|
|
154
|
+
# 面板**真实可见视口**的尺寸 [w, h](诊断 + dev_mode 的"面板被压扁"提醒用)。
|
|
155
|
+
# 滚动面板下它不等于 Painter 的尺寸(后者是声明的内容尺寸):libui 后端读
|
|
156
|
+
# clip view 的真实边界。后端没有这个信息(桩后端、还没布局、非 macOS)时返回
|
|
157
|
+
# nil —— 提醒逻辑据此只按 Painter 尺寸判断。
|
|
158
|
+
def area_visible_size(_area) = nil
|
|
159
|
+
|
|
160
|
+
# ── 窗口激活(设计 2.3:macOS 下 uiControlShow 之后窗口不是 key window,
|
|
161
|
+
# 必须先激活应用,键盘才有人收)────────────────────────
|
|
162
|
+
# 返回 true/false(后端没有激活能力时如实返回 false)
|
|
163
|
+
def window_activate(_window) = false
|
|
164
|
+
|
|
165
|
+
# 控件种类(:window/:box/:label/:button/:entry/:checkbox/:area):诊断与断言用
|
|
166
|
+
required :kind
|
|
167
|
+
|
|
168
|
+
# 句柄 → 稳定字符串(日志与错误信息用;不参与逻辑判定)
|
|
169
|
+
def describe(handle)
|
|
170
|
+
"#<#{kind(handle)}>"
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# 桩后端始终随适配层加载(不依赖 libui,测试与真实后端并存的成本只是一个小文件)。
|
|
178
|
+
# 放在文件末尾:Memory < Base 需要 Base 已定义。
|
|
179
|
+
require_relative "widgets/memory"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Citrine::Native — Citrine 组件的 CRuby 原生运行时(Shoes 式:ruby app.rb 直接起窗口)。
|
|
4
|
+
#
|
|
5
|
+
# 设计与计划见 GOALS.md。本 gem 实现 `Citrine::Renderer` 的平台钩子(renderer.rb),
|
|
6
|
+
# 把节点树翻译成原生控件树;只依赖 citrine 的平台无关核心,**不引入 Opal**。
|
|
7
|
+
#
|
|
8
|
+
# require "citrine-native"
|
|
9
|
+
#
|
|
10
|
+
# class Counter < Citrine::Component
|
|
11
|
+
# state :count, 0
|
|
12
|
+
# def view
|
|
13
|
+
# stack(gap: 8) do
|
|
14
|
+
# label { "计数:#{count}" }
|
|
15
|
+
# button(on_click: -> { self.count += 1 }) { "点我 +1" }
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# Citrine::Native.run(Counter, title: "计数器", width: 400, height: 300)
|
|
21
|
+
|
|
22
|
+
require "citrine"
|
|
23
|
+
|
|
24
|
+
module Citrine
|
|
25
|
+
module Native
|
|
26
|
+
# 本 gem 的基类异常(组件代码不必 rescue,出错就是要看见)
|
|
27
|
+
class Error < StandardError; end
|
|
28
|
+
|
|
29
|
+
# 元素/属性在原生后端没有对应概念(GOALS 4.3:不静默降级)
|
|
30
|
+
class UnsupportedElementError < Error; end
|
|
31
|
+
|
|
32
|
+
# 后端工具包不可用(缺少 libui 动态库等)
|
|
33
|
+
class ToolkitUnavailableError < Error; end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
require_relative "native/version"
|
|
38
|
+
require_relative "native/style_matrix"
|
|
39
|
+
require_relative "native/pointer_event"
|
|
40
|
+
require_relative "native/painter"
|
|
41
|
+
require_relative "native/area_handle"
|
|
42
|
+
require_relative "native/widgets"
|
|
43
|
+
require_relative "native/renderer"
|
|
44
|
+
require_relative "native/timer"
|
|
45
|
+
require_relative "native/app"
|
|
46
|
+
|
|
47
|
+
module Citrine
|
|
48
|
+
module Native
|
|
49
|
+
class << self
|
|
50
|
+
# 活动后端(适配层实例):由 Renderer 建立时登记(与核心"活动渲染器 = 最近
|
|
51
|
+
# 挂载的那个"同口径)。定时器靠它把自己排回主线程,应用一般不用碰。
|
|
52
|
+
attr_accessor :active_widgets
|
|
53
|
+
|
|
54
|
+
# 周期定时器(设计 2.5)→ Timer 句柄,可 #stop;块在主线程执行
|
|
55
|
+
#
|
|
56
|
+
# @ticker = Citrine::Native.every(200) { self.tick }
|
|
57
|
+
# # on_unmount 里:@ticker.stop
|
|
58
|
+
def every(milliseconds, &block) = Timer.every(milliseconds, &block)
|
|
59
|
+
|
|
60
|
+
# 一次性定时器(设计 2.5)
|
|
61
|
+
def after(milliseconds, &block) = Timer.after(milliseconds, &block)
|
|
62
|
+
|
|
63
|
+
# 起一个原生窗口应用(阻塞到窗口关闭)。
|
|
64
|
+
#
|
|
65
|
+
# Citrine::Native.run(Counter, title: "计数器", width: 400, height: 300)
|
|
66
|
+
#
|
|
67
|
+
# component 可以是组件类(无 prop 构造)或已构造的实例。
|
|
68
|
+
# 其余关键字直接作为窗口描述交给渲染器:title / width / height / margined。
|
|
69
|
+
#
|
|
70
|
+
# dev_mode 默认开:原生运行时没有构建管线(脚本即应用),开发期提醒
|
|
71
|
+
# (未支持的样式键/属性、未声明方向的 box)应当直接可见;显式传
|
|
72
|
+
# dev_mode: false 可关掉,传 nil 则保留调用方此前的设置。
|
|
73
|
+
#
|
|
74
|
+
# signals 默认 nil(不接管进程级信号):库不该悄悄覆盖宿主已有的处理器。
|
|
75
|
+
# 把运行脚本当独立进程时传 `signals: :default`,Ctrl+C / SIGTERM 就会走
|
|
76
|
+
# "退出主循环 → 有序拆解",而不是硬杀(见 App#trap_quit!)。
|
|
77
|
+
def run(component, dev_mode: true, widgets: nil, **options)
|
|
78
|
+
Citrine.dev_mode = dev_mode unless dev_mode.nil?
|
|
79
|
+
App.new(component, widgets: widgets, **options).run
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# 只建窗口挂组件、不进主循环(测试与自管事件循环用)
|
|
83
|
+
def start(component, dev_mode: nil, widgets: nil, **options)
|
|
84
|
+
Citrine.dev_mode = dev_mode unless dev_mode.nil?
|
|
85
|
+
App.new(component, widgets: widgets, **options).tap(&:setup)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: citrine-native
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- ShiningRay
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: citrine
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.2'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.2'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: libui
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.1'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.1'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: base64
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0.2'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0.2'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: minitest
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '5.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '5.0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: rake
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '13.0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '13.0'
|
|
82
|
+
description: citrine-native:Citrine 组件的 CRuby 原生运行时。不经 Opal/JS,同一份信号式组件代码直接用 ruby
|
|
83
|
+
启动为桌面窗口应用(Shoes 精神)。实现 Citrine::Renderer 协议,首版后端为 libui(原生控件)。
|
|
84
|
+
email:
|
|
85
|
+
- shiningray@users.noreply.github.com
|
|
86
|
+
executables: []
|
|
87
|
+
extensions: []
|
|
88
|
+
extra_rdoc_files: []
|
|
89
|
+
files:
|
|
90
|
+
- CHANGELOG.md
|
|
91
|
+
- GOALS.md
|
|
92
|
+
- LICENSE
|
|
93
|
+
- README.md
|
|
94
|
+
- lib/citrine-native.rb
|
|
95
|
+
- lib/citrine/native.rb
|
|
96
|
+
- lib/citrine/native/app.rb
|
|
97
|
+
- lib/citrine/native/area_handle.rb
|
|
98
|
+
- lib/citrine/native/painter.rb
|
|
99
|
+
- lib/citrine/native/pointer_event.rb
|
|
100
|
+
- lib/citrine/native/renderer.rb
|
|
101
|
+
- lib/citrine/native/style_matrix.rb
|
|
102
|
+
- lib/citrine/native/timer.rb
|
|
103
|
+
- lib/citrine/native/version.rb
|
|
104
|
+
- lib/citrine/native/widgets.rb
|
|
105
|
+
- lib/citrine/native/widgets/libui.rb
|
|
106
|
+
- lib/citrine/native/widgets/memory.rb
|
|
107
|
+
homepage: https://github.com/ShiningRay/citrine-native
|
|
108
|
+
licenses:
|
|
109
|
+
- MIT
|
|
110
|
+
metadata:
|
|
111
|
+
source_code_uri: https://github.com/ShiningRay/citrine-native
|
|
112
|
+
changelog_uri: https://github.com/ShiningRay/citrine-native/blob/main/CHANGELOG.md
|
|
113
|
+
rdoc_options: []
|
|
114
|
+
require_paths:
|
|
115
|
+
- lib
|
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
|
+
requirements:
|
|
118
|
+
- - ">="
|
|
119
|
+
- !ruby/object:Gem::Version
|
|
120
|
+
version: 3.1.0
|
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
|
+
requirements:
|
|
123
|
+
- - ">="
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0'
|
|
126
|
+
requirements: []
|
|
127
|
+
rubygems_version: 4.0.20
|
|
128
|
+
specification_version: 4
|
|
129
|
+
summary: CRuby native runtime for Citrine components (Shoes-style desktop apps)
|
|
130
|
+
test_files: []
|