glimmer-dsl-libui 0.2.8 → 0.2.12

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.8
1
+ 0.2.12
@@ -7,14 +7,15 @@ window('Area Gallery', 400, 400) {
7
7
  path { # declarative stable path
8
8
  square(0, 0, 100)
9
9
  square(100, 100, 400)
10
-
10
+
11
11
  fill r: 102, g: 102, b: 204
12
12
  }
13
13
  path { # declarative stable path
14
14
  rectangle(0, 100, 100, 400)
15
15
  rectangle(100, 0, 400, 100)
16
-
17
- fill r: 204, g: 102, b: 204
16
+
17
+ # linear gradient (has x0, y0, x1, y1, and stops)
18
+ fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
18
19
  }
19
20
  path { # declarative stable path
20
21
  figure(100, 100) {
@@ -40,17 +41,24 @@ window('Area Gallery', 400, 400) {
40
41
  fill r: 202, g: 102, b: 204, a: 0.5
41
42
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
42
43
  }
44
+ path { # declarative stable path
45
+ arc(400, 220, 180, 90, 90, false)
46
+
47
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
48
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
49
+ stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
50
+ }
43
51
  path { # declarative stable path
44
52
  circle(200, 200, 90)
45
53
 
46
54
  fill r: 202, g: 102, b: 204, a: 0.5
47
55
  stroke r: 0, g: 0, b: 0, thickness: 2
48
56
  }
49
- path { # declarative stable path
50
- arc(400, 220, 180, 90, 90, false)
51
-
52
- fill r: 204, g: 102, b: 204, a: 0.5
53
- stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
57
+ text(160, 40, 100) { # x, y, width
58
+ string('Area Gallery') {
59
+ font family: 'Times', size: 14
60
+ color :black
61
+ }
54
62
  }
55
63
 
56
64
  on_mouse_event do |area_mouse_event|
@@ -32,7 +32,8 @@ window('Area Gallery', 400, 400) {
32
32
  height 100
33
33
  }
34
34
 
35
- fill r: 204, g: 102, b: 204
35
+ # linear gradient (has x0, y0, x1, y1, and stops)
36
+ fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
36
37
  }
37
38
  path { # declarative stable path
38
39
  figure {
@@ -94,16 +95,6 @@ window('Area Gallery', 400, 400) {
94
95
  fill r: 202, g: 102, b: 204, a: 0.5
95
96
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
96
97
  }
97
- path { # declarative stable path
98
- circle {
99
- x_center 200
100
- y_center 200
101
- radius 90
102
- }
103
-
104
- fill r: 202, g: 102, b: 204, a: 0.5
105
- stroke r: 0, g: 0, b: 0, thickness: 2
106
- }
107
98
  path { # declarative stable path
108
99
  arc {
109
100
  x_center 400
@@ -114,9 +105,32 @@ window('Area Gallery', 400, 400) {
114
105
  is_negative false
115
106
  }
116
107
 
117
- fill r: 204, g: 102, b: 204, a: 0.5
108
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
109
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
118
110
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
119
111
  }
112
+ path { # declarative stable path
113
+ circle {
114
+ x_center 200
115
+ y_center 200
116
+ radius 90
117
+ }
118
+
119
+ fill r: 202, g: 102, b: 204, a: 0.5
120
+ stroke r: 0, g: 0, b: 0, thickness: 2
121
+ }
122
+ text {
123
+ x 160
124
+ y 40
125
+ width 100
126
+
127
+ string {
128
+ font family: 'Times', size: 14
129
+ color :black
130
+
131
+ 'Area Gallery'
132
+ }
133
+ }
120
134
 
121
135
  on_mouse_event do |area_mouse_event|
122
136
  p area_mouse_event
@@ -15,7 +15,8 @@ window('Area Gallery', 400, 400) {
15
15
  rectangle(0, 100, 100, 400)
16
16
  rectangle(100, 0, 400, 100)
17
17
 
18
- fill r: 204, g: 102, b: 204
18
+ # linear gradient (has x0, y0, x1, y1, and stops)
19
+ fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
19
20
  }
20
21
  path { # a dynamic path is added semi-declaratively inside on_draw block
21
22
  figure(100, 100) {
@@ -41,17 +42,24 @@ window('Area Gallery', 400, 400) {
41
42
  fill r: 202, g: 102, b: 204, a: 0.5
42
43
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
43
44
  }
45
+ path { # a dynamic path is added semi-declaratively inside on_draw block
46
+ arc(400, 220, 180, 90, 90, false)
47
+
48
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
49
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
50
+ stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
51
+ }
44
52
  path { # a dynamic path is added semi-declaratively inside on_draw block
45
53
  circle(200, 200, 90)
46
54
 
47
55
  fill r: 202, g: 102, b: 204, a: 0.5
48
56
  stroke r: 0, g: 0, b: 0, thickness: 2
49
57
  }
50
- path { # a dynamic path is added semi-declaratively inside on_draw block
51
- arc(400, 220, 180, 90, 90, false)
52
-
53
- fill r: 204, g: 102, b: 204, a: 0.5
54
- stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
58
+ text(160, 40, 100) { # x, y, width
59
+ string('Area Gallery') {
60
+ font family: 'Times', size: 14
61
+ color :black
62
+ }
55
63
  }
56
64
  end
57
65
 
@@ -33,7 +33,8 @@ window('Area Gallery', 400, 400) {
33
33
  height 100
34
34
  }
35
35
 
36
- fill r: 204, g: 102, b: 204
36
+ # linear gradient (has x0, y0, x1, y1, and stops)
37
+ fill x0: 10, y0: 10, x1: 350, y1: 350, stops: [{pos: 0.25, r: 204, g: 102, b: 204}, {pos: 0.75, r: 102, g: 102, b: 204}]
37
38
  }
38
39
  path { # a dynamic path is added semi-declaratively inside on_draw block
39
40
  figure {
@@ -95,16 +96,6 @@ window('Area Gallery', 400, 400) {
95
96
  fill r: 202, g: 102, b: 204, a: 0.5
96
97
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
97
98
  }
98
- path { # a dynamic path is added semi-declaratively inside on_draw block
99
- circle {
100
- x_center 200
101
- y_center 200
102
- radius 90
103
- }
104
-
105
- fill r: 202, g: 102, b: 204, a: 0.5
106
- stroke r: 0, g: 0, b: 0, thickness: 2
107
- }
108
99
  path { # a dynamic path is added semi-declaratively inside on_draw block
109
100
  arc {
110
101
  x_center 400
@@ -115,9 +106,32 @@ window('Area Gallery', 400, 400) {
115
106
  is_negative false
116
107
  }
117
108
 
118
- fill r: 204, g: 102, b: 204, a: 0.5
109
+ # radial gradient (has an outer_radius in addition to x0, y0, x1, y1, and stops)
110
+ fill outer_radius: 90, x0: 0, y0: 0, x1: 500, y1: 500, stops: [{pos: 0.25, r: 102, g: 102, b: 204, a: 0.5}, {pos: 0.75, r: 204, g: 102, b: 204}]
119
111
  stroke r: 0, g: 0, b: 0, thickness: 2, dashes: [50, 10, 10, 10], dash_phase: -50.0
120
112
  }
113
+ path { # a dynamic path is added semi-declaratively inside on_draw block
114
+ circle {
115
+ x_center 200
116
+ y_center 200
117
+ radius 90
118
+ }
119
+
120
+ fill r: 202, g: 102, b: 204, a: 0.5
121
+ stroke r: 0, g: 0, b: 0, thickness: 2
122
+ }
123
+ text {
124
+ x 160
125
+ y 40
126
+ width 100
127
+
128
+ string {
129
+ font family: 'Times', size: 14
130
+ color :black
131
+
132
+ 'Area Gallery'
133
+ }
134
+ }
121
135
  end
122
136
 
123
137
  on_mouse_event do |area_mouse_event|
@@ -16,7 +16,6 @@ class BasicDrawText
16
16
  else
17
17
  color r: 0, g: 128, b: 0, a: 0.7
18
18
  end
19
-
20
19
  block.call + "\n\n"
21
20
  }
22
21
  end
@@ -27,6 +27,7 @@ window('Animal sounds', 300, 200) {
27
27
 
28
28
  on_changed do |row, type, row_data|
29
29
  puts "Row #{row} #{type}: #{row_data}"
30
+ $stdout.flush
30
31
  end
31
32
  }
32
33
  }
@@ -26,7 +26,7 @@ window('Task Progress', 300, 200) {
26
26
 
27
27
  on_clicked do
28
28
  data.each_with_index do |row_data, row|
29
- data[row] = [row_data[0], 100] # automatically updates table due to implicit data-binding
29
+ data[row][1] = 100 # automatically updates table due to implicit data-binding
30
30
  end
31
31
  end
32
32
  }
@@ -6,6 +6,8 @@ include Glimmer
6
6
 
7
7
  window('color button', 230) {
8
8
  color_button { |cb|
9
+ color :blue
10
+
9
11
  on_changed do
10
12
  rgba = cb.color
11
13
  p rgba
@@ -23,10 +23,12 @@ window('Editable animal sounds', 300, 200) {
23
23
 
24
24
  on_changed do |row, type, row_data| # fires on all changes (even ones happening through data array)
25
25
  puts "Row #{row} #{type}: #{row_data}"
26
+ $stdout.flush
26
27
  end
27
28
 
28
29
  on_edited do |row, row_data| # only fires on direct table editing
29
30
  puts "Row #{row} edited: #{row_data}"
31
+ $stdout.flush
30
32
  end
31
33
  }
32
34
  }
data/examples/form.rb CHANGED
@@ -16,11 +16,21 @@ window('Form') {
16
16
  @last_name_entry = entry {
17
17
  label 'Last Name' # label property is available when control is nested under form
18
18
  }
19
+
20
+ @phone_entry = entry {
21
+ label 'Phone' # label property is available when control is nested under form
22
+ }
23
+
24
+ @email_entry = entry {
25
+ label 'Email' # label property is available when control is nested under form
26
+ }
19
27
  }
20
28
 
21
- button('Display Name') {
29
+ button('Display Info') {
30
+ stretchy false
31
+
22
32
  on_clicked do
23
- msg_box('Name', "#{@first_name_entry.text} #{@last_name_entry.text}")
33
+ msg_box('Info', "#{@first_name_entry.text} #{@last_name_entry.text} has phone #{@phone_entry.text} and email #{@email_entry.text}")
24
34
  end
25
35
  }
26
36
  }
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
3
1
  require 'glimmer-dsl-libui'
4
2
  require 'facets'
3
+ require 'fileutils'
5
4
 
6
5
  class MetaExample
7
6
  include Glimmer
@@ -42,6 +41,18 @@ class MetaExample
42
41
  examples[@selected_example_index]
43
42
  end
44
43
 
44
+ def run_example(example)
45
+ command = "ruby -r #{glimmer_dsl_libui_file} #{example} 2>&1"
46
+ result = ''
47
+ IO.popen(command) do |f|
48
+ f.each_line do |line|
49
+ result << line
50
+ puts line
51
+ end
52
+ end
53
+ msg_box('Error Running Example', result) if result.downcase.include?('error')
54
+ end
55
+
45
56
  def launch
46
57
  window('Meta-Example', 700, 500) {
47
58
  margined true
@@ -50,16 +61,16 @@ class MetaExample
50
61
  vertical_box {
51
62
  stretchy false
52
63
 
53
- @rbs = radio_buttons {
64
+ @example_radio_buttons = radio_buttons {
54
65
  stretchy false
55
66
  items examples_with_versions
56
67
  selected @selected_example_index
57
68
 
58
69
  on_selected do
59
- @selected_example_index = @rbs.selected
70
+ @selected_example_index = @example_radio_buttons.selected
60
71
  example = selected_example
61
- @nwme.text = File.read(file_path_for(example))
62
- @sb.value = 1
72
+ @code_entry.text = File.read(file_path_for(example))
73
+ @version_spinbox.value = 1
63
74
  end
64
75
  }
65
76
 
@@ -68,17 +79,17 @@ class MetaExample
68
79
  stretchy false
69
80
  }
70
81
 
71
- @sb = spinbox(1, 100) {
82
+ @version_spinbox = spinbox(1, 100) {
72
83
  value 1
73
84
 
74
85
  on_changed do
75
86
  example = selected_example
76
- if @sb.value > version_count_for(example)
77
- @sb.value -= 1
87
+ if @version_spinbox.value > version_count_for(example)
88
+ @version_spinbox.value -= 1
78
89
  else
79
- version_number = @sb.value == 1 ? '' : @sb.value
90
+ version_number = @version_spinbox.value == 1 ? '' : @version_spinbox.value
80
91
  example = "#{selected_example}#{version_number}"
81
- @nwme.text = File.read(file_path_for(example))
92
+ @code_entry.text = File.read(file_path_for(example))
82
93
  end
83
94
  end
84
95
  }
@@ -90,25 +101,29 @@ class MetaExample
90
101
  button('Launch') {
91
102
  on_clicked do
92
103
  begin
93
- meta_example_file = File.join(Dir.home, '.meta_example.rb')
94
- File.write(meta_example_file, @nwme.text)
95
- result = `ruby -r #{glimmer_dsl_libui_file} #{meta_example_file} 2>&1`
96
- msg_box('Error Running Example', result) if result.include?('error')
104
+ parent_dir = File.join(Dir.home, '.glimmer-dsl-libui', 'examples')
105
+ FileUtils.mkdir_p(parent_dir)
106
+ example_file = File.join(parent_dir, "#{selected_example.underscore}.rb")
107
+ File.write(example_file, @code_entry.text)
108
+ FileUtils.cp_r(File.expand_path('../icons', __dir__), File.dirname(parent_dir))
109
+ FileUtils.cp_r(File.expand_path('../sounds', __dir__), File.dirname(parent_dir))
110
+ run_example(example_file)
97
111
  rescue => e
112
+ puts e.full_message
98
113
  puts 'Unable to write code changes! Running original example...'
99
- system "ruby -r #{glimmer_dsl_libui_file} #{file_path_for(selected_example)}"
114
+ run_example(file_path_for(selected_example))
100
115
  end
101
116
  end
102
117
  }
103
118
  button('Reset') {
104
119
  on_clicked do
105
- @nwme.text = File.read(file_path_for(selected_example))
120
+ @code_entry.text = File.read(file_path_for(selected_example))
106
121
  end
107
122
  }
108
123
  }
109
124
  }
110
125
 
111
- @nwme = non_wrapping_multiline_entry {
126
+ @code_entry = non_wrapping_multiline_entry {
112
127
  text File.read(file_path_for(selected_example))
113
128
  }
114
129
  }
@@ -0,0 +1,97 @@
1
+ require 'glimmer-dsl-libui'
2
+ require 'facets'
3
+
4
+ include Glimmer
5
+
6
+ Address = Struct.new(:street, :p_o_box, :city, :state, :zip_code)
7
+
8
+ def form_field(model, property)
9
+ property = property.to_s
10
+ entry { |e|
11
+ label property.underscore.split('_').map(&:capitalize).join(' ')
12
+ text model.send(property).to_s
13
+
14
+ on_changed do
15
+ model.send("#{property}=", e.text)
16
+ end
17
+ }
18
+ end
19
+
20
+ def address_form(address)
21
+ form {
22
+ form_field(address, :street)
23
+ form_field(address, :p_o_box)
24
+ form_field(address, :city)
25
+ form_field(address, :state)
26
+ form_field(address, :zip_code)
27
+ }
28
+ end
29
+
30
+ def label_pair(model, attribute, value)
31
+ name_label = nil
32
+ value_label = nil
33
+ horizontal_box {
34
+ name_label = label(attribute.to_s.underscore.split('_').map(&:capitalize).join(' '))
35
+ value_label = label(value.to_s)
36
+ }
37
+ Glimmer::DataBinding::Observer.proc do
38
+ value_label.text = model.send(attribute)
39
+ end.observe(model, attribute)
40
+ end
41
+
42
+ def address(address)
43
+ vertical_box {
44
+ address.each_pair do |attribute, value|
45
+ label_pair(address, attribute, value)
46
+ end
47
+ }
48
+ end
49
+
50
+ address1 = Address.new('123 Main St', '23923', 'Denver', 'Colorado', '80014')
51
+ address2 = Address.new('2038 Park Ave', '83272', 'Boston', 'Massachusetts', '02101')
52
+
53
+ window('Method-Based Custom Keyword') {
54
+ margined true
55
+
56
+ horizontal_box {
57
+ vertical_box {
58
+ label('Address 1') {
59
+ stretchy false
60
+ }
61
+
62
+ address_form(address1)
63
+
64
+ horizontal_separator {
65
+ stretchy false
66
+ }
67
+
68
+ label('Address 1 (Saved)') {
69
+ stretchy false
70
+ }
71
+
72
+ address(address1)
73
+ }
74
+
75
+ vertical_separator {
76
+ stretchy false
77
+ }
78
+
79
+ vertical_box {
80
+ label('Address 2') {
81
+ stretchy false
82
+ }
83
+
84
+ address_form(address2)
85
+
86
+ horizontal_separator {
87
+ stretchy false
88
+ }
89
+
90
+ label('Address 2 (Saved)') {
91
+ stretchy false
92
+ }
93
+
94
+ address(address2)
95
+ }
96
+ }
97
+ }.show
Binary file
@@ -32,11 +32,18 @@ module Glimmer
32
32
 
33
33
  def can_interpret?(parent, keyword, *args, &block)
34
34
  super and
35
- parent.is_a?(Glimmer::LibUI::ControlProxy::TextProxy)
35
+ (
36
+ parent.is_a?(Glimmer::LibUI::ControlProxy::TextProxy) or
37
+ parent.is_a?(Glimmer::LibUI::AttributedString)
38
+ )
36
39
  end
37
40
 
38
41
  def interpret(parent, keyword, *args, &block)
39
- Glimmer::LibUI::AttributedString.new(keyword, parent, args, &block)
42
+ if parent.is_a?(Glimmer::LibUI::ControlProxy::TextProxy)
43
+ Glimmer::LibUI::AttributedString.new(keyword, parent, args, &block)
44
+ else
45
+ parent.string = args.join
46
+ end
40
47
  end
41
48
 
42
49
  def add_content(parent, keyword, *args, &block)
@@ -27,7 +27,6 @@ require 'glimmer/libui/control_proxy/transformable'
27
27
  module Glimmer
28
28
  module LibUI
29
29
  class AttributedString
30
- attr_accessor :string
31
30
  attr_reader :block, :keyword, :parent_proxy, :args
32
31
 
33
32
  def initialize(keyword, parent_proxy, args, &block)
@@ -39,6 +38,17 @@ module Glimmer
39
38
  post_add_content if @block.nil?
40
39
  end
41
40
 
41
+ def string(value = nil)
42
+ if value.nil?
43
+ @string
44
+ else
45
+ @string = value
46
+ redraw
47
+ end
48
+ end
49
+ alias string= string
50
+ alias set_string string
51
+
42
52
  def font(value = nil)
43
53
  if value.nil?
44
54
  @font
@@ -106,7 +116,7 @@ module Glimmer
106
116
  alias set_open_type_features open_type_features
107
117
 
108
118
  def post_add_content
109
- block_result = block&.call
119
+ block_result = @block&.call
110
120
  @string = block_result if block_result.is_a?(String)
111
121
  @parent_proxy&.post_initialize_child(self)
112
122
  end
@@ -69,7 +69,6 @@ module Glimmer
69
69
  @fill ||= {}
70
70
  else
71
71
  @fill = Glimmer::LibUI.interpret_color(args)
72
- @fill[:a] = 1.0 if @fill.is_a?(Hash) && @fill[:a].nil?
73
72
  @parent_proxy&.queue_redraw_all
74
73
  end
75
74
  @fill.tap do
@@ -94,7 +93,6 @@ module Glimmer
94
93
  @stroke ||= {}
95
94
  else
96
95
  @stroke = Glimmer::LibUI.interpret_color(args)
97
- @stroke[:a] = 1.0 if @stroke.is_a?(Hash) && @stroke[:a].nil?
98
96
  @parent_proxy&.queue_redraw_all
99
97
  end
100
98
  @stroke.tap do
@@ -149,11 +147,38 @@ module Glimmer
149
147
  end
150
148
 
151
149
  def init_draw_brush(draw_brush, draw_brush_args)
150
+ if draw_brush_args[:r] || draw_brush_args[:g] || draw_brush_args[:b] || draw_brush_args[:a]
151
+ draw_brush_args[:type] ||= :solid
152
+ elsif draw_brush_args[:outer_radius]
153
+ draw_brush_args[:type] ||= :radial_gradient
154
+ else
155
+ draw_brush_args[:type] ||= :linear_gradient
156
+ end
152
157
  draw_brush.Type = Glimmer::LibUI.enum_symbol_to_value(:draw_brush_type, draw_brush_args[:type])
153
- draw_brush.R = (draw_brush_args[:r] || draw_brush_args[:red]).to_f / 255.0
154
- draw_brush.G = (draw_brush_args[:g] || draw_brush_args[:green]).to_f / 255.0
155
- draw_brush.B = (draw_brush_args[:b] || draw_brush_args[:blue]).to_f / 255.0
156
- draw_brush.A = (draw_brush_args[:a] || draw_brush_args[:alpha])
158
+ if draw_brush.Type == 0
159
+ draw_brush.R = (draw_brush_args[:r] || draw_brush_args[:red]).to_f / 255.0
160
+ draw_brush.G = (draw_brush_args[:g] || draw_brush_args[:green]).to_f / 255.0
161
+ draw_brush.B = (draw_brush_args[:b] || draw_brush_args[:blue]).to_f / 255.0
162
+ draw_brush.A = (draw_brush_args[:a] || draw_brush_args[:alpha] || 1.0)
163
+ else
164
+ draw_brush.X0 = draw_brush_args[:x0].to_f
165
+ draw_brush.Y0 = draw_brush_args[:y0].to_f
166
+ draw_brush.X1 = draw_brush_args[:x1].to_f
167
+ draw_brush.Y1 = draw_brush_args[:y1].to_f
168
+ draw_brush.OuterRadius = draw_brush_args[:outer_radius].to_f if draw_brush.Type == 2
169
+ stop_structs = draw_brush_args[:stops].to_a.map do |stop|
170
+ ::LibUI::FFI::DrawBrushGradientStop.malloc.tap do |stop_struct|
171
+ stop_struct.Pos = stop[:pos].to_f
172
+ stop_color = Glimmer::LibUI.interpret_color(stop)
173
+ stop_struct.R = stop_color[:r].to_f / 255.0
174
+ stop_struct.G = stop_color[:g].to_f / 255.0
175
+ stop_struct.B = stop_color[:b].to_f / 255.0
176
+ stop_struct.A = stop_color[:a] || 1.0
177
+ end
178
+ end
179
+ draw_brush.NumStops = stop_structs.count
180
+ draw_brush.Stops = stop_structs.map(&:to_ptr).map(&:to_s).reduce(:+)
181
+ end
157
182
  end
158
183
  end
159
184
  end
@@ -83,7 +83,7 @@ module Glimmer
83
83
  else
84
84
  @cell_rows = rows
85
85
  @cell_rows.tap do
86
- @last_cell_rows = @cell_rows.clone
86
+ @last_cell_rows = array_deep_clone(@cell_rows)
87
87
  Glimmer::DataBinding::Observer.proc do
88
88
  if @cell_rows.size < @last_cell_rows.size && @last_cell_rows.include_all?(*@cell_rows)
89
89
  @last_cell_rows.array_diff_indexes(@cell_rows).reverse.each do |row|
@@ -103,8 +103,8 @@ module Glimmer
103
103
  end
104
104
  end
105
105
  end
106
- @last_cell_rows = @cell_rows.clone
107
- end.observe(self, :cell_rows)
106
+ @last_cell_rows = array_deep_clone(@cell_rows)
107
+ end.observe(self, :cell_rows, recursive: true)
108
108
  end
109
109
  end
110
110
  end
@@ -205,6 +205,16 @@ module Glimmer
205
205
  @next_column_index ||= -1
206
206
  @next_column_index += 1
207
207
  end
208
+
209
+ def array_deep_clone(array_or_object)
210
+ if array_or_object.is_a?(Array)
211
+ array_or_object.map do |element|
212
+ array_deep_clone(element)
213
+ end
214
+ else
215
+ array_or_object.clone
216
+ end
217
+ end
208
218
  end
209
219
  end
210
220
  end
data/lib/glimmer/libui.rb CHANGED
@@ -44,8 +44,8 @@ module Glimmer
44
44
  value = value[0...-1]
45
45
  end
46
46
  value = value.first if value.is_a?(Array) && value.size == 1
47
- value = value.to_s if value.is_a?(Symbol)
48
47
  value = value[:color] if value.is_a?(Hash) && value[:color]
48
+ value = value.to_s if value.is_a?(Symbol)
49
49
  result = if value.is_a?(Array)
50
50
  old_value = value
51
51
  value = {