libui_paradise 0.2.49 → 0.4.13

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +405 -259
  3. data/bin/libui_message +7 -0
  4. data/doc/README.gen +356 -131
  5. data/doc/todo/todo.md +14 -5
  6. data/lib/libui_paradise/autoinclude.rb +2 -1
  7. data/lib/libui_paradise/base/base.rb +51 -62
  8. data/lib/libui_paradise/base_module/base_module.rb +1514 -0
  9. data/lib/libui_paradise/colours/colours.rb +14 -2
  10. data/lib/libui_paradise/domain_specific_language/README.md +6 -0
  11. data/lib/libui_paradise/examples/complex/002_tabs_example.rb +1 -2
  12. data/lib/libui_paradise/examples/complex/003_open_file_button_example.rb +3 -5
  13. data/lib/libui_paradise/examples/complex/006_coloured_boxes_example.rb +2 -2
  14. data/lib/libui_paradise/examples/complex/007_slider_example.rb +10 -4
  15. data/lib/libui_paradise/examples/complex/008_radio_button_example.rb +2 -2
  16. data/lib/libui_paradise/examples/complex/009_separator_example.rb +2 -2
  17. data/lib/libui_paradise/examples/complex/010_table_example.rb +139 -49
  18. data/lib/libui_paradise/examples/complex/011_two_buttons_showing_how_to_enable_and_disable_them.rb +2 -1
  19. data/lib/libui_paradise/examples/complex/012_password_entry_example.rb +1 -1
  20. data/lib/libui_paradise/examples/complex/013_form_example.rb +1 -1
  21. data/lib/libui_paradise/examples/complex/014_text_example.rb +1 -1
  22. data/lib/libui_paradise/examples/complex/015_text_view_example.rb +4 -4
  23. data/lib/libui_paradise/examples/complex/016_grid_example.rb +20 -11
  24. data/lib/libui_paradise/examples/complex/017_unicode_text_example.rb +2 -2
  25. data/lib/libui_paradise/examples/complex/018_spinbutton_example.rb +1 -1
  26. data/lib/libui_paradise/examples/complex/019_combo_box_example.rb +1 -1
  27. data/lib/libui_paradise/examples/complex/020_checkbox_example.rb +5 -5
  28. data/lib/libui_paradise/examples/complex/021_font_example.rb +4 -3
  29. data/lib/libui_paradise/examples/complex/022_simple_notepad_example.rb +3 -3
  30. data/lib/libui_paradise/examples/complex/023_msg_box_error.rb +5 -5
  31. data/lib/libui_paradise/examples/complex/024_parse_config_file_example.rb +2 -2
  32. data/lib/libui_paradise/examples/complex/025_colour_button.rb +1 -1
  33. data/lib/libui_paradise/examples/complex/026_basic_table_image.rb +5 -8
  34. data/lib/libui_paradise/examples/complex/027_basic_button_example.rb +3 -3
  35. data/lib/libui_paradise/examples/complex/028_try_for_automatic_button_press_event_after_a_delay.rb +4 -5
  36. data/lib/libui_paradise/examples/complex/029_progressbar_example.rb +4 -5
  37. data/lib/libui_paradise/examples/complex/030_entry_responds_to_comment_as_synonymous_to_the_enter_key_pressed_example.rb +5 -6
  38. data/lib/libui_paradise/examples/complex/031_notification_functionality_example.rb +3 -2
  39. data/lib/libui_paradise/examples/complex/032_simple_window_example.rb +2 -1
  40. data/lib/libui_paradise/examples/complex/033_daemonize_and_exit_after_delay_example.rb +3 -2
  41. data/lib/libui_paradise/examples/complex/034_bold_text_example.rb +115 -0
  42. data/lib/libui_paradise/examples/complex/035_parse_into_table_example.rb +109 -0
  43. data/lib/libui_paradise/examples/simple/001_open_file_example.rb +1 -1
  44. data/lib/libui_paradise/examples/simple/002_histogram_example.rb +6 -6
  45. data/lib/libui_paradise/examples/simple/003_fancy_text_example.rb +80 -43
  46. data/lib/libui_paradise/examples/simple/005_text_drawing_example.rb +11 -11
  47. data/lib/libui_paradise/examples/simple/007_control_gallery.rb +21 -14
  48. data/lib/libui_paradise/examples/simple/009_spectrum.rb +7 -1
  49. data/lib/libui_paradise/examples/simple/010_font_button.rb +31 -0
  50. data/lib/libui_paradise/examples/simple/011_simple_notepad.rb +24 -0
  51. data/lib/libui_paradise/examples/simple/012_table_example.rb +71 -0
  52. data/lib/libui_paradise/examples/simple/013_scrolling_pane_example.rb +28 -0
  53. data/lib/libui_paradise/examples/simple/014_simple_entry_example.rb +30 -0
  54. data/lib/libui_paradise/examples/simple/015_slider_example.rb +32 -0
  55. data/lib/libui_paradise/fiddle/{pointer.rb → fiddle.rb} +768 -615
  56. data/lib/libui_paradise/generic_window/generic_window.rb +1 -1
  57. data/lib/libui_paradise/images/README.md +5 -2
  58. data/lib/libui_paradise/libui_classes/button.rb +31 -0
  59. data/lib/libui_paradise/libui_classes/entry.rb +35 -0
  60. data/lib/libui_paradise/libui_classes/grid.rb +14 -23
  61. data/lib/libui_paradise/libui_classes/hbox.rb +39 -0
  62. data/lib/libui_paradise/libui_classes/libui_classes.rb +9 -1595
  63. data/lib/libui_paradise/libui_classes/msg_box.rb +121 -0
  64. data/lib/libui_paradise/libui_classes/msg_box_error.rb +41 -0
  65. data/lib/libui_paradise/libui_classes/slider.rb +28 -0
  66. data/lib/libui_paradise/libui_classes/spinbox.rb +48 -0
  67. data/lib/libui_paradise/libui_classes/vbox.rb +38 -0
  68. data/lib/libui_paradise/project/project.rb +6 -1
  69. data/lib/libui_paradise/prototype/prototype.rb +8 -10
  70. data/lib/libui_paradise/requires/require_the_libui_classes.rb +2 -2
  71. data/lib/libui_paradise/requires/require_the_libui_paradise_project.rb +5 -3
  72. data/lib/libui_paradise/toplevel_methods/add_to_the_registered_widgets.rb +70 -0
  73. data/lib/libui_paradise/toplevel_methods/hash_fiddle_pointer_widgets.rb +37 -0
  74. data/lib/libui_paradise/toplevel_methods/toplevel_counters.rb +83 -0
  75. data/lib/libui_paradise/toplevel_methods/toplevel_methods.rb +792 -0
  76. data/lib/libui_paradise/version/version.rb +2 -2
  77. data/lib/libui_paradise.rb +0 -0
  78. data/libui_paradise.gemspec +5 -4
  79. data/test/testing_generic_window.rb +2 -0
  80. metadata +35 -30
  81. data/doc/SNIPPETS.md +0 -94
  82. data/lib/libui_paradise/extensions/counters.rb +0 -58
  83. data/lib/libui_paradise/extensions/extensions.rb +0 -29
  84. data/lib/libui_paradise/extensions/hash_fiddle_pointer_widgets.rb +0 -150
  85. data/lib/libui_paradise/extensions/misc.rb +0 -754
  86. data/lib/libui_paradise/libui_classes/box.rb +0 -156
  87. data/lib/libui_paradise/toplevel_methods/misc.rb +0 -13
@@ -0,0 +1,792 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # require 'libui_paradise/toplevel_methods/toplevel_methods.rb'
6
+ # =========================================================================== #
7
+ module LibuiParadise
8
+
9
+ # ========================================================================= #
10
+ # === @main_window
11
+ #
12
+ # This variable can be used to keep track of the main window in use.
13
+ # ========================================================================= #
14
+ @main_window = nil
15
+
16
+ # ========================================================================= #
17
+ # === LibuiParadise.main_window?
18
+ # ========================================================================= #
19
+ def self.main_window?
20
+ @main_window
21
+ end
22
+
23
+ # ========================================================================= #
24
+ # === LibuiParadise.set_main_window
25
+ # ========================================================================= #
26
+ def self.set_main_window(i)
27
+ @main_window = i
28
+ end; self.instance_eval { alias set_window set_main_window } # === LibuiParadise.set_window
29
+
30
+ # ========================================================================= #
31
+ # === LibuiParadise.window (window tag)
32
+ #
33
+ # This method will create a new main-window.
34
+ #
35
+ # It will also call UI.simple_exit(). This is done mostly so that we
36
+ # can omit that line whenever we use e. g. ui_main_window().
37
+ # ========================================================================= #
38
+ def self.window(
39
+ the_title = '', # Pick a title for the window here.
40
+ width = WIDTH, # width in n pixels.
41
+ height = HEIGHT, # height in n pixels.
42
+ has_menubar = 1, # hasMenubar or has not.
43
+ &block
44
+ )
45
+ case width
46
+ # ======================================================================= #
47
+ # === :default
48
+ # ======================================================================= #
49
+ when :default
50
+ width = WIDTH
51
+ end
52
+ case the_title
53
+ # ======================================================================= #
54
+ # === :filename
55
+ # ======================================================================= #
56
+ when :filename,
57
+ :file_name
58
+ # ===================================================================== #
59
+ # __FILE__ contains the desired name. We only need the raw name, though.
60
+ # Well, in 2022 it was realized that the real filename is stored in
61
+ # $PROGRAM_NAME, so here we go.
62
+ # ===================================================================== #
63
+ the_title = File.basename($PROGRAM_NAME)
64
+ end
65
+ raw_has_menubar = 0
66
+ if has_menubar.is_a? Numeric
67
+ raw_has_menubar = has_menubar
68
+ end
69
+ # ======================================================================= #
70
+ # Instantiate a new main-window next:
71
+ # ======================================================================= #
72
+ main_window = ::LibUI.new_window(
73
+ the_title,
74
+ width,
75
+ height,
76
+ raw_has_menubar
77
+ )
78
+ set_main_window(main_window) # Keep a reference stored here.
79
+ # ======================================================================= #
80
+ # Since as of 30.08.2021 we will also register the main-window.
81
+ #
82
+ # In the long run we may obsolete and deprecate @main_window, since
83
+ # it is no longer needed - but for now we will retain that variable.
84
+ # ======================================================================= #
85
+ add_to_the_registered_widgets(main_window, __method__)
86
+ if has_menubar and has_menubar.is_a?(Hash)
87
+ if has_menubar.has_key? :margin
88
+ if has_menubar[:margin] == true
89
+ main_window.has_margin
90
+ end
91
+ end
92
+ end
93
+ ::LibUI.simple_exit(main_window)
94
+ if block_given?
95
+ yield
96
+ end
97
+ return main_window # Always return it here.
98
+ end; self.instance_eval { alias main_window window } # === LibuiParadise.main_window
99
+ self.instance_eval { alias ui_main_window window } # === LibuiParadise.ui_main_window
100
+ self.instance_eval { alias margined_window window } # === LibuiParadise.margined_window
101
+ self.instance_eval { alias ui_window window } # === LibuiParadise.ui_window
102
+ self.instance_eval { alias window_or_vbox window } # === LibuiParadise.window_or_vbox
103
+ self.instance_eval { alias ui_padded_main_window window } # === LibuiParadise.margined_window
104
+ self.instance_eval { alias padded_window window } # === LibuiParadise.padded_window
105
+ self.instance_eval { alias padded_main_window window } # === LibuiParadise.padded_main_window
106
+
107
+ # ========================================================================= #
108
+ # === LibuiParadise.string_length
109
+ #
110
+ # This method is specifically for attributed-Strings.
111
+ # ========================================================================= #
112
+ def self.string_length(i = self)
113
+ return ::LibUI.attributed_string_len(i)
114
+ end
115
+
116
+ # ========================================================================= #
117
+ # === LibuiParadise.init
118
+ # ========================================================================= #
119
+ def self.init
120
+ ::LibUI.init
121
+ end
122
+
123
+ # ========================================================================= #
124
+ # === LibuiParadise.string
125
+ #
126
+ # This is a wrapper over LibUI.new_attributed_string().
127
+ # ========================================================================= #
128
+ def self.string(i = '')
129
+ return ::LibUI.new_attributed_string(i)
130
+ end; self.instance_eval { alias fancy_text string } # === LibuiParadise.fancy_text
131
+
132
+ # ========================================================================= #
133
+ # === LibuiParadise.label (text tag, label tag)
134
+ #
135
+ # Add text to the widget at hand. This is actually called a "label".
136
+ # ========================================================================= #
137
+ def self.label(
138
+ i = ''
139
+ )
140
+ if i.include? '</'
141
+ # ===================================================================== #
142
+ # For now we must remove "HTML tags" from the given input. Perhaps
143
+ # at some later point in time we can retain them.
144
+ # ===================================================================== #
145
+ i = i.dup if i.frozen?
146
+ i.gsub!(%r{<[^>]+>}, '')
147
+ end
148
+ _ = ::LibUI.new_label(i.to_s)
149
+ add_to_the_registered_widgets(_, __method__)
150
+ return _
151
+ end; self.instance_eval { alias text label } # === LibuiParadise.text
152
+ self.instance_eval { alias ui_text label } # === LibuiParadise.ui_text
153
+ self.instance_eval { alias ui_label label } # === LibuiParadise.ui_label
154
+
155
+ # ========================================================================= #
156
+ # === LibuiParadise.radio_buttons
157
+ #
158
+ # This method will create some radio buttons.
159
+ #
160
+ # You can pass an Array into this method, which should be an Array of
161
+ # Strings. This is optional. If such an Array is given, though, then
162
+ # these entries will become radio-buttons, with the associated label
163
+ # (the text they display) becoming the label right next to the radio
164
+ # button element (that round circle that the user can select via
165
+ # the mouse cursor).
166
+ # ========================================================================= #
167
+ def self.radio_buttons(
168
+ optional_array = []
169
+ )
170
+ _ = ::LibUI.new_radio_buttons
171
+ if optional_array and optional_array.is_a?(Array) and !optional_array.empty?
172
+ optional_array.each {|this_element|
173
+ ::LibUI.radio_buttons_append(_, this_element)
174
+ }
175
+ end
176
+ add_to_the_registered_widgets(_, __method__)
177
+ return _
178
+ end; self.instance_eval { alias ui_radio_buttons radio_buttons } # === LibuiParadise.ui_radio_buttons
179
+
180
+ # ========================================================================= #
181
+ # === LibuiParadise.text_layout
182
+ # ========================================================================= #
183
+ def self.text_layout(
184
+ i = ''
185
+ )
186
+ _ = ::LibUI.draw_new_text_layout(i.to_s)
187
+ add_to_the_registered_widgets(_, __method__)
188
+ return _
189
+ end
190
+
191
+ # ========================================================================= #
192
+ # === LibuiParadise.menu (menu tag)
193
+ # ========================================================================= #
194
+ def self.menu(
195
+ title = ''
196
+ )
197
+ _ = ::LibUI.new_menu(title)
198
+ add_to_the_registered_widgets(_, __method__)
199
+ return _
200
+ end; self.instance_eval { alias ui_menu menu } # === ui_menu
201
+
202
+ # ========================================================================= #
203
+ # === LibuiParadise.table
204
+ #
205
+ # The argument to this method should be of type table_params.
206
+ #
207
+ # Example for this:
208
+ #
209
+ # table_params = LibUI::FFI::TableParams.malloc
210
+ # table_params.Model = model
211
+ # table_params.RowBackgroundColorModelColumn = -1
212
+ #
213
+ # ========================================================================= #
214
+ def self.table(i)
215
+ _ = ::LibUI.new_table(i)
216
+ register_this_fiddle_pointer_widget(_, __method__)
217
+ return _
218
+ end; self.instance_eval { alias ui_table table } # === LibuiParadise.ui_table
219
+
220
+ # ========================================================================= #
221
+ # === LibuiParadise.vertical_separator
222
+ #
223
+ # This method will add a new vertical separator.
224
+ # ========================================================================= #
225
+ def self.vertical_separator
226
+ ::LibUI.new_vertical_separator
227
+ end; self.instance_eval { alias ui_vseparator vertical_separator } # === LibuiParadise.ui_verticalseparator
228
+ self.instance_eval { alias ui_vsep vertical_separator } # === LibuiParadise.ui_vsep
229
+ self.instance_eval { alias vspacer vertical_separator } # === LibuiParadise.vspacer
230
+ self.instance_eval { alias vertical_spacer vertical_separator } # === LibuiParadise.vertical_spacer
231
+ self.instance_eval { alias vsep vertical_separator } # === LibuiParadise.vsep
232
+
233
+ # ========================================================================= #
234
+ # === Libuiparadise.image
235
+ #
236
+ # This is currently limited to .png files only, due to ChunkyPng.
237
+ #
238
+ # At some later point in the future this limitation may be lifted. For
239
+ # now it has to remain in place.
240
+ # ========================================================================= #
241
+ def self.image(
242
+ this_file,
243
+ width = :try_to_infer_automatically,
244
+ height = :infer_automatically
245
+ )
246
+ if (width == :infer_automatically) or
247
+ (height == :infer_automatically)
248
+ unless Object.const_defined? :ChunkyPNG
249
+ begin
250
+ require 'chunky_png'
251
+ rescue LoadError; end
252
+ end
253
+ canvas = ChunkyPNG::Canvas.from_file(this_file)
254
+ data = canvas.to_rgba_stream
255
+ width = canvas.width
256
+ height = canvas.height
257
+ _ = ::LibUI.new_image(width, height) # Create the image here.
258
+ add_to_the_registered_widgets(_, __method__)
259
+ ::LibUI.image_append(
260
+ _,
261
+ data,
262
+ width,
263
+ height,
264
+ width
265
+ )
266
+ return _
267
+ end
268
+ nil
269
+ end; self.instance_eval { alias ui_image image } # === LibuiParadise.ui_image
270
+
271
+ # ========================================================================= #
272
+ # === LibuiParadise.font_button
273
+ #
274
+ # Create a new font button via this method.
275
+ # ========================================================================= #
276
+ def self.font_button
277
+ _ = ::LibUI.new_font_button
278
+ add_to_the_registered_widgets(_, __method__)
279
+ return _
280
+ end; self.instance_eval { alias ui_font_button font_button } # === LibuiParadise.ui_font_button
281
+
282
+ # ========================================================================= #
283
+ # === LibuiParadise.multiline_entry (multiline_entry tag)
284
+ #
285
+ # The upstream code for the linux-variant for a multiline-entry can
286
+ # be found here:
287
+ #
288
+ # https://raw.githubusercontent.com/andlabs/libui/master/unix/multilineentry.c
289
+ #
290
+ # A multiline-entry, also known more traditionally as a "textview",
291
+ # is a widget that allows the user to input text and modify that
292
+ # text as well.
293
+ # ========================================================================= #
294
+ def self.multiline_entry(
295
+ optional_content = nil
296
+ )
297
+ _ = ::LibUI.new_multiline_entry
298
+ add_to_the_registered_widgets(_, __method__)
299
+ if optional_content and optional_content.is_a?(String) and !optional_content.empty?
300
+ _.set_text(optional_content) # Set the text here, if the user provided a non-empty String.
301
+ end
302
+ return _
303
+ end; self.instance_eval { alias ui_multiline_entry multiline_entry } # === LibuiParadise.ui_multiline_entry
304
+ self.instance_eval { alias textview multiline_entry } # === LibuiParadise.textview
305
+ self.instance_eval { alias text_view multiline_entry } # === LibuiParadise.text_view
306
+ self.instance_eval { alias ui_text_view multiline_entry } # === LibuiParadise.ui_text_view
307
+ self.instance_eval { alias ui_textview multiline_entry } # === LibuiParadise.ui_textview
308
+ self.instance_eval { alias ui_text_buffer multiline_entry } # === LibuiParadise.ui_text_buffer
309
+ self.instance_eval { alias input_field multiline_entry } # === LibuiParadise.input_field
310
+ self.instance_eval { alias input multiline_entry } # === LibuiParadise.input
311
+ self.instance_eval { alias create_text_view multiline_entry } # === LibuiParadise.create_text_view
312
+
313
+ # ========================================================================= #
314
+ # === LibuiParadise.checkbox (checkbox tag)
315
+ # ========================================================================= #
316
+ def self.checkbox(i = '')
317
+ _ = ::LibUI.new_checkbox(i)
318
+ add_to_the_registered_widgets(_, __method__)
319
+ return _
320
+ end; self.instance_eval { alias create_checkbox checkbox } # === LibuiParadise.create_checkbox
321
+
322
+ # ========================================================================= #
323
+ # === LibuiParadise.password_entry
324
+ #
325
+ # This method will create and returns a new password entry widget. This
326
+ # means that input will be "disguised" via the '*' character.
327
+ #
328
+ # Usage example:
329
+ #
330
+ # entry = LibuiParadise.password_entry
331
+ #
332
+ # ========================================================================= #
333
+ def self.password_entry
334
+ entry = ::LibUI.new_password_entry
335
+ add_to_the_registered_widgets(entry, __method__)
336
+ return entry
337
+ end; self.instance_eval { alias ui_password_entry password_entry } # === LibuiParadise.ui_password_entry
338
+
339
+ # ========================================================================= #
340
+ # === LibuiParadise.wrapper_new_progress_bar
341
+ #
342
+ # The name of this method contains "wrapper_" because there already
343
+ # exists a method called LibUI.new_progress_bar().
344
+ #
345
+ # The upstream C API for the libui-progressbar can be found here:
346
+ #
347
+ # https://github.com/andlabs/libui/blob/master/unix/progressbar.c
348
+ #
349
+ # ========================================================================= #
350
+ def self.wrapper_new_progress_bar
351
+ _ = ::LibUI.new_progress_bar
352
+ add_to_the_registered_widgets(_, :new_progress_bar)
353
+ return _
354
+ end; self.instance_eval { alias new_progress_bar wrapper_new_progress_bar } # === LibuiParadise.new_progress_bar
355
+
356
+ # ========================================================================= #
357
+ # === LibuiParadise.tab
358
+ #
359
+ # This could be also called "notebook_tab" - see the alias on the
360
+ # bottom.
361
+ # ========================================================================= #
362
+ def self.tab
363
+ _ = ::LibUI.new_tab # Create a new notebook-tab here.
364
+ add_to_the_registered_widgets(_, __method__)
365
+ return _
366
+ end; self.instance_eval { alias ui_tab tab } # === LibuiParadise.ui_tab
367
+ self.instance_eval { alias ui_tabs tab } # === LibuiParadise.ui_tabs
368
+ self.instance_eval { alias notebook tab } # === LibuiParadise.notebook
369
+ self.instance_eval { alias ui_notebook tab } # === LibuiParadise.ui_notebook
370
+ self.instance_eval { alias notebook_tab tab } # === LibuiParadise.notebook_tab
371
+ self.instance_eval { alias create_tab tab } # === LibuiParadise.create_tab
372
+
373
+ # ========================================================================= #
374
+ # === LibuiParadise.area
375
+ #
376
+ # AreaHandler defines the functionality needed for handling events from
377
+ # an Area.
378
+ #
379
+ # Upstream documentation, at the least for Go, can be found here:
380
+ #
381
+ # https://github.com/andlabs/ui/blob/master/areahandler.go
382
+ #
383
+ # ========================================================================= #
384
+ def self.area(
385
+ i = :use_new_area_handler
386
+ )
387
+ case i
388
+ # ======================================================================= #
389
+ # === :use_new_area_handler
390
+ # ======================================================================= #
391
+ when :use_new_area_handler,
392
+ :default
393
+ # ===================================================================== #
394
+ # malloc a new area-handled next:
395
+ # ===================================================================== #
396
+ i = ::LibUI::FFI::AreaHandler.malloc
397
+ i.to_ptr.free = Fiddle::RUBY_FREE # This one is done in upstream LibUI as well.
398
+ end
399
+ _ = ::LibUI.new_area(i) # Our new area, with the given handler.
400
+ add_to_the_registered_widgets(_, __method__)
401
+ return _
402
+ end; self.instance_eval { alias area_handler area } # === LibuiParadise.area_handler
403
+
404
+ # ========================================================================= #
405
+ # === LibuiParadise.font (font tag, fonts tag)
406
+ # ========================================================================= #
407
+ def self.font(&block)
408
+ use_this_font = ::LibUI::FFI::FontDescriptor.malloc
409
+ # ======================================================================= #
410
+ # === Handle blocks next
411
+ # ======================================================================= #
412
+ if block_given?
413
+ yielded = yield
414
+ if yielded.is_a? Hash
415
+ # =================================================================== #
416
+ # === :font_size
417
+ # =================================================================== #
418
+ if yielded.has_key? :font_size
419
+ use_this_font.Size = yielded.delete(:font_size)
420
+ end
421
+ # =================================================================== #
422
+ # === :font_family
423
+ # =================================================================== #
424
+ if yielded.has_key? :font_family
425
+ use_this_font.Family = yielded.delete(:font_family)
426
+ end
427
+ # =================================================================== #
428
+ # === :stretch
429
+ # =================================================================== #
430
+ if yielded.has_key? :stretch
431
+ use_this_font.Stretch = yielded.delete(:stretch)
432
+ end
433
+ # =================================================================== #
434
+ # === :weight
435
+ # =================================================================== #
436
+ if yielded.has_key? :weight
437
+ use_this_font.Weight = yielded.delete(:weight)
438
+ end
439
+ # =================================================================== #
440
+ # === :italic
441
+ # =================================================================== #
442
+ if yielded.has_key? :italic
443
+ _ = yielded.delete(:italic_family)
444
+ if _ == true
445
+ _ = 1
446
+ elsif _ == false
447
+ _ = 0
448
+ end
449
+ use_this_font.Italic = _
450
+ end
451
+ end
452
+ end
453
+ return use_this_font
454
+ end; self.instance_eval { alias ui_font font } # === LibuiParadise::Extensions.ui_font
455
+ self.instance_eval { alias font_descriptor font } # === LibuiParadise::Extensions.font_descriptor
456
+
457
+ # ========================================================================= #
458
+ # === LibuiParadise.hello_world
459
+ #
460
+ # This is merely an ad-hoc test.
461
+ # ========================================================================= #
462
+ def self.hello_world
463
+ e 'Hello world!'
464
+ end
465
+
466
+ # ========================================================================= #
467
+ # === LibuiParadise.register_sigint
468
+ # ========================================================================= #
469
+ def self.register_sigint
470
+ Signal.trap('SIGINT') { exit }
471
+ end
472
+
473
+ # ========================================================================= #
474
+ # === LibuiParadise.run_in_the_background
475
+ # ========================================================================= #
476
+ def self.run_in_the_background
477
+ Process.daemon
478
+ end
479
+
480
+ # ========================================================================= #
481
+ # === LibuiParadise.open_file
482
+ #
483
+ # This method can be used to open a local file, via a button, the
484
+ # "open-file" button. Furthermore a begin/rescue clause is used to
485
+ # avoid "NULL pointer given" errors. At a later time we may
486
+ # have to fine-tune this, but for now this shall suffice.
487
+ # ========================================================================= #
488
+ def self.open_file(
489
+ main_window = main_window?
490
+ )
491
+ begin
492
+ _ = ::LibUI.open_file(main_window)
493
+ add_to_the_registered_widgets(_, __method__)
494
+ return _
495
+ rescue ArgumentError => _error # Rescue #<ArgumentError: NULL pointer given> here.
496
+ # pp _error
497
+ return nil
498
+ end
499
+ end; self.instance_eval { alias ui_open_file open_file } # === LibuiParadise.ui_open_file
500
+
501
+ # ========================================================================= #
502
+ # === LibuiParadise.search_entry
503
+ # ========================================================================= #
504
+ def self.search_entry
505
+ _ = ::LibUI.new_search_entry
506
+ add_to_the_registered_widgets(_, __method__)
507
+ return _
508
+ end; self.instance_eval { alias ui_search_entry search_entry } # === LibuiParadise.ui_search_entry
509
+
510
+ # ========================================================================= #
511
+ # === LibuiParadise.non_wrapping_multiline_entry
512
+ #
513
+ # The upstream C API for the non-wrapping multiline edit can be found here:
514
+ #
515
+ # https://raw.githubusercontent.com/andlabs/libui/master/unix/multilineentry.c
516
+ #
517
+ # ========================================================================= #
518
+ def self.non_wrapping_multiline_entry
519
+ _ = ::LibUI.new_non_wrapping_multiline_entry
520
+ add_to_the_registered_widgets(_, __method__)
521
+ return _
522
+ end
523
+
524
+ # ========================================================================= #
525
+ # === LibuiParadise.draw_rectangle
526
+ #
527
+ # This method can be used to draw a rectangle.
528
+ #
529
+ # The third argument to this method should be a HTML colour, as a Symbol.
530
+ # ========================================================================= #
531
+ def self.draw_rectangle(
532
+ width = :default,
533
+ height = :default,
534
+ colour = :orange
535
+ )
536
+ unless ::LibuiParadise.respond_to?(:padded_vbox)
537
+ require 'libui_paradise/libui_classes/vbox.rb'
538
+ end
539
+ unless Object.const_defined? :Colours
540
+ begin
541
+ require 'colours'
542
+ rescue LoadError; end
543
+ end
544
+ case width
545
+ # ======================================================================= #
546
+ # === :default
547
+ # ======================================================================= #
548
+ when :default
549
+ width = 25
550
+ end
551
+ case height
552
+ # ======================================================================= #
553
+ # === :default
554
+ # ======================================================================= #
555
+ when :default
556
+ height = 25
557
+ end
558
+ handler = LibUI::FFI::AreaHandler.malloc
559
+ handler.to_ptr.free = Fiddle::RUBY_FREE
560
+ area = LibUI.new_area(handler)
561
+ brush = LibUI::FFI::DrawBrush.malloc
562
+ brush.to_ptr.free = Fiddle::RUBY_FREE
563
+
564
+ handler_draw_event = Fiddle::Closure::BlockCaller.new(0, [1, 1, 1]) { |_, _, area_draw_params|
565
+ path = LibUI.draw_new_path(0)
566
+ LibUI.draw_path_add_rectangle(path, 0, 0, width, height)
567
+ LibUI.draw_path_end(path)
568
+ brush.Type = 0
569
+ # ===================================================================== #
570
+ # Need to find out the true RGB values. For now we divide by 255.
571
+ #
572
+ # See here:
573
+ #
574
+ # https://stackoverflow.com/questions/10848990/rgb-values-to-0-to-1-scale
575
+ #
576
+ # ===================================================================== #
577
+ array = Colours.colour_to_rgb(colour)
578
+ brush.R = array[0] / 255.0 # 0.4
579
+ brush.G = array[1] / 255.0 # 0.4
580
+ brush.B = array[2] / 255.0 # 0.8
581
+ brush.A = 1.0 # Hardcoded for now.
582
+ area_draw_params = LibUI::FFI::AreaDrawParams.new(area_draw_params)
583
+ LibUI.draw_fill(area_draw_params.Context, path, brush.to_ptr)
584
+ LibUI.draw_free_path(path)
585
+ }
586
+
587
+ do_nothing = Fiddle::Closure::BlockCaller.new(0, [0]) {}
588
+ key_event = Fiddle::Closure::BlockCaller.new(1, [0]) { 0 }
589
+
590
+ handler.Draw = handler_draw_event
591
+ handler.MouseEvent = do_nothing
592
+ handler.MouseCrossed = do_nothing
593
+ handler.DragBroken = do_nothing
594
+ handler.KeyEvent = key_event
595
+
596
+ vbox = ::LibuiParadise.padded_vbox # Create our vbox here.
597
+ vbox.maximal(area)
598
+ return vbox
599
+ end
600
+
601
+ # ========================================================================= #
602
+ # === LibuiParadise.scrolling_area
603
+ #
604
+ # It seems as if scrolling is not yet easily available in libui.
605
+ #
606
+ # The upstream API is like this:
607
+ #
608
+ # uiArea *area = uiNewScrollingArea(&handler, 400, 400);
609
+ #
610
+ # The two numbers are width and height, as integers, respectively.
611
+ # In total three arguments are required. The first argument is
612
+ # a so-called "AreaHandler".
613
+ #
614
+ # The code may be found here:
615
+ #
616
+ # https://github.com/andlabs/libui/blob/master/windows/areascroll.cpp
617
+ #
618
+ # ========================================================================= #
619
+ def self.scrolling_area(
620
+ widget,
621
+ width = :default,
622
+ height = :default
623
+ )
624
+ case width
625
+ # ======================================================================= #
626
+ # === :default
627
+ # ======================================================================= #
628
+ when :default, nil
629
+ width = 400
630
+ end
631
+ case height
632
+ # ======================================================================= #
633
+ # === :default
634
+ # ======================================================================= #
635
+ when :default, nil
636
+ height = 400
637
+ end
638
+ _ = ::LibUI.new_scrolling_area(widget, width, height)
639
+ # ======================================================================= #
640
+ # The next part does not yet work - is it even possible to add widgets
641
+ # to a scrolling area in libui?
642
+ # if optional_widget
643
+ # _.add(optional_widget)
644
+ # end
645
+ # ======================================================================= #
646
+ add_to_the_registered_widgets(_, __method__)
647
+ return _
648
+ end; self.instance_eval { alias ui_scrolling_area scrolling_area } # === LibuiParadise::Extensions.ui_scrolling_area
649
+ self.instance_eval { alias ui_scrolled_window scrolling_area } # === LibuiParadise::Extensions.ui_scrolling_window
650
+
651
+ # ========================================================================= #
652
+ # === LibuiParadise.colour_button
653
+ #
654
+ # The upstream API for a colour-button (in C) can be found here:
655
+ #
656
+ # https://github.com/andlabs/libui/blob/master/unix/colorbutton.c
657
+ #
658
+ # ========================================================================= #
659
+ def self.colour_button
660
+ _ = ::LibUI.new_color_button
661
+ ::LibuiParadise.register_this_fiddle_pointer_widget(_, __method__)
662
+ return _
663
+ end; self.instance_eval { alias color_button colour_button } # === LibuiParadise.color_button
664
+ self.instance_eval { alias new_color_button colour_button } # === LibuiParadise.new_color_button
665
+ self.instance_eval { alias new_colour_button colour_button } # === LibuiParadise.new_colour_button
666
+ self.instance_eval { alias ui_colour_button colour_button } # === LibuiParadise.ui_colour_button
667
+
668
+ # ========================================================================= #
669
+ # === LibuiParadise.generic_window
670
+ #
671
+ # Usage example:
672
+ #
673
+ # x = LibuiParadise.generic_window(LibuiParadise.button('1'), LibuiParadise.button('2'))
674
+ # x = LibuiParadise.generic_window(LibuiParadise.button('1'), LibuiParadise.button('2')) {{ height: 50 }}
675
+ # x = LibuiParadise.generic_window(LibuiParadise.button('1'), LibuiParadise.button('2')) {{ height: 50, width: 120 }}
676
+ #
677
+ # ========================================================================= #
678
+ def self.generic_window(
679
+ *use_these_widgets,
680
+ &block
681
+ )
682
+ unless LibuiParadise.respond_to?(:GenericWindow)
683
+ require 'libui_paradise/generic_window/generic_window.rb'
684
+ end
685
+ generic_window = LibuiParadise::GenericWindow.new { :do_not_run_yet }
686
+ # ======================================================================= #
687
+ # === Handle blocks next
688
+ # ======================================================================= #
689
+ if block_given?
690
+ yielded = yield
691
+ if yielded.is_a? Hash
692
+ # =================================================================== #
693
+ # === :height
694
+ # =================================================================== #
695
+ if yielded.has_key?(:height)
696
+ generic_window.set_height(
697
+ yielded[:height]
698
+ )
699
+ generic_window.update_the_main_window
700
+ end
701
+ # =================================================================== #
702
+ # === :width
703
+ # =================================================================== #
704
+ if yielded.has_key?(:width)
705
+ generic_window.set_width(
706
+ yielded[:width]
707
+ )
708
+ generic_window.update_the_main_window
709
+ end
710
+ # =================================================================== #
711
+ # === :title
712
+ # =================================================================== #
713
+ if yielded.has_key?(:title)
714
+ generic_window.set_title(
715
+ yielded[:title]
716
+ )
717
+ generic_window.update_the_main_window
718
+ end
719
+ end
720
+ end
721
+ # ======================================================================= #
722
+ # Next prepare adding more widgets to this generic window:
723
+ # ======================================================================= #
724
+ use_these_widgets.flatten!
725
+ use_these_widgets.compact!
726
+ if use_these_widgets.is_a?(Array) and !use_these_widgets.empty?
727
+ generic_window.add_these_widgets(use_these_widgets)
728
+ end
729
+ return generic_window
730
+ end
731
+
732
+ # ========================================================================= #
733
+ # === LibuiParadise.combobox
734
+ # ========================================================================= #
735
+ def self.combobox(
736
+ optional_array = nil, &block
737
+ )
738
+ combobox = ::LibUI.new_combobox
739
+ # ======================================================================= #
740
+ # Register it at once:
741
+ # ======================================================================= #
742
+ add_to_the_registered_widgets(combobox, __method__)
743
+ if block_given?
744
+ optional_array = yield
745
+ end
746
+ if optional_array and optional_array.is_a?(Array)
747
+ # append_this_array_to_that_combobox(optional_array, combobox)
748
+ combobox.append_this_array(optional_array)
749
+ end
750
+ return combobox
751
+ end; self.instance_eval { alias combo_box combobox } # === LibuiParadise.combo_box
752
+ self.instance_eval { alias ui_combo_box combobox } # === LibuiParadise.ui_combo_box
753
+ self.instance_eval { alias ui_combobox combobox } # === LibuiParadise.ui_combobox
754
+
755
+ # ========================================================================= #
756
+ # === LibuiParadise.editable_combobox
757
+ #
758
+ # This is a combo-box that the user can modify.
759
+ # ========================================================================= #
760
+ def self.editable_combobox(
761
+ optional_array = nil,
762
+ &block
763
+ )
764
+ _ = ::LibUI.new_editable_combobox
765
+ if block_given?
766
+ optional_array = yield
767
+ end
768
+ if optional_array and optional_array.is_a?(Array)
769
+ append_this_array_to_that_combobox(optional_array, _)
770
+ end
771
+ add_to_the_registered_widgets(_, __method__)
772
+ return _
773
+ end; self.instance_eval { alias editable_combo_box editable_combobox } # === LibuiParadise.editable_combo_box
774
+ self.instance_eval { alias ui_editable_combo_box editable_combobox } # === LibuiParadise.ui_editable_combo_box
775
+
776
+ # ========================================================================= #
777
+ # === LibuiParadise.set_title
778
+ #
779
+ # Simpler window-set-title functionality.
780
+ # ========================================================================= #
781
+ def self.set_title(
782
+ this_title,
783
+ main_window = main_window?
784
+ )
785
+ ::LibUI.window_set_title(main_window, this_title)
786
+ end
787
+
788
+ end
789
+
790
+ if __FILE__ == $PROGRAM_NAME
791
+ LibuiParadise.hello_world
792
+ end