pub struct Drawing<'a> {
base: IndexedDocument<'a>,
path: &'a BlockPath,
index: Option<&'a SpatialIndex>,
pub(super) presentation: &'a mut Presentation,
gesture: &'a mut Gesture,
previewed: Previewed,
}Expand description
A transient view onto one scope of the document. Reads project the
scope’s entities out of indexed; writes are emitted into sink and
only become document state when the gesture seals and submits.
Fields§
§base: IndexedDocument<'a>The session’s prediction. Reads go through Drawing::indexed,
which overlays whatever the gesture has already authored — never
this field directly, which is what makes a gesture able to read its
own writes.
path: &'a BlockPath§index: Option<&'a SpatialIndex>Optional spatial index over the current level’s hittables, for broad-phase
viewport culling and hit-testing. Built and cached by App; None on the
paths that don’t need it (SVG export, tests, popups), where queries fall
back to a full linear scan with identical results.
presentation: &'a mut PresentationThe document’s derived state — solver geometry, measurement caches,
propagated accents. Mandatory where the index is optional: derived
state has no linear-scan fallback, and the solver passes that fill
it run inside Drawing methods, so it rides every borrow.
gesture: &'a mut GestureThe gesture in progress. Private, and reachable only through
Drawing::author: a tool cannot hold the sink, and a write cannot
skip advancing the prediction the next read will see.
previewed: PreviewedImplementations§
Source§impl Drawing<'_>
impl Drawing<'_>
Sourcepub fn copy_selection(&self, shapes: &[ShapeId]) -> Option<Clipboard>
pub fn copy_selection(&self, shapes: &[ShapeId]) -> Option<Clipboard>
The value snapshot of shapes — each with the subtree it owns, the
wires landing on any of their pins, and those wires’ labels. None
when the selection holds nothing copyable.
Sourcepub fn copy_pins(&self, pins: &[PinId]) -> Option<Clipboard>
pub fn copy_pins(&self, pins: &[PinId]) -> Option<Clipboard>
The value snapshot of a pin selection — the payload a paste slots onto another block’s boundary.
Sourcepub fn cut_selection(
&mut self,
shapes: &[ShapeId],
from: DocumentNonce,
) -> Option<Clipboard>
pub fn cut_selection( &mut self, shapes: &[ShapeId], from: DocumentNonce, ) -> Option<Clipboard>
Copy shapes, then delete them — one commit, so the cut and the
cascade it implies undo together. What the delete declines the copy
declines too, which is what makes the paste that follows a move.
from is the session document the cut is coming out of: the paste
that completes it keeps its ids only where it lands back there.
Sourcepub fn cut_pins(
&mut self,
pins: &[PinId],
from: DocumentNonce,
) -> Option<Clipboard>
pub fn cut_pins( &mut self, pins: &[PinId], from: DocumentNonce, ) -> Option<Clipboard>
Copy a pin selection, then delete it — the pin half of a cut.
Sourcepub fn paste_snapshot(
&mut self,
clip: &Clipboard,
into: DocumentNonce,
target_top_left: Option<Pos2>,
) -> Vec<ShapeId>
pub fn paste_snapshot( &mut self, clip: &Clipboard, into: DocumentNonce, target_top_left: Option<Pos2>, ) -> Vec<ShapeId>
Insert clip into this scope, returning the roots so the caller can
select them. A payload this document’s own cut made, none of whose
sources it still holds, is the cut this paste completes and moves in
place; anything else duplicates.
into is the session document being pasted into — a paste into any
other document mints, however free the ids look.
target_top_left lands the group’s own top-left corner there; with no
target the group is offset diagonally so it does not hide its source.
Source§impl<'a> Drawing<'a>
impl<'a> Drawing<'a>
pub fn new( base: IndexedDocument<'a>, path: &'a BlockPath, presentation: &'a mut Presentation, gesture: &'a mut Gesture, ) -> Self
Sourcepub(super) fn indexed(&self) -> IndexedDocument<'_>
pub(super) fn indexed(&self) -> IndexedDocument<'_>
The document as this gesture has left it: the session’s prediction with the gesture’s own ops folded on. Every read goes through here, so a tool that just created a block can name it in the same frame.
Sourcepub(super) fn split(&mut self) -> (IndexedDocument<'_>, &mut Presentation)
pub(super) fn split(&mut self) -> (IndexedDocument<'_>, &mut Presentation)
Self::indexed and the presentation together, borrowing only the
fields each reads — for a pass that fills solved geometry while
reading the document it was solved from.
Sourcepub fn writability(&self) -> Writability
pub fn writability(&self) -> Writability
Whether this session may write at all — the answer the sink itself gives, so what the tools offer and what the write door accepts come from one value.
Whether the add-affordances that belong to no particular shape — the route-start targets, a wire’s handles — are on offer this frame.
Whether shape’s own add-affordances are on offer: the session must
be writable and the shape’s interface unlocked.
Sourcepub fn unlocked_scope(&self, block: BlockId) -> Option<UnlockedScope>
pub fn unlocked_scope(&self, block: BlockId) -> Option<UnlockedScope>
The proof a material interface edit needs on block, or None when
the lock refuses one — the read half of crate::edit::lock, for a
tool that must decide before it commits.
Sourcepub fn mint<K: IdKind>(&mut self) -> Id<K>
pub fn mint<K: IdKind>(&mut self) -> Id<K>
A fresh document-global id, taken from the document’s marks as this gesture has left them. The tools take the minted id back, so a gesture can anchor to what it just made.
Sourcepub(super) fn ids(&self) -> Allocator
pub(super) fn ids(&self) -> Allocator
The allocator an emitter mints a data-dependent number of ids from (paste). Every other creating emitter takes its ids pre-minted.
Author into the gesture. The one write door in the waist: emit
receives the document as Self::indexed would report it and the
sink to push into, and the prediction advances before it returns.
Sourcepub fn new_indexed(
base: IndexedDocument<'a>,
path: &'a BlockPath,
index: &'a SpatialIndex,
presentation: &'a mut Presentation,
gesture: &'a mut Gesture,
) -> Self
pub fn new_indexed( base: IndexedDocument<'a>, path: &'a BlockPath, index: &'a SpatialIndex, presentation: &'a mut Presentation, gesture: &'a mut Gesture, ) -> Self
Like Self::new, but with a spatial index (see the index field) so
broad-phase queries (culling, hit-testing) skip the full linear scan.
Sourcepub fn current_scope(&self) -> Scope
pub fn current_scope(&self) -> Scope
The scope being drawn: the path’s last segment, or the document root, which is a scope like any other.
Sourcepub(super) fn scope(&self) -> Option<&BlockIndex>
pub(super) fn scope(&self) -> Option<&BlockIndex>
What the current scope holds. None only when the scope’s block
has been deleted under the path.
Sourcepub(super) fn current(&self) -> Option<&Block>
pub(super) fn current(&self) -> Option<&Block>
The block whose interior is being drawn, or None at the document
root — which has a scope but no block entity behind it.
pub(super) fn held_block(&self, id: BlockId) -> Option<&Block>
pub fn held_pin(&self, id: PinId) -> Option<&Pin>
Sourcepub fn pin_shape(&self, pin: PinId) -> Option<ShapeId>
pub fn pin_shape(&self, pin: PinId) -> Option<ShapeId>
Which shape draws pin in this scope: the scope’s own boundary port,
or a stub on the child block that owns it. The port-vs-pin split is
resolved here, once, from the ownership the document records.
Sourcepub fn block_shape(&self, id: BlockId) -> Option<BlockShape<'_>>
pub fn block_shape(&self, id: BlockId) -> Option<BlockShape<'_>>
A child block as the geometry layer draws it — body plus the pins that
hang off it. The one unwrap of Self::shape’s block arm, so callers
reaching for BaseShape’s block-only methods do not each spell it.
Sourcepub fn pin_on_shape(&self, pin: PinId) -> Option<(ShapeRef<'_>, &Pin)>
pub fn pin_on_shape(&self, pin: PinId) -> Option<(ShapeRef<'_>, &Pin)>
The shape drawing pin here, paired with the pin entity: the stub’s
geometry hangs off the shape, its labels off the pin, and every
pin-level read wants both.
Sourcepub fn pin_owner_locked(&self, pin: PinId) -> bool
pub fn pin_owner_locked(&self, pin: PinId) -> bool
Whether the block that owns pin is locked. A locked block keeps
its pin/port interface frozen, so callers consult this before any
material pin edit.
Sourcepub fn current_locked(&self) -> bool
pub fn current_locked(&self) -> bool
Whether the current block (whose ports these are) is locked. The document root is never locked — there is no block to freeze.
Sourcepub fn shape_owner_locked(&self, id: ShapeId) -> bool
pub fn shape_owner_locked(&self, id: ShapeId) -> bool
Whether the block that owns id’s pins is locked: a child block by its own
flag, a port by the current block’s flag. Shapes without a pin interface
(text, area, image) are never locked.
Sourcepub fn shape_accents(&self) -> ShapeAccents<'_>
pub fn shape_accents(&self) -> ShapeAccents<'_>
The derived pin-accent lookup for the shapes of this scope: every stub drawn here takes its color from the wires routed here, whether it belongs to a child block or to the scope’s own boundary.
Sourcefn ordered<'s, K, T>(
&'s self,
ids: impl IntoIterator<Item = Id<K>>,
lookup: impl Fn(&'s DocDocument, &Id<K>) -> Option<&'s T>,
) -> Vec<(Id<K>, &'s T)>
fn ordered<'s, K, T>( &'s self, ids: impl IntoIterator<Item = Id<K>>, lookup: impl Fn(&'s DocDocument, &Id<K>) -> Option<&'s T>, ) -> Vec<(Id<K>, &'s T)>
ids resolved to their entities in chronological order — the
doc crate’s one draw-order policy, so painting, hit-testing, and the
router cannot disagree about which shape is on top.
Sourcepub fn child_blocks(&self) -> Vec<(BlockId, &Block)>
pub fn child_blocks(&self) -> Vec<(BlockId, &Block)>
The scope’s child blocks, in draw order.
Sourcepub fn block(&self, id: BlockId) -> Option<&Block>
pub fn block(&self, id: BlockId) -> Option<&Block>
One child block of this scope. A block the scope does not hold is not this drawing’s to read, even though the document holds it.
Sourcepub(super) fn block_pins(&self, scope: Scope) -> Vec<(PinId, &Pin)>
pub(super) fn block_pins(&self, scope: Scope) -> Vec<(PinId, &Pin)>
A scope’s own pins, in draw order — the set the geometry layer is handed alongside the block (or, at the root, the document’s own boundary), since a pin is its own entity.
fn scope_texts(&self) -> Vec<(TextId, &Text)>
fn scope_areas(&self) -> Vec<(AreaId, &Area)>
fn scope_images(&self) -> Vec<(ImageId, &Image)>
Sourcefn scope_owns(&self, owner: BlockId) -> bool
fn scope_owns(&self, owner: BlockId) -> bool
Whether this scope holds what owner names. A scope whose block has
been deleted under the path holds nothing, which is what keeps a
single lookup agreeing with a walk of the index’s per-scope sets.
Sourcefn scope_owned<'s, T: Entity>(
&'s self,
entity: Option<&'s T>,
owner: impl Fn(&T) -> BlockId,
) -> Option<&'s T>
fn scope_owned<'s, T: Entity>( &'s self, entity: Option<&'s T>, owner: impl Fn(&T) -> BlockId, ) -> Option<&'s T>
An entity, iff this scope owns it. Ownership is the owner
register, which is what the index’s per-scope sets are built from —
so this answers the same question as a scan of them, in one lookup.
Sourcefn asset(&self, hash: &AssetHash) -> Option<&Asset>
fn asset(&self, hash: &AssetHash) -> Option<&Asset>
The bytes an asset hash names, or None when the document does not
hold them — which the zero icon’s null hash also reads as.
Sourcepub fn delete(&mut self, what: Deletable)
pub fn delete(&mut self, what: Deletable)
Delete a shape or route. The cascade — a block’s subtree, the wires landing on any pin it carries, each wire’s labels — is the delete emitter’s own closure, so one selection is one commit however deep it reaches.
Sourcefn shape_targets(&mut self, shapes: &[ShapeId]) -> Vec<Target>
fn shape_targets(&mut self, shapes: &[ShapeId]) -> Vec<Target>
The entities shapes name, zeroing every icon among them on the way:
an icon is a value on its block, so it has no id for the cascade to
delete and its own emitter clears it instead.
Sourcepub(super) fn scope_route_ids(&self) -> Vec<RouteId> ⓘ
pub(super) fn scope_route_ids(&self) -> Vec<RouteId> ⓘ
The scope’s wires, in draw order — the doc crate’s one
chronological policy, so painting, hit-testing, and the crossing
pass all walk the same sequence.
pub(super) fn route(&self, id: RouteId) -> Option<&Route>
pub fn auto_routes(&self) -> impl Iterator<Item = (RouteId, Wire<'_>)>
Sourcepub fn auto_route(&self, id: RouteId) -> Option<Wire<'_>>
pub fn auto_route(&self, id: RouteId) -> Option<Wire<'_>>
One wire of this scope: the authored route bundled with the labels the index hangs off it. A route the scope does not hold is not this drawing’s to read, even though the document holds it.
Sourcepub fn add_route(
&mut self,
from: PinId,
to: RouteEnd,
waypoints: Vec<Waypoint>,
) -> RouteId
pub fn add_route( &mut self, from: PinId, to: RouteEnd, waypoints: Vec<Waypoint>, ) -> RouteId
Wire from to to along the solved waypoints, in this scope. A
destination the gesture drew onto a free slot arrives as
RouteEnd::Fresh and is
stamped in the same commit; an owner that refuses it takes the wire
with it.
Sourcepub fn route_geometry(&self, id: RouteId) -> Option<&RouteGeometry>
pub fn route_geometry(&self, id: RouteId) -> Option<&RouteGeometry>
The solved geometry beside id, or None for a route that has not
been reconstructed — nothing to draw or hit-test yet.
Sourcepub fn add_image(&mut self, placement: Placement, asset: &Asset) -> ShapeId
pub fn add_image(&mut self, placement: Placement, asset: &Asset) -> ShapeId
Create a free-floating background image with asset as its content,
boxed by placement, returning its id as a ShapeId.
pub fn image(&self, id: ImageId) -> Option<&Image>
Sourcepub fn icon(&self, id: BlockId) -> Option<&Icon>
pub fn icon(&self, id: BlockId) -> Option<&Icon>
The artwork block id carries, or None for the zero icon — an
empty box with the null asset is “no image”, not a blank picture.
Sourcepub fn set_icon(&mut self, id: BlockId, asset: &Asset)
pub fn set_icon(&mut self, id: BlockId, asset: &Asset)
Attach (or replace) block id’s icon with asset, sized to a default
box centered on the block.
pub fn add_block(&mut self, start: Pos2, end: Pos2) -> BlockId
Sourcepub fn add_rect_box(&mut self, start: Pos2, end: Pos2) -> BlockId
pub fn add_rect_box(&mut self, start: Pos2, end: Pos2) -> BlockId
Alias kept for callers that haven’t been updated yet.
Sourcepub fn add_text_box(&mut self, pos: Pos2) -> TextId
pub fn add_text_box(&mut self, pos: Pos2) -> TextId
Create an empty, default-sized text box with its top-left corner at
pos, returning its freshly assigned id. The caller typically follows up
by opening the text editor on the returned box.
pub fn text_box(&self, id: TextId) -> Option<&Text>
Sourcepub fn add_area(&mut self, start: Pos2, end: Pos2) -> ShapeId
pub fn add_area(&mut self, start: Pos2, end: Pos2) -> ShapeId
Create a boundary area covering the drag rectangle start..end,
returning its id as a ShapeId. The caller (the NewArea tool)
typically selects it afterwards.
Sourcepub fn areas(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
pub fn areas(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
Iterate the current level’s areas — the top layer, drawn above the
blocks and routes. Kept separate from Self::shapes so areas neither
render in the base layer nor act as routing obstacles.
Sourcepub fn add_port_auto_named(&mut self, inner: Rect) -> PinId
pub fn add_port_auto_named(&mut self, inner: Rect) -> PinId
Insert a port whose name is auto-derived from its freshly assigned id
("Port N"). The id is only known after insertion, hence the two-step
insert-then-rename. The boundary side+offset is picked from the
first entry of current().new_pin_locations(); the current block is
grown by one pin slot (one PIN_PITCH) in height if no boundary
location is available.
Sourcepub fn shape(&self, id: ShapeId) -> Option<ShapeRef<'_>>
pub fn shape(&self, id: ShapeId) -> Option<ShapeRef<'_>>
Generic lookup: returns a ShapeRef regardless of kind.
The pin-tag visibility of a selected port, for the selection bar’s toggle.
None for shapes that carry no such tag (blocks, text boxes, areas,
images).
Set the pin-tag visibility of a port — the counterpart to
shape_tag_hidden. No-op for other shapes.
Sourcepub fn set_role(&mut self, target: RoleTarget, role: Option<u8>)
pub fn set_role(&mut self, target: RoleTarget, role: Option<u8>)
Give target the accent role role (None clears it). A route’s
role repropagates the derived pin accents when the commit lands.
Sourcepub fn set_pins_kind(&mut self, pins: &[PinId], dir: PinDir)
pub fn set_pins_kind(&mut self, pins: &[PinId], dir: PinDir)
Set the I/O direction on every pin in the group whose owner is unlocked — a locked block keeps its pin interface frozen.
Sourcepub fn cycle_pin_kind(&mut self, pin: PinId)
pub fn cycle_pin_kind(&mut self, pin: PinId)
Cycle one pin’s I/O direction in place — the selected-stub click. A locked owner declines: direction is what a pin is.
Show or hide the location tags on a pin group.
Sourcepub fn set_block_locked(&mut self, block: BlockId, lock: InterfaceLock)
pub fn set_block_locked(&mut self, block: BlockId, lock: InterfaceLock)
Freeze or thaw a block’s pin interface.
Sourcepub fn set_title_text(&mut self, shape: ShapeId, text: &str)
pub fn set_title_text(&mut self, shape: ShapeId, text: &str)
Write text to shape’s title, if it carries one — a block or a
area.
Sourcepub fn place_title(&mut self, shape: ShapeId, placement: LabelPlacement)
pub fn place_title(&mut self, shape: ShapeId, placement: LabelPlacement)
Commit a dragged title’s placement.
Sourcepub fn set_type_label_text(&mut self, rect: BlockId, text: &str)
pub fn set_type_label_text(&mut self, rect: BlockId, text: &str)
Write text to block rect’s type label.
Sourcepub fn place_type_label(&mut self, rect: BlockId, placement: LabelPlacement)
pub fn place_type_label(&mut self, rect: BlockId, placement: LabelPlacement)
Commit a dragged type label’s placement.
Sourcepub fn label_fit(
&self,
pin: PinId,
name: Option<&str>,
type_name: Option<&str>,
) -> LabelFitWidth
pub fn label_fit( &self, pin: PinId, name: Option<&str>, type_name: Option<&str>, ) -> LabelFitWidth
The width pin pin’s port body must reach to hold its labels, with
name/type_name overriding what it holds now — the measurement a
rename or retype owes its emitter, which cannot make one for itself.
Sourcepub fn rename_pin(&mut self, pin: PinId, text: &str, fit: LabelFitWidth)
pub fn rename_pin(&mut self, pin: PinId, text: &str, fit: LabelFitWidth)
Rename a pin, widening the port body to fit its labels. A locked block keeps its pin interface frozen — the commit is dropped.
Sourcepub fn set_pin_tag(&mut self, pin: PinId, text: &str)
pub fn set_pin_tag(&mut self, pin: PinId, text: &str)
Set a pin’s location tag. Tags extend outward over the stub, so no widening. Locked owners drop the commit, as with renames.
Sourcepub fn retype_pin(&mut self, pin: PinId, text: &str, fit: LabelFitWidth)
pub fn retype_pin(&mut self, pin: PinId, text: &str, fit: LabelFitWidth)
Set a pin’s type label, widening the port body to fit. Locked owners drop the commit.
Sourcepub fn add_named_pin(
&mut self,
block: BlockId,
loc: PinLocation,
) -> Option<PinId>
pub fn add_named_pin( &mut self, block: BlockId, loc: PinLocation, ) -> Option<PinId>
Add a pin at loc on block, auto-named “Port N” from its ordinal.
Returns the id so the caller can anchor a route to it. A locked
block keeps its pin interface frozen — None.
Sourcepub fn apply_resize(&mut self, shape: ShapeId, new_rect: Rect)
pub fn apply_resize(&mut self, shape: ShapeId, new_rect: Rect)
Commit a handle-drag resize: the caller resolved the final rect (constraints, snapping, magnetism, which corner moved), this writes it — geometry, carried pins, and icon box.
Sourcepub fn move_pin_snapped(&mut self, pin: PinId, to: PinSlot)
pub fn move_pin_snapped(&mut self, pin: PinId, to: PinSlot)
Move a pin to to, which the gesture already resolved against the
live preview (BaseShape::pin_drop_candidate)
— so the drop lands exactly where the drag promised. A destination
another pin holds writes nothing.
Sourcepub fn set_route_name(
&mut self,
route: RouteId,
label: RouteLabelId,
text: &str,
)
pub fn set_route_name( &mut self, route: RouteId, label: RouteLabelId, text: &str, )
Name a wire. An empty/whitespace name removes label entirely and
clears the shared name, so the wire goes back to unlabeled rather
than carrying a blank slot.
Sourcepub fn set_text_box_content(&mut self, id: TextId, text: &str)
pub fn set_text_box_content(&mut self, id: TextId, text: &str)
Commit a text box’s content. Emptying the box discards it rather than leaving it invisible.
The extent is not written here: it is measured on demand by
Self::refresh_text_extents, because the text can change without an
editor being involved and a cache only filled by the editor goes
stale the moment it does.
Sourcepub fn refresh_text_extents(&mut self, painter: &Style<'_, impl Renderer>)
pub fn refresh_text_extents(&mut self, painter: &Style<'_, impl Renderer>)
Measure any text box in this scope whose cached extent no longer matches its text, so the box draws and hit-tests at its real size.
On demand rather than on commit. A box’s text changes under the cache whenever the editor was not what changed it — an undo, a redo — and an extent written only by the editor would leave those boxes on the character-count estimate until someone re-opened them. Cheap by construction: an entry that still matches its text is not measured again, so a frame that changed no text measures nothing.
Sourcepub fn add_route_label(
&mut self,
route: RouteId,
pos: Pos2,
) -> Option<RouteLabelId>
pub fn add_route_label( &mut self, route: RouteId, pos: Pos2, ) -> Option<RouteLabelId>
Drop a name label on route at the projection of pos onto its
polyline. None for a wire with no solved geometry to project onto.
Sourcepub fn place_route_label(&mut self, label: RouteLabelId, dist: FracVal)
pub fn place_route_label(&mut self, label: RouteLabelId, dist: FracVal)
Place a wire’s name label at an arc length along its route — the label drag’s one document write, of the distance the preview settled on.
Sourcepub fn flip_shape_pins(&mut self, id: ShapeId)
pub fn flip_shape_pins(&mut self, id: ShapeId)
Mirror a selected shape left/right. No-op for shapes without pins; the caller re-routes afterwards.
A port flips only its port_orientation (the way its stub faces), so
the pin it represents on the parent block doesn’t move. A block flips
the edge side of all its pins, but first freezes each pin’s
port_orientation to its current value — so descending into the block
shows the same boundary ports as before and its internal routes are left
intact.
Sourcepub fn wrap_top(&mut self)
pub fn wrap_top(&mut self)
Add a level above the whole document: a fresh root whose sole child is the old one, which demotes to a child rect.
Reachable from nothing on screen: a navigation button that quietly writes a block is the wrong door for it (docs/ui-issues-2.md, item 8), and the right one has not been chosen.
Sourcepub fn flip_block_vertical(&mut self, block: BlockId)
pub fn flip_block_vertical(&mut self, block: BlockId)
Vertically mirror a block’s pins about its center: a pin in slot offset
moves to slot h - offset, where h (crate::grid::max_pin_slot) is
the block’s
height in slots. Each pin keeps its side; only its vertical slot moves.
A double flip is an exact identity. The caller re-routes afterwards.
Sourcepub fn current_blocks(&self) -> impl Iterator<Item = (BlockId, &Block)>
pub fn current_blocks(&self) -> impl Iterator<Item = (BlockId, &Block)>
The current level’s child blocks paired with their ids, for callers that
need the Block directly rather than as a ShapeRef.
Sourcefn shape_of_block<'s>(&'s self, id: BlockId, block: &'s Block) -> BlockShape<'s>
fn shape_of_block<'s>(&'s self, id: BlockId, block: &'s Block) -> BlockShape<'s>
A block as the renderer sees it: its pins, and whether it opens a scope
of its own. The one place a Block becomes a BlockShape, so no
caller can hand the renderer a block whose interior it never asked about.
Sourcepub fn blocks_layer(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
pub fn blocks_layer(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
The child blocks of the current level, as renderable shapes — each bundled with the pins that hang off it.
Sourcepub fn ports_layer(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
pub fn ports_layer(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
The current level’s boundary ports, as renderable shapes: the scope’s
own pins, drawn as the port bodies their rect register places.
Sourcepub fn texts_layer(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
pub fn texts_layer(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
The current level’s text boxes, as renderable shapes.
Sourcepub fn images_layer(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
pub fn images_layer(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
The current level’s free-floating background images, as renderable shapes.
Sourcepub fn icons(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
pub fn icons(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
The current level’s block icons, as renderable shapes — the foreground
layer, drawn on top of everything (see
DrawingPasses).
Sourcepub fn shapes(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
pub fn shapes(&self) -> impl Iterator<Item = (ShapeId, ShapeRef<'_>)>
Iterate over all shapes (blocks first, then ports, then text boxes, then
images). This order is for non-render uses (hit-testing, copy); the
painted layer order lives in DrawingPasses.
Sourcepub fn can_relocate_pins(&self, moves: &[PinMove]) -> bool
pub fn can_relocate_pins(&self, moves: &[PinMove]) -> bool
Whether every destination is free and in bounds — the gate a group pin move’s preview asks before drawing it as valid. The same predicate the commit runs, so the preview cannot promise a move the emitter will refuse.
Sourcepub fn relocate_pins(&mut self, moves: &[PinMove]) -> bool
pub fn relocate_pins(&mut self, moves: &[PinMove]) -> bool
Apply a group pin move iff Self::can_relocate_pins holds; returns
whether it was applied. On success each pin takes its new slot.
Sourcepub fn nudge_pins(&mut self, pins: &[PinId], slot_delta: i32)
pub fn nudge_pins(&mut self, pins: &[PinId], slot_delta: i32)
Shift anchors rigidly by slot_delta slots (negative = up), keeping
each pin’s side. The shift is clamped to the tightest range that keeps
every pin on its block — like a multi-pin drag — so a
group moves as one and never runs off an edge.
Sourcepub fn content_bounds(&self, painter: &Style<'_, impl Renderer>) -> Option<Rect>
pub fn content_bounds(&self, painter: &Style<'_, impl Renderer>) -> Option<Rect>
World-space bounding box of everything this scope draws — the whole
diagram, wires, labels and waypoints included, not just the shapes that
hold them. Taken by running the real draw passes into a measuring
backend, so a shape kind added later joins the extent the moment it is
drawn. None when the scope draws nothing.
Sourcefn draw_key(id: ShapeId) -> (u8, ShapeId)
fn draw_key(id: ShapeId) -> (u8, ShapeId)
Where id sits in the draw order: its paint layer, then the
document’s one chronological order — ascending id — within that
layer. Sorting the index’s (unordered) hits by this reproduces the
linear Self::shapes walk exactly, so the two broad phases
cannot disagree about which shape is on top.
Sourcepub fn shape_candidates(&self, query: Rect) -> Vec<(ShapeId, ShapeRef<'_>)>
pub fn shape_candidates(&self, query: Rect) -> Vec<(ShapeId, ShapeRef<'_>)>
Shapes (blocks/ports/texts/images — not areas) whose coarse bounds
fall near query, in draw order. Index-limited when available;
otherwise every shape in Self::shapes order, which is the same
order. Areas are queried by their own (short) linear scan, so they
are excluded here.
Sourcepub fn hit_candidates(&self, query: Rect) -> Vec<(ShapeId, ShapeRef<'_>)>
pub fn hit_candidates(&self, query: Rect) -> Vec<(ShapeId, ShapeRef<'_>)>
Self::shape_candidates back-to-front: the shape painted last —
the one on top — comes first, so a top-down hit test takes the first
match. Hit order is the reverse of draw order, and this is the only
place that says so.
Sourcepub(super) fn preview_shapes(&mut self, previews: &[(ShapeId, Rect)])
pub(super) fn preview_shapes(&mut self, previews: &[(ShapeId, Rect)])
Record where this frame’s preview puts each shape. A block’s icon rides inside its block, so the block’s previewed rect is where the icon goes too — recorded here rather than by each tool that draws them together.
Sourcepub(super) fn scope_path(&self) -> &BlockPath
pub(super) fn scope_path(&self) -> &BlockPath
The scope this drawing is over, for a caller that has to say where something happened as well as what.
Sourcepub(super) fn preview_routes(&mut self, routes: Vec<RouteId>)
pub(super) fn preview_routes(&mut self, routes: Vec<RouteId>)
Record the wires this frame’s preview re-solved — the ones now drawn somewhere the document does not put them.
Sourcepub(crate) fn visible_ids(&self, viewport: Rect) -> Option<HashSet<HitId>>
pub(crate) fn visible_ids(&self, viewport: Rect) -> Option<HashSet<HitId>>
Ids to draw when culling the scene to viewport (world space): the
hittables whose bounds are on screen. None means “no index — draw
everything”, which is what the SVG export and tests want (they must not
cull). Shares the one index with the hit-test broad phase.
The index is keyed by the document value, so it answers for committed geometry only. A live preview moves where a shape paints without moving its rect, so this frame’s preview is asked too and its answers are unioned in — that set is the dragged shapes and the wires re-solved against them, never the document.
Sourcepub fn hops(&self, among: &[RouteId]) -> Hops
pub fn hops(&self, among: &[RouteId]) -> Hops
The hops each of among draws. among is in draw order and holds every wire through any
point whose hop is wanted — what the index reports for a rectangle, or
the whole scope (route_hops).
Sourcepub fn course<'h>(
&'h self,
id: RouteId,
hops: &'h [Crossing],
) -> Option<Course<'h>>
pub fn course<'h>( &'h self, id: RouteId, hops: &'h [Crossing], ) -> Option<Course<'h>>
How to draw id: its geometry and hops. None for a wire with no
solved geometry, which draws nothing.
Sourcepub(crate) fn wire_conflicts(
&self,
routes: &[RouteId],
shapes: &[ShapeId],
) -> Vec<Rect>
pub(crate) fn wire_conflicts( &self, routes: &[RouteId], shapes: &[ShapeId], ) -> Vec<Rect>
Where routes run through the routing shapes among shapes: each
illegal stretch of a wire that settled on its fallback L, grown half a
cell so the draw pass has an area to hatch. The same crossing the router
refuses a leg for, so the mark and the refusal cannot disagree. A shape
a preview is dragging counts where the preview draws it.
Sourcepub fn hops_of(&self, id: RouteId) -> Vec<Crossing>
pub fn hops_of(&self, id: RouteId) -> Vec<Crossing>
The hops one wire draws, against the wires the index finds near it — for a caller redrawing it alone, over the scene.
Sourcepub(crate) fn route_candidates(&self, query: Rect) -> Vec<(RouteId, Wire<'_>)>
pub(crate) fn route_candidates(&self, query: Rect) -> Vec<(RouteId, Wire<'_>)>
Routes whose coarse bounds fall near query. Index-limited when available,
sorted back into auto_routes() (insertion) order so that when wires
overlap — e.g. at a crossing — the same one wins as in the linear scan;
otherwise every route in auto_routes() order.
Source§impl Drawing<'_>
impl Drawing<'_>
Sourcepub fn resolve_at_pos(
&self,
pos: Pos2,
painter: &Style<'_, impl Renderer>,
) -> Option<HitTarget>
pub fn resolve_at_pos( &self, pos: Pos2, painter: &Style<'_, impl Renderer>, ) -> Option<HitTarget>
What pos lands on, in priority order: labels first (title, block type,
then a pin’s name / type / tag / stub), then a port body, then routes,
then any other shape body. None is empty canvas. A port is resolved
ahead of the routes so grabbing one always moves the port, never a route
crossing it; the rest of its body arrives as a plain HitTarget::Shape.
Source§impl Drawing<'_>
impl Drawing<'_>
pub fn port_at_pos(&self, pos: Pos2) -> Option<PinId>
Sourcepub fn pins_in_rect(&self, marquee: Rect) -> Vec<PinId> ⓘ
pub fn pins_in_rect(&self, marquee: Rect) -> Vec<PinId> ⓘ
Collect the child-block pins whose stub falls fully inside marquee.
Only pins on child blocks are returned; boundary ports are
marquee-selected as whole shapes, not as pins.
Sourcepub fn shape_at_pos(&self, pos: Pos2) -> Option<ShapeId>
pub fn shape_at_pos(&self, pos: Pos2) -> Option<ShapeId>
Find any shape at pos, honoring the paint layers top-down. Icons are the
foreground layer, tested first. Areas are next — but by their border
(and title), not their interior, so a click inside one falls through.
Images are the next annotation layer (above the blocks), tested by their
whole rect so an image drawn over a block is still selectable. Blocks,
ports, and text boxes come last.
Sourcepub fn image_at_pos(&self, pos: Pos2) -> Option<ImageId>
pub fn image_at_pos(&self, pos: Pos2) -> Option<ImageId>
Find the top-most free-floating image whose rect contains pos. Images
are an annotation layer above the blocks, so they are hit-tested before
blocks/ports (see Self::shape_at_pos). Later images (drawn on top) win
ties.
Sourcepub fn icon_at_pos(&self, pos: Pos2) -> Option<BlockId>
pub fn icon_at_pos(&self, pos: Pos2) -> Option<BlockId>
The block whose icon contains pos, if any. Icons are the foreground
layer (drawn above everything), so they are hit-tested before any other
shape (see Self::shape_at_pos). Later child blocks (drawn on top) win
ties.
Sourcepub fn area_at_pos(&self, pos: Pos2) -> Option<AreaId>
pub fn area_at_pos(&self, pos: Pos2) -> Option<AreaId>
Find an area whose border (within RESIZE_SHIM of the outline) or
title text contains pos. The interior is deliberately not hit-testable
so clicks pass through to shapes beneath the area. Later areas (drawn
on top) win ties.
pub fn anchor_at_pos(&self, pos: Pos2) -> Option<PinId>
Sourcepub fn anchor_targets(&self) -> Vec<(PinId, Pos2)>
pub fn anchor_targets(&self) -> Vec<(PinId, Pos2)>
Every pin/port anchor in the current view paired with its stub-end point.
The all-anchors generalization of Self::anchor_at_pos, used to drive the
route-start/end hover targets.
pub fn route_label_at_pos( &self, pos: Pos2, painter: &Style<'_, impl Renderer>, ) -> Option<(RouteId, RouteLabelId)>
pub fn route_at_pos(&self, pos: Pos2) -> Option<RouteId>
Sourcefn pin_part_at_pos(
&self,
pos: Pos2,
hit_rect: impl Fn(&ShapeRef<'_>, PinId, &Pin) -> Option<Rect>,
) -> Option<(PinId, PinLocation)>
fn pin_part_at_pos( &self, pos: Pos2, hit_rect: impl Fn(&ShapeRef<'_>, PinId, &Pin) -> Option<Rect>, ) -> Option<(PinId, PinLocation)>
The first pin whose hit_rect contains pos, scanning pin-bearing
candidates in layer order. hit_rect yields the already-padded rect for
the part of the pin being tested, or None for a pin that doesn’t draw
that part.
pub fn pin_text_at_pos( &self, pos: Pos2, painter: &Style<'_, impl Renderer>, ) -> Option<(PinId, PinLocation)>
Sourcepub fn pin_type_at_pos(
&self,
pos: Pos2,
painter: &Style<'_, impl Renderer>,
) -> Option<(PinId, PinLocation)>
pub fn pin_type_at_pos( &self, pos: Pos2, painter: &Style<'_, impl Renderer>, ) -> Option<(PinId, PinLocation)>
Like Self::pin_text_at_pos, but hit-tests each pin’s type label
(the smaller second line) instead of its name.
Sourcepub fn pin_stub_at_pos(&self, pos: Pos2) -> Option<(PinId, PinLocation)>
pub fn pin_stub_at_pos(&self, pos: Pos2) -> Option<(PinId, PinLocation)>
Like Self::pin_text_at_pos, but hit-tests each pin’s stub (the red
line) instead of its name. Used by tools that act on the stub.
Sourcepub fn pin_tag_at_pos(
&self,
pos: Pos2,
painter: &Style<'_, impl Renderer>,
) -> Option<(PinId, PinLocation)>
pub fn pin_tag_at_pos( &self, pos: Pos2, painter: &Style<'_, impl Renderer>, ) -> Option<(PinId, PinLocation)>
Like Self::pin_text_at_pos, but hit-tests each pin’s tag label
(drawn above the stub) instead of its name. A hidden tag draws nothing,
so it is not hit-testable. A shown but empty tag is hit-tested against its
“+tag” placeholder extent so the prompt is double-clickable to start
editing.
Sourcepub fn title_at_pos(
&self,
pos: Pos2,
painter: &Style<'_, impl Renderer>,
) -> Option<ShapeId>
pub fn title_at_pos( &self, pos: Pos2, painter: &Style<'_, impl Renderer>, ) -> Option<ShapeId>
Find a titled shape whose title text bbox contains pos. Blocks and
areas have titles; areas (the top layer) are tested first. Ports and
text boxes have no title and are skipped.
Sourcepub fn title_anchor_at_pos(&self, pos: Pos2) -> Option<ShapeId>
pub fn title_anchor_at_pos(&self, pos: Pos2) -> Option<ShapeId>
Find a titled shape whose title anchor handle is near pos. Blocks and
areas have title anchors; areas (the top layer) are tested first.
Source§impl Drawing<'_>
impl Drawing<'_>
Sourcepub fn conflicts(
&self,
shapes: &[ShapeId],
delta: Vec2,
moving: Moving,
) -> Vec<GridRect>
pub fn conflicts( &self, shapes: &[ShapeId], delta: Vec2, moving: Moving, ) -> Vec<GridRect>
The cells a move of shapes by delta would have to share with
something the router routes around — empty when it would be taken.
Asked of the same rule the commit is refused by
(edit_geometry::move_conflicts), so a drag cannot show a landing
the release then refuses.
Sourcepub fn constrain_move(&self, shape: ShapeId, delta: Vec2) -> Vec2
pub fn constrain_move(&self, shape: ShapeId, delta: Vec2) -> Vec2
The delta a move of shape will actually apply, so a drag preview can
match the commit. An icon is held inside the block it belongs to; every
other shape moves by delta unchanged.
Sourcepub fn move_shape(&mut self, id: ShapeId, delta: Vec2)
pub fn move_shape(&mut self, id: ShapeId, delta: Vec2)
Move any shape (block, port, text box, area, image, or icon) by
delta. Blocks and ports are collision-checked; annotations float
freely, and an icon is held inside the block it belongs to.
Sourcepub(super) fn riding_pins(
&self,
moved_blocks: &HashSet<BlockId>,
moved_ports: &HashSet<PinId>,
) -> HashSet<PinId>
pub(super) fn riding_pins( &self, moved_blocks: &HashSet<BlockId>, moved_ports: &HashSet<PinId>, ) -> HashSet<PinId>
The pins riding a set of moved shapes: a moved block carries its whole
boundary, a moved port is one pin of its own — the classification the
preview reconciles routes against. The commit runs the same rule from
the emitter’s side (edit_geometry::move_group).
Sourcepub fn trim_partial_route_approaches(&mut self, moved: &[ShapeId])
pub fn trim_partial_route_approaches(&mut self, moved: &[ShapeId])
Drop the stale approach waypoints on every route of this scope that
straddles a move: exactly one endpoint anchored to a moved shape. The
moved side’s leading (or trailing) auto-corners are removed so the
re-route regenerates a clean approach; routes fully inside or fully
outside the move keep their waypoints. Commit-time only: the
single-shape drop calls it directly, a group drag folds the same trim
into edit_geometry::move_group’s own riders, and the live preview
computes the identical set without applying it.
Sourcepub fn trim_anchor_approach(&mut self, pin: PinId)
pub fn trim_anchor_approach(&mut self, pin: PinId)
Trim the approach waypoints of every route ending on pin (a single
dragged pin or port), from that endpoint’s side.
Sourcefn trim_approaches(&mut self, riding: &HashSet<PinId>)
fn trim_approaches(&mut self, riding: &HashSet<PinId>)
One authoring for every wire the trim touches, as a group move’s riders are: each authored op re-folds the gesture and re-indexes the document, so a wire at a time paid that once per straddling wire. With no offset the riders leave a wire with both ends riding as it is.
Sourcepub fn move_shapes(&mut self, ids: &[ShapeId], delta: Vec2)
pub fn move_shapes(&mut self, ids: &[ShapeId], delta: Vec2)
Move several shapes rigidly by delta. Intra-group collisions are ignored
(the group keeps its relative layout); the move is rejected wholesale if
any moved shape would overlap a shape that is not part of ids. Each
route the selection touches is reconciled in the same commit: one fully
inside keeps its shape and shifts its corners rigidly, one that straddles
the set drops its stale approach on the moved side.
Source§impl Drawing<'_>
impl Drawing<'_>
Sourcepub fn solve_routes(&mut self, ripup: &[RouteId]) -> Promoted
pub fn solve_routes(&mut self, ripup: &[RouteId]) -> Promoted
Solve this scope’s wires against the settled document and report the corner lists the solve promotes. Read-only: the geometry lands in the presentation layer, and the promoted lists are the gesture funnel’s to push as ops.
Sourcepub fn solve_foreground(
&mut self,
foreground: &Foreground,
ripup: &[RouteId],
) -> Promoted
pub fn solve_foreground( &mut self, foreground: &Foreground, ripup: &[RouteId], ) -> Promoted
Re-solve only foreground’s wires. Every other wire in the scope keeps
the geometry it has and contributes it as occupancy, so the foreground
routes around the rest and lands last — which is what makes the result
depend on the selection, deliberately
(docs/foreground-router-playbook.md).
Sourcepub fn preview_drag(&mut self, _phase: &PreviewPhase, drags: &[(ShapeId, Vec2)])
pub fn preview_drag(&mut self, _phase: &PreviewPhase, drags: &[(ShapeId, Vec2)])
Suppose each (shape, offset) in drags displaced by its offset,
without moving the shapes themselves in the model: the previewed rects
the frame draws at, and — for the shapes that take part in routing — the
wires re-solved to track them. With grid-snapped offsets the geometry
matches what the real move on drop produces.
Sourcepub fn preview_resize(
&mut self,
_phase: &PreviewPhase,
resizes: &[(ShapeId, Rect)],
)
pub fn preview_resize( &mut self, _phase: &PreviewPhase, resizes: &[(ShapeId, Rect)], )
Suppose each (shape, rect) in resizes at that previewed geometry,
without resizing the shapes in the model — the resize-aware counterpart
of Self::preview_drag.
Sourcepub fn preview_pin_drag(
&mut self,
_phase: &PreviewPhase,
pin: PinId,
side: PinSide,
offset: u32,
)
pub fn preview_pin_drag( &mut self, _phase: &PreviewPhase, pin: PinId, side: PinSide, offset: u32, )
Re-route the routes touching pin as if it sat at (side, offset),
for the live drag preview. The hypothetical slot rides into the solve as
an override — anchor point and zero-cost channel both — so the pin itself
never moves; its routes’ approach corners are computed as trimmed so the
preview matches the clean re-route the drop produces.
Sourcepub fn preview_pin_drags(&mut self, _phase: &PreviewPhase, moves: &[PinMove])
pub fn preview_pin_drags(&mut self, _phase: &PreviewPhase, moves: &[PinMove])
Re-route as if every listed pin were already at its previewed
(side, slot) — the group equivalent of
preview_pin_drag, minus the approach trim
(the group flow never trimmed). Applies the whole move set as overrides
so the routes re-solve in a single pass while a multi-pin drag previews
them, without committing the relocation.
Sourcefn preview_foreground(
&self,
shapes: impl IntoIterator<Item = ShapeId>,
heading_for: &[(ShapeId, Rect)],
) -> Foreground
fn preview_foreground( &self, shapes: impl IntoIterator<Item = ShapeId>, heading_for: &[(ShapeId, Rect)], ) -> Foreground
What a preview may re-solve: the wires the moving shapes carry or
disturb, both where they are and where they are heading_for.
Sourcefn anchor_pos_overridden(
&self,
pin: PinId,
hypo: GeometryOverrides<'_>,
) -> Option<Pos2>
fn anchor_pos_overridden( &self, pin: PinId, hypo: GeometryOverrides<'_>, ) -> Option<Pos2>
Where a route endpoint anchors, honoring a hypo entry for the shape
(previewed rect) or the pin (previewed slot) it lands on. Which shape
draws the pin is Drawing::pin_shape’s one answer, and the anchor
math is the shape layer’s own — the same the emitters read.
Sourcefn routing_shapes(&self) -> Vec<(ShapeId, ShapeRef<'_>)>
fn routing_shapes(&self) -> Vec<(ShapeId, ShapeRef<'_>)>
The scope’s routing shapes — its child blocks and its own boundary ports, in draw order. Exactly what the router registers as obstacles and what the obstacle index tests, so a leg judged clear by one is judged clear by the other.
Sourcefn build_closed_router(
&self,
hypo: GeometryOverrides<'_>,
seed_points: &[Point],
) -> ClosedRouter
fn build_closed_router( &self, hypo: GeometryOverrides<'_>, seed_points: &[Point], ) -> ClosedRouter
Build the closed routing graph for this scope: seed each child/port
obstacle rect and its pin channels (at previewed geometry for any shape
or pin in hypo), plus a full channel at every point in seed_points
(route endpoints and waypoints), then freeze the graph. The seed points
are exactly the ones every route needs, so the closed graph contains a
node for every route’s endpoints and waypoints.
Sourcefn build_router_within(
&self,
within: Region,
hypo: GeometryOverrides<'_>,
seed_points: &[Point],
) -> ClosedRouter
fn build_router_within( &self, within: Region, hypo: GeometryOverrides<'_>, seed_points: &[Point], ) -> ClosedRouter
The same build, confined to within. A region keeps every block that
intersects it — a block straddling the edge blocks as much as it does
anywhere — and every seed point inside it. What that leaves out is the
rest of the diagram, which is the point: the lattice costs what the
region holds rather than what the sheet holds.
Sourcefn healing_lattice(
&self,
within: Region,
seeding: &Seeding<'_>,
routed: &HashSet<RouteId>,
) -> ClosedRouter
fn healing_lattice( &self, within: Region, seeding: &Seeding<'_>, routed: &HashSet<RouteId>, ) -> ClosedRouter
A lattice over region, with every wire not being routed laid in as
occupancy before anything routes — so the wires that do route land
last, around the rest.
Sourcefn heal<W>(
&mut self,
wires: Vec<(RouteId, W)>,
region: Rect,
seeding: &Seeding<'_>,
route: impl FnMut(RouteId, &W, &mut RouteGeometry, &mut ClosedRouter) -> Resolution,
)
fn heal<W>( &mut self, wires: Vec<(RouteId, W)>, region: Rect, seeding: &Seeding<'_>, route: impl FnMut(RouteId, &W, &mut RouteGeometry, &mut ClosedRouter) -> Resolution, )
Route wires through a lattice over region, everything else laid in
as occupancy first; then route the ones that fell back again, through a
lattice over the whole scope. A region too small to detour in is routine
and says nothing about the wire, so a wire is unresolved only when the
sheet itself holds no path — what it would have been before regions.
route lays one wire in the lattice it is given and says whether it
found a path. One that finds none over the scope keeps its fallback L:
that is what it settles on.
Sourcefn obstacle_rects(&self, overrides: &[(ShapeId, Rect)]) -> Obstacles
fn obstacle_rects(&self, overrides: &[(ShapeId, Rect)]) -> Obstacles
The obstacle rectangles of this scope, at previewed geometry for any
shape in overrides. These are exactly the rects
Self::build_closed_router registers as router blocks, wrapped for the
cheap “does a straight leg cross a block?” test used by reconstruction,
so a leg judged clear here is the same one the router would leave
straight — without building the routing graph.
Sourcefn preview_exclusions(
&self,
endpoints: &[(RouteId, Pos2, Pos2)],
spec: &PreviewSpec<'_>,
) -> HashMap<RouteId, PreviewExclusions>
fn preview_exclusions( &self, endpoints: &[(RouteId, Pos2, Pos2)], spec: &PreviewSpec<'_>, ) -> HashMap<RouteId, PreviewExclusions>
The waypoints each route must route around this preview frame: the
straddle trim (the moved side of a route with exactly one end riding the
gesture) plus the backtracking prune, both computed against the frame’s
hypothetical endpoints — previewed, never applied. A route fully inside the
gesture keeps its skeleton byte-identical: it previews through rigidly
offset waypoints and, moving rigidly, can’t introduce a reversal. Both
rules are the emitters’ own (crate::edit::geometry), read from the
preview’s side.
Sourcefn route_update_closed(
&mut self,
ripup: &[RouteId],
hypo: GeometryOverrides<'_>,
pass: RoutePass<'_>,
solving: Solving<'_>,
) -> Promoted
fn route_update_closed( &mut self, ripup: &[RouteId], hypo: GeometryOverrides<'_>, pass: RoutePass<'_>, solving: Solving<'_>, ) -> Promoted
Closed-graph route solver used by every path except live RouteTool
drawing: load, interactive commits, AND the drag/resize preview. It builds
the routing graph ONCE with all obstacle, endpoint, and waypoint geometry
(honoring overrides for previewed shapes and offsetting waypoints of
fully-dragged routes) seeded up front, then routes every route against it,
applying WIRE_COST occupancy by mutating existing edge weights in place —
so the graph is never rebuilt per route (the O(routes²) cost the old
per-route rebuild paid; see TUNING.md Finding 1).
pass distinguishes a permanent edit (a drop, delete, paste, nudge —
the geometry is final) from a transient drag/resize preview (recomputed
every frame from stable state). On commit a changed route is
re-reconstructed per leg — its straight legs are kept and only the legs that
are now blocked or non-colinear are routed — and its corners are promoted
to waypoints; the backtracking prune really removes reversal corners. A
preview never touches the document: it routes through the stable waypoint
skeleton minus its previewed trims and prunes (so per-frame recomputation
never piles up derived corners), taking only immutable borrows.
Sourcefn route_reaches(&self, id: RouteId, reconstructing: Reconstructing<'_>) -> bool
fn route_reaches(&self, id: RouteId, reconstructing: Reconstructing<'_>) -> bool
Is this wire one of the set being reconstructed? A wire with no geometry yet has never been reconstructed, so a rectangle always reaches it.
Sourcepub fn reconstruct_routes(&mut self)
pub fn reconstruct_routes(&mut self)
Reconstruct every route’s edge geometry from its stored corner waypoints WITHOUT globally re-routing. Straight (axis-aligned, unobstructed) legs are drawn directly; only non-colinear or obstacle-crossing legs are routed, and then only for the routes that need it. A clean block (every leg straight) is rebuilt with zero pathfinding, so stored/hand-adjusted geometry is preserved exactly. This is the load-time reconstruction; the interactive mutation path reuses the same per-leg policy.
Sourcepub(crate) fn reconstruct_routes_reaching(
&mut self,
reconstructing: Reconstructing<'_>,
)
pub(crate) fn reconstruct_routes_reaching( &mut self, reconstructing: Reconstructing<'_>, )
The same reconstruction, confined to the wires reconstructing names.
A wire it does not reach is drawn from geometry that is still correct —
nothing moved near it — so re-deriving it would spend the sheet’s time
to arrive back where it started. A commit that knows what it disturbed
passes that rectangle; an open, an undo or a foreign commit knows
nothing and passes Reconstructing::Everything; a preview’s next
borrow takes back Reconstructing::These wires it drew.
Sourcefn route_ends(&self, id: RouteId) -> Option<Endpoints>
fn route_ends(&self, id: RouteId) -> Option<Endpoints>
The route’s resolved, snapped anchor endpoints against the settled document — the ends every route-edit relayout runs between.
Sourcefn relay_route(
&mut self,
id: RouteId,
corners: &[GridPoint],
stored: &[Waypoint],
anchors: &[(RouteLabelId, Pos2)],
) -> Option<(Vec<Waypoint>, Vec<(RouteLabelId, FracVal)>)>
fn relay_route( &mut self, id: RouteId, corners: &[GridPoint], stored: &[Waypoint], anchors: &[(RouteLabelId, Pos2)], ) -> Option<(Vec<Waypoint>, Vec<(RouteLabelId, FracVal)>)>
Re-lay a single route’s edges directly from corners, WITHOUT the
router — straight legs stay straight and a diagonal leg gets an
L-bend, so the wire goes exactly where it was put and never
autoroutes. Returns the corner list the relayed geometry promotes and
each captured label anchor re-projected onto it: the pair the route
edit’s commit pushes as ops.
Sourcepub fn route_edit_session(
&self,
id: RouteId,
cursors: &[Pos2],
) -> Option<RouteEditSession>
pub fn route_edit_session( &self, id: RouteId, cursors: &[Pos2], ) -> Option<RouteEditSession>
Plan a route edit: classify where each cursor’s working corner lands on
route id — a grabbed existing corner within half a cell is reused,
anything else inserts in path order — and capture each label’s world
anchor. Read-only: Self::preview_route_edit renders the plan per
drag frame and Self::commit_route_edit applies it on release, so
between them the document is never written. Cursors must sit at least a
cell apart (the edge drag’s boundary seeds guarantee it); two cursors
collapsing onto one working corner abort the plan.
Sourcepub fn preview_route_edit(
&mut self,
_phase: &PreviewPhase,
id: RouteId,
session: &RouteEditSession,
cursors: &[Pos2],
)
pub fn preview_route_edit( &mut self, _phase: &PreviewPhase, id: RouteId, session: &RouteEditSession, cursors: &[Pos2], )
Relay route id directly through the session’s hypothetical corner
list at cursors — the pure per-frame preview of a route edit. Writes
derived geometry only; the authored route and its labels (the drag
overlay draws them pinned at the session’s anchors) are untouched.
Sourcepub fn commit_route_edit(
&mut self,
id: RouteId,
session: &RouteEditSession,
cursors: &[Pos2],
)
pub fn commit_route_edit( &mut self, id: RouteId, session: &RouteEditSession, cursors: &[Pos2], )
Finalize a route edit — the drag’s one document write. Relays the session’s working corners (locked: the user placed them), promotes the resulting corners so the hand-placed geometry persists, and re-anchors each label to its captured drag-start position.
Sourcepub fn reroute(&mut self, id: RouteId)
pub fn reroute(&mut self, id: RouteId)
Rip up a route entirely and autoroute it fresh: drop every waypoint so the endpoints re-route on Dijkstra cost alone, with no user-placed corners. The gesture’s solve rider re-promotes the corners the router finds.
Sourcepub fn reroute_block(&mut self, block: BlockId)
pub fn reroute_block(&mut self, block: BlockId)
Rip up and autoroute every wire of THIS scope with an endpoint on
block (either end): drop their user waypoints and let the rider
re-solve them. The block-wide analogue of Self::reroute.
Scoped deliberately: a block’s pins are its boundary ports, so the wires inside it end on the same ids. Those are drawn one level down, the rider does not re-solve them, and tearing up a path nobody re-lays would just lose it.
Sourcefn rip_up(&mut self, ids: &[RouteId])
fn rip_up(&mut self, ids: &[RouteId])
Forget what these wires were solved to, so the next pass re-solves them from nothing rather than keeping the path the user just tore up. The rip-up is the one gesture that must NOT be handed its own previous answer, and dropped geometry is how the solve is told so.
Sourcepub fn scratch_closed_router(&self, extra_seeds: &[Point]) -> ClosedRouter
pub fn scratch_closed_router(&self, extra_seeds: &[Point]) -> ClosedRouter
Closed-router view of the current scope’s geometry and existing-route
occupancy, for tools that pathfind against it without mutating the
document (RouteTool). The graph is built ONCE (obstacles + every existing
route’s endpoints and waypoints + extra_seeds), then existing routes are
re-applied as WIRE_COST occupancy in place — no per-route rebuild.
extra_seeds seeds the points the caller will route through (an in-progress
route’s endpoints/waypoints) so they exist as graph nodes.
Sourcepub fn healing_bound(
&self,
foreground: &Foreground,
) -> Option<(Rect, Vec<Mark>)>
pub fn healing_bound( &self, foreground: &Foreground, ) -> Option<(Rect, Vec<Mark>)>
Where a gesture on foreground routes, for the diagnostic overlay: the
healing region around every wire it raises, and the lattice the router
builds there with everything else laid in as occupancy.
The largest bound such a gesture uses: a pass heals only the raised
wires that need routing, and the region around those is inside this
one. None when the foreground raises no wire of this scope.
Auto Trait Implementations§
impl<'a> Freeze for Drawing<'a>
impl<'a> RefUnwindSafe for Drawing<'a>
impl<'a> Send for Drawing<'a>
impl<'a> Sync for Drawing<'a>
impl<'a> Unpin for Drawing<'a>
impl<'a> UnsafeUnpin for Drawing<'a>
impl<'a> !UnwindSafe for Drawing<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<D> OwoColorize for D
impl<D> OwoColorize for D
§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg] or
a color-specific method, such as [OwoColorize::green], Read more§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg] or
a color-specific method, such as [OwoColorize::on_yellow], Read more