Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Actions page editable #9949

Merged
6 commits merged into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 64 additions & 8 deletions src/cascadia/TerminalSettingsEditor/Actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
});
}

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();
Expand All @@ -59,30 +64,36 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
// if we're in edit mode,
// pre-populate the text box with the current keys
_ProposedKeys = KeyChordText();
_NotifyChanges(L"ProposedKeys");
ProposedKeys(KeyChordText());
}
}

void KeyBindingViewModel::AttemptAcceptChanges()
{
AttemptAcceptChanges(_ProposedKeys);
}

void KeyBindingViewModel::AttemptAcceptChanges(hstring newKeyChordText)
{
auto args{ make_self<RebindKeysEventArgs>(_Keys, _Keys) };
try
{
// Attempt to convert the provided key chord text
const auto newKeyChord{ KeyChordSerialization::FromString(_ProposedKeys) };
const auto newKeyChord{ KeyChordSerialization::FromString(newKeyChordText) };
args->NewKeys(newKeyChord);
_RebindKeysRequestedHandlers(*this, *args);
}
catch (hresult_invalid_argument)
{
// Converting the text into a key chord failed
// TODO CARLOS:
// TODO GH #6900:
// This is tricky. I still haven't found a way to reference the
// key chord text box. It's hidden behind the data template.
// Ideally, some kind of notification would alert the user, but
// to make it look nice, we need it to somehow target the text box.
// Alternatively, we want a full key chord editor/listener.
// If we implement that, we won't need this validation or error message.
}
_RebindKeysRequestedHandlers(*this, *args);
}

Actions::Actions()
Expand All @@ -95,6 +106,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_AutomationPeerAttached = true;
for (const auto& kbdVM : _KeyBindingList)
carlos-zamora marked this conversation as resolved.
Show resolved Hide resolved
{
// 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);
carlos-zamora marked this conversation as resolved.
Show resolved Hide resolved
}
return nullptr;
Expand Down Expand Up @@ -122,6 +136,34 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
_KeyBindingList = single_threaded_observable_vector(std::move(keyBindingList));
}

void Actions::KeyChordEditor_PreviewKeyDown(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e)
{
const auto& senderTB{ sender.as<TextBox>() };
const auto& kbdVM{ senderTB.DataContext().as<Editor::KeyBindingViewModel>() };
if (e.OriginalKey() == VirtualKey::Enter)
{
// Fun fact: this is happening _before_ "_ProposedKeys" gets updated
// with the two-way data binding. So we need to directly extract the text
// and tell the view model to update itself.
get_self<KeyBindingViewModel>(kbdVM)->AttemptAcceptChanges(senderTB.Text());

// For an unknown reason, when 'AcceptChangesFlyout' is set in the code above,
// the flyout isn't shown, forcing the 'Enter' key to do nothing.
// To get around this, detect if the flyout was set, and display it
// on the text box.
carlos-zamora marked this conversation as resolved.
Show resolved Hide resolved
if (kbdVM.AcceptChangesFlyout() != nullptr)
{
kbdVM.AcceptChangesFlyout().ShowAt(senderTB);
}
e.Handled(true);
}
else if (e.OriginalKey() == VirtualKey::Escape)
{
kbdVM.ToggleEditMode();
e.Handled(true);
}
}

void Actions::_ViewModelPropertyChangedHandler(const IInspectable& sender, const Windows::UI::Xaml::Data::PropertyChangedEventArgs& args)
{
const auto senderVM{ sender.as<Editor::KeyBindingViewModel>() };
Expand All @@ -130,26 +172,40 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
{
if (senderVM.IsInEditMode())
{
// Ensure that...
// 1. we move focus to the edit mode controls
// 2. this is the only entry that is in edit mode
for (uint32_t i = 0; i < _KeyBindingList.Size(); ++i)
{
const auto& kbdVM{ _KeyBindingList.GetAt(i) };
if (senderVM == kbdVM)
{
// move focus to the edit mode controls
// 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);
}
else
{
// exit edit mode for all other containers
// Exit edit mode for all other containers
get_self<KeyBindingViewModel>(kbdVM)->DisableEditMode();
}
}

const auto& containerBackgroundColor{ Resources().Lookup(box_value(L"SystemListMediumColor")).as<Windows::UI::Color>() };
Windows::UI::Xaml::Media::SolidColorBrush brush;
brush.Color(containerBackgroundColor);
get_self<KeyBindingViewModel>(senderVM)->ContainerBackground(brush);
carlos-zamora marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
// Focus on the list view item
KeyBindingsListView().ContainerFromItem(senderVM).as<Controls::Control>().Focus(FocusState::Programmatic);

Windows::UI::Xaml::Media::SolidColorBrush brush;
brush.Color(Windows::UI::Colors::Transparent());
get_self<KeyBindingViewModel>(senderVM)->ContainerBackground(brush);
}
}
}
Expand Down Expand Up @@ -256,7 +312,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
}
}

// TODO CARLOS:
// TODO GH #6900:
// an expedited search can be done if we use cmd.Name()
// to quickly search through the sorted list.
return std::nullopt;
Expand Down
10 changes: 9 additions & 1 deletion src/cascadia/TerminalSettingsEditor/Actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
hstring KeyChordText() const { return _KeyChordText; }
Settings::Model::Command Command() const { return _Command; };

hstring UIAHelpText() const { return hstring{ fmt::format(L"{}, {}", Name(), KeyChordText()) }; };
// UIA Text
hstring EditButtonName() const noexcept;
hstring CancelButtonName() const noexcept;
hstring AcceptButtonName() const noexcept;
hstring DeleteButtonName() const noexcept;

void EnterHoverMode() { IsHovered(true); };
carlos-zamora marked this conversation as resolved.
Show resolved Hide resolved
void ExitHoverMode() { IsHovered(false); };
void FocusContainer() { IsContainerFocused(true); };
Expand All @@ -51,6 +56,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void ToggleEditMode();
void DisableEditMode() { IsInEditMode(false); }
void AttemptAcceptChanges();
void AttemptAcceptChanges(hstring newKeyChordText);
void DeleteKeyBinding() { _DeleteKeyBindingRequestedHandlers(*this, _Keys); }

VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsInEditMode, false);
Expand All @@ -61,6 +67,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsHovered, false);
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsContainerFocused, false);
VIEW_MODEL_OBSERVABLE_PROPERTY(bool, IsEditButtonFocused, false);
VIEW_MODEL_OBSERVABLE_PROPERTY(Windows::UI::Xaml::Media::Brush, ContainerBackground, nullptr);
TYPED_EVENT(RebindKeysRequested, Editor::KeyBindingViewModel, Editor::RebindKeysEventArgs);
TYPED_EVENT(DeleteKeyBindingRequested, Editor::KeyBindingViewModel, Terminal::Control::KeyChord);

Expand All @@ -85,6 +92,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation

void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer();
void KeyChordEditor_PreviewKeyDown(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);

WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
WINRT_PROPERTY(Editor::ActionsPageNavigationState, State, nullptr);
Expand Down
6 changes: 5 additions & 1 deletion src/cascadia/TerminalSettingsEditor/Actions.idl
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@ namespace Microsoft.Terminal.Settings.Editor
String KeyChordText { get; };

// UI side
String UIAHelpText { get; };
Boolean ShowEditButton { get; };
Boolean IsInEditMode { get; };
String ProposedKeys;
Windows.UI.Xaml.Controls.Flyout AcceptChangesFlyout;
String EditButtonName { get; };
String CancelButtonName { get; };
carlos-zamora marked this conversation as resolved.
Show resolved Hide resolved
String AcceptButtonName { get; };
String DeleteButtonName { get; };
Windows.UI.Xaml.Media.Brush ContainerBackground { get; };

void EnterHoverMode();
void ExitHoverMode();
Expand Down
Loading