pub struct Document {
pub engine: EngineState,
pub ecad: Editors,
pub ecad_blocks: [BlockSync; 4],
pub ecad_parts_revision: Option<u64>,
pub ecad_parts_reported: Vec<String>,
pub ecad_occurrences: Option<OccurrenceMark>,
pub ecad_outdated: Vec<String>,
pub ecad_update_requested: bool,
/* private fields */
}Expand description
ONE open model: the engine that owns it plus the identity the file lane needs — the store name it was opened from / saved to, and the clean baseline.
Fields§
§engine: EngineStateThe windowing-agnostic brain for THIS document (scene, camera, history, settings, selection). Panels borrow it; it is never forked.
ecad: EditorsThis document’s eCAD editors — Diagram, PCB, Symbol and Pads — kept
beside its engine, so each tab has its own and a tab switch keeps their
pan, zoom and view: a switch rebuilds the PANELS
(reset_document_scoped_state), never a document. Built with the
document; all four measured 0.65 ms (release), so no document waits for
its first eCAD workbench to have them.
ecad_blocks: [BlockSync; 4]Each editor’s standing with its block of this document’s history: what
takes BREP’s undo and redo to the editor, and the editor’s edits into the
document (ecad::BlockSync).
ecad_parts_revision: Option<u64>§ecad_parts_reported: Vec<String>The broken-reference lines [crate::panels::ecad_parts::sync] has
already put in front of the user. A device whose part is missing is a
STANDING state and the revision bumps on every edit, so without this it
would toast on every keystroke — the same rule
ecad::BlockSync::unreported keeps for an UNLINKED component.
ecad_occurrences: Option<OccurrenceMark>What [crate::panels::ecad_parts::follow_occurrences] last saw of the
assembly’s occurrences; None until the first frame looks.
ecad_outdated: Vec<String>The parts-library entries whose saved part has moved on since this
document took it — the shell’s UpdateComponents list for the active
document, handed over each frame so the Diagram and PCB workbenches can
mark the components placed from them and offer the update where the
user is looking (viewport::ecad).
ecad_update_requested: boolSet by the eCAD host’s Update parts button; the shell runs the update
(UpdateComponents::run, one undo step) on its next frame.
Implementations§
Source§impl Document
impl Document
Sourcepub fn new(engine: EngineState) -> Self
pub fn new(engine: EngineState) -> Self
Wrap engine as a document, taking its CURRENT model as the clean
baseline — so a freshly loaded (or freshly emptied) document is clean and
the first edit marks it dirty.
Sourcepub fn recovered(engine: EngineState, name: Option<String>) -> Self
pub fn recovered(engine: EngineState, name: Option<String>) -> Self
Wrap engine as a document RESTORED from the autosave blob
(crate::recovery): it carries the store identity it had (None for
an untitled one) and NO clean baseline, so it is dirty from its first
frame — the work it holds is exactly what was never saved, and the close
guard and the tab dot must say so until a Save writes it somewhere.
Sourcepub fn set_access(&mut self, access: Access)
pub fn set_access(&mut self, access: Access)
Make the document editable or read-only. Read-only locks the engine’s history, so its saved bytes cannot change until it is editable again.
Sourcepub fn take_refused(&mut self) -> Option<String>
pub fn take_refused(&mut self) -> Option<String>
The sentence to show when an edit was refused since the last call —
None when nothing was. Called once a frame by the shell, which toasts it.
pub fn set_name(&mut self, name: Option<String>)
Sourcepub fn mark_clean(&mut self)
pub fn mark_clean(&mut self)
Snapshot the current model as the clean baseline (after New / Open /
Save, or a ?loadModel= boot-load).
Sourcepub fn is_dirty(&self) -> bool
pub fn is_dirty(&self) -> bool
Dirty = the live model differs from the last saved/opened baseline.
(Rolling the history does NOT change the request document, so navigating
steps never marks dirty — only real edits/add/delete/reorder do.)
The workbench the document is in is not part of it ([signature]).
HONEST but not free: it serializes the whole request document, which for
an assembly carrying an embedded parts library is megabytes. Every place
where being wrong would cost the user work — the close prompt, Save —
calls THIS. The per-frame tab dot calls Self::dirty_marker instead.
Sourcepub fn edit_key(&self) -> (u64, u64)
pub fn edit_key(&self) -> (u64, u64)
What moves when the saved document can have changed: the APPLIED RUN generation and the history’s revision.
Both, because each misses edits the other sees. An ordinary edit (a
param change, add, delete, reorder, undo) re-runs the history, but a
block write runs nothing — a drawing sheet, a PMI label move, an eCAD
edit, a BOM part-attribute edit — and moves only the revision, which
every write to the SAVED document moves, the partsLibrary block
included (it is held in a field beside the document and both its setters
tick the revision themselves). An object-metadata change (a workbench
change is not an unsaved change at all, [signature]) moves neither and can
leave the dot one edit behind: a marker briefly optimistic, never a lost
edit, since Self::is_dirty is recomputed honestly at the close prompt.
Sourcepub fn refresh_dirty_marker(&mut self)
pub fn refresh_dirty_marker(&mut self)
The cached dirty flag the tab strip draws. Recomputing it serializes
the whole document, so it is recomputed only when the
Self::edit_key moved, and, once the tab is marked unsaved, only when
a RUN moved it (an ordinary edit, an undo, a redo).
The second rule is for drags. Dragging a block (a PMI label, a view on a sheet) writes the document every frame and moves only the revision; recomputing there serialized the document on every frame, 2.6 ms in a release build on a 1.3 MB assembly. An unsaved tab stays unsaved while only the revision moves, so a drag pays one serialization, on the frame the dot lights. Param-slider drags re-run the history each frame and still recompute each frame, as they always did.
The residue is deliberate: a block edit that lands exactly back on the
saved bytes keeps the dot on until the next run or Save. Showing unsaved
when clean costs one needless Save; the opposite loses work, which is
the bug the revision key fixed. Self::is_dirty stays honest at the
close prompt either way.
Sourcepub fn absorb_open_write(
&mut self,
before: &Value,
after: &Value,
key: (u64, u64),
)
pub fn absorb_open_write( &mut self, before: &Value, after: &Value, key: (u64, u64), )
Take a write that OPENING the document made — before and after are
the saved document either side of it, key the Self::edit_key before
it — as though the file had been saved that way: every top-level block
the write changed, and that was still as last saved, is moved in the
clean baseline too, and a tab dot that was current stays as it was.
For an eCAD editor’s first sight of an older board (viewport::ecad’s
store). Not Self::mark_clean: whatever else was unsaved before the
open stays unsaved. So the open changes nothing a document that needed no
bringing up would show — the honest Self::is_dirty and the dot alike.
Sourcepub fn dirty_checks(&self) -> u64
pub fn dirty_checks(&self) -> u64
How many times Self::refresh_dirty_marker has serialized the
document.
pub fn dirty_marker(&self) -> bool
Auto Trait Implementations§
impl !RefUnwindSafe for Document
impl !Send for Document
impl !Sync for Document
impl !UnwindSafe for Document
impl Freeze for Document
impl Unpin for Document
impl UnsafeUnpin for Document
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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.