libui_paradise 0.1.49

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of libui_paradise might be problematic. Click here for more details.

Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1505 -0
  3. data/doc/README.gen +1252 -0
  4. data/doc/SNIPPETS.md +221 -0
  5. data/doc/TODO.md +14 -0
  6. data/lib/libui_paradise/autoinclude.rb +9 -0
  7. data/lib/libui_paradise/domain_specific_language/README.md +5 -0
  8. data/lib/libui_paradise/domain_specific_language/button.yml +7 -0
  9. data/lib/libui_paradise/examples/001_basic_button_example.rb +17 -0
  10. data/lib/libui_paradise/examples/002_basic_table_image.rb +92 -0
  11. data/lib/libui_paradise/examples/003_font_button.rb +34 -0
  12. data/lib/libui_paradise/examples/004_date_time_picker.rb +31 -0
  13. data/lib/libui_paradise/examples/005_msg_box_error.rb +25 -0
  14. data/lib/libui_paradise/examples/006_histogram.rb +193 -0
  15. data/lib/libui_paradise/examples/007_combo_box_example.rb +41 -0
  16. data/lib/libui_paradise/examples/008_simple_notepad_example.rb +23 -0
  17. data/lib/libui_paradise/examples/009_checkbox_example.rb +82 -0
  18. data/lib/libui_paradise/examples/010_grid_example.rb +26 -0
  19. data/lib/libui_paradise/examples/011_fancy_text_example.rb +21 -0
  20. data/lib/libui_paradise/examples/012_control_gallery.rb +180 -0
  21. data/lib/libui_paradise/examples/013_midi_player.rb +91 -0
  22. data/lib/libui_paradise/examples/014_basic_draw_text.rb +134 -0
  23. data/lib/libui_paradise/examples/015_font_example.rb +91 -0
  24. data/lib/libui_paradise/examples/016_search_entry_example.rb +16 -0
  25. data/lib/libui_paradise/examples/017_tabs_example.rb +22 -0
  26. data/lib/libui_paradise/examples/018_image_example.rb +82 -0
  27. data/lib/libui_paradise/examples/019_open_file_button_example.rb +24 -0
  28. data/lib/libui_paradise/examples/020_unicode_text_example.rb +28 -0
  29. data/lib/libui_paradise/examples/021_spinbutton_example.rb +25 -0
  30. data/lib/libui_paradise/examples/022_text_example.rb +16 -0
  31. data/lib/libui_paradise/examples/023_parse_config_file_example.config +6 -0
  32. data/lib/libui_paradise/examples/023_parse_config_file_example.rb +13 -0
  33. data/lib/libui_paradise/examples/024_text_view_example.rb +14 -0
  34. data/lib/libui_paradise/examples/025_scrolling_area.rb +16 -0
  35. data/lib/libui_paradise/examples/026_colour_button.rb +51 -0
  36. data/lib/libui_paradise/examples/027_form_example.rb +37 -0
  37. data/lib/libui_paradise/examples/028_password_entry_example.rb +17 -0
  38. data/lib/libui_paradise/examples/029_two_buttons_showing_how_to_enable_and_disable_them.rb +32 -0
  39. data/lib/libui_paradise/examples/030_table_example.rb +51 -0
  40. data/lib/libui_paradise/experimental/dsl.rb +17 -0
  41. data/lib/libui_paradise/extensions/extensions.rb +25 -0
  42. data/lib/libui_paradise/extensions/hash_fiddle_pointer_widgets.rb +129 -0
  43. data/lib/libui_paradise/extensions/misc.rb +309 -0
  44. data/lib/libui_paradise/fiddle/pointer.rb +841 -0
  45. data/lib/libui_paradise/images/LIBUI_PARADISE_LOGO.png +0 -0
  46. data/lib/libui_paradise/images/README.md +2 -0
  47. data/lib/libui_paradise/images/form_example.png +0 -0
  48. data/lib/libui_paradise/libui_classes/area_handler.rb +52 -0
  49. data/lib/libui_paradise/libui_classes/button.rb +82 -0
  50. data/lib/libui_paradise/libui_classes/checkbox.rb +37 -0
  51. data/lib/libui_paradise/libui_classes/color_button.rb +44 -0
  52. data/lib/libui_paradise/libui_classes/combobox.rb +55 -0
  53. data/lib/libui_paradise/libui_classes/editable_combobox.rb +51 -0
  54. data/lib/libui_paradise/libui_classes/entry.rb +80 -0
  55. data/lib/libui_paradise/libui_classes/font.rb +78 -0
  56. data/lib/libui_paradise/libui_classes/font_button.rb +40 -0
  57. data/lib/libui_paradise/libui_classes/grid.rb +55 -0
  58. data/lib/libui_paradise/libui_classes/hbox.rb +98 -0
  59. data/lib/libui_paradise/libui_classes/horizontal_separator.rb +41 -0
  60. data/lib/libui_paradise/libui_classes/image.rb +82 -0
  61. data/lib/libui_paradise/libui_classes/label.rb +83 -0
  62. data/lib/libui_paradise/libui_classes/menu.rb +36 -0
  63. data/lib/libui_paradise/libui_classes/msg_box.rb +97 -0
  64. data/lib/libui_paradise/libui_classes/msg_box_error.rb +49 -0
  65. data/lib/libui_paradise/libui_classes/multiline_entry.rb +59 -0
  66. data/lib/libui_paradise/libui_classes/non_wrapping_multiline_entry.rb +41 -0
  67. data/lib/libui_paradise/libui_classes/open_file.rb +42 -0
  68. data/lib/libui_paradise/libui_classes/password_entry.rb +49 -0
  69. data/lib/libui_paradise/libui_classes/progressbar.rb +41 -0
  70. data/lib/libui_paradise/libui_classes/radio_buttons.rb +36 -0
  71. data/lib/libui_paradise/libui_classes/scrolling_area.rb +85 -0
  72. data/lib/libui_paradise/libui_classes/search_entry.rb +36 -0
  73. data/lib/libui_paradise/libui_classes/spinbox.rb +55 -0
  74. data/lib/libui_paradise/libui_classes/tab.rb +39 -0
  75. data/lib/libui_paradise/libui_classes/table.rb +45 -0
  76. data/lib/libui_paradise/libui_classes/text_layout.rb +42 -0
  77. data/lib/libui_paradise/libui_classes/vbox.rb +51 -0
  78. data/lib/libui_paradise/libui_classes/window.rb +167 -0
  79. data/lib/libui_paradise/project/project.rb +26 -0
  80. data/lib/libui_paradise/prototype/README.md +3 -0
  81. data/lib/libui_paradise/prototype/prototype.rb +101 -0
  82. data/lib/libui_paradise/requires/require_the_libui_classes.rb +26 -0
  83. data/lib/libui_paradise/requires/require_the_libui_paradise_project.rb +11 -0
  84. data/lib/libui_paradise/version/version.rb +17 -0
  85. data/lib/libui_paradise.rb +1 -0
  86. data/libui_paradise.gemspec +49 -0
  87. metadata +164 -0
data/doc/README.gen ADDED
@@ -0,0 +1,1252 @@
1
+ GOBOLINUX_IS_GREAT
2
+ ADD_LAST_UPDATE
3
+
4
+ ## The libui_paradise project
5
+
6
+ <img src="https://i.imgur.com/hYf3sum.png" style="margin: 1em; padding: 8px">
7
+
8
+ (This image has been partially auto-generated via **cfdg**, then modified
9
+ by me via **gimp** and ImageMagick - the rounded borders were
10
+ done via ImageMagick. You can re-use this image if you want to, including
11
+ the colour-pattern, via a **CC BY 3.0** licence. See the following link
12
+ for that licence: https://creativecommons.org/licenses/by/3.0/. For
13
+ cfdg itself, have a look at: https://www.contextfreeart.org/gallery/)
14
+
15
+ The **libui_paradise project** aims to enhance the official (upstream)
16
+ ruby-libui bindings a little bit.
17
+
18
+ You can find the upstream ruby-libui bindings, maintained by **kojix2**,
19
+ here:
20
+
21
+ https://rubygems.org/gems/libui
22
+
23
+ (Or visit the github page for ruby-libui here via this link:
24
+ https://github.com/kojix2/LibUI )
25
+
26
+ (Be wary of the name that I use on this page - the currently maintained gem is
27
+ called **libui**; the older gem, which was called **libui-ruby**, is no longer
28
+ maintained since as of **2019**. In the document here I may call kojix2' gem
29
+ **ruby-libui**, but the official name is simply **libui**, which refers to the
30
+ gem mentioned above: https://rubygems.org/gems/libui - I understand that I
31
+ am using a misnomer when I refer to this as **ruby-libui**, but it helps
32
+ me remember, so ...)
33
+
34
+ Aside from this mentioned goal of **trying to enhance** the upstream ruby-bindings,
35
+ the **libui_paradise** project also attempts to demonstrate how we could **try to
36
+ use a DSL** to write less code in the long run; at the least less syntax.
37
+
38
+ Less syntax is not automatically a win-win situation, but often it can
39
+ be very useful.
40
+
41
+ Example for this:
42
+
43
+ _ = button('Hello world!') # for libui
44
+
45
+ You can use a similar variant in ruby-gtk3, for example:
46
+
47
+ _ = Gtk::Button.new('Hello world!')
48
+
49
+ Or, if you want to use "toplevel-methods", like the above, identical to the
50
+ first variant:
51
+
52
+ _ = button('Hello world!') # for ruby-gtk
53
+
54
+ In fact: if you notice the above three lines of code then there is indeed no
55
+ difference between which toolkit to use between the first variant and
56
+ the last variant. We could then, in theory, "plug in" different toolkits,
57
+ be it ruby-gtk, ruby-tk, ruby-libui and so forth. The **glimmer** project
58
+ is doing this to some extent, as a general DSL wrapper over GUI-related
59
+ functionality, including the www - see here: https://github.com/AndyObtiva/glimmer
60
+
61
+ We could even extend this to the www and generate the appropriate
62
+ tags that way, by treating HTML tags as "objects". Note that this is
63
+ "in theory"; in practice there are some shortcomings, or limitations,
64
+ such as different toolkits not supporting the same widgets or
65
+ functionality. The old ruby-qt toolkit, for example, required you to
66
+ connect slots to signals, due to qt requiring this. I do not know if
67
+ this is still the case or not, but back in the days this was
68
+ necessary and it complicated using ruby-qt a little bit.
69
+
70
+ The **libui_paradise gem** here is highly experimental at this stage
71
+ and may not work for all use cases, or may have bugs - I am still
72
+ learning myself here. I want to see which API calls make the most sense
73
+ in the long run, ideally even across different GUIs as well as the
74
+ www. (For those of you who have some experience with ruby-gtk this may
75
+ seem familiar, as pointed out above - API elements such as **.set_text()**
76
+ or **widget1.add(widget2)**; I kind of learned GUIs first via
77
+ **ruby-gtk**, which evidently shaped my opinion on GUI layouts
78
+ to some extent.)
79
+
80
+ The official ruby-libui project maintained by kojix2 comes with
81
+ **13 examples** (August 2021) so far. I assume that more examples
82
+ may be added over the coming months and years depending on use
83
+ case, time availability, motivation and so forth. Have a look at
84
+ the code provided on the github page to understand what is going
85
+ on - in particular the **histogram** example is really nifty if
86
+ you want to play around with it **interactively**. It is probably the
87
+ best example in this regard, because it features interactive and
88
+ dynamic use in a visual way - you can choose the colours, for
89
+ example. A spin-button allows for visual change too, but I think
90
+ colours are more impressive than simple up-and-down counters.
91
+
92
+ On windows this may look like so (via kotlin-libui):
93
+
94
+ <img src="https://raw.githubusercontent.com/msink/kotlin-libui/master/samples/histogram/histogram-windows7.png" style="margin-left: 2em">
95
+
96
+ Also check out kojix2' other examples in ruby-gtk - would be great
97
+ if we could have the same in libui one day, but this also depends
98
+ on what upstream libui makes available, unless it is somehow
99
+ possible to connect multiple shared libraries into libui; then
100
+ we could perhaps extend libui.
101
+
102
+ I am trying to think about ways to simplify the code in these
103
+ examples as well, so that we can "do more by writing less". But as
104
+ stated before: this is all **highly experimental** and subject
105
+ to change. I am going via slow, tiny babysteps here! Constant
106
+ wins the race in the long run, just remember the turtle versus
107
+ the rabbit. The rabbit always believed that he would win the
108
+ race ...
109
+
110
+ **kojix2** pointed out that a half-baked or incomplete OOP design may
111
+ not make a lot of sense in regards to ruby-libui - we have to think a
112
+ bit about **Fiddle::Pointer** which not everyone may have done before.
113
+
114
+ Otherwise you may end up segfaulting everything all over the place
115
+ (which I did run into already - but it is both scary and fun at the
116
+ same time!). Subclassing is also difficult to do properly - which
117
+ functions should be called to create a "proper" subclass? May there
118
+ be problems as a consequence of trying this? I have no idea right
119
+ now. This is definitely more related to the C API of ruby than
120
+ "pure", plain ruby as such. You kind of have to understand the
121
+ underlying C code to some extent.
122
+
123
+ I do not really know C very well; **pointers** are way above my
124
+ level of understanding, so **kojix2's** point is a fair one
125
+ to make, since someone may have to maintain a growing code base -
126
+ this may well be the case here too, so 'defensive programming'
127
+ is a viable strategy. There are examples where one has to work
128
+ around ruby's GC too, for instance - this all makes this a little
129
+ bit more complicated than plain, "pure" ruby code.
130
+
131
+ **However had**, at the same I still want to **experiment** and see
132
+ what may happen with the code in general - which pitfalls may happen
133
+ or which things could be improved upon. I think the more people use
134
+ libui and ruby-libui, the better this may become in the long run.
135
+ Imagine we could almost create a full desktop system based on
136
+ libui! Even if the original scope never was aimed towards that. :D
137
+
138
+ This may then be fast enough for ruby-on-the-desktop, and simple
139
+ enough to do that, too. Right now this has too many shortcomings;
140
+ I miss CSS styling in particular. But, in theory, we could do
141
+ this. Anyone feels clever enough to use ruby as a desktop-UI
142
+ language via libui? I suppose it still requires some decent
143
+ knowledge of C ...
144
+
145
+ Lots of different people could create widgets and add-ons when
146
+ this were possible ... but I digress.
147
+
148
+ **Write a GUI once, run everywhere** (well ... at the least in
149
+ theory). This is an excellent idea, even if libui may not be
150
+ around one day, that idea should be retained for other GUIs
151
+ in the future.
152
+
153
+ It's quite difficult to get GTK and ruby-gtk to work on
154
+ **windows** - I tried to compile it some weeks ago but I
155
+ ended up having "missing symbols" error messages afterwards.
156
+ I managed to get the hello-world.c example working, but the
157
+ more complicated examples did not work for me.
158
+
159
+ On Linux this is much, much easier to do ... I literally just
160
+ compile GTK, after its dependencies are properly installed (glib,
161
+ pango, atk, and so forth), and then the ruby bindings maintained
162
+ largely by kou (and others), and ... it works! At the least
163
+ on linux.
164
+
165
+ (I used to be able to run ruby-gtk2 on windows in the past,
166
+ a long time ago, using the provided binaries, but sadly upstream
167
+ GTK developers no longer provide binaries as-is, and there are
168
+ no binary bundles for ruby-gtk on windows anymore either. I
169
+ assume it is possible if you know msys2, and the windows
170
+ platform, but I am no expert on either, so ...)
171
+
172
+ **libui** is so much simpler to use on windows than GTK,
173
+ though - just do **gem install libui** and it'll work,
174
+ as-is. Literally. That's it. I tried it on my windows
175
+ laptop and it **does** indeed work. That convinced me
176
+ that it makes sense to use libui and ruby-libui. The reason it
177
+ works is because the ruby-libui gem (just called **libui**)
178
+ bundles the respective binaries, and it is quite small. This
179
+ would be much harder to do with ruby-gtk.
180
+
181
+ Now I am trying to find more awesome examples to showcase
182
+ what can be done. Who knows - perhaps even CSS may be supported
183
+ one day (perhaps only on linux though, which limits the
184
+ benefit of it; ruby-gtk3 does allow for CSS though). A
185
+ font example has also been provided, so we can upscale,
186
+ downscale, use different fonts, bold, in colours and so
187
+ on and so forth now.
188
+
189
+ Check out the colours in the file **basic_draw_text.rb**,
190
+ as courtesy provided by kojix2. That way you can style
191
+ the content of a widget more easily - only the fiddle-protection
192
+ against segfault parts is a bit strange, but that's a detail.
193
+
194
+ There currently is quite a bit of code to make this work;
195
+ in the long run I plan to simplify this if possible. **The
196
+ less code we have to write, the better** - as long as the
197
+ end code is still **readable**.
198
+
199
+ Note that the subclass situation may change eventually; see
200
+ upstream kojix2 and related discussion for fiddle. For
201
+ the time being, though, I'll retain my old approach until
202
+ I am sufficiently content with the project as-is. Right now
203
+ libui_paradise has way too much undocumented and untested
204
+ code and I still have not added all examples either (coloured
205
+ text, for instance, still has to be added; and more image-related
206
+ examples that are smaller). Stay tuned.
207
+
208
+ ## How to require the libui_paradise project
209
+
210
+ In order to **require the libui_paradise project**, use
211
+ something like the following:
212
+
213
+ require 'libui_paradise'
214
+
215
+ More frequently if you look at the **examples/** subdirectory, the
216
+ following is used instead:
217
+
218
+ require 'libui_paradise/autoinclude'
219
+
220
+ Note that this particular require call does a few things automatically,
221
+ which may not always be what you may want to use. So, again - check
222
+ out the official ruby-libui repository first, including the examples,
223
+ before having a look at **libui_paradise**. This project here is a
224
+ tinker-project, very unstable, subject to change - don't use it in
225
+ production yet.
226
+
227
+ In my own projects I tend to use the above autoinclude variant
228
+ most of the time, because that way I can write less code (omit
229
+ a few lines).
230
+
231
+ ## How to get started with ruby-libui and the libui_paradise project?
232
+
233
+ Well - as stated elsewhere, I first recommend to you that you look directly
234
+ at ruby-libui provided by kojix2, in particular the examples that he
235
+ distributes in the gem. Work through the examples step-by-step, possibly
236
+ starting with the smallest example, see whether they work (they do,
237
+ or should) and have a look at how things work - just to get an
238
+ overview.
239
+
240
+ Have a look at the code as well, in order to understand how it
241
+ works roughly; after some minutes or perhaps a very few hours of tinker-time
242
+ you should understand quite a bit already, if you already know ruby. Even
243
+ more so if you did work with GUIs before, including GUIs via a www-interface.
244
+
245
+ Then you are recommended to look at the libui_paradise project and look to
246
+ see what has been added on top of what kojix2 provides. Look at the examples
247
+ of the libui_paradise project as well (they are a bit simplified compared
248
+ to the upstream examples; unfortunately a few of them currently do not
249
+ work), then consider using **libui_paradise/prototype/prototype.rb** in
250
+ particular. Copy it and adjust it to your project and use case, as-is. You
251
+ may want to remove the grid that is inside there and use a hbox or a vbox
252
+ instead, or a padded_hbox and padded_vbox. It's all quite simple actually
253
+ once you understand the basic API: windows, widgets, buttons, entries.
254
+
255
+ For example, a button can be added in this way to a vbox, if you use
256
+ the libui_paradise gem:
257
+
258
+ outer_vbox = padded_vbox # padded means that it will have some padding to the sides
259
+ button = ui_button('Hello world!') # You can drop the ui_ prefix if you'd like to
260
+ button.on_clicked {
261
+ puts 'Hello world!'
262
+ }
263
+ outer_vbox.minimal(button) # Use minimal space if possible. Or use .add().
264
+
265
+ That's it! Inside of the **.on_clicked {}** block you can run the ruby code
266
+ that you want to use. A button that is in a container (such as **vbox**) that
267
+ outputs hello world when clicked. Can't get much simpler than that. \o/
268
+
269
+ You can omit the **ui_** part above. I just use it to point out the difference;
270
+ and because I'd otherwise may have to use "button = button" aka "button = button()"
271
+ which may be confusing, so I use **ui_button()** instead.
272
+
273
+ ## Fiddle::Pointer and playing with pointers
274
+
275
+ The **ruby-libui bindings** make use of **Fiddle::Pointer** a lot -
276
+ see the file called **ffi.rb** in the ruby-libui gem ("gem install libui").
277
+ It's like **magic** to me - scary and awesome at the same time.
278
+
279
+ As a consequence the libui_paradise project has to 'handle' pointers
280
+ as well, indirectly so, via whatever ruby-libui makes available.
281
+
282
+ I decided that, at the least for the time being, we will add
283
+ **ad-hoc code** straight to Fiddle::Pointer. This is not the
284
+ optimal solution and I do not recommend doing so, even more so as
285
+ we modify Fiddle::Pointer directly which I don't think is a good
286
+ idea; it may be better to have some proper data structures and
287
+ perhaps **subclass** from Fiddle::Pointer instead, and then modify
288
+ that subclass instead. That may be better. But for the time being,
289
+ the code here will remain as it is, until we can come up with
290
+ better ways to deal with the situation. For now **simplicity**
291
+ rules.
292
+
293
+ Some of the examples used require assigment to local variables
294
+ to avoid the GC to kick in and cause the program to end. This
295
+ is presently not very elegant - see a discussion between kojix2
296
+ and kou to improve on this part. For the time being, though,
297
+ some of the examples require 'boilerplate' assignment to
298
+ variabless. Stay tuned for improvements in this regard; ideally
299
+ we can use libui without having to play with pointers ever.
300
+
301
+ ## Constraints of the libui_paradise gem
302
+
303
+ The libui_paradise gem comes with some **constraints**.
304
+
305
+ For example, many of the ad-hoc methods on **Fiddle::Pointer**
306
+ will only work after you called e. g. **ui_vbox** or a
307
+ similar constructor where we registered which widgets are
308
+ created (aka the **new_** methods that are available on
309
+ the **LibUI** 'namespace'). Only when this has happened
310
+ will that widget become registered in the main Hash.
311
+
312
+ That then means, logically, that if you use a method such as:
313
+
314
+ check_button = ui_check_button
315
+ check_button.is_active?
316
+
317
+ This will only work if that widget was created already prior
318
+ to that "method call".
319
+
320
+ What this means in practice is that it is best if you
321
+ **create all the skeleton** (the **basic UI elements**) **before**
322
+ calling any other code, including on-clicked or on-toggle
323
+ events. Otherwise you may find nil values and don't
324
+ know why that is the case so. If this seems too complicated
325
+ for you, don't worry - the examples distributed via the
326
+ libui_paradise gem should work fine (except two buggy ones), so
327
+ the point of this subsection here is to keep your attention to
328
+ the fact that, as of right now, if you use libui_paradise, the
329
+ **proper-order-of-elements is important**. Ideally create all
330
+ the widgets first, before you add additional functionality to them.
331
+
332
+ This is admittedly not a very elegant limitation right
333
+ now, and one day this restrictions may be removed or
334
+ lifted - but for now, it is a limitation that requires
335
+ a tiny bit of discipline to work around, for the time being.
336
+ So, again - it is best to split up the skeleton UI from
337
+ the function.
338
+
339
+ ## How to use an 'Open File' button
340
+
341
+ I came up with the following solution for now:
342
+
343
+ outer_vbox = padded_vbox
344
+ button_open_file = button('Open file')
345
+ button_open_file.on_clicked {
346
+ filename = open_file(window).to_s # This is the part that will open a local file.
347
+ }
348
+ outer_vbox << button_open_file # Add the button to the outer-vbox.
349
+
350
+ Calling the **.to_s** method on the Fiddle::Pointer yields the actual
351
+ filename. You can then add more code to deal with this.
352
+
353
+ **window** above refers to the **main_window**. See the example
354
+ **019_open_file_button_example.rb** for how this actually works.
355
+
356
+ In the future this may be even further simplified a little, as
357
+ opening local files is a very common task in most GUIs. A
358
+ single method probably should suffice for using such a
359
+ specialized button.
360
+
361
+ ## How to quit from a ruby-libui widget
362
+
363
+ I found that:
364
+
365
+ UI.quit
366
+
367
+ Works best overall. And seems to suffice as well.
368
+
369
+ There are some other calls, such as destroy-control and similar
370
+ actions, which are probably clean-up related - but by and large
371
+ **UI.quit** seems to be the main part how to exit from a
372
+ libui-application.
373
+
374
+ I document this here in the event that I forget it in a few
375
+ months.
376
+
377
+ If you use the libui_paradise gem then you can use the
378
+ following method to use a quit button:
379
+
380
+ a_quit_button = ui_quit_button
381
+
382
+ If you want another textual description then you can do the
383
+ following:
384
+
385
+ a_quit_button = ui_quit_button(text: 'Open a local file') # That text description would be confusing though
386
+ a_quit_button = ui_quit_button(text: 'Exit the application') # Much better now! \o/
387
+
388
+ ## UI.new_button()
389
+
390
+ UI.new_button allows us to create a new button.
391
+
392
+ Examples:
393
+
394
+ button1 = UI.new_button('Text')
395
+ button2 = UI.new_button('▶')
396
+
397
+ ## Subclassing
398
+
399
+ Currently subclassing from LibUI elements does not work - I simply
400
+ have no idea how to "subclass" from a **Fiddle::Pointer**. Perhaps we
401
+ have to build up a data structure that behaves like Fiddle::Pointer
402
+ but also has methods that allow 'OOP behaviour'. Has anyone tried
403
+ this yet? I am scared to try considering I already got segfaults ...
404
+
405
+ Eventually I may figure this out - or someone else with more knowledge
406
+ will make this available. We can probably 'fake' subclassing to
407
+ a pointer somehow ... after all ruby internally has to figure it
408
+ out as well and probably did so already, on the C-level side.
409
+
410
+ ## Quickly adding text to a widget
411
+
412
+ You can use something like this:
413
+
414
+ outer_vbox = ui_vbox
415
+ outer_vbox.text(
416
+ 'This widget can be used to do xyz.'
417
+ )
418
+
419
+ Again - this modifies **Fiddle::Pointer** so be wary. The second
420
+ argument is the default one for use in a label / ui_text widget.
421
+
422
+ ## Working with combo-boxes
423
+
424
+ To create a combo-box, do:
425
+
426
+ combo_box = ui_combo_box
427
+
428
+ You can fill it with an array of entries **on creation-time** via:
429
+
430
+ combo_box = ui_combo_box([1,2,3,4])
431
+
432
+ This will also focus on the very first element when doing so.
433
+
434
+ If you need to do so manually, and focus on another element,
435
+ you can use the following toplevel method:
436
+
437
+ UI.combobox_set_selected()
438
+
439
+ To query the currently selected value, use:
440
+
441
+ UI.combobox_selected(pointer)
442
+
443
+ This is usually done via a **proc {}** object. See kojix2' examples.
444
+
445
+ In LibuiParadise a few custom methods were added, such as
446
+ **.ui_sync_connect()**. This method was added to connect a
447
+ combo-box to a entry and automatically sync that entry whenever
448
+ the combo box is changed. See the example **007_combo_box_example.rb**
449
+ for how this works.
450
+
451
+ The **source code** to the combo-box in libui, at the least
452
+ for UNIX/Linux, can be seen here:
453
+
454
+ https://github.com/andlabs/libui/blob/master/unix/combobox.c
455
+
456
+ ## Error messages and ui_error_message
457
+
458
+ In LibUI respectively ruby-libui you can display error messages
459
+ via a popup window.
460
+
461
+ The API is something like this:
462
+
463
+ UI.msg_box(main_window, 'Information', 'You clicked the button')
464
+ UI.msg_box_error(main_window, 'Information', 'You clicked the button')
465
+
466
+ The first line shows a normal message box; the second line shows how to
467
+ use a message box specifically 'adapted' for displaying errors to the
468
+ end user.
469
+
470
+ LibuiParadise makes this available via **ui_msg_box** and **ui_msg_box_error**
471
+ respectively.
472
+
473
+ ## Libui Form
474
+
475
+ **Form** is a container that takes labels for its contents. This is currently
476
+ just a stub though - we may have to research this with better examples.
477
+
478
+ ## Libui Checkbox
479
+
480
+ A simple checkbox example in **plain** ruby-libui follows:
481
+
482
+ checkbox = UI.checkbox('Checkbox')
483
+ checkbox_toggle_callback = proc { |ptr|
484
+ checked = UI.checkbox_checked(ptr) == 1
485
+ UI.checkbox_set_text(ptr, "I am the checkbox (#{checked})")
486
+ }
487
+
488
+ This may look like so on Linux:
489
+
490
+ <img src="https://i.imgur.com/d7qWalZ.png" style="margin-left: 2em; padding: 4px; border: 1px solid black;">
491
+
492
+ To query whether a checkbox is **active**, use code such as the
493
+ following:
494
+
495
+ checkbox.is_active?
496
+ checkbox.active?
497
+
498
+ This depends on the modifications to Fiddler::Pointer, so
499
+ be wary when you use this - there be dragons (perhaps). Most
500
+ of these modifications are based on **.object_id**, which is
501
+ registered in a main, toplevel Hash in the
502
+ **libui_paradise project**. Not very elegant, but simple, and
503
+ it works (for the most part).
504
+
505
+ ## Adding a widget into another widget
506
+
507
+ I chose the following **API** for this:
508
+
509
+ box1.add(box2, 1)
510
+
511
+ Note that this is "cheating" a bit because the method **.add()** is defined
512
+ on **Fiddle::Pointer**. That's scary! Segfaults coming your way. But it
513
+ also seems to work to some extent. Which is amazing ... :-)
514
+
515
+ In ruby-gtk it is quite common to use **.add()**. While **.pack_start()**
516
+ and **.pack_end()** are available in ruby-gtk as well, I think .add() is
517
+ the simpler name. We just **add a widget to another widget** - job done.
518
+
519
+ (I may also use << as alias to .add() and while << is great, remember
520
+ that it can not easily be used all the time, e. g. box1 << box2 <<
521
+ box3 versus box1.add(box2).add(box3) - the latter is a bit more
522
+ resilient syntax-wise.)
523
+
524
+ As stated, **<<** was added as an alias to **.add()** but I am not yet sure
525
+ if this is a very good idea. It's super-nifty to use << everywhere, but it
526
+ also changes the syntax of the whole .rb file ... on the other hand, using
527
+ << is easier than .add() so ... I'll go with that as well. Remember
528
+ there is more than one way to do something in ruby - you need to
529
+ select the variant(s) that work best for you and possibly ignore the
530
+ other variants.
531
+
532
+ Since a while the above can be simplified a bit, as will be shown
533
+ next.
534
+
535
+ Rather than use:
536
+
537
+ box1.add(box2, 1)
538
+
539
+ You can now do this instead:
540
+
541
+ box1.maximal(box2)
542
+
543
+ This is a tiny bit longer, but you can omit the ", 1" part, which is
544
+ nice. The alternative is .minimal(), which defaults to:
545
+
546
+ add(second_widget, 0)
547
+
548
+ So the only difference between .maximal() and .minimal() will be
549
+ whether you pass 0 or 1 to the method. See the upstream libui
550
+ API to understand the difference.
551
+
552
+ ## Libui Tabs
553
+
554
+ The notebook-tab may look like this:
555
+
556
+ <img src="https://i.imgur.com/olWQAIJ.png" style="margin-left: 2em">
557
+
558
+ ## Create a vertical box:
559
+
560
+ Use code like this:
561
+
562
+ vbox = UI.new_vertical_box
563
+
564
+ If you use the libui_paradise gem, you can use this:
565
+
566
+ vbox = ui_vbox # or
567
+ vbox = padded_vbox
568
+
569
+ ## Adding a horizontal separator
570
+
571
+ The method **UI.new_horizontal_separator** can be used to add (or rather
572
+ first create) a horizontal separator.
573
+
574
+ You can then add it via .add() or << if you use the libui_paradise
575
+ project. Alternatively you can use the toplevel method provided by
576
+ ruby-libui, since that is what the libui_paradise project is doing anyway.
577
+
578
+ To simplify this further, you can do something like this:
579
+
580
+ outer_vbox = ui_vbox # I call the most-outer vbox usually outer-vbox
581
+ outer_vbox.add_hsep
582
+ # outer_vbox.add_horizontal_separator # Or this variant if you prefer some verbosity instead.
583
+
584
+ Or, perhaps better, use a padded vbox:
585
+
586
+ outer_vbox = padded_vbox # note that "ui_" is not used here
587
+ outer_vbox.add_hsep
588
+
589
+ I needed this functionality to quickly add horizontal separators for some
590
+ visual cue in the **User Interface**. Using **.add_hsep** is very
591
+ convenient and fast to write/type. If you want more verbosity then remember
592
+ that you can always use the upstream API as-is.
593
+
594
+ ## Entries in LibUI (ui_entry)
595
+
596
+ The official source for an ui_entry for Unix (including Linux) can be read
597
+ here:
598
+
599
+ https://github.com/andlabs/libui/blob/master/unix/entry.c
600
+
601
+ Personally I tend to create a new entry element in this way:
602
+
603
+ entry = ui_entry
604
+
605
+ To set new content to it, do:
606
+
607
+ entry.set_text('foobar') # Make sure it is a String; that seems to work better.
608
+
609
+ To respond to events look at **OnChanged**.
610
+
611
+ It can be set read only via:
612
+
613
+ entry.read_only # This has not been added into libui-paradise yet.
614
+
615
+ To respond to on-changed events, you can use:
616
+
617
+ UI.entry_on_changed()
618
+
619
+ Complete example:
620
+
621
+ text_changed_callback = proc { |ptr|
622
+ puts "Current textbox data: '#{UI.entry_text(ptr)}'"
623
+ }
624
+
625
+ text_entry = ui_entry
626
+ text_entry.set_text('Please enter a command')
627
+ text_entry.on_changed {
628
+ text_changed_callback
629
+ }
630
+
631
+ The Proc object has to be passed into the {} block variation.
632
+
633
+ The latter uses:
634
+
635
+ UI.entry_on_changed(text_entry, text_changed_callback, nil)
636
+
637
+ ## Grids in LibUI
638
+
639
+ The API is quite complex and hard to remember:
640
+
641
+ UI.grid_append(grid, entry1, 0, 0, 2, 1, 0, 0, 1, 0)
642
+
643
+ Who can remember offhand what these values mean?
644
+
645
+ The upstream struct is this:
646
+
647
+ struct gridChild {
648
+ uiControl *c;
649
+ int left;
650
+ int top;
651
+ int xspan;
652
+ int yspan;
653
+ int hexpand;
654
+ uiAlign halign;
655
+ int vexpand;
656
+ uiAlign valign;
657
+
658
+ // have these here so they don't need to be reallocated each relayout
659
+ int finalx, finaly;
660
+ int finalwidth, finalheight;
661
+ int minwidth, minheight;
662
+ };
663
+
664
+ The documentation for Go has this signature:
665
+
666
+ func (g *Grid) Append(child Control, left, top int, xspan, yspan int, hexpand bool, halign Align, vexpand bool, valign Align)
667
+
668
+ Append adds the given control to the Grid, at the given coordinate.
669
+
670
+ I assume that **uiControl c** refers to the widget that is to be embedded
671
+ into the grid, so the numbers that follow afterwards are the ones
672
+ that are important. Let's have a look at them, based on the above API
673
+ call, and only list these again, without the **()**:
674
+
675
+ # left, top, xspan, yspan, hexpand, halign, vexpand, valign
676
+ # 0, 0, 2, 1, 0, 0, 1, 0
677
+
678
+ xspan and yspan refer to width; left and top refer to the position
679
+ in the grid. hexpand and vexpand means whether the grid-cell will
680
+ expand horizontally or vertically. halign and valign, I think,
681
+ are used to align the grid-cell horizontally and vertically, so you
682
+ can position them exactly in the middle.
683
+
684
+ Recently (August 2021) I discovered that you can actually put
685
+ a button-in-a-button. I don't know whether this is a bug or
686
+ a feature, but it is hilarious.
687
+
688
+ The 'raw' code I used for this was the following:
689
+
690
+ UI.grid_append(grid, UI.new_button('3'),0,1,1,1,1,1,1,1)
691
+ UI.grid_append(grid, UI.new_button('4'),1,1,1,1,1,1,1,1)
692
+ UI.grid_append(grid, UI.new_button('5'),0,1,1,1,1,0,1,0)
693
+ UI.grid_append(grid, UI.new_button('6'),1,1,1,1,1,0,1,0)
694
+
695
+ This led to the following image:
696
+
697
+ <img src="https://i.imgur.com/6sWwWKh.png" style="margin-left: 1em">
698
+
699
+ The smaller buttons and the larger buttons can be clicked. They
700
+ reside in the same grid-cell. I don't know whether this is a
701
+ bug or a feature really, but this was quite hilarious to see.
702
+ In the event that I may forget this, I'll keep this here as
703
+ a reference.
704
+
705
+ ## Margins in LibUI
706
+
707
+ The **margin** property specifies if the window content should have a
708
+ margin or not. The default value is false, meaning that there will
709
+ be no margin.
710
+
711
+ In order to understand the difference, a visual image may be
712
+ best - the first image that is shown next shows **no margin**,
713
+ whereas the second image **shows** a margin.
714
+
715
+ <img src="https://cloud.githubusercontent.com/assets/11197111/16465935/804a30d4-3e41-11e6-8189-150e8cddc152.png" style="margin-left: 2em"><br>
716
+ <img src="https://cloud.githubusercontent.com/assets/11197111/16465906/68304cfe-3e41-11e6-8ae0-3123205ee136.png" style="margin-left: 2em"><br>
717
+
718
+ Note that the API name is **margined** rather than **margin** -
719
+ got me a little while to get used to that name.
720
+
721
+ The API in Go is: __func (*Group) SetMargined__ respectively
722
+ __func (g *Group) SetMargined(margined bool)__. When **true**
723
+ then the group has margins around the child widgets, as mentioned
724
+ already.
725
+
726
+ The **size** of the margins in use, is, unfortunately, determined
727
+ automatically by the OS - we currently (2021) do not have control
728
+ over the size of the margin at hand via **libui**.
729
+
730
+ Code examples for 'raw' **ruby-libui** are these:
731
+
732
+ UI.window_set_margined(MAIN_WINDOW, 1)
733
+ UI.group_set_margined(group, 1)
734
+
735
+ Because I prefer calling methods on objects, I added this instead:
736
+
737
+ MAIN_WINDOW.is_margined
738
+ MAIN_WINDOW.uses_a_margin # Or this variant.
739
+
740
+ Note that we are here faking method-calls on a Fiddle::Pointer, but
741
+ if we don't pay attention then it looks like **OOP**! If it walks
742
+ like a duck, quacks like a duck then ... it may be a
743
+ **Fiddle::Pointer:Duck**!!!
744
+
745
+ ## Entry
746
+
747
+ An entry can be set read only (readOnly: Boolean, aka true or false).
748
+
749
+ An entry in libui may look like this:
750
+
751
+ <img src="https://raw.githubusercontent.com/parro-it/libui-node/master/docs/media/UiEntry.png" style="margin-left:1em">
752
+
753
+ ## Borderless windows
754
+
755
+ A window that is **borderless: true** will not show any title or
756
+ outside frame. This may be useful for games and what not.
757
+
758
+ ## Spinbutton / Spinbox
759
+
760
+ You can use:
761
+
762
+ UI.new_spinbox
763
+
764
+ To create a new spinbox.
765
+
766
+ To specify the min and max range, pass them as parameters:
767
+
768
+ UI.new_spinbox(0, 100)
769
+
770
+ If you use the extensions then you can do this instead:
771
+
772
+ ui_spinbox
773
+ spinbox # this is the simplest variant
774
+
775
+ You should be able to set a value via set_value but I have
776
+ not yet added an example for this.
777
+
778
+ Relevant methods are:
779
+
780
+ UI.spinbox_on_changed()
781
+ UI.spinbox_set_value()
782
+ UI.spinbox_value()
783
+
784
+ To set a value:
785
+
786
+ spinbox.set_value(42)
787
+ spinbox.value = 42 # this works as well
788
+
789
+ ## Create a text-view widget
790
+
791
+ A text-view widget shows content, such as the content of a local file.
792
+
793
+ In libui the general API for this is:
794
+
795
+ UI.new_multiline_entry # this is a textview
796
+
797
+ ## Control Gallery
798
+
799
+ Here is an image, from kotlin-libui, how this may look on windows:
800
+
801
+ <img src="https://raw.githubusercontent.com/msink/kotlin-libui/master/samples/controlgallery/controlgallery-windows7.png" style="margin-left: 2em">
802
+
803
+ ## Enabling / Disabling buttons in libui
804
+
805
+ This is, assumingly, already possible via:
806
+
807
+ libui/ui.h
808
+
809
+ Lines 105 to 107 in a0a9807
810
+ _UI_EXTERN int uiControlEnabled(uiControl *);
811
+ _UI_EXTERN void uiControlEnable(uiControl *);
812
+ _UI_EXTERN void uiControlDisable(uiControl *);
813
+
814
+ In ruby-libui this should be possible via:
815
+
816
+ LibUI.control_enable()
817
+ UI.control_enable()
818
+
819
+ LibUI.control_disable()
820
+ UI.control_disable()
821
+
822
+ See the example **029_two_buttons_showing_how_to_enable_and_disable_them.rb**
823
+ in how this works.
824
+
825
+ ## libui and ruby-libui internals
826
+
827
+ This is an incomplete subsection. I know almost nothing at all about
828
+ C; kojix2 knows more, so I refer you to the homepage of ruby-libui
829
+ respectively.
830
+
831
+ Most of the code for ruby-libui resides under **ffi.rb**. In August 2021
832
+ this file contains almost 1000 lines, including newlines. Still quite
833
+ some code. If you want to look at the raw content, have a look at
834
+ the following link for **ffi.rb**:
835
+
836
+ https://raw.githubusercontent.com/kojix2/LibUI/main/lib/libui/ffi.rb
837
+
838
+ The two most important components there, as far as I understand it,
839
+ are **try_extern** and **structs**.
840
+
841
+ For instance:
842
+
843
+ try_extern 'void uiOnShouldQuit(int (*f)(void *data), void *data)'
844
+
845
+ Control = struct [
846
+
847
+ I assume that any support made available for ruby **must** have a
848
+ corresponding entry in **ffi.rb**. At the least this is how I
849
+ understood it.
850
+
851
+ If it is not in **ffi.rb** then support for that was not (yet) added.
852
+
853
+ Individual enum entries can also be seen. For instance, for font-related
854
+ data the following attributes are in use:
855
+
856
+ AttributeTypeFamily = 0
857
+ AttributeTypeSize = 1
858
+ AttributeTypeWeight = 2
859
+ AttributeTypeItalic = 3
860
+ AttributeTypeStretch = 4
861
+ AttributeTypeColor = 5
862
+ AttributeTypeBackground = 6
863
+ AttributeTypeUnderline = 7
864
+ AttributeTypeUnderlineColor = 8
865
+ AttributeTypeFeatures = 9
866
+
867
+ You can probably use the rubygems features of comparing old gem
868
+ releases with one another to see which support has been added to
869
+ ruby-libui over the past months or so. Most work was probably done
870
+ in 2020 or even before that (there are some older ruby bindings
871
+ to libui, but these work differently as kojix2 explained).
872
+
873
+ ## Limitations of/in LibUI
874
+
875
+ LibUI is not perfect - it is missing many things that should work just fine
876
+ on the main operating systems. On top of that I'd love to support specific
877
+ features on a given operating system even if it is NOT cross-platform. But
878
+ this is not possible via LibUI.
879
+
880
+ The following subsection mentions a few constraints of LibUI in varying
881
+ degrees of complexity/importance:
882
+
883
+ - No CSS support. I miss this. On ruby-gtk3 this is possible. In LibUI I can't.
884
+ - Unable to set different fonts for an application other than using FontButton.
885
+
886
+ ## Structure of the project
887
+
888
+ In **September 2021** the libui_paradise project was re-arranged slightly. There
889
+ is now a dedicated **libui_classes/** directory that "simulates" separate classes.
890
+ For example, libui_button now resides in **button.rb**. I use the same directory
891
+ layout in the **gtk_paradise** gem and I think it makes a lot of sense - at the
892
+ least I can quickly find the code that I may want to modify or extend. If I
893
+ want to extend buttons, then I modify **buttons.rb**. That's simple, right?
894
+
895
+ Another reason why the project was re-structured was so that we can use a
896
+ **unified DSL** for the GUI elements in the long run.
897
+
898
+ For example, code such as the following:
899
+
900
+ _ = button
901
+ _.on_clicked {
902
+ puts 'Hello world!'
903
+ }
904
+
905
+ Should work on ruby-gtk3, libui and all the other toolkits one day - even on
906
+ the www. But the different toolkits do not implement the same functionality.
907
+ Libui only offers a reduced functionality, for instance. Thus, the DSL that
908
+ we may then use **can only support a subset of functionality**, whereas other
909
+ toolkits are more useful in this regard. This was an additional reason why files
910
+ such as button.rb were created - it makes it easier to know which functionality
911
+ has to be changed in order for libui_paradise to enable such a unified
912
+ DSL approach. This currently does not yet work fine in 2021, but one day it
913
+ should work just fine.
914
+
915
+ Note that the older l**ibui_paradise gem** will be made available at the
916
+ least for three months (so until end of December 2021 at the least). It used
917
+ a different directory layout.
918
+
919
+ You may ask why the main module is called **LibuiParadise::Extensions**.
920
+ Why not modify LibUI directly? After all the gtk_paradise gem does the
921
+ same, by modifying **module Gtk** directly.
922
+
923
+ That is a good question, and the main reason for this is because I was
924
+ not sure whether I can actually get away with modifying the LibUI
925
+ namespace directly. Fiddle::Pointer still scares me, so I am experimenting.
926
+
927
+ For now I thought it best to create a separate module, that is then included
928
+ and modified - see the **included hook** that is presently used. This seems
929
+ to be simpler for the time being. I may plan to change a lot more one day,
930
+ if I ever manage to find out how to simulate proper subclasses via
931
+ Fiddle::Pointer ... :)
932
+
933
+ --------------------------------------------------------------------------------
934
+ ## SNIPPETS.md
935
+
936
+ Next, the content of the file called **SNIPPETS.md** will be shown.
937
+
938
+ EMBED_THIS_FILE /home/x/programming/ruby/src/libui_paradise/doc/SNIPPETS.md
939
+
940
+ --------------------------------------------------------------------------------
941
+
942
+ ## Advantages and Disadvantages of the libui project
943
+
944
+ It would be unfair to only selectively name advantages but not talk about
945
+ disadvantages, so this subsection will show some limitations, trade-offs,
946
+ constraints and opportunities. This is not complete, but it may become
947
+ somewhat more complete over time. Stay tuned.
948
+
949
+ (a) Advantages:
950
+
951
+ - Works on windows out-of-the-box after you installed the libui-gem.
952
+ - Is super-simple to use compared to other toolkits, including ruby-gtk.
953
+ - Super-simple to build up a prototype for a GUI, buttons that work,
954
+ spin-boxes, text-views and so forth. Faster than any other toolkit
955
+ IMO.
956
+ - Works cross-platform.
957
+
958
+ (b) Disadvantage:
959
+
960
+ - Limited ability to control the layout and size of widgets.
961
+ - May look like utter crap ... :-)
962
+ - Some functionality is missing, such as a scrolled-window for every widget.
963
+ - No way to use different fonts in the same application and choosing a font
964
+ is needlessly complicated.
965
+
966
+ Some more disadvantages relate to Fiddle::Pointer. You kind of need to
967
+ know C fairly well as well as the GC in ruby, in order to understand
968
+ what is going on. Since I don't, I hit a dead end, kind of.
969
+
970
+ This is so far in September 2021. Let's see what the future brings.
971
+ Perhaps other toolkits will learn from libui and implement the good
972
+ parts for **their own** widget set.
973
+
974
+ ## LibuiParadise.parse_this_config_file()
975
+
976
+ This method can be used to parse a .config file. This file should
977
+ describe the main window, such as:
978
+
979
+ width: 1000
980
+ height: 150
981
+ title: Parse Config File Example
982
+
983
+ I have been using this in gtk_paradise and I think it may be convenient
984
+ if you create lots of small windows and widgets that you don't want
985
+ to hardcode values for directly into the .rb file at hand.
986
+
987
+ To create a toplevel window from this use code such as the following:
988
+
989
+ use_this_config_file = '023_parse_config_file_example.config'
990
+ window = LibuiParadise.parse_this_config_file(use_this_config_file)
991
+
992
+ In fact, the example **023_parse_config_file_example.rb** shows how
993
+ this is used. The width of the main window will be 1000 and the
994
+ height only 150.
995
+
996
+ This functionality may be extended in the future. For example, we
997
+ could enable to automatically parse such a .config file if it
998
+ exists, thus not even requiring that method call in the future.
999
+
1000
+ For now, though, you have to explicitely use that method if you
1001
+ want to instantiate such a window from a .config file. It will
1002
+ be evaluated at a later time (past September 2021) how useful this
1003
+ really is.
1004
+
1005
+ ## Width and Height of the main window
1006
+
1007
+ Different computers have different display values (their monitor).
1008
+
1009
+ I use a wide-screen LCD monitor, but I also have smaller laptops,
1010
+ and I want libui to work there just as well.
1011
+
1012
+ The following API can be used to set the width and height of the
1013
+ main window:
1014
+
1015
+ set_height()
1016
+ set_width()
1017
+
1018
+ You can also use something like '95%' as input. In that case the
1019
+ desired value will be calculated depending on the max-resolution
1020
+ of the current display. This presently only works on linux; if
1021
+ someone knows how to make this work on windows and Mac OSX let
1022
+ me know. (On these systems it will instead default to a hardcoded
1023
+ value of 1024 for width and 800 for height).
1024
+
1025
+ The following example shows how to use a percentage value:
1026
+
1027
+ set_height('80%')
1028
+
1029
+ ## Coloured Text
1030
+
1031
+ At this point I only show how this may look on Win7, re-using
1032
+ the picture the kotlin-libui developers made available:
1033
+
1034
+ <img src="https://raw.githubusercontent.com/msink/kotlin-libui/master/samples/drawtext/drawtext-windows7.png" style="margin-left: 2em">
1035
+
1036
+ Doesn't look that bad, right? May not be the prettiest GUI of all
1037
+ times, but it is functional - and simple.
1038
+
1039
+ ## Status of the libui_paradise project
1040
+
1041
+ I am still, as of 2021, experimenting somewhat randomly. While I intend to
1042
+ improve libui_paradise, it is a hobby project that is not as important
1043
+ as, say, the gtk_paradise project (which contains custom ruby-gtk
1044
+ related addons; ruby-gtk has a LOT more functionality than libui has).
1045
+
1046
+ I can not promise to work reliably on libui_paradise, but every now and
1047
+ then, say every some weeks, I will try to add more code to it, in
1048
+ particular examples and documentation. However had, keep in mind that
1049
+ the project is not one of my most important projects, so it may not
1050
+ receive as many updates as other projects. See also the next subsection,
1051
+ the "Todo List".
1052
+
1053
+ ## DSLs for libui (in ruby)
1054
+
1055
+ kojix2 pointed out that glimmer has support for libui; check it out
1056
+ here:
1057
+
1058
+ https://github.com/AndyObtiva/glimmer-dsl-libui
1059
+
1060
+ libui_paradise will support the same syntax (in the long run) as
1061
+ glimmer does, either directly, or via a module and a way to
1062
+ require it specifically. But stay tuned for this - right now as
1063
+ of late 2021 this is not yet guaranteed. (If anyone needs quick
1064
+ API changes, let me know and I'll change libui_paradise. Other
1065
+ than that, the libui_paradise project is in a slow maintenance
1066
+ mode right now, so again, stay tuned. \o/ )
1067
+
1068
+ ## Todo List and Goals related to libui
1069
+
1070
+ Here I will list some todo entries and related goals for libui or the
1071
+ libui_paradise gem - if anyone finds out how to solve some of these
1072
+ limitations, you are welcome to share!
1073
+
1074
+ - Add more small, **standalone examples** showcasing how to use (and
1075
+ combine) different functionality, in particular colourized text and use
1076
+ of (embedded) images if applicable. Ideally we should be able to combine
1077
+ both freely, if possible.
1078
+
1079
+ - Find out how to create "proper" subclasses to Fiddle::Pointer, simulating
1080
+ a subclass to it.
1081
+
1082
+ - Find out how halign and valign work in Libui-Grid. Somehow I can not easily reposition it ...
1083
+ or perhaps I have been able to, and just have not noticed this (may have to embed one
1084
+ widget in another widget in order for this to come into effect)
1085
+
1086
+ - Find out how to do ad-hoc calls on linux to gtk, so that we can use CSS.
1087
+ Perhaps some extension mechanism could be used, similar to how ffi works
1088
+ in general. Unfortunately this probably requires knowledge of C, so this
1089
+ is an obstacle for me. I should have learned C before ruby ... :P
1090
+
1091
+ - Get more people to learn about libui and use them in their projects,
1092
+ in particular for simple applications. I think this is the most important
1093
+ goal: we need more people to learn about libui and begin to use it.
1094
+ Contribute to upstream as well. If we have a sufficiently large user
1095
+ base then it should be easier to add new possibilities onto libui,
1096
+ which in turn will "cascade" downwards to all the other bindings
1097
+ to libui, be it in kotlin, python, ruby and so forth.
1098
+
1099
+ ## DateTime Widget
1100
+
1101
+ Only an image is shown how it may look on windows:
1102
+
1103
+ <img src="https://raw.githubusercontent.com/msink/kotlin-libui/master/samples/datetime/datetime-windows7.png" style="margin-left: 2em">
1104
+
1105
+ ## Password entries in LibUI
1106
+
1107
+ If you use the libui_paradise gem then you can create a new password entry
1108
+ in using any of the following variants:
1109
+
1110
+ entry = ui_password_entry
1111
+ entry = password_entry
1112
+
1113
+ For "raw" libui, use this:
1114
+
1115
+ LibUI.new_password_entry
1116
+
1117
+ ## Progress Bars in LibUI
1118
+
1119
+ Here an image how this may look:
1120
+
1121
+ <img src="https://i.imgur.com/i1i4ppZ.png" style="margin-left: 2em">
1122
+
1123
+ ## Tables in LibUI
1124
+
1125
+ You may be able to create a new table via:
1126
+
1127
+ table = LibUI.new_table
1128
+
1129
+ model = LibUI.new_table_model(model_handler)
1130
+
1131
+ table_params = LibUI::FFI::TableParams.malloc
1132
+ table_params = Fiddle::RUBY_FREE
1133
+ table_params.Model = model
1134
+ table_params.RowBackgroundColorModelColumn = -1
1135
+ table = LibUI.new_table(table_params)
1136
+
1137
+ The table header is an array that contains the following attributes:
1138
+
1139
+ 1. editable, bool type, the column is whether editable
1140
+ 2. textColor
1141
+ 3. title
1142
+ 4. type, specify value of button, image, imgtext, progress, checkbox, checkboxtext, color, text
1143
+
1144
+ Note that this is incomplete; it's a bit complicated.
1145
+
1146
+ In the end, this is possible though:
1147
+
1148
+ <img src="https://raw.githubusercontent.com/msink/kotlin-libui/master/samples/table/table-windows7.png" style="margin-left: 2em">
1149
+
1150
+ ## Form example in LibuiParadise
1151
+
1152
+ Inspired by **glimmer-libui**, I ported the form example, into
1153
+ **027_form_example.rb**. Unfortunately it does not look
1154
+ as good as it does in **glimmer-libui**, and the code I use for
1155
+ it is too verbose right now.
1156
+
1157
+ Still, if you are curious, this is how it looks on icewm
1158
+ in October 2021:
1159
+
1160
+ <img src="https://i.imgur.com/FkU6aWd.png" style="margin-left: 2em">
1161
+
1162
+ I may improve this eventually a bit, so that the alignment looks
1163
+ as good as it does on glimmer-dsl; the code of 27_form_example.rb
1164
+ may also be cleaned up in the future (the glimmer-libui code
1165
+ looks better). But for now this is how it is; Andy is very
1166
+ actively improving **glimmer-libui** right now.
1167
+
1168
+ Available "new"-widgets in LibUI:
1169
+
1170
+ LibUI.new_area
1171
+ LibUI.new_attributed_string
1172
+ LibUI.new_group
1173
+ LibUI.new_spinbox
1174
+ LibUI.new_stretch_attribute
1175
+ LibUI.new_background_attribute
1176
+ LibUI.new_button # this is a simple button
1177
+ LibUI.new_checkbox # this is a simple checkbox
1178
+ LibUI.new_color_attribute
1179
+ LibUI.new_color_button
1180
+ LibUI.new_combobox # this is a combobox
1181
+ LibUI.new_date_picker
1182
+ LibUI.new_date_time_picker
1183
+ LibUI.new_editable_combobox
1184
+ LibUI.new_grid
1185
+ LibUI.new_horizontal_box
1186
+ LibUI.new_horizontal_separator # this is a simple horizontal separator
1187
+ LibUI.new_image # this is a simple image
1188
+ LibUI.new_italic_attribute # this is basically italic font-style
1189
+ LibUI.new_label
1190
+ LibUI.new_tab
1191
+ LibUI.new_table # this is a simple table
1192
+ LibUI.new_table_model
1193
+ LibUI.new_table_value_image
1194
+ LibUI.new_table_value_int
1195
+ LibUI.new_table_value_color
1196
+ LibUI.new_table_value_string
1197
+ LibUI.new_time_picker
1198
+ LibUI.new_menu
1199
+ LibUI.new_multiline_entry # this is a textview
1200
+ LibUI.new_non_wrapping_multiline_entry
1201
+ LibUI.new_open_type_features
1202
+ LibUI.new_password_entry
1203
+ LibUI.new_underline_attribute
1204
+ LibUI.new_entry
1205
+ LibUI.new_progress_bar # this is a progress_bar
1206
+ LibUI.new_underline_color_attribute
1207
+ LibUI.new_family_attribute
1208
+ LibUI.new_radio_buttons
1209
+ LibUI.new_vertical_box
1210
+ LibUI.new_features_attribute
1211
+ LibUI.new_scrolling_area # this is a scrolling area
1212
+ LibUI.new_vertical_separator
1213
+ LibUI.new_font_button
1214
+ LibUI.new_search_entry # this is a search entry
1215
+ LibUI.new_weight_attribute
1216
+ LibUI.new_form # this is a form
1217
+ LibUI.new_size_attribute
1218
+ LibUI.new_window
1219
+ LibUI.new_slider
1220
+
1221
+ ## Links related to libui or libui-based projects
1222
+
1223
+ This subsection may contain a few links, in the event that other
1224
+ people want to see useful entries.
1225
+
1226
+ I will try to explain what is to be seen by these various pages.
1227
+
1228
+ (1) https://wiki.call-cc.org/eggref/4/libui
1229
+
1230
+ This is using chicken-egg scheme for bindings to libui. I like the
1231
+ simplicity and overview - it's really nice to read and use. I'd
1232
+ wish we would have this for ruby too. :)
1233
+
1234
+ Note that the documentation is outdated as of 2021, though. A fate
1235
+ shared with a lot of documentation in general out there ...
1236
+
1237
+ (2) https://pkg.go.dev/github.com/andlabs/ui
1238
+
1239
+ This is andlabs' documentation for libui, from the point of view of
1240
+ **Go**. It is probably the biggest, most complete documentation for
1241
+ libui. While it is specific to Go, as it was written by the same
1242
+ author you can expect the documentation to be quite decent.
1243
+
1244
+ (Note that some other bindings contain good documentation too,
1245
+ such as kotlin libui bindings and others.)
1246
+
1247
+ (3) http://api.call-cc.org/4/doc/libui
1248
+
1249
+ Similar to the first one, but uses a different layout, which
1250
+ may be helpful.
1251
+
1252
+ ADD_CONTACT_INFORMATION