mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Add Vertical Alignment and Text Direction + UICatalog Demo (#1195)
* Add Vertical Alignment and Text Direction + UICatalog Demo * Justified text with "Right to Left" or "Bottom To Top" Directions.
This commit is contained in:
committed by
GitHub
parent
ae2f713e23
commit
cec9cc3559
@@ -27,6 +27,80 @@ namespace Terminal.Gui {
|
||||
Justified
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Vertical text alignment enumeration, controls how text is displayed.
|
||||
/// </summary>
|
||||
public enum VerticalTextAlignment {
|
||||
/// <summary>
|
||||
/// Aligns the text to the top of the frame.
|
||||
/// </summary>
|
||||
Top,
|
||||
/// <summary>
|
||||
/// Aligns the text to the bottom of the frame.
|
||||
/// </summary>
|
||||
Bottom,
|
||||
/// <summary>
|
||||
/// Centers the text verticaly in the frame.
|
||||
/// </summary>
|
||||
Middle,
|
||||
/// <summary>
|
||||
/// Shows the text as justified text in the frame.
|
||||
/// </summary>
|
||||
Justified
|
||||
}
|
||||
|
||||
/// TextDirection [H] = Horizontal [V] = Vertical
|
||||
/// =============
|
||||
/// LeftRight_TopBottom [H] Normal
|
||||
/// TopBottom_LeftRight [V] Normal
|
||||
///
|
||||
/// RightLeft_TopBottom [H] Invert Text
|
||||
/// TopBottom_RightLeft [V] Invert Lines
|
||||
///
|
||||
/// LeftRight_BottomTop [H] Invert Lines
|
||||
/// BottomTop_LeftRight [V] Invert Text
|
||||
///
|
||||
/// RightLeft_BottomTop [H] Invert Text + Invert Lines
|
||||
/// BottomTop_RightLeft [V] Invert Text + Invert Lines
|
||||
///
|
||||
/// <summary>
|
||||
/// Text direction enumeration, controls how text is displayed.
|
||||
/// </summary>
|
||||
public enum TextDirection {
|
||||
/// <summary>
|
||||
/// Normal Horizontal
|
||||
/// </summary>
|
||||
LeftRight_TopBottom,
|
||||
/// <summary>
|
||||
/// Normal Vertical
|
||||
/// </summary>
|
||||
TopBottom_LeftRight,
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
RightLeft_TopBottom,
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
TopBottom_RightLeft,
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
LeftRight_BottomTop,
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
BottomTop_LeftRight,
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
RightLeft_BottomTop,
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
BottomTop_RightLeft
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides text formatting capabilities for console apps. Supports, hotkeys, horizontal alignment, multiple lines, and word-based line wrap.
|
||||
/// </summary>
|
||||
@@ -34,6 +108,8 @@ namespace Terminal.Gui {
|
||||
List<ustring> lines = new List<ustring> ();
|
||||
ustring text;
|
||||
TextAlignment textAlignment;
|
||||
VerticalTextAlignment textVerticalAlignment;
|
||||
TextDirection textDirection;
|
||||
Attribute textColor = -1;
|
||||
bool needsFormat;
|
||||
Key hotKey;
|
||||
@@ -70,6 +146,90 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the vertical text-alignment property.
|
||||
/// </summary>
|
||||
/// <value>The text vertical alignment.</value>
|
||||
public VerticalTextAlignment VerticalAlignment {
|
||||
get => textVerticalAlignment;
|
||||
set {
|
||||
textVerticalAlignment = value;
|
||||
NeedsFormat = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the text-direction property.
|
||||
/// </summary>
|
||||
/// <value>The text vertical alignment.</value>
|
||||
public TextDirection Direction {
|
||||
get => textDirection;
|
||||
set {
|
||||
textDirection = value;
|
||||
NeedsFormat = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if it is a horizontal direction
|
||||
/// </summary>
|
||||
public static bool IsHorizontalDirection (TextDirection textDirection)
|
||||
{
|
||||
switch (textDirection) {
|
||||
case TextDirection.LeftRight_TopBottom:
|
||||
case TextDirection.LeftRight_BottomTop:
|
||||
case TextDirection.RightLeft_TopBottom:
|
||||
case TextDirection.RightLeft_BottomTop:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if it is a vertical direction
|
||||
/// </summary>
|
||||
public static bool IsVerticalDirection (TextDirection textDirection)
|
||||
{
|
||||
switch (textDirection) {
|
||||
case TextDirection.TopBottom_LeftRight:
|
||||
case TextDirection.TopBottom_RightLeft:
|
||||
case TextDirection.BottomTop_LeftRight:
|
||||
case TextDirection.BottomTop_RightLeft:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if it is Left to Right direction
|
||||
/// </summary>
|
||||
public static bool IsLeftToRight (TextDirection textDirection)
|
||||
{
|
||||
switch (textDirection) {
|
||||
case TextDirection.LeftRight_TopBottom:
|
||||
case TextDirection.LeftRight_BottomTop:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if it is Top to Bottom direction
|
||||
/// </summary>
|
||||
public static bool IsTopToBottom (TextDirection textDirection)
|
||||
{
|
||||
switch (textDirection) {
|
||||
case TextDirection.TopBottom_LeftRight:
|
||||
case TextDirection.TopBottom_RightLeft:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the area the text will be constrained to when formatted.
|
||||
/// </summary>
|
||||
@@ -113,7 +273,7 @@ namespace Terminal.Gui {
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Upon a 'get' of this property, if the text needs to be formatted (if <see cref="NeedsFormat"/> is <c>true</c>)
|
||||
/// <see cref="Format(ustring, int, TextAlignment, bool, bool)"/> will be called internally.
|
||||
/// <see cref="Format(ustring, int, bool, bool, bool)"/> will be called internally.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public List<ustring> Lines {
|
||||
@@ -135,7 +295,13 @@ namespace Terminal.Gui {
|
||||
if (Size.IsEmpty) {
|
||||
throw new InvalidOperationException ("Size must be set before accessing Lines");
|
||||
}
|
||||
lines = Format (shown_text, Size.Width, textAlignment, Size.Height > 1);
|
||||
|
||||
if (IsVerticalDirection (textDirection)) {
|
||||
lines = Format (shown_text, Size.Height, textVerticalAlignment == VerticalTextAlignment.Justified, Size.Width > 1);
|
||||
} else {
|
||||
lines = Format (shown_text, Size.Width, textAlignment == TextAlignment.Justified, Size.Height > 1);
|
||||
}
|
||||
|
||||
NeedsFormat = false;
|
||||
}
|
||||
return lines;
|
||||
@@ -256,6 +422,18 @@ namespace Terminal.Gui {
|
||||
/// <param name="talign">Alignment.</param>
|
||||
/// <returns>Justified and clipped text.</returns>
|
||||
public static ustring ClipAndJustify (ustring text, int width, TextAlignment talign)
|
||||
{
|
||||
return ClipAndJustify (text, width, talign == TextAlignment.Justified);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Justifies text within a specified width.
|
||||
/// </summary>
|
||||
/// <param name="text">The text to justify.</param>
|
||||
/// <param name="width">If the text length is greater that <c>width</c> it will be clipped.</param>
|
||||
/// <param name="justify">Justify.</param>
|
||||
/// <returns>Justified and clipped text.</returns>
|
||||
public static ustring ClipAndJustify (ustring text, int width, bool justify)
|
||||
{
|
||||
if (width < 0) {
|
||||
throw new ArgumentOutOfRangeException ("Width cannot be negative.");
|
||||
@@ -269,7 +447,7 @@ namespace Terminal.Gui {
|
||||
if (slen > width) {
|
||||
return ustring.Make (runes.GetRange (0, width));
|
||||
} else {
|
||||
if (talign == TextAlignment.Justified) {
|
||||
if (justify) {
|
||||
return Justify (text, width);
|
||||
}
|
||||
return text;
|
||||
@@ -337,6 +515,31 @@ namespace Terminal.Gui {
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static List<ustring> Format (ustring text, int width, TextAlignment talign, bool wordWrap, bool preserveTrailingSpaces = false)
|
||||
{
|
||||
return Format (text, width, talign == TextAlignment.Justified, wordWrap, preserveTrailingSpaces);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reformats text into lines, applying text alignment and optionally wrapping text to new lines on word boundaries.
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <param name="width">The width to bound the text to for word wrapping and clipping.</param>
|
||||
/// <param name="justify">Specifies whether the text should be justified.</param>
|
||||
/// <param name="wordWrap">If <c>true</c>, the text will be wrapped to new lines as need. If <c>false</c>, forces text to fit a single line. Line breaks are converted to spaces. The text will be clipped to <c>width</c></param>
|
||||
/// <param name="preserveTrailingSpaces">If <c>true</c> and 'wordWrap' also true, the wrapped text will keep the trailing spaces. If <c>false</c>, the trailing spaces will be trimmed.</param>
|
||||
/// <returns>A list of word wrapped lines.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// An empty <c>text</c> string will result in one empty line.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If <c>width</c> is 0, a single, empty line will be returned.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If <c>width</c> is int.MaxValue, the text will be formatted to the maximum width possible.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static List<ustring> Format (ustring text, int width, bool justify, bool wordWrap, bool preserveTrailingSpaces = false)
|
||||
{
|
||||
if (width < 0) {
|
||||
throw new ArgumentOutOfRangeException ("width cannot be negative");
|
||||
@@ -353,7 +556,7 @@ namespace Terminal.Gui {
|
||||
|
||||
if (wordWrap == false) {
|
||||
text = ReplaceCRLFWithSpace (text);
|
||||
lineResult.Add (ClipAndJustify (text, width, talign));
|
||||
lineResult.Add (ClipAndJustify (text, width, justify));
|
||||
return lineResult;
|
||||
}
|
||||
|
||||
@@ -365,7 +568,7 @@ namespace Terminal.Gui {
|
||||
if (c == '\n') {
|
||||
var wrappedLines = WordWrap (ustring.Make (runes.GetRange (lp, i - lp)), width, preserveTrailingSpaces);
|
||||
foreach (var line in wrappedLines) {
|
||||
lineResult.Add (ClipAndJustify (line, width, talign));
|
||||
lineResult.Add (ClipAndJustify (line, width, justify));
|
||||
}
|
||||
if (wrappedLines.Count == 0) {
|
||||
lineResult.Add (ustring.Empty);
|
||||
@@ -374,7 +577,7 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
foreach (var line in WordWrap (ustring.Make (runes.GetRange (lp, runeCount - lp)), width, preserveTrailingSpaces)) {
|
||||
lineResult.Add (ClipAndJustify (line, width, talign));
|
||||
lineResult.Add (ClipAndJustify (line, width, justify));
|
||||
}
|
||||
|
||||
return lineResult;
|
||||
@@ -388,7 +591,7 @@ namespace Terminal.Gui {
|
||||
/// <param name="width">The minimum width for the text.</param>
|
||||
public static int MaxLines (ustring text, int width)
|
||||
{
|
||||
var result = TextFormatter.Format (text, width, TextAlignment.Left, true);
|
||||
var result = TextFormatter.Format (text, width, false, true);
|
||||
return result.Count;
|
||||
}
|
||||
|
||||
@@ -400,7 +603,7 @@ namespace Terminal.Gui {
|
||||
/// <param name="width">The minimum width for the text.</param>
|
||||
public static int MaxWidth (ustring text, int width)
|
||||
{
|
||||
var result = TextFormatter.Format (text, width, TextAlignment.Left, true);
|
||||
var result = TextFormatter.Format (text, width, false, true);
|
||||
var max = 0;
|
||||
result.ForEach (s => {
|
||||
var m = 0;
|
||||
@@ -585,38 +788,111 @@ namespace Terminal.Gui {
|
||||
Application.Driver?.SetAttribute (normalColor);
|
||||
|
||||
// Use "Lines" to ensure a Format (don't use "lines"))
|
||||
for (int line = 0; line < Lines.Count; line++) {
|
||||
if (line > bounds.Height)
|
||||
|
||||
var linesFormated = Lines;
|
||||
switch (textDirection) {
|
||||
case TextDirection.TopBottom_RightLeft:
|
||||
case TextDirection.LeftRight_BottomTop:
|
||||
case TextDirection.RightLeft_BottomTop:
|
||||
case TextDirection.BottomTop_RightLeft:
|
||||
linesFormated.Reverse ();
|
||||
break;
|
||||
}
|
||||
|
||||
for (int line = 0; line < linesFormated.Count; line++) {
|
||||
var isVertical = IsVerticalDirection (textDirection);
|
||||
|
||||
if ((isVertical && (line > bounds.Width)) || (!isVertical && (line > bounds.Height)))
|
||||
continue;
|
||||
|
||||
var runes = lines [line].ToRunes ();
|
||||
int x;
|
||||
switch (textAlignment) {
|
||||
case TextAlignment.Left:
|
||||
case TextAlignment.Justified:
|
||||
x = bounds.Left;
|
||||
|
||||
switch (textDirection) {
|
||||
case TextDirection.RightLeft_BottomTop:
|
||||
case TextDirection.RightLeft_TopBottom:
|
||||
case TextDirection.BottomTop_LeftRight:
|
||||
case TextDirection.BottomTop_RightLeft:
|
||||
runes = runes.Reverse ().ToArray ();
|
||||
break;
|
||||
}
|
||||
|
||||
// When text is justified, we lost left or right, so we use the direction to align.
|
||||
|
||||
int x, y;
|
||||
// Horizontal Alignment
|
||||
if (textAlignment == TextAlignment.Right || (textAlignment == TextAlignment.Justified && !IsLeftToRight (textDirection))) {
|
||||
if (isVertical) {
|
||||
x = bounds.Right - Lines.Count + line;
|
||||
CursorPosition = bounds.Width - Lines.Count + hotKeyPos;
|
||||
} else {
|
||||
x = bounds.Right - runes.Length;
|
||||
CursorPosition = bounds.Width - runes.Length + hotKeyPos;
|
||||
}
|
||||
} else if (textAlignment == TextAlignment.Left || textAlignment == TextAlignment.Justified) {
|
||||
if (isVertical) {
|
||||
x = bounds.Left + line;
|
||||
} else {
|
||||
x = bounds.Left;
|
||||
}
|
||||
CursorPosition = hotKeyPos;
|
||||
break;
|
||||
case TextAlignment.Right:
|
||||
x = bounds.Right - runes.Length;
|
||||
CursorPosition = bounds.Width - runes.Length + hotKeyPos;
|
||||
break;
|
||||
case TextAlignment.Centered:
|
||||
x = bounds.Left + (bounds.Width - runes.Length) / 2;
|
||||
CursorPosition = (bounds.Width - runes.Length) / 2 + hotKeyPos;
|
||||
break;
|
||||
default:
|
||||
} else if (textAlignment == TextAlignment.Centered) {
|
||||
if (isVertical) {
|
||||
x = bounds.Left + line + ((bounds.Width - Lines.Count) / 2);
|
||||
CursorPosition = (bounds.Width - Lines.Count) / 2 + hotKeyPos;
|
||||
} else {
|
||||
x = bounds.Left + (bounds.Width - runes.Length) / 2;
|
||||
CursorPosition = (bounds.Width - runes.Length) / 2 + hotKeyPos;
|
||||
}
|
||||
} else {
|
||||
throw new ArgumentOutOfRangeException ();
|
||||
}
|
||||
var col = bounds.Left;
|
||||
for (var idx = bounds.Left; idx < bounds.Left + bounds.Width; idx++) {
|
||||
Application.Driver?.Move (col, bounds.Top + line);
|
||||
|
||||
// Vertical Alignment
|
||||
if (textVerticalAlignment == VerticalTextAlignment.Bottom || (textVerticalAlignment == VerticalTextAlignment.Justified && !IsTopToBottom (textDirection))) {
|
||||
if (isVertical) {
|
||||
y = bounds.Bottom - runes.Length;
|
||||
} else {
|
||||
y = bounds.Bottom - Lines.Count + line;
|
||||
}
|
||||
} else if (textVerticalAlignment == VerticalTextAlignment.Top || textVerticalAlignment == VerticalTextAlignment.Justified) {
|
||||
if (isVertical) {
|
||||
y = bounds.Top;
|
||||
} else {
|
||||
y = bounds.Top + line;
|
||||
}
|
||||
} else if (textVerticalAlignment == VerticalTextAlignment.Middle) {
|
||||
if (isVertical) {
|
||||
var s = (bounds.Height - runes.Length) / 2;
|
||||
y = bounds.Top + s;
|
||||
} else {
|
||||
var s = (bounds.Height - Lines.Count) / 2;
|
||||
y = bounds.Top + line + s;
|
||||
}
|
||||
} else {
|
||||
throw new ArgumentOutOfRangeException ();
|
||||
}
|
||||
|
||||
var start = isVertical ? bounds.Top : bounds.Left;
|
||||
var size = isVertical ? bounds.Height : bounds.Width;
|
||||
|
||||
var current = start;
|
||||
for (var idx = start; idx < start + size; idx++) {
|
||||
var rune = (Rune)' ';
|
||||
if (idx >= x && idx < (x + runes.Length)) {
|
||||
rune = runes [idx - x];
|
||||
if (isVertical) {
|
||||
Application.Driver?.Move (x, current);
|
||||
if (idx >= y && idx < (y + runes.Length)) {
|
||||
rune = runes [idx - y];
|
||||
}
|
||||
} else {
|
||||
Application.Driver?.Move (current, y);
|
||||
if (idx >= x && idx < (x + runes.Length)) {
|
||||
rune = runes [idx - x];
|
||||
}
|
||||
}
|
||||
if ((rune & HotKeyTagMask) == HotKeyTagMask) {
|
||||
if (textAlignment == TextAlignment.Justified) {
|
||||
CursorPosition = idx - bounds.Left;
|
||||
if ((isVertical && textVerticalAlignment == VerticalTextAlignment.Justified) ||
|
||||
(!isVertical && textAlignment == TextAlignment.Justified)) {
|
||||
CursorPosition = idx - start;
|
||||
}
|
||||
Application.Driver?.SetAttribute (hotColor);
|
||||
Application.Driver?.AddRune ((Rune)((uint)rune & ~HotKeyTagMask));
|
||||
@@ -624,9 +900,8 @@ namespace Terminal.Gui {
|
||||
} else {
|
||||
Application.Driver?.AddRune (rune);
|
||||
}
|
||||
col += Rune.ColumnWidth (rune);
|
||||
if (idx + 1 > - 1 && idx + 1 < runes.Length && col
|
||||
+ Rune.ColumnWidth (runes [idx + 1]) > bounds.Width) {
|
||||
current += Rune.ColumnWidth (rune);
|
||||
if (idx + 1 < runes.Length && current + Rune.ColumnWidth (runes [idx + 1]) > size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1995,6 +1995,30 @@ namespace Terminal.Gui {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets how the View's <see cref="Text"/> is aligned verticaly 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 {
|
||||
textFormatter.Direction = value;
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get or sets if the <see cref="View"/> was already initialized.
|
||||
/// This derived from <see cref="ISupportInitializeNotification"/> to allow notify all the views that are being initialized.
|
||||
|
||||
187
UICatalog/Scenarios/TextAlignmentsAndDirection.cs
Normal file
187
UICatalog/Scenarios/TextAlignmentsAndDirection.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Terminal.Gui;
|
||||
|
||||
namespace UICatalog {
|
||||
[ScenarioMetadata (Name: "Text Alignment and Direction", Description: "Demonstrates text alignment")]
|
||||
[ScenarioCategory ("Text")]
|
||||
class TextAlignmentsAndDirections : Scenario {
|
||||
|
||||
public override void Setup ()
|
||||
{
|
||||
// string txt = ".\n...\n.....\nHELLO\n.....\n...\n.";
|
||||
// string txt = "┌──┴──┐\n┤HELLO├\n└──┬──┘";
|
||||
string txt = "HELLO WORLD";
|
||||
|
||||
var color1 = new ColorScheme { Normal = Application.Driver.MakeAttribute (Color.Black, Color.Gray) };
|
||||
var color2 = new ColorScheme { Normal = Application.Driver.MakeAttribute (Color.Black, Color.DarkGray) };
|
||||
|
||||
var txts = new List<Label> (); // single line
|
||||
var mtxts = new List<Label> (); // multi line
|
||||
|
||||
// Horizontal Single-Line
|
||||
|
||||
var labelHL = new Label ("Left") { X = 1, Y = 1, Width = 9, Height = 1, TextAlignment = TextAlignment.Right, ColorScheme = Colors.ColorSchemes ["Dialog"] };
|
||||
var labelHC = new Label ("Centered") { X = 1, Y = 2, Width = 9, Height = 1, TextAlignment = TextAlignment.Right, ColorScheme = Colors.ColorSchemes ["Dialog"] };
|
||||
var labelHR = new Label ("Right") { X = 1, Y = 3, Width = 9, Height = 1, TextAlignment = TextAlignment.Right, ColorScheme = Colors.ColorSchemes ["Dialog"] };
|
||||
var labelHJ = new Label ("Justified") { X = 1, Y = 4, Width = 9, Height = 1, TextAlignment = TextAlignment.Right, ColorScheme = Colors.ColorSchemes ["Dialog"] };
|
||||
|
||||
var txtLabelHL = new Label (txt) { X = Pos.Right (labelHL) + 1, Y = Pos.Y (labelHL), Width = Dim.Fill (1) - 9, Height = 1, ColorScheme = color1, TextAlignment = TextAlignment.Left };
|
||||
var txtLabelHC = new Label (txt) { X = Pos.Right (labelHC) + 1, Y = Pos.Y (labelHC), Width = Dim.Fill (1) - 9, Height = 1, ColorScheme = color2, TextAlignment = TextAlignment.Centered };
|
||||
var txtLabelHR = new Label (txt) { X = Pos.Right (labelHR) + 1, Y = Pos.Y (labelHR), Width = Dim.Fill (1) - 9, Height = 1, ColorScheme = color1, TextAlignment = TextAlignment.Right };
|
||||
var txtLabelHJ = new Label (txt) { X = Pos.Right (labelHJ) + 1, Y = Pos.Y (labelHJ), Width = Dim.Fill (1) - 9, Height = 1, ColorScheme = color2, TextAlignment = TextAlignment.Justified };
|
||||
|
||||
txts.Add (txtLabelHL); txts.Add (txtLabelHC); txts.Add (txtLabelHR); txts.Add (txtLabelHJ);
|
||||
|
||||
Win.Add (labelHL); Win.Add (txtLabelHL);
|
||||
Win.Add (labelHC); Win.Add (txtLabelHC);
|
||||
Win.Add (labelHR); Win.Add (txtLabelHR);
|
||||
Win.Add (labelHJ); Win.Add (txtLabelHJ);
|
||||
|
||||
// Vertical Single-Line
|
||||
|
||||
var labelVT = new Label ("Top") { X = Pos.AnchorEnd (8), Y = 1, Width = 2, Height = 9, ColorScheme = color1, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Bottom };
|
||||
var labelVM = new Label ("Middle") { X = Pos.AnchorEnd (6), Y = 1, Width = 2, Height = 9, ColorScheme = color1, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Bottom };
|
||||
var labelVB = new Label ("Bottom") { X = Pos.AnchorEnd (4), Y = 1, Width = 2, Height = 9, ColorScheme = color1, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Bottom };
|
||||
var labelVJ = new Label ("Justified") { X = Pos.AnchorEnd (2), Y = 1, Width = 1, Height = 9, ColorScheme = color1, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Bottom };
|
||||
|
||||
var txtLabelVT = new Label (txt) { X = Pos.X (labelVT), Y = Pos.Bottom (labelVT) + 1, Width = 1, Height = Dim.Fill (1), ColorScheme = color1, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Top };
|
||||
var txtLabelVM = new Label (txt) { X = Pos.X (labelVM), Y = Pos.Bottom (labelVM) + 1, Width = 1, Height = Dim.Fill (1), ColorScheme = color2, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Middle };
|
||||
var txtLabelVB = new Label (txt) { X = Pos.X (labelVB), Y = Pos.Bottom (labelVB) + 1, Width = 1, Height = Dim.Fill (1), ColorScheme = color1, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Bottom };
|
||||
var txtLabelVJ = new Label (txt) { X = Pos.X (labelVJ), Y = Pos.Bottom (labelVJ) + 1, Width = 1, Height = Dim.Fill (1), ColorScheme = color2, TextDirection = TextDirection.TopBottom_LeftRight, VerticalTextAlignment = VerticalTextAlignment.Justified };
|
||||
|
||||
txts.Add (txtLabelVT); txts.Add (txtLabelVM); txts.Add (txtLabelVB); txts.Add (txtLabelVJ);
|
||||
|
||||
Win.Add (labelVT); Win.Add (txtLabelVT);
|
||||
Win.Add (labelVM); Win.Add (txtLabelVM);
|
||||
Win.Add (labelVB); Win.Add (txtLabelVB);
|
||||
Win.Add (labelVJ); Win.Add (txtLabelVJ);
|
||||
|
||||
// Multi-Line
|
||||
|
||||
var container = new View () { X = 0, Y = Pos.Bottom (txtLabelHJ), Width = Dim.Fill (31), Height = Dim.Fill (7), ColorScheme = color2 };
|
||||
|
||||
var txtLabelTL = new Label (txt) { X = 1 /* */, Y = 1, Width = Dim.Percent (100f / 3f), Height = Dim.Percent (100f / 3f), TextAlignment = TextAlignment.Left, VerticalTextAlignment = VerticalTextAlignment.Top, ColorScheme = color1 };
|
||||
var txtLabelTC = new Label (txt) { X = Pos.Right (txtLabelTL) + 2, Y = 1, Width = Dim.Percent (100f / 3f), Height = Dim.Percent (100f / 3f), TextAlignment = TextAlignment.Centered, VerticalTextAlignment = VerticalTextAlignment.Top, ColorScheme = color1 };
|
||||
var txtLabelTR = new Label (txt) { X = Pos.Right (txtLabelTC) + 2, Y = 1, Width = Dim.Percent (100f, true), Height = Dim.Percent (100f / 3f), TextAlignment = TextAlignment.Right, VerticalTextAlignment = VerticalTextAlignment.Top, ColorScheme = color1 };
|
||||
|
||||
var txtLabelML = new Label (txt) { X = Pos.X (txtLabelTL)/* */, Y = Pos.Bottom (txtLabelTL) + 1, Width = Dim.Width (txtLabelTL), Height = Dim.Percent (100f / 3f), TextAlignment = TextAlignment.Left, VerticalTextAlignment = VerticalTextAlignment.Middle, ColorScheme = color1 };
|
||||
var txtLabelMC = new Label (txt) { X = Pos.X (txtLabelTC)/* */, Y = Pos.Bottom (txtLabelTC) + 1, Width = Dim.Width (txtLabelTC), Height = Dim.Percent (100f / 3f), TextAlignment = TextAlignment.Centered, VerticalTextAlignment = VerticalTextAlignment.Middle, ColorScheme = color1 };
|
||||
var txtLabelMR = new Label (txt) { X = Pos.X (txtLabelTR)/* */, Y = Pos.Bottom (txtLabelTR) + 1, Width = Dim.Percent (100f, true), Height = Dim.Percent (100f / 3f), TextAlignment = TextAlignment.Right, VerticalTextAlignment = VerticalTextAlignment.Middle, ColorScheme = color1 };
|
||||
|
||||
var txtLabelBL = new Label (txt) { X = Pos.X (txtLabelML)/* */, Y = Pos.Bottom (txtLabelML) + 1, Width = Dim.Width (txtLabelML), Height = Dim.Percent (100f, true), TextAlignment = TextAlignment.Left, VerticalTextAlignment = VerticalTextAlignment.Bottom, ColorScheme = color1 };
|
||||
var txtLabelBC = new Label (txt) { X = Pos.X (txtLabelMC)/* */, Y = Pos.Bottom (txtLabelMC) + 1, Width = Dim.Width (txtLabelMC), Height = Dim.Percent (100f, true), TextAlignment = TextAlignment.Centered, VerticalTextAlignment = VerticalTextAlignment.Bottom, ColorScheme = color1 };
|
||||
var txtLabelBR = new Label (txt) { X = Pos.X (txtLabelMR)/* */, Y = Pos.Bottom (txtLabelMR) + 1, Width = Dim.Percent (100f, true), Height = Dim.Percent (100f, true), TextAlignment = TextAlignment.Right, VerticalTextAlignment = VerticalTextAlignment.Bottom, ColorScheme = color1 };
|
||||
|
||||
mtxts.Add (txtLabelTL); mtxts.Add (txtLabelTC); mtxts.Add (txtLabelTR);
|
||||
mtxts.Add (txtLabelML); mtxts.Add (txtLabelMC); mtxts.Add (txtLabelMR);
|
||||
mtxts.Add (txtLabelBL); mtxts.Add (txtLabelBC); mtxts.Add (txtLabelBR);
|
||||
|
||||
// Save Alignments in Data
|
||||
foreach (var t in mtxts) {
|
||||
t.Data = new { h = t.TextAlignment, v = t.VerticalTextAlignment };
|
||||
}
|
||||
|
||||
container.Add (txtLabelTL);
|
||||
container.Add (txtLabelTC);
|
||||
container.Add (txtLabelTR);
|
||||
|
||||
container.Add (txtLabelML);
|
||||
container.Add (txtLabelMC);
|
||||
container.Add (txtLabelMR);
|
||||
|
||||
container.Add (txtLabelBL);
|
||||
container.Add (txtLabelBC);
|
||||
container.Add (txtLabelBR);
|
||||
|
||||
Win.Add (container);
|
||||
|
||||
|
||||
// Edit Text
|
||||
|
||||
var editText = new TextView () {
|
||||
X = 1,
|
||||
Y = Pos.Bottom (container) + 1,
|
||||
Width = Dim.Fill (10),
|
||||
Height = Dim.Fill (1),
|
||||
ColorScheme = color2,
|
||||
Text = txt
|
||||
};
|
||||
|
||||
editText.MouseClick += (m) => {
|
||||
foreach (var v in txts) {
|
||||
v.Text = editText.Text;
|
||||
}
|
||||
foreach (var v in mtxts) {
|
||||
v.Text = editText.Text;
|
||||
}
|
||||
};
|
||||
|
||||
Win.KeyUp += (m) => {
|
||||
foreach (var v in txts) {
|
||||
v.Text = editText.Text;
|
||||
}
|
||||
foreach (var v in mtxts) {
|
||||
v.Text = editText.Text;
|
||||
}
|
||||
};
|
||||
|
||||
editText.SetFocus ();
|
||||
|
||||
Win.Add (editText);
|
||||
|
||||
|
||||
// JUSTIFY CHECKBOX
|
||||
|
||||
var justifyCheckbox = new CheckBox ("Justify") {
|
||||
X = Pos.Right (container) + 1,
|
||||
Y = Pos.Y (container) + 1,
|
||||
Width = Dim.Fill (10),
|
||||
Height = 1
|
||||
};
|
||||
|
||||
justifyCheckbox.Toggled += (prevtoggled) => {
|
||||
if (prevtoggled) {
|
||||
foreach (var t in mtxts) {
|
||||
t.TextAlignment = (TextAlignment)((dynamic)t.Data).h;
|
||||
t.VerticalTextAlignment = (VerticalTextAlignment)((dynamic)t.Data).v;
|
||||
}
|
||||
} else {
|
||||
foreach (var t in mtxts) {
|
||||
if (TextFormatter.IsVerticalDirection (t.TextDirection)) {
|
||||
t.VerticalTextAlignment = VerticalTextAlignment.Justified;
|
||||
t.TextAlignment = ((dynamic)t.Data).h;
|
||||
} else {
|
||||
t.TextAlignment = TextAlignment.Justified;
|
||||
t.VerticalTextAlignment = ((dynamic)t.Data).v;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Win.Add (justifyCheckbox);
|
||||
|
||||
|
||||
// Direction Options
|
||||
|
||||
var directionsEnum = Enum.GetValues (typeof (Terminal.Gui.TextDirection)).Cast<Terminal.Gui.TextDirection> ().ToList ();
|
||||
|
||||
var directionOptions = new RadioGroup (directionsEnum.Select (e => NStack.ustring.Make (e.ToString ())).ToArray ()) {
|
||||
X = Pos.Right (container) + 1,
|
||||
Y = Pos.Bottom (justifyCheckbox) + 1,
|
||||
Width = Dim.Fill (10),
|
||||
Height = Dim.Fill (1),
|
||||
HotKeySpecifier = '\xffff'
|
||||
};
|
||||
|
||||
directionOptions.SelectedItemChanged += (ev) => {
|
||||
foreach (var v in mtxts) {
|
||||
v.TextDirection = (TextDirection)ev.SelectedItem;
|
||||
}
|
||||
};
|
||||
|
||||
Win.Add (directionOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user