Skip to content

Commit

Permalink
Add a progress ring indicator to the tab header (microsoft#8133)
Browse files Browse the repository at this point in the history
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 microsoft#6700
  • Loading branch information
PankajBhojwani authored and mpela81 committed Jan 28, 2021
1 parent 395d29c commit 8eacefa
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/TabHeaderControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/TabHeaderControl.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
15 changes: 15 additions & 0 deletions src/cascadia/TerminalApp/TabHeaderControl.xaml
Original file line number Diff line number Diff line change
@@ -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}"
Expand Down
70 changes: 69 additions & 1 deletion src/cascadia/TerminalApp/TerminalTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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());
Expand All @@ -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.
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/TerminalTab.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -87,6 +88,7 @@ namespace winrt::TerminalApp::implementation
uint16_t _nextPaneId{ 0 };

bool _receivedKeyDown{ false };
bool _iconHidden{ false };

winrt::hstring _runtimeTabText{};
bool _inRename{ false };
Expand Down

0 comments on commit 8eacefa

Please sign in to comment.