terminal/src/cascadia/TerminalSettingsEditor/Actions.cpp

392 lines
18 KiB
C++
Raw Normal View History

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "Actions.h"
#include "Actions.g.cpp"
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
#include "KeyBindingViewModel.g.cpp"
#include "ActionsPageNavigationState.g.cpp"
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
#include "LibraryResources.h"
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
#include "../TerminalSettingsModel/AllShortcutActions.h"
using namespace winrt::Windows::Foundation;
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Core;
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Data;
using namespace winrt::Windows::UI::Xaml::Navigation;
using namespace winrt::Microsoft::Terminal::Settings::Model;
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
KeyBindingViewModel::KeyBindingViewModel(const Windows::Foundation::Collections::IObservableVector<hstring>& availableActions) :
KeyBindingViewModel(nullptr, availableActions.First().Current(), availableActions) {}
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
KeyBindingViewModel::KeyBindingViewModel(const Control::KeyChord& keys, const hstring& actionName, const IObservableVector<hstring>& availableActions) :
Add a KeyChordListener to the Settings UI (#10652) ## Summary of the Pull Request Replaces the key chord editor in the actions page with a listener instead of a plain text box. ## References #6900 - Settings UI Epic ## Detailed Description of the Pull Request / Additional comments - `Actions` page: - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction` - `ProposedKeys` is now a `Control::KeyChord` - removes key chord validation (now we don't need it) - removes accept/cancel shortcuts (nowhere we could use it now) - `KeyChordListener`: - `Keys`: dependency property that hooks us up to a system to the committed setting value - this is the key binding view model, which propagates the change to the settings model clone on "accept changes" - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box) - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation) ## Validation Steps Performed - Tested a few key chords: - ✅single key: <kbd>X</kbd> - ✅key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> - ❌plain modifier: <kbd>Ctrl</kbd> - ✅key that is used by text box: <kbd>Ctrl+A</kbd> - ✅key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd> - ❌key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd> - ✅key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> - Known issue: - global key taken by Windows Terminal: (i.e. quake mode keybinding) - Behavior: global key binding executed - Expected: key chord recorded ## Demo ![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-17 00:11:55 +02:00
_CurrentKeys{ keys },
_KeyChordText{ KeyChordSerialization::ToString(keys) },
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
_CurrentAction{ actionName },
_ProposedAction{ box_value(actionName) },
_AvailableActions{ availableActions }
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
{
// Add a property changed handler to our own property changed event.
// This propagates changes from the settings model to anybody listening to our
// unique view model members.
PropertyChanged([this](auto&&, const PropertyChangedEventArgs& args) {
const auto viewModelProperty{ args.PropertyName() };
Add a KeyChordListener to the Settings UI (#10652) ## Summary of the Pull Request Replaces the key chord editor in the actions page with a listener instead of a plain text box. ## References #6900 - Settings UI Epic ## Detailed Description of the Pull Request / Additional comments - `Actions` page: - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction` - `ProposedKeys` is now a `Control::KeyChord` - removes key chord validation (now we don't need it) - removes accept/cancel shortcuts (nowhere we could use it now) - `KeyChordListener`: - `Keys`: dependency property that hooks us up to a system to the committed setting value - this is the key binding view model, which propagates the change to the settings model clone on "accept changes" - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box) - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation) ## Validation Steps Performed - Tested a few key chords: - ✅single key: <kbd>X</kbd> - ✅key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> - ❌plain modifier: <kbd>Ctrl</kbd> - ✅key that is used by text box: <kbd>Ctrl+A</kbd> - ✅key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd> - ❌key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd> - ✅key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> - Known issue: - global key taken by Windows Terminal: (i.e. quake mode keybinding) - Behavior: global key binding executed - Expected: key chord recorded ## Demo ![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-17 00:11:55 +02:00
if (viewModelProperty == L"CurrentKeys")
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
{
Add a KeyChordListener to the Settings UI (#10652) ## Summary of the Pull Request Replaces the key chord editor in the actions page with a listener instead of a plain text box. ## References #6900 - Settings UI Epic ## Detailed Description of the Pull Request / Additional comments - `Actions` page: - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction` - `ProposedKeys` is now a `Control::KeyChord` - removes key chord validation (now we don't need it) - removes accept/cancel shortcuts (nowhere we could use it now) - `KeyChordListener`: - `Keys`: dependency property that hooks us up to a system to the committed setting value - this is the key binding view model, which propagates the change to the settings model clone on "accept changes" - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box) - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation) ## Validation Steps Performed - Tested a few key chords: - ✅single key: <kbd>X</kbd> - ✅key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> - ❌plain modifier: <kbd>Ctrl</kbd> - ✅key that is used by text box: <kbd>Ctrl+A</kbd> - ✅key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd> - ❌key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd> - ✅key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> - Known issue: - global key taken by Windows Terminal: (i.e. quake mode keybinding) - Behavior: global key binding executed - Expected: key chord recorded ## Demo ![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-17 00:11:55 +02:00
_KeyChordText = KeyChordSerialization::ToString(_CurrentKeys);
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
_NotifyChanges(L"KeyChordText");
}
else if (viewModelProperty == L"IsContainerFocused" ||
viewModelProperty == L"IsEditButtonFocused" ||
viewModelProperty == L"IsHovered" ||
viewModelProperty == L"IsAutomationPeerAttached" ||
viewModelProperty == L"IsInEditMode")
{
_NotifyChanges(L"ShowEditButton");
}
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
else if (viewModelProperty == L"CurrentAction")
{
_NotifyChanges(L"Name");
}
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
});
}
hstring KeyBindingViewModel::EditButtonName() const noexcept { return RS_(L"Actions_EditButton/[using:Windows.UI.Xaml.Controls]ToolTipService/ToolTip"); }
hstring KeyBindingViewModel::CancelButtonName() const noexcept { return RS_(L"Actions_CancelButton/[using:Windows.UI.Xaml.Controls]ToolTipService/ToolTip"); }
hstring KeyBindingViewModel::AcceptButtonName() const noexcept { return RS_(L"Actions_AcceptButton/[using:Windows.UI.Xaml.Controls]ToolTipService/ToolTip"); }
hstring KeyBindingViewModel::DeleteButtonName() const noexcept { return RS_(L"Actions_DeleteButton/[using:Windows.UI.Xaml.Controls]ToolTipService/ToolTip"); }
bool KeyBindingViewModel::ShowEditButton() const noexcept
{
return (IsContainerFocused() || IsEditButtonFocused() || IsHovered() || IsAutomationPeerAttached()) && !IsInEditMode();
}
void KeyBindingViewModel::ToggleEditMode()
{
// toggle edit mode
IsInEditMode(!_IsInEditMode);
if (_IsInEditMode)
{
// if we're in edit mode,
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
// - pre-populate the text box with the current keys
// - reset the combo box with the current action
Add a KeyChordListener to the Settings UI (#10652) ## Summary of the Pull Request Replaces the key chord editor in the actions page with a listener instead of a plain text box. ## References #6900 - Settings UI Epic ## Detailed Description of the Pull Request / Additional comments - `Actions` page: - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction` - `ProposedKeys` is now a `Control::KeyChord` - removes key chord validation (now we don't need it) - removes accept/cancel shortcuts (nowhere we could use it now) - `KeyChordListener`: - `Keys`: dependency property that hooks us up to a system to the committed setting value - this is the key binding view model, which propagates the change to the settings model clone on "accept changes" - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box) - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation) ## Validation Steps Performed - Tested a few key chords: - ✅single key: <kbd>X</kbd> - ✅key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> - ❌plain modifier: <kbd>Ctrl</kbd> - ✅key that is used by text box: <kbd>Ctrl+A</kbd> - ✅key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd> - ❌key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd> - ✅key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> - Known issue: - global key taken by Windows Terminal: (i.e. quake mode keybinding) - Behavior: global key binding executed - Expected: key chord recorded ## Demo ![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-17 00:11:55 +02:00
ProposedKeys(_CurrentKeys);
ProposedAction(box_value(_CurrentAction));
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
}
}
void KeyBindingViewModel::AttemptAcceptChanges()
{
AttemptAcceptChanges(_ProposedKeys);
}
Add a KeyChordListener to the Settings UI (#10652) ## Summary of the Pull Request Replaces the key chord editor in the actions page with a listener instead of a plain text box. ## References #6900 - Settings UI Epic ## Detailed Description of the Pull Request / Additional comments - `Actions` page: - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction` - `ProposedKeys` is now a `Control::KeyChord` - removes key chord validation (now we don't need it) - removes accept/cancel shortcuts (nowhere we could use it now) - `KeyChordListener`: - `Keys`: dependency property that hooks us up to a system to the committed setting value - this is the key binding view model, which propagates the change to the settings model clone on "accept changes" - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box) - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation) ## Validation Steps Performed - Tested a few key chords: - ✅single key: <kbd>X</kbd> - ✅key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> - ❌plain modifier: <kbd>Ctrl</kbd> - ✅key that is used by text box: <kbd>Ctrl+A</kbd> - ✅key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd> - ❌key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd> - ✅key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> - Known issue: - global key taken by Windows Terminal: (i.e. quake mode keybinding) - Behavior: global key binding executed - Expected: key chord recorded ## Demo ![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-17 00:11:55 +02:00
void KeyBindingViewModel::AttemptAcceptChanges(const Control::KeyChord newKeys)
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
{
Add a KeyChordListener to the Settings UI (#10652) ## Summary of the Pull Request Replaces the key chord editor in the actions page with a listener instead of a plain text box. ## References #6900 - Settings UI Epic ## Detailed Description of the Pull Request / Additional comments - `Actions` page: - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction` - `ProposedKeys` is now a `Control::KeyChord` - removes key chord validation (now we don't need it) - removes accept/cancel shortcuts (nowhere we could use it now) - `KeyChordListener`: - `Keys`: dependency property that hooks us up to a system to the committed setting value - this is the key binding view model, which propagates the change to the settings model clone on "accept changes" - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box) - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation) ## Validation Steps Performed - Tested a few key chords: - ✅single key: <kbd>X</kbd> - ✅key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> - ❌plain modifier: <kbd>Ctrl</kbd> - ✅key that is used by text box: <kbd>Ctrl+A</kbd> - ✅key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd> - ❌key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd> - ✅key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> - Known issue: - global key taken by Windows Terminal: (i.e. quake mode keybinding) - Behavior: global key binding executed - Expected: key chord recorded ## Demo ![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-17 00:11:55 +02:00
const auto args{ make_self<ModifyKeyBindingEventArgs>(_CurrentKeys, // OldKeys
newKeys, // NewKeys
_IsNewlyAdded ? hstring{} : _CurrentAction, // OldAction
unbox_value<hstring>(_ProposedAction)) }; // NewAction
_ModifyKeyBindingRequestedHandlers(*this, *args);
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
}
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
void KeyBindingViewModel::CancelChanges()
{
if (_IsNewlyAdded)
{
_DeleteNewlyAddedKeyBindingHandlers(*this, nullptr);
}
else
{
ToggleEditMode();
}
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
}
Actions::Actions()
{
InitializeComponent();
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
Automation::AutomationProperties::SetName(AddNewButton(), RS_(L"Actions_AddNewTextBlock/Text"));
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
}
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
Automation::Peers::AutomationPeer Actions::OnCreateAutomationPeer()
{
_AutomationPeerAttached = true;
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
for (const auto& kbdVM : _KeyBindingList)
{
// To create a more accessible experience, we want the "edit" buttons to _always_
// appear when a screen reader is attached. This ensures that the edit buttons are
// accessible via the UIA tree.
get_self<KeyBindingViewModel>(kbdVM)->IsAutomationPeerAttached(_AutomationPeerAttached);
}
return nullptr;
}
void Actions::OnNavigatedTo(const NavigationEventArgs& e)
{
_State = e.Parameter().as<Editor::ActionsPageNavigationState>();
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
// Populate AvailableActionAndArgs
_AvailableActionMap = single_threaded_map<hstring, Model::ActionAndArgs>();
std::vector<hstring> availableActionAndArgs;
for (const auto& [name, actionAndArgs] : _State.Settings().ActionMap().AvailableActions())
{
availableActionAndArgs.push_back(name);
_AvailableActionMap.Insert(name, actionAndArgs);
}
std::sort(begin(availableActionAndArgs), end(availableActionAndArgs));
_AvailableActionAndArgs = single_threaded_observable_vector(std::move(availableActionAndArgs));
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
// Convert the key bindings from our settings into a view model representation
const auto& keyBindingMap{ _State.Settings().ActionMap().KeyBindings() };
std::vector<Editor::KeyBindingViewModel> keyBindingList;
keyBindingList.reserve(keyBindingMap.Size());
for (const auto& [keys, cmd] : keyBindingMap)
{
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
// convert the cmd into a KeyBindingViewModel
auto container{ make_self<KeyBindingViewModel>(keys, cmd.Name(), _AvailableActionAndArgs) };
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
_RegisterEvents(container);
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
keyBindingList.push_back(*container);
}
std::sort(begin(keyBindingList), end(keyBindingList), KeyBindingViewModelComparator{});
_KeyBindingList = single_threaded_observable_vector(std::move(keyBindingList));
}
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
void Actions::AddNew_Click(const IInspectable& /*sender*/, const RoutedEventArgs& /*eventArgs*/)
{
// Create the new key binding and register all of the event handlers.
auto kbdVM{ make_self<KeyBindingViewModel>(_AvailableActionAndArgs) };
_RegisterEvents(kbdVM);
kbdVM->DeleteNewlyAddedKeyBinding({ this, &Actions::_ViewModelDeleteNewlyAddedKeyBindingHandler });
// Manually add the editing background. This needs to be done in Actions not the view model.
// We also have to do this manually because it hasn't been added to the list yet.
kbdVM->IsInEditMode(true);
const auto& containerBackground{ Resources().Lookup(box_value(L"ActionContainerBackgroundEditing")).as<Windows::UI::Xaml::Media::Brush>() };
kbdVM->ContainerBackground(containerBackground);
// IMPORTANT: do this _after_ setting IsInEditMode. Otherwise, it'll get deleted immediately
// by the PropertyChangedHandler below (where we delete any IsNewlyAdded items)
kbdVM->IsNewlyAdded(true);
_KeyBindingList.InsertAt(0, *kbdVM);
}
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
void Actions::_ViewModelPropertyChangedHandler(const IInspectable& sender, const Windows::UI::Xaml::Data::PropertyChangedEventArgs& args)
{
const auto senderVM{ sender.as<Editor::KeyBindingViewModel>() };
const auto propertyName{ args.PropertyName() };
if (propertyName == L"IsInEditMode")
{
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
if (senderVM.IsInEditMode())
{
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
// Ensure that...
// 1. we move focus to the edit mode controls
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
// 2. any actions that were newly added are removed
// 3. this is the only entry that is in edit mode
for (int32_t i = _KeyBindingList.Size() - 1; i >= 0; --i)
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
{
const auto& kbdVM{ _KeyBindingList.GetAt(i) };
if (senderVM == kbdVM)
{
// This is the view model entry that went into edit mode.
// Move focus to the edit mode controls by
// extracting the list view item container.
const auto& container{ KeyBindingsListView().ContainerFromIndex(i).try_as<ListViewItem>() };
container.Focus(FocusState::Programmatic);
}
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
else if (kbdVM.IsNewlyAdded())
{
// Remove any actions that were newly added
_KeyBindingList.RemoveAt(i);
}
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
else
{
// Exit edit mode for all other containers
get_self<KeyBindingViewModel>(kbdVM)->DisableEditMode();
}
}
const auto& containerBackground{ Resources().Lookup(box_value(L"ActionContainerBackgroundEditing")).as<Windows::UI::Xaml::Media::Brush>() };
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
get_self<KeyBindingViewModel>(senderVM)->ContainerBackground(containerBackground);
}
else
{
// Focus on the list view item
KeyBindingsListView().ContainerFromItem(senderVM).as<Controls::Control>().Focus(FocusState::Programmatic);
const auto& containerBackground{ Resources().Lookup(box_value(L"ActionContainerBackground")).as<Windows::UI::Xaml::Media::Brush>() };
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
get_self<KeyBindingViewModel>(senderVM)->ContainerBackground(containerBackground);
}
}
}
void Actions::_ViewModelDeleteKeyBindingHandler(const Editor::KeyBindingViewModel& senderVM, const Control::KeyChord& keys)
{
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
// Update the settings model
_State.Settings().ActionMap().DeleteKeyBinding(keys);
// Find the current container in our list and remove it.
// This is much faster than rebuilding the entire ActionMap.
uint32_t index;
if (_KeyBindingList.IndexOf(senderVM, index))
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
{
_KeyBindingList.RemoveAt(index);
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
// Focus the new item at this index
if (_KeyBindingList.Size() != 0)
{
const auto newFocusedIndex{ std::clamp(index, 0u, _KeyBindingList.Size() - 1) };
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
KeyBindingsListView().ContainerFromIndex(newFocusedIndex).as<Controls::Control>().Focus(FocusState::Programmatic);
}
}
}
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
void Actions::_ViewModelModifyKeyBindingHandler(const Editor::KeyBindingViewModel& senderVM, const Editor::ModifyKeyBindingEventArgs& args)
{
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
const auto isNewAction{ !args.OldKeys() && args.OldActionName().empty() };
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
auto applyChangesToSettingsModel = [=]() {
// If the key chord was changed,
// update the settings model and view model appropriately
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
// NOTE: we still need to update the view model if we're working with a newly added action
if (isNewAction || args.OldKeys().Modifiers() != args.NewKeys().Modifiers() || args.OldKeys().Vkey() != args.NewKeys().Vkey())
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
{
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
if (!isNewAction)
{
// update settings model
_State.Settings().ActionMap().RebindKeys(args.OldKeys(), args.NewKeys());
}
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
// update view model
auto senderVMImpl{ get_self<KeyBindingViewModel>(senderVM) };
Add a KeyChordListener to the Settings UI (#10652) ## Summary of the Pull Request Replaces the key chord editor in the actions page with a listener instead of a plain text box. ## References #6900 - Settings UI Epic ## Detailed Description of the Pull Request / Additional comments - `Actions` page: - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction` - `ProposedKeys` is now a `Control::KeyChord` - removes key chord validation (now we don't need it) - removes accept/cancel shortcuts (nowhere we could use it now) - `KeyChordListener`: - `Keys`: dependency property that hooks us up to a system to the committed setting value - this is the key binding view model, which propagates the change to the settings model clone on "accept changes" - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box) - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation) ## Validation Steps Performed - Tested a few key chords: - ✅single key: <kbd>X</kbd> - ✅key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> - ❌plain modifier: <kbd>Ctrl</kbd> - ✅key that is used by text box: <kbd>Ctrl+A</kbd> - ✅key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd> - ❌key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd> - ✅key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> - Known issue: - global key taken by Windows Terminal: (i.e. quake mode keybinding) - Behavior: global key binding executed - Expected: key chord recorded ## Demo ![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-17 00:11:55 +02:00
senderVMImpl->CurrentKeys(args.NewKeys());
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
}
// If the action was changed,
// update the settings model and view model appropriately
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
// NOTE: no need to check for "isNewAction" here. <empty_string> != <action name> already.
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
if (args.OldActionName() != args.NewActionName())
{
// convert the action's name into a view model.
const auto& newAction{ _AvailableActionMap.Lookup(args.NewActionName()) };
// update settings model
_State.Settings().ActionMap().RegisterKeyBinding(args.NewKeys(), newAction);
// update view model
auto senderVMImpl{ get_self<KeyBindingViewModel>(senderVM) };
senderVMImpl->CurrentAction(args.NewActionName());
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
senderVMImpl->IsNewlyAdded(false);
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
}
};
// Check for this special case:
// we're changing the key chord,
// but the new key chord is already in use
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
if (isNewAction || args.OldKeys().Modifiers() != args.NewKeys().Modifiers() || args.OldKeys().Vkey() != args.NewKeys().Vkey())
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
{
const auto& conflictingCmd{ _State.Settings().ActionMap().GetActionByKeyChord(args.NewKeys()) };
if (conflictingCmd)
{
// We're about to overwrite another key chord.
// Display a confirmation dialog.
TextBlock errorMessageTB{};
errorMessageTB.Text(RS_(L"Actions_RenameConflictConfirmationMessage"));
const auto conflictingCmdName{ conflictingCmd.Name() };
TextBlock conflictingCommandNameTB{};
conflictingCommandNameTB.Text(fmt::format(L"\"{}\"", conflictingCmdName.empty() ? RS_(L"Actions_UnnamedCommandName") : conflictingCmdName));
conflictingCommandNameTB.FontStyle(Windows::UI::Text::FontStyle::Italic);
TextBlock confirmationQuestionTB{};
confirmationQuestionTB.Text(RS_(L"Actions_RenameConflictConfirmationQuestion"));
Button acceptBTN{};
acceptBTN.Content(box_value(RS_(L"Actions_RenameConflictConfirmationAcceptButton")));
acceptBTN.Click([=](auto&, auto&) {
// remove conflicting key binding from list view
const auto containerIndex{ _GetContainerIndexByKeyChord(args.NewKeys()) };
_KeyBindingList.RemoveAt(*containerIndex);
// remove flyout
senderVM.AcceptChangesFlyout().Hide();
senderVM.AcceptChangesFlyout(nullptr);
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
// update settings model and view model
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
applyChangesToSettingsModel();
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
senderVM.ToggleEditMode();
});
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
StackPanel flyoutStack{};
flyoutStack.Children().Append(errorMessageTB);
flyoutStack.Children().Append(conflictingCommandNameTB);
flyoutStack.Children().Append(confirmationQuestionTB);
flyoutStack.Children().Append(acceptBTN);
Flyout acceptChangesFlyout{};
acceptChangesFlyout.Content(flyoutStack);
senderVM.AcceptChangesFlyout(acceptChangesFlyout);
return;
}
}
Allow setting the action on Actions page (#10220) This introduces the ability to set the action for a key binding. A combo box is used to let the user select a new action. ## References #6900 - Actions page Epic #9427 - Actions page design doc #9949 - Actions page PR ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `ActionAndArgs` - new ctor that just takes a `ShortcutAction` - `ActionMap` - `AvailableActions` provides a map of all the "acceptable" actions to choose from. This is a merged list of (1) all `{ "command": X }` style actions and (2) any actions with args that are already defined in the ActionMap (or any parents). - `RegisterKeyBinding` introduces a new unnamed key binding to the action map. ### Editor Changes - XAML - Pretty straightforward, when in edit mode, we replace the text block with a combo box. This combo box just presents the actions you can choose from. - `RebindKeysEventArgs` --> `ModifyKeyBindingEventArgs` - `AvailableActionAndArgs` - stores the list of actions to choose from in the combo box - _Unfortunately_, `KeyBindingViewModel` needs this so that we can populate the combo box - `Actions` stores and maintains this though. We populate this from the settings model on navigation. - `ProposedAction` vs `CurrentAction` - similar to `ProposedKeys` and `Keys`, we need a way to distinguish the value from the settings model and the value of the control (i.e. combo box). - `CurrentAction` --> settings model - `ProposedAction` --> combo box selected item ## Validation Steps Performed - Cancel: - ✔️ change action --> cancel button --> begin editing action again --> original action is selected - Accept: - ✔️ don't change anything - ✔️ change action --> OK! --> Save! - NOTE: The original action is still left as a stub `{ "command": "closePane" }`. This is intentional because we want to prevent all modifications to the command palette. - ✔️ change action & change key chord --> OK! --> Save! - ✔️ change action & change key chord (conflicting key chord) --> OK! --> click ok on flyout --> Save! - NOTE: original action is left as a stub; original key chord explicitly unbound; new command/keys combo added.
2021-07-03 00:35:55 +02:00
// update settings model and view model
applyChangesToSettingsModel();
// We NEED to toggle the edit mode here,
// so that if nothing changed, we still exit
// edit mode.
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
senderVM.ToggleEditMode();
}
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
void Actions::_ViewModelDeleteNewlyAddedKeyBindingHandler(const Editor::KeyBindingViewModel& senderVM, const IInspectable& /*args*/)
{
for (uint32_t i = 0; i < _KeyBindingList.Size(); ++i)
{
const auto& kbdVM{ _KeyBindingList.GetAt(i) };
if (kbdVM == senderVM)
{
_KeyBindingList.RemoveAt(i);
return;
}
}
}
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
// Method Description:
// - performs a search on KeyBindingList by key chord.
// Arguments:
// - keys - the associated key chord of the command we're looking for
// Return Value:
// - the index of the view model referencing the command. If the command doesn't exist, nullopt
std::optional<uint32_t> Actions::_GetContainerIndexByKeyChord(const Control::KeyChord& keys)
{
for (uint32_t i = 0; i < _KeyBindingList.Size(); ++i)
{
const auto kbdVM{ get_self<KeyBindingViewModel>(_KeyBindingList.GetAt(i)) };
Add a KeyChordListener to the Settings UI (#10652) ## Summary of the Pull Request Replaces the key chord editor in the actions page with a listener instead of a plain text box. ## References #6900 - Settings UI Epic ## Detailed Description of the Pull Request / Additional comments - `Actions` page: - Replace `Keys` with `CurrentKeys` for consistency with `Action`/`CurrentAction` - `ProposedKeys` is now a `Control::KeyChord` - removes key chord validation (now we don't need it) - removes accept/cancel shortcuts (nowhere we could use it now) - `KeyChordListener`: - `Keys`: dependency property that hooks us up to a system to the committed setting value - this is the key binding view model, which propagates the change to the settings model clone on "accept changes" - We bind to `PreviewKeyDown` to intercept the key event _before_ some special key bindings are handled (i.e. "select all" in the text box) - `CoreWindow` is used to get the modifier keys because (1) it's easier than updating on each key press and (2) that approach resulted in a strange bug where the <kbd>Alt</kbd> key-up event was not detected - `LosingFocus` means that we have completed our operation and want to commit our changes to the key binding view model - `KeyDown` does most of the magic of updating `Keys`. We filter out any key chords that could be problematic (i.e. <kbd>Shift</kbd>+<kbd>Tab</kbd> and <kbd>Tab</kbd> for keyboard navigation) ## Validation Steps Performed - Tested a few key chords: - ✅single key: <kbd>X</kbd> - ✅key with modifier(s): <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>X</kbd> - ❌plain modifier: <kbd>Ctrl</kbd> - ✅key that is used by text box: <kbd>Ctrl+A</kbd> - ✅key that is used by Windows Terminal: <kbd>Alt</kbd>+<kbd>F4</kbd> - ❌key that is taken by Windows OS: <kbd>Windows</kbd>+<kbd>X</kbd> - ✅key that is not taken by Windows OS: <kbd>Windows</kbd>+<kbd>Shift</kbd>+<kbd>X</kbd> - Known issue: - global key taken by Windows Terminal: (i.e. quake mode keybinding) - Behavior: global key binding executed - Expected: key chord recorded ## Demo ![Key Chord Listener Demo](https://user-images.githubusercontent.com/11050425/125538094-08ea4eaa-21eb-4488-a74c-6ce65324cdf1.gif)
2021-07-17 00:11:55 +02:00
const auto& otherKeys{ kbdVM->CurrentKeys() };
if (otherKeys && keys.Modifiers() == otherKeys.Modifiers() && keys.Vkey() == otherKeys.Vkey())
Make Actions page editable (#9949) ## Summary of the Pull Request This PR lays the foundation for a new Actions page in the Settings UI as designed in #6900. The Actions page now leverages the `ActionMap` to display all of the key bindings and allow the user to modify the associated key chord or delete the key binding entirely. ## References #9621 - ActionMap #9926 - ActionMap serialization #9428 - ActionMap Spec #6900 - Actions page #9427 - Actions page design doc ## Detailed Description of the Pull Request / Additional comments ### Settings Model Changes - `Command::Copy()` now copies the `ActionAndArgs` - `ActionMap::RebindKeys()` handles changing the key chord of a key binding. If a conflict occurs, the conflicting key chord is overwritten. - `ActionMap::DeleteKeyBinding()` "deletes" a key binding by binding "unbound" to the given key chord. - `ActionMap::KeyBindings()` presents another view (similar to `NameMap`) of the `ActionMap`. It specifically presents a map of key chords to commands. It is generated similar to how `NameMap` is generated. ### Editor Changes - `Actions.xaml` is mainly split into two parts: - `ListView` (as before) holds the list of key bindings. We _could_ explore the idea of an items repeater, but the `ListView` seems to provide some niceties with regards to navigating the list via the key board (though none are selectable). - `DataTemplate` is used to represent each key binding inside the `ListView`. This is tricky because it is bound to a `KeyBindingViewModel` which must provide _all_ context necessary to modify the UI and the settings model. We cannot use names to target UI elements inside this template, so we must make the view model smart and force updates to the UI via changes in the view model. - `KeyBindingViewModel` is a view model object that controls the UI and the settings model. There are a number of TODOs in Actions.cpp will be long-term follow-ups and would be nice to have. This includes... - a binary search by name on `Actions::KeyBindingList` - presenting an error when the provided key chord is invalid. ## Demo ![Actions Page Demo](https://user-images.githubusercontent.com/11050425/116034988-131d1b80-a619-11eb-8df2-c7e57c6fad86.gif)
2021-05-18 23:37:16 +02:00
{
return i;
}
}
// TODO GH #6900:
// an expedited search can be done if we use cmd.Name()
// to quickly search through the sorted list.
return std::nullopt;
}
Add the 'Add new' button to the Actions page (#10550) ## Summary of the Pull Request This adds the "add new" button to the actions page. It build on the work of #10220 by basically just adding a new list item to the top of the key binding list. This also makes it so that if you click the "accept changes" button when you have an invalid key chord, we don't do anything. ## References #6900 - Actions page Epic #9427 - Actions page design doc #10220 - Actions page PR - set action ## Detailed Description of the Pull Request / Additional comments - `ModifyKeyBindingEventArgs` is used to introduce new key bindings. We just ignore `OldKeys` and `OldActionName` because both didn't exist before. - `IsNewlyAdded` tracks if this is an action that was added, but has not been confirmed to add to the settings model. - `CancelChanges()` is directly bound to the cancel button. This allows us to delete the key binding when it's clicked on a "newly added" action. ## Validation Steps Performed - Cancel: - Deletes the action (because it doesn't truly exist until you confirm changes) - Accept: - Adds the new action. - If you attempt to edit it, the delete button is back. - Add Action: - Delete button should not be visible (redundant with 'Cancel') - Action should be initialized to a value - Key chord should be empty - Cannot add another action if a newly added action exists - Keyboard interaction: - escape --> cancel - enter --> accept - Accessibility: - "add new" button has a name - Interaction with other key bindings: - editing another action --> delete the "newly added" action (it hasn't been added yet) - only one action can be edited at a time
2021-07-08 01:43:40 +02:00
void Actions::_RegisterEvents(com_ptr<KeyBindingViewModel>& kbdVM)
{
kbdVM->PropertyChanged({ this, &Actions::_ViewModelPropertyChangedHandler });
kbdVM->DeleteKeyBindingRequested({ this, &Actions::_ViewModelDeleteKeyBindingHandler });
kbdVM->ModifyKeyBindingRequested({ this, &Actions::_ViewModelModifyKeyBindingHandler });
kbdVM->IsAutomationPeerAttached(_AutomationPeerAttached);
}
}