Update makepad-plot from Makepad 1.0 (live_design! DSL, wyeworks rev 53b2e5c84)
to Makepad 2.0 and make every plot widget usable in Splash fashion — i.e.
declarable and scriptable from the Splash DSL (script_mod! / ScriptVm), exactly like
the built-in Makepad 2.0 widgets (Button, Label, CandlestickChart, …).
Makepad 2.0 replaces live_design! with the Splash script system:
-
Widgets are Rust structs deriving
#[derive(Script, ScriptHook, Widget)]with#[source] source: ScriptObjectRef,#[walk],#[layout],#[live]props,#[rust]state and#[deref]composition. -
Each widget module registers itself with the VM in a
script_mod!block:script_mod! { use mod.prelude.widgets_internal.* use mod.widgets.* mod.plot.LinePlotBase = #(LinePlot::register_widget(vm)) mod.plot.LinePlot = set_type_default() do mod.plot.LinePlotBase{ width: Fill height: Fill } } -
Splash scripts then declare widgets declaratively (
line := LinePlot{ title: "..." }) and call methods at runtime (ui.line.set_data([...])) which are dispatched to the widget'sWidget::script_call(vm, method, args)implementation. -
Reference implementation:
~/home/makepad/widgets/src/chart.rs(ChartView + CandlestickChart/LineChart/... registered inmod.widgets), app skeleton:~/home/makepad/examples/charts/src/main.rs.
makepad-widgets = { path = "../makepad/widgets" } # Makepad 2.0 (dev branch)The old math_widget dependency is dropped (Makepad 1.0 only); LaTeX annotations
render as plain text in this port.
Old 1.0 elements.rs custom shaders (DrawPlotLine, DrawPieSlice, …) are replaced
by Makepad 2.0's DrawVector immediate-mode vector canvas
(move_to/line_to/bezier_to/close/rect/circle/ellipse, stroke(w)/fill(),
set_color, gradients) plus DrawColor for rects and DrawText.draw_abs for text.
src/
├── lib.rs # modules, re-exports, pub fn script_mod(vm) → creates mod.plot
├── types.rs # Series, ScaleType, LineStyle, MarkerStyle, StepStyle,
│ # LegendPosition, Colormap, annotations… (ported ~verbatim)
├── plot_view.rs # PlotView: core cartesian plot widget
└── charts/
├── line.rs # LinePlot, StepPlot, AreaChart, StemPlot, LinePlotDual,
│ # Stackplot, Streamgraph
├── bar.rs # BarPlot, HistogramChart, WaterfallChart, CandlestickChart
├── scatter.rs # ScatterPlot, BubbleChart, HexbinChart
├── circular.rs # PieChart, DonutChart, GaugeChart, FunnelChart, PolarPlot, RadarChart
├── stats.rs # BoxPlotChart, ViolinPlot
├── field.rs # HeatmapChart, ContourPlot, QuiverPlot
├── three_d.rs # Surface3D, Scatter3D, Line3D
├── hierarchy.rs # Treemap, SankeyDiagram
└── grid.rs # SubplotGrid
One shared base widget (used via #[deref] by all cartesian charts), owning:
DrawColor draw_bg,DrawColor draw_grid,DrawVector draw_vector,DrawText draw_text- plot margins,
title,xlabel,ylabel(#[live]strings) - viewport (x/y min/max) +
ScaleTypeper axis;data_to_px/px_to_data - nice-tick generation (via
ScaleType::generate_ticks/format_tick), grid + axis labels + border - legend drawing (position enum, swatch + label)
- pan (drag) & zoom (scroll) interaction, matching
ChartView - draw helpers over
DrawVector: styled lines (solid/dashed/dotted/dash-dot via dash marching), 8 marker styles, polygon fill, bars, polyline arcs / pie slices (line segments every ~4°), arrows
#[derive(Script, ScriptHook, Widget)]
pub struct LinePlot {
#[source] source: ScriptObjectRef,
#[deref] plot_view: PlotView,
#[rust] series: Vec<Series>,
...
}
impl Widget for LinePlot {
fn handle_event(...) { self.plot_view.handle_event(...) }
fn draw_walk(...) { /* fit-viewport, grid, draw series, legend */ }
fn script_call(...) { /* set_data, add_series, set_title, … */ }
}- Default demo data: when a chart has no data it self-populates with generated
demo data, so a bare
LinePlot{}in a Splash script renders immediately (same convention as makepad'schart.rs). - Splash-callable methods via
script_call(dispatched fromui.<id>.method(...)): every chart gets at leastset_title(t),set_xlabel(t)/set_ylabel(t)where meaningful, plus data setters, e.g.LinePlot:set_data(xs, ys),add_series(label, xs, ys),clear()BarPlot:set_data(labels, values)PieChart/DonutChart:set_data(labels, values)HeatmapChart:set_data(rows)(array of arrays)Scatter3D/Surface3D: numeric array setters- array args parsed with
vm.bx.heap.vec_len/vec_value(...).as_f64()
- Registration: each
charts/*.rshas ascript_mod!block registeringmod.plot.<Name>Base+ prototypemod.plot.<Name>with defaults.
lib.rs:
pub fn script_mod(vm: &mut ScriptVm) {
vm.bx.heap.new_module(id!(plot));
crate::plot_view::script_mod(vm);
crate::charts::line::script_mod(vm);
// … all chart modules
}Apps opt in with:
impl AppMain for App {
fn script_mod(vm: &mut ScriptVm) -> ScriptValue {
makepad_widgets::script_mod(vm);
makepad_plot::script_mod(vm);
self::script_mod(vm)
}
...
}and in Splash: use mod.plot.*.
Splash-declared demo app (the plot_demo bin): a window with a scrollable grid
showing all ported chart widgets, each rendering its built-in demo data, with
pan/zoom on cartesian charts — the whole UI written in the Splash DSL.
| Makepad 1.0 (old code) | Makepad 2.0 (this port) |
|---|---|
#[derive(Live, LiveHook, Widget)] |
#[derive(Script, ScriptHook, Widget)] + #[source] |
live_design!{ pub X = {{X}} {…} } |
script_mod!{ mod.plot.XBase = #(X::register_widget(vm)) … } |
Vec4 / vec4(…) |
Vec4f / vec4f(…) (script-side colors) |
DrawPlotLine::draw_line_styled |
PlotView::draw_line_styled (DrawVector dash marching) |
DrawPlotPoint::draw_marker |
PlotView::draw_marker (DrawVector shapes) |
DrawPieSlice/DrawArc shaders |
polyline arc fans on DrawVector |
PlotLabel / Math widgets |
DrawText::draw_abs (+ font_size via text_style) |
widget Ref rust setter APIs |
kept, plus Splash script_call methods |
#[deref]flattens the inner widget's script fields onto the outer type: prototypes must setplot_margin/draw_bg/ etc. at top level, never nested under the deref field name.draw_textprototypes needtext_style: theme.font_regular{}or nothing renders ("empty font family").- Text glyph quads write depth over their whole quad, so any DrawVector geometry
flushed after a text call is depth-rejected underneath glyphs (background-colored
holes in fills). PlotView therefore queues all text and draws it after the vector
flush in
end(). Flow::Right{wrap:true}breaks DrawVector widgets: the deferred row-wrap align pass shifts instance rects but not vector vertex geometry, so the first widget of each wrapped row loses its vector layer.SubplotGriduses explicitSubplotRows instead of a wrapping flow for this reason.- DrawVector geometry is not clipped by the enclosing turtle, so charts must keep their geometry inside their own rect (3D charts clamp zoom to 0.5–1.6).
- Splash array literals are typed arrays, not objects: parse method args with
value.as_array()+heap.array_len/array_index_unchecked(with an object-vec fallback), and read numbers withas_number()—as_f64()returnsNonefor integer-encoded values.
- LaTeX/math rendering of annotations (plain text instead)
- GPU-gradient parity for every 1.0 shader effect (solid/per-vertex color instead; DrawVector gradients can be layered in later)
- The old 5.6k-line Rust demo (
plot_demo.rs) is replaced by the Splash demo.