pub struct Dispatcher<R: Resource> { /* private fields */ }Expand description
Submits a view’s edits. Cloneable; clones share one queue.
Two doors, one path. submit and apply
queue an invocation the host resolves after the event, exactly as a
control bound to an action would. apply_now applies
one typed action immediately, inside the event or the settle pass
(Widget::settle), for an editor that must
see the result of its own edit before the next keystroke (the paragraph a
split created, the cell a table insert made). Both check the
participant’s permission, apply through the replayable executor with
attribution, and are undone per author.
§A drag as one undo step
A slider or a drag handle a surface draws itself applies each value it
passes through with apply_now, so the document — and
every collaborator — follows the drag live. The resource declares that
one value continues the one before it (Resource::coalesces: the same
field of the same item), which makes the whole drag one step, and the
surface calls settle when the pointer is let go, so the
next drag is a step of its own:
fn coalesces(previous: &Action, next: &Action) -> bool {
matches!((previous, next), (Action::SetLevel(..), Action::SetLevel(..)))
}
// In the surface's `handle_event`:
WindowEvent::CursorMoved { .. } if self.dragging => {
let _ = self.dispatch.apply_now(&mut ctx.edits(), &Action::SetLevel(level));
}
WindowEvent::MouseInput { state: ElementState::Released, .. } => {
self.dragging = false;
self.dispatch.settle();
}A toolkit slider bound with ViewCx::control instead invokes its action
once per drag when built with Slider::commits_on_release.
Implementations§
Source§impl<R: Resource> Dispatcher<R>
impl<R: Resource> Dispatcher<R>
Sourcepub fn me(&self) -> Option<&str>
pub fn me(&self) -> Option<&str>
Who edits through this dispatcher: the participant this view is
for, the same id an action they invoke reads as its author
(ActionCx::author). None in a
view of a past version, which nobody edits.
Sourcepub fn is_past(&self) -> bool
pub fn is_past(&self) -> bool
Whether the view shows a past version in History mode, drawn from a frozen document. Such a view must start no work: no worker, no network, no files. A surface that would fetch or watch something presents what the document holds instead.
Sourcepub fn read_only(&self) -> bool
pub fn read_only(&self) -> bool
Whether edits from this participant will be refused, as of now: it follows role changes while the app runs. Surfaces use it to present themselves read-only instead of letting an edit bounce.
Sourcepub fn read_only_state(&self) -> LocalState<bool>
pub fn read_only_state(&self) -> LocalState<bool>
Self::read_only as observable state, for a widget that shows or
disables something while the participant may only view.
Sourcepub fn permission_state(&self, need: ActionNeed) -> LocalState<bool>
pub fn permission_state(&self, need: ActionNeed) -> LocalState<bool>
Whether the host currently allows what need is, as observable view
state. It follows changes even when writing remains allowed and the
resource document does not change. Bind it to a conditional pane or
label; action invocation still checks the host’s current authority.
Sourcepub fn govern_state(&self) -> LocalState<bool>
pub fn govern_state(&self) -> LocalState<bool>
Whether the participant may govern the room (invite, grant, change its settings), as observable view state: for an owner’s pane.
Sourcepub fn may(&self, need: &ActionNeed) -> bool
pub fn may(&self, need: &ActionNeed) -> bool
Whether the participant may, as of now, do what need is: an
undoable change for most edits, one of the comments for a reply.
Sourcepub fn may_govern(&self) -> bool
pub fn may_govern(&self) -> bool
Whether the participant may, as of now, change the room’s settings.
Sourcepub fn may_apply(&self, action: &R::Action) -> bool
pub fn may_apply(&self, action: &R::Action) -> bool
Whether the participant may apply action
(tilo_resource::need_of).
Sourcepub fn refused(&self) -> LocalState<Option<Refused>>
pub fn refused(&self) -> LocalState<Option<Refused>>
The last edit or effect submitted here that was refused — denied permission, unavailable, failed — and why, for a view to show. An edit waiting for the user’s confirmation is not refused.
Sourcepub fn landed(&self) -> LocalState<Option<Landed>>
pub fn landed(&self) -> LocalState<Option<Landed>>
The last submission of this view the door applied, with what it
answered: the ids a “new” verb minted (Landed::minted), for a
surface that opens what it just created.
Sourcepub fn effect<E: Effect>(&self, effect: &E)
pub fn effect<E: Effect>(&self, effect: &E)
Invoke one of the app’s effects (dispatcher.effect(&Backups::BackUp))
through the same door as a button bound to it: permission, the
effect’s availability and a destructive effect’s confirmation are
checked, then its handler runs. A participant who may only view still
invokes the effects declared kind = "read".
Sourcepub fn effect_on<E: Effect>(&self, row: &str, effect: &E)
pub fn effect_on<E: Effect>(&self, row: &str, effect: &E)
Invoke effect as the live row row offers it
(LiveRow::effect): under the row’s
contract, so a confirmation the row asks for (typing the name of the
device it erases) is asked here too.
Sourcepub fn submit(&self, submit: impl Submit<R>)
pub fn submit(&self, submit: impl Submit<R>)
Submit a field edit (dispatcher.submit(p.favorite.set(true))) or a
verb (dispatcher.submit(Snippets::DELETE.with(id))) through the
door, after the event, as a control bound to it would.
An effect’s invocation (Invoke::effect) reaches its handler as
Self::effect does.
Sourcepub fn open_search(&self, request: &SearchRequest)
pub fn open_search(&self, request: &SearchRequest)
Open the platform search with request, narrowed to this app or one
part of it (SearchRequest::within). Searching is a view, so a
participant who may only view can search too.
Ask for the link to resource (this resource or one nested in it,
such as an item) as a control bound to its share-link would: the
framework copies it to the clipboard and reports it in
Self::landed, or why there is none in Self::refused. A link
grants nothing, so a participant who may only view asks too.
Sourcepub fn apply(&self, action: &R::Action)
pub fn apply(&self, action: &R::Action)
Submit one typed action value — an edit with no named declaration,
such as a drag’s final geometry. The door applies it after the
event; if it refuses it, Self::refused says why.
Sourcepub fn group<T>(&self, edits: impl FnOnce() -> T) -> T
pub fn group<T>(&self, edits: impl FnOnce() -> T) -> T
Submit every edit edits makes through this dispatcher (or a clone
of it) as one action: one change, one version in history, one undo
step. For a gesture that is several edits — split a linked clip pair,
delete a selection — which the user takes back with one Ctrl+Z.
One action is one undo step by default; a group is the explicit exception. Groups nest: the outermost one submits. A group of one edit submits that edit unchanged.
Sourcepub fn begin_group(&self) -> DispatchGroup<R>
pub fn begin_group(&self) -> DispatchGroup<R>
Open a group that submits when the returned guard drops: the
group for code whose edits are spread over a scope,
such as one input event of a custom surface.
Sourcepub fn submit_now(
&self,
edits: &mut Edits<'_>,
submit: impl Submit<R>,
) -> Result<(), ActionError>
pub fn submit_now( &self, edits: &mut Edits<'_>, submit: impl Submit<R>, ) -> Result<(), ActionError>
Apply a field edit (p.title.splice(..)) or a verb to the document
edits lends, now, as Self::apply_now applies a typed action: for
an editor that must see its own edit before the next keystroke.
One that needs confirming (a destructive verb, a removal) is not
applied now: it goes to the host’s door, which asks first, and
applies once the person agreed, as Self::submit does.
§Errors
Returns why the submission does not build, or as Self::apply_now.
Sourcepub fn apply_now(
&self,
edits: &mut Edits<'_>,
action: &R::Action,
) -> Result<(), ActionError>
pub fn apply_now( &self, edits: &mut Edits<'_>, action: &R::Action, ) -> Result<(), ActionError>
Apply one typed action to the document edits lends — an event’s,
or a settle pass’s — now, attributed to the participant, with history
recording what the action did.
One event’s actions are one undo step, and an action that continues
the previous one (Resource::coalesces, the next letter of a word)
joins its step. An action that needs confirming (a destructive verb,
a removal) is not applied now: it is submitted to the host’s door,
which asks the person first (Self::apply).
§Errors
Returns ActionError::Refused for a participant who may only view,
and the action’s own refusal; nothing is written either way.
Sourcepub fn apply_confirmed(
&self,
edits: &mut Edits<'_>,
action: &R::Action,
) -> Result<(), ActionError>
pub fn apply_confirmed( &self, edits: &mut Edits<'_>, action: &R::Action, ) -> Result<(), ActionError>
Self::apply_now of an action the person already confirmed, as
the host applies it once they agreed: what a test resolving the
queue as confirmed applies.
§Errors
As apply_now.
Sourcepub fn child<C: Resource>(
&self,
id: &str,
wrap: impl Fn(C::Action) -> R::Action + 'static,
) -> Dispatcher<C>
pub fn child<C: Resource>( &self, id: &str, wrap: impl Fn(C::Action) -> R::Action + 'static, ) -> Dispatcher<C>
The dispatcher of a resource nested in this one at id — a note’s
rich-text body, a draft’s SQL — whose every edit is this resource’s
action wrap(edit).
The child is edited like a root: its named actions,
apply, group and
apply_now take C’s own actions, coalesce into
undo steps by C’s Resource::coalesces, and history names them
after C’s labels. Underneath, each applies as this resource’s
action: the same permission check, history, undo and replay. Queued
invocations are addressed to the child resource id, so this
resource publishes the child at the same id with the same wrap
([tilo_resource::publish_child] in Resource::children), which
is also what lets the palette, agents and scripts reach it.
Sourcepub fn settle(&self)
pub fn settle(&self)
End the gesture the last immediate actions belonged to: the pointer
was let go of a slider or a drag handle. The next action starts a
step of its own even when it would continue the last one
(Resource::coalesces), so two drags of one slider are two undo
steps while every value one drag passes through is one.
Sourcepub fn app_id(&self) -> &'static str
pub fn app_id(&self) -> &'static str
The id of the app whose resource this is, which presence keys name
(ResourceSelection::presence).
Trait Implementations§
Auto Trait Implementations§
impl<R> Freeze for Dispatcher<R>
impl<R> !RefUnwindSafe for Dispatcher<R>
impl<R> !Send for Dispatcher<R>
impl<R> !Sync for Dispatcher<R>
impl<R> Unpin for Dispatcher<R>
impl<R> UnsafeUnpin for Dispatcher<R>
impl<R> !UnwindSafe for Dispatcher<R>
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
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§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.§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.§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.§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.§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>
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 more