nuklear 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 (102) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +29 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +196 -0
  8. data/Rakefile +26 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/examples/arial.ttf +0 -0
  12. data/examples/calculator.rb +102 -0
  13. data/examples/hello_nuklear.rb +182 -0
  14. data/examples/lib/opengl_font.rb +32 -0
  15. data/examples/lib/opengl_init.rb +4 -0
  16. data/examples/lib/sdl2_init.rb +6 -0
  17. data/examples/lib/sdl2_input.rb +81 -0
  18. data/examples/lib/window.rb +47 -0
  19. data/ext/freetype/extconf.rb +26 -0
  20. data/ext/nuklear/extconf.rb +14 -0
  21. data/ext/nuklear/nkrb.c +79 -0
  22. data/ext/nuklear/nkrb.h +89 -0
  23. data/ext/nuklear/nkrb_buffer.c +80 -0
  24. data/ext/nuklear/nkrb_context.c +241 -0
  25. data/ext/nuklear/nkrb_font.c +80 -0
  26. data/ext/nuklear/nkrb_renderer.c +114 -0
  27. data/ext/nuklear/nkrb_style.c +61 -0
  28. data/ext/nuklear/nkrb_style_color.c +126 -0
  29. data/ext/nuklear/nkrb_style_image.c +32 -0
  30. data/ext/nuklear/nkrb_ui.c +32 -0
  31. data/ext/nuklear/nkrb_ui_builder.c +29 -0
  32. data/ext/nuklear/nkrb_ui_button.c +55 -0
  33. data/ext/nuklear/nkrb_ui_color_picker.c +20 -0
  34. data/ext/nuklear/nkrb_ui_combo.c +73 -0
  35. data/ext/nuklear/nkrb_ui_container.c +7 -0
  36. data/ext/nuklear/nkrb_ui_edit_string.c +38 -0
  37. data/ext/nuklear/nkrb_ui_group.c +27 -0
  38. data/ext/nuklear/nkrb_ui_label.c +30 -0
  39. data/ext/nuklear/nkrb_ui_layout.c +125 -0
  40. data/ext/nuklear/nkrb_ui_menu.c +49 -0
  41. data/ext/nuklear/nkrb_ui_menu_item.c +30 -0
  42. data/ext/nuklear/nkrb_ui_menubar.c +18 -0
  43. data/ext/nuklear/nkrb_ui_popup.c +24 -0
  44. data/ext/nuklear/nkrb_ui_progress.c +19 -0
  45. data/ext/nuklear/nkrb_ui_property.c +20 -0
  46. data/ext/nuklear/nkrb_ui_selectables.c +53 -0
  47. data/ext/nuklear/nkrb_ui_slider.c +19 -0
  48. data/ext/nuklear/nkrb_ui_tree.c +29 -0
  49. data/ext/nuklear/nkrb_ui_widget.c +7 -0
  50. data/ext/nuklear/nkrb_ui_window.c +43 -0
  51. data/ext/nuklear/nuklear.h +23378 -0
  52. data/ext/nuklear_renderer_opengl2/KHR/khrplatform.h +285 -0
  53. data/ext/nuklear_renderer_opengl2/extconf.rb +13 -0
  54. data/ext/nuklear_renderer_opengl2/glad.c +1432 -0
  55. data/ext/nuklear_renderer_opengl2/glad.h +2747 -0
  56. data/ext/nuklear_renderer_opengl2/nuklear_renderer_opengl2.c +197 -0
  57. data/ext/nuklear_renderer_opengl4/KHR/khrplatform.h +285 -0
  58. data/ext/nuklear_renderer_opengl4/extconf.rb +13 -0
  59. data/ext/nuklear_renderer_opengl4/glad.c +1782 -0
  60. data/ext/nuklear_renderer_opengl4/glad.h +3687 -0
  61. data/ext/nuklear_renderer_opengl4/nuklear_renderer_opengl4.c +255 -0
  62. data/lib/nuklear/context.rb +49 -0
  63. data/lib/nuklear/dsl.rb +46 -0
  64. data/lib/nuklear/event_buffer.rb +23 -0
  65. data/lib/nuklear/renderer/opengl24.rb +13 -0
  66. data/lib/nuklear/renderer.rb +108 -0
  67. data/lib/nuklear/style/color.rb +24 -0
  68. data/lib/nuklear/style/image.rb +9 -0
  69. data/lib/nuklear/style.rb +8 -0
  70. data/lib/nuklear/test_case.rb +30 -0
  71. data/lib/nuklear/ui/base.rb +34 -0
  72. data/lib/nuklear/ui/button.rb +77 -0
  73. data/lib/nuklear/ui/checkbox.rb +39 -0
  74. data/lib/nuklear/ui/col.rb +21 -0
  75. data/lib/nuklear/ui/color_picker.rb +31 -0
  76. data/lib/nuklear/ui/combo_box.rb +42 -0
  77. data/lib/nuklear/ui/container.rb +80 -0
  78. data/lib/nuklear/ui/edit_string.rb +48 -0
  79. data/lib/nuklear/ui/enableable.rb +29 -0
  80. data/lib/nuklear/ui/events.rb +23 -0
  81. data/lib/nuklear/ui/group.rb +31 -0
  82. data/lib/nuklear/ui/label.rb +21 -0
  83. data/lib/nuklear/ui/menu.rb +43 -0
  84. data/lib/nuklear/ui/menu_bar.rb +19 -0
  85. data/lib/nuklear/ui/menu_item.rb +34 -0
  86. data/lib/nuklear/ui/option.rb +17 -0
  87. data/lib/nuklear/ui/option_group.rb +22 -0
  88. data/lib/nuklear/ui/popup.rb +37 -0
  89. data/lib/nuklear/ui/progress.rb +33 -0
  90. data/lib/nuklear/ui/property.rb +28 -0
  91. data/lib/nuklear/ui/row.rb +28 -0
  92. data/lib/nuklear/ui/select_list.rb +31 -0
  93. data/lib/nuklear/ui/selectable.rb +21 -0
  94. data/lib/nuklear/ui/slider.rb +26 -0
  95. data/lib/nuklear/ui/text_align.rb +14 -0
  96. data/lib/nuklear/ui/tree.rb +62 -0
  97. data/lib/nuklear/ui/window.rb +175 -0
  98. data/lib/nuklear/ui.rb +33 -0
  99. data/lib/nuklear/version.rb +3 -0
  100. data/lib/nuklear.rb +26 -0
  101. data/nuklear.gemspec +41 -0
  102. metadata +233 -0
@@ -0,0 +1,39 @@
1
+ module Nuklear
2
+ module UI
3
+ class Checkbox < Nuklear::UI::Base
4
+ attr_accessor :text
5
+
6
+ def initialize(text, checked: false, enabled: true, &block)
7
+ super enabled: enabled
8
+ @text = text
9
+ @checked = checked
10
+ on(true) { @checked = true }
11
+ on(false) { @checked = false }
12
+ if block_given?
13
+ on true, &block
14
+ on false, &block
15
+ end
16
+ end
17
+
18
+ def checked?
19
+ @checked
20
+ end
21
+
22
+ def checked=(checked)
23
+ @checked = checked
24
+ @last_event = checked
25
+ end
26
+
27
+ alias selected? checked?
28
+ alias selected= checked=
29
+
30
+ def to_command
31
+ [ :ui_checkbox, text, checked? ]
32
+ end
33
+
34
+ def result(event, context)
35
+ trigger event
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ module Nuklear
2
+ module UI
3
+ class Col < Base
4
+ include Nuklear::UI::Container
5
+ attr_accessor :width
6
+
7
+ def initialize(width:, **options)
8
+ super(**options)
9
+ self.width = width
10
+ end
11
+
12
+ def to_command
13
+ [:ui_layout_row_push, width]
14
+ end
15
+
16
+ def result(_, context)
17
+ run_commands(context)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ module Nuklear
2
+ module UI
3
+ class ColorPicker < Base
4
+ attr_accessor :color
5
+ attr_reader :type
6
+
7
+ def initialize(color, type: :rgba, **options)
8
+ super(**options)
9
+ self.color = color
10
+ self.type = type
11
+ end
12
+
13
+ def type=(t)
14
+ case t
15
+ when :rgb, :rgba then @type = t
16
+ else raise ArgumentError, "invalid color picker type, must be :rgb or :rgba"
17
+ end
18
+ end
19
+
20
+ def to_command
21
+ [:ui_color_picker, color, type]
22
+ end
23
+
24
+ def result(color, context)
25
+ @color = color
26
+ trigger :color_changed
27
+ @last_event = nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ module Nuklear
2
+ module UI
3
+ class ComboBox < Nuklear::UI::Base
4
+ include Nuklear::UI::Container
5
+
6
+ attr_accessor :text, :image, :color, :symbol, :width, :height
7
+
8
+ def initialize(text: nil, image: nil, color: nil, symbol: nil, width:, height:, **options)
9
+ super(**options)
10
+ self.text = text
11
+ self.image = image
12
+ self.color = color
13
+ self.symbol = symbol
14
+ self.width = width
15
+ self.height = height
16
+ end
17
+
18
+ def red; color.red; end
19
+ def red=(a); color.red = a; end
20
+ def green; color.green; end
21
+ def green=(a); color.green = a; end
22
+ def blue; color.blue; end
23
+ def blue=(a); color.blue = a; end
24
+ def alpha; color.alpha; end
25
+ def alpha=(a); color.alpha = a; end
26
+ def hue; color.hue; end
27
+ def hue=(a); color.hue = a; end
28
+ def saturation; color.saturation; end
29
+ def saturation=(a); color.saturation = a; end
30
+ def value; color.value; end
31
+ def value=(a); color.value = a; end
32
+
33
+ def to_command
34
+ [ :ui_combobox, text, color, symbol, image, width, height ]
35
+ end
36
+
37
+ def result(expanded, context)
38
+ run_commands(context) if expanded
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,80 @@
1
+ module Nuklear
2
+ module UI
3
+ module Container
4
+ def commands
5
+ @commands ||= []
6
+ end
7
+
8
+ def run_command(context, command)
9
+ if command.respond_to?(:to_command)
10
+ if !command.respond_to?(:enabled?) || command.enabled?
11
+ cmd = command.to_command
12
+ result = send(cmd[0], context, *cmd[1..-1]) do |ret|
13
+ command.result(ret, context) if command.respond_to?(:result)
14
+ end
15
+ command.result(result, context) if !result.nil? && command.respond_to?(:result)
16
+ end
17
+ elsif command.respond_to?(:[])
18
+ send(command[0], context, *command[1..-1])
19
+ else
20
+ raise "Unexpected command #{command.inspect}"
21
+ end
22
+ end
23
+
24
+ def run_commands(context)
25
+ commands.each do |command|
26
+ if command.respond_to?(:to_commands)
27
+ command.to_commands.each { |cmd| run_command(context, cmd) }
28
+ else
29
+ run_command(context, command)
30
+ end
31
+ end
32
+ end
33
+
34
+ def <<(other)
35
+ commands << other
36
+ end
37
+
38
+ # Iterates over every item in this container, and yields each item
39
+ # (starting with the container itself) to the block.
40
+ def traverse(&block)
41
+ yield self
42
+ commands.each do |item|
43
+ if item.respond_to?(:traverse)
44
+ item.traverse(&block)
45
+ else
46
+ yield item
47
+ end
48
+ end
49
+ end
50
+
51
+ # Traverses this container and any of its sub-containers, yielding each
52
+ # item to the block. Returns each item for which the block returned true.
53
+ def find(&block)
54
+ matches = []
55
+ traverse do |item|
56
+ matches << item if yield(item)
57
+ end
58
+ return matches
59
+ end
60
+
61
+ LayoutRowDynamic = Struct.new(:height, :ncols) do
62
+ def to_command
63
+ [ :ui_layout_row_dynamic, height, ncols ]
64
+ end
65
+ end
66
+
67
+ def layout_row_dynamic(height, ncols)
68
+ LayoutRowDynamic.new(height, ncols).tap { |row| commands << row }
69
+ end
70
+
71
+ def method_missing(name, *args)
72
+ if respond_to?(:"ui_#{name}")
73
+ commands << [:"ui_#{name}", *args]
74
+ else
75
+ super
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,48 @@
1
+ module Nuklear
2
+ module UI
3
+ class EditString < Nuklear::UI::Base
4
+ attr_accessor :flags, :max_length, :filter, :text
5
+
6
+ def initialize(text: "", flags: 0, max_length: 255, filter: nil, enabled: true)
7
+ super enabled: enabled
8
+ @text = text
9
+ @flags = Nuklear.parse_flags :edit, flags
10
+ @max_length = max_length
11
+ @filter = filter
12
+ @demand_focus = false
13
+ end
14
+
15
+ def demand_focus?
16
+ @demand_focus
17
+ end
18
+
19
+ def focus
20
+ @demand_focus = true
21
+ end
22
+
23
+ def to_commands
24
+ if demand_focus?
25
+ @demand_focus = false
26
+ [
27
+ [:ui_edit_focus, flags],
28
+ self,
29
+ ]
30
+ else
31
+ [self]
32
+ end
33
+ end
34
+
35
+ def to_command
36
+ [:ui_edit_string, flags, text, max_length, filter]
37
+ end
38
+
39
+ def result(result, context)
40
+ trigger(:activated) if (result & Nuklear::NK_EDIT_ACTIVATED) > 0
41
+ trigger(:deactivated) if (result & Nuklear::NK_EDIT_DEACTIVATED) > 0
42
+ trigger(:committed) if (result & Nuklear::NK_EDIT_COMMITED) > 0
43
+ trigger(:active) if (result & Nuklear::NK_EDIT_ACTIVE) > 0
44
+ trigger(:inactive) if (result & Nuklear::NK_EDIT_INACTIVE) > 0
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ module Nuklear
2
+ module UI
3
+ module Enableable
4
+ def enabled=(a)
5
+ @enabled = a
6
+ end
7
+
8
+ def disabled=(a)
9
+ self.enabled = !a
10
+ end
11
+
12
+ def enable
13
+ self.enabled = true
14
+ end
15
+
16
+ def disable
17
+ self.enabled = false
18
+ end
19
+
20
+ def enabled?
21
+ @enabled.nil? ? true : @enabled
22
+ end
23
+
24
+ def disabled?
25
+ !enabled?
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ module Nuklear
2
+ module UI
3
+ module Events
4
+ def on(*events, &block)
5
+ events.each do |event|
6
+ event_listeners_for(event) << block
7
+ end
8
+ end
9
+
10
+ def event_listeners_for(event)
11
+ @event_listeners ||= {}
12
+ @event_listeners[event] ||= []
13
+ end
14
+
15
+ def trigger(event)
16
+ if event != @last_event # prevent triggering every frame
17
+ event_listeners_for(event).each { |listener| listener.call event }
18
+ @last_event = event
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module Nuklear
2
+ module UI
3
+ class Group < Nuklear::UI::Base
4
+ include Nuklear::UI::Container
5
+
6
+ attr_accessor :title, :scroll_x, :scroll_y
7
+
8
+ def initialize(title = object_id.to_s, **options)
9
+ super(**options)
10
+ @scroll_x = @scroll_y = 0
11
+ self.title = title
12
+ end
13
+
14
+ def to_command
15
+ [ :ui_group, title, flags, scroll_x, scroll_y ]
16
+ end
17
+
18
+ def flags
19
+ 0
20
+ end
21
+
22
+ def result(new_state, context)
23
+ if new_state.kind_of?(Array)
24
+ @scroll_x, @scroll_y = new_state
25
+ else
26
+ run_commands(context)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ module Nuklear
2
+ module UI
3
+ class Label < Nuklear::UI::Base
4
+ include Nuklear::UI::TextAlign
5
+
6
+ attr_accessor :text, :color, :wrap, :align
7
+
8
+ def initialize(text, color: nil, wrap: false, align: :left, **options)
9
+ super(**options)
10
+ self.text = text
11
+ self.color = color
12
+ self.wrap = wrap
13
+ self.align = align
14
+ end
15
+
16
+ def to_command
17
+ [:ui_label, text, color, wrap, align_as_flags(align)]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,43 @@
1
+ module Nuklear
2
+ module UI
3
+ class Menu < Nuklear::UI::Base
4
+ include Nuklear::UI::Container
5
+ include Nuklear::UI::TextAlign
6
+
7
+ attr_accessor :title, :image, :symbol, :align, :width, :height
8
+
9
+ def initialize(enabled: true, title: nil, image: nil, symbol: nil,
10
+ align: :left, width:, height:)
11
+ super enabled: enabled
12
+ @title = title
13
+ @image = image
14
+ @symbol = symbol
15
+ @align = align
16
+ @width = width
17
+ @height = height
18
+ end
19
+
20
+ def to_command
21
+ [:ui_menu, {
22
+ id: object_id,
23
+ title: title,
24
+ image: image,
25
+ symbol: symbol,
26
+ align: align_as_flags(align),
27
+ width: width,
28
+ height: height
29
+ }
30
+ ]
31
+ end
32
+
33
+ def visible?
34
+ @visible
35
+ end
36
+
37
+ def result(visible, context)
38
+ @visible = visible
39
+ run_commands(context) if visible
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ module Nuklear
2
+ module UI
3
+ class MenuBar < Nuklear::UI::Base
4
+ include Nuklear::UI::Container
5
+
6
+ def initialize(enabled: true)
7
+ super enabled: enabled
8
+ end
9
+
10
+ def to_command
11
+ [:ui_menubar]
12
+ end
13
+
14
+ def result(visible, context)
15
+ run_commands(context) if visible
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ module Nuklear
2
+ module UI
3
+ class MenuItem < Nuklear::UI::Base
4
+ include Nuklear::UI::Container
5
+ include Nuklear::UI::TextAlign
6
+
7
+ attr_accessor :title, :image, :symbol, :align
8
+
9
+ def initialize(enabled: true, title: nil, image: nil, symbol: nil, align: :left, &block)
10
+ super enabled: enabled
11
+ @title = title
12
+ @image = image
13
+ @symbol = symbol
14
+ @align = align
15
+ on(:clicked, &block) if block_given?
16
+ end
17
+
18
+ def to_command
19
+ [:ui_menu_item, {
20
+ title: title,
21
+ image: image,
22
+ symbol: symbol,
23
+ align: align_as_flags(align)
24
+ }
25
+ ]
26
+ end
27
+
28
+ def result(clicked, context)
29
+ trigger(:clicked)
30
+ @last_event = nil # trigger event each time
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ module Nuklear
2
+ module UI
3
+ class Option < Nuklear::UI::Checkbox
4
+ def to_command
5
+ [ :ui_option, text, checked? ]
6
+ end
7
+
8
+ # Override #result to prevent user deselecting this option by clicking
9
+ # on it. Checkbox can be deselected, option cannot. Only choosing a
10
+ # competing option can cause it to be deselected, and doing that does
11
+ # not call #result. See Nuklear::UI::OptionGroup.
12
+ def result(event, context)
13
+ trigger event if event
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module Nuklear
2
+ module UI
3
+ class OptionGroup < Base
4
+ include Nuklear::UI::Container
5
+
6
+ def initialize(**options)
7
+ super(**options)
8
+ @options = []
9
+ end
10
+
11
+ def selection=(selected)
12
+ @options.each { |option| option.selected = (option == selected) }
13
+ end
14
+
15
+ def <<(other)
16
+ super other
17
+ @options << other
18
+ other.on(true) { self.selection = other }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ require 'nuklear/ui/window'
2
+
3
+ module Nuklear
4
+ module UI
5
+ class Popup < Nuklear::UI::Window
6
+ attr_accessor :type
7
+
8
+ def initialize(title, type: :static, enabled: false, **options)
9
+ super title, enabled: enabled, **options
10
+ self.type = type
11
+ on(:visible) { self.enabled = true }
12
+ on(:hidden) { self.enabled = false }
13
+ end
14
+
15
+ def to_command
16
+ [:ui_popup,
17
+ type == :dynamic ? NK_POPUP_DYNAMIC : NK_POPUP_STATIC,
18
+ title,
19
+ flags,
20
+ left,
21
+ top,
22
+ width,
23
+ height
24
+ ]
25
+ end
26
+
27
+ def visible?
28
+ @enabled
29
+ end
30
+
31
+ def result(visibility, context)
32
+ trigger(visibility)
33
+ run_commands(context) if visible?
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,33 @@
1
+ module Nuklear
2
+ module UI
3
+ class Progress < Base
4
+ attr_accessor :current, :min, :max
5
+ attr_writer :modifiable
6
+
7
+ def initialize(enabled: true, min: 1, max: 100, current: 1, modifiable: true)
8
+ super enabled: enabled
9
+ @min = min
10
+ @max = max
11
+ @current = current
12
+ @modifiable = modifiable
13
+ on(:changed) { yield @current } if block_given?
14
+ end
15
+
16
+ def to_command
17
+ [:ui_progress, current, max, modifiable?]
18
+ end
19
+
20
+ def modifiable?
21
+ @modifiable
22
+ end
23
+
24
+ def result(x, context)
25
+ x = min if x < min
26
+ return unless x != @current
27
+ @current = x
28
+ trigger :changed
29
+ @last_event = nil
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ module Nuklear
2
+ module UI
3
+ class Property < Base
4
+ attr_accessor :current, :min, :max, :step, :inc_per_pixel, :text
5
+
6
+ def initialize(enabled: true, text: '', min: 1, max: 100, current: 1, step: 1, inc_per_pixel: 1)
7
+ super enabled: enabled
8
+ @text = text
9
+ @min = min
10
+ @max = max
11
+ @current = current
12
+ @step = step
13
+ @inc_per_pixel = inc_per_pixel
14
+ on(:changed) { yield @current } if block_given?
15
+ end
16
+
17
+ def to_command
18
+ [:ui_property, text, min, current, max, step, inc_per_pixel]
19
+ end
20
+
21
+ def result(x, context)
22
+ @current = x
23
+ trigger :changed
24
+ @last_event = nil
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ module Nuklear
2
+ module UI
3
+ class Row < Base
4
+ include Nuklear::UI::Container
5
+ attr_accessor :height, :type, :width
6
+
7
+ def initialize(height:, width: nil, type: nil, **options)
8
+ super(**options)
9
+ self.type = type
10
+ self.height = height
11
+ self.width = width
12
+ raise ArgumentError, ":width is required if type is :static" if type == :static && width.nil?
13
+ end
14
+
15
+ def to_command
16
+ case type
17
+ when :dynamic then [:ui_layout_row_dynamic, height, commands.size]
18
+ when :static then [:ui_layout_row_static, height, width, commands.size]
19
+ else [:ui_layout_row_begin, type || :static, height, commands.size]
20
+ end
21
+ end
22
+
23
+ def result(_, context)
24
+ run_commands(context)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ module Nuklear
2
+ module UI
3
+ class SelectList < Nuklear::UI::Base
4
+ include Nuklear::UI::Container
5
+
6
+ attr_accessor :choices, :selection, :item_height, :width, :height
7
+
8
+ def initialize(choices, selection: choices[0], item_height:, width:, height:, **options)
9
+ super(**options)
10
+ self.choices = choices
11
+ self.selection = selection
12
+ self.item_height = item_height
13
+ self.width = width
14
+ self.height = height
15
+ on(:selection_changed) { yield self.selection } if block_given?
16
+ end
17
+
18
+ def to_command
19
+ [ :ui_combo, choices.index(selection) || 0, choices, item_height, width, height ]
20
+ end
21
+
22
+ def result(choice_index, context)
23
+ if @selection != choices[choice_index]
24
+ @selection = choices[choice_index]
25
+ trigger(:selection_changed)
26
+ @last_event = nil
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ module Nuklear
2
+ module UI
3
+ class Selectable < Nuklear::UI::Checkbox
4
+ include Nuklear::UI::TextAlign
5
+
6
+ attr_accessor :image, :text, :align
7
+
8
+ def initialize(text: nil, align: :left, image: nil, selected: false, **options, &block)
9
+ super(**options, &block)
10
+ self.selected = selected
11
+ @text = text
12
+ @image = image
13
+ @align = align
14
+ end
15
+
16
+ def to_command
17
+ [ :ui_selectable, image, text, selected?, align_as_flags(align) ]
18
+ end
19
+ end
20
+ end
21
+ end