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.
- checksums.yaml +4 -4
- data/README.md +114 -218
- data/lib/libui/area_handler.rb +155 -0
- data/lib/libui/callback_registry.rb +123 -0
- data/lib/libui/draw_values.rb +143 -0
- data/lib/libui/ffi.rb +37 -2
- data/lib/libui/font.rb +13 -0
- data/lib/libui/libui_base.rb +23 -29
- data/lib/libui/path.rb +70 -0
- data/lib/libui/platform.rb +12 -12
- data/lib/libui/table_model.rb +175 -0
- data/lib/libui/version.rb +1 -1
- data/lib/libui.rb +601 -2
- data/vendor/libui.x86_64.so +0 -0
- metadata +8 -2
data/lib/libui.rb
CHANGED
|
@@ -2,6 +2,7 @@ require_relative 'libui/version'
|
|
|
2
2
|
require_relative 'libui/utils'
|
|
3
3
|
require_relative 'libui/error'
|
|
4
4
|
require_relative 'libui/platform'
|
|
5
|
+
require 'date'
|
|
5
6
|
|
|
6
7
|
module LibUI
|
|
7
8
|
class << self
|
|
@@ -20,11 +21,200 @@ module LibUI
|
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
require_relative 'libui/ffi'
|
|
24
|
+
require_relative 'libui/callback_registry'
|
|
23
25
|
require_relative 'libui/libui_base'
|
|
26
|
+
require_relative 'libui/font'
|
|
27
|
+
require_relative 'libui/area_handler'
|
|
28
|
+
require_relative 'libui/table_model'
|
|
29
|
+
require_relative 'libui/draw_values'
|
|
30
|
+
require_relative 'libui/path'
|
|
24
31
|
|
|
25
32
|
extend LibUIBase
|
|
26
33
|
|
|
27
34
|
class << self
|
|
35
|
+
def control_on_destroyed(control, callback = nil, data = nil, &block)
|
|
36
|
+
callback = block if block
|
|
37
|
+
unless callback.nil? || callback.respond_to?(:call)
|
|
38
|
+
raise TypeError, 'expected a callable destruction callback'
|
|
39
|
+
end
|
|
40
|
+
CallbackRegistry.on_destroyed(control, callback, data)
|
|
41
|
+
nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def queue_main(callback = nil, data = nil, &block)
|
|
45
|
+
callback = block if block
|
|
46
|
+
raise TypeError, 'expected a callable callback' unless callback.respond_to?(:call)
|
|
47
|
+
|
|
48
|
+
key = Object.new
|
|
49
|
+
closure = nil
|
|
50
|
+
closure = Fiddle::Closure::BlockCaller.new(Fiddle::TYPE_VOID, [Fiddle::TYPE_VOIDP]) do |native_data|
|
|
51
|
+
begin
|
|
52
|
+
callback.call(native_data)
|
|
53
|
+
rescue StandardError => e
|
|
54
|
+
CallbackRegistry.report(e)
|
|
55
|
+
ensure
|
|
56
|
+
CallbackRegistry.release_global(key)
|
|
57
|
+
closure.to_i
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
CallbackRegistry.global(key, closure)
|
|
61
|
+
FFI.uiQueueMain(closure, data)
|
|
62
|
+
rescue StandardError
|
|
63
|
+
CallbackRegistry.release_global(key) if key
|
|
64
|
+
raise
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def timer(milliseconds, callback = nil, data = nil, &block)
|
|
68
|
+
callback = block if block
|
|
69
|
+
raise TypeError, 'expected a callable callback' unless callback.respond_to?(:call)
|
|
70
|
+
|
|
71
|
+
key = Object.new
|
|
72
|
+
closure = nil
|
|
73
|
+
closure = Fiddle::Closure::BlockCaller.new(Fiddle::TYPE_INT, [Fiddle::TYPE_VOIDP]) do |native_data|
|
|
74
|
+
result = begin
|
|
75
|
+
value = callback.call(native_data)
|
|
76
|
+
value == true ? 1 : (value == false || value.nil? ? 0 : Integer(value))
|
|
77
|
+
rescue StandardError => e
|
|
78
|
+
CallbackRegistry.report(e)
|
|
79
|
+
0
|
|
80
|
+
end
|
|
81
|
+
CallbackRegistry.release_global(key) if result.zero?
|
|
82
|
+
closure.to_i
|
|
83
|
+
result
|
|
84
|
+
end
|
|
85
|
+
CallbackRegistry.global(key, closure)
|
|
86
|
+
FFI.uiTimer(milliseconds, closure, data)
|
|
87
|
+
rescue StandardError
|
|
88
|
+
CallbackRegistry.release_global(key) if key
|
|
89
|
+
raise
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def uninit
|
|
93
|
+
result = super
|
|
94
|
+
CallbackRegistry.clear
|
|
95
|
+
result
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def toolbar_append_button(toolbar, text, icon = nil)
|
|
99
|
+
item = super(toolbar, text, icon)
|
|
100
|
+
CallbackRegistry.track_other_child(toolbar, item)
|
|
101
|
+
item
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def toolbar_append_toggle_button(toolbar, text, icon = nil)
|
|
105
|
+
item = super(toolbar, text, icon)
|
|
106
|
+
CallbackRegistry.track_other_child(toolbar, item)
|
|
107
|
+
item
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def free_toolbar(toolbar)
|
|
111
|
+
raise RuntimeError, 'detach toolbar from its window before freeing it' if CallbackRegistry.toolbar_attached?(toolbar)
|
|
112
|
+
|
|
113
|
+
result = super(toolbar)
|
|
114
|
+
CallbackRegistry.release_other(toolbar)
|
|
115
|
+
result
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def window_set_toolbar(window, toolbar)
|
|
119
|
+
result = super(window, toolbar)
|
|
120
|
+
CallbackRegistry.attach_toolbar(window, toolbar)
|
|
121
|
+
result
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def new_area(handler)
|
|
125
|
+
return super(handler) unless handler.is_a?(AreaHandler)
|
|
126
|
+
|
|
127
|
+
area = super(handler.to_ptr)
|
|
128
|
+
CallbackRegistry.control(area, :area_handler, handler)
|
|
129
|
+
area
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def new_scrolling_area(handler, width, height)
|
|
133
|
+
return super(handler, width, height) unless handler.is_a?(AreaHandler)
|
|
134
|
+
|
|
135
|
+
area = super(handler.to_ptr, width, height)
|
|
136
|
+
CallbackRegistry.control(area, :area_handler, handler)
|
|
137
|
+
area
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def new_table_model(handler)
|
|
141
|
+
return super(handler) unless handler.is_a?(TableModelHandler)
|
|
142
|
+
|
|
143
|
+
model = super(handler.to_ptr)
|
|
144
|
+
raise RuntimeError, 'libui-ng could not create table model' if model.nil? || model.null?
|
|
145
|
+
|
|
146
|
+
CallbackRegistry.other(model, :table_model_handler, handler)
|
|
147
|
+
model
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def free_table_model(model)
|
|
151
|
+
return model.free if model.is_a?(TableModel)
|
|
152
|
+
|
|
153
|
+
result = super(model)
|
|
154
|
+
CallbackRegistry.release_other(model)
|
|
155
|
+
result
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def new_table(params = nil, model: nil, row_background_color_model_column: -1)
|
|
159
|
+
return super(params) if model.nil?
|
|
160
|
+
raise ArgumentError, 'provide params or model, not both' unless params.nil?
|
|
161
|
+
raise TypeError, 'expected LibUI::TableModel' unless model.is_a?(TableModel)
|
|
162
|
+
|
|
163
|
+
native = FFI::TableParams.malloc
|
|
164
|
+
native.to_ptr.free = Fiddle::RUBY_FREE
|
|
165
|
+
native.Model = model.to_ptr
|
|
166
|
+
native.RowBackgroundColorModelColumn = row_background_color_model_column
|
|
167
|
+
table = super(native)
|
|
168
|
+
CallbackRegistry.control(table, :table_model, model)
|
|
169
|
+
CallbackRegistry.on_cleanup(table) { model.detach_table }
|
|
170
|
+
model.attach_table
|
|
171
|
+
table
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def table_append_text_column(table, name, text_column, editable_column, options = nil,
|
|
175
|
+
color_model_column: nil)
|
|
176
|
+
super(table, name, text_column, editable_column,
|
|
177
|
+
table_text_params(options, color_model_column))
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def table_append_image_text_column(table, name, image_column, text_column,
|
|
181
|
+
editable_column, options = nil, color_model_column: nil)
|
|
182
|
+
super(table, name, image_column, text_column, editable_column,
|
|
183
|
+
table_text_params(options, color_model_column))
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def table_append_checkbox_text_column(table, name, checkbox_column,
|
|
187
|
+
checkbox_editable_column, text_column,
|
|
188
|
+
text_editable_column, options = nil,
|
|
189
|
+
color_model_column: nil)
|
|
190
|
+
super(table, name, checkbox_column, checkbox_editable_column,
|
|
191
|
+
text_column, text_editable_column,
|
|
192
|
+
table_text_params(options, color_model_column))
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def draw_fill(context, path, brush)
|
|
196
|
+
super(context, path.is_a?(Path) ? path.to_ptr : path,
|
|
197
|
+
brush.is_a?(Brush) ? brush.to_ptr : brush)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def draw_stroke(context, path, brush, stroke_params)
|
|
201
|
+
super(context, path.is_a?(Path) ? path.to_ptr : path,
|
|
202
|
+
brush.is_a?(Brush) ? brush.to_ptr : brush,
|
|
203
|
+
stroke_params.is_a?(StrokeParams) ? stroke_params.to_ptr : stroke_params)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def draw_clip(context, path)
|
|
207
|
+
super(context, path.is_a?(Path) ? path.to_ptr : path)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def draw_transform(context, matrix)
|
|
211
|
+
super(context, matrix.is_a?(Matrix) ? matrix.to_ptr : matrix)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def version
|
|
215
|
+
super.to_s
|
|
216
|
+
end
|
|
217
|
+
|
|
28
218
|
def init(opt = nil)
|
|
29
219
|
# Allocate uiInitOptions if not provided
|
|
30
220
|
unless opt
|
|
@@ -143,6 +333,246 @@ module LibUI
|
|
|
143
333
|
super(str)
|
|
144
334
|
end
|
|
145
335
|
|
|
336
|
+
def load_control_font(descriptor = nil)
|
|
337
|
+
return super(descriptor) if descriptor
|
|
338
|
+
|
|
339
|
+
read_font_descriptor { |native| super(native) }
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def font_button_font(button, descriptor = nil)
|
|
343
|
+
return super(button, descriptor) if descriptor
|
|
344
|
+
|
|
345
|
+
read_font_descriptor { |native| super(button, native) }
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
def draw_new_text_layout(string_or_params, font: nil, width: -1, align: DrawTextAlignLeft)
|
|
349
|
+
return super(string_or_params) if font.nil?
|
|
350
|
+
raise TypeError, 'expected LibUI::Font' unless font.is_a?(Font)
|
|
351
|
+
|
|
352
|
+
native_family = Fiddle::Pointer.malloc(font.family.bytesize + 1, Fiddle::RUBY_FREE)
|
|
353
|
+
native_family[0, font.family.bytesize + 1] = font.family + "\0"
|
|
354
|
+
native_font = FFI::FontDescriptor.malloc
|
|
355
|
+
native_font.to_ptr.free = Fiddle::RUBY_FREE
|
|
356
|
+
native_font.Family = native_family
|
|
357
|
+
native_font.Size = font.size
|
|
358
|
+
native_font.Weight = font.weight
|
|
359
|
+
native_font.Italic = font.italic
|
|
360
|
+
native_font.Stretch = font.stretch
|
|
361
|
+
|
|
362
|
+
params = FFI::DrawTextLayoutParams.malloc
|
|
363
|
+
params.to_ptr.free = Fiddle::RUBY_FREE
|
|
364
|
+
params.String = string_or_params
|
|
365
|
+
params.DefaultFont = native_font
|
|
366
|
+
params.Width = width
|
|
367
|
+
params.Align = align
|
|
368
|
+
result = super(params)
|
|
369
|
+
# Keep both native allocations alive through the native call.
|
|
370
|
+
native_font.to_ptr.to_i
|
|
371
|
+
native_family.to_i
|
|
372
|
+
result
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def window_title(window)
|
|
376
|
+
read_owned_text(super(window))
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def button_text(button)
|
|
380
|
+
read_owned_text(super(button))
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def checkbox_text(checkbox)
|
|
384
|
+
read_owned_text(super(checkbox))
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def entry_text(entry)
|
|
388
|
+
read_owned_text(super(entry))
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def label_text(label)
|
|
392
|
+
read_owned_text(super(label))
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def group_title(group)
|
|
396
|
+
read_owned_text(super(group))
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def editable_combobox_text(combobox)
|
|
400
|
+
read_owned_text(super(combobox))
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def multiline_entry_text(entry)
|
|
404
|
+
read_owned_text(super(entry))
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def open_file(window)
|
|
408
|
+
read_owned_text(super(window))
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def open_folder(window)
|
|
412
|
+
read_owned_text(super(window))
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def save_file(window)
|
|
416
|
+
read_owned_text(super(window))
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
def attribute_family(attribute)
|
|
420
|
+
read_borrowed_text(super(attribute))
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def attributed_string_string(attributed_string)
|
|
424
|
+
read_borrowed_text(super(attributed_string))
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
def table_value_string(value)
|
|
428
|
+
read_borrowed_text(super(value))
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def date_time_picker_time(picker)
|
|
432
|
+
tm = FFI::TM.malloc
|
|
433
|
+
tm.to_ptr.free = Fiddle::RUBY_FREE
|
|
434
|
+
super(picker, tm)
|
|
435
|
+
if tm.tm_isdst.negative?
|
|
436
|
+
Time.local(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
|
437
|
+
tm.tm_hour, tm.tm_min, tm.tm_sec)
|
|
438
|
+
else
|
|
439
|
+
# The ten-argument form preserves which side of a repeated DST hour was selected.
|
|
440
|
+
Time.local(tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mday,
|
|
441
|
+
tm.tm_mon + 1, tm.tm_year + 1900, 0, 0,
|
|
442
|
+
tm.tm_isdst != 0, nil)
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def date_time_picker_set_time(picker, value)
|
|
447
|
+
local_time = case value
|
|
448
|
+
when Time, DateTime then value.to_time.getlocal
|
|
449
|
+
when Date then Time.local(value.year, value.month, value.day)
|
|
450
|
+
else raise TypeError, 'expected Time, DateTime, or Date'
|
|
451
|
+
end
|
|
452
|
+
tm = FFI::TM.malloc
|
|
453
|
+
tm.to_ptr.free = Fiddle::RUBY_FREE
|
|
454
|
+
tm.to_ptr[0, FFI::TM.size] = "\0" * FFI::TM.size
|
|
455
|
+
tm.tm_sec = local_time.sec
|
|
456
|
+
tm.tm_min = local_time.min
|
|
457
|
+
tm.tm_hour = local_time.hour
|
|
458
|
+
tm.tm_mday = local_time.day
|
|
459
|
+
tm.tm_mon = local_time.month - 1
|
|
460
|
+
tm.tm_year = local_time.year - 1900
|
|
461
|
+
tm.tm_wday = local_time.wday
|
|
462
|
+
tm.tm_yday = local_time.yday - 1
|
|
463
|
+
tm.tm_isdst = Fiddle::WINDOWS ? -1 : (local_time.dst? ? 1 : 0)
|
|
464
|
+
super(picker, tm)
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
def toolbar_item_text(item)
|
|
468
|
+
read_owned_text(super(item))
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
def toolbar_item_tooltip(item)
|
|
472
|
+
read_owned_text(super(item))
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
def window_content_size(window)
|
|
476
|
+
read_outputs('i', 2) { |width, height| super(window, width, height) }
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
def color_button_color(button)
|
|
480
|
+
read_outputs('d', 4) { |r, g, b, a| super(button, r, g, b, a) }
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
def table_value_color(value)
|
|
484
|
+
read_outputs('d', 4) { |r, g, b, a| super(value, r, g, b, a) }
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
def attribute_color(attribute)
|
|
488
|
+
read_outputs('d', 4) { |r, g, b, a| super(attribute, r, g, b, a) }
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def attribute_underline_color(attribute)
|
|
492
|
+
color = nil
|
|
493
|
+
underline = read_outputs('i', 1) do |type|
|
|
494
|
+
color = read_outputs('d', 4) do |r, g, b, a|
|
|
495
|
+
super(attribute, type, r, g, b, a)
|
|
496
|
+
end
|
|
497
|
+
end
|
|
498
|
+
underline + color
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
def draw_text_layout_extents(layout)
|
|
502
|
+
read_outputs('d', 2) { |width, height| super(layout, width, height) }
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def draw_matrix_transform_point(matrix, x, y)
|
|
506
|
+
matrix = matrix.to_ptr if matrix.is_a?(Matrix)
|
|
507
|
+
x_pointer = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE, Fiddle::RUBY_FREE)
|
|
508
|
+
y_pointer = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE, Fiddle::RUBY_FREE)
|
|
509
|
+
x_pointer[0, Fiddle::SIZEOF_DOUBLE] = [x].pack('d')
|
|
510
|
+
y_pointer[0, Fiddle::SIZEOF_DOUBLE] = [y].pack('d')
|
|
511
|
+
super(matrix, x_pointer, y_pointer)
|
|
512
|
+
[x_pointer[0, Fiddle::SIZEOF_DOUBLE].unpack1('d'),
|
|
513
|
+
y_pointer[0, Fiddle::SIZEOF_DOUBLE].unpack1('d')]
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def draw_matrix_transform_size(matrix, x, y)
|
|
517
|
+
matrix = matrix.to_ptr if matrix.is_a?(Matrix)
|
|
518
|
+
x_pointer = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE, Fiddle::RUBY_FREE)
|
|
519
|
+
y_pointer = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE, Fiddle::RUBY_FREE)
|
|
520
|
+
x_pointer[0, Fiddle::SIZEOF_DOUBLE] = [x].pack('d')
|
|
521
|
+
y_pointer[0, Fiddle::SIZEOF_DOUBLE] = [y].pack('d')
|
|
522
|
+
super(matrix, x_pointer, y_pointer)
|
|
523
|
+
[x_pointer[0, Fiddle::SIZEOF_DOUBLE].unpack1('d'),
|
|
524
|
+
y_pointer[0, Fiddle::SIZEOF_DOUBLE].unpack1('d')]
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
def table_get_selection(table)
|
|
528
|
+
selection = super(table)
|
|
529
|
+
return nil if selection.nil? || selection.null?
|
|
530
|
+
|
|
531
|
+
data = FFI::TableSelection.new(selection)
|
|
532
|
+
rows = data.Rows
|
|
533
|
+
Array.new(data.NumRows) do |index|
|
|
534
|
+
rows[index * Fiddle::SIZEOF_INT, Fiddle::SIZEOF_INT].unpack1('i')
|
|
535
|
+
end
|
|
536
|
+
ensure
|
|
537
|
+
free_table_selection(selection) if selection && !selection.null?
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def table_set_selection(table, rows)
|
|
541
|
+
unless rows.is_a?(Array)
|
|
542
|
+
valid_native = rows.is_a?(FFI::TableSelection) ||
|
|
543
|
+
(rows.is_a?(Fiddle::Pointer) && !rows.null?)
|
|
544
|
+
raise TypeError, 'expected an Array or native uiTableSelection' unless valid_native
|
|
545
|
+
|
|
546
|
+
return super(table, rows)
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
max_int = (1 << (Fiddle::SIZEOF_INT * 8 - 1)) - 1
|
|
550
|
+
raise RangeError, 'too many selected rows' if rows.length > max_int
|
|
551
|
+
|
|
552
|
+
rows.each do |row|
|
|
553
|
+
raise TypeError, 'row index must be an Integer' unless row.is_a?(Integer)
|
|
554
|
+
raise RangeError, 'row index is out of range' unless row.between?(0, max_int)
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
native_rows = if rows.empty?
|
|
558
|
+
Fiddle::Pointer.new(0)
|
|
559
|
+
else
|
|
560
|
+
packed = rows.pack('i*')
|
|
561
|
+
pointer = Fiddle::Pointer.malloc(packed.bytesize, Fiddle::RUBY_FREE)
|
|
562
|
+
pointer[0, packed.bytesize] = packed
|
|
563
|
+
pointer
|
|
564
|
+
end
|
|
565
|
+
selection = FFI::TableSelection.malloc
|
|
566
|
+
selection.to_ptr.free = Fiddle::RUBY_FREE
|
|
567
|
+
selection.NumRows = rows.length
|
|
568
|
+
selection.Rows = native_rows
|
|
569
|
+
result = super(table, selection)
|
|
570
|
+
# Keep both native allocations alive until libui-ng copies the rows.
|
|
571
|
+
selection.to_ptr.to_i
|
|
572
|
+
native_rows.to_i
|
|
573
|
+
result
|
|
574
|
+
end
|
|
575
|
+
|
|
146
576
|
# Gets the window position.
|
|
147
577
|
# Coordinates are measured from the top left corner of the screen.
|
|
148
578
|
# @param w [Fiddle::Pointer] Pointer of uiWindow instance.
|
|
@@ -172,9 +602,172 @@ module LibUI
|
|
|
172
602
|
super(otf, a, b, c, d)
|
|
173
603
|
end
|
|
174
604
|
|
|
175
|
-
def open_type_features_get(otf, a, b, c, d
|
|
605
|
+
def open_type_features_get(otf, a, b, c, d)
|
|
176
606
|
a, b, c, d = [a, b, c, d].map { |s| s.is_a?(String) ? s.ord : s }
|
|
177
|
-
|
|
607
|
+
value = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
|
|
608
|
+
return nil if super(otf, a, b, c, d, value).zero?
|
|
609
|
+
|
|
610
|
+
value[0, Fiddle::SIZEOF_INT].unpack1('L')
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
# The native function copies the pixels before returning. The input must be
|
|
614
|
+
# premultiplied RGBA, with rows separated by byte_stride bytes.
|
|
615
|
+
def image_append(image, pixels, width, height, byte_stride)
|
|
616
|
+
[width, height, byte_stride].each do |number|
|
|
617
|
+
raise TypeError, 'image dimensions and stride must be Integers' unless number.is_a?(Integer)
|
|
618
|
+
end
|
|
619
|
+
raise ArgumentError, 'image dimensions must be positive' if width <= 0 || height <= 0
|
|
620
|
+
max_int = (1 << (Fiddle::SIZEOF_INT * 8 - 1)) - 1
|
|
621
|
+
raise RangeError, 'image dimensions or stride exceed C int' if [width, height, byte_stride].any? { |number| number > max_int }
|
|
622
|
+
raise ArgumentError, 'byte stride is too small' if byte_stride < width * 4
|
|
623
|
+
raise TypeError, 'pixels must be a String or Fiddle::Pointer' unless pixels.is_a?(String) || pixels.is_a?(Fiddle::Pointer)
|
|
624
|
+
if pixels.is_a?(String) && pixels.bytesize < byte_stride * height
|
|
625
|
+
raise ArgumentError, 'pixel buffer is shorter than stride * height'
|
|
626
|
+
end
|
|
627
|
+
if pixels.is_a?(Fiddle::Pointer) && pixels.size.positive? && pixels.size < byte_stride * height
|
|
628
|
+
raise ArgumentError, 'pixel buffer is shorter than stride * height'
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
super(image, pixels, width, height, byte_stride)
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
# Convert straight RGBA (as used by PNG libraries) to premultiplied RGBA.
|
|
635
|
+
def image_append_rgba(image, pixels, width, height, byte_stride = width * 4)
|
|
636
|
+
raise TypeError, 'pixels must be a String' unless pixels.is_a?(String)
|
|
637
|
+
[width, height, byte_stride].each do |number|
|
|
638
|
+
raise TypeError, 'image dimensions and stride must be Integers' unless number.is_a?(Integer)
|
|
639
|
+
end
|
|
640
|
+
raise ArgumentError, 'image dimensions must be positive' if width <= 0 || height <= 0
|
|
641
|
+
raise ArgumentError, 'byte stride is too small' if byte_stride < width * 4
|
|
642
|
+
raise ArgumentError, 'pixel buffer is shorter than stride * height' if pixels.bytesize < byte_stride * height
|
|
643
|
+
|
|
644
|
+
converted = pixels.b.dup
|
|
645
|
+
height.times do |y|
|
|
646
|
+
width.times do |x|
|
|
647
|
+
offset = y * byte_stride + x * 4
|
|
648
|
+
alpha = converted.getbyte(offset + 3)
|
|
649
|
+
3.times do |channel|
|
|
650
|
+
converted.setbyte(offset + channel, (converted.getbyte(offset + channel) * alpha + 127) / 255)
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
image_append(image, converted, width, height, byte_stride)
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
def open_type_features_for_each(features)
|
|
658
|
+
return enum_for(__method__, features) unless block_given?
|
|
659
|
+
|
|
660
|
+
error = nil
|
|
661
|
+
callback = Fiddle::Closure::BlockCaller.new(Fiddle::TYPE_INT,
|
|
662
|
+
[Fiddle::TYPE_VOIDP] + [Fiddle::TYPE_CHAR] * 4 +
|
|
663
|
+
[Fiddle::TYPE_UINT32_T, Fiddle::TYPE_VOIDP]) do |_features, a, b, c, d, value, _data|
|
|
664
|
+
begin
|
|
665
|
+
tag = [a, b, c, d].pack('C*').force_encoding(Encoding::ASCII_8BIT)
|
|
666
|
+
yield(tag, value) == ForEachStop ? ForEachStop : ForEachContinue
|
|
667
|
+
rescue StandardError => e
|
|
668
|
+
error = e
|
|
669
|
+
ForEachStop
|
|
670
|
+
end
|
|
671
|
+
end
|
|
672
|
+
FFI.uiOpenTypeFeaturesForEach(features, callback, nil)
|
|
673
|
+
raise error if error
|
|
674
|
+
|
|
675
|
+
features
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
def attribute_features(attribute)
|
|
679
|
+
borrowed = super(attribute)
|
|
680
|
+
return nil if borrowed.nil? || borrowed.null?
|
|
681
|
+
|
|
682
|
+
open_type_features_for_each(borrowed).to_h
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
# Values are copied during the callback; native attribute pointers expire
|
|
686
|
+
# as soon as the callback returns.
|
|
687
|
+
def attributed_string_for_each_attribute(string)
|
|
688
|
+
return enum_for(__method__, string) unless block_given?
|
|
689
|
+
|
|
690
|
+
error = nil
|
|
691
|
+
callback = Fiddle::Closure::BlockCaller.new(Fiddle::TYPE_INT,
|
|
692
|
+
[Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP,
|
|
693
|
+
Fiddle::TYPE_SIZE_T, Fiddle::TYPE_SIZE_T,
|
|
694
|
+
Fiddle::TYPE_VOIDP]) do |_string, attribute, first, last, _data|
|
|
695
|
+
begin
|
|
696
|
+
yield(attribute_snapshot(attribute), first, last) == ForEachStop ? ForEachStop : ForEachContinue
|
|
697
|
+
rescue StandardError => e
|
|
698
|
+
error = e
|
|
699
|
+
ForEachStop
|
|
700
|
+
end
|
|
701
|
+
end
|
|
702
|
+
FFI.uiAttributedStringForEachAttribute(string, callback, nil)
|
|
703
|
+
raise error if error
|
|
704
|
+
|
|
705
|
+
string
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
private
|
|
709
|
+
|
|
710
|
+
def table_text_params(options, color_model_column)
|
|
711
|
+
return options if color_model_column.nil?
|
|
712
|
+
raise ArgumentError, 'provide options or color_model_column, not both' unless options.nil?
|
|
713
|
+
|
|
714
|
+
native = FFI::TableTextColumnOptionalParams.malloc
|
|
715
|
+
native.to_ptr.free = Fiddle::RUBY_FREE
|
|
716
|
+
native.ColorModelColumn = Integer(color_model_column)
|
|
717
|
+
native
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
def attribute_snapshot(attribute)
|
|
721
|
+
type = attribute_get_type(attribute)
|
|
722
|
+
value = case type
|
|
723
|
+
when AttributeTypeFamily then attribute_family(attribute)
|
|
724
|
+
when AttributeTypeSize then attribute_size(attribute)
|
|
725
|
+
when AttributeTypeWeight then attribute_weight(attribute)
|
|
726
|
+
when AttributeTypeItalic then attribute_italic(attribute)
|
|
727
|
+
when AttributeTypeStretch then attribute_stretch(attribute)
|
|
728
|
+
when AttributeTypeColor then attribute_color(attribute)
|
|
729
|
+
# libui-ng exposes no getter for a background attribute's color.
|
|
730
|
+
when AttributeTypeBackground then nil
|
|
731
|
+
when AttributeTypeUnderline then attribute_underline(attribute)
|
|
732
|
+
when AttributeTypeUnderlineColor then attribute_underline_color(attribute)
|
|
733
|
+
when AttributeTypeFeatures then attribute_features(attribute)
|
|
734
|
+
else raise ArgumentError, "unknown attribute type: #{type}"
|
|
735
|
+
end
|
|
736
|
+
{ type: type, value: value }
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
def read_font_descriptor
|
|
740
|
+
descriptor = FFI::FontDescriptor.malloc
|
|
741
|
+
descriptor.to_ptr.free = Fiddle::RUBY_FREE
|
|
742
|
+
filled = false
|
|
743
|
+
yield(descriptor)
|
|
744
|
+
filled = true
|
|
745
|
+
Font.new(family: descriptor.Family.to_s.force_encoding(Encoding::UTF_8),
|
|
746
|
+
size: descriptor.Size, weight: descriptor.Weight,
|
|
747
|
+
italic: descriptor.Italic, stretch: descriptor.Stretch)
|
|
748
|
+
ensure
|
|
749
|
+
free_font_descriptor(descriptor) if filled
|
|
750
|
+
end
|
|
751
|
+
|
|
752
|
+
def read_owned_text(pointer)
|
|
753
|
+
return nil if pointer.nil? || pointer.null?
|
|
754
|
+
|
|
755
|
+
pointer.to_s.force_encoding(Encoding::UTF_8)
|
|
756
|
+
ensure
|
|
757
|
+
free_text(pointer) if pointer && !pointer.null?
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
def read_borrowed_text(pointer)
|
|
761
|
+
return nil if pointer.nil? || pointer.null?
|
|
762
|
+
|
|
763
|
+
pointer.to_s.force_encoding(Encoding::UTF_8)
|
|
764
|
+
end
|
|
765
|
+
|
|
766
|
+
def read_outputs(format, count)
|
|
767
|
+
size = format == 'd' ? Fiddle::SIZEOF_DOUBLE : Fiddle::SIZEOF_INT
|
|
768
|
+
pointers = Array.new(count) { Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) }
|
|
769
|
+
yield(*pointers)
|
|
770
|
+
pointers.map { |pointer| pointer[0, size].unpack1(format) }
|
|
178
771
|
end
|
|
179
772
|
end
|
|
180
773
|
|
|
@@ -335,6 +928,12 @@ module LibUI
|
|
|
335
928
|
AtTrailing = 2
|
|
336
929
|
AtBottom = 3
|
|
337
930
|
|
|
931
|
+
# ToolbarDisplayMode
|
|
932
|
+
ToolbarDisplayModeIconOnly = 0
|
|
933
|
+
ToolbarDisplayModeIconAndTextHorizontal = 1
|
|
934
|
+
ToolbarDisplayModeIconAndTextVertical = 2
|
|
935
|
+
ToolbarDisplayModeTextOnly = 3
|
|
936
|
+
|
|
338
937
|
# ImageViewContentMode
|
|
339
938
|
ImageViewContentCenter = 0
|
|
340
939
|
ImageViewContentFit = 1
|
data/vendor/libui.x86_64.so
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: libui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.0.
|
|
4
|
+
version: 0.3.0.pre3
|
|
5
5
|
platform: x86_64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- kojix2
|
|
@@ -32,11 +32,17 @@ files:
|
|
|
32
32
|
- LICENSE.txt
|
|
33
33
|
- README.md
|
|
34
34
|
- lib/libui.rb
|
|
35
|
+
- lib/libui/area_handler.rb
|
|
36
|
+
- lib/libui/callback_registry.rb
|
|
37
|
+
- lib/libui/draw_values.rb
|
|
35
38
|
- lib/libui/error.rb
|
|
36
39
|
- lib/libui/ffi.rb
|
|
37
40
|
- lib/libui/fiddle_patch.rb
|
|
41
|
+
- lib/libui/font.rb
|
|
38
42
|
- lib/libui/libui_base.rb
|
|
43
|
+
- lib/libui/path.rb
|
|
39
44
|
- lib/libui/platform.rb
|
|
45
|
+
- lib/libui/table_model.rb
|
|
40
46
|
- lib/libui/utils.rb
|
|
41
47
|
- lib/libui/version.rb
|
|
42
48
|
- vendor/LICENSE.md
|
|
@@ -60,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
60
66
|
- !ruby/object:Gem::Version
|
|
61
67
|
version: '0'
|
|
62
68
|
requirements: []
|
|
63
|
-
rubygems_version:
|
|
69
|
+
rubygems_version: 4.0.20
|
|
64
70
|
specification_version: 4
|
|
65
71
|
summary: Ruby bindings to libui
|
|
66
72
|
test_files: []
|