Add a progress ring indicator to the tab header (#8133)
This commit adds a [progress ring] to the tab header when we receive an OSC 9 sequence. Adds an event handler in `Tab.cpp` for the event we raise when we get a request to set the taskbar state/progress. This event handler updates the tab header with the active control's state/progress. When we want to show the progress ring, we hide the tab icon and place the progress ring over it. [progress ring]: https://docs.microsoft.com/en-us/uwp/api/Microsoft.UI.Xaml.Controls.ProgressRing?view=winui-2.4 References #6700
This commit is contained in:
parent
22d43a431c
commit
551cc9a98b
|
@ -23,6 +23,9 @@ namespace winrt::TerminalApp::implementation
|
|||
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
|
||||
OBSERVABLE_GETSET_PROPERTY(winrt::hstring, Title, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(bool, IsPaneZoomed, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(bool, IsProgressRingActive, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(bool, IsProgressRingIndeterminate, _PropertyChangedHandlers);
|
||||
OBSERVABLE_GETSET_PROPERTY(uint32_t, ProgressValue, _PropertyChangedHandlers);
|
||||
|
||||
private:
|
||||
bool _receivedKeyDown{ false };
|
||||
|
|
|
@ -9,6 +9,9 @@ namespace TerminalApp
|
|||
{
|
||||
String Title { get; set; };
|
||||
Boolean IsPaneZoomed { get; set; };
|
||||
Boolean IsProgressRingActive { get; set; };
|
||||
Boolean IsProgressRingIndeterminate { get; set; };
|
||||
UInt32 ProgressValue { get; set; };
|
||||
|
||||
TabHeaderControl();
|
||||
void BeginRename();
|
||||
|
|
|
@ -1,16 +1,31 @@
|
|||
<!-- 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.TabHeaderControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:TerminalApp"
|
||||
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel x:Name="HeaderStackPanel"
|
||||
Orientation="Horizontal">
|
||||
<mux:ProgressRing x:Name="HeaderProgressRing"
|
||||
IsActive="{x:Bind IsProgressRingActive, Mode=OneWay}"
|
||||
Visibility="{x:Bind IsProgressRingActive, Mode=OneWay}"
|
||||
IsIndeterminate="{x:Bind IsProgressRingIndeterminate, Mode=OneWay}"
|
||||
Value="{x:Bind ProgressValue, Mode=OneWay}"
|
||||
MinHeight="0"
|
||||
MinWidth="0"
|
||||
Height="15"
|
||||
Width="15"
|
||||
Margin="-7.5,0,8,0"/>
|
||||
<!--We want the progress ring to 'replace' the tab icon, but we don't have control
|
||||
over the tab icon here (the tab view item does) - so we hide the tab icon there
|
||||
and use a negative margin for the progress ring here to put it where the icon would be-->
|
||||
<FontIcon x:Name="HeaderZoomIcon"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Visibility="{x:Bind IsPaneZoomed, Mode=OneWay}"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "TerminalTab.g.cpp"
|
||||
#include "Utils.h"
|
||||
#include "ColorHelper.h"
|
||||
#include "AppLogic.h"
|
||||
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::UI::Xaml;
|
||||
|
@ -159,7 +160,7 @@ namespace winrt::TerminalApp::implementation
|
|||
// - profile: The GUID of the profile these settings should apply to.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalTab::UpdateSettings(const TerminalSettings& settings, const GUID& profile)
|
||||
void TerminalTab::UpdateSettings(const winrt::TerminalApp::TerminalSettings& settings, const GUID& profile)
|
||||
{
|
||||
_rootPane->UpdateSettings(settings, profile);
|
||||
}
|
||||
|
@ -180,6 +181,13 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
_lastIconPath = iconPath;
|
||||
|
||||
// If the icon is currently hidden, just return here (but only after setting _lastIconPath to the new path
|
||||
// for when we show the icon again)
|
||||
if (_iconHidden)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
co_await winrt::resume_foreground(TabViewItem().Dispatcher());
|
||||
|
@ -192,6 +200,34 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Hide or show the tab icon for this tab
|
||||
// - Used when we want to show the progress ring, which should replace the icon
|
||||
// Arguments:
|
||||
// - hide: if true, we hide the icon; if false, we show the icon
|
||||
winrt::fire_and_forget TerminalTab::HideIcon(const bool hide)
|
||||
{
|
||||
auto weakThis{ get_weak() };
|
||||
|
||||
co_await winrt::resume_foreground(TabViewItem().Dispatcher());
|
||||
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
if (hide)
|
||||
{
|
||||
Icon({});
|
||||
TabViewItem().IconSource(IconPathConverter::IconSourceMUX({}));
|
||||
tab->_iconHidden = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Icon(_lastIconPath);
|
||||
TabViewItem().IconSource(IconPathConverter::IconSourceMUX(_lastIconPath));
|
||||
tab->_iconHidden = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the title string of the last focused terminal control in our tree.
|
||||
// Returns the empty string if there is no such control.
|
||||
|
@ -441,6 +477,38 @@ namespace winrt::TerminalApp::implementation
|
|||
tab->_RecalculateAndApplyTabColor();
|
||||
}
|
||||
});
|
||||
|
||||
control.SetTaskbarProgress([weakThis](auto&&, auto&&) {
|
||||
// Check if Tab's lifetime has expired
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
// The progress of the control changed, but not necessarily the progress of the tab.
|
||||
// Set the tab's progress ring to the active pane's progress
|
||||
if (tab->GetActiveTerminalControl().TaskbarState() > 0)
|
||||
{
|
||||
if (tab->GetActiveTerminalControl().TaskbarState() == 3)
|
||||
{
|
||||
// 3 is the indeterminate state, set the progress ring as such
|
||||
tab->_headerControl.IsProgressRingIndeterminate(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// any non-indeterminate state has a value, set the progress ring as such
|
||||
tab->_headerControl.IsProgressRingIndeterminate(false);
|
||||
tab->_headerControl.ProgressValue(gsl::narrow<uint32_t>(tab->GetActiveTerminalControl().TaskbarProgress()));
|
||||
}
|
||||
// Hide the tab icon (the progress ring is placed over it)
|
||||
tab->HideIcon(true);
|
||||
tab->_headerControl.IsProgressRingActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show the tab icon
|
||||
tab->HideIcon(false);
|
||||
tab->_headerControl.IsProgressRingActive(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace winrt::TerminalApp::implementation
|
|||
void SplitPane(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType, const GUID& profile, winrt::Microsoft::Terminal::TerminalControl::TermControl& control);
|
||||
|
||||
winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath);
|
||||
winrt::fire_and_forget HideIcon(const bool hide);
|
||||
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
winrt::Microsoft::Terminal::Settings::Model::SplitState PreCalculateAutoSplit(winrt::Windows::Foundation::Size rootSize) const;
|
||||
|
@ -87,6 +88,7 @@ namespace winrt::TerminalApp::implementation
|
|||
uint16_t _nextPaneId{ 0 };
|
||||
|
||||
bool _receivedKeyDown{ false };
|
||||
bool _iconHidden{ false };
|
||||
|
||||
winrt::hstring _runtimeTabText{};
|
||||
bool _inRename{ false };
|
||||
|
|
Loading…
Reference in a new issue