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/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