spec/pus_lvgl_spec.cr @ trunk
spec
scale = 0.75 fontscale = 1.500 box wid 1.380 ht 0.340 with .nw at (0.035, -0.035) fill 0xCBD5E1 color 0xCBD5E1 box wid 1.380 ht 0.340 with .nw at (0.000, 0.000) fill 0x7C83E6 color 0x7C83E6 box wid 0.300 ht 0.065 rad 0.018 at (0.370, -0.022) fill 0xffffff color 0xffffff line from (0.140, 0.000) to (0.140, -0.340) color white line from (1.240, 0.000) to (1.240, -0.340) color white text "require 'spec'" color white at (0.690, -0.170)→ /pikchrshow
crystal source
require "spec"
json block
{
"kind": "require",
"name": "spec",
"doc": null,
"children": []
}
../src/gpcr/pus_lvgl
scale = 0.75 fontscale = 1.500 box wid 2.481 ht 0.340 with .nw at (0.035, -0.455) fill 0xCBD5E1 color 0xCBD5E1 box wid 2.481 ht 0.340 with .nw at (0.000, -0.420) fill 0x7C83E6 color 0x7C83E6 box wid 0.300 ht 0.065 rad 0.018 at (0.370, -0.443) fill 0xffffff color 0xffffff line from (0.140, -0.420) to (0.140, -0.760) color white line from (2.341, -0.420) to (2.341, -0.760) color white text "require '../src/gpcr/pus_lvgl'" color white at (1.241, -0.590)→ /pikchrshow
crystal source
require "../src/gpcr/pus_lvgl"
json block
{
"kind": "require",
"name": "../src/gpcr/pus_lvgl",
"doc": null,
"children": []
}
PUS_SAMPLE = <<-PIKCHR
scale = 1
start_btn: box wid 1.00 ht 0.50 rad 0.10 with .nw at (0.00,2.00) fill 0x112233 color 0x445566 # id=start_btn op={"op":"call","target":"blink"} ev=clicked
text "Start" color 0xFFFFFF at (0.50,1.75)
line from (0.00,1.00) to (1.00,1.00) color 0xCCCCCC
ellipse wid 0.20 ht 0.20 at (1.50,1.50) fill 0xFF0000 color 0x00FF00
PIKCHR
describe GPCR::PUS do
it "parses admitted PUS-1 elements and annotations" do
doc = GPCR::PUS.parse(PUS_SAMPLE)
doc.scale.should eq(1.0)
doc.elements.map(&.kind).should eq([:box, :text, :line, :ellipse])
box = doc.elements[0]
box.tag.should eq("start_btn")
box.annotation.id.should eq("start_btn")
box.annotation.op.should eq(%({"op":"call","target":"blink"}))
box.annotation.ev.should eq("clicked")
end
it "resolves Pikchr inches to lvgl pixels with top-left Y inversion" do
plan = GPCR::PUS.to_lvgl_plan(PUS_SAMPLE)
plan.canvas_height.should eq(2.0)
box = plan.operations[0]
box.bindable.should be_true
box.code.should contain("box_1 = Lvgl::Widgets::Button.new(PARENT)")
box.code.should contain("box_1.set_pos(0, 0)")
box.code.should contain("box_1.set_size(144, 72)")
box.code.should contain("box_1.set_style_radius(14)")
end
it "parents contained text and centers it relative to the containing box" do
plan = GPCR::PUS.to_lvgl_plan(PUS_SAMPLE)
text = plan.operations[1]
text.bindable.should be_true
text.code.should contain("text_2 = Lvgl::Widgets::Label.new(box_1)")
text.code.should contain(%(text_2.text = "Start"))
text.code.should contain("text_2.long_mode = Lvgl::LabelLongMode::Clip")
text.code.should contain("text_2.set_size(77, 23)")
text.code.should contain("text_2.set_style_text_align(Lvgl::TextAlign::Center, Lvgl.style_selector)")
text.code.should contain("text_2.align(Lvgl::Align::Center, offset: {0, 0})")
text.note.should eq("child of box_1")
end
it "emits real line widgets while keeping ellipse explicitly unsupported" do
plan = GPCR::PUS.to_lvgl_plan(PUS_SAMPLE)
line = plan.operations[2]
line.kind.should eq(:line)
line.bindable.should be_true
line.code.should contain("line_3 = Lvgl::Widgets::Line.new(PARENT)")
line.code.should contain("line_3.points = [{0, 144}, {144, 144}]")
line.code.should contain("line_3.set_style_line_color(Lvgl::Color.hex(0xCCCCCC))")
ellipse = plan.operations[3]
ellipse.kind.should eq(:ellipse)
ellipse.bindable.should be_false
ellipse.note.not_nil!.should contain("lv_arc_create")
end
it "emits inspectable lvgl-crystal code with line widgets and missing ellipse comments" do
code = GPCR::PUS.emit_lvgl_code(GPCR::PUS.to_lvgl_plan(PUS_SAMPLE), "screen")
code.should contain("Lvgl::Widgets::Button.new(screen)")
code.should contain("Lvgl::Widgets::Line.new(screen)")
code.should contain("dispatch_op")
code.should_not contain("# MISSING_BINDING line")
code.should contain("# MISSING_BINDING ellipse")
end
it "lowers open N-point polylines through the retained Line point buffer" do
plan = GPCR::PUS.to_lvgl_plan("scale = 1\nline from (0,2) to (1,1) then to (2,2) color 0x123456\n")
line = plan.operations[0]
line.bindable.should be_true
line.code.should contain("line_1.points = [{0, 0}, {144, 144}, {288, 0}]")
end
it "lowers predefined-process vertical bars through line widgets" do
plan = GPCR::PUS.to_lvgl_plan("scale = 1\nline from (0.140, 0.000) to (0.140, -0.340) color white\n")
line = plan.operations[0]
line.bindable.should be_true
line.code.should contain("line_1 = Lvgl::Widgets::Line.new(PARENT)")
line.code.should contain("line_1.points = [{20, 0}, {20, 49}]")
line.code.should contain("line_1.set_style_line_color(Lvgl::Color.hex(0xFFFFFF))")
end
it "lowers skinny divider boxes through line widgets with pixel thickness" do
plan = GPCR::PUS.to_lvgl_plan("scale = 1\nbox wid 1.00 ht 0.05 rad 0.02 with .nw at (0,1) fill 0xABCDEF color 0xABCDEF\n")
line = plan.operations[0]
line.bindable.should be_true
line.code.should contain("box_1 = Lvgl::Widgets::Line.new(PARENT)")
line.code.should contain("box_1.points = [{0, 3}, {144, 3}]")
line.code.should contain("box_1.set_style_line_width(7)")
line.code.should contain("box_1.set_style_line_rounded(true)")
end
it "lowers skinny vertical side bars through line widgets" do
plan = GPCR::PUS.to_lvgl_plan("scale = 1\nbox wid 0.04 ht 0.50 with .nw at (0,1) fill 0x111111 color 0x111111\n")
line = plan.operations[0]
line.bindable.should be_true
line.code.should contain("box_1 = Lvgl::Widgets::Line.new(PARENT)")
line.code.should contain("box_1.points = [{3, 0}, {3, 72}]")
line.code.should contain("box_1.set_style_line_width(6)")
end
it "rejects elements outside the admitted subset" do
expect_raises(GPCR::PUS::Error, /circle is outside/) do
GPCR::PUS.parse("scale = 1\ncircle rad 0.1 at (0,0) fill 0x000000 color 0x000000\n")
end
end
it "normalizes named text colors emitted by the GPCR renderer" do
plan = GPCR::PUS.to_lvgl_plan(%(scale = 1\ntext "label" color white at (0,0)\n))
plan.operations[0].code.should contain("Lvgl::Color.hex(0xFFFFFF)")
end
end