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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module LibUI
|
|
2
|
+
# Native controls can outlive the Ruby pointer returned by their constructor.
|
|
3
|
+
# Keep closures by native address until libui-ng reports destruction.
|
|
4
|
+
module CallbackRegistry
|
|
5
|
+
@controls = {}
|
|
6
|
+
@destroy_hooks = {}
|
|
7
|
+
@other = {}
|
|
8
|
+
@other_children = {}
|
|
9
|
+
@attached_toolbars = {}
|
|
10
|
+
@toolbar_window_hooks = {}
|
|
11
|
+
@global = {}
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
def control(pointer, key, callback)
|
|
15
|
+
raise ArgumentError, 'control pointer is null' if pointer.nil? || pointer.to_i.zero?
|
|
16
|
+
|
|
17
|
+
address = pointer.to_i
|
|
18
|
+
callbacks = (@controls[address] ||= {})
|
|
19
|
+
unless @destroy_hooks.key?(address)
|
|
20
|
+
hook = nil
|
|
21
|
+
hook = Fiddle::Closure::BlockCaller.new(Fiddle::TYPE_VOID,
|
|
22
|
+
[Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP]) do |native, _data|
|
|
23
|
+
destroyed_address = native.to_i
|
|
24
|
+
begin
|
|
25
|
+
callbacks = @controls[destroyed_address]
|
|
26
|
+
callbacks&.fetch(:cleanup, [])&.each do |cleanup|
|
|
27
|
+
begin
|
|
28
|
+
cleanup.call
|
|
29
|
+
rescue StandardError => e
|
|
30
|
+
report(e)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
user = callbacks&.delete(:on_destroyed)
|
|
34
|
+
user[0].call(native, user[1]) if user && user[0]
|
|
35
|
+
rescue StandardError => e
|
|
36
|
+
report(e)
|
|
37
|
+
ensure
|
|
38
|
+
@controls.delete(destroyed_address)
|
|
39
|
+
@destroy_hooks.delete(destroyed_address)
|
|
40
|
+
hook.to_i
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
@destroy_hooks[address] = hook
|
|
44
|
+
begin
|
|
45
|
+
FFI.uiControlOnDestroyed(pointer, hook, nil)
|
|
46
|
+
rescue StandardError
|
|
47
|
+
@destroy_hooks.delete(address)
|
|
48
|
+
@controls.delete(address) if callbacks.empty?
|
|
49
|
+
raise
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
callbacks[key] = callback
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def on_destroyed(pointer, callback, data)
|
|
56
|
+
control(pointer, :on_destroyed, [callback, data])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def on_cleanup(pointer, &block)
|
|
60
|
+
control(pointer, :cleanup, []) unless @controls.dig(pointer.to_i, :cleanup)
|
|
61
|
+
@controls[pointer.to_i][:cleanup] << block
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def other(pointer, key, callback)
|
|
65
|
+
(@other[pointer.to_i] ||= {})[key] = callback
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def release_other(pointer)
|
|
69
|
+
address = pointer.to_i
|
|
70
|
+
@other.delete(address)
|
|
71
|
+
(@other_children.delete(address) || []).each { |child| @other.delete(child) }
|
|
72
|
+
@attached_toolbars.delete(address)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def track_other_child(parent, child)
|
|
76
|
+
(@other_children[parent.to_i] ||= []) << child.to_i
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def attach_toolbar(window, toolbar)
|
|
80
|
+
window_address = window.to_i
|
|
81
|
+
@attached_toolbars.delete_if { |_toolbar, owner| owner == window_address }
|
|
82
|
+
return if toolbar.nil? || toolbar.to_i.zero?
|
|
83
|
+
|
|
84
|
+
@attached_toolbars[toolbar.to_i] = window_address
|
|
85
|
+
return if @toolbar_window_hooks[window_address]
|
|
86
|
+
|
|
87
|
+
on_cleanup(window) do
|
|
88
|
+
@attached_toolbars.delete_if { |_toolbar, owner| owner == window_address }
|
|
89
|
+
@toolbar_window_hooks.delete(window_address)
|
|
90
|
+
end
|
|
91
|
+
@toolbar_window_hooks[window_address] = true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def toolbar_attached?(toolbar)
|
|
95
|
+
@attached_toolbars.key?(toolbar.to_i)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def global(key, callback)
|
|
99
|
+
@global[key] = callback
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def release_global(key)
|
|
103
|
+
@global.delete(key)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def clear
|
|
107
|
+
@controls.clear
|
|
108
|
+
@destroy_hooks.clear
|
|
109
|
+
@other.clear
|
|
110
|
+
@other_children.clear
|
|
111
|
+
@attached_toolbars.clear
|
|
112
|
+
@toolbar_window_hooks.clear
|
|
113
|
+
@global.clear
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def report(error)
|
|
117
|
+
warn "LibUI callback error: #{error.full_message}"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
private_constant :CallbackRegistry
|
|
123
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
module LibUI
|
|
2
|
+
class Brush
|
|
3
|
+
GradientStop = Struct.new(:position, :red, :green, :blue, :alpha,
|
|
4
|
+
keyword_init: true)
|
|
5
|
+
|
|
6
|
+
def initialize(type: DrawBrushTypeSolid, color: [0.0, 0.0, 0.0, 1.0],
|
|
7
|
+
x0: 0.0, y0: 0.0, x1: 0.0, y1: 0.0, outer_radius: 0.0,
|
|
8
|
+
stops: [])
|
|
9
|
+
@native = FFI::DrawBrush.malloc
|
|
10
|
+
@native.to_ptr.free = Fiddle::RUBY_FREE
|
|
11
|
+
@native.to_ptr[0, FFI::DrawBrush.size] = "\0" * FFI::DrawBrush.size
|
|
12
|
+
@native.Type = type
|
|
13
|
+
self.color = color
|
|
14
|
+
@native.X0 = x0
|
|
15
|
+
@native.Y0 = y0
|
|
16
|
+
@native.X1 = x1
|
|
17
|
+
@native.Y1 = y1
|
|
18
|
+
@native.OuterRadius = outer_radius
|
|
19
|
+
self.stops = stops
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_ptr
|
|
23
|
+
@native.to_ptr
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def color=(rgba)
|
|
27
|
+
unless rgba.is_a?(Array) && rgba.length == 4 && rgba.all? { |component| component.is_a?(Numeric) }
|
|
28
|
+
raise TypeError, 'color must be an RGBA array'
|
|
29
|
+
end
|
|
30
|
+
@native.R, @native.G, @native.B, @native.A = rgba
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def stops=(stops)
|
|
34
|
+
raise TypeError, 'stops must be an Array' unless stops.is_a?(Array)
|
|
35
|
+
|
|
36
|
+
size = FFI::DrawBrushGradientStop.size
|
|
37
|
+
pointer = stops.empty? ? Fiddle::Pointer.new(0) : Fiddle::Pointer.malloc(size * stops.length, Fiddle::RUBY_FREE)
|
|
38
|
+
stops.each_with_index do |entry, index|
|
|
39
|
+
stop = entry.is_a?(GradientStop) ? entry.to_a : entry
|
|
40
|
+
unless stop.is_a?(Array) && stop.length == 5 && stop.all? { |value| value.is_a?(Numeric) }
|
|
41
|
+
raise TypeError, 'each stop must have position, red, green, blue, alpha'
|
|
42
|
+
end
|
|
43
|
+
native = FFI::DrawBrushGradientStop.new(pointer + index * size)
|
|
44
|
+
native.Pos, native.R, native.G, native.B, native.A = stop
|
|
45
|
+
end
|
|
46
|
+
@stops_pointer = pointer
|
|
47
|
+
@native.Stops = pointer
|
|
48
|
+
@native.NumStops = stops.length
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class StrokeParams
|
|
53
|
+
def initialize(cap: DrawLineCapFlat, join: DrawLineJoinMiter,
|
|
54
|
+
thickness: 1.0, miter_limit: DrawDefaultMiterLimit,
|
|
55
|
+
dashes: [], dash_phase: 0.0)
|
|
56
|
+
@native = FFI::DrawStrokeParams.malloc
|
|
57
|
+
@native.to_ptr.free = Fiddle::RUBY_FREE
|
|
58
|
+
@native.to_ptr[0, FFI::DrawStrokeParams.size] = "\0" * FFI::DrawStrokeParams.size
|
|
59
|
+
@native.Cap = cap
|
|
60
|
+
@native.Join = join
|
|
61
|
+
@native.Thickness = thickness
|
|
62
|
+
@native.MiterLimit = miter_limit
|
|
63
|
+
@native.DashPhase = dash_phase
|
|
64
|
+
self.dashes = dashes
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def to_ptr
|
|
68
|
+
@native.to_ptr
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def dashes=(values)
|
|
72
|
+
unless values.is_a?(Array) && values.all? { |value| value.is_a?(Numeric) && value.positive? }
|
|
73
|
+
raise TypeError, 'dashes must be an array of positive numbers'
|
|
74
|
+
end
|
|
75
|
+
bytes = values.pack('d*')
|
|
76
|
+
pointer = if values.empty?
|
|
77
|
+
Fiddle::Pointer.new(0)
|
|
78
|
+
else
|
|
79
|
+
allocated = Fiddle::Pointer.malloc(bytes.bytesize, Fiddle::RUBY_FREE)
|
|
80
|
+
allocated[0, bytes.bytesize] = bytes
|
|
81
|
+
allocated
|
|
82
|
+
end
|
|
83
|
+
@dashes_pointer = pointer
|
|
84
|
+
@native.Dashes = pointer
|
|
85
|
+
@native.NumDashes = values.length
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class Matrix
|
|
90
|
+
def initialize
|
|
91
|
+
@native = FFI::DrawMatrix.malloc
|
|
92
|
+
@native.to_ptr.free = Fiddle::RUBY_FREE
|
|
93
|
+
LibUI.draw_matrix_set_identity(@native)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def to_ptr
|
|
97
|
+
@native.to_ptr
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def translate(x, y)
|
|
101
|
+
LibUI.draw_matrix_translate(@native, x, y)
|
|
102
|
+
self
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def scale(center_x, center_y, x, y)
|
|
106
|
+
LibUI.draw_matrix_scale(@native, center_x, center_y, x, y)
|
|
107
|
+
self
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def rotate(x, y, angle)
|
|
111
|
+
LibUI.draw_matrix_rotate(@native, x, y, angle)
|
|
112
|
+
self
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def skew(x, y, x_amount, y_amount)
|
|
116
|
+
LibUI.draw_matrix_skew(@native, x, y, x_amount, y_amount)
|
|
117
|
+
self
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def multiply(other)
|
|
121
|
+
raise TypeError, 'expected LibUI::Matrix' unless other.is_a?(Matrix)
|
|
122
|
+
|
|
123
|
+
LibUI.draw_matrix_multiply(@native, other.to_ptr)
|
|
124
|
+
self
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def invertible?
|
|
128
|
+
LibUI.draw_matrix_invertible(@native) != 0
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def invert
|
|
132
|
+
LibUI.draw_matrix_invert(@native) != 0
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def transform_point(x, y)
|
|
136
|
+
LibUI.draw_matrix_transform_point(@native, x, y)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def transform_size(x, y)
|
|
140
|
+
LibUI.draw_matrix_transform_size(@native, x, y)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
data/lib/libui/ffi.rb
CHANGED
|
@@ -45,6 +45,7 @@ module LibUI
|
|
|
45
45
|
# https://github.com/andlabs/libui/blob/master/ui.h
|
|
46
46
|
# keep same order
|
|
47
47
|
|
|
48
|
+
try_extern 'const char *uiVersion(void)'
|
|
48
49
|
try_extern 'const char *uiInit(uiInitOptions *options)'
|
|
49
50
|
try_extern 'void uiUninit(void)'
|
|
50
51
|
try_extern 'void uiFreeInitError(const char *err)'
|
|
@@ -76,6 +77,8 @@ module LibUI
|
|
|
76
77
|
]
|
|
77
78
|
|
|
78
79
|
try_extern 'void uiControlDestroy(uiControl *c)'
|
|
80
|
+
try_extern 'void uiControlOnDestroyed(uiControl *c, void (*f)(uiControl *c, void *data), void *data)'
|
|
81
|
+
try_extern 'void uiControlSetTooltip(uiControl *c, const char *tooltip)'
|
|
79
82
|
try_extern 'uintptr_t uiControlHandle(uiControl *c)'
|
|
80
83
|
try_extern 'uiControl *uiControlParent(uiControl *c)'
|
|
81
84
|
try_extern 'void uiControlSetParent(uiControl *c, uiControl *parent)'
|
|
@@ -86,6 +89,7 @@ module LibUI
|
|
|
86
89
|
try_extern 'int uiControlEnabled(uiControl *c)'
|
|
87
90
|
try_extern 'void uiControlEnable(uiControl *c)'
|
|
88
91
|
try_extern 'void uiControlDisable(uiControl *c)'
|
|
92
|
+
try_extern 'void uiControlSetMinimumSize(uiControl *c, int width, int height)'
|
|
89
93
|
|
|
90
94
|
try_extern 'uiControl *uiAllocControl(size_t n, uint32_t OSsig, uint32_t typesig, const char *typenamestr)'
|
|
91
95
|
try_extern 'void uiFreeControl(uiControl *c)'
|
|
@@ -117,6 +121,8 @@ module LibUI
|
|
|
117
121
|
try_extern 'void uiWindowSetMargined(uiWindow *w, int margined)'
|
|
118
122
|
try_extern 'int uiWindowResizeable(uiWindow *w)'
|
|
119
123
|
try_extern 'void uiWindowSetResizeable(uiWindow *w, int resizeable)'
|
|
124
|
+
try_extern 'void uiWindowSetToolbar(uiWindow *w, uiToolbar *t)'
|
|
125
|
+
try_extern 'uiToolbar *uiWindowToolbar(uiWindow *w)'
|
|
120
126
|
try_extern 'uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)'
|
|
121
127
|
|
|
122
128
|
# uiButton
|
|
@@ -160,6 +166,9 @@ module LibUI
|
|
|
160
166
|
|
|
161
167
|
try_extern 'char *uiLabelText(uiLabel *l)'
|
|
162
168
|
try_extern 'void uiLabelSetText(uiLabel *l, const char *text)'
|
|
169
|
+
try_extern 'double uiLabelFontSize(uiLabel *l)'
|
|
170
|
+
try_extern 'void uiLabelSetFontSize(uiLabel *l, double size)'
|
|
171
|
+
try_extern 'void uiLabelResetFontSize(uiLabel *l)'
|
|
163
172
|
try_extern 'uiLabel *uiNewLabel(const char *text)'
|
|
164
173
|
|
|
165
174
|
# uiTab
|
|
@@ -285,6 +294,9 @@ module LibUI
|
|
|
285
294
|
try_extern 'void uiMultilineEntrySetText(uiMultilineEntry *e, const char *text)'
|
|
286
295
|
try_extern 'void uiMultilineEntryAppend(uiMultilineEntry *e, const char *text)'
|
|
287
296
|
try_extern 'void uiMultilineEntryOnChanged(uiMultilineEntry *e, void (*f)(uiMultilineEntry *sender, void *senderData), void *data)'
|
|
297
|
+
try_extern 'double uiMultilineEntryFontSize(uiMultilineEntry *e)'
|
|
298
|
+
try_extern 'void uiMultilineEntrySetFontSize(uiMultilineEntry *e, double size)'
|
|
299
|
+
try_extern 'void uiMultilineEntryResetFontSize(uiMultilineEntry *e)'
|
|
288
300
|
try_extern 'int uiMultilineEntryReadOnly(uiMultilineEntry *e)'
|
|
289
301
|
try_extern 'void uiMultilineEntrySetReadOnly(uiMultilineEntry *e, int readonly)'
|
|
290
302
|
try_extern 'uiMultilineEntry *uiNewMultilineEntry(void)'
|
|
@@ -421,7 +433,7 @@ module LibUI
|
|
|
421
433
|
try_extern 'void uiDrawClip(uiDrawContext *c, uiDrawPath *path)'
|
|
422
434
|
try_extern 'void uiDrawSave(uiDrawContext *c)'
|
|
423
435
|
try_extern 'void uiDrawRestore(uiDrawContext *c)'
|
|
424
|
-
try_extern 'void uiDrawImage(uiDrawContext *c, uiImage *img, double x, double y, double width, double height)'
|
|
436
|
+
try_extern 'void uiDrawImage(uiDrawContext *c, const uiImage *img, double x, double y, double width, double height)'
|
|
425
437
|
|
|
426
438
|
# uiAttribute
|
|
427
439
|
try_extern 'void uiFreeAttribute(uiAttribute *a)'
|
|
@@ -575,6 +587,7 @@ module LibUI
|
|
|
575
587
|
|
|
576
588
|
try_extern 'void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)'
|
|
577
589
|
try_extern 'void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign)'
|
|
590
|
+
try_extern 'void uiGridDelete(uiGrid *g, uiControl *c)'
|
|
578
591
|
try_extern 'int uiGridPadded(uiGrid *g)'
|
|
579
592
|
try_extern 'void uiGridSetPadded(uiGrid *g, int padded)'
|
|
580
593
|
try_extern 'uiGrid *uiNewGrid(void)'
|
|
@@ -583,7 +596,29 @@ module LibUI
|
|
|
583
596
|
|
|
584
597
|
try_extern 'uiImage *uiNewImage(double width, double height)'
|
|
585
598
|
try_extern 'void uiFreeImage(uiImage *i)'
|
|
586
|
-
try_extern 'void uiImageAppend(uiImage *i, void *pixels, int pixelWidth, int pixelHeight, int byteStride)'
|
|
599
|
+
try_extern 'void uiImageAppend(uiImage *i, const void *pixels, int pixelWidth, int pixelHeight, int byteStride)'
|
|
600
|
+
|
|
601
|
+
# uiToolbar
|
|
602
|
+
typealias 'uiToolbarDisplayMode', 'int'
|
|
603
|
+
|
|
604
|
+
try_extern 'uiToolbar *uiNewToolbar(void)'
|
|
605
|
+
try_extern 'void uiFreeToolbar(uiToolbar *t)'
|
|
606
|
+
try_extern 'uiToolbarDisplayMode uiToolbarGetDisplayMode(uiToolbar *t)'
|
|
607
|
+
try_extern 'void uiToolbarSetDisplayMode(uiToolbar *t, uiToolbarDisplayMode mode)'
|
|
608
|
+
try_extern 'uiToolbarItem *uiToolbarAppendButton(uiToolbar *t, const char *text, uiImage *icon)'
|
|
609
|
+
try_extern 'uiToolbarItem *uiToolbarAppendToggleButton(uiToolbar *t, const char *text, uiImage *icon)'
|
|
610
|
+
try_extern 'void uiToolbarAppendSeparator(uiToolbar *t)'
|
|
611
|
+
try_extern 'char *uiToolbarItemText(uiToolbarItem *item)'
|
|
612
|
+
try_extern 'void uiToolbarItemSetText(uiToolbarItem *item, const char *text)'
|
|
613
|
+
try_extern 'void uiToolbarItemSetIcon(uiToolbarItem *item, uiImage *icon)'
|
|
614
|
+
try_extern 'char *uiToolbarItemTooltip(uiToolbarItem *item)'
|
|
615
|
+
try_extern 'void uiToolbarItemSetTooltip(uiToolbarItem *item, const char *tooltip)'
|
|
616
|
+
try_extern 'int uiToolbarItemEnabled(uiToolbarItem *item)'
|
|
617
|
+
try_extern 'void uiToolbarItemEnable(uiToolbarItem *item)'
|
|
618
|
+
try_extern 'void uiToolbarItemDisable(uiToolbarItem *item)'
|
|
619
|
+
try_extern 'void uiToolbarItemOnClicked(uiToolbarItem *item, void (*f)(uiToolbarItem *sender, void *senderData), void *data)'
|
|
620
|
+
try_extern 'int uiToolbarItemChecked(uiToolbarItem *item)'
|
|
621
|
+
try_extern 'void uiToolbarItemSetChecked(uiToolbarItem *item, int checked)'
|
|
587
622
|
|
|
588
623
|
# uiImageView
|
|
589
624
|
try_extern 'uiImageView *uiNewImageView(void)'
|
data/lib/libui/font.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module LibUI
|
|
2
|
+
Font = Struct.new(:family, :size, :weight, :italic, :stretch, keyword_init: true) do
|
|
3
|
+
def initialize(family:, size:, weight: 400, italic: 0, stretch: 4)
|
|
4
|
+
family = String(family)
|
|
5
|
+
raise ArgumentError, 'font family contains a NUL byte' if family.include?("\0")
|
|
6
|
+
|
|
7
|
+
super(family: family.dup.freeze, size: Float(size),
|
|
8
|
+
weight: Integer(weight), italic: Integer(italic),
|
|
9
|
+
stretch: Integer(stretch))
|
|
10
|
+
freeze
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/libui/libui_base.rb
CHANGED
|
@@ -5,47 +5,41 @@ module LibUI
|
|
|
5
5
|
func = FFI.func_map[original_method_name]
|
|
6
6
|
|
|
7
7
|
define_method(name) do |*args, &blk|
|
|
8
|
-
# Assume that block is the last argument.
|
|
9
8
|
args << blk if blk
|
|
10
|
-
|
|
11
|
-
# The proc object is converted to a Closure::BlockCaller object.
|
|
9
|
+
retained = []
|
|
12
10
|
args.map!.with_index do |arg, idx|
|
|
13
11
|
next arg unless arg.is_a?(Proc)
|
|
14
12
|
|
|
15
|
-
# now arg must be Proc
|
|
16
|
-
|
|
17
|
-
# The types of the function arguments are stored in advance.
|
|
18
|
-
# See the monkey patch in ffi.rb.
|
|
19
13
|
_f, ret_type, arg_types = func.callback_argument_types[idx]
|
|
20
|
-
#
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
receiver.nil? ||
|
|
31
|
-
(receiver.respond_to?(:frozen?) && receiver.frozen?) # UI.timer(100) {}
|
|
32
|
-
LibUIBase # keep a reference on an internal module to avoid GC
|
|
33
|
-
else
|
|
34
|
-
receiver # receiver object holds the callback
|
|
35
|
-
end
|
|
36
|
-
if owner.instance_variable_defined?(:@callbacks)
|
|
37
|
-
owner.instance_variable_get(:@callbacks) << callback
|
|
38
|
-
else
|
|
39
|
-
owner.instance_variable_set(:@callbacks, [callback])
|
|
14
|
+
raise ArgumentError, "#{name} does not accept a block at argument #{idx}" unless _f
|
|
15
|
+
|
|
16
|
+
ruby_callback = arg
|
|
17
|
+
callback = Fiddle::Closure::BlockCaller.new(ret_type, arg_types) do |*callback_args|
|
|
18
|
+
begin
|
|
19
|
+
ruby_callback.call(*callback_args)
|
|
20
|
+
rescue StandardError => e
|
|
21
|
+
CallbackRegistry.report(e)
|
|
22
|
+
0
|
|
23
|
+
end
|
|
40
24
|
end
|
|
25
|
+
retained << [idx, callback]
|
|
41
26
|
callback
|
|
42
27
|
end
|
|
43
28
|
|
|
44
|
-
# Make it possible to omit the last nil. This may be an over-optimization.
|
|
45
29
|
siz = func.argument_types.size - 1
|
|
46
30
|
args[siz] = nil if args.size == siz
|
|
47
31
|
|
|
48
|
-
FFI.public_send(original_method_name, *args)
|
|
32
|
+
result = FFI.public_send(original_method_name, *args)
|
|
33
|
+
retained.each do |idx, callback|
|
|
34
|
+
if idx.zero? || args.first.nil?
|
|
35
|
+
CallbackRegistry.global(original_method_name, callback)
|
|
36
|
+
elsif original_method_name.start_with?('uiMenuItem', 'uiToolbarItem')
|
|
37
|
+
CallbackRegistry.other(args.first, original_method_name, callback)
|
|
38
|
+
else
|
|
39
|
+
CallbackRegistry.control(args.first, original_method_name, callback)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
result
|
|
49
43
|
end
|
|
50
44
|
end
|
|
51
45
|
end
|
data/lib/libui/path.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module LibUI
|
|
2
|
+
class Path
|
|
3
|
+
def self.open(fill_mode = DrawFillModeWinding)
|
|
4
|
+
path = new(fill_mode)
|
|
5
|
+
begin
|
|
6
|
+
yield path
|
|
7
|
+
ensure
|
|
8
|
+
path.close
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(fill_mode = DrawFillModeWinding)
|
|
13
|
+
@pointer = LibUI.draw_new_path(fill_mode)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_ptr
|
|
17
|
+
raise RuntimeError, 'draw path is closed' unless @pointer
|
|
18
|
+
|
|
19
|
+
@pointer
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def new_figure(x, y)
|
|
23
|
+
LibUI.draw_path_new_figure(to_ptr, x, y)
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def new_figure_with_arc(x, y, radius, start_angle, sweep, negative = false)
|
|
28
|
+
LibUI.draw_path_new_figure_with_arc(to_ptr, x, y, radius, start_angle, sweep, negative ? 1 : 0)
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def line_to(x, y)
|
|
33
|
+
LibUI.draw_path_line_to(to_ptr, x, y)
|
|
34
|
+
self
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def arc_to(x, y, radius, start_angle, sweep, negative = false)
|
|
38
|
+
LibUI.draw_path_arc_to(to_ptr, x, y, radius, start_angle, sweep, negative ? 1 : 0)
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def bezier_to(c1x, c1y, c2x, c2y, end_x, end_y)
|
|
43
|
+
LibUI.draw_path_bezier_to(to_ptr, c1x, c1y, c2x, c2y, end_x, end_y)
|
|
44
|
+
self
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def close_figure
|
|
48
|
+
LibUI.draw_path_close_figure(to_ptr)
|
|
49
|
+
self
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def add_rectangle(x, y, width, height)
|
|
53
|
+
LibUI.draw_path_add_rectangle(to_ptr, x, y, width, height)
|
|
54
|
+
self
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def end_path
|
|
58
|
+
LibUI.draw_path_end(to_ptr)
|
|
59
|
+
self
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def close
|
|
63
|
+
return if @pointer.nil?
|
|
64
|
+
|
|
65
|
+
LibUI.draw_free_path(@pointer)
|
|
66
|
+
@pointer = nil
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
data/lib/libui/platform.rb
CHANGED
|
@@ -6,38 +6,38 @@ module LibUI
|
|
|
6
6
|
'arm64-darwin' => {
|
|
7
7
|
vendor: 'vendor/libui.arm64.dylib',
|
|
8
8
|
lib_names: ['libui.arm64.dylib', 'libui.dylib'],
|
|
9
|
-
release_zip: '
|
|
10
|
-
release_src: '
|
|
9
|
+
release_zip: 'libui-ng-macos-arm64-shared-release.zip',
|
|
10
|
+
release_src: 'lib/libui.dylib'
|
|
11
11
|
},
|
|
12
12
|
'x86_64-darwin' => {
|
|
13
13
|
vendor: 'vendor/libui.x86_64.dylib',
|
|
14
14
|
lib_names: ['libui.x86_64.dylib', 'libui.dylib'],
|
|
15
|
-
release_zip: '
|
|
16
|
-
release_src: '
|
|
15
|
+
release_zip: 'libui-ng-macos-x64-shared-release.zip',
|
|
16
|
+
release_src: 'lib/libui.dylib'
|
|
17
17
|
},
|
|
18
18
|
'x86_64-linux' => {
|
|
19
19
|
vendor: 'vendor/libui.x86_64.so',
|
|
20
20
|
lib_names: ['libui.x86_64.so', 'libui.so'],
|
|
21
|
-
release_zip: '
|
|
22
|
-
release_src: '
|
|
21
|
+
release_zip: 'libui-ng-ubuntu-x64-shared-release.zip',
|
|
22
|
+
release_src: 'lib/libui.so'
|
|
23
23
|
},
|
|
24
24
|
'aarch64-linux' => {
|
|
25
25
|
vendor: 'vendor/libui.aarch64.so',
|
|
26
26
|
lib_names: ['libui.aarch64.so', 'libui.so'],
|
|
27
|
-
release_zip: '
|
|
28
|
-
release_src: '
|
|
27
|
+
release_zip: 'libui-ng-ubuntu-arm64-shared-release.zip',
|
|
28
|
+
release_src: 'lib/libui.so'
|
|
29
29
|
},
|
|
30
30
|
'x64-mingw32' => {
|
|
31
31
|
vendor: 'vendor/libui.x64.dll',
|
|
32
32
|
lib_names: ['libui.x64.dll', 'libui.dll'],
|
|
33
|
-
release_zip: '
|
|
34
|
-
release_src: '
|
|
33
|
+
release_zip: 'libui-ng-windows-x64-msvc-shared-md-release.zip',
|
|
34
|
+
release_src: 'bin/libui.dll'
|
|
35
35
|
},
|
|
36
36
|
'x86-mingw32' => {
|
|
37
37
|
vendor: 'vendor/libui.x86.dll',
|
|
38
38
|
lib_names: ['libui.x86.dll', 'libui.dll'],
|
|
39
|
-
release_zip: '
|
|
40
|
-
release_src: '
|
|
39
|
+
release_zip: 'libui-ng-windows-x86-msvc-shared-md-release.zip',
|
|
40
|
+
release_src: 'bin/libui.dll'
|
|
41
41
|
}
|
|
42
42
|
}.freeze
|
|
43
43
|
|