pub struct ShortcutRegistry { /* private fields */ }Expand description
Two-layer registry of Shortcuts.
defaultsholds the records registered by widgets during theirbuild(). Re-registering the same id upserts: code-owned fields are updated, the user override (if any) is preserved.overridesholds user-supplied keystroke rebindings keyed by shortcut id. Overrides persist across widget rebuilds and even when the corresponding default is temporarily unregistered — graveyard semantics, so a widget that disappears and reappears keeps its user-customised bindings.
Every mutation bumps ShortcutRegistry::version so consumers
(menu labels, settings UIs) can observe that signal and re-read
through ShortcutRegistry::effective.
Implementations§
Source§impl ShortcutRegistry
impl ShortcutRegistry
pub fn new() -> Self
Sourcepub fn version(&self) -> &Signal<u64>
pub fn version(&self) -> &Signal<u64>
A reactive handle that ticks on every mutation (register, unregister, rebind, put_override). Menus and settings widgets observe it to refresh derived state.
Sourcepub fn effective_primary_signal(
&mut self,
id: &'static str,
) -> Signal<Option<KeyStroke>>
pub fn effective_primary_signal( &mut self, id: &'static str, ) -> Signal<Option<KeyStroke>>
A reactive handle to the effective primary keystroke for a
single shortcut id, created lazily and seeded with the current
value. It ticks only when that id’s resolved primary actually
changes — registering, unregistering or rebinding any other
shortcut leaves it untouched.
This is the granular counterpart to Self::version: a widget
that displays one shortcut’s accelerator (a menu item, a
tooltip) should bind this and update its label as a leaf value,
rather than observing the coarse global version and rebuilding.
Sourcepub fn register(&mut self, shortcut: Shortcut) -> Option<Shortcut>
pub fn register(&mut self, shortcut: Shortcut) -> Option<Shortcut>
Upsert a shortcut default without an owner. If id already
exists this replaces the code-owned fields but
preserves any existing user override.
Use ShortcutRegistry::register_owned to tie the lifetime
of a registration to a widget (so arena destroy can clean up
automatically).
Sourcepub fn register_owned(
&mut self,
shortcut: Shortcut,
owner: WidgetId,
) -> Option<Shortcut>
pub fn register_owned( &mut self, shortcut: Shortcut, owner: WidgetId, ) -> Option<Shortcut>
Upsert a shortcut default owned by owner. When owner is
destroyed, the framework calls
ShortcutRegistry::unregister_all_for_owner to remove this
registration. Preserves user overrides identically to
ShortcutRegistry::register.
Sourcepub fn unregister(&mut self, id: &str) -> Option<Shortcut>
pub fn unregister(&mut self, id: &str) -> Option<Shortcut>
Remove a default by id. The user override for that id (if any) stays in the graveyard so it can be re-applied if the shortcut is later re-registered.
Sourcepub fn unregister_all_for_owner(&mut self, owner: WidgetId)
pub fn unregister_all_for_owner(&mut self, owner: WidgetId)
Remove every shortcut registered by owner. Called by the
widget tree when a widget is destroyed — keeps the registry
from leaking entries whose on_activate closures may capture
state owned by the destroyed widget.
Sourcepub fn owner_of(&self, id: &str) -> Option<WidgetId>
pub fn owner_of(&self, id: &str) -> Option<WidgetId>
The widget id that currently owns id, if any.
pub fn len(&self) -> usize
pub fn is_empty(&self) -> bool
Sourcepub fn iter_defaults(&self) -> impl Iterator<Item = &Shortcut>
pub fn iter_defaults(&self) -> impl Iterator<Item = &Shortcut>
Iterate the raw defaults (no overrides merged). Most UI code
wants ShortcutRegistry::iter_effective instead.
Sourcepub fn get_default(&self, id: &str) -> Option<&Shortcut>
pub fn get_default(&self, id: &str) -> Option<&Shortcut>
Borrow the raw default record.
Sourcepub fn override_for(&self, id: &str) -> Option<KeyStrokeOverride>
pub fn override_for(&self, id: &str) -> Option<KeyStrokeOverride>
Current override for id, if any.
Sourcepub fn put_override(
&mut self,
id: impl Into<String>,
override_: KeyStrokeOverride,
)
pub fn put_override( &mut self, id: impl Into<String>, override_: KeyStrokeOverride, )
Set the full override for id. Intended for loading persisted
user preferences at app startup.
Sourcepub fn rebind_primary(
&mut self,
id: impl Into<String>,
keystroke: Option<KeyStroke>,
)
pub fn rebind_primary( &mut self, id: impl Into<String>, keystroke: Option<KeyStroke>, )
Set the primary slot of the override for id. The secondary
slot is left untouched — with per-slot SlotOverride
semantics the untouched slot continues to delegate to
whatever default the shortcut currently declares.
Sourcepub fn rebind_secondary(
&mut self,
id: impl Into<String>,
keystroke: Option<KeyStroke>,
)
pub fn rebind_secondary( &mut self, id: impl Into<String>, keystroke: Option<KeyStroke>, )
Set the secondary slot of the override for id. The primary
slot stays in whatever state it was (Default or user-set).
Sourcepub fn clear_override(&mut self, id: &str)
pub fn clear_override(&mut self, id: &str)
Drop the user override for id, restoring the declared defaults.
Sourcepub fn clear_all_overrides(&mut self)
pub fn clear_all_overrides(&mut self)
Clear every override. Restores the declared defaults for all registered shortcuts. Graveyard entries are dropped too.
Sourcepub fn export_overrides(&self) -> HashMap<String, KeyStrokeOverride>
pub fn export_overrides(&self) -> HashMap<String, KeyStrokeOverride>
Snapshot of the full override map, suitable for persisting to disk. Cloned intentionally so callers can serialize without holding a borrow on the registry.
Sourcepub fn import_overrides(
&mut self,
overrides: HashMap<String, KeyStrokeOverride>,
)
pub fn import_overrides( &mut self, overrides: HashMap<String, KeyStrokeOverride>, )
Replace the entire override map from a persisted snapshot. Typically called once at app startup after loading user preferences from disk. Overrides for ids that are not yet registered are kept in the graveyard so they apply whenever the widget that declares the corresponding default shows up.
Sourcepub fn effective(&self, id: &str) -> Option<EffectiveShortcut<'_>>
pub fn effective(&self, id: &str) -> Option<EffectiveShortcut<'_>>
Effective (defaults + overrides) view of id. None when the
id has no registered default — overrides alone don’t manifest
as effective records, but they’re kept in the graveyard.
Sourcepub fn iter_effective(&self) -> impl Iterator<Item = EffectiveShortcut<'_>>
pub fn iter_effective(&self) -> impl Iterator<Item = EffectiveShortcut<'_>>
Iterate all effective shortcuts, including currently-disabled
ones. The per-item enabled flag lets settings UIs render
disabled rows greyed out.
Order is deterministic: sorted by (category, id) so repeated
calls produce identical sequences regardless of the internal
HashMap insertion order.
Sourcepub fn find_conflict(
&self,
keystroke: KeyStroke,
excluding_id: Option<&str>,
) -> Option<&'static str>
pub fn find_conflict( &self, keystroke: KeyStroke, excluding_id: Option<&str>, ) -> Option<&'static str>
Find the first shortcut id that genuinely conflicts with
keystroke, excluding excluding_id if given. Used by settings
UIs to auto-unbind conflicts when the user rebinds a chord.
Includes disabled shortcuts — a chord is “taken” regardless of
whether its current binding is live.
Scope-aware. Two shortcuts only conflict when they could be
simultaneously active: either one is ShortcutScope::Global
(active everywhere), or both are ShortcutScope::Scoped to the
same widget. Two shortcuts scoped to different widgets —
e.g. a Delete binding in two separate panels — are not a
conflict, because the dispatcher resolves them by focus. (The
registry can’t see the tree, so two different Scoped ids are
assumed disjoint; the rare genuinely-nested overlap is left
unflagged, erring toward allowing the binding.)
When excluding_id is None (or names an unregistered id) the
“self” scope is unknown, so every same-chord shortcut is flagged
— the safe, conservative fallback.
Sourcepub fn matches_by_keystroke(
&self,
keystroke: KeyStroke,
) -> impl Iterator<Item = EffectiveShortcut<'_>>
pub fn matches_by_keystroke( &self, keystroke: KeyStroke, ) -> impl Iterator<Item = EffectiveShortcut<'_>>
All effective shortcuts whose primary or secondary keystroke
matches and are currently enabled, in the deterministic
(category, id) order of iter_effective.
The dispatcher needs every same-chord candidate, not just the
first: the first by id-order may be a Scoped binding whose
subtree doesn’t contain the current focus (and so must yield to
an applicable Global one), or a Global binding that should
itself yield to an in-focus Scoped one (most-specific-scope
wins). Resolving that needs the widget tree (descendant checks),
which the registry can’t see — so it hands back all candidates
and the dispatcher selects with focus in hand.
Sourcepub fn find_by_keystroke(
&self,
keystroke: KeyStroke,
) -> Option<EffectiveShortcut<'_>>
pub fn find_by_keystroke( &self, keystroke: KeyStroke, ) -> Option<EffectiveShortcut<'_>>
First effective shortcut whose primary or secondary keystroke
matches and is currently enabled. Disabled shortcuts are
invisible to the dispatcher — the keystroke falls through to
the focused widget’s normal on_key handling, matching the
“treated as if not registered” semantic advertised by
Shortcut::enabled_when.
Note: this ignores scope applicability — for focus-aware
resolution the dispatcher uses
matches_by_keystroke instead.