glimmer-dsl-libui 0.4.4 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -1
  3. data/README.md +932 -160
  4. data/VERSION +1 -1
  5. data/examples/button_counter.rb +2 -1
  6. data/examples/color_button.rb +18 -13
  7. data/examples/color_button2.rb +14 -0
  8. data/examples/date_time_picker.rb +19 -14
  9. data/examples/date_time_picker2.rb +20 -0
  10. data/examples/dynamic_area.rb +77 -90
  11. data/examples/dynamic_area2.rb +14 -12
  12. data/examples/dynamic_area3.rb +90 -0
  13. data/examples/dynamic_area4.rb +95 -0
  14. data/examples/font_button.rb +17 -12
  15. data/examples/font_button2.rb +18 -0
  16. data/examples/form_table.rb +0 -2
  17. data/examples/form_table2.rb +0 -2
  18. data/examples/histogram.rb +93 -91
  19. data/examples/histogram2.rb +109 -0
  20. data/examples/meta_example.rb +17 -6
  21. data/examples/midi_player.rb +5 -6
  22. data/examples/midi_player2.rb +83 -0
  23. data/examples/midi_player3.rb +84 -0
  24. data/examples/tetris.rb +15 -18
  25. data/examples/timer.rb +28 -31
  26. data/examples/timer2.rb +129 -0
  27. data/glimmer-dsl-libui.gemspec +0 -0
  28. data/lib/glimmer/libui/control_proxy/checkbox_proxy.rb +5 -0
  29. data/lib/glimmer/libui/control_proxy/color_button_proxy.rb +5 -0
  30. data/lib/glimmer/libui/control_proxy/combobox_proxy.rb +18 -2
  31. data/lib/glimmer/libui/control_proxy/date_time_picker_proxy.rb +5 -0
  32. data/lib/glimmer/libui/control_proxy/editable_combobox_proxy.rb +5 -0
  33. data/lib/glimmer/libui/control_proxy/font_button_proxy.rb +4 -0
  34. data/lib/glimmer/libui/control_proxy/menu_item_proxy/check_menu_item_proxy.rb +5 -0
  35. data/lib/glimmer/libui/control_proxy/menu_item_proxy/radio_menu_item_proxy.rb +17 -4
  36. data/lib/glimmer/libui/control_proxy/radio_buttons_proxy.rb +20 -0
  37. data/lib/glimmer/libui/control_proxy/slider_proxy.rb +38 -0
  38. data/lib/glimmer/libui/control_proxy/spinbox_proxy.rb +38 -0
  39. data/lib/glimmer/libui/control_proxy.rb +2 -2
  40. metadata +13 -2
@@ -2,106 +2,108 @@
2
2
 
3
3
  require 'glimmer-dsl-libui'
4
4
 
5
- include Glimmer
6
-
7
- X_OFF_LEFT = 20
8
- Y_OFF_TOP = 20
9
- X_OFF_RIGHT = 20
10
- Y_OFF_BOTTOM = 20
11
- POINT_RADIUS = 5
12
- COLOR_BLUE = 0x1E90FF
13
-
14
- @datapoints = 10.times.map {Random.new.rand(90)}
15
-
16
- def graph_size(area_width, area_height)
17
- graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
18
- graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
19
- [graph_width, graph_height]
20
- end
21
-
22
- def point_locations(width, height)
23
- xincr = width / 9.0 # 10 - 1 to make the last point be at the end
24
- yincr = height / 100.0
25
-
26
- @datapoints.each_with_index.map do |value, i|
27
- val = 100 - value
28
- [xincr * i, yincr * val]
5
+ class Histogram
6
+ include Glimmer
7
+
8
+ X_OFF_LEFT = 20
9
+ Y_OFF_TOP = 20
10
+ X_OFF_RIGHT = 20
11
+ Y_OFF_BOTTOM = 20
12
+ POINT_RADIUS = 5
13
+ COLOR_BLUE = Glimmer::LibUI.interpret_color(0x1E90FF)
14
+
15
+ attr_accessor :datapoints, :histogram_color
16
+
17
+ def initialize
18
+ @datapoints = 10.times.map {Random.new.rand(90)}
19
+ @histogram_color = COLOR_BLUE
29
20
  end
30
- end
31
-
32
- # method-based custom control representing a graph path
33
- def graph_path(width, height, should_extend, &block)
34
- locations = point_locations(width, height).flatten
35
- path {
36
- if should_extend
37
- polygon(locations + [width, height, 0, height])
38
- else
39
- polyline(locations)
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
+ def point_locations(width, height)
29
+ xincr = width / 9.0 # 10 - 1 to make the last point be at the end
30
+ yincr = height / 100.0
31
+
32
+ @datapoints.each_with_index.map do |value, i|
33
+ val = 100 - value
34
+ [xincr * i, yincr * val]
40
35
  end
41
-
42
- # apply a transform to the coordinate space for this path so (0, 0) is the top-left corner of the graph
43
- transform {
44
- translate X_OFF_LEFT, Y_OFF_TOP
45
- }
46
-
47
- block.call
48
- }
49
- end
50
-
51
- window('histogram example', 640, 480) {
52
- margined true
36
+ end
53
37
 
54
- horizontal_box {
55
- vertical_box {
56
- stretchy false
57
-
58
- 10.times do |i|
59
- spinbox(0, 100) { |sb|
60
- stretchy false
61
- value @datapoints[i]
62
-
63
- on_changed do
64
- @datapoints[i] = sb.value
65
- @area.queue_redraw_all
66
- end
67
- }
38
+ # method-based custom control representing a graph path
39
+ def graph_path(width, height, should_extend, &block)
40
+ locations = point_locations(width, height).flatten
41
+ path {
42
+ if should_extend
43
+ polygon(locations + [width, height, 0, height])
44
+ else
45
+ polyline(locations)
68
46
  end
69
47
 
70
- @color_button = color_button {
71
- stretchy false
72
- color COLOR_BLUE
73
-
74
- on_changed do
75
- @area.queue_redraw_all
76
- end
48
+ # apply a transform to the coordinate space for this path so (0, 0) is the top-left corner of the graph
49
+ transform {
50
+ translate X_OFF_LEFT, Y_OFF_TOP
77
51
  }
52
+
53
+ block.call
78
54
  }
79
-
80
- @area = area {
81
- on_draw do |area_draw_params|
82
- rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height]) {
83
- fill 0xFFFFFF
84
- }
85
-
86
- graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
55
+ end
56
+
57
+ def launch
58
+ window('histogram example', 640, 480) {
59
+ margined true
87
60
 
88
- figure(X_OFF_LEFT, Y_OFF_TOP) {
89
- line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
90
- line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
61
+ horizontal_box {
62
+ vertical_box {
63
+ stretchy false
91
64
 
92
- stroke 0x000000, thickness: 2, miter_limit: 10
93
- }
94
-
95
- # now create the fill for the graph below the graph line
96
- graph_path(graph_width, graph_height, true) {
97
- fill @color_button.color.merge(a: 0.5)
65
+ 10.times do |i|
66
+ spinbox(0, 100) { |sb|
67
+ stretchy false
68
+ value <=> [self, "datapoints[#{i}]", after_write: -> { @area.queue_redraw_all }]
69
+ }
70
+ end
71
+
72
+ color_button { |cb|
73
+ stretchy false
74
+ color <=> [self, :histogram_color, after_write: -> { @area.queue_redraw_all }]
75
+ }
98
76
  }
99
77
 
100
- # now draw the histogram line
101
- graph_path(graph_width, graph_height, false) {
102
- stroke @color_button.color.merge(thickness: 2, miter_limit: 10)
78
+ @area = area {
79
+ on_draw do |area_draw_params|
80
+ rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height]) {
81
+ fill 0xFFFFFF
82
+ }
83
+
84
+ graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
85
+
86
+ figure(X_OFF_LEFT, Y_OFF_TOP) {
87
+ line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
88
+ line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
89
+
90
+ stroke 0x000000, thickness: 2, miter_limit: 10
91
+ }
92
+
93
+ # now create the fill for the graph below the graph line
94
+ graph_path(graph_width, graph_height, true) {
95
+ fill @histogram_color.merge(a: 0.5)
96
+ }
97
+
98
+ # now draw the histogram line
99
+ graph_path(graph_width, graph_height, false) {
100
+ stroke @histogram_color.merge(thickness: 2, miter_limit: 10)
101
+ }
102
+ end
103
103
  }
104
- end
105
- }
106
- }
107
- }.show
104
+ }
105
+ }.show
106
+ end
107
+ end
108
+
109
+ Histogram.new.launch
@@ -0,0 +1,109 @@
1
+ # https://github.com/jamescook/libui-ruby/blob/master/example/histogram.rb
2
+
3
+ require 'glimmer-dsl-libui'
4
+
5
+ include Glimmer
6
+
7
+ X_OFF_LEFT = 20
8
+ Y_OFF_TOP = 20
9
+ X_OFF_RIGHT = 20
10
+ Y_OFF_BOTTOM = 20
11
+ POINT_RADIUS = 5
12
+ COLOR_BLUE = Glimmer::LibUI.interpret_color(0x1E90FF)
13
+
14
+ @datapoints = 10.times.map {Random.new.rand(90)}
15
+ @color = COLOR_BLUE
16
+
17
+ def graph_size(area_width, area_height)
18
+ graph_width = area_width - X_OFF_LEFT - X_OFF_RIGHT
19
+ graph_height = area_height - Y_OFF_TOP - Y_OFF_BOTTOM
20
+ [graph_width, graph_height]
21
+ end
22
+
23
+ def point_locations(width, height)
24
+ xincr = width / 9.0 # 10 - 1 to make the last point be at the end
25
+ yincr = height / 100.0
26
+
27
+ @datapoints.each_with_index.map do |value, i|
28
+ val = 100 - value
29
+ [xincr * i, yincr * val]
30
+ end
31
+ end
32
+
33
+ # method-based custom control representing a graph path
34
+ def graph_path(width, height, should_extend, &block)
35
+ locations = point_locations(width, height).flatten
36
+ path {
37
+ if should_extend
38
+ polygon(locations + [width, height, 0, height])
39
+ else
40
+ polyline(locations)
41
+ end
42
+
43
+ # apply a transform to the coordinate space for this path so (0, 0) is the top-left corner of the graph
44
+ transform {
45
+ translate X_OFF_LEFT, Y_OFF_TOP
46
+ }
47
+
48
+ block.call
49
+ }
50
+ end
51
+
52
+ window('histogram example', 640, 480) {
53
+ margined true
54
+
55
+ horizontal_box {
56
+ vertical_box {
57
+ stretchy false
58
+
59
+ 10.times do |i|
60
+ spinbox(0, 100) { |sb|
61
+ stretchy false
62
+ value @datapoints[i]
63
+
64
+ on_changed do
65
+ @datapoints[i] = sb.value
66
+ @area.queue_redraw_all
67
+ end
68
+ }
69
+ end
70
+
71
+ color_button { |cb|
72
+ stretchy false
73
+ color COLOR_BLUE
74
+
75
+ on_changed do
76
+ @color = cb.color
77
+ @area.queue_redraw_all
78
+ end
79
+ }
80
+ }
81
+
82
+ @area = area {
83
+ on_draw do |area_draw_params|
84
+ rectangle(0, 0, area_draw_params[:area_width], area_draw_params[:area_height]) {
85
+ fill 0xFFFFFF
86
+ }
87
+
88
+ graph_width, graph_height = *graph_size(area_draw_params[:area_width], area_draw_params[:area_height])
89
+
90
+ figure(X_OFF_LEFT, Y_OFF_TOP) {
91
+ line(X_OFF_LEFT, Y_OFF_TOP + graph_height)
92
+ line(X_OFF_LEFT + graph_width, Y_OFF_TOP + graph_height)
93
+
94
+ stroke 0x000000, thickness: 2, miter_limit: 10
95
+ }
96
+
97
+ # now create the fill for the graph below the graph line
98
+ graph_path(graph_width, graph_height, true) {
99
+ fill @color.merge(a: 0.5)
100
+ }
101
+
102
+ # now draw the histogram line
103
+ graph_path(graph_width, graph_height, false) {
104
+ stroke @color.merge(thickness: 2, miter_limit: 10)
105
+ }
106
+ end
107
+ }
108
+ }
109
+ }.show
@@ -24,18 +24,28 @@ class MetaExample
24
24
  @examples
25
25
  end
26
26
 
27
+ def basic_examples
28
+ examples.select {|example| example.start_with?('Basic') || ADDITIONAL_BASIC_EXAMPLES.include?(example) }
29
+ end
30
+
31
+ def advanced_examples
32
+ examples - basic_examples
33
+ end
34
+
27
35
  def examples_with_versions
28
- examples.map do |example|
29
- version_count_for(example) > 1 ? "#{example} (#{version_count_for(example)} versions)" : example
30
- end
36
+ append_versions(examples)
31
37
  end
32
38
 
33
39
  def basic_examples_with_versions
34
- examples_with_versions.select {|example| example.start_with?('Basic') || ADDITIONAL_BASIC_EXAMPLES.include?(example) }
40
+ append_versions(basic_examples)
35
41
  end
36
42
 
37
43
  def advanced_examples_with_versions
38
- examples_with_versions - basic_examples_with_versions
44
+ append_versions(advanced_examples)
45
+ end
46
+
47
+ def append_versions(examples)
48
+ examples.map { |example| version_count_for(example) > 1 ? "#{example} (#{version_count_for(example)} versions)" : example }
39
49
  end
40
50
 
41
51
  def file_path_for(example)
@@ -72,7 +82,7 @@ class MetaExample
72
82
  end
73
83
 
74
84
  def launch
75
- window('Meta-Example', 700, 500) {
85
+ window('Meta-Example', 1000, 500) {
76
86
  margined true
77
87
 
78
88
  horizontal_box {
@@ -107,6 +117,7 @@ class MetaExample
107
117
  @advanced_example_radio_buttons = radio_buttons {
108
118
  stretchy false
109
119
  items advanced_examples_with_versions
120
+ selected -1
110
121
 
111
122
  on_selected do
112
123
  @selected_example_index = examples_with_versions.index(advanced_examples_with_versions[@advanced_example_radio_buttons.selected])
@@ -6,6 +6,8 @@ class TinyMidiPlayer
6
6
  include Glimmer
7
7
 
8
8
  VERSION = '0.0.1'
9
+
10
+ attr_accessor :selected_file
9
11
 
10
12
  def initialize
11
13
  @pid = nil
@@ -68,13 +70,10 @@ class TinyMidiPlayer
68
70
  }
69
71
  }
70
72
 
71
- combobox { |c|
73
+ combobox {
72
74
  items @midi_files.map { |path| File.basename(path) }
73
-
74
- on_selected do
75
- @selected_file = @midi_files[c.selected]
76
- play_midi if @th&.alive?
77
- end
75
+ # data-bind selected item (String) to self.selected_file with on-read/on-write converters and after_write operation
76
+ selected_item <=> [self, :selected_file, on_read: ->(f) {File.basename(f.to_s)}, on_write: ->(f) {File.join(@music_directory, f)}, after_write: -> { play_midi if @th&.alive? }]
78
77
  }
79
78
  }
80
79
  }.show
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'glimmer-dsl-libui'
4
+
5
+ class TinyMidiPlayer
6
+ include Glimmer
7
+
8
+ VERSION = '0.0.1'
9
+
10
+ attr_accessor :selected_file
11
+
12
+ def initialize
13
+ @pid = nil
14
+ @music_directory = File.expand_path('../sounds', __dir__)
15
+ @midi_files = Dir.glob(File.join(@music_directory, '**/*.mid'))
16
+ .sort_by { |path| File.basename(path) }
17
+ at_exit { stop_midi }
18
+ create_gui
19
+ end
20
+
21
+ def stop_midi
22
+ if @pid
23
+ Process.kill(:SIGKILL, @pid) if @th.alive?
24
+ @pid = nil
25
+ end
26
+ end
27
+
28
+ def play_midi
29
+ stop_midi
30
+ if @pid.nil? && @selected_file
31
+ begin
32
+ @pid = spawn "timidity #{@selected_file}"
33
+ @th = Process.detach @pid
34
+ rescue Errno::ENOENT
35
+ warn 'Timidty++ not found. Please install Timidity++.'
36
+ warn 'https://sourceforge.net/projects/timidity/'
37
+ end
38
+ end
39
+ end
40
+
41
+ def show_version
42
+ msg_box('Tiny Midi Player',
43
+ "Written in Ruby\n" \
44
+ "https://github.com/kojix2/libui\n" \
45
+ "Version #{VERSION}")
46
+ end
47
+
48
+ def create_gui
49
+ menu('Help') {
50
+ menu_item('Version') {
51
+ on_clicked do
52
+ show_version
53
+ end
54
+ }
55
+ }
56
+ window('Tiny Midi Player', 200, 50) {
57
+ horizontal_box {
58
+ vertical_box {
59
+ stretchy false
60
+
61
+ button('▶') {
62
+ on_clicked do
63
+ play_midi
64
+ end
65
+ }
66
+ button('■') {
67
+ on_clicked do
68
+ stop_midi
69
+ end
70
+ }
71
+ }
72
+
73
+ combobox { |c|
74
+ items @midi_files.map { |path| File.basename(path) }
75
+ # data-bind selected index (Integer) to self.selected_file with on-read/on-write converters and after_write operation
76
+ selected <=> [self, :selected_file, on_read: ->(f) {@midi_files.index(f)}, on_write: ->(i) {@midi_files[i]}, after_write: -> { play_midi if @th&.alive? }]
77
+ }
78
+ }
79
+ }.show
80
+ end
81
+ end
82
+
83
+ TinyMidiPlayer.new
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'glimmer-dsl-libui'
4
+
5
+ class TinyMidiPlayer
6
+ include Glimmer
7
+
8
+ VERSION = '0.0.1'
9
+
10
+ def initialize
11
+ @pid = nil
12
+ @music_directory = File.expand_path('../sounds', __dir__)
13
+ @midi_files = Dir.glob(File.join(@music_directory, '**/*.mid'))
14
+ .sort_by { |path| File.basename(path) }
15
+ at_exit { stop_midi }
16
+ create_gui
17
+ end
18
+
19
+ def stop_midi
20
+ if @pid
21
+ Process.kill(:SIGKILL, @pid) if @th.alive?
22
+ @pid = nil
23
+ end
24
+ end
25
+
26
+ def play_midi
27
+ stop_midi
28
+ if @pid.nil? && @selected_file
29
+ begin
30
+ @pid = spawn "timidity #{@selected_file}"
31
+ @th = Process.detach @pid
32
+ rescue Errno::ENOENT
33
+ warn 'Timidty++ not found. Please install Timidity++.'
34
+ warn 'https://sourceforge.net/projects/timidity/'
35
+ end
36
+ end
37
+ end
38
+
39
+ def show_version
40
+ msg_box('Tiny Midi Player',
41
+ "Written in Ruby\n" \
42
+ "https://github.com/kojix2/libui\n" \
43
+ "Version #{VERSION}")
44
+ end
45
+
46
+ def create_gui
47
+ menu('Help') {
48
+ menu_item('Version') {
49
+ on_clicked do
50
+ show_version
51
+ end
52
+ }
53
+ }
54
+ window('Tiny Midi Player', 200, 50) {
55
+ horizontal_box {
56
+ vertical_box {
57
+ stretchy false
58
+
59
+ button('▶') {
60
+ on_clicked do
61
+ play_midi
62
+ end
63
+ }
64
+ button('■') {
65
+ on_clicked do
66
+ stop_midi
67
+ end
68
+ }
69
+ }
70
+
71
+ combobox { |c|
72
+ items @midi_files.map { |path| File.basename(path) }
73
+
74
+ on_selected do
75
+ @selected_file = @midi_files[c.selected]
76
+ play_midi if @th&.alive?
77
+ end
78
+ }
79
+ }
80
+ }.show
81
+ end
82
+ end
83
+
84
+ TinyMidiPlayer.new
data/examples/tetris.rb CHANGED
@@ -109,22 +109,23 @@ class Tetris
109
109
  menu('Game') {
110
110
  @pause_menu_item = check_menu_item('Pause') {
111
111
  enabled false
112
-
113
- on_clicked do
114
- @game.paused = @pause_menu_item.checked?
115
- end
112
+ checked <=> [@game, :paused]
116
113
  }
114
+
117
115
  menu_item('Restart') {
118
116
  on_clicked do
119
117
  @game.restart!
120
118
  end
121
119
  }
120
+
122
121
  separator_menu_item
122
+
123
123
  menu_item('Exit') {
124
124
  on_clicked do
125
125
  exit(0)
126
126
  end
127
127
  }
128
+
128
129
  quit_menu_item if OS.mac?
129
130
  }
130
131
 
@@ -134,6 +135,7 @@ class Tetris
134
135
  show_high_scores
135
136
  end
136
137
  }
138
+
137
139
  menu_item('Clear High Scores') {
138
140
  on_clicked {
139
141
  @game.clear_high_scores!
@@ -142,22 +144,16 @@ class Tetris
142
144
  }
143
145
 
144
146
  menu('Options') {
145
- radio_menu_item('Instant Down on Up Arrow') {
146
- on_clicked do
147
- @game.instant_down_on_up = true
148
- end
147
+ radio_menu_item('Instant Down on Up Arrow') { |r|
148
+ checked <=> [@game, :instant_down_on_up]
149
149
  }
150
- radio_menu_item('Rotate Right on Up Arrow') {
151
- on_clicked do
152
- @game.rotate_right_on_up = true
153
- end
150
+
151
+ radio_menu_item('Rotate Right on Up Arrow') { |r|
152
+ checked <=> [@game, :rotate_right_on_up]
154
153
  }
155
- radio_menu_item('Rotate Left on Up Arrow') {
156
- checked true
157
-
158
- on_clicked do
159
- @game.rotate_left_on_up = true
160
- end
154
+
155
+ radio_menu_item('Rotate Left on Up Arrow') { |r|
156
+ checked <=> [@game, :rotate_left_on_up]
161
157
  }
162
158
  }
163
159
 
@@ -169,6 +165,7 @@ class Tetris
169
165
  end
170
166
  }
171
167
  end
168
+
172
169
  menu_item('About') {
173
170
  on_clicked do
174
171
  show_about_dialog