Allow a Pane to host a UserControl instead of a TermControl
This commit is contained in:
parent
14d21f492b
commit
c66a56656e
|
@ -34,7 +34,7 @@ static const Duration AnimationDuration = DurationHelper::FromTimeSpan(winrt::Wi
|
|||
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_focusedBorderBrush = { nullptr };
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush Pane::s_unfocusedBorderBrush = { nullptr };
|
||||
|
||||
Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFocused) :
|
||||
Pane::Pane(const Profile& profile, const Controls::UserControl& control, const bool lastFocused) :
|
||||
_control{ control },
|
||||
_lastActive{ lastFocused },
|
||||
_profile{ profile }
|
||||
|
@ -42,8 +42,12 @@ Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFo
|
|||
_root.Children().Append(_border);
|
||||
_border.Child(_control);
|
||||
|
||||
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
|
||||
_warningBellToken = _control.WarningBell({ this, &Pane::_ControlWarningBellHandler });
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
if (termControl)
|
||||
{
|
||||
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
|
||||
_warningBellToken = termControl.WarningBell({ this, &Pane::_ControlWarningBellHandler });
|
||||
}
|
||||
|
||||
// On the first Pane's creation, lookup resources we'll use to theme the
|
||||
// Pane, including the brushed to use for the focused/unfocused border
|
||||
|
@ -829,8 +833,12 @@ void Pane::_ControlConnectionStateChangedHandler(const winrt::Windows::Foundatio
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto newConnectionState = _control.ConnectionState();
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
if (!termControl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const auto newConnectionState = termControl.ConnectionState();
|
||||
const auto previousConnectionState = std::exchange(_connectionState, newConnectionState);
|
||||
|
||||
if (newConnectionState < ConnectionState::Closed)
|
||||
|
@ -873,7 +881,9 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
|
|||
{
|
||||
return;
|
||||
}
|
||||
if (_profile)
|
||||
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
if (_profile && termControl)
|
||||
{
|
||||
// We don't want to do anything if nothing is set, so check for that first
|
||||
if (static_cast<int>(_profile.BellStyle()) != 0)
|
||||
|
@ -887,7 +897,7 @@ void Pane::_ControlWarningBellHandler(const winrt::Windows::Foundation::IInspect
|
|||
|
||||
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
|
||||
{
|
||||
_control.BellLightOn();
|
||||
termControl.BellLightOn();
|
||||
}
|
||||
|
||||
// raise the event with the bool value corresponding to the taskbar flag
|
||||
|
@ -942,7 +952,11 @@ void Pane::Shutdown()
|
|||
std::unique_lock lock{ _createCloseLock };
|
||||
if (_IsLeaf())
|
||||
{
|
||||
_control.Close();
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
if (termControl)
|
||||
{
|
||||
termControl.Close();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -952,7 +966,7 @@ void Pane::Shutdown()
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Get the root UIElement of this pane. There may be a single TermControl as a
|
||||
// - Get the root UIElement of this pane. There may be a single UserControl as a
|
||||
// child, or an entire tree of grids and panes as children of this element.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
|
@ -993,10 +1007,11 @@ std::shared_ptr<Pane> Pane::GetActivePane()
|
|||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - nullptr if this Pane is a parent, otherwise the TermControl of this Pane.
|
||||
TermControl Pane::GetTerminalControl()
|
||||
// - nullptr if this Pane is a parent or isn't hosting a Terminal, otherwise the
|
||||
// TermControl of this Pane.
|
||||
TermControl Pane::GetTerminalControl() const
|
||||
{
|
||||
return _IsLeaf() ? _control : nullptr;
|
||||
return _IsLeaf() ? _control.try_as<TermControl>() : nullptr;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1147,9 +1162,13 @@ void Pane::_FocusFirstChild()
|
|||
void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
|
||||
{
|
||||
assert(_IsLeaf());
|
||||
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
if (!termControl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_profile = profile;
|
||||
auto controlSettings = _control.Settings().as<TerminalSettings>();
|
||||
auto controlSettings = termControl.Settings().as<TerminalSettings>();
|
||||
// Update the parent of the control's settings object (and not the object itself) so
|
||||
// that any overrides made by the control don't get affected by the reload
|
||||
controlSettings.SetParent(settings.DefaultSettings());
|
||||
|
@ -1162,8 +1181,8 @@ void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Pr
|
|||
// sure the unfocused settings inherit from that.
|
||||
unfocusedSettings.SetParent(controlSettings);
|
||||
}
|
||||
_control.UnfocusedAppearance(unfocusedSettings);
|
||||
_control.UpdateSettings();
|
||||
termControl.UnfocusedAppearance(unfocusedSettings);
|
||||
termControl.UpdateSettings();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -1294,8 +1313,12 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
|
|||
_id = remainingChild->Id();
|
||||
|
||||
// Add our new event handler before revoking the old one.
|
||||
_connectionStateChangedToken = _control.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
|
||||
_warningBellToken = _control.WarningBell({ this, &Pane::_ControlWarningBellHandler });
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
if (termControl)
|
||||
{
|
||||
_connectionStateChangedToken = termControl.ConnectionStateChanged({ this, &Pane::_ControlConnectionStateChangedHandler });
|
||||
_warningBellToken = termControl.WarningBell({ this, &Pane::_ControlWarningBellHandler });
|
||||
}
|
||||
|
||||
// Revoke the old event handlers. Remove both the handlers for the panes
|
||||
// themselves closing, and remove their handlers for their controls
|
||||
|
@ -1306,21 +1329,30 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
|
|||
// handlers since it is just getting moved.
|
||||
if (!isDetaching)
|
||||
{
|
||||
closedChild->_control.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
|
||||
closedChild->_control.WarningBell(closedChild->_warningBellToken);
|
||||
const auto& closedControl{ closedChild->_control.try_as<TermControl>() };
|
||||
if (closedControl)
|
||||
{
|
||||
closedControl.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
|
||||
closedControl.WarningBell(closedChild->_warningBellToken);
|
||||
}
|
||||
}
|
||||
|
||||
closedChild->Closed(closedChildClosedToken);
|
||||
remainingChild->Closed(remainingChildClosedToken);
|
||||
remainingChild->_control.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
|
||||
remainingChild->_control.WarningBell(remainingChild->_warningBellToken);
|
||||
|
||||
const auto& remainingControl{ remainingChild->_control.try_as<TermControl>() };
|
||||
if (remainingControl)
|
||||
{
|
||||
remainingControl.ConnectionStateChanged(remainingChild->_connectionStateChangedToken);
|
||||
remainingControl.WarningBell(remainingChild->_warningBellToken);
|
||||
}
|
||||
|
||||
// If either of our children was focused, we want to take that focus from
|
||||
// them.
|
||||
_lastActive = _firstChild->_lastActive || _secondChild->_lastActive;
|
||||
|
||||
// Remove all the ui elements of the remaining child. This'll make sure
|
||||
// we can re-attach the TermControl to our Grid.
|
||||
// we can re-attach the UserControl to our Grid.
|
||||
remainingChild->_root.Children().Clear();
|
||||
remainingChild->_border.Child(nullptr);
|
||||
|
||||
|
@ -1330,7 +1362,7 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
|
|||
_root.ColumnDefinitions().Clear();
|
||||
_root.RowDefinitions().Clear();
|
||||
|
||||
// Reattach the TermControl to our grid.
|
||||
// Reattach the UserControl to our grid.
|
||||
_root.Children().Append(_border);
|
||||
_border.Child(_control);
|
||||
|
||||
|
@ -1389,8 +1421,12 @@ void Pane::_CloseChild(const bool closeFirst, const bool isDetaching)
|
|||
closedChild->Closed(closedChildClosedToken);
|
||||
if (!isDetaching)
|
||||
{
|
||||
closedChild->_control.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
|
||||
closedChild->_control.WarningBell(closedChild->_warningBellToken);
|
||||
const auto& closedControl{ closedChild->_control.try_as<TermControl>() };
|
||||
if (closedControl)
|
||||
{
|
||||
closedControl.ConnectionStateChanged(closedChild->_connectionStateChangedToken);
|
||||
closedControl.WarningBell(closedChild->_warningBellToken);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset our UI:
|
||||
|
@ -1958,18 +1994,18 @@ std::optional<bool> Pane::PreCalculateCanSplit(const std::shared_ptr<Pane> targe
|
|||
|
||||
// Method Description:
|
||||
// - Split the focused pane in our tree of panes, and place the given
|
||||
// TermControl into the newly created pane. If we're the focused pane, then
|
||||
// UserControl into the newly created pane. If we're the focused pane, then
|
||||
// we'll create two new children, and place them side-by-side in our Grid.
|
||||
// Arguments:
|
||||
// - splitType: what type of split we want to create.
|
||||
// - profile: The profile to associate with the newly created pane.
|
||||
// - control: A TermControl to use in the new pane.
|
||||
// - control: A UserControl to use in the new pane.
|
||||
// Return Value:
|
||||
// - The two newly created Panes
|
||||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::Split(SplitState splitType,
|
||||
const float splitSize,
|
||||
const Profile& profile,
|
||||
const TermControl& control)
|
||||
const Controls::UserControl& control)
|
||||
{
|
||||
if (!_IsLeaf())
|
||||
{
|
||||
|
@ -2075,10 +2111,11 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
|
|||
// modify our tree
|
||||
std::unique_lock lock{ _createCloseLock };
|
||||
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
// revoke our handler - the child will take care of the control now.
|
||||
_control.ConnectionStateChanged(_connectionStateChangedToken);
|
||||
termControl.ConnectionStateChanged(_connectionStateChangedToken);
|
||||
_connectionStateChangedToken.value = 0;
|
||||
_control.WarningBell(_warningBellToken);
|
||||
termControl.WarningBell(_warningBellToken);
|
||||
_warningBellToken.value = 0;
|
||||
|
||||
// Remove our old GotFocus handler from the control. We don't what the
|
||||
|
@ -2091,7 +2128,7 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
|
|||
_desiredSplitPosition = 1.0f - splitSize;
|
||||
|
||||
// Remove any children we currently have. We can't add the existing
|
||||
// TermControl to a new grid until we do this.
|
||||
// UserControl to a new grid until we do this.
|
||||
_root.Children().Clear();
|
||||
_border.Child(nullptr);
|
||||
|
||||
|
@ -2413,8 +2450,13 @@ float Pane::CalcSnappedDimension(const bool widthOrHeight, const float dimension
|
|||
// If requested size is already snapped, then both returned values equal this value.
|
||||
Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const float dimension) const
|
||||
{
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
if (_IsLeaf())
|
||||
{
|
||||
if (!termControl)
|
||||
{
|
||||
return { dimension, dimension };
|
||||
}
|
||||
// If we're a leaf pane, align to the grid of controlling terminal
|
||||
|
||||
const auto minSize = _GetMinSize();
|
||||
|
@ -2425,7 +2467,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
|
|||
return { minDimension, minDimension };
|
||||
}
|
||||
|
||||
float lower = _control.SnapDimensionToGrid(widthOrHeight, dimension);
|
||||
float lower = termControl.SnapDimensionToGrid(widthOrHeight, dimension);
|
||||
if (widthOrHeight)
|
||||
{
|
||||
lower += WI_IsFlagSet(_borders, Borders::Left) ? PaneBorderSize : 0;
|
||||
|
@ -2445,7 +2487,7 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
|
|||
}
|
||||
else
|
||||
{
|
||||
const auto cellSize = _control.CharacterDimensions();
|
||||
const auto cellSize = termControl.CharacterDimensions();
|
||||
const auto higher = lower + (widthOrHeight ? cellSize.Width : cellSize.Height);
|
||||
return { lower, higher };
|
||||
}
|
||||
|
@ -2490,7 +2532,8 @@ Pane::SnapSizeResult Pane::_CalcSnappedDimension(const bool widthOrHeight, const
|
|||
// - <none>
|
||||
void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& sizeNode) const
|
||||
{
|
||||
if (_IsLeaf())
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
if (_IsLeaf() && termControl)
|
||||
{
|
||||
// We're a leaf pane, so just add one more row or column (unless isMinimumSize
|
||||
// is true, see below).
|
||||
|
@ -2505,11 +2548,11 @@ void Pane::_AdvanceSnappedDimension(const bool widthOrHeight, LayoutSizeNode& si
|
|||
}
|
||||
else
|
||||
{
|
||||
const auto cellSize = _control.CharacterDimensions();
|
||||
const auto cellSize = termControl.CharacterDimensions();
|
||||
sizeNode.size += widthOrHeight ? cellSize.Width : cellSize.Height;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!_IsLeaf())
|
||||
{
|
||||
// We're a parent pane, so we have to advance dimension of our children panes. In
|
||||
// fact, we advance only one child (chosen later) to keep the growth fine-grained.
|
||||
|
@ -2611,7 +2654,8 @@ Size Pane::_GetMinSize() const
|
|||
{
|
||||
if (_IsLeaf())
|
||||
{
|
||||
auto controlSize = _control.MinimumSize();
|
||||
const auto& termControl{ _control.try_as<TermControl>() };
|
||||
auto controlSize = termControl ? termControl.MinimumSize() : Size{ 1, 1 };
|
||||
auto newWidth = controlSize.Width;
|
||||
auto newHeight = controlSize.Height;
|
||||
|
||||
|
@ -2800,7 +2844,8 @@ std::optional<SplitState> Pane::PreCalculateAutoSplit(const std::shared_ptr<Pane
|
|||
// - Returns true if the pane or one of its descendants is read-only
|
||||
bool Pane::ContainsReadOnly() const
|
||||
{
|
||||
return _IsLeaf() ? _control.ReadOnly() : (_firstChild->ContainsReadOnly() || _secondChild->ContainsReadOnly());
|
||||
const auto& termControl{ GetTerminalControl() };
|
||||
return termControl ? termControl.ReadOnly() : (_firstChild->ContainsReadOnly() || _secondChild->ContainsReadOnly());
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -2813,13 +2858,14 @@ bool Pane::ContainsReadOnly() const
|
|||
// - <none>
|
||||
void Pane::CollectTaskbarStates(std::vector<winrt::TerminalApp::TaskbarState>& states)
|
||||
{
|
||||
if (_IsLeaf())
|
||||
const auto& termControl{ GetTerminalControl() };
|
||||
if (termControl)
|
||||
{
|
||||
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(_control.TaskbarState(),
|
||||
_control.TaskbarProgress()) };
|
||||
auto tbState{ winrt::make<winrt::TerminalApp::implementation::TaskbarState>(termControl.TaskbarState(),
|
||||
termControl.TaskbarProgress()) };
|
||||
states.push_back(tbState);
|
||||
}
|
||||
else
|
||||
else if (!_IsLeaf())
|
||||
{
|
||||
_firstChild->CollectTaskbarStates(states);
|
||||
_secondChild->CollectTaskbarStates(states);
|
||||
|
|
|
@ -48,11 +48,11 @@ class Pane : public std::enable_shared_from_this<Pane>
|
|||
{
|
||||
public:
|
||||
Pane(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control,
|
||||
const winrt::Windows::UI::Xaml::Controls::UserControl& control,
|
||||
const bool lastFocused = false);
|
||||
|
||||
std::shared_ptr<Pane> GetActivePane();
|
||||
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl();
|
||||
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl() const;
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
|
||||
|
||||
// Method Description:
|
||||
|
@ -84,7 +84,7 @@ public:
|
|||
std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Split(winrt::Microsoft::Terminal::Settings::Model::SplitState splitType,
|
||||
const float splitSize,
|
||||
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile,
|
||||
const winrt::Microsoft::Terminal::Control::TermControl& control);
|
||||
const winrt::Windows::UI::Xaml::Controls::UserControl& control);
|
||||
bool ToggleSplitOrientation();
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitState> PreCalculateAutoSplit(const std::shared_ptr<Pane> target,
|
||||
|
@ -155,7 +155,7 @@ private:
|
|||
|
||||
winrt::Windows::UI::Xaml::Controls::Grid _root{};
|
||||
winrt::Windows::UI::Xaml::Controls::Border _border{};
|
||||
winrt::Microsoft::Terminal::Control::TermControl _control{ nullptr };
|
||||
winrt::Windows::UI::Xaml::Controls::UserControl _control{ nullptr };
|
||||
winrt::Microsoft::Terminal::TerminalConnection::ConnectionState _connectionState{ winrt::Microsoft::Terminal::TerminalConnection::ConnectionState::NotConnected };
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_focusedBorderBrush;
|
||||
static winrt::Windows::UI::Xaml::Media::SolidColorBrush s_unfocusedBorderBrush;
|
||||
|
|
Loading…
Reference in a new issue