1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-24 13:38:34 +01:00

Compare commits

..

No commits in common. "d385581c25db946ee9520c63a3d652b0ee8673bf" and "f94d471365376f646b5d50eb179ff59d68f73756" have entirely different histories.

8 changed files with 44 additions and 123 deletions

View file

@ -60,17 +60,6 @@ namespace MLEM.Ui.Elements {
this.CanBeSelected = !value; this.CanBeSelected = !value;
} }
} }
/// <summary>
/// Whether this button's <see cref="Text"/> should be truncated if it exceeds this button's width.
/// Defaults to false.
/// </summary>
public bool TruncateTextIfLong {
get => this.Text?.TruncateIfLong ?? false;
set {
if (this.Text != null)
this.Text.TruncateIfLong = value;
}
}
/// <summary> /// <summary>
/// Creates a new button with the given settings /// Creates a new button with the given settings
@ -82,7 +71,7 @@ namespace MLEM.Ui.Elements {
/// <param name="tooltipWidth">The width of this button's <see cref="Tooltip"/>, or 50 by default</param> /// <param name="tooltipWidth">The width of this button's <see cref="Tooltip"/>, or 50 by default</param>
public Button(Anchor anchor, Vector2 size, string text = null, string tooltipText = null, float tooltipWidth = 50) : base(anchor, size) { public Button(Anchor anchor, Vector2 size, string text = null, string tooltipText = null, float tooltipWidth = 50) : base(anchor, size) {
if (text != null) { if (text != null) {
this.Text = new Paragraph(Anchor.Center, 1, text, true) {Padding = new Vector2(1)}; this.Text = new Paragraph(Anchor.Center, 1, text, true);
this.AddChild(this.Text); this.AddChild(this.Text);
} }
if (tooltipText != null) if (tooltipText != null)

View file

@ -64,16 +64,6 @@ namespace MLEM.Ui.Elements {
/// </summary> /// </summary>
public bool AutoAdjustWidth; public bool AutoAdjustWidth;
/// <summary> /// <summary>
/// Whether this paragraph should be truncated instead of split if the displayed <see cref="Text"/>'s width exceeds the provided width.
/// When the string is truncated, the <see cref="Ellipsis"/> is added to its end.
/// </summary>
public bool TruncateIfLong;
/// <summary>
/// The ellipsis characters to use if <see cref="TruncateIfLong"/> is enabled and the string is truncated.
/// If this is set to an empty string, no ellipsis will be attached to the truncated string.
/// </summary>
public string Ellipsis = "...";
/// <summary>
/// An event that gets called when this paragraph's <see cref="Text"/> is queried. /// An event that gets called when this paragraph's <see cref="Text"/> is queried.
/// Use this event for setting this paragraph's text if it changes frequently. /// Use this event for setting this paragraph's text if it changes frequently.
/// </summary> /// </summary>
@ -152,14 +142,7 @@ namespace MLEM.Ui.Elements {
foreach (var link in this.TokenizedText.Tokens.Where(t => t.AppliedCodes.Any(c => c is LinkCode))) foreach (var link in this.TokenizedText.Tokens.Where(t => t.AppliedCodes.Any(c => c is LinkCode)))
this.AddChild(new Link(Anchor.TopLeft, link, this.TextScale * this.TextScaleMultiplier)); this.AddChild(new Link(Anchor.TopLeft, link, this.TextScale * this.TextScaleMultiplier));
} }
this.TokenizedText.Split(this.RegularFont, size.X - this.ScaledPadding.Width, this.TextScale * this.TextScaleMultiplier * this.Scale);
var width = size.X - this.ScaledPadding.Width;
var scale = this.TextScale * this.TextScaleMultiplier * this.Scale;
if (this.TruncateIfLong) {
this.TokenizedText.Truncate(this.RegularFont, width, scale, this.Ellipsis);
} else {
this.TokenizedText.Split(this.RegularFont, width, scale);
}
} }
private void QueryTextCallback() { private void QueryTextCallback() {

View file

@ -1,17 +0,0 @@
using System.Text.RegularExpressions;
namespace MLEM.Formatting.Codes {
/// <inheritdoc />
public class ResetFormattingCode : Code {
/// <inheritdoc />
public ResetFormattingCode(Match match, Regex regex) : base(match, regex) {
}
/// <inheritdoc />
public override bool EndsHere(Code other) {
return true;
}
}
}

View file

@ -6,13 +6,13 @@ using MLEM.Font;
namespace MLEM.Formatting.Codes { namespace MLEM.Formatting.Codes {
/// <inheritdoc /> /// <inheritdoc />
public class ShadowCode : Code { public class ShadowCode : FontCode {
private readonly Color color; private readonly Color color;
private readonly Vector2 offset; private readonly Vector2 offset;
/// <inheritdoc /> /// <inheritdoc />
public ShadowCode(Match match, Regex regex, Color color, Vector2 offset) : base(match, regex) { public ShadowCode(Match match, Regex regex, Color color, Vector2 offset) : base(match, regex, null) {
this.color = color; this.color = color;
this.offset = offset; this.offset = offset;
} }
@ -24,10 +24,5 @@ namespace MLEM.Formatting.Codes {
return false; return false;
} }
/// <inheritdoc />
public override bool EndsHere(Code other) {
return base.EndsHere(other) || other is ResetFormattingCode;
}
} }
} }

View file

@ -29,10 +29,5 @@ namespace MLEM.Formatting.Codes {
return false; return false;
} }
/// <inheritdoc />
public override bool EndsHere(Code other) {
return base.EndsHere(other) || other is ResetFormattingCode;
}
} }
} }

View file

@ -38,8 +38,7 @@ namespace MLEM.Formatting {
m.Groups[1].Success ? ColorHelper.FromHexString(m.Groups[1].Value) : Color.Black, m.Groups[1].Success ? ColorHelper.FromHexString(m.Groups[1].Value) : Color.Black,
new Vector2(float.TryParse(m.Groups[2].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var offset) ? offset : 2))); new Vector2(float.TryParse(m.Groups[2].Value, NumberStyles.Number, CultureInfo.InvariantCulture, out var offset) ? offset : 2)));
this.Codes.Add(new Regex("<u>"), (f, m, r) => new UnderlineCode(m, r, 1 / 16F, 0.85F)); this.Codes.Add(new Regex("<u>"), (f, m, r) => new UnderlineCode(m, r, 1 / 16F, 0.85F));
this.Codes.Add(new Regex("</(s|u|l)>"), (f, m, r) => new ResetFormattingCode(m, r)); this.Codes.Add(new Regex("</(b|i|s|u|l)>"), (f, m, r) => new FontCode(m, r, null));
this.Codes.Add(new Regex("</(b|i)>"), (f, m, r) => new FontCode(m, r, null));
// color codes // color codes
foreach (var c in typeof(Color).GetProperties()) { foreach (var c in typeof(Color).GetProperties()) {

View file

@ -29,15 +29,15 @@ namespace MLEM.Formatting {
/// </summary> /// </summary>
public readonly string Substring; public readonly string Substring;
/// <summary> /// <summary>
/// The string that is displayed by this token. If the tokenized string has been <see cref="TokenizedString.Split"/> or <see cref="TokenizedString.Truncate"/> has been used, this string will contain the newline characters. /// The string that is displayed by this token. If the tokenized string has been split, this string will contain the newline characters.
/// </summary> /// </summary>
public string DisplayString => this.ModifiedSubstring ?? this.Substring; public string DisplayString => this.SplitSubstring ?? this.Substring;
/// <summary> /// <summary>
/// The substring that this token contains, without the formatting codes removed. /// The substring that this token contains, without the formatting codes removed.
/// </summary> /// </summary>
public readonly string RawSubstring; public readonly string RawSubstring;
internal RectangleF[] Area; internal RectangleF[] Area;
internal string ModifiedSubstring; internal string SplitSubstring;
internal Token(Code[] appliedCodes, int index, int rawIndex, string substring, string rawSubstring) { internal Token(Code[] appliedCodes, int index, int rawIndex, string substring, string rawSubstring) {
this.AppliedCodes = appliedCodes; this.AppliedCodes = appliedCodes;

View file

@ -24,9 +24,9 @@ namespace MLEM.Formatting {
public readonly string String; public readonly string String;
/// <summary> /// <summary>
/// The string that is actually displayed by this tokenized string. /// The string that is actually displayed by this tokenized string.
/// If this string has been <see cref="Split"/> or <see cref="Truncate"/> has been used, this string will contain the newline characters. /// If this string has been <see cref="Split"/>, this string will contain the newline characters.
/// </summary> /// </summary>
public string DisplayString => this.modifiedString ?? this.String; public string DisplayString => this.splitString ?? this.String;
/// <summary> /// <summary>
/// The tokens that this tokenized string contains. /// The tokens that this tokenized string contains.
/// </summary> /// </summary>
@ -36,7 +36,7 @@ namespace MLEM.Formatting {
/// Note that, to get a formatting code for a certain token, use <see cref="Token.AppliedCodes"/> /// Note that, to get a formatting code for a certain token, use <see cref="Token.AppliedCodes"/>
/// </summary> /// </summary>
public readonly Code[] AllCodes; public readonly Code[] AllCodes;
private string modifiedString; private string splitString;
internal TokenizedString(GenericFont font, string rawString, string strg, Token[] tokens) { internal TokenizedString(GenericFont font, string rawString, string strg, Token[] tokens) {
this.RawString = rawString; this.RawString = rawString;
@ -49,30 +49,44 @@ namespace MLEM.Formatting {
/// <summary> /// <summary>
/// Splits this tokenized string, inserting newline characters if the width of the string is bigger than the maximum width. /// Splits this tokenized string, inserting newline characters if the width of the string is bigger than the maximum width.
/// Note that a tokenized string can be re-split without losing any of its actual data, as this operation merely modifies the <see cref="DisplayString"/>.
/// <seealso cref="GenericFont.SplitString"/> /// <seealso cref="GenericFont.SplitString"/>
/// </summary> /// </summary>
/// <param name="font">The font to use for width calculations</param> /// <param name="font">The font to use for width calculations</param>
/// <param name="width">The maximum width, in display pixels based on the font and scale</param> /// <param name="width">The maximum width</param>
/// <param name="scale">The scale to use for width measurements</param> /// <param name="scale">The scale to use fr width calculations</param>
public void Split(GenericFont font, float width, float scale) { public void Split(GenericFont font, float width, float scale) {
// a split string has the same character count as the input string but with newline characters added // a split string has the same character count as the input string
this.modifiedString = font.SplitString(this.String, width, scale); // but with newline characters added
this.StoreModifiedSubstrings(font); this.splitString = font.SplitString(this.String, width, scale);
} // skip splitting logic for unformatted text
if (this.Tokens.Length == 1) {
this.Tokens[0].SplitSubstring = this.splitString;
return;
}
/// <summary> // this is basically a substring function that ignores newlines for indexing
/// Truncates this tokenized string, removing any additional characters that exceed the length from the displayed string. var index = 0;
/// Note that a tokenized string can be re-truncated without losing any of its actual data, as this operation merely modifies the <see cref="DisplayString"/>. var currToken = 0;
/// <seealso cref="GenericFont.TruncateString"/> var splitIndex = 0;
/// </summary> var ret = new StringBuilder();
/// <param name="font">The font to use for width calculations</param> while (splitIndex < this.splitString.Length) {
/// <param name="width">The maximum width, in display pixels based on the font and scale</param> var token = this.Tokens[currToken];
/// <param name="scale">The scale to use for width measurements</param> if (token.Substring.Length > 0) {
/// <param name="ellipsis">The characters to add to the end of the string if it is too long</param> ret.Append(this.splitString[splitIndex]);
public void Truncate(GenericFont font, float width, float scale, string ellipsis = "") { // if the current char is not an added newline, we simulate length increase
this.modifiedString = font.TruncateString(this.String, width, scale, false, ellipsis); if (this.splitString[splitIndex] != '\n' || this.String[index] == '\n')
this.StoreModifiedSubstrings(font); index++;
splitIndex++;
}
// move on to the next token if we reached its end
if (index >= token.Index + token.Substring.Length) {
token.SplitSubstring = ret.ToString();
ret.Clear();
currToken++;
}
}
this.CalculateTokenAreas(font);
} }
/// <inheritdoc cref="GenericFont.MeasureString(string)"/> /// <inheritdoc cref="GenericFont.MeasureString(string)"/>
@ -123,43 +137,6 @@ namespace MLEM.Formatting {
} }
} }
private void StoreModifiedSubstrings(GenericFont font) {
// skip substring logic for unformatted text
if (this.Tokens.Length == 1) {
this.Tokens[0].ModifiedSubstring = this.modifiedString;
return;
}
// this is basically a substring function that ignores added newlines for indexing
var index = 0;
var currToken = 0;
var splitIndex = 0;
var ret = new StringBuilder();
while (splitIndex < this.modifiedString.Length) {
var token = this.Tokens[currToken];
if (token.Substring.Length > 0) {
ret.Append(this.modifiedString[splitIndex]);
// if the current char is not an added newline, we simulate length increase
if (this.modifiedString[splitIndex] != '\n' || this.String[index] == '\n')
index++;
splitIndex++;
}
// move on to the next token if we reached its end
if (index >= token.Index + token.Substring.Length) {
token.ModifiedSubstring = ret.ToString();
ret.Clear();
currToken++;
}
}
// set additional token contents beyond our string in case we truncated
if (ret.Length > 0)
this.Tokens[currToken - 1].ModifiedSubstring += ret.ToString();
while (currToken < this.Tokens.Length)
this.Tokens[currToken++].ModifiedSubstring = string.Empty;
this.CalculateTokenAreas(font);
}
private void CalculateTokenAreas(GenericFont font) { private void CalculateTokenAreas(GenericFont font) {
var innerOffset = new Vector2(); var innerOffset = new Vector2();
foreach (var token in this.Tokens) { foreach (var token in this.Tokens) {