Vixen
02b45cc4
csharp
public sealed class KeyMap

Which chord runs which command.

Read the guide page for this →

Remarks

Three layers: the defaults the application ships, a preset, and the overrides the user made. Only the last is saved, which is what makes "we moved Save All to Ctrl+Alt+S in 0.3" reach everyone who had not deliberately rebound it — a keymap file holding every binding freezes the defaults at the version the user first ran, and every editor that shipped one has a support burden to prove it.

⚠ The preset is a layer and not an edit, and doc 20's A5 says why that is the work. Choosing Unreal and then rebinding one key has to leave the other two hundred following the preset; a preset applied by copying its bindings into the user's file would make the next preset update reach nobody who had ever rebound anything. See KeyMapPreset.

⚠ The layers are composed, so a higher one takes a chord off a lower one. A command whose effective chord has already been claimed by a more specific layer ends up unbound rather than sharing it — which is what makes a preset able to move Play onto the palette's key without the preset having to say where the palette went for every command it displaces. Within one layer the order is the command id's, so the composition is the same every time.

⚠ Conflicts are detected, not resolved — within a context. A chord belongs to at most one command per context, so binding an occupied chord fails and says who has it; the caller decides whether to ask the user and rebind with Bind's replace. Two commands sharing a chord in one context would be an editor where the same keystroke does different things depending on which handler happened to be registered first.

⚠ Across contexts, sharing a chord is the point rather than the hazard. Delete in the outliner and Delete in the content browser are two commands and one key, and an editor that made the second of them pick another key would be one nobody's fingers can use. ContextOf is how this class finds out which context a command belongs to — the registry answers it, so the declaration lives on the command and not in a second table here — and a binding made in a context shadows the global one for as long as that context has the focus.

Bindings survive the commands they name. A chord bound to a plugin's command is kept while the plugin is unloaded, so reinstalling it restores the user's shortcut instead of quietly dropping it — the same reason a saved dock layout keeps a panel it cannot currently show.

Fields and properties (6)

  • public IReadOnlyDictionary<string, KeyChord> Bindings

    Every binding in force, as command id to chord.

  • public IReadOnlyDictionary<string, KeyChord> Defaults

    What the application declared, underneath whatever is on top of it.

  • public KeyMapPreset? Preset

    Which preset is in force, or for the shipped defaults.

  • public string PresetName

    What Preset is called, or Vixen.

  • public Func<string, KeyMapPreset?> PresetSource

    Where a preset named in a keymap file is looked up.

  • public Func<string, string?>? ContextOf

    Which context a command belongs to, asked whenever a chord is claimed or resolved.

Events (1)

  • public Action<KeyMap>? Changed

    Raised after anything changes a binding.

Methods (15)

  • public BindResult SetDefault(string commandId, KeyChord chord)

    Declares what a command is bound to out of the box.

  • public BindResult Bind(string commandId, KeyChord chord, bool replace = false)

    Gives a command a chord, as the user asking for it.

  • public bool ResetBinding(string commandId)

    Drops the user's override for a command, so it follows the preset or the default again.

  • public void UsePreset(KeyMapPreset? chosen)

    Puts a preset in force, keeping the user's own overrides on top of it.

  • public bool UsePreset(string? name)

    Puts a preset in force by name, through PresetSource.

  • public string? CommandFor(KeyChord chord, string? context = null)

    What has a chord in a context, if anything.

  • public void Reserve(string commandId)

    Makes a command's key beat any context that binds the same chord.

  • public bool IsReserved(string commandId)

    Whether a command's key beats any context.

  • public KeyChord ChordFor(string commandId)

    What a command is bound to.

  • public BindingSource SourceOf(string commandId)

    Which layer a command's binding came from.

  • public bool IsCustomised(string commandId)

    Whether the user has bound a command themselves.

  • public IEnumerable<string> Ids()

    Every command that any layer has an opinion about, in id order.

  • public void Reset()

    Throws the user's overrides away, leaving the preset and the defaults.

  • public string Save()

    The user's overrides and their chosen preset, as YAML.

  • public void Load(string yaml)

    Applies a user keymap over the defaults.

Used by (28)

  • BlockoutModeVixen.Editor.Blockout
  • BlockoutModeTestsVixen.Editor.Blockout.Tests
  • CommandDispatcherVixen.Editor.Ui
  • CommandPaletteSourceVixen.Editor.Ui
  • CommandTestsVixen.Editor.Ui.Tests
  • EditorApplicationVixen.Editor.App
  • EditorModeTestsVixen.Editor.App.Tests
  • EditorShellVixen.Editor.Ui
  • EditorShellTestsVixen.Editor.Ui.Tests
  • FoliageModeVixen.Editor.Terrain
  • FoliageModeTestsVixen.Editor.Terrain.Tests
  • KeyBindingsPanelTestsVixen.Editor.App.Tests
  • KeyBindingsViewVixen.Editor.Ui
  • KeyMapPresetTestsVixen.Editor.Ui.Tests
  • MenuBarTestsVixen.Editor.App.Tests
  • MenuCompositionTestsVixen.Editor.Ui.Tests
  • MenuPresenterVixen.Editor.Ui
  • MenuTestsVixen.Editor.Ui.Tests
  • MilestoneE3TestsVixen.Editor.App.Tests
  • ModeTestsVixen.Editor.Ui.Tests
  • PaletteTestsVixen.Editor.Ui.Tests
  • PlatformKeyTestsVixen.Editor.Ui.Tests
  • PluginContextVixen.Editor.Plugin
  • ScopeTestsVixen.Editor.Ui.Tests
  • TerrainModeVixen.Editor.Terrain
  • TerrainModeTestsVixen.Editor.Terrain.Tests
  • ToolbarPresenterVixen.Editor.Ui
  • ToolbarSectionTestsVixen.Editor.Ui.Tests