mirror of
https://github.com/microsoft/terminal.git
synced 2026-07-08 18:16:28 +00:00
Polish Edit Action page
- Fix key bindings section being hidden when no keys are present
- Fix action name not updating when type changes
- Polish interactions with action type suggestions list
- select all text when control gets focus
- do NOT open suggestions when the page gets navigated to or
light dismiss (aka programmatic focus)
- DO open suggestions when user tabs to control
This commit is contained in:
@@ -444,6 +444,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
ActionArgsVM(*actionArgsVM);
|
||||
if (!_command.HasName())
|
||||
{
|
||||
// Invalidate the cache to make the getter recompute the display name for the "action name" field
|
||||
_cachedDisplayName.clear();
|
||||
_NotifyChanges(L"DisplayName");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,30 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Depth-first search of the visual tree under 'root' for the first TextBox (the AutoSuggestBox's
|
||||
// inner editable TextBox), so we can select its text on focus.
|
||||
static Controls::TextBox _findChildTextBox(const Windows::UI::Xaml::DependencyObject& root)
|
||||
{
|
||||
if (!root)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
if (const auto textBox = root.try_as<Controls::TextBox>())
|
||||
{
|
||||
return textBox;
|
||||
}
|
||||
const auto count = Windows::UI::Xaml::Media::VisualTreeHelper::GetChildrenCount(root);
|
||||
for (int32_t i = 0; i < count; ++i)
|
||||
{
|
||||
const auto child = Windows::UI::Xaml::Media::VisualTreeHelper::GetChild(root, i);
|
||||
if (const auto found = _findChildTextBox(child))
|
||||
{
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EditAction::EditAction()
|
||||
{
|
||||
}
|
||||
@@ -77,6 +101,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
const auto args = e.Parameter().as<Editor::NavigateToPageArgs>();
|
||||
_ViewModel = args.ViewModel().as<Editor::CommandViewModel>();
|
||||
|
||||
// Suppress opening the suggestion list for the whole page-entry window; see LostFocus.
|
||||
_isPageEntryFocus = true;
|
||||
_propagateWindowRootRevoker = _ViewModel.PropagateWindowRootRequested(
|
||||
winrt::auto_revoke,
|
||||
[windowRoot = args.WindowRoot()](const IInspectable&, const Editor::ArgWrapper& wrapper) {
|
||||
@@ -144,6 +171,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
if (const auto listener = _findKeyChordListener(container.try_as<DependencyObject>()))
|
||||
{
|
||||
// Entry focus went to a key chord row, not the box; entry is over.
|
||||
_isPageEntryFocus = false;
|
||||
listener.FocusInput();
|
||||
return;
|
||||
}
|
||||
@@ -163,23 +192,44 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void EditAction::ShortcutActionBox_GettingFocus(const IInspectable& /*sender*/, const Windows::UI::Xaml::Input::GettingFocusEventArgs& args)
|
||||
{
|
||||
// Open on Tab, but not on page entry.
|
||||
// FocusState is unreliable, so use InputDevice: "Keyboard" means we tabbed to focus.
|
||||
_openSuggestionsOnFocus = args.InputDevice() == Windows::UI::Xaml::Input::FocusInputDeviceKind::Keyboard && !_isPageEntryFocus;
|
||||
}
|
||||
|
||||
void EditAction::ShortcutActionBox_GotFocus(const IInspectable& sender, const RoutedEventArgs&)
|
||||
{
|
||||
// Only rebuild the list if we don't have a cached list or if the cached list is filtered
|
||||
if (!_filteredActions || !_currentActionFilter.empty())
|
||||
{
|
||||
// Open the suggestions list with all available actions
|
||||
std::vector<winrt::hstring> allActions;
|
||||
for (const auto& action : _ViewModel.AvailableShortcutActions())
|
||||
{
|
||||
allActions.push_back(action);
|
||||
}
|
||||
const auto box = sender.as<AutoSuggestBox>();
|
||||
|
||||
_filteredActions = winrt::single_threaded_observable_vector(std::move(allActions));
|
||||
_currentActionFilter = L"";
|
||||
sender.as<AutoSuggestBox>().ItemsSource(_filteredActions);
|
||||
// Seeding ItemsSource inside this branch is intentional: assigning it on a focused
|
||||
// AutoSuggestBox opens the popup on its own. Typing filters via ShortcutActionBox_TextChanged.
|
||||
if (_openSuggestionsOnFocus)
|
||||
{
|
||||
// Only rebuild the list if we don't have a cached list or if the cached list is filtered
|
||||
if (!_filteredActions || !_currentActionFilter.empty())
|
||||
{
|
||||
// Open the suggestions list with all available actions
|
||||
std::vector<winrt::hstring> allActions;
|
||||
for (const auto& action : _ViewModel.AvailableShortcutActions())
|
||||
{
|
||||
allActions.push_back(action);
|
||||
}
|
||||
|
||||
_filteredActions = winrt::single_threaded_observable_vector(std::move(allActions));
|
||||
_currentActionFilter = L"";
|
||||
box.ItemsSource(_filteredActions);
|
||||
}
|
||||
box.IsSuggestionListOpen(true);
|
||||
}
|
||||
|
||||
// Select all current text so the user can immediately overwrite it. AutoSuggestBox has no
|
||||
// SelectAll, so use the inner TextBox.
|
||||
if (const auto textBox = _findChildTextBox(box.as<Windows::UI::Xaml::DependencyObject>()))
|
||||
{
|
||||
textBox.SelectAll();
|
||||
}
|
||||
sender.as<AutoSuggestBox>().IsSuggestionListOpen(true);
|
||||
}
|
||||
|
||||
void EditAction::ShortcutActionBox_TextChanged(const AutoSuggestBox& sender, const AutoSuggestBoxTextChangedEventArgs& args)
|
||||
@@ -225,6 +275,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
void EditAction::ShortcutActionBox_LostFocus(const IInspectable& sender, const RoutedEventArgs&)
|
||||
{
|
||||
_isPageEntryFocus = false;
|
||||
|
||||
// The auto suggest box does a weird thing where it reverts to the last query text when you
|
||||
// keyboard navigate out of it. Intercept it here and keep the correct text.
|
||||
const auto box = sender.as<AutoSuggestBox>();
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
WINRT_OBSERVABLE_PROPERTY(Editor::CommandViewModel, ViewModel, PropertyChanged.raise, nullptr);
|
||||
|
||||
void ShortcutActionBox_GotFocus(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
|
||||
void ShortcutActionBox_GettingFocus(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::Input::GettingFocusEventArgs& args);
|
||||
void ShortcutActionBox_TextChanged(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxTextChangedEventArgs& args);
|
||||
void ShortcutActionBox_QuerySubmitted(const winrt::Windows::UI::Xaml::Controls::AutoSuggestBox& sender, const winrt::Windows::UI::Xaml::Controls::AutoSuggestBoxQuerySubmittedEventArgs& args);
|
||||
void ShortcutActionBox_LostFocus(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
|
||||
@@ -33,6 +34,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<winrt::hstring> _filteredActions{ nullptr };
|
||||
winrt::hstring _lastValidAction;
|
||||
winrt::hstring _currentActionFilter;
|
||||
bool _openSuggestionsOnFocus{ false };
|
||||
bool _isPageEntryFocus{ false };
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -430,6 +430,7 @@
|
||||
<AutoSuggestBox x:Name="ShortcutActionBox"
|
||||
MinWidth="248"
|
||||
AutomationProperties.Name="{x:Bind ViewModel.ShortcutActionComboBoxAutomationPropName}"
|
||||
GettingFocus="ShortcutActionBox_GettingFocus"
|
||||
GotFocus="ShortcutActionBox_GotFocus"
|
||||
LostFocus="ShortcutActionBox_LostFocus"
|
||||
QuerySubmitted="ShortcutActionBox_QuerySubmitted"
|
||||
@@ -438,8 +439,7 @@
|
||||
|
||||
<!-- Key bindings -->
|
||||
<StackPanel x:Name="KeyBindingsContainer"
|
||||
Spacing="4"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(ViewModel.HasNoKeyChords), Mode=OneWay}">
|
||||
Spacing="4">
|
||||
<TextBlock x:Uid="EditAction_KeyBindings"
|
||||
Style="{StaticResource TextBlockSubHeaderStyle}" />
|
||||
|
||||
@@ -462,7 +462,8 @@
|
||||
HorizontalContentAlignment="Stretch"
|
||||
IsTabStop="False"
|
||||
ItemTemplate="{StaticResource KeyChordTemplate}"
|
||||
ItemsSource="{x:Bind ViewModel.KeyChordList, Mode=OneWay}">
|
||||
ItemsSource="{x:Bind ViewModel.KeyChordList, Mode=OneWay}"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(ViewModel.HasNoKeyChords), Mode=OneWay}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical"
|
||||
|
||||
Reference in New Issue
Block a user