139 lines
4.0 KiB
C#
139 lines
4.0 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Globalization;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Media;
|
|
|
|
namespace OperationControl.Controls
|
|
{
|
|
public class AutoFitTextBlock : TextBlock
|
|
{
|
|
public static readonly DependencyProperty MinFontSizeProperty =
|
|
DependencyProperty.Register(
|
|
nameof(MinFontSize),
|
|
typeof(double),
|
|
typeof(AutoFitTextBlock),
|
|
new PropertyMetadata(10.0, OnAutoFitPropertyChanged));
|
|
|
|
public static readonly DependencyProperty MaxLinesProperty =
|
|
DependencyProperty.Register(
|
|
nameof(MaxLines),
|
|
typeof(int),
|
|
typeof(AutoFitTextBlock),
|
|
new PropertyMetadata(2, OnAutoFitPropertyChanged));
|
|
|
|
private double _baseFontSize = 14;
|
|
private bool _isAdjusting;
|
|
|
|
public double MinFontSize
|
|
{
|
|
get => (double)GetValue(MinFontSizeProperty);
|
|
set => SetValue(MinFontSizeProperty, value);
|
|
}
|
|
|
|
public int MaxLines
|
|
{
|
|
get => (int)GetValue(MaxLinesProperty);
|
|
set => SetValue(MaxLinesProperty, value);
|
|
}
|
|
|
|
public AutoFitTextBlock()
|
|
{
|
|
Loaded += AutoFitTextBlock_Loaded;
|
|
SizeChanged += (_, _) => AdjustFontSize();
|
|
}
|
|
|
|
private void AutoFitTextBlock_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
_baseFontSize = FontSize;
|
|
|
|
WatchProperty(TextProperty);
|
|
WatchProperty(FontSizeProperty);
|
|
WatchProperty(FontFamilyProperty);
|
|
WatchProperty(FontStyleProperty);
|
|
WatchProperty(FontWeightProperty);
|
|
WatchProperty(FontStretchProperty);
|
|
WatchProperty(TextWrappingProperty);
|
|
|
|
AdjustFontSize();
|
|
}
|
|
|
|
private void WatchProperty(DependencyProperty dp)
|
|
{
|
|
var descriptor = DependencyPropertyDescriptor.FromProperty(dp, typeof(AutoFitTextBlock));
|
|
descriptor?.AddValueChanged(this, (_, _) =>
|
|
{
|
|
if (!_isAdjusting && dp == FontSizeProperty)
|
|
_baseFontSize = FontSize;
|
|
|
|
AdjustFontSize();
|
|
});
|
|
}
|
|
|
|
private static void OnAutoFitPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
{
|
|
if (d is AutoFitTextBlock tb)
|
|
tb.AdjustFontSize();
|
|
}
|
|
|
|
private void AdjustFontSize()
|
|
{
|
|
if (_isAdjusting || !IsLoaded)
|
|
return;
|
|
|
|
if (ActualWidth <= 0 || string.IsNullOrWhiteSpace(Text))
|
|
return;
|
|
|
|
_isAdjusting = true;
|
|
|
|
try
|
|
{
|
|
double startFont = _baseFontSize;
|
|
double minFont = MinFontSize;
|
|
|
|
FontSize = startFont;
|
|
|
|
while (FontSize > minFont)
|
|
{
|
|
if (Fits(FontSize))
|
|
return;
|
|
|
|
FontSize -= 0.5;
|
|
}
|
|
|
|
FontSize = minFont;
|
|
}
|
|
finally
|
|
{
|
|
_isAdjusting = false;
|
|
}
|
|
}
|
|
|
|
private bool Fits(double fontSize)
|
|
{
|
|
double pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip;
|
|
|
|
var formattedText = new FormattedText(
|
|
Text ?? string.Empty,
|
|
CultureInfo.CurrentUICulture,
|
|
FlowDirection,
|
|
new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
|
|
fontSize,
|
|
Foreground,
|
|
pixelsPerDip)
|
|
{
|
|
MaxTextWidth = Math.Max(0, ActualWidth),
|
|
Trimming = TextTrimming.None
|
|
};
|
|
|
|
if (TextWrapping == TextWrapping.Wrap)
|
|
formattedText.MaxLineCount = MaxLines;
|
|
|
|
double lineHeight = fontSize * 1.25;
|
|
double maxAllowedHeight = lineHeight * MaxLines;
|
|
|
|
return formattedText.Height <= maxAllowedHeight + 1;
|
|
}
|
|
}
|
|
} |