konpeito 0.1.0 → 0.1.1
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 +15 -0
- data/lib/konpeito/codegen/jvm_generator.rb +61 -8
- data/lib/konpeito/hir/builder.rb +6 -4
- data/lib/konpeito/ui/column.rb +41 -11
- data/lib/konpeito/ui/core.rb +45 -0
- data/lib/konpeito/ui/row.rb +34 -8
- data/lib/konpeito/version.rb +1 -1
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
- data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +3 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7d7f18a84d8cfece0c51becca2067ab474195205b4d5ce09b7a4e197b129851a
|
|
4
|
+
data.tar.gz: ca0f8a113919d8ca6b28e8109fd2ed031979de67e695c9aaad9f659b425dab89
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 62a1bd26cf53ddc918f1129772574021154079e492c33f48437290179fd71bdba65ca78c95890f16c224cf58930fbc879040c595580eb73a1d7e6868f0460cd9
|
|
7
|
+
data.tar.gz: 295d6ac004cda8c7823ad711dca5015a95c78302fd0f3c2da0796cb30ef0c638a13bac53f0c8ae439fc50556bb1262e6a304facdd4dfaa3c6b425f1d3842f85a
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ All notable changes to Konpeito will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.1] - 2026-02-16
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- JVM backend: detect and resolve field type conflicts in `dedup_inherited_fields` to prevent runtime NPE when parent/child classes use same ivar with different types
|
|
12
|
+
- JVM backend: UI layout fixes for Castella dashboard (`.class` dispatch, `attr_accessor` field access, scrollbar thumb rendering, etc.)
|
|
13
|
+
- Remove duplicate `source_code_uri` from gemspec metadata
|
|
14
|
+
- Remove debug `puts` from data_table widget
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Castella UI: visual properties (`bg_color`, `border_radius`, `border_color`, `border_width`) directly on Column/Row layouts, eliminating Container wrapper boilerplate
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- Documentation: note that JVM backend might be more mature than LLVM backend
|
|
21
|
+
|
|
8
22
|
## [0.1.0] - 2026-02-13
|
|
9
23
|
|
|
10
24
|
### Added
|
|
@@ -72,4 +86,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
72
86
|
- `%a{extern}` - external C struct wrappers
|
|
73
87
|
- `%a{simd}` - SIMD vectorization
|
|
74
88
|
|
|
89
|
+
[0.1.1]: https://github.com/i2y/konpeito/compare/v0.1.0...v0.1.1
|
|
75
90
|
[0.1.0]: https://github.com/i2y/konpeito/releases/tag/v0.1.0
|
|
@@ -187,6 +187,10 @@ module Konpeito
|
|
|
187
187
|
# Classes are generated before main class, so we need this early.
|
|
188
188
|
prescan_top_level_constants(hir_program)
|
|
189
189
|
|
|
190
|
+
# Pre-scan: register global variable static fields early so that
|
|
191
|
+
# global variables referenced inside blocks have fields available.
|
|
192
|
+
prescan_global_variables(hir_program)
|
|
193
|
+
|
|
190
194
|
# Generate module interfaces FIRST (before classes that may implement them)
|
|
191
195
|
hir_program.modules.each do |module_def|
|
|
192
196
|
@block_methods = []
|
|
@@ -294,17 +298,43 @@ module Konpeito
|
|
|
294
298
|
}
|
|
295
299
|
end
|
|
296
300
|
|
|
301
|
+
# Yield every instruction in basic_blocks, recursing into block bodies
|
|
302
|
+
# attached to HIR::Call nodes.
|
|
303
|
+
def each_instruction_recursive(basic_blocks, &blk)
|
|
304
|
+
basic_blocks.each do |bb|
|
|
305
|
+
bb.instructions.each do |inst|
|
|
306
|
+
blk.call(inst)
|
|
307
|
+
if inst.is_a?(HIR::Call) && inst.block
|
|
308
|
+
each_instruction_recursive(inst.block.body, &blk)
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
297
314
|
# Pre-scan top-level StoreConstant instructions to populate @constant_fields early.
|
|
298
315
|
# This is needed because user classes are generated before the main class, and
|
|
299
316
|
# class constructors may reference top-level constants (e.g. EXPANDING = 1).
|
|
317
|
+
# Recurses into block bodies so constants defined inside lambdas are also found.
|
|
300
318
|
def prescan_top_level_constants(hir_program)
|
|
301
319
|
hir_program.functions.each do |func|
|
|
302
320
|
next if func.owner_class || func.owner_module
|
|
303
|
-
func.body
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
321
|
+
each_instruction_recursive(func.body) do |inst|
|
|
322
|
+
if inst.is_a?(HIR::StoreConstant) && inst.scope.nil?
|
|
323
|
+
@constant_fields << inst.name.to_s
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Pre-scan all functions for global variable access (LoadGlobalVar/StoreGlobalVar)
|
|
330
|
+
# and register the corresponding static fields early. This ensures global variables
|
|
331
|
+
# referenced inside blocks have their fields available during code generation.
|
|
332
|
+
def prescan_global_variables(hir_program)
|
|
333
|
+
hir_program.functions.each do |func|
|
|
334
|
+
each_instruction_recursive(func.body) do |inst|
|
|
335
|
+
if inst.is_a?(HIR::LoadGlobalVar) || inst.is_a?(HIR::StoreGlobalVar)
|
|
336
|
+
field_name = inst.name.sub(/^\$/, "GLOBAL_")
|
|
337
|
+
register_global_field(field_name)
|
|
308
338
|
end
|
|
309
339
|
end
|
|
310
340
|
end
|
|
@@ -3709,6 +3739,11 @@ module Konpeito
|
|
|
3709
3739
|
# Remove fields from child classes that are already declared on a parent class.
|
|
3710
3740
|
# Must run AFTER all classes are registered (register_class_info) since the
|
|
3711
3741
|
# HIR class order may register children before parents.
|
|
3742
|
+
#
|
|
3743
|
+
# Type conflict detection: when a child class assigns a concrete but different type
|
|
3744
|
+
# to a field that the parent typed narrowly (e.g. parent :i64, child :string), widen
|
|
3745
|
+
# the parent's field to :value (Object) to prevent runtime NPE.
|
|
3746
|
+
# If the child type is :value (unresolved/unknown), keep the parent's concrete type.
|
|
3712
3747
|
def dedup_inherited_fields
|
|
3713
3748
|
@class_info.each do |class_name, info|
|
|
3714
3749
|
parent = info[:super_name]
|
|
@@ -3719,6 +3754,16 @@ module Konpeito
|
|
|
3719
3754
|
if parent_info[:fields]
|
|
3720
3755
|
parent_info[:fields].each_key do |fname|
|
|
3721
3756
|
if info[:fields].key?(fname)
|
|
3757
|
+
child_type = info[:fields][fname]
|
|
3758
|
+
parent_type = parent_info[:fields][fname]
|
|
3759
|
+
# Only widen when both types are concrete but different.
|
|
3760
|
+
# If child is :value (unknown), trust the parent's type.
|
|
3761
|
+
# If parent is :value, trust it (already wide enough).
|
|
3762
|
+
if child_type != parent_type && child_type != :value && parent_type != :value
|
|
3763
|
+
warn "[konpeito] JVM field type conflict: #{parent_name}##{fname} is :#{parent_type}, " \
|
|
3764
|
+
"but subclass #{class_name} uses :#{child_type}. Widening to :value (Object)."
|
|
3765
|
+
parent_info[:fields][fname] = :value
|
|
3766
|
+
end
|
|
3722
3767
|
info[:fields].delete(fname)
|
|
3723
3768
|
end
|
|
3724
3769
|
end
|
|
@@ -5189,8 +5234,13 @@ module Konpeito
|
|
|
5189
5234
|
end
|
|
5190
5235
|
instructions = []
|
|
5191
5236
|
|
|
5192
|
-
# Load self
|
|
5193
|
-
|
|
5237
|
+
# Load self — use @block_self_slot if inside a block that captured self
|
|
5238
|
+
self_slot = @block_self_slot || 0
|
|
5239
|
+
instructions << { "op" => "aload", "var" => self_slot }
|
|
5240
|
+
# If self was captured as Object, checkcast to the expected class
|
|
5241
|
+
if @block_self_slot
|
|
5242
|
+
instructions << { "op" => "checkcast", "type" => jvm_class }
|
|
5243
|
+
end
|
|
5194
5244
|
|
|
5195
5245
|
# Prefer registered descriptor for consistency with method definition
|
|
5196
5246
|
registered = @method_descriptors["#{@current_class_name}##{method_name}"]
|
|
@@ -6478,7 +6528,8 @@ module Konpeito
|
|
|
6478
6528
|
instructions
|
|
6479
6529
|
end
|
|
6480
6530
|
|
|
6481
|
-
# Check if a block body accesses instance variables
|
|
6531
|
+
# Check if a block body accesses instance variables or calls methods on
|
|
6532
|
+
# implicit self (receiver-less calls like `kpi_card(label, value)`).
|
|
6482
6533
|
# Recursively checks nested blocks (e.g., on_click inside a yield block)
|
|
6483
6534
|
# so that outer blocks capture self when inner blocks need it.
|
|
6484
6535
|
def block_needs_self?(block_def)
|
|
@@ -6486,6 +6537,8 @@ module Konpeito
|
|
|
6486
6537
|
bb.instructions.any? { |inst|
|
|
6487
6538
|
if inst.is_a?(HIR::LoadInstanceVar) || inst.is_a?(HIR::StoreInstanceVar)
|
|
6488
6539
|
true
|
|
6540
|
+
elsif inst.is_a?(HIR::Call) && (inst.receiver.nil? || inst.receiver.is_a?(HIR::SelfRef))
|
|
6541
|
+
true
|
|
6489
6542
|
elsif inst.is_a?(HIR::Call) && inst.block
|
|
6490
6543
|
block_needs_self?(inst.block)
|
|
6491
6544
|
else
|
data/lib/konpeito/hir/builder.rb
CHANGED
|
@@ -2072,12 +2072,14 @@ module Konpeito
|
|
|
2072
2072
|
# Check if this is a keyword hash argument
|
|
2073
2073
|
if arg.node.is_a?(Prism::KeywordHashNode)
|
|
2074
2074
|
# Extract keyword arguments from the hash
|
|
2075
|
-
arg.
|
|
2075
|
+
# arg.children are typed AssocNode wrappers; each has children[0]=key, children[1]=value
|
|
2076
|
+
arg.node.elements.each_with_index do |elem, ei|
|
|
2076
2077
|
if elem.is_a?(Prism::AssocNode) && elem.key.is_a?(Prism::SymbolNode)
|
|
2077
2078
|
key_name = elem.key.unescaped.to_sym
|
|
2078
|
-
#
|
|
2079
|
-
|
|
2080
|
-
if
|
|
2079
|
+
# Navigate through the typed AssocNode to get the typed value child
|
|
2080
|
+
typed_assoc = arg.children[ei]
|
|
2081
|
+
if typed_assoc && typed_assoc.children && typed_assoc.children.size >= 2
|
|
2082
|
+
value_typed = typed_assoc.children[1]
|
|
2081
2083
|
keyword_args[key_name] = visit(value_typed)
|
|
2082
2084
|
else
|
|
2083
2085
|
# Fallback: create typed node for the value
|
data/lib/konpeito/ui/column.rb
CHANGED
|
@@ -77,20 +77,35 @@ class Column < Layout
|
|
|
77
77
|
|
|
78
78
|
#: (untyped painter) -> void
|
|
79
79
|
def relocate_children(painter)
|
|
80
|
-
|
|
80
|
+
# Account for padding
|
|
81
|
+
inner_w = @width - @pad_left - @pad_right
|
|
82
|
+
inner_h = @height - @pad_top - @pad_bottom
|
|
83
|
+
if inner_w < 0.0
|
|
84
|
+
inner_w = 0.0
|
|
85
|
+
end
|
|
86
|
+
if inner_h < 0.0
|
|
87
|
+
inner_h = 0.0
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
remaining = inner_h
|
|
81
91
|
expanding_total_flex = 0
|
|
82
92
|
|
|
83
93
|
# First pass: measure FIXED/CONTENT children, collect EXPANDING
|
|
94
|
+
# In a Column, non-FIXED children fill the column width (for centering, word-wrap, etc.)
|
|
84
95
|
i = 0
|
|
85
96
|
while i < @children.length
|
|
86
97
|
c = @children[i]
|
|
87
98
|
if c.get_height_policy != EXPANDING
|
|
88
99
|
# Set width before measure so word-wrapping can calculate line count
|
|
89
|
-
if c.get_width_policy
|
|
90
|
-
c.resize_wh(
|
|
100
|
+
if c.get_width_policy != FIXED
|
|
101
|
+
c.resize_wh(inner_w, c.get_height)
|
|
91
102
|
end
|
|
92
103
|
cs = c.measure(painter)
|
|
93
|
-
c.
|
|
104
|
+
if c.get_width_policy == FIXED
|
|
105
|
+
c.resize_wh(cs.width, cs.height)
|
|
106
|
+
else
|
|
107
|
+
c.resize_wh(inner_w, cs.height)
|
|
108
|
+
end
|
|
94
109
|
remaining = remaining - cs.height
|
|
95
110
|
else
|
|
96
111
|
expanding_total_flex = expanding_total_flex + c.get_flex
|
|
@@ -104,7 +119,7 @@ class Column < Layout
|
|
|
104
119
|
end
|
|
105
120
|
|
|
106
121
|
# Second pass: distribute remaining space to EXPANDING children, position all
|
|
107
|
-
cy = @y
|
|
122
|
+
cy = @y + @pad_top
|
|
108
123
|
if @is_scrollable
|
|
109
124
|
cy = cy - @scroll_offset
|
|
110
125
|
end
|
|
@@ -117,14 +132,14 @@ class Column < Layout
|
|
|
117
132
|
if expanding_total_flex > 0 && remaining > 0.0
|
|
118
133
|
h = remaining * c.get_flex / expanding_total_flex
|
|
119
134
|
end
|
|
120
|
-
c.resize_wh(
|
|
135
|
+
c.resize_wh(inner_w, h)
|
|
121
136
|
else
|
|
122
|
-
#
|
|
123
|
-
if c.get_width_policy
|
|
124
|
-
c.resize_wh(
|
|
137
|
+
# In a Column, non-FIXED children fill the column width
|
|
138
|
+
if c.get_width_policy != FIXED
|
|
139
|
+
c.resize_wh(inner_w, c.get_height)
|
|
125
140
|
end
|
|
126
141
|
end
|
|
127
|
-
c.move_xy(@x, cy)
|
|
142
|
+
c.move_xy(@x + @pad_left, cy)
|
|
128
143
|
cy = cy + c.get_height + @spacing
|
|
129
144
|
total_content_h = total_content_h + c.get_height
|
|
130
145
|
total_content_h = total_content_h + @spacing if i > 0
|
|
@@ -134,7 +149,7 @@ class Column < Layout
|
|
|
134
149
|
|
|
135
150
|
# Auto-scroll to bottom when pinned
|
|
136
151
|
if @pin_bottom && @is_scrollable
|
|
137
|
-
max_scroll = @content_height -
|
|
152
|
+
max_scroll = @content_height - inner_h
|
|
138
153
|
if max_scroll > 0.0
|
|
139
154
|
@scroll_offset = max_scroll
|
|
140
155
|
end
|
|
@@ -143,9 +158,24 @@ class Column < Layout
|
|
|
143
158
|
|
|
144
159
|
#: (untyped painter, bool completely) -> void
|
|
145
160
|
def redraw(painter, completely)
|
|
161
|
+
saved_bg = $__bg_clear_color
|
|
162
|
+
# When this layout has a custom background and is dirty, we handle clearing
|
|
163
|
+
# ourselves to preserve rounded corners. Clear dirty flag so redraw_children
|
|
164
|
+
# won't overwrite with a solid fill_rect.
|
|
165
|
+
if @custom_bg && is_dirty
|
|
166
|
+
parent_bg = saved_bg
|
|
167
|
+
if parent_bg == nil || parent_bg == 0
|
|
168
|
+
parent_bg = $theme.bg_canvas
|
|
169
|
+
end
|
|
170
|
+
painter.fill_rect(0.0, 0.0, @width, @height, parent_bg)
|
|
171
|
+
set_dirty(false)
|
|
172
|
+
completely = true
|
|
173
|
+
end
|
|
174
|
+
draw_visual_background(painter)
|
|
146
175
|
relocate_children(painter)
|
|
147
176
|
redraw_children(painter, completely)
|
|
148
177
|
draw_scrollbar(painter) if @is_scrollable
|
|
178
|
+
$__bg_clear_color = saved_bg
|
|
149
179
|
end
|
|
150
180
|
|
|
151
181
|
#: (untyped painter) -> void
|
data/lib/konpeito/ui/core.rb
CHANGED
|
@@ -1864,6 +1864,51 @@ class Layout < Widget
|
|
|
1864
1864
|
def initialize
|
|
1865
1865
|
super
|
|
1866
1866
|
@children = []
|
|
1867
|
+
# Visual properties (background, border)
|
|
1868
|
+
@bg_color_val = 0
|
|
1869
|
+
@border_color_val = 0
|
|
1870
|
+
@custom_bg = false
|
|
1871
|
+
@custom_border = false
|
|
1872
|
+
@border_radius_val = 0.0
|
|
1873
|
+
@border_width_val = 1.0
|
|
1874
|
+
@bg_clear_color = nil
|
|
1875
|
+
end
|
|
1876
|
+
|
|
1877
|
+
# --- Visual Properties (method chaining) ---
|
|
1878
|
+
|
|
1879
|
+
#: (Integer c) -> Layout
|
|
1880
|
+
def bg_color(c)
|
|
1881
|
+
@bg_color_val = c
|
|
1882
|
+
@custom_bg = true
|
|
1883
|
+
self
|
|
1884
|
+
end
|
|
1885
|
+
|
|
1886
|
+
#: (Integer c) -> Layout
|
|
1887
|
+
def border_color(c)
|
|
1888
|
+
@border_color_val = c
|
|
1889
|
+
@custom_border = true
|
|
1890
|
+
self
|
|
1891
|
+
end
|
|
1892
|
+
|
|
1893
|
+
#: (Float r) -> Layout
|
|
1894
|
+
def border_radius(r)
|
|
1895
|
+
@border_radius_val = r
|
|
1896
|
+
self
|
|
1897
|
+
end
|
|
1898
|
+
|
|
1899
|
+
#: (Float w) -> Layout
|
|
1900
|
+
def border_width(w)
|
|
1901
|
+
@border_width_val = w
|
|
1902
|
+
self
|
|
1903
|
+
end
|
|
1904
|
+
|
|
1905
|
+
# Draw background and border if visual properties are set.
|
|
1906
|
+
#: (untyped painter) -> void
|
|
1907
|
+
def draw_visual_background(painter)
|
|
1908
|
+
if @custom_bg
|
|
1909
|
+
painter.fill_round_rect(0.0, 0.0, @width, @height, @border_radius_val, @bg_color_val)
|
|
1910
|
+
@bg_clear_color = @bg_color_val
|
|
1911
|
+
end
|
|
1867
1912
|
end
|
|
1868
1913
|
|
|
1869
1914
|
#: () -> Array
|
data/lib/konpeito/ui/row.rb
CHANGED
|
@@ -74,7 +74,17 @@ class Row < Layout
|
|
|
74
74
|
|
|
75
75
|
#: (untyped painter) -> void
|
|
76
76
|
def relocate_children(painter)
|
|
77
|
-
|
|
77
|
+
# Account for padding
|
|
78
|
+
inner_w = @width - @pad_left - @pad_right
|
|
79
|
+
inner_h = @height - @pad_top - @pad_bottom
|
|
80
|
+
if inner_w < 0.0
|
|
81
|
+
inner_w = 0.0
|
|
82
|
+
end
|
|
83
|
+
if inner_h < 0.0
|
|
84
|
+
inner_h = 0.0
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
remaining = inner_w
|
|
78
88
|
expanding_total_flex = 0
|
|
79
89
|
|
|
80
90
|
# First pass: measure FIXED/CONTENT children, collect EXPANDING
|
|
@@ -84,10 +94,14 @@ class Row < Layout
|
|
|
84
94
|
if c.get_width_policy != EXPANDING
|
|
85
95
|
# Set height before measure so height-dependent layouts work
|
|
86
96
|
if c.get_height_policy == EXPANDING
|
|
87
|
-
c.resize_wh(c.get_width,
|
|
97
|
+
c.resize_wh(c.get_width, inner_h)
|
|
88
98
|
end
|
|
89
99
|
cs = c.measure(painter)
|
|
90
|
-
c.
|
|
100
|
+
if c.get_height_policy == EXPANDING
|
|
101
|
+
c.resize_wh(cs.width, inner_h)
|
|
102
|
+
else
|
|
103
|
+
c.resize_wh(cs.width, cs.height)
|
|
104
|
+
end
|
|
91
105
|
remaining = remaining - cs.width
|
|
92
106
|
else
|
|
93
107
|
expanding_total_flex = expanding_total_flex + c.get_flex
|
|
@@ -101,7 +115,7 @@ class Row < Layout
|
|
|
101
115
|
end
|
|
102
116
|
|
|
103
117
|
# Second pass: distribute remaining space, position all
|
|
104
|
-
cx = @x
|
|
118
|
+
cx = @x + @pad_left
|
|
105
119
|
if @is_scrollable
|
|
106
120
|
cx = cx - @scroll_offset
|
|
107
121
|
end
|
|
@@ -114,13 +128,13 @@ class Row < Layout
|
|
|
114
128
|
if expanding_total_flex > 0 && remaining > 0.0
|
|
115
129
|
w = remaining * c.get_flex / expanding_total_flex
|
|
116
130
|
end
|
|
117
|
-
c.resize_wh(w,
|
|
131
|
+
c.resize_wh(w, inner_h)
|
|
118
132
|
else
|
|
119
133
|
if c.get_height_policy == EXPANDING
|
|
120
|
-
c.resize_wh(c.get_width,
|
|
134
|
+
c.resize_wh(c.get_width, inner_h)
|
|
121
135
|
end
|
|
122
136
|
end
|
|
123
|
-
c.move_xy(cx, @y)
|
|
137
|
+
c.move_xy(cx, @y + @pad_top)
|
|
124
138
|
cx = cx + c.get_width + @spacing
|
|
125
139
|
total_content_w = total_content_w + c.get_width
|
|
126
140
|
total_content_w = total_content_w + @spacing if i > 0
|
|
@@ -130,7 +144,7 @@ class Row < Layout
|
|
|
130
144
|
|
|
131
145
|
# Auto-scroll to end when pinned
|
|
132
146
|
if @pin_right && @is_scrollable
|
|
133
|
-
max_scroll = @content_width -
|
|
147
|
+
max_scroll = @content_width - inner_w
|
|
134
148
|
if max_scroll > 0.0
|
|
135
149
|
@scroll_offset = max_scroll
|
|
136
150
|
end
|
|
@@ -139,9 +153,21 @@ class Row < Layout
|
|
|
139
153
|
|
|
140
154
|
#: (untyped painter, bool completely) -> void
|
|
141
155
|
def redraw(painter, completely)
|
|
156
|
+
saved_bg = $__bg_clear_color
|
|
157
|
+
if @custom_bg && is_dirty
|
|
158
|
+
parent_bg = saved_bg
|
|
159
|
+
if parent_bg == nil || parent_bg == 0
|
|
160
|
+
parent_bg = $theme.bg_canvas
|
|
161
|
+
end
|
|
162
|
+
painter.fill_rect(0.0, 0.0, @width, @height, parent_bg)
|
|
163
|
+
set_dirty(false)
|
|
164
|
+
completely = true
|
|
165
|
+
end
|
|
166
|
+
draw_visual_background(painter)
|
|
142
167
|
relocate_children(painter)
|
|
143
168
|
redraw_children(painter, completely)
|
|
144
169
|
draw_scrollbar(painter) if @is_scrollable
|
|
170
|
+
$__bg_clear_color = saved_bg
|
|
145
171
|
end
|
|
146
172
|
|
|
147
173
|
#: (untyped painter) -> void
|
data/lib/konpeito/version.rb
CHANGED
|
Binary file
|
|
@@ -56,6 +56,9 @@ public class RubyDispatch {
|
|
|
56
56
|
RUBY_NAME_ALIASES.put("to_s", new String[]{"toString"});
|
|
57
57
|
RUBY_NAME_ALIASES.put("to_a", new String[]{"toArray_"});
|
|
58
58
|
|
|
59
|
+
// Reserved name aliases (jvm_method_name mangles these)
|
|
60
|
+
RUBY_NAME_ALIASES.put("k_class", new String[]{"getClass"});
|
|
61
|
+
|
|
59
62
|
// Hash: keys/values → Ruby-specific methods returning KArray
|
|
60
63
|
RUBY_NAME_ALIASES.put("keys", new String[]{"rubyKeys"});
|
|
61
64
|
RUBY_NAME_ALIASES.put("values", new String[]{"rubyValues"});
|