mirror of
https://github.com/microsoft/terminal.git
synced 2026-02-05 13:47:06 +00:00
PRE-MERGE #17330 Add a snippets pane
This commit is contained in:
@@ -1521,4 +1521,5 @@ namespace winrt::TerminalApp::implementation
|
||||
_ShowAboutDialog();
|
||||
args.Handled(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,11 +21,22 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// This class is a wrapper of PaletteItem, that is used as an item of a filterable list in CommandPalette.
|
||||
// It manages a highlighted text that is computed by matching search filter characters to item name
|
||||
FilteredCommand::FilteredCommand(const winrt::TerminalApp::PaletteItem& item) :
|
||||
_Item(item),
|
||||
_Filter(L""),
|
||||
_Weight(0)
|
||||
FilteredCommand::FilteredCommand(const winrt::TerminalApp::PaletteItem& item)
|
||||
{
|
||||
// Actually implement the ctor in _constructFilteredCommand
|
||||
_constructFilteredCommand(item);
|
||||
}
|
||||
|
||||
// We need to actually implement the ctor in a separate helper. This is
|
||||
// because we have a FilteredTask class which derives from FilteredCommand.
|
||||
// HOWEVER, for cppwinrt ~ r e a s o n s ~, it doesn't actually derive from
|
||||
// FilteredCommand directly, so we can't just use the FilteredCommand ctor
|
||||
// directly in the base class.
|
||||
void FilteredCommand::_constructFilteredCommand(const winrt::TerminalApp::PaletteItem& item)
|
||||
{
|
||||
_Item = item;
|
||||
_Filter = L"";
|
||||
_Weight = 0;
|
||||
_HighlightedName = _computeHighlightedName();
|
||||
|
||||
// Recompute the highlighted name if the item name changes
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace winrt::TerminalApp::implementation
|
||||
FilteredCommand() = default;
|
||||
FilteredCommand(const winrt::TerminalApp::PaletteItem& item);
|
||||
|
||||
void UpdateFilter(const winrt::hstring& filter);
|
||||
virtual void UpdateFilter(const winrt::hstring& filter);
|
||||
|
||||
static int Compare(const winrt::TerminalApp::FilteredCommand& first, const winrt::TerminalApp::FilteredCommand& second);
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace winrt::TerminalApp::implementation
|
||||
WINRT_OBSERVABLE_PROPERTY(winrt::TerminalApp::HighlightedText, HighlightedName, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(int, Weight, PropertyChanged.raise);
|
||||
|
||||
protected:
|
||||
void _constructFilteredCommand(const winrt::TerminalApp::PaletteItem& item);
|
||||
|
||||
private:
|
||||
winrt::TerminalApp::HighlightedText _computeHighlightedName();
|
||||
int _computeWeight();
|
||||
|
||||
@@ -6,7 +6,7 @@ import "HighlightedTextControl.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
[default_interface] runtimeclass FilteredCommand : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
[default_interface] unsealed runtimeclass FilteredCommand : Windows.UI.Xaml.Data.INotifyPropertyChanged
|
||||
{
|
||||
FilteredCommand();
|
||||
FilteredCommand(PaletteItem item);
|
||||
|
||||
@@ -913,4 +913,15 @@
|
||||
<data name="ActionSaveFailedToast.Title" xml:space="preserve">
|
||||
<value>Action save failed</value>
|
||||
</data>
|
||||
<data name="SnippetPaneTitle.Text" xml:space="preserve">
|
||||
<value>Snippets</value>
|
||||
<comment>Header for a page that includes small snippets of text for the user to enter</comment>
|
||||
</data>
|
||||
<data name="SnippetsFilterBox.PlaceholderText" xml:space="preserve">
|
||||
<value>Filter snippets...</value>
|
||||
<comment>Placeholder text for a text box to filter snippets (on the same page as the 'SnippetPaneTitle')</comment>
|
||||
</data>
|
||||
<data name="SnippetPlayButton.[using:Windows.UI.Xaml.Controls]ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Input this command</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
125
src/cascadia/TerminalApp/SnippetsPaneContent.cpp
Normal file
125
src/cascadia/TerminalApp/SnippetsPaneContent.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "SnippetsPaneContent.h"
|
||||
#include "SnippetsPaneContent.g.cpp"
|
||||
#include "FilteredTask.g.cpp"
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Microsoft::Terminal::Settings;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
namespace WUX = Windows::UI::Xaml;
|
||||
namespace MUX = Microsoft::UI::Xaml;
|
||||
using IInspectable = Windows::Foundation::IInspectable;
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
SnippetsPaneContent::SnippetsPaneContent()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// auto res = Windows::UI::Xaml::Application::Current().Resources();
|
||||
auto bg = Resources().Lookup(winrt::box_value(L"PageBackground"));
|
||||
Background(bg.try_as<WUX::Media::Brush>());
|
||||
}
|
||||
|
||||
void SnippetsPaneContent::_updateFilteredCommands()
|
||||
{
|
||||
const auto& queryString = _filterBox().Text();
|
||||
|
||||
// DON'T replace the itemSource here. If you do, it'll un-expand all the
|
||||
// nested items the user has expanded. Instead, just update the filter.
|
||||
// That'll also trigger a PropertyChanged for the Visibility property.
|
||||
for (const auto& t : _allTasks)
|
||||
{
|
||||
t.UpdateFilter(queryString);
|
||||
}
|
||||
}
|
||||
|
||||
void SnippetsPaneContent::UpdateSettings(const CascadiaSettings& settings)
|
||||
{
|
||||
_settings = settings;
|
||||
|
||||
// You'd think that `FilterToSendInput(queryString)` would work. It
|
||||
// doesn't! That uses the queryString as the current command the user
|
||||
// has typed, then relies on the suggestions UI to _also_ filter with that
|
||||
// string.
|
||||
|
||||
const auto tasks = _settings.GlobalSettings().ActionMap().FilterToSendInput(L""); // IVector<Model::Command>
|
||||
_allTasks = winrt::single_threaded_observable_vector<TerminalApp::FilteredTask>();
|
||||
for (const auto& t : tasks)
|
||||
{
|
||||
const auto& filtered{ winrt::make<FilteredTask>(t) };
|
||||
_allTasks.Append(filtered);
|
||||
}
|
||||
_treeView().ItemsSource(_allTasks);
|
||||
|
||||
_updateFilteredCommands();
|
||||
}
|
||||
|
||||
void SnippetsPaneContent::_filterTextChanged(const IInspectable& /*sender*/,
|
||||
const Windows::UI::Xaml::RoutedEventArgs& /*args*/)
|
||||
{
|
||||
_updateFilteredCommands();
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::FrameworkElement SnippetsPaneContent::GetRoot()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
winrt::Windows::Foundation::Size SnippetsPaneContent::MinimumSize()
|
||||
{
|
||||
return { 1, 1 };
|
||||
}
|
||||
void SnippetsPaneContent::Focus(winrt::Windows::UI::Xaml::FocusState reason)
|
||||
{
|
||||
reason;
|
||||
// _box.Focus(reason);
|
||||
}
|
||||
void SnippetsPaneContent::Close()
|
||||
{
|
||||
CloseRequested.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
INewContentArgs SnippetsPaneContent::GetNewTerminalArgs(BuildStartupKind /*kind*/) const
|
||||
{
|
||||
return BaseContentArgs(L"snippets");
|
||||
}
|
||||
|
||||
winrt::hstring SnippetsPaneContent::Icon() const
|
||||
{
|
||||
static constexpr std::wstring_view glyph{ L"\xe70b" }; // QuickNote
|
||||
return winrt::hstring{ glyph };
|
||||
}
|
||||
|
||||
winrt::Windows::UI::Xaml::Media::Brush SnippetsPaneContent::BackgroundBrush()
|
||||
{
|
||||
return Background();
|
||||
}
|
||||
|
||||
void SnippetsPaneContent::SetLastActiveControl(const Microsoft::Terminal::Control::TermControl& control)
|
||||
{
|
||||
_control = control;
|
||||
}
|
||||
|
||||
void SnippetsPaneContent::_runCommandButtonClicked(const Windows::Foundation::IInspectable& sender,
|
||||
const Windows::UI::Xaml::RoutedEventArgs&)
|
||||
{
|
||||
if (const auto& taskVM{ sender.try_as<WUX::Controls::Button>().DataContext().try_as<FilteredTask>() })
|
||||
{
|
||||
if (const auto& strongControl{ _control.get() })
|
||||
{
|
||||
// By using the last active control as the sender here, the
|
||||
// action dispatch will send this to the active control,
|
||||
// thinking that it is the control that requested this event.
|
||||
DispatchCommandRequested.raise(strongControl, taskVM->Command());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
140
src/cascadia/TerminalApp/SnippetsPaneContent.h
Normal file
140
src/cascadia/TerminalApp/SnippetsPaneContent.h
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
#include "SnippetsPaneContent.g.h"
|
||||
#include "FilteredTask.g.h"
|
||||
#include "FilteredCommand.h"
|
||||
#include "ActionPaletteItem.h"
|
||||
#include <LibraryResources.h>
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct SnippetsPaneContent : SnippetsPaneContentT<SnippetsPaneContent>
|
||||
{
|
||||
SnippetsPaneContent();
|
||||
|
||||
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
|
||||
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
|
||||
|
||||
winrt::Windows::Foundation::Size MinimumSize();
|
||||
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic);
|
||||
void Close();
|
||||
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(BuildStartupKind kind) const;
|
||||
|
||||
winrt::hstring Title() { return RS_(L"SnippetPaneTitle/Text"); }
|
||||
uint64_t TaskbarState() { return 0; }
|
||||
uint64_t TaskbarProgress() { return 0; }
|
||||
bool ReadOnly() { return false; }
|
||||
winrt::hstring Icon() const;
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept { return nullptr; }
|
||||
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
|
||||
|
||||
void SetLastActiveControl(const Microsoft::Terminal::Control::TermControl& control);
|
||||
|
||||
til::typed_event<> ConnectionStateChanged;
|
||||
til::typed_event<IPaneContent> CloseRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
|
||||
til::typed_event<IPaneContent> TitleChanged;
|
||||
til::typed_event<IPaneContent> TabColorChanged;
|
||||
til::typed_event<IPaneContent> TaskbarProgressChanged;
|
||||
til::typed_event<IPaneContent> ReadOnlyChanged;
|
||||
til::typed_event<IPaneContent> FocusRequested;
|
||||
|
||||
til::typed_event<winrt::Windows::Foundation::IInspectable, Microsoft::Terminal::Settings::Model::Command> DispatchCommandRequested;
|
||||
|
||||
private:
|
||||
friend struct SnippetsPaneContentT<SnippetsPaneContent>; // for Xaml to bind events
|
||||
|
||||
winrt::weak_ref<Microsoft::Terminal::Control::TermControl> _control{ nullptr };
|
||||
winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings _settings{ nullptr };
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<TerminalApp::FilteredTask> _allTasks{ nullptr };
|
||||
|
||||
void _runCommandButtonClicked(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs&);
|
||||
void _filterTextChanged(const Windows::Foundation::IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& args);
|
||||
|
||||
void _updateFilteredCommands();
|
||||
};
|
||||
|
||||
struct FilteredTask : FilteredTaskT<FilteredTask, TerminalApp::implementation::FilteredCommand>
|
||||
{
|
||||
FilteredTask() = default;
|
||||
|
||||
FilteredTask(const winrt::Microsoft::Terminal::Settings::Model::Command& command)
|
||||
{
|
||||
_constructFilteredCommand(winrt::make<winrt::TerminalApp::implementation::ActionPaletteItem>(command, L""));
|
||||
_command = command;
|
||||
|
||||
// The Children() method must always return a non-null vector
|
||||
_children = winrt::single_threaded_observable_vector<TerminalApp::FilteredTask>();
|
||||
if (_command.HasNestedCommands())
|
||||
{
|
||||
for (const auto& [_, child] : _command.NestedCommands())
|
||||
{
|
||||
auto vm{ winrt::make<FilteredTask>(child) };
|
||||
_children.Append(vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateFilter(const winrt::hstring& filter) override
|
||||
{
|
||||
TerminalApp::implementation::FilteredCommand::UpdateFilter(filter);
|
||||
for (const auto& c : _children)
|
||||
{
|
||||
c.UpdateFilter(filter);
|
||||
}
|
||||
|
||||
PropertyChanged.raise(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Visibility" });
|
||||
}
|
||||
|
||||
winrt::hstring Input()
|
||||
{
|
||||
if (const auto& actionItem{ _Item.try_as<winrt::TerminalApp::ActionPaletteItem>() })
|
||||
{
|
||||
if (const auto& command{ actionItem.Command() })
|
||||
{
|
||||
if (const auto& sendInput{ command.ActionAndArgs().Args().try_as<winrt::Microsoft::Terminal::Settings::Model::SendInputArgs>() })
|
||||
{
|
||||
return sendInput.Input();
|
||||
}
|
||||
}
|
||||
}
|
||||
return L"";
|
||||
};
|
||||
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<TerminalApp::FilteredTask> Children() { return _children; }
|
||||
bool HasChildren() { return _children.Size() > 0; }
|
||||
winrt::Microsoft::Terminal::Settings::Model::Command Command() { return _command; }
|
||||
|
||||
// Used to control if this item is visible in the TreeView. Turns out,
|
||||
// TreeView is in fact sane enough to remove items entirely if they're
|
||||
// Collapsed.
|
||||
winrt::Windows::UI::Xaml::Visibility Visibility()
|
||||
{
|
||||
// Is there no filter, or do we match it?
|
||||
if (_Filter.empty() || _Weight > 0)
|
||||
{
|
||||
return winrt::Windows::UI::Xaml::Visibility::Visible;
|
||||
}
|
||||
// If we don't match, maybe one of our children does
|
||||
auto totalWeight = _Weight;
|
||||
for (const auto& c : _children)
|
||||
{
|
||||
totalWeight += c.Weight();
|
||||
}
|
||||
|
||||
return totalWeight > 0 ? winrt::Windows::UI::Xaml::Visibility::Visible : winrt::Windows::UI::Xaml::Visibility::Collapsed;
|
||||
};
|
||||
|
||||
private:
|
||||
winrt::Microsoft::Terminal::Settings::Model::Command _command{ nullptr };
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<TerminalApp::FilteredTask> _children{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
namespace winrt::TerminalApp::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(SnippetsPaneContent);
|
||||
}
|
||||
236
src/cascadia/TerminalApp/SnippetsPaneContent.xaml
Normal file
236
src/cascadia/TerminalApp/SnippetsPaneContent.xaml
Normal file
@@ -0,0 +1,236 @@
|
||||
<!--
|
||||
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
|
||||
the MIT License. See LICENSE in the project root for license information.
|
||||
-->
|
||||
<UserControl x:Class="TerminalApp.SnippetsPaneContent"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:model="using:Microsoft.Terminal.Settings.Model"
|
||||
xmlns:mtu="using:Microsoft.Terminal.UI"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
AllowFocusOnInteraction="True"
|
||||
IsTabStop="True"
|
||||
TabNavigation="Cycle"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
<Style x:Key="PlayButtonTemplate"
|
||||
TargetType="Button">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Padding" Value="4" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border x:Name="ButtonBaseElement"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Viewbox Width="14"
|
||||
Height="14">
|
||||
<Grid>
|
||||
<FontIcon x:Name="ButtonBackgroundIcon"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
Foreground="{ThemeResource PlayButtonHoveredColor}"
|
||||
Glyph=""
|
||||
Visibility="Collapsed" />
|
||||
<FontIcon x:Name="ButtonOutlineIcon"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
Foreground="{ThemeResource PlayButtonNormalColor}"
|
||||
Glyph="" />
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
|
||||
<VisualState x:Name="Normal">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Visibility" Value="Collapsed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Visibility" Value="Visible" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled" />
|
||||
</VisualStateGroup>
|
||||
|
||||
<VisualStateGroup x:Name="PlayButtonStates">
|
||||
<VisualState x:Name="Ready">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ButtonBackgroundIcon.Glyph" Value="" />
|
||||
<Setter Target="ButtonOutlineIcon.Glyph" Value="" />
|
||||
<Setter Target="StatusProgress.IsActive" Value="False" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
</Style>
|
||||
|
||||
<DataTemplate x:Key="TaskItemTemplate"
|
||||
x:DataType="local:FilteredTask">
|
||||
<mux:TreeViewItem x:Name="rootItem"
|
||||
ItemsSource="{x:Bind Children}"
|
||||
Visibility="{x:Bind Visibility, Mode=OneWay}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ContentPresenter Grid.Column="0">
|
||||
<IconSourceElement Width="16"
|
||||
Height="16"
|
||||
IconSource="{x:Bind mtu:IconPathConverter.IconSourceWUX(Item.Icon), Mode=OneTime}"
|
||||
Visibility="Collapsed" />
|
||||
</ContentPresenter>
|
||||
|
||||
<Button x:Uid="SnippetPlayButton"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="1"
|
||||
Grid.Column="0"
|
||||
Margin="-28,0,0,0"
|
||||
Padding="3"
|
||||
VerticalAlignment="Bottom"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
Click="_runCommandButtonClicked"
|
||||
Style="{StaticResource PlayButtonTemplate}"
|
||||
Visibility="{x:Bind mtu:Converters.InvertedBooleanToVisibility(HasChildren), Mode=OneWay}">
|
||||
|
||||
<Button.Content>
|
||||
<FontIcon FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="12"
|
||||
Glyph="" />
|
||||
<!--
|
||||
xE768 is Play, which is just an outline.
|
||||
xF5B0 is PlaySolid, also a good option. Seemed
|
||||
better to have a lightweight outline though
|
||||
-->
|
||||
</Button.Content>
|
||||
|
||||
<Button.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{StaticResource SystemAccentColor}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<SolidColorBrush x:Key="ButtonBackground"
|
||||
Color="{ThemeResource SystemColorButtonFaceColor}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="ButtonBackgroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForeground"
|
||||
Color="{ThemeResource SystemColorButtonTextColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
<SolidColorBrush x:Key="ButtonForegroundPressed"
|
||||
Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
|
||||
<local:HighlightedTextControl Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind HighlightedName, Mode=OneWay}" />
|
||||
<TextBlock Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="12,0,0,6"
|
||||
FontFamily="Cascadia Mono, Consolas"
|
||||
IsTextSelectionEnabled="True"
|
||||
Style="{ThemeResource BodyTextBlockStyle}"
|
||||
Text="{x:Bind Input}"
|
||||
Visibility="{Binding ElementName=rootItem, Path=IsSelected}" />
|
||||
</Grid>
|
||||
</mux:TreeViewItem>
|
||||
</DataTemplate>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<!-- same as in MainPage, this is SolidBackgroundFillColorTertiary -->
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<Color x:Key="PageBackground">#282828</Color>
|
||||
<Color x:Key="PlayButtonHoveredColor">#90ef90</Color>
|
||||
<Color x:Key="PlayButtonNormalColor">#8888</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="PageBackground">#F9F9F9</Color>
|
||||
<Color x:Key="PlayButtonHoveredColor">#257f01</Color>
|
||||
<Color x:Key="PlayButtonNormalColor">#88222222</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<!-- Define resources for HighContrast mode here -->
|
||||
<StaticResource x:Key="PageBackground"
|
||||
ResourceKey="SystemColorWindowColorBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Background="{ThemeResource PageBackground}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock x:Name="_title"
|
||||
x:Uid="SnippetPaneTitle"
|
||||
Grid.Row="0"
|
||||
Margin="4"
|
||||
FontSize="24" />
|
||||
|
||||
<TextBox x:Name="_filterBox"
|
||||
x:Uid="SnippetsFilterBox"
|
||||
Grid.Row="1"
|
||||
Margin="8,0,8,8"
|
||||
TextChanged="_filterTextChanged" />
|
||||
|
||||
<mux:TreeView x:Name="_treeView"
|
||||
Grid.Row="2"
|
||||
CanDragItems="False"
|
||||
CanReorderItems="False"
|
||||
ItemTemplate="{StaticResource TaskItemTemplate}" />
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -71,6 +71,9 @@
|
||||
<Page Include="SuggestionsControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="SnippetsPaneContent.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<!-- ========================= Headers ======================== -->
|
||||
<ItemGroup>
|
||||
@@ -161,6 +164,9 @@
|
||||
<ClInclude Include="ScratchpadContent.h">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SnippetsPaneContent.h">
|
||||
<DependentUpon>SnippetsPaneContent.xaml</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SettingsPaneContent.h">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
@@ -274,6 +280,9 @@
|
||||
<ClCompile Include="ScratchpadContent.cpp">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SnippetsPaneContent.cpp">
|
||||
<DependentUpon>SnippetsPaneContent.xaml</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SettingsPaneContent.cpp">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
@@ -352,7 +361,10 @@
|
||||
</Midl>
|
||||
<Midl Include="FilteredCommand.idl" />
|
||||
<Midl Include="IPaneContent.idl" />
|
||||
<Midl Include="TerminalPaneContent.idl" />
|
||||
<Midl Include="TerminalPaneContent.idl" >
|
||||
<DependentUpon>TaskPaneContent.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Midl>
|
||||
<Midl Include="TerminalSettingsCache.idl" />
|
||||
</ItemGroup>
|
||||
<!-- ========================= Misc Files ======================== -->
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "DebugTapConnection.h"
|
||||
#include "SettingsPaneContent.h"
|
||||
#include "ScratchpadContent.h"
|
||||
#include "SnippetsPaneContent.h"
|
||||
#include "TabRowControl.h"
|
||||
#include "Utils.h"
|
||||
|
||||
@@ -453,10 +454,10 @@ namespace winrt::TerminalApp::implementation
|
||||
// - command - command to dispatch
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_OnDispatchCommandRequested(const IInspectable& /*sender*/, const Microsoft::Terminal::Settings::Model::Command& command)
|
||||
void TerminalPage::_OnDispatchCommandRequested(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::Command& command)
|
||||
{
|
||||
const auto& actionAndArgs = command.ActionAndArgs();
|
||||
_actionDispatch->DoAction(actionAndArgs);
|
||||
_actionDispatch->DoAction(sender, actionAndArgs);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -3252,6 +3253,15 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
content = _makeSettingsContent();
|
||||
}
|
||||
else if (paneType == L"snippets")
|
||||
{
|
||||
const auto& tasksContent{ winrt::make_self<SnippetsPaneContent>() };
|
||||
tasksContent->UpdateSettings(_settings);
|
||||
tasksContent->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
|
||||
tasksContent->DispatchCommandRequested({ this, &TerminalPage::_OnDispatchCommandRequested });
|
||||
|
||||
content = *tasksContent;
|
||||
}
|
||||
|
||||
assert(content);
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace winrt::TerminalApp::implementation
|
||||
Windows::Foundation::Size GridUnitSize();
|
||||
|
||||
til::typed_event<TerminalApp::TerminalPaneContent, winrt::Windows::Foundation::IInspectable> RestartTerminalRequested;
|
||||
|
||||
til::typed_event<> ConnectionStateChanged;
|
||||
til::typed_event<IPaneContent> CloseRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import "IPaneContent.idl";
|
||||
import "TerminalSettingsCache.idl";
|
||||
import "FilteredCommand.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
@@ -16,4 +17,21 @@ namespace TerminalApp
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<TerminalPaneContent, Object> RestartTerminalRequested;
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass FilteredTask : TerminalApp.FilteredCommand
|
||||
{
|
||||
String Input{ get; };
|
||||
Windows.Foundation.Collections.IObservableVector<FilteredTask> Children { get; };
|
||||
Boolean HasChildren { get; };
|
||||
Windows.UI.Xaml.Visibility Visibility { get; };
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass SnippetsPaneContent : Windows.UI.Xaml.Controls.UserControl, IPaneContent
|
||||
{
|
||||
SnippetsPaneContent();
|
||||
void SetLastActiveControl(Microsoft.Terminal.Control.TermControl control);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Microsoft.Terminal.Settings.Model.Command> DispatchCommandRequested;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1243,6 +1243,18 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// Raise our own ActivePaneChanged event.
|
||||
ActivePaneChanged.raise(*this, nullptr);
|
||||
|
||||
const auto content{ pane->GetContent() };
|
||||
if (const auto termContent{ content.try_as<winrt::TerminalApp::TerminalPaneContent>() })
|
||||
{
|
||||
const auto& termControl{ termContent.GetTermControl() };
|
||||
_rootPane->WalkTree([termControl](const auto& p) {
|
||||
if (const auto& taskPane{ p->GetContent().try_as<SnippetsPaneContent>() })
|
||||
{
|
||||
taskPane.SetLastActiveControl(termControl);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -836,6 +836,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
cmdImpl.copy_from(winrt::get_self<implementation::Command>(command));
|
||||
|
||||
const auto inArgs{ command.ActionAndArgs().Args().try_as<Model::SendInputArgs>() };
|
||||
|
||||
const auto inputString{ inArgs ? inArgs.Input() : L"" };
|
||||
auto args = winrt::make_self<SendInputArgs>(
|
||||
winrt::hstring{ fmt::format(FMT_COMPILE(L"{:\x7f^{}}{}"),
|
||||
|
||||
@@ -126,6 +126,9 @@
|
||||
<data name="SplitPaneParentCommandName" xml:space="preserve">
|
||||
<value>Split pane</value>
|
||||
</data>
|
||||
<data name="SnippetsPaneCommandName" xml:space="preserve">
|
||||
<value>Open snippets pane</value>
|
||||
</data>
|
||||
<data name="ApplicationDisplayNamePortable" xml:space="preserve">
|
||||
<value>Terminal (Portable)</value>
|
||||
<comment>This display name is used when the Terminal application is running in a "portable" mode, where settings are not stored in a shared location.</comment>
|
||||
@@ -730,4 +733,8 @@
|
||||
<data name="SaveActionNamePrefix" xml:space="preserve">
|
||||
<value>Save Task</value>
|
||||
</data>
|
||||
<data name="OpenTasksPaneCommandKey" xml:space="preserve">
|
||||
<value>Open tasks pane</value>
|
||||
<comment>This will open a pane with a list of the users's saved commands in it</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -446,6 +446,7 @@
|
||||
{ "command": "quit", "id": "Terminal.Quit" },
|
||||
{ "command": "restoreLastClosed", "id": "Terminal.RestoreLastClosed" },
|
||||
{ "command": "openAbout", "id": "Terminal.OpenAboutDialog" },
|
||||
{ "command": "experimental.openTasks", "id": "Terminal.OpenTasks" },
|
||||
|
||||
// Tab Management
|
||||
// "command": "closeTab" is unbound by default.
|
||||
@@ -528,6 +529,7 @@
|
||||
{ "command": { "action": "movePane", "index": 8 }, "id": "Terminal.MovePaneToTab8" },
|
||||
{ "command": { "action": "movePane", "window": "new" }, "id": "Terminal.MovePaneToNewWindow" },
|
||||
{ "command": "restartConnection", "id": "Terminal.RestartConnection" },
|
||||
{ "command": { "action": "splitPane", "type": "snippets" }, "id": "Terminal.OpenSnippetsPane", "name": { "key": "SnippetsPaneCommandName" } },
|
||||
|
||||
// Clipboard Integration
|
||||
{ "command": { "action": "copy", "singleLine": false }, "id": "Terminal.CopyToClipboard" },
|
||||
|
||||
@@ -133,7 +133,7 @@ public: \
|
||||
_##name = value; \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
protected: \
|
||||
type _##name{ __VA_ARGS__ };
|
||||
|
||||
// Use this macro to quickly implement both the getter and setter for an
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
private: \
|
||||
protected: \
|
||||
type _##name{ __VA_ARGS__ }; \
|
||||
void _set##name(const type& value) \
|
||||
{ \
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// The same as the above, but it doesn't visualize BS nor SPC.
|
||||
_TIL_INLINEPREFIX std::wstring visualize_nonspace_control_codes(std::wstring str) noexcept
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user