Skip to content

Commit 0acb4d9

Browse files
committed
Allow a Pane to host a UserControl instead of a TermControl
1 parent 84e7ec4 commit 0acb4d9

File tree

2 files changed

+98
-50
lines changed

2 files changed

+98
-50
lines changed

src/cascadia/TerminalApp/Pane.cpp

Lines changed: 94 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,20 @@ static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Wi
3434
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr };
3535
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr };
3636

37-
Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFocused) :
37+
Pane::Pane(const Profile& profile, const Controls::UserControl& control, const bool lastFocused) :
3838
_control{ control },
3939
_lastActive{ lastFocused },
4040
_profile{ profile }
4141
{
4242
_root.Children().Append(_borderFirst);
4343
_borderFirst.Child(_control);
4444

45-
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
46-
_warningBellToken = _control.WarningBell({ this, &Pane::_ControlWarningBellHandler });
45+
const auto& termControl{ _control.try_as<TermControl>() };
46+
if (termControl)
47+
{
48+
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
49+
_warningBellToken = termControl.WarningBell({ this, &Pane::_ControlWarningBellHandler });
50+
}
4751

4852
// On the first Pane's creation, lookup resources we'll use to theme the
4953
// Pane, including the brushed to use for the focused/unfocused border
@@ -1079,8 +1083,12 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
10791083
{
10801084
return;
10811085
}
1082-
1083-
const auto newConnectionState = _control.ConnectionState();
1086+
const auto& termControl{ _control.try_as<TermControl>() };
1087+
if (!termControl)
1088+
{
1089+
return;
1090+
}
1091+
const auto newConnectionState = termControl.ConnectionState();
10841092
const auto previousConnectionState = std::exchange(_connectionState, newConnectionState);
10851093

10861094
if (newConnectionState < ConnectionState::Closed)
@@ -1123,7 +1131,9 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
11231131
{
11241132
return;
11251133
}
1126-
if (_profile)
1134+
1135+
const auto& termControl{ _control.try_as<TermControl>() };
1136+
if (_profile && termControl)
11271137
{
11281138
// We don't want to do anything if nothing is set, so check for that first
11291139
if (static_cast<int>(_profile.BellStyle()) != 0)
@@ -1137,7 +1147,7 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
11371147

11381148
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
11391149
{
1140-
_control.BellLightOn();
1150+
termControl.BellLightOn();
11411151
}
11421152

11431153
// raise the event with the bool value corresponding to the taskbar flag
@@ -1197,7 +1207,11 @@ void Pane::Shutdown()
11971207
std::unique_lock lock{ _createCloseLock };
11981208
if (_IsLeaf())
11991209
{
1200-
_control.Close();
1210+
const auto& termControl{ _control.try_as<TermControl>() };
1211+
if (termControl)
1212+
{
1213+
termControl.Close();
1214+
}
12011215
}
12021216
else
12031217
{
@@ -1207,7 +1221,7 @@ void Pane::Shutdown()
12071221
}
12081222

12091223
// Method Description:
1210-
// - Get the root UIElement of this pane. There may be a single TermControl as a
1224+
// - Get the root UIElement of this pane. There may be a single UserControl as a
12111225
// child, or an entire tree of grids and panes as children of this element.
12121226
// Arguments:
12131227
// - <none>
@@ -1283,10 +1297,11 @@ TermControl Pane::GetLastFocusedTerminalControl()
12831297
// Arguments:
12841298
// - <none>
12851299
// Return Value:
1286-
// - nullptr if this Pane is a parent, otherwise the TermControl of this Pane.
1287-
TermControl Pane::GetTerminalControl()
1300+
// - nullptr if this Pane is a parent or isn't hosting a Terminal, otherwise the
1301+
// TermControl of this Pane.
1302+
TermControl Pane::GetTerminalControl() const
12881303
{
1289-
return _IsLeaf() ? _control : nullptr;
1304+
return _IsLeaf() ? _control.try_as<TermControl>() : nullptr;
12901305
}
12911306

12921307
// Method Description:
@@ -1457,9 +1472,13 @@ void Pane::_FocusFirstChild()
14571472
void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
14581473
{
14591474
assert(_IsLeaf());
1460-
1475+
const auto& termControl{ _control.try_as<TermControl>() };
1476+
if (!termControl)
1477+
{
1478+
return;
1479+
}
14611480
_profile = profile;
1462-
auto controlSettings = _control.Settings().as<TerminalSettings>();
1481+
auto controlSettings = termControl.Settings().as<TerminalSettings>();
14631482
// Update the parent of the control's settings object (and not the object itself) so
14641483
// that any overrides made by the control don't get affected by the reload
14651484
controlSettings.SetParent(settings.DefaultSettings());
@@ -1472,8 +1491,8 @@ void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Pr
14721491
// sure the unfocused settings inherit from that.
14731492
unfocusedSettings.SetParent(controlSettings);
14741493
}
1475-
_control.UnfocusedAppearance(unfocusedSettings);
1476-
_control.UpdateSettings();
1494+
termControl.UnfocusedAppearance(unfocusedSettings);
1495+
termControl.UpdateSettings();
14771496
}
14781497

14791498
// Method Description:
@@ -1614,8 +1633,12 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
16141633
_id = remainingChild->Id();
16151634

16161635
// Add our new event handler before revoking the old one.
1617-
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
1618-
_warningBellToken = _control.WarningBell({ this, &Pane::_ControlWarningBellHandler });
1636+
const auto& termControl{ _control.try_as<TermControl>() };
1637+
if (termControl)
1638+
{
1639+
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
1640+
_warningBellToken = termControl.WarningBell({ this, &Pane::_ControlWarningBellHandler });
1641+
}
16191642

16201643
// Revoke the old event handlers. Remove both the handlers for the panes
16211644
// themselves closing, and remove their handlers for their controls
@@ -1629,24 +1652,33 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
16291652
closedChild->WalkTree([](auto p) {
16301653
if (p->_IsLeaf())
16311654
{
1632-
p->_control.ConnectionStateChanged(p->_connectionStateChangedToken);
1633-
p->_control.WarningBell(p->_warningBellToken);
1655+
const auto& closedControl{ p->_control.try_as<TermControl>() };
1656+
if (closedControl)
1657+
{
1658+
closedControl.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
1659+
closedControl.WarningBell(closedChild->_warningBellToken);
1660+
}
16341661
}
16351662
return false;
16361663
});
16371664
}
16381665

16391666
closedChild->Closed(closedChildClosedToken);
16401667
remainingChild->Closed(remainingChildClosedToken);
1641-
remainingChild->_control.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
1642-
remainingChild->_control.WarningBell(remainingChild->_warningBellToken);
1668+
1669+
const auto& remainingControl{ remainingChild->_control.try_as<TermControl>() };
1670+
if (remainingControl)
1671+
{
1672+
remainingControl.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
1673+
remainingControl.WarningBell(remainingChild->_warningBellToken);
1674+
}
16431675

16441676
// If we or either of our children was focused, we want to take that
16451677
// focus from them.
16461678
_lastActive = _lastActive || _firstChild->_lastActive || _secondChild->_lastActive;
16471679

16481680
// Remove all the ui elements of the remaining child. This'll make sure
1649-
// we can re-attach the TermControl to our Grid.
1681+
// we can re-attach the UserControl to our Grid.
16501682
remainingChild->_root.Children().Clear();
16511683
remainingChild->_borderFirst.Child(nullptr);
16521684

@@ -1657,7 +1689,7 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
16571689
_root.ColumnDefinitions().Clear();
16581690
_root.RowDefinitions().Clear();
16591691

1660-
// Reattach the TermControl to our grid.
1692+
// Reattach the UserControl to our grid.
16611693
_root.Children().Append(_borderFirst);
16621694
_borderFirst.Child(_control);
16631695

@@ -1719,8 +1751,12 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
17191751
closedChild->WalkTree([](auto p) {
17201752
if (p->_IsLeaf())
17211753
{
1722-
p->_control.ConnectionStateChanged(p->_connectionStateChangedToken);
1723-
p->_control.WarningBell(p->_warningBellToken);
1754+
const auto& closedControl{ p->_control.try_as<TermControl>() };
1755+
if (closedControl)
1756+
{
1757+
closedControl.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
1758+
closedControl.WarningBell(closedChild->_warningBellToken);
1759+
}
17241760
}
17251761
return false;
17261762
});
@@ -2352,18 +2388,18 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
23522388

23532389
// Method Description:
23542390
// - Split the focused pane in our tree of panes, and place the given
2355-
// TermControl into the newly created pane. If we're the focused pane, then
2391+
// UserControl into the newly created pane. If we're the focused pane, then
23562392
// we'll create two new children, and place them side-by-side in our Grid.
23572393
// Arguments:
23582394
// - splitType: what type of split we want to create.
23592395
// - profile: The profile to associate with the newly created pane.
2360-
// - control: A TermControl to use in the new pane.
2396+
// - control: A UserControl to use in the new pane.
23612397
// Return Value:
23622398
// - The two newly created Panes, with the original pane first
23632399
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitDirection splitType,
23642400
const float splitSize,
23652401
const Profile& profile,
2366-
const TermControl& control)
2402+
const Controls::UserControl& control)
23672403
{
23682404
if (!_lastActive)
23692405
{
@@ -2471,11 +2507,14 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
24712507

24722508
if (_IsLeaf())
24732509
{
2474-
// revoke our handler - the child will take care of the control now.
2475-
_control.ConnectionStateChanged(_connectionStateChangedToken);
2476-
_connectionStateChangedToken.value = 0;
2477-
_control.WarningBell(_warningBellToken);
2478-
_warningBellToken.value = 0;
2510+
if (const auto& termControl{ _control.try_as<TermControl>() })
2511+
{
2512+
// revoke our handler - the child will take care of the control now.
2513+
termControl.ConnectionStateChanged(_connectionStateChangedToken);
2514+
_connectionStateChangedToken.value = 0;
2515+
termControl.WarningBell(_warningBellToken);
2516+
_warningBellToken.value = 0;
2517+
}
24792518

24802519
// Remove our old GotFocus handler from the control. We don't want the
24812520
// control telling us that it's now focused, we want it telling its new
@@ -2485,7 +2524,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitDirect
24852524
}
24862525

24872526
// Remove any children we currently have. We can't add the existing
2488-
// TermControl to a new grid until we do this.
2527+
// UserControl to a new grid until we do this.
24892528
_root.Children().Clear();
24902529
_borderFirst.Child(nullptr);
24912530
_borderSecond.Child(nullptr);
@@ -2863,8 +2902,13 @@ float Pane::CalcSnappedDimension(const bool widthOrHeight, const float dimension
28632902
// If requested size is already snapped, then both returned values equal this value.
28642903
Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
28652904
{
2905+
const auto& termControl{ _control.try_as<TermControl>() };
28662906
if (_IsLeaf())
28672907
{
2908+
if (!termControl)
2909+
{
2910+
return { dimension, dimension };
2911+
}
28682912
// If we're a leaf pane, align to the grid of controlling terminal
28692913

28702914
const auto minSize = _GetMinSize();
@@ -2875,7 +2919,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
28752919
return { minDimension, minDimension };
28762920
}
28772921

2878-
float lower = _control.SnapDimensionToGrid(widthOrHeight, dimension);
2922+
float lower = termControl.SnapDimensionToGrid(widthOrHeight, dimension);
28792923
if (widthOrHeight)
28802924
{
28812925
lower += WI_IsFlagSet(_borders, Borders::Left) ? PaneBorderSize : 0;
@@ -2895,7 +2939,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
28952939
}
28962940
else
28972941
{
2898-
const auto cellSize = _control.CharacterDimensions();
2942+
const auto cellSize = termControl.CharacterDimensions();
28992943
const auto higher = lower + (widthOrHeight ? cellSize.Width : cellSize.Height);
29002944
return { lower, higher };
29012945
}
@@ -2940,7 +2984,8 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
29402984
// - <none>
29412985
void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& sizeNode) const
29422986
{
2943-
if (_IsLeaf())
2987+
const auto& termControl{ _control.try_as<TermControl>() };
2988+
if (_IsLeaf() && termControl)
29442989
{
29452990
// We're a leaf pane, so just add one more row or column (unless isMinimumSize
29462991
// is true, see below).
@@ -2955,11 +3000,11 @@ void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& si
29553000
}
29563001
else
29573002
{
2958-
const auto cellSize = _control.CharacterDimensions();
3003+
const auto cellSize = termControl.CharacterDimensions();
29593004
sizeNode.size += widthOrHeight ? cellSize.Width : cellSize.Height;
29603005
}
29613006
}
2962-
else
3007+
else if (!_IsLeaf())
29633008
{
29643009
// We're a parent pane, so we have to advance dimension of our children panes. In
29653010
// fact, we advance only one child (chosen later) to keep the growth fine-grained.
@@ -3061,7 +3106,8 @@ Size Pane::_GetMinSize() const
30613106
{
30623107
if (_IsLeaf())
30633108
{
3064-
auto controlSize = _control.MinimumSize();
3109+
const auto& termControl{ _control.try_as<TermControl>() };
3110+
auto controlSize = termControl ? termControl.MinimumSize() : Size{ 1, 1 };
30653111
auto newWidth = controlSize.Width;
30663112
auto newHeight = controlSize.Height;
30673113

@@ -3247,7 +3293,8 @@ std::optional<SplitDirection> Pane::PreCalculateAutoSplit(const std::shared_ptr<
32473293
// - Returns true if the pane or one of its descendants is read-only
32483294
bool Pane::ContainsReadOnly() const
32493295
{
3250-
return _IsLeaf() ? _control.ReadOnly() : (_firstChild->ContainsReadOnly() || _secondChild->ContainsReadOnly());
3296+
const auto& termControl{ GetTerminalControl() };
3297+
return termControl ? termControl.ReadOnly() : (_firstChild->ContainsReadOnly() || _secondChild->ContainsReadOnly());
32513298
}
32523299

32533300
// Method Description:
@@ -3260,13 +3307,14 @@ bool Pane::ContainsReadOnly() const
32603307
// - <none>
32613308
void Pane::CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states)
32623309
{
3263-
if (_IsLeaf())
3310+
const auto& termControl{ GetTerminalControl() };
3311+
if (termControl)
32643312
{
3265-
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(_control.TaskbarState(),
3266-
_control.TaskbarProgress()) };
3313+
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(termControl.TaskbarState(),
3314+
termControl.TaskbarProgress()) };
32673315
states.push_back(tbState);
32683316
}
3269-
else
3317+
else if (!_IsLeaf())
32703318
{
32713319
_firstChild->CollectTaskbarStates(states);
32723320
_secondChild->CollectTaskbarStates(states);

src/cascadia/TerminalApp/Pane.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class Pane : public std::enable_shared_from_this<Pane>
5656
{
5757
public:
5858
Pane(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
59-
const winrt::Microsoft::Terminal::Control::TermControl& control,
59+
const winrt::Windows::UI::Xaml::Controls::UserControl& control,
6060
const bool lastFocused = false);
6161

6262
Pane(std::shared_ptr<Pane> first,
@@ -67,7 +67,7 @@ class Pane : public std::enable_shared_from_this<Pane>
6767

6868
std::shared_ptr<Pane> GetActivePane();
6969
winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl();
70-
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl();
70+
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl() const;
7171
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
7272

7373
// Method Description:
@@ -111,7 +111,7 @@ class Pane : public std::enable_shared_from_this<Pane>
111111
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
112112
const float splitSize,
113113
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
114-
const winrt::Microsoft::Terminal::Control::TermControl& control);
114+
const winrt::Windows::UI::Xaml::Controls::UserControl& control);
115115
bool ToggleSplitOrientation();
116116
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
117117
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
@@ -201,7 +201,7 @@ class Pane : public std::enable_shared_from_this<Pane>
201201
winrt::Windows::UI::Xaml::Controls::Grid _root{};
202202
winrt::Windows::UI::Xaml::Controls::Border _borderFirst{};
203203
winrt::Windows::UI::Xaml::Controls::Border _borderSecond{};
204-
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
204+
winrt::Windows::UI::Xaml::Controls::UserControl _control{ nullptr };
205205
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
206206
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_focusedBorderBrush;
207207
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_unfocusedBorderBrush;

0 commit comments

Comments
 (0)