mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
* Updated overview docs * Updated toc * Updated docs more * Updated yml via dependabot * Initial work in progress * Fixed some autosize things * Revamped Pos / Dim API docs * Removed margin * horiz->width * Updated MessageBoxes and Dialogs Scenarios to use AutoSize * AutoSize->Auxo * Adds validation * prep for Dialog to use Dim.Auto - Simplify unit tests to not depend on things not important to the unit test (like Dialog) * prep for Dialog to use Dim.Auto - Simplify unit tests * prep for Dialog to use Dim.Auto - Simplify unit tests * prep for Dialog to use Dim.Auto - Make Dialog tests not depend on MessageBox * Started on DimAuto unit tests * started impl on min/max. * started impl on min/max. * Added DimAutoStyle * Added arg checking for not implemented features * Temporarily made DimAutoStyle.Subviews default * Removed unneeded override of Anchor * Fixed GethashCode warning * Implemented DimAuto(min) * Fixed unit tests * renamed scenario * WIP * Moved ViewLayout.cs into Layout folder * Clean up cocde formatting * Renamed and moved SetFrameToFitText * Fixed API docs for SetRelativeLayout * Factored out SetRelativeLayout tests * Better documented existing SetRelativeLayout behavior + unit tess * Debugging Pos.Center + x in SetRelativeLayout - WIP * Progress on low level unit tess * Initial commit * Restored unmodified scenarios * Bump deps
260 lines
9.0 KiB
C#
260 lines
9.0 KiB
C#
using System.Text;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Terminal.Gui {
|
|
|
|
public partial class View {
|
|
string _text;
|
|
|
|
/// <summary>
|
|
/// The text displayed by the <see cref="View"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// The text will be drawn before any subviews are drawn.
|
|
/// </para>
|
|
/// <para>
|
|
/// The text will be drawn starting at the view origin (0, 0) and will be formatted according
|
|
/// to <see cref="TextAlignment"/> and <see cref="TextDirection"/>.
|
|
/// </para>
|
|
/// <para>
|
|
/// The text will word-wrap to additional lines if it does not fit horizontally. If <see cref="Bounds"/>'s height
|
|
/// is 1, the text will be clipped.
|
|
/// </para>
|
|
/// <para>
|
|
/// Set the <see cref="HotKeySpecifier"/> to enable hotkey support. To disable hotkey support set <see cref="HotKeySpecifier"/> to
|
|
/// <c>(Rune)0xffff</c>.
|
|
/// </para>
|
|
/// </remarks>
|
|
public virtual string Text {
|
|
get => _text;
|
|
set {
|
|
_text = value;
|
|
SetHotKey ();
|
|
UpdateTextFormatterText ();
|
|
//TextFormatter.Format ();
|
|
OnResizeNeeded ();
|
|
|
|
#if DEBUG
|
|
if (_text != null && string.IsNullOrEmpty (Id)) {
|
|
Id = _text;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="Gui.TextFormatter"/> used to format <see cref="Text"/>.
|
|
/// </summary>
|
|
public TextFormatter TextFormatter { get; set; }
|
|
|
|
/// <summary>
|
|
/// Can be overridden if the <see cref="Terminal.Gui.TextFormatter.Text"/> has
|
|
/// different format than the default.
|
|
/// </summary>
|
|
protected virtual void UpdateTextFormatterText ()
|
|
{
|
|
if (TextFormatter != null) {
|
|
TextFormatter.Text = _text;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets whether trailing spaces at the end of word-wrapped lines are preserved
|
|
/// or not when <see cref="TextFormatter.WordWrap"/> is enabled.
|
|
/// If <see langword="true"/> trailing spaces at the end of wrapped lines will be removed when
|
|
/// <see cref="Text"/> is formatted for display. The default is <see langword="false"/>.
|
|
/// </summary>
|
|
public virtual bool PreserveTrailingSpaces {
|
|
get => TextFormatter.PreserveTrailingSpaces;
|
|
set {
|
|
if (TextFormatter.PreserveTrailingSpaces != value) {
|
|
TextFormatter.PreserveTrailingSpaces = value;
|
|
TextFormatter.NeedsFormat = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets how the View's <see cref="Text"/> is aligned horizontally when drawn. Changing this property will redisplay the <see cref="View"/>.
|
|
/// </summary>
|
|
/// <value>The text alignment.</value>
|
|
public virtual TextAlignment TextAlignment {
|
|
get => TextFormatter.Alignment;
|
|
set {
|
|
TextFormatter.Alignment = value;
|
|
UpdateTextFormatterText ();
|
|
OnResizeNeeded ();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets how the View's <see cref="Text"/> is aligned vertically when drawn. Changing this property will redisplay the <see cref="View"/>.
|
|
/// </summary>
|
|
/// <value>The text alignment.</value>
|
|
public virtual VerticalTextAlignment VerticalTextAlignment {
|
|
get => TextFormatter.VerticalAlignment;
|
|
set {
|
|
TextFormatter.VerticalAlignment = value;
|
|
SetNeedsDisplay ();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the direction of the View's <see cref="Text"/>. Changing this property will redisplay the <see cref="View"/>.
|
|
/// </summary>
|
|
/// <value>The text alignment.</value>
|
|
public virtual TextDirection TextDirection {
|
|
get => TextFormatter.Direction;
|
|
set {
|
|
UpdateTextDirection (value);
|
|
TextFormatter.Direction = value;
|
|
}
|
|
}
|
|
|
|
private void UpdateTextDirection (TextDirection newDirection)
|
|
{
|
|
var directionChanged = TextFormatter.IsHorizontalDirection (TextFormatter.Direction)
|
|
!= TextFormatter.IsHorizontalDirection (newDirection);
|
|
TextFormatter.Direction = newDirection;
|
|
|
|
var isValidOldAutoSize = AutoSize && IsValidAutoSize (out var _);
|
|
|
|
UpdateTextFormatterText ();
|
|
|
|
if ((!ValidatePosDim && directionChanged && AutoSize)
|
|
|| (ValidatePosDim && directionChanged && AutoSize && isValidOldAutoSize)) {
|
|
OnResizeNeeded ();
|
|
} else if (directionChanged && IsAdded) {
|
|
ResizeBoundsToFit (Bounds.Size);
|
|
// BUGBUG: I think this call is redundant.
|
|
SetFrameToFitText ();
|
|
} else {
|
|
SetFrameToFitText ();
|
|
}
|
|
TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey ();
|
|
SetNeedsDisplay ();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Sets the size of the View to the minimum width or height required to fit <see cref="Text"/>.
|
|
/// </summary>
|
|
/// <returns><see langword="true"/> if the size was changed; <see langword="false"/> if <see cref="AutoSize"/> == <see langword="true"/> or
|
|
/// <see cref="Text"/> will not fit.</returns>
|
|
/// <remarks>
|
|
/// Always returns <see langword="false"/> if <see cref="AutoSize"/> is <see langword="true"/> or
|
|
/// if <see cref="Height"/> (Horizontal) or <see cref="Width"/> (Vertical) are not not set or zero.
|
|
/// Does not take into account word wrapping.
|
|
/// </remarks>
|
|
bool SetFrameToFitText ()
|
|
{
|
|
// BUGBUG: This API is broken - should not assume Frame.Height == Bounds.Height
|
|
// <summary>
|
|
// Gets the minimum dimensions required to fit the View's <see cref="Text"/>, factoring in <see cref="TextDirection"/>.
|
|
// </summary>
|
|
// <param name="sizeRequired">The minimum dimensions required.</param>
|
|
// <returns><see langword="true"/> if the dimensions fit within the View's <see cref="Bounds"/>, <see langword="false"/> otherwise.</returns>
|
|
// <remarks>
|
|
// Always returns <see langword="false"/> if <see cref="AutoSize"/> is <see langword="true"/> or
|
|
// if <see cref="Height"/> (Horizontal) or <see cref="Width"/> (Vertical) are not not set or zero.
|
|
// Does not take into account word wrapping.
|
|
// </remarks>
|
|
bool GetMinimumSizeOfText (out Size sizeRequired)
|
|
{
|
|
if (!IsInitialized) {
|
|
sizeRequired = new Size (0, 0);
|
|
return false;
|
|
}
|
|
sizeRequired = Bounds.Size;
|
|
|
|
if (!AutoSize && !string.IsNullOrEmpty (TextFormatter.Text)) {
|
|
switch (TextFormatter.IsVerticalDirection (TextDirection)) {
|
|
case true:
|
|
int colWidth = TextFormatter.GetSumMaxCharWidth (new List<string> { TextFormatter.Text }, 0, 1);
|
|
// TODO: v2 - This uses frame.Width; it should only use Bounds
|
|
if (_frame.Width < colWidth &&
|
|
(Width == null ||
|
|
Bounds.Width >= 0 &&
|
|
Width is Dim.DimAbsolute &&
|
|
Width.Anchor (0) >= 0 &&
|
|
Width.Anchor (0) < colWidth)) {
|
|
sizeRequired = new Size (colWidth, Bounds.Height);
|
|
return true;
|
|
}
|
|
break;
|
|
default:
|
|
if (_frame.Height < 1 &&
|
|
(Height == null ||
|
|
Height is Dim.DimAbsolute &&
|
|
Height.Anchor (0) == 0)) {
|
|
sizeRequired = new Size (Bounds.Width, 1);
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (GetMinimumSizeOfText (out var size)) {
|
|
_frame = new Rect (_frame.Location, size);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the width or height of the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> characters
|
|
/// in the <see cref="Text"/> property.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Only the first hotkey specifier found in <see cref="Text"/> is supported.
|
|
/// </remarks>
|
|
/// <param name="isWidth">If <see langword="true"/> (the default) the width required for the hotkey specifier is returned. Otherwise the height is returned.</param>
|
|
/// <returns>The number of characters required for the <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>. If the text direction specified
|
|
/// by <see cref="TextDirection"/> does not match the <paramref name="isWidth"/> parameter, <c>0</c> is returned.</returns>
|
|
public int GetHotKeySpecifierLength (bool isWidth = true)
|
|
{
|
|
if (isWidth) {
|
|
return TextFormatter.IsHorizontalDirection (TextDirection) &&
|
|
TextFormatter.Text?.Contains ((char)HotKeySpecifier.Value) == true
|
|
? Math.Max (HotKeySpecifier.GetColumns (), 0) : 0;
|
|
} else {
|
|
return TextFormatter.IsVerticalDirection (TextDirection) &&
|
|
TextFormatter.Text?.Contains ((char)HotKeySpecifier.Value) == true
|
|
? Math.Max (HotKeySpecifier.GetColumns (), 0) : 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the dimensions required for <see cref="Text"/> ignoring a <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/>.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Size GetSizeNeededForTextWithoutHotKey ()
|
|
{
|
|
return new Size (TextFormatter.Size.Width - GetHotKeySpecifierLength (),
|
|
TextFormatter.Size.Height - GetHotKeySpecifierLength (false));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the dimensions required for <see cref="Text"/> accounting for a <see cref="Terminal.Gui.TextFormatter.HotKeySpecifier"/> .
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Size GetTextFormatterSizeNeededForTextAndHotKey ()
|
|
{
|
|
if (string.IsNullOrEmpty (TextFormatter.Text)) {
|
|
|
|
if (!IsInitialized) return Size.Empty;
|
|
|
|
return Bounds.Size;
|
|
}
|
|
|
|
// BUGBUG: This IGNORES what Text is set to, using on only the current View size. This doesn't seem to make sense.
|
|
// BUGBUG: This uses Frame; in v2 it should be Bounds
|
|
return new Size (Bounds.Size.Width + GetHotKeySpecifierLength (),
|
|
Bounds.Size.Height + GetHotKeySpecifierLength (false));
|
|
}
|
|
}
|
|
} |