hokusai-zero 0.2.6.pre.pinephone2 → 0.2.6.pre.pinephone4

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/ast/src/core/input.c +0 -135
  3. data/ast/src/core/input.h +0 -33
  4. data/ast/test/hokusai.c +0 -2
  5. data/hokusai.gemspec +1 -1
  6. data/ui/examples/forum/file.rb +1 -1
  7. data/ui/examples/forum/post.rb +0 -1
  8. data/ui/examples/forum.rb +7 -7
  9. data/ui/examples/keyboard.rb +47 -0
  10. data/ui/examples/shader/test.rb +28 -18
  11. data/ui/examples/spreadsheet.rb +12 -11
  12. data/ui/lib/lib_hokusai.rb +19 -37
  13. data/ui/spec/hokusai/e2e/keyboard_spec.rb +52 -0
  14. data/ui/src/hokusai/assets/icons/outline/arrow-big-up.svg +19 -0
  15. data/ui/src/hokusai/assets/icons/outline/backspace.svg +20 -0
  16. data/ui/src/hokusai/backends/raylib/config.rb +2 -1
  17. data/ui/src/hokusai/backends/raylib.rb +54 -20
  18. data/ui/src/hokusai/backends/sdl2/config.rb +9 -6
  19. data/ui/src/hokusai/backends/sdl2/font.rb +3 -1
  20. data/ui/src/hokusai/backends/sdl2.rb +164 -65
  21. data/ui/src/hokusai/blocks/input.rb +1 -1
  22. data/ui/src/hokusai/blocks/keyboard.rb +249 -0
  23. data/ui/src/hokusai/blocks/slider.rb +139 -0
  24. data/ui/src/hokusai/commands/rect.rb +2 -2
  25. data/ui/src/hokusai/events/touch.rb +5 -11
  26. data/ui/src/hokusai/mounting/loop_entry.rb +1 -1
  27. data/ui/src/hokusai/painter.rb +6 -2
  28. data/ui/src/hokusai/types.rb +160 -50
  29. data/ui/src/hokusai/util/wrap_stream.rb +197 -0
  30. data/ui/src/hokusai.rb +61 -30
  31. metadata +8 -6
  32. data/ast/test/input.c +0 -44
  33. data/ui/src/hokusai/backends/embedded/config.rb +0 -48
  34. data/ui/src/hokusai/backends/embedded/font.rb +0 -112
  35. data/ui/src/hokusai/backends/embedded/keys.rb +0 -124
  36. data/ui/src/hokusai/backends/embedded.rb +0 -540
@@ -0,0 +1,249 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hokusai::Blocks
4
+ class Key < Hokusai::Block
5
+ template <<~EOF
6
+ [template]
7
+ empty {
8
+ @mousedown="set_down"
9
+ @mouseup="set_up"
10
+ cursor="pointer"
11
+ }
12
+ EOF
13
+
14
+ uses(empty: Hokusai::Blocks::Empty)
15
+
16
+ computed! :value
17
+ computed :size, default: 24, convert: proc(&:to_i)
18
+ computed :background, default: Hokusai::Color.new(70, 70, 70), convert: Hokusai::Color
19
+ computed :color, default: Hokusai::Color.new(244, 244, 244), convert: Hokusai::Color
20
+ computed :background_down, default: Hokusai::Color.new(33,33,33), convert: Hokusai::Color
21
+ computed :margin, default: Hokusai::Padding.new(3.0, 2.5, 3.0, 2.5), convert: Hokusai::Padding
22
+
23
+ inject :keyboard_icons
24
+
25
+ attr_accessor :down, :last_commands, :last_canvas, :last_value
26
+
27
+ def initialize(**args)
28
+ @down = false
29
+ @last_commands = []
30
+ @last_canvas = nil
31
+ @last_value = nil
32
+
33
+ super
34
+ end
35
+
36
+ def set_down(event)
37
+ if !down
38
+ emit("clicked", value[0], event)
39
+
40
+ self.down = true
41
+ else
42
+ emit("released", value[0], event)
43
+ end
44
+ end
45
+
46
+ def set_up(event)
47
+ self.down = false
48
+ emit("released", value[0], event)
49
+ end
50
+
51
+ def render(canvas)
52
+ hpad = (canvas.width - size) / 2
53
+ vpad = (canvas.height - margin.height - size) / 2
54
+
55
+ draw do
56
+ if last_canvas != canvas && last_value != value
57
+ self.last_value = value
58
+ self.last_canvas = canvas
59
+
60
+ if icon = keyboard_icons[value[0]]
61
+ if icon[:width]
62
+ node.meta.set_prop(:width, icon[:width])
63
+ end
64
+
65
+ rect(canvas.x + margin.left, canvas.y + margin.top, canvas.width - margin.width, canvas.height - margin.height) do |command|
66
+ command.color = icon[:background]# down ? background_down : background
67
+ command.round = 0.2
68
+
69
+ last_commands << command
70
+ end
71
+
72
+ svg(icon[:file], canvas.x + icon[:size] / 3, canvas.y + icon[:size] / 3, icon[:size], icon[:size]) do |command|
73
+ command.color = icon[:color]
74
+
75
+ last_commands << command
76
+ end
77
+ else
78
+ rect(canvas.x + margin.left, canvas.y + margin.top, canvas.width - margin.width, canvas.height - margin.height) do |command|
79
+ command.color = down ? background_down : background
80
+ command.round = 0.2
81
+
82
+ last_commands << command
83
+ end
84
+
85
+ text(value[1].to_s, canvas.x + hpad + margin.width, canvas.y + margin.height) do |command|
86
+ command.color = color
87
+ command.size = size
88
+
89
+ last_commands << command
90
+ end
91
+ end
92
+ else
93
+ queue.concat(last_commands)
94
+ end
95
+ end
96
+
97
+ yield canvas
98
+ end
99
+ end
100
+
101
+ class KeyboardRow < Hokusai::Block
102
+ style <<~EOF
103
+ [style]
104
+ keyboardStyle {
105
+ background: rgb(28, 28, 28);
106
+ }
107
+ keyStyle {
108
+ background: rgb(46, 46, 46);
109
+ color: rgb(208, 205, 218);
110
+ background_down: rgb(37, 37, 37);
111
+ }
112
+ EOF
113
+
114
+ template <<~EOF
115
+ [template]
116
+ hblock { ...keyboardStyle }
117
+ [for="number in keys"]
118
+ key {
119
+ ...keyStyle
120
+ :key="index"
121
+ :value="number"
122
+ @clicked="emit_key"
123
+ @released="emit_released"
124
+ }
125
+ EOF
126
+
127
+ uses(
128
+ hblock: Hblock,
129
+ vblock: Vblock,
130
+ key: Key
131
+ )
132
+
133
+ computed! :keys
134
+
135
+ inject :keyboard_icons
136
+
137
+ def loop_key(value)
138
+ @keys ||= {}
139
+ @keys[value] ||= "key-#{value}".freeze
140
+ end
141
+
142
+ def emit_key(key, event)
143
+ emit("key", key, event)
144
+ end
145
+
146
+ def emit_released(key, event)
147
+ emit("released", key, event)
148
+ end
149
+ end
150
+
151
+ class Keyboard < Hokusai::Block
152
+ style <<~EOF
153
+ [style]
154
+ kstyle {
155
+ padding: padding(10.0, 5.0, 10.0, 5.0);
156
+ background: rgb(28, 28, 28);
157
+ }
158
+ EOF
159
+
160
+ template <<~EOF
161
+ [template]
162
+ vblock { ...kstyle }
163
+ [for="row in key_rows"]
164
+ row {
165
+ :icons="icons"
166
+ @released="handle_released"
167
+ @key="handle_keypress"
168
+ :key="index"
169
+ :keys="row"
170
+ }
171
+ EOF
172
+
173
+ uses(
174
+ vblock: Hokusai::Blocks::Vblock,
175
+ row: KeyboardRow
176
+ )
177
+
178
+ def icons
179
+ {
180
+ :shift => {
181
+ file: Hokusai.asset("icons/outline/arrow-big-up.svg"),
182
+ width: 54.0,
183
+ size: 30,
184
+ background: Hokusai::Color.new(50, 109, 70),
185
+ color: Hokusai::Color.new(172, 224, 189)
186
+ },
187
+ :backspace => {
188
+ file: Hokusai.asset("icons/outline/backspace.svg"),
189
+ width: 54.0,
190
+ size: 30,
191
+ background: Hokusai::Color.new(50, 109, 70),
192
+ color: Hokusai::Color.new(172, 224, 189)
193
+ }
194
+ }
195
+ end
196
+
197
+ computed :row_height, default: 48.0, convert: proc(&:to_f)
198
+
199
+ provide :keyboard_icons, :icons
200
+
201
+ def on_mounted
202
+ node.meta.set_prop(:height, row_height * 5.0 + 20)
203
+ end
204
+
205
+ def space_row
206
+ [[:comma, ","], [:space, ''], [:period, "."]]
207
+ end
208
+
209
+ def key_rows
210
+ [number_keys, querty_keys, asdf_keys, zxcv_keys, space_row]
211
+ end
212
+
213
+ def handle_released(key, event)
214
+ event.input.keyboard_override = false
215
+ end
216
+
217
+ def handle_keypress(key, event)
218
+ event.input.keyboard_override = true
219
+ LibHokusai.hoku_input_keyboard_start(event.input.raw)
220
+ LibHokusai.hoku_input_keyboard_set_key(event.input.raw, key.to_sym, true)
221
+ LibHokusai.hoku_input_keyboard_stop(event.input.raw)
222
+ end
223
+
224
+ def zxcv_keys
225
+ @zxcv_keys ||= begin
226
+ keys = %w[z x c v b n m]
227
+ middle = keys.zip(keys)
228
+ # middle << [:backspace, :backspace]
229
+ # middle.unshift([:shift, :shift])
230
+ middle
231
+ end
232
+ end
233
+
234
+ def asdf_keys
235
+ keys = %w[a s d f g h j k l]
236
+ @asdf_keys ||= keys.zip(keys)
237
+ end
238
+
239
+ def querty_keys
240
+ keys = %w[q w e r t y u i o p]
241
+ @querty_keys ||= keys.zip(keys)
242
+ end
243
+
244
+ def number_keys
245
+ keys = [[:one,1],[:two, 2], [:three,3], [:four,4],[:five, 5], [:six,6], [:seven,7], [:eight,8],[:nine,9], [:zero, 0]]
246
+ @number_keys ||= keys
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,139 @@
1
+
2
+ module Hokusai::Blocks
3
+ class Slider < Hokusai::Block
4
+ template <<~EOF
5
+ [template]
6
+ empty {
7
+ @click="start_slider"
8
+ @mousemove="move_slider"
9
+ @mouseup="stop_slider"
10
+ }
11
+ EOF
12
+
13
+ uses(empty: Hokusai::Blocks::Empty)
14
+
15
+ computed :fill, default: [61,171,211], convert: Hokusai::Color
16
+ computed :initial, default: 0.0, convert: proc(&:to_f)
17
+ computed :size, default: 50.0, convert: proc(&:to_f)
18
+ computed :step, default: 20.0, convert: proc(&:to_f)
19
+ computed :min, default: 0.0, convert: proc(&:to_f)
20
+ computed :max, default: 100.0, convert: proc(&:to_f)
21
+
22
+ attr_reader :slider_width, :slider_start, :steps_x, :steps_val
23
+ attr_accessor :sliding, :slider_x, :last_index
24
+
25
+ def initialize(**args)
26
+ @sliding = false
27
+ @slider_width = 0.0
28
+ @slider_start = 0.0
29
+ @slider_x = 0.0
30
+ @last_index = 0
31
+ @configured = false
32
+
33
+ super
34
+
35
+ @last_max = nil
36
+ end
37
+
38
+ def start_slider(event)
39
+ self.sliding = true
40
+ end
41
+
42
+ def on_resize(canvas)
43
+ # create our buckets for steps
44
+ @slider_start = canvas.x
45
+ @slider_width = canvas.width
46
+
47
+ @steps_val = [*(min..max).step(step).to_a, max]
48
+ steps_val.pop if steps_val[-1] == steps_val[-2]
49
+
50
+ step_x = (slider_width) / (steps_val.size - 1)
51
+ @steps_x = (slider_start..(slider_start + slider_width)).step(step_x).to_a
52
+
53
+ (steps_val.size - steps_x.size).times do |i|
54
+ steps_x << steps_x.last + step_x * i
55
+ end
56
+
57
+ steps_x[-1] = slider_start + slider_width if slider_start + slider_width != steps_x.last
58
+ end
59
+
60
+ def move_slider(event)
61
+ if sliding && event.left.down
62
+ pos = event.pos.x
63
+ index = steps_x.size - 1
64
+
65
+ (0...steps_x.size - 1).each do |i|
66
+ next if steps_x[i + 1] && pos - steps_x[i + 1] > step
67
+
68
+ if pos - steps_x[i] > pos - steps_x[i + 1]
69
+ index = i
70
+ break
71
+ else
72
+ index = i + 1
73
+ break
74
+ end
75
+ end
76
+
77
+ self.last_index = index
78
+
79
+ emit("updated", steps_val[index])
80
+ else
81
+ self.sliding = false
82
+ end
83
+ end
84
+
85
+ def stop_slider(event)
86
+ if event.left.up
87
+ self.sliding = false
88
+ end
89
+ end
90
+
91
+ def render(canvas)
92
+ if max != @last_max
93
+ on_resize(canvas)
94
+
95
+ @last_max = max
96
+ end
97
+
98
+ unless @setup || steps_val.nil? || initial.nil?
99
+ steps_val.each_with_index do |val, index|
100
+ if val == initial
101
+ self.last_index = index
102
+
103
+ break
104
+ end
105
+ end
106
+
107
+ @setup = true
108
+ end
109
+
110
+ slider_x = steps_x[last_index]
111
+ padding = Hokusai::Padding.new(0.0, 0.0, 0.0, 0.0)
112
+ percent = slider_x * 100.00
113
+ x = slider_x + padding.left
114
+ x = (canvas.x + canvas.width) - (size / 2) - 2 if x > (canvas.x + canvas.width) - (size / 2)
115
+ x = canvas.x if x < canvas.x
116
+ cursor = (x + size / 2)
117
+
118
+ draw do
119
+ # draw background
120
+ rect(canvas.x + padding.left, canvas.y + padding.top, canvas.width - padding.right - padding.left, size) do |command|
121
+ command.round = size / 2
122
+ command.color = Hokusai::Color.new(33, 33, 33)
123
+ command.padding = Hokusai::Padding.new(5.0, 20.0, 5.0, 20.0)
124
+ end
125
+
126
+ rect(canvas.x + padding.left + 1, canvas.y + padding.top + 1, x + (size / 2) - canvas.x - 2, size - 2) do |command|
127
+ command.round = size / 2
128
+ command.color = fill
129
+ end
130
+
131
+ circle(cursor + padding.left, canvas.y + (size / 2) + padding.top, size / 2) do |command|
132
+ command.color = Hokusai::Color.new(233, 233, 233)
133
+ end
134
+ end
135
+
136
+ yield canvas
137
+ end
138
+ end
139
+ end
@@ -11,8 +11,8 @@ module Hokusai
11
11
  @height = height.to_f
12
12
  @outline = Outline.default
13
13
  @rounding = 0.0
14
- @color = Color.new(0, 0, 0, 0)
15
- @outline_color = Color.new(0, 0, 0, 255)
14
+ @color = Color.new(255, 255, 255, 0)
15
+ @outline_color = Color.new(0, 0, 0, 0)
16
16
  @padding = Padding.new(0.0, 0.0, 0.0, 0.0)
17
17
  @gradient = nil
18
18
  end
@@ -2,9 +2,9 @@ module Hokusai
2
2
  class TouchEvent < Event
3
3
  extend Forwardable
4
4
 
5
- def_delegators :@touch, :tapped?, :swiped?, :longtapped?, :touching?,
6
- :duration, :direction, :angle, :position, :last_position,
7
- :touch_len, :touch_count, :timer
5
+ def_delegators :@touch, :tapped?, :swiped?, :longtapped?, :longtapping?, :touching?,
6
+ :duration, :direction, :distance, :angle, :position, :last_position,
7
+ :touch_len, :touch_count, :timer
8
8
 
9
9
  attr_reader :input
10
10
 
@@ -32,14 +32,8 @@ module Hokusai
32
32
  name "taphold"
33
33
 
34
34
  def capture(block, canvas)
35
- if longtapped? && hovered(canvas)
36
- block.node.meta.focus
37
-
38
- if matches(block)
39
- captures << block
40
- end
41
- elsif touching?
42
- block.node.meta.blur
35
+ if matches(block) && longtapped? && hovered(canvas)
36
+ captures << block
43
37
  end
44
38
  end
45
39
  end
@@ -65,7 +65,7 @@ module Hokusai
65
65
 
66
66
  portal = Node.new(ast)
67
67
  node = child_block_class.compile(ast.type, portal)
68
- child_block = child_block_class.new(node: node)
68
+ child_block = child_block_class.new(node: node, providers: mount_providers)
69
69
  child_block.node.add_styles(target.class)
70
70
  child_block.node.add_props_from_block(target, context: ctx)
71
71
  child_block.node.meta.set_prop(ast.loop.var.to_sym, value)
@@ -110,7 +110,6 @@ module Hokusai
110
110
  while group = group_children.shift
111
111
  z = group.block.node.meta.get_prop(:z)&.to_i || 0
112
112
  ztarget = group.block.node.meta.get_prop(:ztarget)
113
- entry = PainterEntry.new(group.block, group.x, group.y, group.w, group.h)
114
113
 
115
114
  if (zindex_counter > 0 || z > 0)
116
115
  case ztarget
@@ -118,9 +117,14 @@ module Hokusai
118
117
  entry = PainterEntry.new(group.block, zroot_x || 0.0, zroot_y || 0.0, zroot_w, zroot_h).freeze
119
118
  when ZTARGET_PARENT
120
119
  entry = PainterEntry.new(group.block, group_parent.x || 0.0, group_parent.y || 0.0, group_parent.w, group_parent.h).freeze
120
+ else
121
+ entry = PainterEntry.new(group.block, group.x, group.y, group.w, group.h).freeze
121
122
  end
123
+ else
124
+ entry = PainterEntry.new(group.block, group.x, group.y, group.w, group.h).freeze
122
125
  end
123
126
 
127
+
124
128
  canvas.reset(entry.x, entry.y, entry.w, entry.h)
125
129
 
126
130
  before_render&.call([group.block, group.parent], canvas, input.raw)
@@ -277,7 +281,7 @@ module Hokusai
277
281
  end
278
282
  events[:mousemove].capture(block, canvas)
279
283
 
280
- if block_is_hovered || block.node.meta.focused
284
+ if block_is_hovered || block.node.meta.focused || input.keyboard_override
281
285
  events[:keyup].capture(block, canvas)
282
286
  events[:keypress].capture(block, canvas)
283
287
  end