hokusai-zero 0.1.2 → 0.1.4

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/Gemfile.lock +4 -0
  4. data/README.md +4 -2
  5. data/ast/src/core/hml.c +9 -9
  6. data/ast/src/core/text.c +1 -3
  7. data/ast/test/text.c +3 -3
  8. data/docs.sh +29 -0
  9. data/ext/extconf.rb +50 -12
  10. data/grammar/corpus/1_document.txt +24 -0
  11. data/grammar/corpus/6_styles.txt +23 -0
  12. data/grammar/grammar.js +4 -4
  13. data/grammar/src/grammar.json +19 -19
  14. data/grammar/src/parser.c +1904 -1956
  15. data/grammar/test.nml +10 -8
  16. data/hokusai.gemspec +5 -1
  17. data/ui/examples/assets/Delius-Regular.ttf +0 -0
  18. data/ui/examples/assets/DoHyeon.ttf +0 -0
  19. data/ui/examples/assets/Inter-Regular.ttf +0 -0
  20. data/ui/examples/assets/ernest.gif +0 -0
  21. data/ui/examples/assets/icons/audio-x-generic.png +0 -0
  22. data/ui/examples/assets/icons/image-x-generic.png +0 -0
  23. data/ui/examples/assets/icons/media-playback-pause.png +0 -0
  24. data/ui/examples/assets/icons/media-playback-start.png +0 -0
  25. data/ui/examples/assets/icons/media-playback-stop.png +0 -0
  26. data/ui/examples/assets/icons/package-x-generic.png +0 -0
  27. data/ui/examples/assets/icons/text-x-generic.png +0 -0
  28. data/ui/examples/assets/icons/video-x-generic.png +0 -0
  29. data/ui/examples/buddy.rb +16 -14
  30. data/ui/examples/clock.rb +38 -36
  31. data/ui/examples/counter.rb +100 -98
  32. data/ui/examples/dynamic.rb +115 -113
  33. data/ui/examples/foobar.rb +189 -187
  34. data/ui/examples/forum/file.rb +54 -0
  35. data/ui/examples/forum/music.rb +76 -0
  36. data/ui/examples/forum/post.rb +146 -0
  37. data/ui/examples/forum.rb +198 -0
  38. data/ui/examples/spreadsheet/csv.rb +261 -0
  39. data/ui/examples/spreadsheet.rb +138 -0
  40. data/ui/examples/stock.rb +86 -92
  41. data/ui/examples/stock_decider/option.rb +1 -1
  42. data/ui/examples/tic_tac_toe.rb +193 -191
  43. data/ui/lib/lib_hokusai.rb +0 -1
  44. data/ui/spec/hokusai/automation/keys_transcoder_spec.rb +5 -5
  45. data/ui/spec/hokusai/e2e/client_spec.rb +1 -0
  46. data/ui/spec/hokusai/e2e/meta_spec.rb +36 -36
  47. data/ui/spec/spec_helper.rb +13 -6
  48. data/ui/src/hokusai/ast.rb +42 -43
  49. data/ui/src/hokusai/backends/raylib/font.rb +1 -2
  50. data/ui/src/hokusai/backends/raylib.rb +16 -7
  51. data/ui/src/hokusai/backends/sdl2/font.rb +13 -9
  52. data/ui/src/hokusai/backends/sdl2.rb +5 -5
  53. data/ui/src/hokusai/block.rb +7 -0
  54. data/ui/src/hokusai/blocks/hblock.rb +2 -2
  55. data/ui/src/hokusai/blocks/image.rb +5 -1
  56. data/ui/src/hokusai/blocks/input.rb +17 -0
  57. data/ui/src/hokusai/blocks/label.rb +5 -2
  58. data/ui/src/hokusai/blocks/text.rb +10 -5
  59. data/ui/src/hokusai/blocks/titlebar/osx.rb +4 -4
  60. data/ui/src/hokusai/blocks/variable.rb +33 -0
  61. data/ui/src/hokusai/blocks/vblock.rb +1 -1
  62. data/ui/src/hokusai/commands/rect.rb +4 -4
  63. data/ui/src/hokusai/commands.rb +33 -31
  64. data/ui/src/hokusai/diff.rb +11 -0
  65. data/ui/src/hokusai/event.rb +19 -5
  66. data/ui/src/hokusai/events/mouse.rb +9 -1
  67. data/ui/src/hokusai/font.rb +60 -0
  68. data/ui/src/hokusai/meta.rb +10 -16
  69. data/ui/src/hokusai/node.rb +1 -1
  70. data/ui/src/hokusai/painter.rb +1 -2
  71. data/ui/src/hokusai/util/clamping_iterator.rb +5 -6
  72. data/ui/src/hokusai.rb +36 -4
  73. data/xmake.lua +5 -4
  74. metadata +79 -3
@@ -16,31 +16,31 @@ describe Hokusai::Automation::KeysTranscoder do
16
16
 
17
17
  it "decodes a string with modifiers" do
18
18
  with_encoded([:shift, 'h'], 'e','l','l','o') do |encoded|
19
- decode(encoded).should eq([[:lshift, 'h'], 'e','l','l','o'])
19
+ expect(decode(encoded)).to eq([[:lshift, 'h'], 'e','l','l','o'])
20
20
  end
21
21
  end
22
22
 
23
23
  it "decodes multiple modifiers" do
24
24
  with_encoded([:shift, 'h'], [:ctrl, 'e','l','l','o']) do |encoded|
25
- decode(encoded).should eq([[:lshift, 'h'], [:lctrl, 'e','l','l','o']])
25
+ expect(decode(encoded)).to eq([[:lshift, 'h'], [:lctrl, 'e','l','l','o']])
26
26
  end
27
27
  end
28
28
 
29
29
  it "encodes a simple string" do
30
30
  with_encoded('h','e','l','l','o') do |encoded|
31
- encoded.should eq("hello")
31
+ expect(encoded).to eq("hello")
32
32
  end
33
33
  end
34
34
 
35
35
  it "encodeds a modifier key" do
36
36
  with_encoded(:tab) do |encoded|
37
- encoded.should eq("\ue004")
37
+ expect(encoded).to eq("\ue004")
38
38
  end
39
39
  end
40
40
 
41
41
  it "encodes mmultiple modifiers" do
42
42
  with_encoded([:shift, 'h'], [:ctrl, 'e','l','l','o']) do |encoded|
43
- encoded.should eq("\ue008h\ue000\ue009ello\ue000")
43
+ expect(encoded).to eq("\ue008h\ue000\ue009ello\ue000")
44
44
  end
45
45
  end
46
46
 
@@ -19,6 +19,7 @@ describe Hokusai::Automation::Client do
19
19
  attr_accessor :count
20
20
 
21
21
  def increment(_event)
22
+ # pp ["INCREMENTING FUCK"]
22
23
  self.count += 1
23
24
  end
24
25
 
@@ -1,42 +1,42 @@
1
- describe Hokusai::Meta do
2
- let(:app) do
3
- Class.new(Hokusai::Block) do
4
- template <<~EOF
5
- [template]
6
- hblock#focus
7
- empty#first
8
- empty#second
9
- hblock#unfocus
10
- empty#third
11
- empty#fourth
12
- EOF
1
+ # describe Hokusai::Meta do
2
+ # let(:app) do
3
+ # Class.new(Hokusai::Block) do
4
+ # template <<~EOF
5
+ # [template]
6
+ # hblock#focus
7
+ # empty#first
8
+ # empty#second
9
+ # hblock#unfocus
10
+ # empty#third
11
+ # empty#fourth
12
+ # EOF
13
13
 
14
- uses(
15
- hblock: Hokusai::Blocks::Hblock,
16
- empty: Hokusai::Blocks::Empty
17
- )
18
- end
19
- end
14
+ # uses(
15
+ # hblock: Hokusai::Blocks::Hblock,
16
+ # empty: Hokusai::Blocks::Empty
17
+ # )
18
+ # end
19
+ # end
20
20
 
21
- describe "focusing" do
22
- it "#focus focuses this block and all of it's children" do
23
- with_app(app) do |client, app|
24
- child_to_focus = app.children.first
25
- child_to_focus.node.meta.focus
21
+ # describe "focusing" do
22
+ # it "#focus focuses this block and all of it's children" do
23
+ # with_app(app) do |client, app|
24
+ # child_to_focus = app.children.first
25
+ # child_to_focus.node.meta.focus
26
26
 
27
- expect(child_to_focus.node.meta.focused).to be(true)
27
+ # expect(child_to_focus.node.meta.focused).to be(true)
28
28
 
29
- child_to_focus.children.each do |child|
30
- expect(child.node.meta.focused).to be(true)
31
- end
29
+ # child_to_focus.children.each do |child|
30
+ # expect(child.node.meta.focused).to be(true)
31
+ # end
32
32
 
33
- child_unfocused = app.children.last
34
- expect(child_unfocused.node.meta.focused).to be(false)
33
+ # child_unfocused = app.children.last
34
+ # expect(child_unfocused.node.meta.focused).to be(false)
35
35
 
36
- child_unfocused.children.each do |child|
37
- expect(child.node.meta.focused).to be(false)
38
- end
39
- end
40
- end
41
- end
42
- end
36
+ # child_unfocused.children.each do |child|
37
+ # expect(child.node.meta.focused).to be(false)
38
+ # end
39
+ # end
40
+ # end
41
+ # end
42
+ # end
@@ -15,16 +15,23 @@ def with_app(app, &block)
15
15
  config.title = "Test application"
16
16
  end
17
17
 
18
- block = app.mount
18
+ client = nil
19
+ error = nil
19
20
 
20
21
  Hokusai::ThreadPool.post do
21
- backend.run(block)
22
+ client = Hokusai::Automation::Client.start
23
+
24
+ yield client
25
+ rescue Exception => ex
26
+ error = ex
27
+ ensure
28
+ backend.class.stop!
22
29
  end
23
30
 
24
- client = Hokusai::Automation::Client.start
25
- yield client, block
31
+ init = app.mount
32
+ backend.run(init)
26
33
 
27
- backend.class.stop!
34
+ client&.wait_until_stopped
28
35
 
29
- client.wait_until_stopped
36
+ raise error if error
30
37
  end
@@ -25,15 +25,21 @@ module Hokusai
25
25
  end
26
26
 
27
27
  # The loop variable
28
+ #
28
29
  # eg [for="item in list"]
29
30
  # the var is `item`
31
+ #
32
+ # @return [String]
30
33
  def var
31
34
  @name ||= raw[:name].freeze
32
35
  end
33
36
 
34
37
  # The loop method
38
+ #
35
39
  # eg [for="item in list"]
36
40
  # the method is `list`
41
+ #
42
+ # @return [String]
37
43
  def method
38
44
  @list_name ||= raw[:list_name].freeze
39
45
  end
@@ -49,6 +55,7 @@ module Hokusai
49
55
  end
50
56
 
51
57
  # Name of the func
58
+ #
52
59
  # eg @target="run_this(one,two)"
53
60
  # the name is `run_this`
54
61
  #
@@ -58,6 +65,7 @@ module Hokusai
58
65
  end
59
66
 
60
67
  # Args of the func
68
+ #
61
69
  # eg @target="run_this(one, two)"
62
70
  # the args are [one, two]
63
71
  #
@@ -74,6 +82,7 @@ module Hokusai
74
82
  class Event
75
83
  attr_reader :raw
76
84
 
85
+ # @param [LibHokusai::Event] raw event
77
86
  def initialize(raw)
78
87
  @raw = raw
79
88
  end
@@ -93,6 +102,7 @@ module Hokusai
93
102
  end
94
103
  end
95
104
 
105
+ # A node representing an ast prop
96
106
  class Prop
97
107
  attr_reader :raw
98
108
 
@@ -100,14 +110,17 @@ module Hokusai
100
110
  @raw = raw
101
111
  end
102
112
 
113
+ # @return [Bool] is this prop computed?
103
114
  def computed?
104
115
  raw[:computed]
105
116
  end
106
117
 
118
+ # @return [String] the props name
107
119
  def name
108
120
  @name ||= raw[:name].freeze
109
121
  end
110
122
 
123
+ # @return [Ast::Func] the props value
111
124
  def value
112
125
  @call ||= raw[:call]
113
126
 
@@ -166,60 +179,74 @@ module Hokusai
166
179
  end
167
180
  end
168
181
 
182
+ # Marks this ast as dirty
183
+ # @return [Void]
169
184
  def dirty!
170
185
  @dirty = true
171
186
  end
172
187
 
188
+ # Is this ast dirty?
189
+ # @return [Bool]
173
190
  def dirty?
174
191
  @dirty
175
192
  end
176
193
 
194
+ # @return [Bool] is this node a slot?
177
195
  def slot?
178
196
  type == "slot"
179
197
  end
180
198
 
199
+ # @return [Bool] is this node virtual?
181
200
  def virtual?
182
201
  type == "virtual"
183
202
  end
184
203
 
204
+ # @return [Bool] does this node belong to a loop?
185
205
  def loop?
186
206
  @loop_condition = !raw[:loop].null? if @loop_condition.nil?
187
207
 
188
208
  @loop_condition
189
209
  end
190
210
 
211
+ # @return [Bool] does this node have an if condition?
191
212
  def has_if_condition?
192
213
  @if_condition = !raw[:cond].null? if @if_condition.nil?
193
214
 
194
215
  @if_condition
195
216
  end
196
217
 
218
+ # @return [Bool] does this node have an else condition?
197
219
  def has_else_condition?
198
220
  @else_condition = !raw[:else_relations].null? if @else_condition.nil?
199
221
 
200
222
  @else_condition
201
223
  end
202
224
 
225
+ # @return [Bool] is the else condition on this node currently active?
203
226
  def else_condition_active?
204
227
  has_else_condition? && @else_active == 1
205
228
  end
206
229
 
230
+ # @param [Bool] else condition is active or not
207
231
  def else_active=(val)
208
232
  @else_active = val
209
233
  end
210
234
 
235
+ # @return [Hokusai::Ast?] the ast of the else condition
211
236
  def else_ast
212
237
  return nil unless has_else_condition?
213
238
 
214
239
  Ast.new(raw[:else_relations][:next_child])
215
240
  end
216
241
 
242
+ # @return [Ast::Loop?] the loop that the ast belongs to
217
243
  def loop
218
244
  return nil unless loop?
219
245
 
220
246
  @loop ||= Loop.new(raw[:loop])
221
247
  end
222
248
 
249
+ # @return [Ast::Func?] the if condition of this ast
223
250
  def if
224
251
  @cond ||= raw[:cond]
225
252
 
@@ -232,14 +259,17 @@ module Hokusai
232
259
  @func ||= Func.new(@call)
233
260
  end
234
261
 
262
+ # @return [String] the node type
235
263
  def type
236
264
  @type ||= raw[:type].nil? ? "(null)" : raw[:type]
237
265
  end
238
266
 
267
+ # @return [String] the node id
239
268
  def id
240
269
  @id ||= raw[:id].nil? ? "(null)" : raw[:id]
241
270
  end
242
271
 
272
+ # @return [Array<String>] the list of classes for this node
243
273
  def classes
244
274
  return @classes unless @classes.nil?
245
275
 
@@ -251,6 +281,7 @@ module Hokusai
251
281
  @classes
252
282
  end
253
283
 
284
+ # @return [Array<Hokusai::Ast>] all the children of this node
254
285
  def children
255
286
  return @children unless @children.nil?
256
287
 
@@ -262,6 +293,7 @@ module Hokusai
262
293
  @children
263
294
  end
264
295
 
296
+ # @return [Array<Hokusai::Ast>] all the siblings of this node
265
297
  def siblings
266
298
  return @siblings unless @siblings.nil?
267
299
 
@@ -277,6 +309,7 @@ module Hokusai
277
309
  @siblings
278
310
  end
279
311
 
312
+ # @return [Array<Hokusai::Ast>] the children of the else condition for this node
280
313
  def else_children
281
314
  children = []
282
315
 
@@ -290,6 +323,7 @@ module Hokusai
290
323
  children
291
324
  end
292
325
 
326
+ # @return [Array<Ast::Prop>] all the props of this node
293
327
  def props
294
328
  return @props unless @props.nil?
295
329
 
@@ -302,6 +336,7 @@ module Hokusai
302
336
  @props
303
337
  end
304
338
 
339
+ # @return [Array<Ast::Event>] all the events of this node
305
340
  def events
306
341
  return @events unless @events.nil?
307
342
 
@@ -382,60 +417,24 @@ module Hokusai
382
417
  i.free
383
418
  end
384
419
 
420
+ # Fetches a prop by name
421
+ #
422
+ # @param [String] name of the prop
423
+ # @return [Ast::Prop?] the prop or nil
385
424
  def prop(name)
386
425
  props[name]
387
426
  end
388
427
 
389
- # Search for a prop by name
390
- #
391
- # @param [String] name the name of the prop to find
392
- # @return [Hokusai::Ast::Prop?] the prop if found
393
- # def prop(name)
394
- # prop_ptr = FFI::MemoryPointer.new :pointer
395
- # code = LibHokusai.hoku_ast_prop_init(prop_ptr, name)
428
+ # Fetches an event by name
396
429
  #
397
- # raise Hokusai::Error.new("Failed to allocate prop") unless code.zero?
398
- #
399
- # prop_ptr2 = prop_ptr.get_pointer(0)
400
- # prop = LibHokusai::HmlAstProp.new(prop_ptr2)
401
- # response = LibHokusai.hoku_ast_get_prop(raw, prop)
402
- # return nil if response.null?
403
- #
404
- # Prop.new(response)
405
- # ensure
406
- # prop_ptr.free
407
- # end
408
-
430
+ # @param [String] the name of the event
431
+ # @return [Ast::Event?] the event or nil
409
432
  def event(name)
410
433
  events[name]
411
434
  end
412
435
 
413
- # Search for an event by name
414
- #
415
- # @param [String] name the name of the prop to find
416
- # @return [Prop?] the prop if found
417
- # def event(name)
418
- # event_ptr = FFI::MemoryPointer.new :pointer
419
- # code = LibHokusai.hoku_ast_prop_init(event_ptr, name)
420
- #
421
- # raise Hokusai::Error.new("Failed to allocate prop") unless code.zero?
422
- #
423
- # event_ptr2 = event_ptr.get_pointer(0)
424
- # event = LibHokusai::HmlAstEvent.new(event_ptr2)
425
- # response = LibHokusai.hoku_ast_get_event(raw, event)
426
- # event_ptr.free
427
- #
428
- # return nil if response.null?
429
- #
430
- # Event.new(response)
431
- # ensure
432
- # event_ptr.free
433
- # end
434
-
435
436
  def destroy
436
- puts "before destroy"
437
437
  LibHokusai.hoku_ast_free(raw)
438
- puts "after destroy"
439
438
  end
440
439
 
441
440
  # dumps this ast to STDOUT
@@ -20,7 +20,7 @@ module Hokusai
20
20
  OnWidthCb = Proc.new do |char, ffi_pointer|
21
21
  data = DataForCb.new ffi_pointer
22
22
 
23
- Raylib.MeasureTextEx(data[:raw], "#{char.chr}", data[:size], data[:spacing]).x + data[:spacing]
23
+ Raylib.MeasureTextEx(data[:raw], "#{char.chr}", data[:size], data[:spacing]).x + 1.565#@ data[:spacing]
24
24
  end
25
25
 
26
26
  class Font < Hokusai::Font
@@ -83,7 +83,6 @@ module Hokusai
83
83
  raw.baseSize
84
84
  end
85
85
 
86
-
87
86
  def clamp_markdown(text, size, width, initial_offset = 0.0)
88
87
  clamping_pointer = FFI::MemoryPointer.new :pointer
89
88
  RaylibBackend::DataForCb.create(size, spacing, raw) do |ptr|
@@ -37,8 +37,8 @@ module Hokusai::Backends
37
37
  yield(config)
38
38
  end
39
39
 
40
- def vec2(x, y)
41
- if @raylib_vec2.nil?
40
+ def vec2(x, y, fresh = false)
41
+ if @raylib_vec2.nil? || fresh
42
42
  @raylib_vec2 = Raylib::Vector2.new
43
43
  end
44
44
  @raylib_vec2[:x] = x
@@ -201,7 +201,9 @@ module Hokusai::Backends
201
201
  height = last_height
202
202
 
203
203
  process_input(input)
204
+ block.public_send(:before_updated) if block.respond_to?(:before_updated)
204
205
  block.update
206
+ block.public_send(:after_updated) if block.respond_to?(:after_updated)
205
207
 
206
208
  canvas.reset(nil, nil, width.to_f, height.to_f)
207
209
 
@@ -368,7 +370,12 @@ module Hokusai::Backends
368
370
  Hokusai::Commands::Text.on_draw do |command|
369
371
  next unless inside_scissor(command.x, command.y, command.size)
370
372
 
373
+ active_name = Hokusai.fonts.active_font_name
371
374
  font = Hokusai.fonts.active
375
+
376
+ Hokusai.fonts.activate command.font.nil? ? active_name : command.font
377
+ font = Hokusai.fonts.active
378
+
372
379
  c = color(command.color)
373
380
  x = command.x + command.padding.l
374
381
  y = command.y + command.padding.t
@@ -380,6 +387,8 @@ module Hokusai::Backends
380
387
  else
381
388
  Raylib.DrawText(command.content, x, y, command.size, c)
382
389
  end
390
+
391
+ Hokusai.fonts.activate active_name
383
392
  end
384
393
 
385
394
  Hokusai::Commands::Rect.on_draw do |command|
@@ -407,26 +416,26 @@ module Hokusai::Backends
407
416
 
408
417
  # now draw the outlines
409
418
  if command.outline_uniform? && command.rounding > 0.0 && outline_color.a > 0
410
- Raylib.DrawRectangleRoundedLines(outline_rect, command.rounding, 50, command.outline.top, outline_color)
419
+ Raylib.DrawRectangleRoundedLinesEx(outline_rect, command.rounding, 50, command.outline.top + 1, outline_color)
411
420
  elsif command.outline_uniform? && !(command.rounding <= 0.0) && outline_color.a > 0
412
421
  Raylib.DrawRectangleLinesEx(outline_rect, command.outline.top, outline_color)
413
422
  elsif !command.outline_uniform?
414
423
  ox, oy, ow, oh = command.background_boundary
415
424
 
416
425
  if command.outline.top > 0.0
417
- Raylib.DrawLineEx(vec2(ox, oy), vec2(ox + ow, oy), command.outline.top, outline_color)
426
+ Raylib.DrawLineEx(vec2(ox, oy, true), vec2(ox + ow, oy, true), command.outline.top, outline_color)
418
427
  end
419
428
 
420
429
  if command.outline.left > 0.0
421
- Raylib.DrawLineEx(vec2(ox, oy), vec2(ox, oy + oh), command.outline.left, outline_color)
430
+ Raylib.DrawLineEx(vec2(ox, oy, true), vec2(ox, oy + oh, true), command.outline.left, outline_color)
422
431
  end
423
432
 
424
433
  if command.outline.right > 0.0
425
- Raylib.DrawLineEx(vec2(ox + ow, oy), vec2(ox + ow, oy + oh), command.outline.right, outline_color)
434
+ Raylib.DrawLineEx(vec2(ox + ow, oy, true), vec2(ox + ow, oy + oh, true), command.outline.right, outline_color)
426
435
  end
427
436
 
428
437
  if command.outline.bottom > 0.0
429
- Raylib.DrawLineEx(vec2(ox, oy + oh), vec2(ox + ow, oy + oh), command.outline.bottom, outline_color)
438
+ Raylib.DrawLineEx(vec2(ox, oy + oh, true), vec2(ox + ow, oy + oh, true), command.outline.bottom, outline_color)
430
439
  end
431
440
  end
432
441
  else
@@ -80,7 +80,6 @@ module Hokusai::Backends
80
80
 
81
81
  def clamp_markdown(text, size, width, initial_offset = 0.0)
82
82
  self.size = size
83
-
84
83
  clamping_pointer = FFI::MemoryPointer.new :pointer
85
84
 
86
85
  ret = LibHokusai.hoku_text_md_clamp(clamping_pointer, text, width, initial_offset, raw, SDLBackend::OnWidthCb)
@@ -105,18 +104,23 @@ module Hokusai::Backends
105
104
  end
106
105
 
107
106
  def measure(text, size = 15)
108
- w = FFI::MemoryPointer.new :int
109
- h = FFI::MemoryPointer.new :int
107
+ begin
108
+ self.size = size
109
+ w = FFI::MemoryPointer.new :int
110
+ h = FFI::MemoryPointer.new :int
110
111
 
111
- SDL.TTF_SizeText(raw, text, w, h)
112
+ SDL.TTF_SizeText(raw, text, w, h)
112
113
 
113
- width = w.read_int
114
- height = h.read_int
114
+ width = w.read_int
115
+ height = h.read_int
115
116
 
116
- w.free
117
- h.free
117
+ w.free
118
+ h.free
118
119
 
119
- [width, height]
120
+ [width, height]
121
+ ensure
122
+ self.size = height
123
+ end
120
124
  end
121
125
 
122
126
  def size=(val)
@@ -57,7 +57,7 @@ module Hokusai::Backends
57
57
  end
58
58
 
59
59
  def run(block)
60
- resize = false
60
+ resize = true
61
61
  self.render_width = config.width
62
62
  self.render_height = config.height
63
63
 
@@ -89,7 +89,7 @@ module Hokusai::Backends
89
89
 
90
90
  Hokusai.fonts.register "default", SDLBackend::Font.from("#{__dir__}/sdl2/Monaco.ttf", 121)
91
91
  Hokusai.fonts.activate "default"
92
- config.after_load&.call
92
+ config.after_load_cb&.call
93
93
 
94
94
  register_command_handlers(renderer, window)
95
95
  # MemoryProfiler.start if ENV["PROFILE"]
@@ -107,7 +107,7 @@ module Hokusai::Backends
107
107
  if process_input(input, event)
108
108
  # since we are using wait event, we need to process the render twice
109
109
  # once to capture all events, and once after updating block state.
110
- SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_BLEND)
110
+ SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_NONE)
111
111
  SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
112
112
  SDL.RenderClear(renderer)
113
113
  canvas.reset(nil, nil, render_width.to_f, render_height.to_f)
@@ -116,7 +116,7 @@ module Hokusai::Backends
116
116
  block.update
117
117
  SDL.RenderPresent(renderer)
118
118
 
119
- SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_BLEND)
119
+ SDL.SetRenderDrawBlendMode(renderer, SDL::BLENDMODE_NONE)
120
120
  SDL.SetRenderDrawColor(renderer, config.background[:r], config.background[:g], config.background[:b], config.background[:a])
121
121
  SDL.RenderClear(renderer)
122
122
  canvas.reset(nil, nil, render_width.to_f, render_height.to_f)
@@ -404,7 +404,6 @@ module Hokusai::Backends
404
404
 
405
405
  Hokusai::Commands::Rect.on_draw do |command|
406
406
  next unless inside_scissor(command.x, command.y, command.height)
407
-
408
407
  # draw background first
409
408
  x, y, w, h = [command.x, command.y, command.width, command.height]
410
409
 
@@ -480,6 +479,7 @@ module Hokusai::Backends
480
479
  rounding = command.rounding
481
480
 
482
481
  if command.rounding > 0
482
+ pp command.color
483
483
  SDL.roundedBoxRGBA(renderer, x, y, x + w, y + h, (command.rounding).ceil.to_i, command.color.r, command.color.g, command.color.b, command.color.a)
484
484
  else
485
485
  rect = SDL::Rect.new
@@ -4,6 +4,11 @@ require "forwardable"
4
4
 
5
5
  module Hokusai
6
6
  module Blocks; end
7
+ # A UI Component
8
+ #
9
+ # Blocks are reusable and can be mounted in other blocks via templates
10
+ #
11
+ # Blocks have `props`` and emit `events`
7
12
  class Block
8
13
  attr_reader :node
9
14
  attr_reader :publisher
@@ -61,6 +66,8 @@ module Hokusai
61
66
  @styles || {}
62
67
  end
63
68
 
69
+ # Defines blocks that this block uses in it's template
70
+ # Keys map to template node names, values map to a `Hokusai::Block`
64
71
  def self.uses(**args)
65
72
  args.each do |key, value|
66
73
  raise Hokusai::Error.new("#{key} value must be a Block, got #{value}") unless value.is_a?(Block.class)
@@ -15,12 +15,12 @@ class Hokusai::Blocks::Hblock < Hokusai::Block
15
15
  canvas.vertical = false
16
16
  canvas.reverse = reverse
17
17
 
18
- if background.nil?
18
+ if background.nil? && outline.nil?
19
19
  yield canvas
20
20
  else
21
21
  draw do
22
22
  rect(canvas.x, canvas.y, canvas.width, canvas.height) do |command|
23
- command.color = background
23
+ command.color = background if background
24
24
  command.outline = outline if outline
25
25
  command.outline_color = outline_color if outline_color
26
26
  command.round = rounding.to_f if rounding
@@ -1,3 +1,5 @@
1
+ require "pathname"
2
+
1
3
  class Hokusai::Blocks::Image < Hokusai::Block
2
4
  template <<~EOF
3
5
  [template]
@@ -9,8 +11,10 @@ class Hokusai::Blocks::Image < Hokusai::Block
9
11
  computed :height, default: nil
10
12
 
11
13
  def render(canvas)
14
+ src = Pathname.new(source).absolute? ? source : "#{File.dirname(caller[-1].split(":")[0])}/#{source}"
15
+
12
16
  draw do
13
- image(source, canvas.x, canvas.y, width&.to_f || canvas.width, height&.to_f || canvas.height)
17
+ image(src, canvas.x, canvas.y, width&.to_f || canvas.width, height&.to_f || canvas.height)
14
18
  end
15
19
 
16
20
  yield canvas