libui 0.3.0.pre2-x86_64-linux → 0.3.0.pre3-x86_64-linux

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.
@@ -0,0 +1,175 @@
1
+ module LibUI
2
+ # A Ruby value. to_native allocates a fresh uiTableValue whose ownership is
3
+ # transferred to libui-ng when returned from CellValue.
4
+ class TableValue
5
+ attr_reader :type, :value
6
+
7
+ def initialize(type, value)
8
+ @type = Integer(type)
9
+ @value = value
10
+ end
11
+
12
+ def to_native
13
+ case type
14
+ when TableValueTypeString
15
+ raise TypeError, 'string table value must be a String' unless value.is_a?(String)
16
+ LibUI.new_table_value_string(value)
17
+ when TableValueTypeImage
18
+ raise TypeError, 'image table value must be a pointer or nil' unless value.nil? || value.is_a?(Fiddle::Pointer)
19
+ LibUI.new_table_value_image(value)
20
+ when TableValueTypeInt
21
+ LibUI.new_table_value_int(Integer(value))
22
+ when TableValueTypeColor
23
+ unless value.is_a?(Array) && value.length == 4 && value.all? { |part| part.is_a?(Numeric) }
24
+ raise TypeError, 'color table value must be an RGBA array'
25
+ end
26
+ LibUI.new_table_value_color(*value)
27
+ else
28
+ raise ArgumentError, "unknown table value type: #{type}"
29
+ end
30
+ end
31
+
32
+ def self.from_native(pointer)
33
+ return nil if pointer.nil? || pointer.to_i.zero?
34
+
35
+ type = LibUI.table_value_get_type(pointer)
36
+ value = case type
37
+ when TableValueTypeString then LibUI.table_value_string(pointer)
38
+ when TableValueTypeImage then LibUI.table_value_image(pointer)
39
+ when TableValueTypeInt then LibUI.table_value_int(pointer)
40
+ when TableValueTypeColor then LibUI.table_value_color(pointer)
41
+ else raise ArgumentError, "unknown table value type: #{type}"
42
+ end
43
+ new(type, value)
44
+ end
45
+ end
46
+
47
+ class TableModelHandler
48
+ attr_reader :column_types
49
+
50
+ def initialize(column_types:, rows:, cell_value: nil, set_cell_value: nil)
51
+ unless column_types.is_a?(Array) && column_types.all? { |type| type.is_a?(Integer) && (0..3).cover?(type) }
52
+ raise ArgumentError, 'column_types must be an array of table value types'
53
+ end
54
+ unless rows.is_a?(Array) || rows.respond_to?(:call)
55
+ raise TypeError, 'rows must be an Array or a row-count callback'
56
+ end
57
+ if rows.respond_to?(:call) && !cell_value
58
+ raise ArgumentError, 'cell_value is required when rows is a callback'
59
+ end
60
+
61
+ @column_types = column_types.dup.freeze
62
+ @rows = rows
63
+ @cell_value = cell_value || ->(row, column) { @rows.fetch(row).fetch(column) }
64
+ @set_cell_value = set_cell_value || (rows.is_a?(Array) ? ->(row, column, value) { @rows.fetch(row)[column] = value } : nil)
65
+ @native = FFI::TableModelHandler.malloc
66
+ @native.to_ptr.free = Fiddle::RUBY_FREE
67
+ @closures = {}
68
+ install_callbacks
69
+ end
70
+
71
+ def to_ptr
72
+ @native.to_ptr
73
+ end
74
+
75
+ private
76
+
77
+ def install_callbacks
78
+ pointer = Fiddle::TYPE_VOIDP
79
+ integer = Fiddle::TYPE_INT
80
+ @closures[:num_columns] = callback(integer, [pointer, pointer]) { @column_types.length }
81
+ @closures[:column_type] = callback(integer, [pointer, pointer, integer]) do |_handler, _model, column|
82
+ @column_types.fetch(column)
83
+ end
84
+ @closures[:num_rows] = callback(integer, [pointer, pointer]) do
85
+ @rows.respond_to?(:call) ? Integer(@rows.call) : @rows.length
86
+ end
87
+ @closures[:cell_value] = callback(pointer, [pointer, pointer, integer, integer]) do |_handler, _model, row, column|
88
+ type = @column_types.fetch(column)
89
+ begin
90
+ value = @cell_value.call(row, column)
91
+ table_value = value.is_a?(TableValue) ? value : TableValue.new(type, value)
92
+ raise TypeError, 'table value type does not match model column' unless table_value.type == type
93
+ table_value.to_native.to_i
94
+ rescue StandardError => e
95
+ CallbackRegistry.report(e)
96
+ fallback = case type
97
+ when TableValueTypeString then ''
98
+ when TableValueTypeImage then nil
99
+ when TableValueTypeInt then 0
100
+ when TableValueTypeColor then [0.0, 0.0, 0.0, 0.0]
101
+ end
102
+ TableValue.new(type, fallback).to_native.to_i
103
+ end
104
+ end
105
+ @closures[:set_cell_value] = callback(Fiddle::TYPE_VOID,
106
+ [pointer, pointer, integer, integer, pointer]) do |_handler, _model, row, column, native_value|
107
+ @set_cell_value&.call(row, column, TableValue.from_native(native_value)&.value)
108
+ end
109
+ @native.NumColumns = @closures[:num_columns]
110
+ @native.ColumnType = @closures[:column_type]
111
+ @native.NumRows = @closures[:num_rows]
112
+ @native.CellValue = @closures[:cell_value]
113
+ @native.SetCellValue = @closures[:set_cell_value]
114
+ end
115
+
116
+ def callback(return_type, argument_types, &block)
117
+ Fiddle::Closure::BlockCaller.new(return_type, argument_types) do |*args|
118
+ begin
119
+ block.call(*args)
120
+ rescue StandardError => e
121
+ CallbackRegistry.report(e)
122
+ 0
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ class TableModel
129
+ attr_reader :handler
130
+
131
+ def initialize(handler = nil, **options)
132
+ @handler = handler || TableModelHandler.new(**options)
133
+ raise TypeError, 'expected LibUI::TableModelHandler' unless @handler.is_a?(TableModelHandler)
134
+
135
+ @pointer = LibUI.new_table_model(@handler)
136
+ @attached_tables = 0
137
+ @freed = false
138
+ end
139
+
140
+ def to_ptr
141
+ raise RuntimeError, 'table model has been freed' if @freed
142
+
143
+ @pointer
144
+ end
145
+
146
+ def row_inserted(index)
147
+ LibUI.table_model_row_inserted(to_ptr, index)
148
+ end
149
+
150
+ def row_changed(index)
151
+ LibUI.table_model_row_changed(to_ptr, index)
152
+ end
153
+
154
+ def row_deleted(index)
155
+ LibUI.table_model_row_deleted(to_ptr, index)
156
+ end
157
+
158
+ def free
159
+ raise RuntimeError, 'table model is still attached to a table' if @attached_tables.positive?
160
+ return if @freed
161
+
162
+ LibUI.free_table_model(@pointer)
163
+ @freed = true
164
+ nil
165
+ end
166
+
167
+ def attach_table
168
+ @attached_tables += 1
169
+ end
170
+
171
+ def detach_table
172
+ @attached_tables -= 1
173
+ end
174
+ end
175
+ end
data/lib/libui/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LibUI
2
- VERSION = '0.3.0.pre2'
2
+ VERSION = '0.3.0.pre3'
3
3
  end