libui_paradise 0.1.49

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.

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/SNIPPETS.md ADDED
@@ -0,0 +1,221 @@
1
+ # How to require libui:
2
+
3
+ require 'libui'
4
+
5
+ # How to instantiate libui:
6
+
7
+ UI = LibUI
8
+ init = UI.init
9
+
10
+ # How to add a new main window:
11
+ # width, height, hasMenubar
12
+ main_window = UI.new_window('hello world', 300, 200, 1)
13
+
14
+ Source code:
15
+
16
+ https://raw.githubusercontent.com/andlabs/libui/master/unix/window.c
17
+
18
+ # How to add a libui-widget to the main window / Designate a child widget:
19
+
20
+ UI.window_set_child(main_window, button)
21
+
22
+ # Act on closing-event (on quit tag):
23
+
24
+ UI.window_on_closing(main_window) {
25
+ puts 'Bye Bye'
26
+ UI.control_destroy(main_window)
27
+ UI.quit
28
+ 0
29
+ }
30
+ # Or simpler:
31
+ close_properly(main_window)
32
+
33
+ # How to properly close via LibuiExtensions:
34
+
35
+ main_window = UI.window('Notepad', 500, 300, 1)
36
+ UI.close_properly(main_window)
37
+ # Or simpler:
38
+ close_properly(main_window)
39
+
40
+ # Add the window to the main UI:
41
+
42
+ UI.control_show(main_window)
43
+ main_window.show_the_controls # Or use this one here.
44
+
45
+ # Set the padding on a grid:
46
+
47
+ UI.grid_set_padded(grid, 25)
48
+
49
+ # Attach a new widget onto the grid:
50
+
51
+ UI.grid_append(grid, text('Yo2'), 1, 0, 1, 1, 0, 0, 1, 0)
52
+
53
+ # How to add a click-action to the button:
54
+
55
+ UI.button_on_clicked(button) {
56
+ UI.msg_box(main_window, 'Information', 'You clicked the button')
57
+ 0
58
+ }
59
+
60
+ # How to add a margin:
61
+
62
+ UI.window_set_margined(MAIN_WINDOW, 1)
63
+
64
+ # How to exit easily:
65
+
66
+ UI.window_on_closing(main_window) {
67
+ UI.exit_from(main_window)
68
+ }
69
+
70
+ # Create an attributed String:
71
+
72
+ string = UI.new_attributed_string
73
+ attributes = UI.new_family_attribute("Courier New 30")
74
+ attribute = UI.new_color_attribute(0.75, 0.25, 0.5, 0.75)
75
+ UI.append_with_attribute("text color", attribute, nil)
76
+
77
+ # How to set a padded box:
78
+
79
+ UI.box_set_padded(box, 1) # The value is either 0 or 1.
80
+
81
+ Alignment may be:
82
+ 0: Fill
83
+ 1: Start
84
+ 2: Center
85
+ 3: End
86
+ Positioning:
87
+ 0: Left
88
+ 1: Top
89
+ 2: Right
90
+
91
+ # Create a message-box and an error message box:
92
+
93
+ UI.msg_box(main_window, 'Information', 'You clicked the button')
94
+ UI.msg_box_error(main_window, 'Information', 'You clicked the button')
95
+
96
+ # Add a checkbox (checkbox tag, checkbutton)
97
+
98
+ checkbox = UI.new_checkbox('Checkbox') # or ui_checkbox
99
+ checkbox_toggle_callback = proc { |pointer|
100
+ checked = UI.checkbox_checked(pointer) == 1
101
+ UI.window_set_title(MAIN_WINDOW, "Checkbox is #{checked}")
102
+ UI.checkbox_set_text(pointer, "I am the checkbox (#{checked})")
103
+ 0
104
+ }
105
+ UI.checkbox_on_toggled(checkbox, checkbox_toggle_callback, nil)
106
+ UI.box_append(inner, checkbox, 0)
107
+
108
+ To set it checked:
109
+
110
+ checkbox.set_checked(1)
111
+
112
+ To query its state:
113
+
114
+ checked = UI.checkbox_checked(pointer) == 1
115
+
116
+ # And the control:
117
+
118
+ UI.control_show(main_window)
119
+
120
+ # Using a text-entry (ui entry tag):
121
+
122
+ text_entry = UI.new_entry
123
+ UI.entry_set_text(text_entry, 'Please enter your feelings')
124
+ UI.entry_on_changed(text_entry, text_changed_callback, nil)
125
+
126
+ # To set this on a "multiline entry", aka spanning several
127
+ # rows, do use:
128
+ UI.multiline_entry_set_text(entry1, 'Yo there')
129
+ ui_text_view # an alias used in libui_paradise
130
+
131
+ text1 = UI.entry_text(entry1) # Obtain text. You may have to call .to_s on it, to guarantee the String.
132
+ UI.multiline_entry_text # Obtain the text from a multiline entry.
133
+
134
+ # Create a textview:
135
+
136
+ UI.new_non_wrapping_multiline_entry
137
+
138
+ # Putting the text-entry into a hbox:
139
+
140
+ UI.box_append(hbox1, text_entry, 1)
141
+
142
+ # Create a combobox (combo tag, combobox tag):
143
+
144
+ combobox_selected_callback = proc { |ptr|
145
+ puts "New combobox selection: #{UI.combobox_selected(ptr)}"
146
+ }
147
+ cbox = UI.new_combobox
148
+ UI.combobox_append(cbox, 'combobox Item 1')
149
+ UI.combobox_append(cbox, 'combobox Item 2')
150
+ UI.combobox_append(cbox, 'combobox Item 3')
151
+ UI.box_append(inner, cbox, 0)
152
+ UI.combobox_on_selected(cbox, combobox_selected_callback, nil)
153
+
154
+ # Or more concise:
155
+ combo_box = UI.combobox {
156
+ ['combobox Item 1', 'combobox Item 2', 'combobox Item 3']
157
+ }
158
+
159
+ # Select the first entry:
160
+
161
+ UI.combobox_set_selected(combobox, 0) # The first one will be active too.
162
+
163
+ # Create a new tabbed notebook:
164
+
165
+ ui_tabs
166
+ ui_notebook
167
+
168
+ # Add content to an editable combox:
169
+
170
+ UI.append() # .append() adds the named item to the end of the EditableCombobox.
171
+
172
+ # How to run the main loop:
173
+
174
+ UI.main
175
+
176
+ # How to quit:
177
+
178
+ UI.quit
179
+
180
+ # How to build a menu-interface (menu tag):
181
+
182
+ help_menu = UI.new_menu('Help')
183
+ version_item = UI.menu_append_item(help_menu, 'Version')
184
+
185
+ # Create a new image:
186
+
187
+ image = UI.new_image(width, height)
188
+
189
+ # Fonts and LibUI:
190
+
191
+ font_descriptor = UI::FFI::FontDescriptor.malloc
192
+ p 'Font family: '+font_descriptor.Family.to_s+
193
+ 'Font size: '+font_descriptor.Size+
194
+ 'Font weight: '+font_descriptor.Weight+
195
+ 'Font italic: '+font_descriptor.Italic+
196
+ 'Font stretch: '+font_descriptor.Stretch
197
+
198
+ # Available widgets in libUI:
199
+
200
+ Button A button with a label
201
+ Checkbox A checkbox with a label
202
+ Combobox A simple combobox
203
+ ColorButton A button for selecting a color
204
+ EditableCombobox A combobox that can be edited.
205
+ Entry Text input, can be disabled.
206
+ FontButton A button for selecting a font (Incomplete: Cannot set programmatically)
207
+ Form A container that takes labels for its contents
208
+ Grid A container that aligns widgets for window design
209
+ Group A container that provides a title for a set of items
210
+ Label Displays a single line of text
211
+ Menu Creates a single column of an application menu
212
+ MultilineEntry An entry that allows multiple lines.
213
+ Time and Date Pickers Allows choosing of a date and/or time.
214
+ ProgressBar Displays a progress bar
215
+ RadioButton A set of radio buttons
216
+ Separator A simple vertical or horizontal separator
217
+ Slider A draggable slider for choosing a value in a range
218
+ Spinbox A numerical input with a minimum and maximum range
219
+ Tab A set named tabs for placing items in
220
+ Window Contains any other widget, cannot be embedded in a container
221
+ VBox, HBox A vertical or horizontal box for grouping items
data/doc/TODO.md ADDED
@@ -0,0 +1,14 @@
1
+ - Make sure that each component has a screenshot. It's ok to
2
+ re-use existing screenshots from other projects.
3
+
4
+ - Make sure the project is API compatible to glimmer-libui.
5
+
6
+ - Rewrite the project from the get-go. Also integrate
7
+ @main_window into the main hash, rather than have it
8
+ standalone.
9
+
10
+ - Re-organize the examples, perhaps starting with another
11
+ one.
12
+
13
+ - Check for image and font support again. Something isn't
14
+ working!
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # require 'libui_paradise/autoinclude.rb'
6
+ # =========================================================================== #
7
+ require 'libui_paradise/requires/require_the_libui_paradise_project.rb'
8
+
9
+ include LibuiParadise::Extensions
@@ -0,0 +1,5 @@
1
+ The directory here is an attempt to simplify the bindings in
2
+ libui_paradise even more.
3
+
4
+ For instance, the user should be able to parse widgets that
5
+ are described in pure yaml.
@@ -0,0 +1,7 @@
1
+ button:
2
+ id: button1
3
+ text: 'This is a button.'
4
+ width: 120
5
+ height: 80
6
+ on_clicked:
7
+ do_call_this_method
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'libui_paradise/autoinclude'
6
+
7
+ main_window = main_window('hello world', 300, 200, 0)
8
+
9
+ button = button('Button')
10
+ button.on_clicked {|widget| # is a <Fiddle::Pointer:0x00005590774f1ca0 ptr=0x0000559077484c90 size=0 free=0x0000000000000000>
11
+ e 'The main button was clicked.'
12
+ ui_msg_box(main_window, 'Information', 'You clicked the button')
13
+ 0
14
+ }
15
+
16
+ main_window.child = button
17
+ main_window.intelligent_exit
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # This example displays images that can be freely downloaded from the
6
+ # Studio Ghibli website.
7
+ # =========================================================================== #
8
+ require 'libui_paradise/autoinclude'
9
+ require 'chunky_png'
10
+ require 'open-uri'
11
+
12
+ N_TIMES = 10
13
+ # =========================================================================== #
14
+ # === REMOTE_URL
15
+ # =========================================================================== #
16
+ REMOTE_URL = 'https://www.ghibli.jp/gallery/thumb-redturtle%03d.png'
17
+
18
+ main_window = ui_main_window('The Red Turtle', 310, 350, 0)
19
+
20
+ hbox = ui_padded_hbox
21
+ main_window.simple_exit
22
+ main_window.child = hbox
23
+
24
+ # =========================================================================== #
25
+ # === IMAGES
26
+ # =========================================================================== #
27
+ IMAGES = []
28
+
29
+ N_TIMES.times do |i|
30
+ url = format(REMOTE_URL, (i + 1))
31
+ this_file = URI.open(url)
32
+ # Use ChunkyPNG::Canvas to get information about the image at hand.
33
+ canvas = ChunkyPNG::Canvas.from_io(this_file)
34
+ this_file.close
35
+ data = canvas.to_rgba_stream
36
+ width = canvas.width
37
+ height = canvas.height
38
+ # ========================================================================= #
39
+ # Add a new image here:
40
+ # ========================================================================= #
41
+ image = UI.new_image(width, height)
42
+ UI.image_append(image, data, width, height, width * 4)
43
+ IMAGES << image # Store all images in the following area.
44
+ rescue StandardError => error
45
+ warn url, error.message
46
+ end
47
+
48
+ # =========================================================================== #
49
+ # Protects BlockCaller objects from garbage collection.
50
+ # =========================================================================== #
51
+ @blockcaller = []
52
+ # =========================================================================== #
53
+ # === rbcallback
54
+ # =========================================================================== #
55
+ def rbcallback(*args, &block)
56
+ args << [0] if args.size == 1 # Argument types are ommited
57
+ blockcaller = Fiddle::Closure::BlockCaller.new(*args, &block)
58
+ @blockcaller << blockcaller
59
+ blockcaller
60
+ end
61
+
62
+ model_handler = UI::FFI::TableModelHandler.malloc
63
+ model_handler.NumColumns = rbcallback(4) { 1 }
64
+ model_handler.ColumnType = rbcallback(4) { 1 } # Image
65
+ model_handler.NumRows = rbcallback(4) { IMAGES.size }
66
+ model_handler.CellValue = rbcallback(1, [1, 1, 4, 4]) do |_, _, row, _column|
67
+ UI.new_table_value_image(IMAGES[row])
68
+ end
69
+ model_handler.SetCellValue = rbcallback(0, [0]) {}
70
+
71
+ model = UI.new_table_model(model_handler)
72
+
73
+ table_params = UI::FFI::TableParams.malloc
74
+ table_params.Model = model
75
+ table_params.RowBackgroundColorModelColumn = -1
76
+
77
+ table = ui_table(table_params)
78
+ UI.table_append_image_column(table, 'www.ghibli.jp/works/red-turtle', -1)
79
+ hbox.maximal(table)
80
+
81
+ main_window.show_the_controls
82
+
83
+ UI.window_on_closing(main_window) {
84
+ e 'Bye Bye'
85
+ UI.control_destroy(main_window)
86
+ UI.free_table_model(model)
87
+ IMAGES.each { |i| UI.free_image(i) }
88
+ UI.quit
89
+ 0
90
+ }
91
+
92
+ UI.main_then_quit
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'libui_paradise/autoinclude'
6
+
7
+ main_window = UI.window('hello world', 300, 200, 1)
8
+
9
+ font_button = UI.font_button
10
+ # =========================================================================== #
11
+ # === font_descriptor
12
+ #
13
+ # The font_descriptor will contain all the important information about the
14
+ # font at hand. It will be updated via UI.font_button_font().
15
+ # =========================================================================== #
16
+ font_descriptor = UI::FFI::FontDescriptor.malloc
17
+ UI.font_button_on_changed(font_button) {
18
+ UI.font_button_font(font_button, font_descriptor)
19
+ # ========================================================================= #
20
+ # The following line will output something like:
21
+ #
22
+ # {:family=>"Georgia", :size=>12.0, :weight=>700, :italic=>0, :stretch=>4}
23
+ #
24
+ # ========================================================================= #
25
+ p family: font_descriptor.Family.to_s,
26
+ size: font_descriptor.Size,
27
+ weight: font_descriptor.Weight,
28
+ italic: font_descriptor.Italic,
29
+ stretch: font_descriptor.Stretch
30
+ }
31
+ main_window.close_properly
32
+ main_window.child = font_button
33
+ main_window.control_show
34
+ UI.main_then_quit
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'libui_paradise/autoinclude'
6
+
7
+ vbox = UI.vbox
8
+
9
+ date_time_picker = UI.new_date_time_picker
10
+
11
+ time = UI::FFI::TM.malloc
12
+
13
+ UI.date_time_picker_on_changed(date_time_picker) do
14
+ UI.date_time_picker_time(date_time_picker, time)
15
+ p sec: time.tm_sec,
16
+ min: time.tm_min,
17
+ hour: time.tm_hour,
18
+ mday: time.tm_mday,
19
+ mon: time.tm_mon,
20
+ year: time.tm_year,
21
+ wday: time.tm_wday,
22
+ yday: time.tm_yday,
23
+ isdst: time.tm_isdst
24
+ end
25
+ vbox.add(date_time_picker, 1)
26
+
27
+ main_window = UI.window('Date Time Pickers', 300, 200, 1)
28
+ main_window.close_properly
29
+ main_window.child = vbox
30
+ main_window.show_the_controls
31
+ UI.main_then_quit
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'libui_paradise/autoinclude'
6
+
7
+ TITLE = 'msg box error'
8
+ main_window = UI.window(TITLE, 300, 200, 1)
9
+
10
+ button1 = UI.button('Text (click me)')
11
+ button1.on_clicked {
12
+ UI.msg_box_error(
13
+ main_window,
14
+ 'Error',
15
+ "You clicked \nthe button"
16
+ )
17
+ 0
18
+ }
19
+
20
+ hbox = UI.hbox
21
+ hbox.append(button1, 1)
22
+ main_window.close_properly
23
+ main_window.child = hbox
24
+ main_window.control_show
25
+ UI.main_then_quit
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
6
+ # =========================================================================== #
7
+ require 'libui_paradise'
8
+
9
+ X_OFF_LEFT = 20
10
+ Y_OFF_TOP = 20
11
+ X_OFF_RIGHT = 20
12
+ Y_OFF_BOTTOM = 20
13
+ POINT_RADIUS = 5
14
+
15
+ init = UI.init
16
+ handler = UI.area_handler
17
+ histogram = UI.new_area(handler)
18
+ brush = UI::FFI::DrawBrush.malloc
19
+ color_button = UI.new_color_button
20
+ datapoints = []
21
+
22
+ def graph_size(area_width, area_height)
23
+ graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
24
+ graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
25
+ [graph_width, graph_height]
26
+ end
27
+
28
+ matrix = UI::FFI::DrawMatrix.malloc
29
+
30
+ # === point_locations
31
+ def point_locations(datapoints, width, height)
32
+ xincr = width / 9.0 # 10 - 1 to make the last point be at the end
33
+ yincr = height / 100.0
34
+
35
+ data = []
36
+ datapoints.each_with_index do |dp, i|
37
+ val = 100 - UI.spinbox_value(dp)
38
+ data << [xincr * i, yincr * val]
39
+ i += 1
40
+ end
41
+
42
+ data
43
+ end
44
+
45
+ # === construct_graph
46
+ def construct_graph(datapoints, width, height, should_extend)
47
+ locations = point_locations(datapoints, width, height)
48
+ path = UI.draw_new_path(0) # winding
49
+ first_location = locations[0] # x and y
50
+ UI.draw_path_new_figure(path, first_location[0], first_location[1])
51
+ locations.each do |loc|
52
+ UI.draw_path_line_to(path, loc[0], loc[1])
53
+ end
54
+
55
+ if should_extend
56
+ UI.draw_path_line_to(path, width, height)
57
+ UI.draw_path_line_to(path, 0, height)
58
+ UI.draw_path_close_figure(path)
59
+ end
60
+
61
+ UI.draw_path_end(path)
62
+
63
+ path
64
+ end
65
+
66
+ handler_draw_event = Fiddle::Closure::BlockCaller.new(
67
+ 0, [1, 1, 1]
68
+ ) do |_area_handler, _area, area_draw_params|
69
+ area_draw_params = UI::FFI::AreaDrawParams.new(area_draw_params)
70
+ path = UI.draw_new_path(0) # winding
71
+ UI.draw_path_add_rectangle(path, 0, 0, area_draw_params.AreaWidth, area_draw_params.AreaHeight)
72
+ UI.draw_path_end(path)
73
+ set_solid_brush(brush, 0xFFFFFF, 1.0) # white
74
+ UI.draw_fill(area_draw_params.Context, path, brush.to_ptr)
75
+ UI.draw_free_path(path)
76
+ dsp = UI::FFI::DrawStrokeParams.malloc
77
+ dsp.Cap = 0 # flat
78
+ dsp.Join = 0 # miter
79
+ dsp.Thickness = 2
80
+ dsp.MiterLimit = 10 # DEFAULT_MITER_LIMIT
81
+ dashes = Fiddle::Pointer.malloc(8)
82
+ dsp.Dashes = dashes
83
+ dsp.NumDashes = 0
84
+ dsp.DashPhase = 0
85
+
86
+ # draw axes
87
+ set_solid_brush(brush, 0x000000, 1.0) # black
88
+ graph_width, graph_height = *graph_size(area_draw_params.AreaWidth, area_draw_params.AreaHeight)
89
+
90
+ path = UI.draw_new_path(0) # winding
91
+ UI.draw_path_new_figure(path, X_OFF_LEFT, Y_OFF_TOP)
92
+ UI.draw_path_line_to(path, X_OFF_LEFT, Y_OFF_TOP + graph_height)
93
+ UI.draw_path_line_to(path, X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
94
+ UI.draw_path_end(path)
95
+ UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
96
+ UI.draw_free_path(path)
97
+
98
+ # now transform the coordinate space so (0, 0) is the top-left corner of the graph
99
+ UI.draw_matrix_set_identity(matrix)
100
+ UI.draw_matrix_translate(matrix, X_OFF_LEFT, Y_OFF_TOP)
101
+ UI.draw_transform(area_draw_params.Context, matrix)
102
+
103
+ # now get the color for the graph itself and set up the brush
104
+ # uiColorButtonColor(colorButton, &graphR, &graphG, &graphB, &graphA)
105
+ graph_r = Fiddle::Pointer.malloc(8) # double
106
+ graph_g = Fiddle::Pointer.malloc(8) # double
107
+ graph_b = Fiddle::Pointer.malloc(8) # double
108
+ graph_a = Fiddle::Pointer.malloc(8) # double
109
+
110
+ UI.color_button_color(color_button, graph_r, graph_g, graph_b, graph_a)
111
+ brush.Type = 0 # solid
112
+ brush.R = graph_r[0, 8].unpack1('d')
113
+ brush.G = graph_g[0, 8].unpack1('d')
114
+ brush.B = graph_b[0, 8].unpack1('d')
115
+
116
+ # now create the fill for the graph below the graph line
117
+ path = construct_graph(datapoints, graph_width, graph_height, true)
118
+ brush.A = graph_a[0, 8].unpack1('d') / 2.0
119
+ UI.draw_fill(area_draw_params.Context, path, brush)
120
+ UI.draw_free_path(path)
121
+
122
+ # now draw the histogram line
123
+ path = construct_graph(datapoints, graph_width, graph_height, false)
124
+ brush.A = graph_a[0, 8].unpack1('d')
125
+ UI.draw_stroke(area_draw_params.Context, path, brush, dsp)
126
+ UI.draw_free_path(path)
127
+ end
128
+
129
+ handler.Draw = handler_draw_event
130
+
131
+ # Assigning to local variables
132
+ # This is intended to protect Fiddle::Closure from garbage collection.
133
+ # See https://github.com/kojix2/LibUI/issues/8
134
+ handler.MouseEvent = (c1 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
135
+ handler.MouseCrossed = (c2 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
136
+ handler.DragBroken = (c3 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
137
+ handler.KeyEvent = (c4 = Fiddle::Closure::BlockCaller.new(1, [0]) { 0 })
138
+
139
+ UI.freeInitError(init) unless init.nil?
140
+
141
+ hbox = UI.hbox
142
+ UI.box_set_padded(hbox, 1)
143
+
144
+ vbox = UI.vbox
145
+ UI.box_set_padded(vbox, 1)
146
+ hbox.add(vbox, 0)
147
+ hbox.add(histogram, 1)
148
+
149
+ datapoints = Array.new(10) {
150
+ UI.new_spinbox(0, 100).tap { |datapoint|
151
+ UI.spinbox_set_value(datapoint, Random.new.rand(90))
152
+ UI.spinbox_on_changed(datapoint) {
153
+ UI.area_queue_redraw_all(histogram)
154
+ }
155
+ UI.box_append(vbox, datapoint, 0)
156
+ }
157
+ }
158
+
159
+ # =========================================================================== #
160
+ # === set_solid_brush
161
+ # =========================================================================== #
162
+ def set_solid_brush(brush, color = 0xFFFFFF, alpha = 1.0)
163
+ brush.Type = 0 # solid
164
+ brush.R = ((color >> 16) & 0xFF) / 255.0
165
+ brush.G = ((color >> 8) & 0xFF) / 255.0
166
+ brush.B = (color & 0xFF) / 255.0
167
+ brush.A = alpha
168
+ brush
169
+ end
170
+
171
+ set_solid_brush(brush, LibuiParadise::Extensions::COLOUR_BLUE, 1.0)
172
+ UI.color_button_set_color(color_button, brush.R, brush.G, brush.B, brush.A)
173
+
174
+ UI.color_button_on_changed(color_button) {
175
+ UI.area_queue_redraw_all(histogram)
176
+ }
177
+
178
+ vbox.add(color_button, 0)
179
+
180
+ MAIN_WINDOW = UI.new_window('histogram example', 640, 480, 1)
181
+ UI.window_set_margined(MAIN_WINDOW, 1)
182
+ UI.window_set_child(MAIN_WINDOW, hbox)
183
+
184
+ should_quit = proc { |_ptr|
185
+ UI.control_destroy(MAIN_WINDOW)
186
+ UI.quit
187
+ 0
188
+ }
189
+
190
+ UI.window_on_closing(MAIN_WINDOW, should_quit)
191
+ UI.on_should_quit(should_quit)
192
+ MAIN_WINDOW.control_show
193
+ UI.main_then_quit
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ require 'libui_paradise/autoinclude'
6
+
7
+ TITLE = 'Combo Box Example'
8
+ WIDTH = 500
9
+ HEIGHT = 250
10
+ main_window = ui_main_window(TITLE, WIDTH, HEIGHT, 0)
11
+
12
+ @entry = ui_entry
13
+
14
+ @combo_box = ui_combobox(
15
+ [
16
+ 'combobox Item 1',
17
+ 'combobox Item 2',
18
+ 'combobox Item 3'
19
+ ]
20
+ )
21
+
22
+ # =========================================================================== #
23
+ # The next code used to be in place until September 2021. I will retain it
24
+ # here in the event that we need to use it again one day.
25
+ # =========================================================================== #
26
+
27
+ # combobox_selected_callback = proc { |pointer|
28
+ # e "New combobox selection: #{UI.combobox_selected(pointer)}"
29
+ # @entry.set_text(selected?(pointer))
30
+ # }
31
+ #
32
+ # UI.combobox_on_selected(@combo_box, combobox_selected_callback, nil)
33
+
34
+ ui_sync_connect(@combo_box, @entry)
35
+
36
+ box = padded_vbox
37
+ box.minimal(@combo_box)
38
+ box.minimal(@entry)
39
+
40
+ main_window.child = box
41
+ main_window.intelligent_exit