glimmer-dsl-libui 0.2.10 → 0.2.14

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.10
1
+ 0.2.14
data/bin/girb CHANGED
File without changes
data/bin/girb_runner.rb CHANGED
@@ -27,7 +27,7 @@ require_relative '../lib/glimmer-dsl-libui'
27
27
 
28
28
  include Glimmer
29
29
 
30
- GIRB_RUNNER_EXIT_FILE = "#{Etc.getpwuid.dir}/.girb_runner_exit"
30
+ GIRB_RUNNER_EXIT_FILE = "#{Dir.home}/.girb_runner_exit"
31
31
  FileUtils.rm_rf GIRB_RUNNER_EXIT_FILE
32
32
 
33
33
  @exit_method = method(:exit)
@@ -55,11 +55,9 @@ window('Area Gallery', 400, 400) {
55
55
  stroke r: 0, g: 0, b: 0, thickness: 2
56
56
  }
57
57
  text(160, 40, 100) { # x, y, width
58
- string {
58
+ string('Area Gallery') {
59
59
  font family: 'Times', size: 14
60
60
  color :black
61
-
62
- 'Area Gallery'
63
61
  }
64
62
  }
65
63
 
@@ -56,11 +56,9 @@ window('Area Gallery', 400, 400) {
56
56
  stroke r: 0, g: 0, b: 0, thickness: 2
57
57
  }
58
58
  text(160, 40, 100) { # x, y, width
59
- string {
59
+ string('Area Gallery') {
60
60
  font family: 'Times', size: 14
61
61
  color :black
62
-
63
- 'Area Gallery'
64
62
  }
65
63
  }
66
64
  end
@@ -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
@@ -12,7 +12,7 @@ data = [
12
12
  %w[cow moo delete]
13
13
  ]
14
14
 
15
- window('Animal sounds', 300, 200) {
15
+ window('Animal sounds', 400, 200) {
16
16
  horizontal_box {
17
17
  table {
18
18
  text_column('Animal')
@@ -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
  }
@@ -12,7 +12,7 @@ data = [
12
12
  ['cow', 'moo', true]
13
13
  ]
14
14
 
15
- window('Animal sounds', 300, 200) {
15
+ window('Animal sounds', 400, 200) {
16
16
  horizontal_box {
17
17
  table {
18
18
  text_column('Animal')
@@ -14,6 +14,7 @@ IMAGE_ROWS = []
14
14
  50.times do |i|
15
15
  url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
16
16
  puts "Processing Image: #{url}"
17
+ $stdout.flush # for Windows
17
18
  f = URI.open(url)
18
19
  canvas = ChunkyPNG::Canvas.from_io(f)
19
20
  f.close
@@ -14,6 +14,7 @@ IMAGE_ROWS = []
14
14
  5.times do |i|
15
15
  url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
16
16
  puts "Processing Image: #{url}"
17
+ $stdout.flush # for Windows
17
18
  f = URI.open(url)
18
19
  canvas = ChunkyPNG::Canvas.from_io(f)
19
20
  f.close
@@ -5,8 +5,8 @@ class ColorTheCircles
5
5
 
6
6
  WINDOW_WIDTH = 800
7
7
  WINDOW_HEIGHT = 600
8
- CIRCLE_MIN_RADIUS = 15
9
- CIRCLE_MAX_RADIUS = 50
8
+ SHAPE_MIN_SIZE = 15
9
+ SHAPE_MAX_SIZE = 75
10
10
  MARGIN_WIDTH = 55
11
11
  MARGIN_HEIGHT = 155
12
12
  TIME_MAX_EASY = 4
@@ -58,12 +58,12 @@ class ColorTheCircles
58
58
  end
59
59
 
60
60
  def add_circle
61
- circle_x_center = rand * (WINDOW_WIDTH - MARGIN_WIDTH - CIRCLE_MAX_RADIUS) + CIRCLE_MAX_RADIUS
62
- circle_y_center = rand * (WINDOW_HEIGHT - MARGIN_HEIGHT - CIRCLE_MAX_RADIUS) + CIRCLE_MAX_RADIUS
63
- circle_radius = rand * (CIRCLE_MAX_RADIUS - CIRCLE_MIN_RADIUS) + CIRCLE_MIN_RADIUS
61
+ circle_x = rand * (WINDOW_WIDTH - MARGIN_WIDTH - SHAPE_MAX_SIZE) + SHAPE_MAX_SIZE
62
+ circle_y = rand * (WINDOW_HEIGHT - MARGIN_HEIGHT - SHAPE_MAX_SIZE) + SHAPE_MAX_SIZE
63
+ circle_size = rand * (SHAPE_MAX_SIZE - SHAPE_MIN_SIZE) + SHAPE_MIN_SIZE
64
64
  stroke_color = Glimmer::LibUI.x11_colors.sample
65
65
  @circles_data << {
66
- args: [circle_x_center, circle_y_center, circle_radius],
66
+ args: [circle_x, circle_y, circle_size],
67
67
  fill: nil,
68
68
  stroke: stroke_color
69
69
  }
@@ -79,7 +79,7 @@ class ColorTheCircles
79
79
 
80
80
  def color_circle(x, y)
81
81
  clicked_circle_data = @circles_data.find do |circle_data|
82
- circle_data[:fill].nil? && circle_data[:circle].include?(x, y)
82
+ circle_data[:fill].nil? && circle_data[:circle]&.include?(x, y)
83
83
  end
84
84
  if clicked_circle_data
85
85
  clicked_circle_data[:fill] = clicked_circle_data[:stroke]
@@ -95,7 +95,7 @@ class ColorTheCircles
95
95
  last_colored_circle_data_index = @circles_data.index(last_colored_circle_data) || -1
96
96
  @circles_data.insert(last_colored_circle_data_index + 1, removed_colored_circle_data)
97
97
  end
98
-
98
+
99
99
  def launch
100
100
  menu('Actions') {
101
101
  menu_item('Restart') {
@@ -190,24 +190,24 @@ class ColorTheCircles
190
190
  vexpand true
191
191
  halign :fill
192
192
  valign :fill
193
-
193
+
194
194
  on_draw do |area_draw_params|
195
195
  path {
196
196
  rectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)
197
-
197
+
198
198
  fill :white
199
199
  }
200
-
200
+
201
201
  @circles_data.each do |circle_data|
202
202
  path {
203
203
  circle_data[:circle] = circle(*circle_data[:args])
204
-
204
+
205
205
  fill circle_data[:fill]
206
206
  stroke circle_data[:stroke]
207
207
  }
208
208
  end
209
209
  end
210
-
210
+
211
211
  on_mouse_down do |area_mouse_event|
212
212
  color_circle(area_mouse_event[:x], area_mouse_event[:y])
213
213
  end
@@ -9,6 +9,7 @@ menu('File') {
9
9
  on_clicked do
10
10
  file = open_file
11
11
  puts file unless file.nil?
12
+ $stdout.flush # for Windows
12
13
  end
13
14
  }
14
15
 
@@ -16,6 +17,7 @@ menu('File') {
16
17
  on_clicked do
17
18
  file = save_file
18
19
  puts file unless file.nil?
20
+ $stdout.flush # for Windows
19
21
  end
20
22
  }
21
23
 
@@ -98,6 +100,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
98
100
 
99
101
  on_changed do |s|
100
102
  puts "New Spinbox value: #{s.value}"
103
+ $stdout.flush # for Windows
101
104
  end
102
105
  }
103
106
 
@@ -107,6 +110,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
107
110
  on_changed do |s|
108
111
  v = s.value
109
112
  puts "New Slider value: #{v}"
113
+ $stdout.flush # for Windows
110
114
  @progress_bar.value = v
111
115
  end
112
116
  }
@@ -125,6 +129,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
125
129
 
126
130
  on_selected do |c|
127
131
  puts "New combobox selection: #{c.selected}"
132
+ $stdout.flush # for Windows
128
133
  end
129
134
  }
130
135
 
@@ -147,6 +152,7 @@ MAIN_WINDOW = window('Control Gallery', 600, 500) {
147
152
 
148
153
  on_changed do |e|
149
154
  puts "Current textbox data: '#{e.text}'"
155
+ $stdout.flush # for Windows
150
156
  end
151
157
  }
152
158
  }
@@ -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
  }
@@ -1,5 +1,6 @@
1
1
  require 'glimmer-dsl-libui'
2
2
  require 'facets'
3
+ require 'fileutils'
3
4
 
4
5
  class MetaExample
5
6
  include Glimmer
@@ -41,15 +42,20 @@ class MetaExample
41
42
  end
42
43
 
43
44
  def run_example(example)
44
- command = "ruby -r #{glimmer_dsl_libui_file} #{example} 2>&1"
45
- result = ''
46
- IO.popen(command) do |f|
47
- f.each_line do |line|
48
- result << line
49
- puts line
45
+ Thread.new do
46
+ command = "ruby -r #{glimmer_dsl_libui_file} #{example} 2>&1"
47
+ result = ''
48
+ IO.popen(command) do |f|
49
+ sleep(0.01) # yield to main thread
50
+ f.each_line do |line|
51
+ result << line
52
+ puts line
53
+ $stdout.flush # for Windows
54
+ sleep(0.01) # yield to main thread
55
+ end
50
56
  end
57
+ Glimmer::LibUI.queue_main { msg_box('Error Running Example', result) } if result.downcase.include?('error')
51
58
  end
52
- msg_box('Error Running Example', result) if result.downcase.include?('error')
53
59
  end
54
60
 
55
61
  def launch
@@ -100,9 +106,13 @@ class MetaExample
100
106
  button('Launch') {
101
107
  on_clicked do
102
108
  begin
103
- meta_example_file = File.join(Dir.home, '.meta_example.rb')
104
- File.write(meta_example_file, @code_entry.text)
105
- run_example(meta_example_file)
109
+ parent_dir = File.join(Dir.home, '.glimmer-dsl-libui', 'examples')
110
+ FileUtils.mkdir_p(parent_dir)
111
+ example_file = File.join(parent_dir, "#{selected_example.underscore}.rb")
112
+ File.write(example_file, @code_entry.text)
113
+ FileUtils.cp_r(File.expand_path('../icons', __dir__), File.dirname(parent_dir))
114
+ FileUtils.cp_r(File.expand_path('../sounds', __dir__), File.dirname(parent_dir))
115
+ run_example(example_file)
106
116
  rescue => e
107
117
  puts e.full_message
108
118
  puts 'Unable to write code changes! Running original example...'
@@ -5,7 +5,7 @@ include Glimmer
5
5
 
6
6
  Address = Struct.new(:street, :p_o_box, :city, :state, :zip_code)
7
7
 
8
- def field(model, property)
8
+ def form_field(model, property)
9
9
  property = property.to_s
10
10
  entry { |e|
11
11
  label property.underscore.split('_').map(&:capitalize).join(' ')
@@ -19,11 +19,11 @@ end
19
19
 
20
20
  def address_form(address)
21
21
  form {
22
- field(address, :street)
23
- field(address, :p_o_box)
24
- field(address, :city)
25
- field(address, :state)
26
- field(address, :zip_code)
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
27
  }
28
28
  end
29
29
 
@@ -58,29 +58,39 @@ window('Method-Based Custom Keyword') {
58
58
  label('Address 1') {
59
59
  stretchy false
60
60
  }
61
+
61
62
  address_form(address1)
63
+
62
64
  horizontal_separator {
63
65
  stretchy false
64
66
  }
67
+
65
68
  label('Address 1 (Saved)') {
66
69
  stretchy false
67
70
  }
71
+
68
72
  address(address1)
69
73
  }
74
+
70
75
  vertical_separator {
71
76
  stretchy false
72
77
  }
78
+
73
79
  vertical_box {
74
80
  label('Address 2') {
75
81
  stretchy false
76
82
  }
83
+
77
84
  address_form(address2)
85
+
78
86
  horizontal_separator {
79
87
  stretchy false
80
88
  }
89
+
81
90
  label('Address 2 (Saved)') {
82
91
  stretchy false
83
92
  }
93
+
84
94
  address(address2)
85
95
  }
86
96
  }
Binary file
@@ -33,6 +33,8 @@ module Glimmer
33
33
  end
34
34
 
35
35
  def interpret(parent, keyword, *args, &block)
36
+ @@inverted_keyword_aliases = Glimmer::LibUI::ControlProxy::KEYWORD_ALIASES.invert unless defined?(@@inverted_keyword_aliases)
37
+ keyword = @@inverted_keyword_aliases[keyword] || keyword
36
38
  Glimmer::LibUI::ControlProxy.create(keyword, parent, args, &block)
37
39
  end
38
40
 
@@ -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
@@ -141,16 +151,26 @@ module Glimmer
141
151
  end
142
152
  end
143
153
  unless font.nil?
144
- family_attribute = ::LibUI.new_family_attribute(font[:family])
145
- ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, family_attribute, @start, @start + @string.size)
146
- size_attribute = ::LibUI.new_size_attribute(font[:size])
147
- ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, size_attribute, @start, @start + @string.size)
148
- weight_attribute = ::LibUI.new_weight_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_weight, font[:weight]))
149
- ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, weight_attribute, @start, @start + @string.size)
150
- italic_attribute = ::LibUI.new_italic_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_italic, font[:italic]))
151
- ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, italic_attribute, @start, @start + @string.size)
152
- stretch_attribute = ::LibUI.new_stretch_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_stretch, font[:stretch]))
153
- ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, stretch_attribute, @start, @start + @string.size)
154
+ if font[:family]
155
+ family_attribute = ::LibUI.new_family_attribute(font[:family])
156
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, family_attribute, @start, @start + @string.size)
157
+ end
158
+ if font[:size]
159
+ size_attribute = ::LibUI.new_size_attribute(font[:size])
160
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, size_attribute, @start, @start + @string.size)
161
+ end
162
+ if font[:weight]
163
+ weight_attribute = ::LibUI.new_weight_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_weight, font[:weight]))
164
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, weight_attribute, @start, @start + @string.size)
165
+ end
166
+ if font[:italic]
167
+ italic_attribute = ::LibUI.new_italic_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_italic, font[:italic]))
168
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, italic_attribute, @start, @start + @string.size)
169
+ end
170
+ if font[:stretch]
171
+ stretch_attribute = ::LibUI.new_stretch_attribute(Glimmer::LibUI.enum_symbol_to_value(:text_stretch, font[:stretch]))
172
+ ::LibUI.attributed_string_set_attribute(@parent_proxy.attributed_string, stretch_attribute, @start, @start + @string.size)
173
+ end
154
174
  end
155
175
  unless open_type_features.nil?
156
176
  open_type_features_attribute = ::LibUI.new_features_attribute(open_type_features.libui)
@@ -37,6 +37,7 @@ module Glimmer
37
37
  end
38
38
 
39
39
  LISTENERS = ['on_draw', 'on_mouse_event', 'on_mouse_move', 'on_mouse_down', 'on_mouse_up', 'on_mouse_drag_start', 'on_mouse_drag', 'on_mouse_drop', 'on_mouse_crossed', 'on_mouse_enter', 'on_mouse_exit', 'on_drag_broken', 'on_key_event', 'on_key_down', 'on_key_up']
40
+
40
41
  LISTENER_ALIASES = {
41
42
  on_drawn: 'on_draw',
42
43
  on_mouse_moved: 'on_mouse_move',
@@ -49,6 +50,30 @@ module Glimmer
49
50
  on_drag_break: 'on_drag_broken',
50
51
  }
51
52
 
53
+ SHIFTED_KEY_CODE_CHARS = {
54
+ '`' => '~',
55
+ '1' => '!',
56
+ '2' => '@',
57
+ '3' => '#',
58
+ '4' => '$',
59
+ '5' => '%',
60
+ '6' => '^',
61
+ '7' => '&',
62
+ '8' => '*',
63
+ '9' => '(',
64
+ '10' => ')',
65
+ '-' => '_',
66
+ '=' => '+',
67
+ ',' => '<',
68
+ '.' => '>',
69
+ '/' => '?',
70
+ ';' => ':',
71
+ "'" => '"',
72
+ '[' => '{',
73
+ ']' => '}',
74
+ "\\" => '|',
75
+ }
76
+
52
77
  include Glimmer::FiddleConsumer
53
78
  include Parent
54
79
  prepend Transformable
@@ -164,19 +189,27 @@ module Glimmer
164
189
  end
165
190
 
166
191
  def area_key_event_hash(area_key_event)
192
+ modifiers = modifiers_to_symbols(area_key_event.Modifiers)
167
193
  {
168
- key: key_to_char(area_key_event.Key),
194
+ key: key_to_char(area_key_event.Key, modifiers),
169
195
  key_value: area_key_event.Key,
170
196
  ext_key: ext_key_to_symbol(area_key_event.ExtKey),
171
197
  ext_key_value: area_key_event.ExtKey,
172
198
  modifier: modifiers_to_symbols(area_key_event.Modifier).first,
173
- modifiers: modifiers_to_symbols(area_key_event.Modifiers),
199
+ modifiers: modifiers,
174
200
  up: Glimmer::LibUI.integer_to_boolean(area_key_event.Up),
175
201
  }
176
202
  end
177
203
 
178
- def key_to_char(key)
179
- key.chr if key > 0
204
+ def key_to_char(key, modifiers = [])
205
+ if key > 0
206
+ char = key.chr
207
+ if modifiers == [:shift]
208
+ SHIFTED_KEY_CODE_CHARS[char]
209
+ else
210
+ char
211
+ end
212
+ end
180
213
  end
181
214
 
182
215
  def ext_key_to_symbol(ext_key_value)
@@ -84,7 +84,7 @@ module Glimmer
84
84
  @cell_rows = rows
85
85
  @cell_rows.tap do
86
86
  @last_cell_rows = array_deep_clone(@cell_rows)
87
- Glimmer::DataBinding::Observer.proc do
87
+ Glimmer::DataBinding::Observer.proc do |new_cell_rows|
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|
90
90
  ::LibUI.table_model_row_deleted(model, row)
@@ -103,8 +103,9 @@ module Glimmer
103
103
  end
104
104
  end
105
105
  end
106
+ @last_last_cell_rows = array_deep_clone(@last_cell_rows)
106
107
  @last_cell_rows = array_deep_clone(@cell_rows)
107
- end.observe(self, :cell_rows)
108
+ end.observe(self, :cell_rows, recursive: true)
108
109
  end
109
110
  end
110
111
  end
@@ -112,7 +113,11 @@ module Glimmer
112
113
  alias set_cell_rows cell_rows
113
114
 
114
115
  def expanded_cell_rows
115
- cell_rows.map do |row|
116
+ expand(cell_rows)
117
+ end
118
+
119
+ def expand(cell_rows)
120
+ cell_rows.to_a.map do |row|
116
121
  row.flatten(1)
117
122
  end
118
123
  end
@@ -146,23 +151,39 @@ module Glimmer
146
151
  3
147
152
  end
148
153
  end
149
- @model_handler.NumRows = fiddle_closure_block_caller(4) { cell_rows.count }
154
+ @model_handler.NumRows = fiddle_closure_block_caller(4) do
155
+ # Note: there is a double-delete bug in Windows when performing table_model_row_deleted, which requires pre-adding and extra empty row
156
+ cell_rows.count + (OS.windows? ? 1 : 0)
157
+ end
150
158
  @model_handler.CellValue = fiddle_closure_block_caller(1, [1, 1, 4, 4]) do |_, _, row, column|
151
159
  the_cell_rows = expanded_cell_rows
152
160
  case @columns[column]
153
161
  when Column::TextColumnProxy, Column::ButtonColumnProxy, Column::TextColorColumnProxy, :text
154
162
  ::LibUI.new_table_value_string((expanded_cell_rows[row] && expanded_cell_rows[row][column]).to_s)
155
163
  when Column::ImageColumnProxy, Column::ImageTextColumnProxy, Column::ImageTextColorColumnProxy
156
- ::LibUI.new_table_value_image((expanded_cell_rows[row] && (expanded_cell_rows[row][column].respond_to?(:libui) ? expanded_cell_rows[row][column].libui : expanded_cell_rows[row][column])))
164
+ if OS.windows? && row == cell_rows.count
165
+ ::LibUI.new_table_value_image((expanded_cell_rows[row - 1] && (expanded_cell_rows[row - 1][column].respond_to?(:libui) ? expanded_cell_rows[row - 1][column].libui : expanded_cell_rows[row - 1][column])))
166
+ else
167
+ ::LibUI.new_table_value_image((expanded_cell_rows[row] && (expanded_cell_rows[row][column].respond_to?(:libui) ? expanded_cell_rows[row][column].libui : expanded_cell_rows[row][column])))
168
+ end
157
169
  when Column::CheckboxColumnProxy, Column::CheckboxTextColumnProxy, Column::CheckboxTextColorColumnProxy
158
- ::LibUI.new_table_value_int((expanded_cell_rows[row] && (expanded_cell_rows[row][column] == 1 || expanded_cell_rows[row][column].to_s.strip.downcase == 'true' ? 1 : 0)))
170
+ ::LibUI.new_table_value_int(((expanded_cell_rows[row] && (expanded_cell_rows[row][column] == 1 || expanded_cell_rows[row][column].to_s.strip.downcase == 'true' ? 1 : 0))) || 0)
159
171
  when Column::ProgressBarColumnProxy
160
- ::LibUI.new_table_value_int((expanded_cell_rows[row] && (expanded_cell_rows[row][column].to_i)))
172
+ value = (expanded_cell_rows[row] && expanded_cell_rows[row][column]).to_i
173
+ expanded_last_last_cell_rows = expand(@last_last_cell_rows)
174
+ old_value = (expanded_last_last_cell_rows[row] && expanded_last_last_cell_rows[row][column]).to_i
175
+ if OS.windows? && old_value == -1 && value >= 0
176
+ Glimmer::Config.logger.error('Switching a progress bar value from -1 to a positive value is not supported on Windows')
177
+ cell_rows[row][column] = -1
178
+ ::LibUI.new_table_value_int(old_value)
179
+ else
180
+ ::LibUI.new_table_value_int((expanded_cell_rows[row] && expanded_cell_rows[row][column]).to_i)
181
+ end
161
182
  when Column::BackgroundColorColumnProxy
162
- background_color = Glimmer::LibUI.interpret_color(expanded_cell_rows[row] && expanded_cell_rows[row][column])
183
+ background_color = Glimmer::LibUI.interpret_color(expanded_cell_rows[row] && expanded_cell_rows[row][column]) || {r: 255, g: 255, b: 255}
163
184
  ::LibUI.new_table_value_color(background_color[:r] / 255.0, background_color[:g] / 255.0, background_color[:b] / 255.0, background_color[:a] || 1.0)
164
185
  when :color
165
- color = Glimmer::LibUI.interpret_color(expanded_cell_rows[row] && expanded_cell_rows[row][column])
186
+ color = Glimmer::LibUI.interpret_color(expanded_cell_rows[row] && expanded_cell_rows[row][column]) || {r: 0, g: 0, b: 0}
166
187
  ::LibUI.new_table_value_color(color[:r] / 255.0, color[:g] / 255.0, color[:b] / 255.0, color[:a] || 1.0)
167
188
  end
168
189
  end
@@ -182,7 +203,6 @@ module Glimmer
182
203
  @cell_rows[row] ||= []
183
204
  @cell_rows[row][column] = ::LibUI.table_value_int(val).to_i == 1
184
205
  end
185
- on_changed.each {|listener| listener.call(row, :changed, @cell_rows[row])}
186
206
  on_edited.each {|listener| listener.call(row, @cell_rows[row])}
187
207
  end
188
208