glimmer-dsl-libui 0.2.23 → 0.3.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +611 -93
- data/VERSION +1 -1
- data/bin/girb +0 -0
- data/examples/basic_image.rb +19 -0
- data/examples/basic_image2.rb +13 -0
- data/examples/basic_image3.rb +23 -0
- data/examples/basic_image4.rb +17 -0
- data/examples/basic_image5.rb +75 -0
- data/examples/basic_table_color.rb +1 -11
- data/examples/basic_table_color2.rb +39 -0
- data/examples/basic_table_image.rb +2 -14
- data/examples/basic_table_image2.rb +44 -0
- data/examples/basic_table_image_text.rb +2 -13
- data/examples/basic_table_image_text2.rb +44 -0
- data/glimmer-dsl-libui.gemspec +0 -0
- data/lib/glimmer/dsl/libui/control_expression.rb +1 -1
- data/lib/glimmer/libui/control_proxy/area_proxy.rb +1 -0
- data/lib/glimmer/libui/control_proxy/column.rb +2 -2
- data/lib/glimmer/libui/control_proxy/image_part_proxy.rb +0 -1
- data/lib/glimmer/libui/control_proxy/image_proxy.rb +159 -12
- data/lib/glimmer/libui/control_proxy/table_proxy.rb +15 -2
- data/lib/glimmer/libui/control_proxy/window_proxy.rb +1 -1
- data/lib/glimmer/libui/control_proxy.rb +7 -7
- data/lib/glimmer/libui/image_path_renderer.rb +30 -0
- data/lib/glimmer/libui.rb +1 -0
- metadata +27 -18
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2
|
1
|
+
0.3.2
|
data/bin/girb
CHANGED
File without changes
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
|
5
|
+
include Glimmer
|
6
|
+
|
7
|
+
window('Basic Image', 96, 96) {
|
8
|
+
area {
|
9
|
+
# image is not a real LibUI control. It is built in Glimmer as a custom control that renders
|
10
|
+
# tiny pixels/lines as rectangle paths. As such, it does not have good performance, but can
|
11
|
+
# be used in exceptional circumstances where an image control is really needed.
|
12
|
+
#
|
13
|
+
# Furthermore, adding image directly under area is even slower due to taking up more memory for every
|
14
|
+
# image pixel rendered. Check basic_image2.rb for a faster alternative using on_draw manually.
|
15
|
+
#
|
16
|
+
# It is recommended to pass width/height args to shrink image and achieve faster performance.
|
17
|
+
image(File.expand_path('../icons/glimmer.png', __dir__), 96, 96)
|
18
|
+
}
|
19
|
+
}.show
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
|
5
|
+
include Glimmer
|
6
|
+
|
7
|
+
window('Basic Image', 96, 96) {
|
8
|
+
area {
|
9
|
+
# image is not a real LibUI control. It is built in Glimmer as a custom control that renders
|
10
|
+
# tiny pixels/lines as rectangle paths. As such, it does not have good performance, but can
|
11
|
+
# be used in exceptional circumstances where an image control is really needed.
|
12
|
+
#
|
13
|
+
# Furthermore, adding image directly under area is even slower due to taking up more memory for every
|
14
|
+
# image pixel rendered. Check basic_image4.rb for a faster alternative using on_draw manually.
|
15
|
+
#
|
16
|
+
# It is recommended to pass width/height args to shrink image and achieve faster performance.
|
17
|
+
image {
|
18
|
+
file File.expand_path('../icons/glimmer.png', __dir__)
|
19
|
+
width 96
|
20
|
+
height 96
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}.show
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
|
5
|
+
include Glimmer
|
6
|
+
|
7
|
+
window('Basic Image', 96, 96) {
|
8
|
+
area {
|
9
|
+
on_draw do |area_draw_params|
|
10
|
+
image {
|
11
|
+
file File.expand_path('../icons/glimmer.png', __dir__)
|
12
|
+
width 96
|
13
|
+
height 96
|
14
|
+
}
|
15
|
+
end
|
16
|
+
}
|
17
|
+
}.show
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This is the manual way of rendering an image unto an area control.
|
4
|
+
# It could come in handy in special situations.
|
5
|
+
# Otherwise, it is recommended to simply utilize the `image` control that
|
6
|
+
# can be nested under area or area on_draw listener to automate all this work.
|
7
|
+
|
8
|
+
require 'glimmer-dsl-libui'
|
9
|
+
require 'chunky_png'
|
10
|
+
|
11
|
+
include Glimmer
|
12
|
+
|
13
|
+
puts 'Parsing image...'; $stdout.flush
|
14
|
+
|
15
|
+
f = File.open(File.expand_path('../icons/glimmer.png', __dir__))
|
16
|
+
canvas = ChunkyPNG::Canvas.from_io(f)
|
17
|
+
f.close
|
18
|
+
canvas.resample_nearest_neighbor!(96, 96)
|
19
|
+
data = canvas.to_rgba_stream
|
20
|
+
width = canvas.width
|
21
|
+
height = canvas.height
|
22
|
+
puts "Image width: #{width}"
|
23
|
+
puts "Image height: #{height}"
|
24
|
+
|
25
|
+
puts 'Parsing colors...'; $stdout.flush
|
26
|
+
|
27
|
+
color_maps = height.times.map do |y|
|
28
|
+
width.times.map do |x|
|
29
|
+
r = data[(y*width + x)*4].ord
|
30
|
+
g = data[(y*width + x)*4 + 1].ord
|
31
|
+
b = data[(y*width + x)*4 + 2].ord
|
32
|
+
a = data[(y*width + x)*4 + 3].ord
|
33
|
+
{x: x, y: y, color: {r: r, g: g, b: b, a: a}}
|
34
|
+
end
|
35
|
+
end.flatten
|
36
|
+
puts "#{color_maps.size} pixels to render..."; $stdout.flush
|
37
|
+
|
38
|
+
puts 'Parsing shapes...'; $stdout.flush
|
39
|
+
|
40
|
+
shape_maps = []
|
41
|
+
original_color_maps = color_maps.dup
|
42
|
+
indexed_original_color_maps = Hash[original_color_maps.each_with_index.to_a]
|
43
|
+
color_maps.each do |color_map|
|
44
|
+
index = indexed_original_color_maps[color_map]
|
45
|
+
@rectangle_start_x ||= color_map[:x]
|
46
|
+
@rectangle_width ||= 1
|
47
|
+
if color_map[:x] < width - 1 && color_map[:color] == original_color_maps[index + 1][:color]
|
48
|
+
@rectangle_width += 1
|
49
|
+
else
|
50
|
+
if color_map[:x] > 0 && color_map[:color] == original_color_maps[index - 1][:color]
|
51
|
+
shape_maps << {x: @rectangle_start_x, y: color_map[:y], width: @rectangle_width, height: 1, color: color_map[:color]}
|
52
|
+
else
|
53
|
+
shape_maps << {x: color_map[:x], y: color_map[:y], width: 1, height: 1, color: color_map[:color]}
|
54
|
+
end
|
55
|
+
@rectangle_width = 1
|
56
|
+
@rectangle_start_x = color_map[:x] == width - 1 ? 0 : color_map[:x] + 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
puts "#{shape_maps.size} shapes to render..."; $stdout.flush
|
60
|
+
|
61
|
+
puts 'Rendering image...'; $stdout.flush
|
62
|
+
|
63
|
+
window('Basic Image', 96, 96) {
|
64
|
+
area {
|
65
|
+
on_draw do |area_draw_params|
|
66
|
+
shape_maps.each do |shape_map|
|
67
|
+
path {
|
68
|
+
rectangle(shape_map[:x], shape_map[:y], shape_map[:width], shape_map[:height])
|
69
|
+
|
70
|
+
fill shape_map[:color]
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
}
|
75
|
+
}.show
|
@@ -1,20 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'glimmer-dsl-libui'
|
4
|
-
require 'chunky_png'
|
5
4
|
|
6
5
|
include Glimmer
|
7
6
|
|
8
|
-
|
9
|
-
canvas = ChunkyPNG::Canvas.from_io(f)
|
10
|
-
f.close
|
11
|
-
canvas.resample_nearest_neighbor!(24, 24)
|
12
|
-
data = canvas.to_rgba_stream
|
13
|
-
width = canvas.width
|
14
|
-
height = canvas.height
|
15
|
-
img = image {
|
16
|
-
image_part(data, width, height, width * 4)
|
17
|
-
}
|
7
|
+
img = image(File.expand_path('../icons/glimmer.png', __dir__), 24, 24)
|
18
8
|
|
19
9
|
data = [
|
20
10
|
[['cat', :red] , ['meow', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], {r: 255, g: 120, b: 0, a: 0.5}],
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'glimmer-dsl-libui'
|
4
|
+
require 'chunky_png'
|
5
|
+
|
6
|
+
include Glimmer
|
7
|
+
|
8
|
+
f = File.open(File.expand_path('../icons/glimmer.png', __dir__))
|
9
|
+
canvas = ChunkyPNG::Canvas.from_io(f)
|
10
|
+
f.close
|
11
|
+
canvas.resample_nearest_neighbor!(24, 24)
|
12
|
+
data = canvas.to_rgba_stream
|
13
|
+
width = canvas.width
|
14
|
+
height = canvas.height
|
15
|
+
img = image {
|
16
|
+
image_part(data, width, height, width * 4)
|
17
|
+
}
|
18
|
+
|
19
|
+
data = [
|
20
|
+
[['cat', :red] , ['meow', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], {r: 255, g: 120, b: 0, a: 0.5}],
|
21
|
+
[['dog', :yellow] , ['woof', {r: 240, g: 32, b: 32}] , [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], :skyblue],
|
22
|
+
[['chicken', :beige], ['cock-a-doodle-doo', :blue] , [false, 'mammal', :red] , [img, 'Glimmer', :beige], {r: 5, g: 120, b: 110}],
|
23
|
+
[['horse', :purple] , ['neigh', {r: 240, g: 32, b: 32}], [true, 'mammal', :green], [img, 'Glimmer', :dark_blue], '13a1fb'],
|
24
|
+
[['cow', :gray] , ['moo', :blue] , [true, 'mammal', :green], [img, 'Glimmer', :brown], 0x12ff02]
|
25
|
+
]
|
26
|
+
|
27
|
+
window('Animals', 500, 200) {
|
28
|
+
horizontal_box {
|
29
|
+
table {
|
30
|
+
text_color_column('Animal')
|
31
|
+
text_color_column('Sound')
|
32
|
+
checkbox_text_color_column('Description')
|
33
|
+
image_text_color_column('GUI')
|
34
|
+
background_color_column('Mammal')
|
35
|
+
|
36
|
+
cell_rows data
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}.show
|
@@ -4,8 +4,6 @@
|
|
4
4
|
# This example displays images that can be freely downloaded from the Studio Ghibli website.
|
5
5
|
|
6
6
|
require 'glimmer-dsl-libui'
|
7
|
-
require 'chunky_png'
|
8
|
-
require 'open-uri'
|
9
7
|
|
10
8
|
include Glimmer
|
11
9
|
|
@@ -13,18 +11,8 @@ IMAGE_ROWS = []
|
|
13
11
|
|
14
12
|
50.times do |i|
|
15
13
|
url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
|
16
|
-
puts "Processing Image: #{url}"
|
17
|
-
|
18
|
-
f = URI.open(url)
|
19
|
-
canvas = ChunkyPNG::Canvas.from_io(f)
|
20
|
-
f.close
|
21
|
-
data = canvas.to_rgba_stream
|
22
|
-
width = canvas.width
|
23
|
-
height = canvas.height
|
24
|
-
img = image {
|
25
|
-
image_part(data, width, height, width * 4)
|
26
|
-
}
|
27
|
-
IMAGE_ROWS << [img] # array of one column cell
|
14
|
+
puts "Processing Image: #{url}"; $stdout.flush # for Windows
|
15
|
+
IMAGE_ROWS << [image(url)] # array of one column cell
|
28
16
|
rescue StandardError => e
|
29
17
|
warn url, e.message
|
30
18
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE:
|
4
|
+
# This example displays images that can be freely downloaded from the Studio Ghibli website.
|
5
|
+
|
6
|
+
require 'glimmer-dsl-libui'
|
7
|
+
require 'chunky_png'
|
8
|
+
require 'open-uri'
|
9
|
+
|
10
|
+
include Glimmer
|
11
|
+
|
12
|
+
IMAGE_ROWS = []
|
13
|
+
|
14
|
+
50.times do |i|
|
15
|
+
url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
|
16
|
+
puts "Processing Image: #{url}"
|
17
|
+
$stdout.flush # for Windows
|
18
|
+
f = URI.open(url)
|
19
|
+
canvas = ChunkyPNG::Canvas.from_io(f)
|
20
|
+
f.close
|
21
|
+
data = canvas.to_rgba_stream
|
22
|
+
width = canvas.width
|
23
|
+
height = canvas.height
|
24
|
+
img = image {
|
25
|
+
image_part(data, width, height, width * 4)
|
26
|
+
}
|
27
|
+
IMAGE_ROWS << [img] # array of one column cell
|
28
|
+
rescue StandardError => e
|
29
|
+
warn url, e.message
|
30
|
+
end
|
31
|
+
|
32
|
+
window('The Red Turtle', 310, 350, false) {
|
33
|
+
horizontal_box {
|
34
|
+
table {
|
35
|
+
image_column('www.ghibli.jp/works/red-turtle')
|
36
|
+
|
37
|
+
cell_rows IMAGE_ROWS
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
on_closing do
|
42
|
+
puts 'Bye Bye'
|
43
|
+
end
|
44
|
+
}.show
|
@@ -4,8 +4,6 @@
|
|
4
4
|
# This example displays images that can be freely downloaded from the Studio Ghibli website.
|
5
5
|
|
6
6
|
require 'glimmer-dsl-libui'
|
7
|
-
require 'chunky_png'
|
8
|
-
require 'open-uri'
|
9
7
|
|
10
8
|
include Glimmer
|
11
9
|
|
@@ -13,18 +11,9 @@ IMAGE_ROWS = []
|
|
13
11
|
|
14
12
|
5.times do |i|
|
15
13
|
url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
|
16
|
-
puts "Processing Image: #{url}"
|
17
|
-
$stdout.flush # for Windows
|
18
|
-
f = URI.open(url)
|
19
|
-
canvas = ChunkyPNG::Canvas.from_io(f)
|
20
|
-
f.close
|
21
|
-
data = canvas.to_rgba_stream
|
22
|
-
width = canvas.width
|
23
|
-
height = canvas.height
|
24
|
-
img = image {
|
25
|
-
image_part(data, width, height, width * 4)
|
26
|
-
}
|
14
|
+
puts "Processing Image: #{url}"; $stdout.flush # for Windows
|
27
15
|
text = url.sub('https://www.ghibli.jp/gallery/thumb-redturtle', '').sub('.png', '')
|
16
|
+
img = image(url)
|
28
17
|
IMAGE_ROWS << [[img, text], [img, text]] # cell values are dual-element arrays
|
29
18
|
rescue StandardError => e
|
30
19
|
warn url, e.message
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE:
|
4
|
+
# This example displays images that can be freely downloaded from the Studio Ghibli website.
|
5
|
+
|
6
|
+
require 'glimmer-dsl-libui'
|
7
|
+
require 'chunky_png'
|
8
|
+
require 'open-uri'
|
9
|
+
|
10
|
+
include Glimmer
|
11
|
+
|
12
|
+
IMAGE_ROWS = []
|
13
|
+
|
14
|
+
5.times do |i|
|
15
|
+
url = format('https://www.ghibli.jp/gallery/thumb-redturtle%03d.png', (i + 1))
|
16
|
+
puts "Processing Image: #{url}"
|
17
|
+
$stdout.flush # for Windows
|
18
|
+
f = URI.open(url)
|
19
|
+
canvas = ChunkyPNG::Canvas.from_io(f)
|
20
|
+
f.close
|
21
|
+
data = canvas.to_rgba_stream
|
22
|
+
width = canvas.width
|
23
|
+
height = canvas.height
|
24
|
+
img = image {
|
25
|
+
image_part(data, width, height, width * 4)
|
26
|
+
}
|
27
|
+
text = url.sub('https://www.ghibli.jp/gallery/thumb-redturtle', '').sub('.png', '')
|
28
|
+
IMAGE_ROWS << [[img, text], [img, text]] # cell values are dual-element arrays
|
29
|
+
rescue StandardError => e
|
30
|
+
warn url, e.message
|
31
|
+
end
|
32
|
+
|
33
|
+
window('The Red Turtle', 670, 350) {
|
34
|
+
horizontal_box {
|
35
|
+
table {
|
36
|
+
image_text_column('image/number')
|
37
|
+
image_text_column('image/number (editable)') {
|
38
|
+
editable true
|
39
|
+
}
|
40
|
+
|
41
|
+
cell_rows IMAGE_ROWS
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}.show
|
data/glimmer-dsl-libui.gemspec
CHANGED
Binary file
|
@@ -218,6 +218,7 @@ module Glimmer
|
|
218
218
|
{
|
219
219
|
key: key_to_char(area_key_event.Key, modifiers),
|
220
220
|
key_value: area_key_event.Key,
|
221
|
+
key_code: area_key_event.Key,
|
221
222
|
ext_key: ext_key_to_symbol(area_key_event.ExtKey),
|
222
223
|
ext_key_value: area_key_event.ExtKey,
|
223
224
|
modifier: modifiers_to_symbols(area_key_event.Modifier).first,
|
@@ -43,9 +43,9 @@ module Glimmer
|
|
43
43
|
@column_index ||= @parent_proxy.send(:next_column_index)
|
44
44
|
end
|
45
45
|
|
46
|
-
# actual index within table columns (disregarding
|
46
|
+
# actual index within table columns (disregarding extra fillings that account for DualColumn instances)
|
47
47
|
def index
|
48
|
-
@parent_proxy.columns.
|
48
|
+
@parent_proxy.columns.select {|c| c.is_a?(Column)}.index(self)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
@@ -20,44 +20,191 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer/libui/control_proxy'
|
23
|
+
require 'glimmer/libui/control_proxy/image_part_proxy'
|
24
|
+
require 'glimmer/libui/image_path_renderer'
|
23
25
|
require 'glimmer/data_binding/observer'
|
26
|
+
require 'glimmer/libui/control_proxy/transformable'
|
24
27
|
|
25
28
|
using ArrayIncludeMethods
|
26
29
|
|
27
30
|
module Glimmer
|
28
31
|
module LibUI
|
29
32
|
class ControlProxy
|
30
|
-
# Proxy for LibUI image
|
33
|
+
# Proxy for LibUI image object and Glimmer custom control
|
31
34
|
#
|
32
35
|
# Follows the Proxy Design Pattern
|
33
36
|
class ImageProxy < ControlProxy
|
37
|
+
include Parent
|
38
|
+
prepend Transformable
|
39
|
+
|
40
|
+
attr_reader :data, :pixels, :shapes
|
41
|
+
|
34
42
|
def initialize(keyword, parent, args, &block)
|
35
43
|
@keyword = keyword
|
36
44
|
@parent_proxy = parent
|
37
45
|
@args = args
|
38
46
|
@block = block
|
39
47
|
@enabled = true
|
40
|
-
@children = []
|
41
48
|
post_add_content if @block.nil?
|
42
49
|
end
|
43
|
-
|
50
|
+
|
44
51
|
def post_add_content
|
45
|
-
|
46
|
-
|
52
|
+
if area_image?
|
53
|
+
@shapes = nil
|
54
|
+
super
|
55
|
+
if @parent_proxy.nil? && AreaProxy.current_area_draw_params
|
56
|
+
draw(AreaProxy.current_area_draw_params)
|
57
|
+
destroy
|
58
|
+
end
|
59
|
+
@content_added = true
|
60
|
+
else # image object not control
|
61
|
+
build_control
|
62
|
+
super
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def file(value = nil)
|
67
|
+
if value.nil?
|
68
|
+
@args[0]
|
69
|
+
else
|
70
|
+
@args[0] = value
|
71
|
+
if @content_added
|
72
|
+
post_add_content
|
73
|
+
request_auto_redraw
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
alias file= file
|
78
|
+
alias set_file file
|
79
|
+
|
80
|
+
def width(value = nil)
|
81
|
+
if value.nil?
|
82
|
+
@args[1]
|
83
|
+
else
|
84
|
+
@args[1] = value
|
85
|
+
if area_image? && @content_added
|
86
|
+
post_add_content
|
87
|
+
request_auto_redraw
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
alias width= width
|
92
|
+
alias set_width width
|
93
|
+
|
94
|
+
def height(value = nil)
|
95
|
+
if value.nil?
|
96
|
+
@args[2]
|
97
|
+
else
|
98
|
+
@args[2] = value
|
99
|
+
if area_image? && @content_added
|
100
|
+
post_add_content
|
101
|
+
request_auto_redraw
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
alias height= height
|
106
|
+
alias set_height height
|
107
|
+
|
108
|
+
def redraw
|
109
|
+
@parent_proxy&.redraw
|
110
|
+
end
|
111
|
+
|
112
|
+
def request_auto_redraw
|
113
|
+
@parent_proxy&.request_auto_redraw if area_image?
|
114
|
+
end
|
115
|
+
|
116
|
+
def draw(area_draw_params)
|
117
|
+
if @shapes.nil?
|
118
|
+
load_image
|
119
|
+
parse_pixels
|
120
|
+
calculate_shapes
|
121
|
+
end
|
122
|
+
ImagePathRenderer.new(@parent_proxy, @shapes).render
|
47
123
|
end
|
48
|
-
|
49
|
-
def
|
50
|
-
@
|
124
|
+
|
125
|
+
def area_image?
|
126
|
+
@area_image ||= !!(@parent_proxy&.is_a?(AreaProxy) || AreaProxy.current_area_draw_params)
|
127
|
+
end
|
128
|
+
|
129
|
+
def destroy
|
130
|
+
@parent_proxy&.children&.delete(self)
|
131
|
+
ControlProxy.control_proxies.delete(self)
|
51
132
|
end
|
52
133
|
|
53
134
|
private
|
54
135
|
|
55
136
|
def build_control
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
137
|
+
unless area_image? # image object
|
138
|
+
if file
|
139
|
+
load_image
|
140
|
+
ImagePartProxy.new('image_part', self, [@data, width, height, width * 4])
|
141
|
+
end
|
142
|
+
@args[1] = @children.first.args[1] if @children.size == 1 && @args[1].nil?
|
143
|
+
@args[2] = @children.first.args[2] if @children.size == 1 && @args[2].nil?
|
144
|
+
@libui = ControlProxy.new_control(@keyword, [width, height])
|
145
|
+
@libui.tap do
|
146
|
+
@children.each {|child| child&.send(:build_control) }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
rescue => e
|
150
|
+
Glimmer::Config.logger.error {"Failed to load image file: #{file}"}
|
151
|
+
Glimmer::Config.logger.error {e.full_message}
|
152
|
+
raise e
|
153
|
+
end
|
154
|
+
|
155
|
+
def load_image
|
156
|
+
require 'chunky_png'
|
157
|
+
canvas = nil
|
158
|
+
if file.start_with?('http')
|
159
|
+
require 'net/http'
|
160
|
+
require 'open-uri'
|
161
|
+
uri = URI(file)
|
162
|
+
canvas = ChunkyPNG::Canvas.from_string(Net::HTTP.get(uri))
|
163
|
+
else
|
164
|
+
f = File.open(file)
|
165
|
+
canvas = ChunkyPNG::Canvas.from_io(f)
|
166
|
+
f.close
|
167
|
+
end
|
168
|
+
canvas.resample_nearest_neighbor!(width, height) if width && height
|
169
|
+
@data = canvas.to_rgba_stream
|
170
|
+
self.width = canvas.width
|
171
|
+
self.height = canvas.height
|
172
|
+
[@data, width, height]
|
173
|
+
end
|
174
|
+
|
175
|
+
def parse_pixels
|
176
|
+
@pixels = height.times.map do |y|
|
177
|
+
width.times.map do |x|
|
178
|
+
r = @data[(y*width + x)*4].ord
|
179
|
+
g = @data[(y*width + x)*4 + 1].ord
|
180
|
+
b = @data[(y*width + x)*4 + 2].ord
|
181
|
+
a = @data[(y*width + x)*4 + 3].ord
|
182
|
+
{x: x, y: y, color: {r: r, g: g, b: b, a: a}}
|
183
|
+
end
|
184
|
+
end.flatten
|
185
|
+
end
|
186
|
+
|
187
|
+
def calculate_shapes
|
188
|
+
@shapes = []
|
189
|
+
original_pixels = @pixels.dup
|
190
|
+
indexed_original_pixels = Hash[original_pixels.each_with_index.to_a]
|
191
|
+
@pixels.each do |pixel|
|
192
|
+
index = indexed_original_pixels[pixel]
|
193
|
+
@rectangle_start_x ||= pixel[:x]
|
194
|
+
@rectangle_width ||= 1
|
195
|
+
if pixel[:x] < width - 1 && pixel[:color] == original_pixels[index + 1][:color]
|
196
|
+
@rectangle_width += 1
|
197
|
+
else
|
198
|
+
if pixel[:x] > 0 && pixel[:color] == original_pixels[index - 1][:color]
|
199
|
+
@shapes << {x: @rectangle_start_x, y: pixel[:y], width: @rectangle_width, height: 1, color: pixel[:color]}
|
200
|
+
else
|
201
|
+
@shapes << {x: pixel[:x], y: pixel[:y], width: 1, height: 1, color: pixel[:color]}
|
202
|
+
end
|
203
|
+
@rectangle_width = 1
|
204
|
+
@rectangle_start_x = pixel[:x] == width - 1 ? 0 : pixel[:x] + 1
|
205
|
+
end
|
60
206
|
end
|
207
|
+
@shapes
|
61
208
|
end
|
62
209
|
end
|
63
210
|
end
|
@@ -21,6 +21,7 @@
|
|
21
21
|
|
22
22
|
require 'glimmer/libui/control_proxy'
|
23
23
|
require 'glimmer/libui/control_proxy/dual_column'
|
24
|
+
require 'glimmer/libui/control_proxy/triple_column'
|
24
25
|
require 'glimmer/data_binding/observer'
|
25
26
|
require 'glimmer/fiddle_consumer'
|
26
27
|
|
@@ -137,7 +138,7 @@ module Glimmer
|
|
137
138
|
|
138
139
|
def build_control
|
139
140
|
@model_handler = ::LibUI::FFI::TableModelHandler.malloc
|
140
|
-
@model_handler.NumColumns = fiddle_closure_block_caller(4) { @columns.map {|c| c.is_a?(DualColumn) ? 2 : 1}.sum }
|
141
|
+
@model_handler.NumColumns = fiddle_closure_block_caller(4) { @columns.map {|c| c.is_a?(DualColumn) ? 2 : (c.is_a?(TripleColumn) ? 3 : 1)}.sum }
|
141
142
|
@model_handler.ColumnType = fiddle_closure_block_caller(4, [1, 1, 4]) do |_, _, column|
|
142
143
|
# TODO consider refactoring to use Glimmer::LibUI.enum_symbols(:table_value_type)
|
143
144
|
case @columns[column]
|
@@ -193,15 +194,27 @@ module Glimmer
|
|
193
194
|
column = @columns[column].index
|
194
195
|
@cell_rows[row] ||= []
|
195
196
|
@cell_rows[row][column] = ::LibUI.table_value_string(val).to_s
|
197
|
+
when Column::TextColorColumnProxy
|
198
|
+
column = @columns[column].index
|
199
|
+
@cell_rows[row] ||= []
|
200
|
+
@cell_rows[row][column] ||= []
|
201
|
+
@cell_rows[row][column][0] = ::LibUI.table_value_string(val).to_s
|
196
202
|
when :text
|
197
203
|
column = @columns[column - 1].index
|
204
|
+
@cell_rows[row] ||= []
|
205
|
+
@cell_rows[row][column] ||= []
|
198
206
|
@cell_rows[row][column][1] = ::LibUI.table_value_string(val).to_s
|
199
207
|
when Column::ButtonColumnProxy
|
200
208
|
@columns[column].notify_listeners(:on_clicked, row)
|
201
|
-
when Column::CheckboxColumnProxy
|
209
|
+
when Column::CheckboxColumnProxy
|
202
210
|
column = @columns[column].index
|
203
211
|
@cell_rows[row] ||= []
|
204
212
|
@cell_rows[row][column] = ::LibUI.table_value_int(val).to_i == 1
|
213
|
+
when Column::CheckboxTextColumnProxy
|
214
|
+
column = @columns[column].index
|
215
|
+
@cell_rows[row] ||= []
|
216
|
+
@cell_rows[row][column] ||= []
|
217
|
+
@cell_rows[row][column][0] = ::LibUI.table_value_int(val).to_i == 1
|
205
218
|
end
|
206
219
|
on_edited.each {|listener| listener.call(row, @cell_rows[row])}
|
207
220
|
end
|
@@ -45,7 +45,7 @@ module Glimmer
|
|
45
45
|
|
46
46
|
def destroy
|
47
47
|
super
|
48
|
-
ControlProxy.image_proxies.each { |image_proxy| ::LibUI.free_image(image_proxy.libui) }
|
48
|
+
ControlProxy.image_proxies.each { |image_proxy| ::LibUI.free_image(image_proxy.libui) unless image_proxy.area_image? }
|
49
49
|
@on_destroy_procs&.each { |on_destroy_proc| on_destroy_proc.call(self)}
|
50
50
|
end
|
51
51
|
|