Files
Terminal.Gui/Terminal.Gui/Views/PanelView.cs
BDisp 49e2b95625 Fixes #1861. Border: Title property is preferable to Text. (#1862)
* Fixes #1861. Border Title property is preferable than the Text.

* Fixes #1866. Bug when scrolling text and type in a TextView. (#1868)

* Some fixes for the WebConsole support. (#1865)

* Invoking NotifyStopRunState for all situations.

* Added Clicked property to support web console.

* Changing to MoveDown to stay always visible.

* Fixes #1849. Wizard as non-popup is broken (#1853)

* trying to make it work

* Fixes #1849. Wizard as non-modal doesn't work

* Fixes #1855. Window and Frame content view without the margin frame.

* Fixing layout of non-modal

* WizardSTep is now a FrameView

* Now use Modal = false to set visual style automatically

* Removed Controls as an explicit construct. Now just Add to WizardStep

Co-authored-by: BDisp <bd.bdisp@gmail.com>

* Update docs with keybindings, global key event and designer (#1869)

* Added docs on keybinding and global key event

* Added TerminalGuiDesigner to showcases/examples

* Regenerated Docs (#1870)

* Fixed cancel logic. Title now shows for non-modal. (#1871)

* Fixes #1874. API docs on github are broken. (#1875)

* Fixes #1874. API docs on github are broken.

* Rebuild with docfx 2.59.3.0 version.

* Fixes Wizard cancel logic and updates docs (#1878)

* Fixed cancel logic. Title now shows for non-modal.

* trying to fix docs

* trying to fix docs

* Fixes #1867. Use Undo and Redo commands with WordWrap enabled. (#1877)

* Updated docs; regeneraged docs (#1881)

* Added a 'Read Only' to the Editor scenario Format menu. (#1882)

* Fixes #1883. Toplevel now propogates Loaded & Ready events to child Toplevel views.

* Updated API doc theme. Added Wizard Sample

* Tweaked API docs format and content. Fixed build warnings.

* Fixes #1889. Docs broken after org move.

* Regen API docs

* Fixes readme links to API docs

* Avoiding breaking change.

* Fixes typos.

* Passing string.Empty to Title from the default constructor.

* Initializes title with string.Empty instead of null.

Co-authored-by: Tig Kindel <tig@users.noreply.github.com>
Co-authored-by: Thomas Nind <31306100+tznind@users.noreply.github.com>
2022-08-01 16:06:15 -07:00

250 lines
6.8 KiB
C#

using System;
namespace Terminal.Gui {
/// <summary>
/// A container for single <see cref="Child"/> that will allow to drawn <see cref="Border"/> in
/// two ways. If <see cref="UsePanelFrame"/> the borders and the child will be accommodated in the available
/// panel size, otherwise the panel will be resized based on the child and borders thickness sizes.
/// </summary>
public class PanelView : View {
ChildContentView childContentView;
private class ChildContentView : View { }
private class SavedPosDim {
public Pos X;
public Pos Y;
public Dim Width;
public Dim Height;
}
private SavedPosDim savedPanel;
private SavedPosDim savedChild;
private View child;
private bool usePanelFrame;
/// <summary>
/// Initializes a panel with a null child.
/// </summary>
public PanelView () : this (null) { }
/// <summary>
/// Initializes a panel with a valid child.
/// </summary>
/// <param name="child"></param>
public PanelView (View child)
{
childContentView = new ChildContentView ();
base.Add (childContentView);
CanFocus = false;
Child = child;
if (child != null) {
Visible = child.Visible;
}
}
/// <summary>
/// Gets or sets if the panel size will used, otherwise the child size.
/// </summary>
public bool UsePanelFrame {
get => usePanelFrame;
set {
usePanelFrame = value;
AdjustContainer ();
}
}
/// <summary>
/// The child that will use this panel.
/// </summary>
public View Child {
get => child;
set {
if (child != null && value == null) {
childContentView.Remove (child);
child = value;
return;
}
child = value;
savedChild = new SavedPosDim () {
X = child?.X ?? child?.Frame.X,
Y = child?.Y ?? child?.Frame.Y,
Width = child?.Width ?? child?.Frame.Width,
Height = child?.Height ?? child?.Frame.Height
};
if (child == null) {
Visible = false;
return;
}
if (child?.Border != null) {
Border = child.Border;
} else {
if (Border == null) {
Border = new Border ();
}
Child.Border = Border;
}
Border.Child = childContentView;
if (!child.IsInitialized) {
child.Initialized += Child_Initialized;
}
childContentView.Add (Child);
}
}
/// <inheritdoc />
public override Border Border {
get => base.Border;
set {
if (base.Border?.Child != null && value.Child == null) {
value.Child = base.Border.Child;
}
base.Border = value;
if (value == null) {
return;
}
Border.BorderChanged += Border_BorderChanged;
if (Child != null && (Child?.Border == null || Child?.Border != value)) {
if (Child?.Border == null) {
Child.Border = new Border ();
}
Child.Border = Border;
Child.Border.BorderChanged += Border_BorderChanged;
}
AdjustContainer ();
}
}
private void Child_Initialized (object sender, EventArgs e)
{
savedPanel = new SavedPosDim () {
X = X,
Y = Y,
Width = Width,
Height = Height
};
AdjustContainer ();
Child.Initialized -= Child_Initialized;
}
private void Border_BorderChanged (Border obj)
{
AdjustContainer ();
}
private void AdjustContainer ()
{
if (Child?.IsInitialized == true) {
if (Child?.Border != null && Child.Border != Border) {
Border = Child.Border;
}
var borderLength = Child.Border.DrawMarginFrame ? 1 : 0;
var sumPadding = Child.Border.GetSumThickness ();
var effect3DOffset = Child.Border.Effect3D ? Child.Border.Effect3DOffset : new Point ();
if (!UsePanelFrame) {
X = savedPanel.X;
childContentView.X = borderLength + sumPadding.Left;
Y = savedPanel.Y;
childContentView.Y = borderLength + sumPadding.Top;
if (savedChild.Width is Dim.DimFill) {
var margin = -savedChild.Width.Anchor (0);
Width = Dim.Fill (margin);
childContentView.Width = Dim.Fill (margin + borderLength + sumPadding.Right);
} else {
var savedLayout = LayoutStyle;
LayoutStyle = LayoutStyle.Absolute;
Width = savedChild.X.Anchor (0) + savedChild.Width + (2 * borderLength) + sumPadding.Right + sumPadding.Left;
LayoutStyle = savedLayout;
childContentView.Width = Dim.Fill (borderLength + sumPadding.Right);
}
if (savedChild.Height is Dim.DimFill) {
var margin = -savedChild.Height.Anchor (0);
Height = Dim.Fill (margin);
childContentView.Height = Dim.Fill (margin + borderLength + sumPadding.Bottom);
} else {
var savedLayout = LayoutStyle;
LayoutStyle = LayoutStyle.Absolute;
Height = savedChild.Y.Anchor (0) + savedChild.Height + (2 * borderLength) + sumPadding.Bottom + sumPadding.Top;
LayoutStyle = savedLayout;
childContentView.Height = Dim.Fill (borderLength + sumPadding.Bottom);
}
} else {
X = savedPanel.X - (effect3DOffset.X < 0 ? effect3DOffset.X : 0);
childContentView.X = borderLength + sumPadding.Left;
Y = savedPanel.Y - (effect3DOffset.Y < 0 ? effect3DOffset.Y : 0);
childContentView.Y = borderLength + sumPadding.Top;
Width = savedPanel.Width;
Height = savedPanel.Height;
if (Width is Dim.DimFill) {
var margin = -savedPanel.Width.Anchor (0) +
(effect3DOffset.X > 0 ? effect3DOffset.X : 0);
Width = Dim.Fill (margin);
childContentView.Width = Dim.Fill (margin + borderLength + sumPadding.Right +
(effect3DOffset.X > 0 ? effect3DOffset.X : 0));
} else {
childContentView.Width = Dim.Fill (borderLength + sumPadding.Right);
}
if (Height is Dim.DimFill) {
var margin = -savedPanel.Height.Anchor (0) +
(effect3DOffset.Y > 0 ? effect3DOffset.Y : 0);
Height = Dim.Fill (margin);
childContentView.Height = Dim.Fill (margin + borderLength + sumPadding.Bottom +
(effect3DOffset.Y > 0 ? effect3DOffset.Y : 0));
} else {
childContentView.Height = Dim.Fill (borderLength + sumPadding.Bottom);
}
}
Visible = Child.Visible;
} else {
Visible = false;
}
}
/// <inheritdoc/>
public override void Add (View view)
{
if (Child != null) {
Child = null;
}
Child = view;
}
/// <inheritdoc/>
public override void Remove (View view)
{
if (view == childContentView) {
base.Remove (view);
return;
}
childContentView.Remove (view);
if (Child != null) {
Child = null;
}
}
/// <inheritdoc/>
public override void RemoveAll ()
{
if (Child != null) {
Child = null;
}
}
/// <inheritdoc/>
public override void Redraw (Rect bounds)
{
if (!NeedDisplay.IsEmpty) {
Driver.SetAttribute (Child.GetNormalColor ());
Clear ();
Child.Border.DrawContent (Border.Child);
}
var savedClip = childContentView.ClipToBounds ();
childContentView.Redraw (childContentView.Bounds);
Driver.Clip = savedClip;
ClearLayoutNeeded ();
ClearNeedsDisplay ();
}
}
}