notesy::drawings
Drawings are .excalidraw files: shapes, arrows, lines, strokes of the
pen and words, as Excalidraw (https://excalidraw.com) draws and saves
them. notesy opens one in a tab to draw on, and shows it in a note that
embeds it (![[Sketch.excalidraw]]). A plugin's script can read and
change drawings, put buttons in a drawing's tool strip
(notesy::zones), and hear when one is opened or saved
(notesy::events). Shapes ready made, for the Stamps list, need no
script at all: see [[stamps]].
rustuse notesy::{drawings, zones, Zone};
pub fn ready() {
zones::add(Zone::DrawingTray, "tint", #{ title: "Make what's picked red", icon: "highlight" }, |drawing| {
for id in drawing.selected {
drawings::update(drawing.path.clone(), id, #{ backgroundColor: "#ffc9c9", fillStyle: "solid" });
}
});
}
#Elements
A drawing is #{ elements, background }: its elements bottom first, as
Excalidraw writes them, and its paper's color when it has one of its own.
Each element has id, type (rectangle, diamond, ellipse,
arrow, line, freedraw, text or image), x, y, width,
height, angle (radians), strokeColor, backgroundColor
("transparent" for none), fillStyle (hachure, cross-hatch or
solid), strokeWidth, strokeStyle (solid, dashed or dotted),
roughness (0 for straight lines, 1, or 2 for the roughest), opacity
(0 to 100), groupIds, locked, and by its type: points (a line's or
an arrow's, [x, y] pairs from its x and y), startArrowhead and
endArrowhead (arrow, bar, dot, triangle), startBinding and
endBinding (#{ elementId, focus, gap }: what an arrow is joined to);
a text's text, fontSize, fontFamily (5 for Excalidraw's hand, 2 for
plain, 3 for code), textAlign and containerId (the shape it's written
in); and boundElements, the words and arrows joined to a shape
([#{ id, type }]). Fields another app added are kept as they are, and
deleted ones are left out. A picture's data isn't read.
What an element a script adds leaves out is filled in: an id, how it's
drawn by hand (its seed), a line's points from its width and
height, and a text's size from its words. A field it gives that notesy
doesn't know of is kept, for Excalidraw. One it does know, of the wrong
kind (an x that's words, text that's a number), is refused, and so
are two elements given one id.
Drawings are named by their path in the vault, with or without
.excalidraw: "Sketch", "Plans/Flow.excalidraw". A path starting at
/ starts at the vault's top.
| Function | Takes | What it does |
|---|---|---|
drawings::read(path) |
notes.read |
The drawing, #{ elements, background }; None when there's none |
drawings::get(path, id) |
notes.read |
Element id of the drawing; None when there's no such element |
drawings::current() |
notes.read |
The drawing in front, #{ path, selected, visible }: the ids of what's picked, and what of it is in view, #{ x, y, width, height } in its own units; None when a drawing isn't in front |
drawings::open(path) |
notes.read |
Opens the drawing in a tab, in front |
drawings::pick(path, ids) |
notes.read |
Picks what ids name (an id, or a list) in the drawing's tab, and nothing else; the drawing has to be open |
drawings::write(path, drawing) |
notes.write |
Puts drawing's elements (#{ elements }, and background when it says) in place of what's there; makes the drawing when there's none |
drawings::add(path, elements) |
notes.write |
Adds an element, or a list of them (at most 2,000 at once), and returns its id, or the list of them |
drawings::update(path, id, fields) |
notes.write |
Puts fields over those of element id; () takes a field away. Words in a shape follow it |
drawings::remove(path, ids) |
notes.write |
Takes an element away, or a list of them by id, and the words in them; arrows and shapes bound to them let go |
A change to a drawing that's open shows at once and is one step the user can undo; one that isn't open is written to its file. To change many elements as one step, read the drawing, change what was read, and write it back: words in a shape are put back in its middle, wherever it went.
#A button of its own in a drawing's tool strip
A plugin's buttons go at the end of every drawing's tool strip, after a rule, each an icon with its title as its tip.
rustuse notesy::{drawings, notices, zones, Zone};
pub fn ready() {
let count = zones::add(Zone::DrawingTray, "count", #{ title: "Count what's picked", icon: "number" }, |drawing| {
notices::info(`${drawing.selected.len()} picked in ${drawing.path}`);
});
// Right-clicking the button opens what's put in its own menu.
count.menu("all", "Count everything", || {
if let Some(drawing) = drawings::current() {
if let Some(all) = drawings::read(drawing.path) {
notices::info(`${all.elements.len()} in all`);
}
}
});
}
| Function | What it does |
|---|---|
zones::add(Zone::DrawingTray, key, options, run) |
Adds a button to every drawing's tool strip, and returns it (notesy::zones): options as any place's entry, the title its tip. run(drawing) gets #{ path, selected }: the drawing in the vault, and the ids of what's picked. |
button.menu(key, options, run) puts items in the button's own
right-click menu (notesy::sections), whose run() takes
nothing: drawings::current() says which drawing it was. Taking the
button out (remove()) takes it out of every drawing. It takes the ui
permission.
#Hearing about drawings
Event::DrawingOpened (drawing.opened) when one is opened in a tab, and
Event::DrawingSaved (drawing.saved) when its tab writes it to its
file, each with its path; Event::AnyDrawing (drawing.*) for both.
They take notes.read (notesy::events).
#An example
examples/plugins/example.flowchart adds flowchart shapes to the Stamps
list from an Excalidraw library, a button that lines up the shapes picked
in a row (or, from its menu, a column), one that joins them with arrows
bound to both ends, and "New flowchart" in the palette.
Every page
- Overview
- plugin.toml: Every field of plugin.toml
- Permissions: What a plugin can ask for, when notesy asks, and what changes it
- Scripts: How a script runs: its lifecycle, events, limits and errors
- Packing and installing: Making, checking, signing, packing and installing
- notesy::log: Lines for its log on the Plugins page
- notesy::events: Hearing what happens, and every event
- notesy::commands: Adding commands, and running notesy's
- notesy::store: Keeping its own data
- notesy::settings: Reading its settings
- notesy::secrets: Keys and tokens, in the system keychain
- notesy::notes: Reading and changing the vault's notes
- notesy::editor: The note in front
- notesy::templates: What templates fill in, and functions of its own for them
- notesy::files: A folder of its own
- notesy::links: Opening pages in the browser, naming links after their pages
- notesy::clipboard: Copying and pasting
- notesy::view: What panels, tabs and sections show
- notesy::sections: Sidebar sections
- notesy::hidden: Hiding notes, files and folders from the tree
- notesy::status: Status bar items
- notesy::tools: Buttons in the formatting bar
- notesy::notices: Notices
- notesy::dialogs: Asking in a dialog, notesy's kinds or its own
- notesy::wizards: Pages one after another, like a setup
- notesy::boards: Boards' cards and arrows, and kinds of card of its own
- notesy::blocks: Drawing its fenced blocks
- notesy::icons: Drawing its own icons
- notesy::net: Requests to the sites it names
- notesy::ipc: Talking to a program on this computer
- notesy::accounts: Signing in to a service
- notesy::json: Reading and writing JSON
- notesy::toml: Reading and writing TOML
- notesy::yaml: Reading and writing YAML, and a note's front matter
- notesy::time: Now, written in the user's time zone, dates read, how long ago
- notesy::math: Trigonometry and the like, for drawing
- Names: Icon, Color, Tone, Side, Method, Command, Zone, Event: Notesy's names as enums
- notesy::preview: Its own screens for notesy preview
- notesy::perf: Timing its own work
- notesy::drawings: Drawings' shapes, and buttons in their tool strip
- notesy::sound: Playing sounds, and making them as it runs
- notesy::tex: Math macros for every note's formulas
- notesy::views: Side panels, tabs of its own, and its part of the tree's hover cards
- notesy::zones: Notesy's own places — its menus, its bars and its headings