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.
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, value)
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
- super(otf, a, b, c, d, value)
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
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.pre2
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: 3.6.9
69
+ rubygems_version: 4.0.20
64
70
  specification_version: 4
65
71
  summary: Ruby bindings to libui
66
72
  test_files: []