diff --git a/src/HandyControl.sln b/src/HandyControl.sln
index 1154962f..5040fb3e 100644
--- a/src/HandyControl.sln
+++ b/src/HandyControl.sln
@@ -34,7 +34,9 @@ Global
Shared\HandyControl_Shared\HandyControl_Shared.projitems*{32204503-2ef0-4681-ae13-aa1feb6c658a}*SharedItemsImports = 4
Shared\HandyControlDemo_Shared\HandyControlDemo_Shared.projitems*{9a7b52e6-94bb-4e7e-bb6a-7cf6761b79a7}*SharedItemsImports = 4
Shared\HandyControl_Shared\HandyControl_Shared.projitems*{aac11083-faca-405d-9197-5c1212d65656}*SharedItemsImports = 13
+ Shared\HandyControl_Shared\HandyControl_Shared.projitems*{be4a567d-b6e0-413e-8f64-e1a53b4f9366}*SharedItemsImports = 5
Shared\HandyControlDemo_Shared\HandyControlDemo_Shared.projitems*{c4694269-c9b8-45d5-87f8-d0088c532510}*SharedItemsImports = 13
+ Shared\HandyControlDemo_Shared\HandyControlDemo_Shared.projitems*{d7107690-8592-4f9f-9379-9b82c1c15d2a}*SharedItemsImports = 5
Shared\HandyControlDemo_Shared\HandyControlDemo_Shared.projitems*{d8ae88f8-c36b-4d10-a7f9-22ffcfba5231}*SharedItemsImports = 4
Shared\HandyControl_Shared\HandyControl_Shared.projitems*{dc966e3d-bcff-4652-98cf-070e5494749a}*SharedItemsImports = 4
EndGlobalSection
diff --git a/src/Shared/HandyControl_Shared/Controls/Text/OutlineText.cs b/src/Shared/HandyControl_Shared/Controls/Text/OutlineText.cs
index 038480de..abc6a971 100644
--- a/src/Shared/HandyControl_Shared/Controls/Text/OutlineText.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Text/OutlineText.cs
@@ -155,24 +155,31 @@ namespace HandyControl.Controls
protected override void OnRender(DrawingContext drawingContext)
{
- EnsureGeometry();
-
- drawingContext.DrawGeometry(Fill, null, _textGeometry);
-
- if (StrokePosition == StrokePosition.Outside)
+ if (StrokeThickness > 0)
{
- drawingContext.PushClip(_clipGeometry);
+ EnsureGeometry();
+
+ drawingContext.DrawGeometry(Fill, null, _textGeometry);
+
+ if (StrokePosition == StrokePosition.Outside)
+ {
+ drawingContext.PushClip(_clipGeometry);
+ }
+ else if (StrokePosition == StrokePosition.Inside)
+ {
+ drawingContext.PushClip(_textGeometry);
+ }
+
+ drawingContext.DrawGeometry(null, _pen, _textGeometry);
+
+ if (StrokePosition == StrokePosition.Outside || StrokePosition == StrokePosition.Inside)
+ {
+ drawingContext.Pop();
+ }
}
- else if (StrokePosition == StrokePosition.Inside)
+ else
{
- drawingContext.PushClip(_textGeometry);
- }
-
- drawingContext.DrawGeometry(null, _pen, _textGeometry);
-
- if (StrokePosition == StrokePosition.Outside || StrokePosition == StrokePosition.Inside)
- {
- drawingContext.Pop();
+ drawingContext.DrawText(_formattedText, new Point());
}
}
diff --git a/src/Shared/HandyControl_Shared/Controls/Text/SimpleText.cs b/src/Shared/HandyControl_Shared/Controls/Text/SimpleText.cs
new file mode 100644
index 00000000..f8f873ba
--- /dev/null
+++ b/src/Shared/HandyControl_Shared/Controls/Text/SimpleText.cs
@@ -0,0 +1,248 @@
+using System;
+using System.ComponentModel;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Documents;
+using System.Windows.Media;
+using HandyControl.Data;
+
+namespace HandyControl.Controls
+{
+ public class SimpleText : FrameworkElement
+ {
+ private Pen _pen;
+
+ private FormattedText _formattedText;
+
+ static SimpleText()
+ {
+ SnapsToDevicePixelsProperty.OverrideMetadata(typeof(SimpleText), new FrameworkPropertyMetadata(ValueBoxes.TrueBox));
+ UseLayoutRoundingProperty.OverrideMetadata(typeof(SimpleText), new FrameworkPropertyMetadata(ValueBoxes.TrueBox));
+ }
+
+ public static readonly DependencyProperty StrokePositionProperty = DependencyProperty.Register(
+ "StrokePosition", typeof(StrokePosition), typeof(SimpleText), new PropertyMetadata(default(StrokePosition)));
+
+ public StrokePosition StrokePosition
+ {
+ get => (StrokePosition)GetValue(StrokePositionProperty);
+ set => SetValue(StrokePositionProperty, value);
+ }
+
+ public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
+ "Text", typeof(string), typeof(SimpleText), new FrameworkPropertyMetadata(
+ string.Empty,
+ FrameworkPropertyMetadataOptions.AffectsMeasure |
+ FrameworkPropertyMetadataOptions.AffectsRender, OnFormattedTextInvalidated));
+
+ public string Text
+ {
+ get => (string)GetValue(TextProperty);
+ set => SetValue(TextProperty, value);
+ }
+
+ public static readonly DependencyProperty TextAlignmentProperty = DependencyProperty.Register(
+ "TextAlignment", typeof(TextAlignment), typeof(SimpleText),
+ new PropertyMetadata(default(TextAlignment), OnFormattedTextUpdated));
+
+ public TextAlignment TextAlignment
+ {
+ get => (TextAlignment)GetValue(TextAlignmentProperty);
+ set => SetValue(TextAlignmentProperty, value);
+ }
+
+ public static readonly DependencyProperty TextTrimmingProperty = DependencyProperty.Register(
+ "TextTrimming", typeof(TextTrimming), typeof(SimpleText),
+ new PropertyMetadata(default(TextTrimming), OnFormattedTextInvalidated));
+
+ public TextTrimming TextTrimming
+ {
+ get => (TextTrimming)GetValue(TextTrimmingProperty);
+ set => SetValue(TextTrimmingProperty, value);
+ }
+
+ public static readonly DependencyProperty TextWrappingProperty = DependencyProperty.Register(
+ "TextWrapping", typeof(TextWrapping), typeof(SimpleText),
+ new PropertyMetadata(TextWrapping.NoWrap, OnFormattedTextInvalidated));
+
+ public TextWrapping TextWrapping
+ {
+ get => (TextWrapping)GetValue(TextWrappingProperty);
+ set => SetValue(TextWrappingProperty, value);
+ }
+
+ public static readonly DependencyProperty FillProperty = DependencyProperty.Register(
+ "Fill", typeof(Brush), typeof(SimpleText), new PropertyMetadata(Brushes.Black, OnFormattedTextUpdated));
+
+ public Brush Fill
+ {
+ get => (Brush)GetValue(FillProperty);
+ set => SetValue(FillProperty, value);
+ }
+
+ public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
+ "Stroke", typeof(Brush), typeof(SimpleText), new PropertyMetadata(Brushes.Black, OnFormattedTextUpdated));
+
+ public Brush Stroke
+ {
+ get => (Brush)GetValue(StrokeProperty);
+ set => SetValue(StrokeProperty, value);
+ }
+
+ public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
+ "StrokeThickness", typeof(double), typeof(SimpleText), new PropertyMetadata(ValueBoxes.Double0Box, OnFormattedTextUpdated));
+
+ public double StrokeThickness
+ {
+ get => (double)GetValue(StrokeThicknessProperty);
+ set => SetValue(StrokeThicknessProperty, value);
+ }
+
+ public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(
+ typeof(SimpleText),
+ new FrameworkPropertyMetadata(OnFormattedTextUpdated));
+
+ public FontFamily FontFamily
+ {
+ get => (FontFamily)GetValue(FontFamilyProperty);
+ set => SetValue(FontFamilyProperty, value);
+ }
+
+ public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
+ typeof(SimpleText),
+ new FrameworkPropertyMetadata(OnFormattedTextUpdated));
+
+ [TypeConverter(typeof(FontSizeConverter))]
+ public double FontSize
+ {
+ get => (double)GetValue(FontSizeProperty);
+ set => SetValue(FontSizeProperty, value);
+ }
+
+ public static readonly DependencyProperty FontStretchProperty = TextElement.FontStretchProperty.AddOwner(
+ typeof(SimpleText),
+ new FrameworkPropertyMetadata(OnFormattedTextUpdated));
+
+ public FontStretch FontStretch
+ {
+ get => (FontStretch)GetValue(FontStretchProperty);
+ set => SetValue(FontStretchProperty, value);
+ }
+
+ public static readonly DependencyProperty FontStyleProperty = TextElement.FontStyleProperty.AddOwner(
+ typeof(SimpleText),
+ new FrameworkPropertyMetadata(OnFormattedTextUpdated));
+
+ public FontStyle FontStyle
+ {
+ get => (FontStyle)GetValue(FontStyleProperty);
+ set => SetValue(FontStyleProperty, value);
+ }
+
+ public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner(
+ typeof(SimpleText),
+ new FrameworkPropertyMetadata(OnFormattedTextUpdated));
+
+ public FontWeight FontWeight
+ {
+ get => (FontWeight)GetValue(FontWeightProperty);
+ set => SetValue(FontWeightProperty, value);
+ }
+
+ protected override void OnRender(DrawingContext drawingContext) => drawingContext.DrawText(_formattedText, new Point());
+
+ private void UpdatePen()
+ {
+ _pen = new Pen(Stroke, StrokeThickness);
+
+ if (StrokePosition == StrokePosition.Outside || StrokePosition == StrokePosition.Inside)
+ {
+ _pen.Thickness = StrokeThickness * 2;
+ }
+ }
+
+ private void EnsureFormattedText()
+ {
+ if (_formattedText != null || Text == null)
+ {
+ return;
+ }
+
+#if netle45
+ _formattedText = new FormattedText(
+ Text,
+ CultureInfo.CurrentUICulture,
+ FlowDirection,
+ new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
+ FontSize, Fill);
+#else
+ var source = PresentationSource.FromVisual(this);
+ var dpi = 1.0;
+ if (source?.CompositionTarget != null)
+ {
+ dpi = 96.0 * source.CompositionTarget.TransformToDevice.M11 / 96.0;
+ }
+ _formattedText = new FormattedText(
+ Text,
+ CultureInfo.CurrentUICulture,
+ FlowDirection,
+ new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
+ FontSize, Fill, dpi);
+#endif
+
+ UpdateFormattedText();
+ }
+
+ private void UpdateFormattedText()
+ {
+ if (_formattedText == null)
+ {
+ return;
+ }
+
+ _formattedText.MaxLineCount = TextWrapping == TextWrapping.NoWrap ? 1 : int.MaxValue;
+ _formattedText.TextAlignment = TextAlignment;
+ _formattedText.Trimming = TextTrimming;
+
+ _formattedText.SetFontSize(FontSize);
+ _formattedText.SetFontStyle(FontStyle);
+ _formattedText.SetFontWeight(FontWeight);
+ _formattedText.SetFontFamily(FontFamily);
+ _formattedText.SetFontStretch(FontStretch);
+ }
+
+ private static void OnFormattedTextUpdated(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var outlinedTextBlock = (SimpleText)d;
+ outlinedTextBlock.UpdateFormattedText();
+
+ outlinedTextBlock.InvalidateMeasure();
+ outlinedTextBlock.InvalidateVisual();
+ }
+
+ private static void OnFormattedTextInvalidated(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var outlinedTextBlock = (SimpleText)d;
+ outlinedTextBlock._formattedText = null;
+
+ outlinedTextBlock.InvalidateMeasure();
+ outlinedTextBlock.InvalidateVisual();
+ }
+
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ EnsureFormattedText();
+
+ // constrain the formatted text according to the available size
+ // the Math.Min call is important - without this constraint (which seems arbitrary, but is the maximum allowable text width), things blow up when availableSize is infinite in both directions
+ // the Math.Max call is to ensure we don't hit zero, which will cause MaxTextHeight to throw
+ _formattedText.MaxTextWidth = Math.Min(3579139, availableSize.Width);
+ _formattedText.MaxTextHeight = Math.Max(0.0001d, availableSize.Height);
+
+ UpdatePen();
+
+ // return the desired size
+ return new Size(_formattedText.Width, _formattedText.Height);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
index a78fba08..1ec85042 100644
--- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
+++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems
@@ -44,6 +44,7 @@
+