notesy::icons

Icons a plugin's script draws: the ones its manifest names in [[icons]] without a file (plugin.toml). The script gives each one an image, SVG it builds or an image's bytes, and can draw it again whenever it likes: a count, a state, a progress mark. Needs nothing.

tomlmain = "main.rn"

[[icons]]
name = "count"
rustuse notesy::{icons, status};

pub fn ready() {
    draw_count(5);
    let left = status::add("left");
    left.set(#{ text: "5 left", icon: "count" });
}

/// A bar as tall as `n` (up to 12), as SVG.
fn draw_count(n) {
    let h = if n > 12 { 12 } else { n };
    icons::set("count", `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><rect x="2" y="${14 - h}" width="12" height="${h}" rx="2"/></svg>`);
}
Function What it does
icons::set(name, image) Draws its icon name from image: SVG text, or the bytes of an SVG or a PNG (like what files::read_bytes gives). Setting it again draws it afresh.
icons::draw(name, shapes) Draws its icon name from shapes, the way notesy's own icons are drawn: crisp at any size, in the icon's color as it hovers and changes with the theme. Drawing it again draws it afresh. See below.

name has to be one of its [[icons]] without a file; any other is an error. The plugin names the icon by name wherever it names an icon (icon: "count"); anything else names it <plugin id>.count. Until the script sets it, it's drawn as notesy's plugin icon.

A tinted icon (the default) is drawn in the theme's colors, like notesy's own: its shapes are what count, not their colors. With tint = false it keeps its own. An image is at most 256 KB, and an <image> in its SVG may be inline data, never a file on this computer.

An SVG that moves moves here too: its <animate>, <animateTransform> and <set> (SMIL, as a small picture uses it), each on the element it's in or the one its href names, with values or from, to and by, keyTimes, calcMode="discrete", begin and dur as times, repeatCount, fill="freeze" and additive="sum". Numbers (in paths and transforms too) and colors change smoothly. notesy draws it once at each of its frames, up to 24 a second over at most 8 seconds, and shows them one after another as the Motion setting says (below); at rest, one that goes round shows its first frame and one that plays once shows how it ends. One that waits for a click or for another animation doesn't start, and CSS animation isn't read.

#Drawing with shapes

notesy::canvas makes the shapes: each in a 16 by 16 box, with 0, 0 at the top left, as notesy's icons are designed. Points are [x, y]; a shape takes more fields after it's made.

rustuse notesy::{canvas, icons};

pub fn ready() {
    let axis = canvas::path([[2.5, 2.0], [2.5, 13.5], [14.0, 13.5]]);
    let low = canvas::fill_rect([4.8, 8.5], [6.8, 11.8]);
    low.corner = 0.6;
    let high = canvas::fill_rect([8.3, 4.5], [10.3, 11.8]);
    high.corner = 0.6;
    icons::draw("chart", [axis, low, high]);
}
Builder Other fields What it draws
canvas::line(from, to) width a line
canvas::path(points) width, closed joined lines; closed back to the first point with closed = true
canvas::polygon(points) a filled shape, convex (a triangle, an arrowhead)
canvas::circle(center, radius) width a circle's edge
canvas::dot(center, radius) a filled circle
canvas::rect(min, max) width, corner a box's edge, its corners rounded by corner
canvas::fill_rect(min, max) corner a filled box
canvas::arc(center, radius, start, sweep) width part of a circle's edge, from start through sweep, in radians (0 points right, going clockwise)

width is its lines' width, 1.4 unless set: notesy's own. A drawing holds at most 64 shapes and 512 points, every number within 4 of the box, and it's checked where icons::draw is called (an error there says what's wrong) and again by notesy. Shapes are always painted in the icon's color, whatever tint says. As with every icon, an icon pack can draw it differently.

#Moving

A shape can move: set its motion to one of these, with a delay on it (seconds) to start later, like drops falling one after another.

rustuse notesy::{canvas, icons};

pub fn ready() {
    // Four rays turning together, once round in 12 seconds.
    let rays = canvas::moving([
        canvas::line([8.0, 1.5], [8.0, 3.5]),
        canvas::line([14.5, 8.0], [12.5, 8.0]),
        canvas::line([8.0, 14.5], [8.0, 12.5]),
        canvas::line([1.5, 8.0], [3.5, 8.0]),
    ], canvas::spin([8.0, 8.0], 12.0));
    // A drop falling, half a second after the rays start.
    let drop = canvas::dot([8.0, 7.0], 1.2);
    let fall = canvas::drift([0.0, 3.0], 1.2);
    fall.delay = 0.5;
    drop.motion = fall;
    let shapes = [canvas::circle([8.0, 8.0], 3.0), drop];
    for ray in rays {
        shapes.push(ray);
    }
    icons::draw("sunny", shapes);
}
Motion What the shape does
canvas::spin(origin, period) turns round origin, clockwise, once each period seconds
canvas::sway(origin, angle, period) turns to and fro, angle radians each way, round origin
canvas::pulse(origin, amount, period) grows and shrinks by amount (0.1: a tenth) round origin
canvas::bob(by, period) goes over by by ([x, y]) and back
canvas::drift(by, period) goes by by, fading on the way, then from the start again: rain falling
canvas::fade(low, period) fades to low (0 to 1) and back
canvas::blink(period) is gone for a moment each time round
canvas::moving(shapes, motion) the shapes, each moving so: parts that move as one

A period is 0.2 to 60 seconds, a delay up to 60. At rest, and before its delay, a shape is as it's drawn. notesy moves it, not the script: at most 30 times a second, and only while it's in sight, so a moving icon costs the script nothing. How much things move is the user's to say (Settings, Appearance, Motion): briefly, when an icon comes into sight and while the pointer's on it (the default), always, or not at all. Copies of one icon move together.

Its icons show in notesy's icon picker too (a note's icon property, in the Properties panel), under the plugin's name: picked, a note's icon names one as <plugin id>.<name>.

Every page