Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 52 additions & 3 deletions maui/src/Button/SfButton.Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -540,15 +540,20 @@ double CalculateWidth(double widthConstraint)
{
if (widthConstraint == double.PositiveInfinity || widthConstraint < 0 || WidthRequest < 0)
{
double buttonContentWidth = 0;
if (ShowIcon && ImageSource != null)
{
return ImageAlignment == Alignment.Top || ImageAlignment == Alignment.Bottom
buttonContentWidth = ImageAlignment == Alignment.Top || ImageAlignment == Alignment.Bottom
? Math.Max(ImageSize, TextSize.Width) + Padding.Left + Padding.Right + StrokeThickness + (_leftPadding * 2) + (_rightPadding * 2)
: ImageSize + TextSize.Width + StrokeThickness + Padding.Left + Padding.Right + (_leftPadding * 2) + (_rightPadding * 2);
}
else
{
return TextSize.Width + Padding.Left + Padding.Right + StrokeThickness + (_leftPadding * 2) + (_rightPadding * 2);
buttonContentWidth = TextSize.Width + Padding.Left + Padding.Right + StrokeThickness + (_leftPadding * 2) + (_rightPadding * 2);
}
if (buttonContentWidth <= widthConstraint)
{
return buttonContentWidth;
}
}
return widthConstraint;
Expand All @@ -564,6 +569,7 @@ double CalculateHeight(double heightConstraint, double width)
{
if (heightConstraint == double.PositiveInfinity || heightConstraint < 0 || VerticalOptions != LayoutOptions.Fill)
{
width = CalculateAvailableTextWidth(width);
if (LineBreakMode == LineBreakMode.WordWrap || LineBreakMode == LineBreakMode.CharacterWrap)
{
_numberOfLines = StringExtensions.GetLinesCount(Text, (float)width, this, LineBreakMode, out _);
Expand All @@ -587,6 +593,46 @@ double CalculateHeight(double heightConstraint, double width)
return heightConstraint;
}

/// <summary>
/// Calculates the available width for the text area within the button.
/// </summary>
/// <param name="width"></param>
/// <returns></returns>
double CalculateAvailableTextWidth(double width)
{
if (ShowIcon && ImageSource != null)
{
if (ImageAlignment == Alignment.Start || ImageAlignment == Alignment.Left)
{
width = (ImageAlignment == Alignment.Start && _isRightToLeft) ? Math.Abs((float)(width - _textRectF.X - ImageSize - (_leftIconPadding * 2) - _textAreaPadding - (StrokeThickness / 2) - Padding.Right))
: Math.Abs((float)(width - _textRectF.X - (StrokeThickness / 2) - _textAreaPadding - Padding.Right));

}
else if (ImageAlignment == Alignment.End || ImageAlignment == Alignment.Right)
{
width = (ImageAlignment == Alignment.End && _isRightToLeft) ? Math.Abs((float)(width - _textRectF.X - (StrokeThickness / 2) - _textAreaPadding - Padding.Right))
: Math.Abs((float)(width - _textRectF.X - ImageSize - _leftIconPadding - _leftIconPadding - _textAreaPadding - (StrokeThickness / 2) - Padding.Right));
}
else if (ImageAlignment == Alignment.Top)
{
width = Math.Abs((float)(width - _textAreaPadding - Padding.Left - Padding.Right - _textAreaPadding - (StrokeThickness / 2) - (StrokeThickness / 2)));
}
else if (ImageAlignment == Alignment.Bottom)
{
width = Math.Abs((float)(width - _textAreaPadding - Padding.Left - Padding.Right - _textAreaPadding - (StrokeThickness / 2) - (StrokeThickness / 2)));
}
else
{
width = Math.Abs((float)(width - _textRectF.X - (StrokeThickness / 2) - _textAreaPadding - Padding.Right));
}
}
else
{
width = Math.Abs((float)(width - _textAreaPadding - Padding.Left - Padding.Right - _textAreaPadding - StrokeThickness));
}
return width;
}

/// <summary>
/// Measures the size of child elements if present and returns the size.
/// </summary>
Expand Down Expand Up @@ -735,7 +781,10 @@ internal override void DrawText(ICanvas canvas, RectF dirtyRect)
canvas.SaveState();
float availableWidth = _textRectF.Width;
#if ANDROID
availableWidth-=AndroidTextMargin;
if (LineBreakMode != LineBreakMode.WordWrap)
{
availableWidth -= AndroidTextMargin;
}
#endif
var trimmedText = _isFontIconText ? Text : StringExtensions.GetTextBasedOnLineBreakMode(ApplyTextTransform(Text), this, availableWidth, _textRectF.Height, LineBreakMode);
if (_textRectF.Width > 0 && _textRectF.Height > 0)
Expand Down
29 changes: 21 additions & 8 deletions maui/src/Core/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ public static Size Measure(this string text, double availableWidth, ITextElement
/// </summary>
/// Note: It can be used from chart and sunbrust chart datalabels implement.
public static string TrimTextToFit(this string inputText, ITextElement textElement, double availableWidth)
{
while (inputText.Measure(textElement).Width > availableWidth && inputText.Length > 0)
{
inputText = inputText.Substring(0, inputText.Length - 1);
}
return inputText;
}
{
string trimmedText = inputText.TrimEnd();
while (trimmedText.Measure(textElement).Width >= availableWidth && trimmedText.Length > 0)
{
trimmedText = trimmedText.Substring(0, trimmedText.Length - 1);
trimmedText = trimmedText.TrimEnd();
}
return trimmedText;
}

/// <summary>
/// This method is utilized to get the total number of lines count from the text to fit within the available width.
Expand Down Expand Up @@ -171,13 +173,24 @@ public static string GetTextBasedOnLineBreakMode(this string text, ITextElement
var leftTrimmedTextSize = leftTrimmedText.Measure((ITextElement)textElement);
int leftLength = 0;

while (leftTrimmedTextSize.Width > charsToKeep && leftTrimmedText.Length > 0)
while (leftTrimmedTextSize.Width >= charsToKeep && leftTrimmedText.Length > 0)
{
leftTrimmedText = leftTrimmedText.Substring(0, leftTrimmedText.Length - 1);
leftTrimmedTextSize = leftTrimmedText.Measure((ITextElement)textElement);
leftLength++;
}
string rightText = text.Substring(leftLength);

leftTrimmedText = leftTrimmedText.TrimEnd();
rightText = rightText.TrimStart();

var rightTrimmedTextSize = rightText.Measure((ITextElement)textElement);
while (rightTrimmedTextSize.Width >= charsToKeep && rightText.Length > 0)
{
leftLength++;
rightText = text.Substring(leftLength).TrimStart();
rightTrimmedTextSize = rightText.Measure((ITextElement)textElement);
}
string trimmedText = leftTrimmedText + "..." + rightText;
return trimmedText;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,32 @@ public void CalculateWidth_ShouldReturnWidth(double width, double expectedValue)
Assert.Equal(expectedValue, actualValue);
}

[Theory]
[InlineData(150, 142, "SampleImage1.png", Alignment.Left)]
[InlineData(150, 108, "SampleImage1.png", Alignment.Right)]
[InlineData(180, 164, "SampleImage1.png", Alignment.Top)]
[InlineData(250, 234, "SampleImage1.png", Alignment.Bottom)]
[InlineData(200, 184, "SampleImage1.png", null)]
public void CalculateAvailableTextWidth_ShouldReturnExpectedWidth(double width, double expectedValue, string imagePath, Alignment? alignment = null)
{
// Arrange
var button = new SfButton();
button.ImageSource = ImageSource.FromFile(imagePath);

if (alignment != null)
{
button.ShowIcon = true;
button.ImageAlignment = (Alignment)alignment;
}

// Set up as needed
button.Padding = new Thickness(4, 4, 4, 4);

var actualValue = InvokePrivateMethod(button, "CalculateAvailableTextWidth", width);

Assert.Equal(expectedValue, actualValue);
}

[Theory]
[InlineData(true, false, false, false, "#000000")]
[InlineData(true, true, false, false, "#FF0000")]
Expand Down