Created
August 2, 2017 19:59
-
-
Save kellyelton/9f3634e428cfb26d84dc8b2f680d5840 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Globalization; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Data; | |
using System.Windows.Documents; | |
using System.Windows.Media; | |
using System.Xml; | |
using Octgn.DataNew.Entities; | |
using System.IO; | |
using System.Windows.Media.Imaging; | |
using System.Xml.Linq; | |
namespace Octgn.Controls | |
{ | |
public class RichTextBlock : TextBlock | |
{ | |
public static DependencyProperty InlineProperty; | |
static RichTextBlock() | |
{ | |
//OverrideMetadata call tells the system that this element wants to provide a style that is different than in base class | |
DefaultStyleKeyProperty.OverrideMetadata(typeof(RichTextBlock), new FrameworkPropertyMetadata( | |
typeof(RichTextBlock))); | |
InlineProperty = DependencyProperty.Register("RichText", typeof(List<Inline>), typeof(RichTextBlock), | |
new PropertyMetadata(null, new PropertyChangedCallback(OnInlineChanged))); | |
} | |
public List<Inline> RichText | |
{ | |
get { return (List<Inline>)GetValue(InlineProperty); } | |
set { SetValue(InlineProperty, value); } | |
} | |
public static void OnInlineChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) | |
{ | |
if (e.NewValue == e.OldValue) | |
return; | |
RichTextBlock r = sender as RichTextBlock ?? throw new InvalidOperationException($"{nameof(sender)} of type {sender?.GetType().FullName} was not expected."); | |
List<Inline> i = e.NewValue as List<Inline> ?? throw new InvalidOperationException($"{nameof(e.NewValue)} of type {e.NewValue?.GetType().FullName} was not expected.");; | |
r.Inlines.Clear(); | |
foreach (Inline inline in i) | |
{ | |
r.Inlines.Add(inline); | |
} | |
} | |
} | |
public class StyledTextConverter : IValueConverter | |
{ | |
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | |
{ | |
var propval = value as PropertyDefValue; | |
if (propval == null) throw new ArgumentInvalidException(nameof(value)); | |
if (!(propval.Value is XElement)) throw new InvalidOperationException($"{nameof(PropertyDefValue)}.{nameof(Value)} is the wrong type"); | |
Span span = new Span(); | |
InternalProcess(span, (XElement)propval.Value, parameter as Game); | |
return span.Inlines.ToList(); | |
} | |
public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture) | |
{ | |
throw new NotImplementedException(); | |
} | |
private static void InternalProcess(Span span, XElement xmlNode, Game game) | |
{ | |
foreach (XNode child in xmlNode.Nodes()) | |
{ | |
if (child is XText text) | |
{ | |
span.Inlines.Add(new Run(text.Value)); | |
} | |
else if (child is XElement element) | |
{ | |
switch (element.Name.ToString().ToUpper()) | |
{ | |
case "B": | |
case "BOLD": | |
{ | |
Span boldSpan = new Span(); | |
InternalProcess(boldSpan, element, game); | |
Bold bold = new Bold(boldSpan); | |
span.Inlines.Add(bold); | |
break; | |
} | |
case "I": | |
case "ITALIC": | |
{ | |
Span italicSpan = new Span(); | |
InternalProcess(italicSpan, element, game); | |
Italic italic = new Italic(italicSpan); | |
span.Inlines.Add(italic); | |
break; | |
} | |
case "U": | |
case "UNDERLINE": | |
{ | |
Span underlineSpan = new Span(); | |
InternalProcess(underlineSpan, element, game); | |
Underline underline = new Underline(underlineSpan); | |
span.Inlines.Add(underline); | |
break; | |
} | |
case "C": | |
case "COLOR": | |
{ | |
Span colorSpan = new Span(); | |
InternalProcess(colorSpan, element, game); | |
try | |
{ | |
colorSpan.Foreground = new BrushConverter().ConvertFromString(element.Attribute("value").Value) as SolidColorBrush; | |
} | |
catch (Exception ex) { //TODO: specify the exception we are actually expecting to get here | |
/* this was the easiest way to make sure that the color string was valid */ | |
Log.Warn("Error parsing Foreground", ex); | |
} | |
span.Inlines.Add(colorSpan); | |
break; | |
} | |
case "S": | |
case "SYMBOL": | |
{ | |
var symbolId = element.Attribute("value").Value; | |
Symbol symbol = game.Symbols.FirstOrDefault(x => x.Id == symbolId); | |
if (symbol == null) throw new InvalidOperationException($"Could not find symbol {symbolId}"); | |
var image = new Image | |
{ | |
Margin = new Thickness(0,0,0,-2), | |
Height = span.FontSize + 2, | |
Stretch = Stretch.Uniform, | |
Source = new BitmapImage(new Uri(symbol.Source)), | |
ToolTip = symbol.Name | |
}; | |
var symbolSpan = new InlineUIContainer(); | |
symbolSpan.Child = image; | |
span.Inlines.Add(symbolSpan); | |
break; | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment