konpeito 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.
Files changed (180) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +75 -0
  4. data/CONTRIBUTING.md +123 -0
  5. data/LICENSE +21 -0
  6. data/README.md +257 -0
  7. data/Rakefile +11 -0
  8. data/bin/konpeito +6 -0
  9. data/konpeito.gemspec +43 -0
  10. data/lib/konpeito/ast/typed_ast.rb +620 -0
  11. data/lib/konpeito/ast/visitor.rb +78 -0
  12. data/lib/konpeito/cache/cache_manager.rb +230 -0
  13. data/lib/konpeito/cache/dependency_graph.rb +192 -0
  14. data/lib/konpeito/cache.rb +8 -0
  15. data/lib/konpeito/cli/base_command.rb +187 -0
  16. data/lib/konpeito/cli/build_command.rb +220 -0
  17. data/lib/konpeito/cli/check_command.rb +104 -0
  18. data/lib/konpeito/cli/config.rb +231 -0
  19. data/lib/konpeito/cli/deps_command.rb +128 -0
  20. data/lib/konpeito/cli/doctor_command.rb +340 -0
  21. data/lib/konpeito/cli/fmt_command.rb +199 -0
  22. data/lib/konpeito/cli/init_command.rb +312 -0
  23. data/lib/konpeito/cli/lsp_command.rb +40 -0
  24. data/lib/konpeito/cli/run_command.rb +150 -0
  25. data/lib/konpeito/cli/test_command.rb +248 -0
  26. data/lib/konpeito/cli/watch_command.rb +212 -0
  27. data/lib/konpeito/cli.rb +301 -0
  28. data/lib/konpeito/codegen/builtin_methods.rb +229 -0
  29. data/lib/konpeito/codegen/cruby_backend.rb +1090 -0
  30. data/lib/konpeito/codegen/debug_info.rb +352 -0
  31. data/lib/konpeito/codegen/inliner.rb +486 -0
  32. data/lib/konpeito/codegen/jvm_backend.rb +197 -0
  33. data/lib/konpeito/codegen/jvm_generator.rb +13412 -0
  34. data/lib/konpeito/codegen/llvm_generator.rb +13191 -0
  35. data/lib/konpeito/codegen/loop_optimizer.rb +363 -0
  36. data/lib/konpeito/codegen/monomorphizer.rb +359 -0
  37. data/lib/konpeito/codegen/profile_runtime.c +341 -0
  38. data/lib/konpeito/codegen/profiler.rb +99 -0
  39. data/lib/konpeito/compiler.rb +592 -0
  40. data/lib/konpeito/dependency_resolver.rb +296 -0
  41. data/lib/konpeito/diagnostics/collector.rb +127 -0
  42. data/lib/konpeito/diagnostics/diagnostic.rb +237 -0
  43. data/lib/konpeito/diagnostics/renderer.rb +144 -0
  44. data/lib/konpeito/formatter/formatter.rb +1214 -0
  45. data/lib/konpeito/hir/builder.rb +7167 -0
  46. data/lib/konpeito/hir/nodes.rb +2465 -0
  47. data/lib/konpeito/lsp/document_manager.rb +820 -0
  48. data/lib/konpeito/lsp/server.rb +183 -0
  49. data/lib/konpeito/lsp/transport.rb +38 -0
  50. data/lib/konpeito/parser/prism_adapter.rb +65 -0
  51. data/lib/konpeito/platform.rb +103 -0
  52. data/lib/konpeito/profile/report.rb +136 -0
  53. data/lib/konpeito/rbs_inline/preprocessor.rb +199 -0
  54. data/lib/konpeito/stdlib/compression/compression.rb +72 -0
  55. data/lib/konpeito/stdlib/compression/compression.rbs +60 -0
  56. data/lib/konpeito/stdlib/compression/compression_native.c +415 -0
  57. data/lib/konpeito/stdlib/compression/extconf.rb +19 -0
  58. data/lib/konpeito/stdlib/crypto/crypto.rb +85 -0
  59. data/lib/konpeito/stdlib/crypto/crypto.rbs +74 -0
  60. data/lib/konpeito/stdlib/crypto/crypto_native.c +312 -0
  61. data/lib/konpeito/stdlib/crypto/extconf.rb +40 -0
  62. data/lib/konpeito/stdlib/http/extconf.rb +19 -0
  63. data/lib/konpeito/stdlib/http/http.rb +125 -0
  64. data/lib/konpeito/stdlib/http/http.rbs +57 -0
  65. data/lib/konpeito/stdlib/http/http_native.c +440 -0
  66. data/lib/konpeito/stdlib/json/extconf.rb +17 -0
  67. data/lib/konpeito/stdlib/json/json.rb +44 -0
  68. data/lib/konpeito/stdlib/json/json.rbs +33 -0
  69. data/lib/konpeito/stdlib/json/json_native.c +286 -0
  70. data/lib/konpeito/stdlib/ui/extconf.rb +216 -0
  71. data/lib/konpeito/stdlib/ui/konpeito_ui_native.cpp +1625 -0
  72. data/lib/konpeito/stdlib/ui/konpeito_ui_native.h +162 -0
  73. data/lib/konpeito/stdlib/ui/ui.rb +318 -0
  74. data/lib/konpeito/stdlib/ui/ui.rbs +247 -0
  75. data/lib/konpeito/type_checker/annotation_parser.rb +67 -0
  76. data/lib/konpeito/type_checker/hm_inferrer.rb +2565 -0
  77. data/lib/konpeito/type_checker/inferrer.rb +565 -0
  78. data/lib/konpeito/type_checker/rbs_loader.rb +1621 -0
  79. data/lib/konpeito/type_checker/type_resolver.rb +276 -0
  80. data/lib/konpeito/type_checker/types.rb +1434 -0
  81. data/lib/konpeito/type_checker/unification.rb +323 -0
  82. data/lib/konpeito/ui/animation/animated_state.rb +80 -0
  83. data/lib/konpeito/ui/animation/easing.rb +59 -0
  84. data/lib/konpeito/ui/animation/value_tween.rb +66 -0
  85. data/lib/konpeito/ui/app.rb +379 -0
  86. data/lib/konpeito/ui/box.rb +38 -0
  87. data/lib/konpeito/ui/castella.rb +70 -0
  88. data/lib/konpeito/ui/castella_native.rb +76 -0
  89. data/lib/konpeito/ui/chart/area_chart.rb +305 -0
  90. data/lib/konpeito/ui/chart/bar_chart.rb +288 -0
  91. data/lib/konpeito/ui/chart/base_chart.rb +210 -0
  92. data/lib/konpeito/ui/chart/chart_helpers.rb +79 -0
  93. data/lib/konpeito/ui/chart/gauge_chart.rb +171 -0
  94. data/lib/konpeito/ui/chart/heatmap_chart.rb +222 -0
  95. data/lib/konpeito/ui/chart/line_chart.rb +289 -0
  96. data/lib/konpeito/ui/chart/pie_chart.rb +219 -0
  97. data/lib/konpeito/ui/chart/scales.rb +77 -0
  98. data/lib/konpeito/ui/chart/scatter_chart.rb +303 -0
  99. data/lib/konpeito/ui/chart/stacked_bar_chart.rb +276 -0
  100. data/lib/konpeito/ui/column.rb +271 -0
  101. data/lib/konpeito/ui/core.rb +2199 -0
  102. data/lib/konpeito/ui/dsl.rb +443 -0
  103. data/lib/konpeito/ui/frame.rb +171 -0
  104. data/lib/konpeito/ui/frame_native.rb +494 -0
  105. data/lib/konpeito/ui/markdown/ast.rb +124 -0
  106. data/lib/konpeito/ui/markdown/mermaid/layout.rb +387 -0
  107. data/lib/konpeito/ui/markdown/mermaid/models.rb +232 -0
  108. data/lib/konpeito/ui/markdown/mermaid/parser.rb +519 -0
  109. data/lib/konpeito/ui/markdown/mermaid/renderer.rb +336 -0
  110. data/lib/konpeito/ui/markdown/parser.rb +805 -0
  111. data/lib/konpeito/ui/markdown/renderer.rb +639 -0
  112. data/lib/konpeito/ui/markdown/theme.rb +165 -0
  113. data/lib/konpeito/ui/render_node.rb +260 -0
  114. data/lib/konpeito/ui/row.rb +207 -0
  115. data/lib/konpeito/ui/spacer.rb +18 -0
  116. data/lib/konpeito/ui/style.rb +799 -0
  117. data/lib/konpeito/ui/theme.rb +563 -0
  118. data/lib/konpeito/ui/themes/material.rb +35 -0
  119. data/lib/konpeito/ui/themes/tokyo_night.rb +6 -0
  120. data/lib/konpeito/ui/widgets/button.rb +103 -0
  121. data/lib/konpeito/ui/widgets/calendar.rb +1034 -0
  122. data/lib/konpeito/ui/widgets/checkbox.rb +119 -0
  123. data/lib/konpeito/ui/widgets/container.rb +91 -0
  124. data/lib/konpeito/ui/widgets/data_table.rb +667 -0
  125. data/lib/konpeito/ui/widgets/divider.rb +29 -0
  126. data/lib/konpeito/ui/widgets/image.rb +105 -0
  127. data/lib/konpeito/ui/widgets/input.rb +485 -0
  128. data/lib/konpeito/ui/widgets/markdown.rb +57 -0
  129. data/lib/konpeito/ui/widgets/modal.rb +163 -0
  130. data/lib/konpeito/ui/widgets/multiline_input.rb +968 -0
  131. data/lib/konpeito/ui/widgets/multiline_text.rb +180 -0
  132. data/lib/konpeito/ui/widgets/net_image.rb +100 -0
  133. data/lib/konpeito/ui/widgets/progress_bar.rb +70 -0
  134. data/lib/konpeito/ui/widgets/radio_buttons.rb +93 -0
  135. data/lib/konpeito/ui/widgets/slider.rb +133 -0
  136. data/lib/konpeito/ui/widgets/switch.rb +84 -0
  137. data/lib/konpeito/ui/widgets/tabs.rb +157 -0
  138. data/lib/konpeito/ui/widgets/text.rb +110 -0
  139. data/lib/konpeito/ui/widgets/tree.rb +426 -0
  140. data/lib/konpeito/version.rb +5 -0
  141. data/lib/konpeito.rb +109 -0
  142. data/test_native_array.rb +172 -0
  143. data/test_native_array_class.rb +197 -0
  144. data/test_native_class.rb +151 -0
  145. data/tools/konpeito-asm/build.sh +65 -0
  146. data/tools/konpeito-asm/lib/asm-9.7.1.jar +0 -0
  147. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KArray.class +0 -0
  148. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCompression.class +0 -0
  149. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KConditionVariable.class +0 -0
  150. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCrypto.class +0 -0
  151. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KFile.class +0 -0
  152. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHTTP.class +0 -0
  153. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHash.class +0 -0
  154. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON$Parser.class +0 -0
  155. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON.class +0 -0
  156. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KMath.class +0 -0
  157. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactor.class +0 -0
  158. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactorPort.class +0 -0
  159. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KSizedQueue.class +0 -0
  160. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KThread.class +0 -0
  161. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KTime.class +0 -0
  162. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
  163. data/tools/konpeito-asm/src/ClassIntrospector.java +312 -0
  164. data/tools/konpeito-asm/src/KonpeitoAssembler.java +659 -0
  165. data/tools/konpeito-asm/src/konpeito/runtime/KArray.java +390 -0
  166. data/tools/konpeito-asm/src/konpeito/runtime/KCompression.java +168 -0
  167. data/tools/konpeito-asm/src/konpeito/runtime/KConditionVariable.java +48 -0
  168. data/tools/konpeito-asm/src/konpeito/runtime/KCrypto.java +151 -0
  169. data/tools/konpeito-asm/src/konpeito/runtime/KFile.java +100 -0
  170. data/tools/konpeito-asm/src/konpeito/runtime/KHTTP.java +113 -0
  171. data/tools/konpeito-asm/src/konpeito/runtime/KHash.java +228 -0
  172. data/tools/konpeito-asm/src/konpeito/runtime/KJSON.java +405 -0
  173. data/tools/konpeito-asm/src/konpeito/runtime/KMath.java +54 -0
  174. data/tools/konpeito-asm/src/konpeito/runtime/KRactor.java +244 -0
  175. data/tools/konpeito-asm/src/konpeito/runtime/KRactorPort.java +53 -0
  176. data/tools/konpeito-asm/src/konpeito/runtime/KSizedQueue.java +49 -0
  177. data/tools/konpeito-asm/src/konpeito/runtime/KThread.java +49 -0
  178. data/tools/konpeito-asm/src/konpeito/runtime/KTime.java +53 -0
  179. data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +416 -0
  180. metadata +267 -0
@@ -0,0 +1,379 @@
1
+ # rbs_inline: enabled
2
+
3
+ # App - main application loop with event dispatching
4
+ # Port of ~/castella/castella/core.py App
5
+
6
+ class App
7
+ #: (JWMFrame frame, untyped widget) -> void
8
+ def initialize(frame, widget)
9
+ @@current = self
10
+ @frame = frame
11
+ @root = widget
12
+ @downed = nil
13
+ @focused = nil
14
+ @mouse_overed = nil
15
+ @prev_abs_x = 0.0
16
+ @prev_abs_y = 0.0
17
+ @prev_rel_x = 0.0
18
+ @prev_rel_y = 0.0
19
+ @focusables = []
20
+ @prev_frame_w = 0.0
21
+ @prev_frame_h = 0.0
22
+ @cursor_x = 0.0
23
+ @cursor_y = 0.0
24
+ @animations = []
25
+ @last_frame_time = 0
26
+ end
27
+
28
+ #: () -> App?
29
+ def self.current
30
+ @@current
31
+ end
32
+
33
+ # Clear references to a widget being detached
34
+ #: (untyped w) -> void
35
+ def clear_widget_refs(w)
36
+ if @mouse_overed == w
37
+ @mouse_overed = nil
38
+ end
39
+ if @focused == w
40
+ @focused = nil
41
+ end
42
+ if @downed == w
43
+ @downed = nil
44
+ end
45
+ end
46
+
47
+ #: (untyped widget) -> void
48
+ def post_update(widget)
49
+ @frame.post_update(nil)
50
+ end
51
+
52
+ #: () -> void
53
+ def run
54
+ frame = @frame
55
+ root = @root
56
+ app = self
57
+
58
+ frame.on_redraw { |painter, completely|
59
+ # Tick animations
60
+ now = painter.current_time_millis
61
+ if @last_frame_time > 0
62
+ dt = (now - @last_frame_time).to_f
63
+ if dt > 100.0
64
+ dt = 100.0 # Cap to avoid jumps
65
+ end
66
+ any_active = false
67
+ i = 0
68
+ while i < @animations.length
69
+ still_going = @animations[i].tick(dt)
70
+ if still_going
71
+ any_active = true
72
+ end
73
+ i = i + 1
74
+ end
75
+ # Remove finished animations
76
+ new_anims = []
77
+ i = 0
78
+ while i < @animations.length
79
+ if @animations[i].animating?
80
+ new_anims << @animations[i]
81
+ end
82
+ i = i + 1
83
+ end
84
+ @animations = new_anims
85
+ if any_active
86
+ completely = true
87
+ frame.post_update(nil)
88
+ end
89
+ end
90
+ @last_frame_time = now
91
+
92
+ frame_size = frame.get_size
93
+ # Detect resize → force complete redraw
94
+ if frame_size.width != @prev_frame_w || frame_size.height != @prev_frame_h
95
+ @prev_frame_w = frame_size.width
96
+ @prev_frame_h = frame_size.height
97
+ completely = true
98
+ end
99
+
100
+ # Resize root based on size policy
101
+ rw = root.get_width_policy == EXPANDING ? frame_size.width : root.get_width
102
+ rh = root.get_height_policy == EXPANDING ? frame_size.height : root.get_height
103
+ root.resize_wh(rw, rh)
104
+ root.move_xy(0.0, 0.0)
105
+
106
+ if completely
107
+ painter.clear($theme.bg_canvas)
108
+ end
109
+ root.redraw(painter, completely)
110
+ }
111
+
112
+ frame.on_mouse_down { |ev|
113
+ result = root.dispatch(ev.pos)
114
+ target = result[0]
115
+ p = result[1]
116
+ if target
117
+ @prev_abs_x = ev.pos.x
118
+ @prev_abs_y = ev.pos.y
119
+ ev.pos = p
120
+ @prev_rel_x = p.x
121
+ @prev_rel_y = p.y
122
+ target.mouse_down(ev)
123
+ app.set_downed(target)
124
+ end
125
+ }
126
+
127
+ frame.on_mouse_up { |ev|
128
+ downed = app.get_downed
129
+ if downed
130
+ # Focus management: unfocus old, focus new
131
+ old_focused = app.get_focused
132
+ if old_focused != nil && old_focused != downed
133
+ old_focused.unfocused
134
+ end
135
+ app.set_focused(downed)
136
+ downed.focused
137
+
138
+ # Convert to local coordinates relative to downed widget
139
+ local_p = Point.new(ev.pos.x - downed.get_x, ev.pos.y - downed.get_y)
140
+ ev.pos = local_p
141
+ downed.mouse_up(ev)
142
+ app.set_downed(nil)
143
+ end
144
+ }
145
+
146
+ frame.on_cursor_pos { |ev|
147
+ app.set_cursor_xy(ev.pos.x, ev.pos.y)
148
+ result = root.dispatch(ev.pos)
149
+ target = result[0]
150
+ p = result[1]
151
+ downed = app.get_downed
152
+ overed = app.get_mouse_overed
153
+
154
+ if target == nil
155
+ # Cursor left all widgets
156
+ if overed != nil
157
+ overed.mouse_out
158
+ app.set_mouse_overed(nil)
159
+ end
160
+ elsif downed == nil
161
+ # No button pressed - handle hover
162
+ if overed == nil
163
+ app.set_mouse_overed(target)
164
+ target.mouse_over
165
+ elsif overed != target
166
+ overed.mouse_out
167
+ app.set_mouse_overed(target)
168
+ target.mouse_over
169
+ end
170
+ # Notify target of cursor position
171
+ if p != nil
172
+ target.cursor_pos(MouseEvent.new(p, 0))
173
+ end
174
+ else
175
+ # Button pressed - handle drag
176
+ diff_x = ev.pos.x - @prev_abs_x
177
+ diff_y = ev.pos.y - @prev_abs_y
178
+ @prev_abs_x = ev.pos.x
179
+ @prev_abs_y = ev.pos.y
180
+ drag_pos = Point.new(@prev_rel_x + diff_x, @prev_rel_y + diff_y)
181
+ @prev_rel_x = drag_pos.x
182
+ @prev_rel_y = drag_pos.y
183
+ downed.mouse_drag(MouseEvent.new(drag_pos, 0))
184
+ end
185
+ }
186
+
187
+ frame.on_mouse_wheel { |ev|
188
+ cursor = Point.new(app.get_cursor_x, app.get_cursor_y)
189
+ result = root.dispatch_to_scrollable(cursor, false)
190
+ target = result[0]
191
+ if target != nil
192
+ target.mouse_wheel(ev)
193
+ end
194
+ }
195
+
196
+ frame.on_input_char { |text|
197
+ focused = app.get_focused
198
+ focused.input_char(text) if focused
199
+ }
200
+
201
+ frame.on_input_key { |key_code, modifiers|
202
+ # Tab (JWM Key.TAB ordinal = 13): cycle focus
203
+ if key_code == 13
204
+ shift = (modifiers & 1) != 0
205
+ app.cycle_focus(root, shift)
206
+ else
207
+ focused = app.get_focused
208
+ focused.input_key(key_code, modifiers) if focused
209
+ end
210
+ }
211
+
212
+ frame.on_ime_preedit { |text, sel_start, sel_end|
213
+ focused = app.get_focused
214
+ focused.ime_preedit(text, sel_start, sel_end) if focused
215
+ }
216
+
217
+ frame.run
218
+ end
219
+
220
+ # Accessors for event state (used from blocks)
221
+ #: (untyped w) -> void
222
+ def set_downed(w)
223
+ @downed = w
224
+ end
225
+
226
+ #: () -> untyped
227
+ def get_downed
228
+ @downed
229
+ end
230
+
231
+ #: (untyped w) -> void
232
+ def set_focused(w)
233
+ @focused = w
234
+ end
235
+
236
+ #: () -> untyped
237
+ def get_focused
238
+ @focused
239
+ end
240
+
241
+ #: (untyped w) -> void
242
+ def set_mouse_overed(w)
243
+ @mouse_overed = w
244
+ end
245
+
246
+ #: () -> untyped
247
+ def get_mouse_overed
248
+ @mouse_overed
249
+ end
250
+
251
+ #: (Float x, Float y) -> void
252
+ def set_cursor_xy(x, y)
253
+ @cursor_x = x
254
+ @cursor_y = y
255
+ end
256
+
257
+ #: () -> Float
258
+ def get_cursor_x
259
+ @cursor_x
260
+ end
261
+
262
+ #: () -> Float
263
+ def get_cursor_y
264
+ @cursor_y
265
+ end
266
+
267
+ # --- Animation ---
268
+
269
+ #: (untyped anim) -> void
270
+ def register_animation(anim)
271
+ i = 0
272
+ while i < @animations.length
273
+ return if @animations[i] == anim
274
+ i = i + 1
275
+ end
276
+ @animations << anim
277
+ @frame.post_update(nil)
278
+ end
279
+
280
+ #: (untyped anim) -> void
281
+ def unregister_animation(anim)
282
+ new_list = []
283
+ i = 0
284
+ while i < @animations.length
285
+ if @animations[i] != anim
286
+ new_list << @animations[i]
287
+ end
288
+ i = i + 1
289
+ end
290
+ @animations = new_list
291
+ end
292
+
293
+ # --- Clipboard ---
294
+
295
+ #: () -> String
296
+ def get_clipboard_text
297
+ @frame.get_clipboard_text
298
+ end
299
+
300
+ #: (String text) -> void
301
+ def set_clipboard_text(text)
302
+ @frame.set_clipboard_text(text)
303
+ end
304
+
305
+ # --- Text Input / IME ---
306
+
307
+ #: () -> void
308
+ def enable_text_input
309
+ @frame.enable_text_input
310
+ end
311
+
312
+ #: () -> void
313
+ def disable_text_input
314
+ @frame.disable_text_input
315
+ end
316
+
317
+ #: (Integer x, Integer y, Integer w, Integer h) -> void
318
+ def set_ime_cursor_rect(x, y, w, h)
319
+ @frame.set_ime_cursor_rect(x, y, w, h)
320
+ end
321
+
322
+ # --- Focus Management ---
323
+ # Collect focusable widgets from tree into @focusables array
324
+
325
+ #: (untyped widget) -> void
326
+ def collect_focusables_from(widget)
327
+ if widget.is_focusable
328
+ @focusables << widget
329
+ end
330
+ children = widget.get_children
331
+ i = 0
332
+ while i < children.length
333
+ collect_focusables_from(children[i])
334
+ i = i + 1
335
+ end
336
+ end
337
+
338
+ #: (untyped root, bool reverse) -> void
339
+ def cycle_focus(root, reverse)
340
+ @focusables = []
341
+ collect_focusables_from(root)
342
+ count = @focusables.length
343
+ return if count == 0
344
+
345
+ # Find current focused index
346
+ current_idx = -1
347
+ i = 0
348
+ while i < count
349
+ if @focusables[i] == @focused
350
+ current_idx = i
351
+ end
352
+ i = i + 1
353
+ end
354
+
355
+ # Compute next index
356
+ next_idx = 0
357
+ if reverse
358
+ next_idx = current_idx - 1
359
+ if next_idx < 0
360
+ next_idx = count - 1
361
+ end
362
+ else
363
+ next_idx = current_idx + 1
364
+ if next_idx >= count
365
+ next_idx = 0
366
+ end
367
+ end
368
+
369
+ new_focus = @focusables[next_idx]
370
+ old = @focused
371
+ if old != nil
372
+ old.unfocused
373
+ end
374
+ @focused = new_focus
375
+ new_focus.focused
376
+ end
377
+ # Initialize @@current
378
+ @@current = nil
379
+ end
@@ -0,0 +1,38 @@
1
+ # rbs_inline: enabled
2
+
3
+ # Box layout - overlay/stack of children (all at same position)
4
+ # Port of Castella Box
5
+
6
+ class Box < Layout
7
+ def initialize
8
+ super
9
+ end
10
+
11
+ #: (untyped painter) -> void
12
+ def relocate_children(painter)
13
+ i = 0
14
+ while i < @children.length
15
+ c = @children[i]
16
+ if c.get_width_policy == EXPANDING
17
+ c.resize_wh(@width, c.get_height)
18
+ end
19
+ if c.get_height_policy == EXPANDING
20
+ c.resize_wh(c.get_width, @height)
21
+ end
22
+ c.move_xy(@x, @y)
23
+ i = i + 1
24
+ end
25
+ end
26
+ end
27
+
28
+ # Top-level helper
29
+ #: (*untyped children) -> Box
30
+ def Box(*children)
31
+ box = Box.new
32
+ i = 0
33
+ while i < children.length
34
+ box.add(children[i])
35
+ i = i + 1
36
+ end
37
+ box
38
+ end
@@ -0,0 +1,70 @@
1
+ # Castella UI - umbrella require
2
+ #
3
+ # Loads all Castella UI components in one line:
4
+ # require_relative "../../lib/konpeito/ui/castella"
5
+
6
+ # Core
7
+ require_relative "render_node"
8
+ require_relative "core"
9
+ require_relative "column"
10
+ require_relative "row"
11
+ require_relative "box"
12
+ require_relative "spacer"
13
+ require_relative "theme"
14
+
15
+ # Widgets
16
+ require_relative "widgets/text"
17
+ require_relative "widgets/button"
18
+ require_relative "widgets/divider"
19
+ require_relative "widgets/container"
20
+ require_relative "widgets/input"
21
+ require_relative "widgets/multiline_input"
22
+ require_relative "widgets/checkbox"
23
+ require_relative "widgets/radio_buttons"
24
+ require_relative "widgets/switch"
25
+ require_relative "widgets/slider"
26
+ require_relative "widgets/progress_bar"
27
+ require_relative "widgets/tabs"
28
+ require_relative "widgets/data_table"
29
+ require_relative "widgets/tree"
30
+ require_relative "widgets/calendar"
31
+ require_relative "widgets/modal"
32
+ require_relative "widgets/image"
33
+ require_relative "widgets/net_image"
34
+
35
+ # Markdown
36
+ require_relative "markdown/ast"
37
+ require_relative "markdown/theme"
38
+ require_relative "markdown/parser"
39
+ require_relative "markdown/mermaid/models"
40
+ require_relative "markdown/mermaid/parser"
41
+ require_relative "markdown/mermaid/layout"
42
+ require_relative "markdown/mermaid/renderer"
43
+ require_relative "markdown/renderer"
44
+ require_relative "widgets/markdown"
45
+
46
+ # Charts
47
+ require_relative "chart/chart_helpers"
48
+ require_relative "chart/scales"
49
+ require_relative "chart/base_chart"
50
+ require_relative "chart/bar_chart"
51
+ require_relative "chart/line_chart"
52
+ require_relative "chart/pie_chart"
53
+ require_relative "chart/scatter_chart"
54
+ require_relative "chart/area_chart"
55
+ require_relative "chart/stacked_bar_chart"
56
+ require_relative "chart/gauge_chart"
57
+ require_relative "chart/heatmap_chart"
58
+
59
+ # Animation
60
+ require_relative "animation/easing"
61
+ require_relative "animation/value_tween"
62
+ require_relative "animation/animated_state"
63
+
64
+ # Framework
65
+ require_relative "frame"
66
+ require_relative "app"
67
+
68
+ # DSL
69
+ require_relative "style"
70
+ require_relative "dsl"
@@ -0,0 +1,76 @@
1
+ # Castella UI - umbrella require (NativeFrame / LLVM backend)
2
+ #
3
+ # Same as castella.rb but uses NativeFrame (SDL3+Skia) instead of JWMFrame (JVM)
4
+ # require_relative "../../lib/konpeito/ui/castella_native"
5
+ #
6
+ # Prerequisites:
7
+ # 1. SDL3: brew install sdl3 (macOS) / apt install libsdl3-dev (Linux)
8
+ # 2. Skia: Build or download, set SKIA_DIR=~/skia-prebuilt
9
+ # 3. Build: cd lib/konpeito/stdlib/ui && ruby extconf.rb && make
10
+ # 4. Check: konpeito doctor --target ui
11
+
12
+ # Core
13
+ require_relative "render_node"
14
+ require_relative "core"
15
+ require_relative "column"
16
+ require_relative "row"
17
+ require_relative "box"
18
+ require_relative "spacer"
19
+ require_relative "theme"
20
+
21
+ # Widgets
22
+ require_relative "widgets/text"
23
+ require_relative "widgets/button"
24
+ require_relative "widgets/divider"
25
+ require_relative "widgets/container"
26
+ require_relative "widgets/input"
27
+ require_relative "widgets/multiline_input"
28
+ require_relative "widgets/checkbox"
29
+ require_relative "widgets/radio_buttons"
30
+ require_relative "widgets/switch"
31
+ require_relative "widgets/slider"
32
+ require_relative "widgets/progress_bar"
33
+ require_relative "widgets/tabs"
34
+ require_relative "widgets/data_table"
35
+ require_relative "widgets/tree"
36
+ require_relative "widgets/calendar"
37
+ require_relative "widgets/modal"
38
+ require_relative "widgets/image"
39
+ require_relative "widgets/net_image"
40
+
41
+ # Markdown
42
+ require_relative "markdown/ast"
43
+ require_relative "markdown/theme"
44
+ require_relative "markdown/parser"
45
+ require_relative "markdown/mermaid/models"
46
+ require_relative "markdown/mermaid/parser"
47
+ require_relative "markdown/mermaid/layout"
48
+ require_relative "markdown/mermaid/renderer"
49
+ require_relative "markdown/renderer"
50
+ require_relative "widgets/markdown"
51
+
52
+ # Charts
53
+ require_relative "chart/chart_helpers"
54
+ require_relative "chart/scales"
55
+ require_relative "chart/base_chart"
56
+ require_relative "chart/bar_chart"
57
+ require_relative "chart/line_chart"
58
+ require_relative "chart/pie_chart"
59
+ require_relative "chart/scatter_chart"
60
+ require_relative "chart/area_chart"
61
+ require_relative "chart/stacked_bar_chart"
62
+ require_relative "chart/gauge_chart"
63
+ require_relative "chart/heatmap_chart"
64
+
65
+ # Animation
66
+ require_relative "animation/easing"
67
+ require_relative "animation/value_tween"
68
+ require_relative "animation/animated_state"
69
+
70
+ # NativeFrame (SDL3 + Skia Metal) instead of JWMFrame
71
+ require_relative "frame_native"
72
+ require_relative "app"
73
+
74
+ # DSL
75
+ require_relative "style"
76
+ require_relative "dsl"