From 12ac2cbfb8e7291838d5abf9c338ca1fa85135d3 Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Tue, 28 Feb 2017 16:30:56 +0200 Subject: [PATCH 01/12] feat(WPF) Support textDecorationLine on components (#709) --- ChakraCore | 1 + .../ReactNative.Net46.csproj | 1 + .../Views/Text/ReactTextShadowNode.cs | 35 +++++++++++++++++++ .../ReactNative.Shared.projitems | 1 + .../Reflection/EnumHelpers.cs | 32 ++++++++++++++--- .../Views/Text/TextDecorationLine.cs | 28 +++++++++++++++ 6 files changed, 93 insertions(+), 5 deletions(-) create mode 160000 ChakraCore create mode 100644 ReactWindows/ReactNative.Shared/Views/Text/TextDecorationLine.cs diff --git a/ChakraCore b/ChakraCore new file mode 160000 index 00000000000..322442447fc --- /dev/null +++ b/ChakraCore @@ -0,0 +1 @@ +Subproject commit 322442447fc234caf381bcca542b44f686ba5e2b diff --git a/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj b/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj index 9d9aff07740..a641102c2d7 100644 --- a/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj +++ b/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj @@ -107,6 +107,7 @@ $(SolutionDir)\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll True + diff --git a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs index e2559775152..7484241f43c 100644 --- a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs +++ b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs @@ -4,6 +4,7 @@ using ReactNative.UIManager; using ReactNative.UIManager.Annotations; using System; +using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; @@ -26,6 +27,8 @@ public class ReactTextShadowNode : LayoutShadowNode private FontWeight? _fontWeight; private TextAlignment _textAlignment = TextAlignment.Left; + private TextDecorationLine _textDecorationLine = TextDecorationLine.None; + private string _fontFamily; /// @@ -37,6 +40,37 @@ public ReactTextShadowNode() MeasureText(this, node, width, widthMode, height, heightMode); } + /// + /// Sets the TextDecorationLine for the node. + /// + /// The TextDecorationLine value. + [ReactProp(ViewProps.TextDecorationLine)] + public void SetTextDecorationLine(string textDecorationLineValue) + { + var textDecorationLine = EnumHelpers.ParseNullable(textDecorationLineValue) ?? TextDecorationLine.None; + if (_textDecorationLine != textDecorationLine) + { + _textDecorationLine = textDecorationLine; + MarkUpdated(); + } + } + + private IEnumerable GetTextDecorationCollection() + { + switch (_textDecorationLine) + { + case TextDecorationLine.Underline: + return TextDecorations.Underline; + case TextDecorationLine.LineThrough: + return TextDecorations.Strikethrough; + case TextDecorationLine.UnderlineLineThrough: + return TextDecorations.Underline.Concat(TextDecorations.Strikethrough); + case TextDecorationLine.None: + default: + return Enumerable.Empty(); + } + } + /// /// Sets the font size for the node. /// @@ -238,6 +272,7 @@ private void UpdateTextBlockCore(TextBlock textBlock, bool measureOnly) textBlock.FontSize = _fontSize ?? 15; textBlock.FontStyle = _fontStyle ?? new FontStyle(); textBlock.FontWeight = _fontWeight ?? FontWeights.Normal; + textBlock.TextDecorations = new TextDecorationCollection(GetTextDecorationCollection()); if (_fontFamily != null) { diff --git a/ReactWindows/ReactNative.Shared/ReactNative.Shared.projitems b/ReactWindows/ReactNative.Shared/ReactNative.Shared.projitems index 19cd176d235..87cf9fd3f67 100644 --- a/ReactWindows/ReactNative.Shared/ReactNative.Shared.projitems +++ b/ReactWindows/ReactNative.Shared/ReactNative.Shared.projitems @@ -230,6 +230,7 @@ + diff --git a/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs b/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs index a489cb0e7ab..24e7c542177 100644 --- a/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs +++ b/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs @@ -2,6 +2,8 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; using static System.FormattableString; namespace ReactNative.Reflection @@ -15,11 +17,7 @@ public static T Parse(string value) { var lookup = s_enumCache.GetOrAdd( typeof(T), - type => Enum.GetValues(type) - .Cast() - .ToDictionary( - e => Normalize(e.ToString()), - e => e)); + type => EnumToDictionary(type)); var result = default(object); if (!lookup.TryGetValue(Normalize(value), out result)) @@ -41,6 +39,30 @@ public static T Parse(string value) return Parse(value); } + private static Dictionary EnumToDictionary(Type t) + { + Dictionary result = new Dictionary(); + + var names = Enum.GetNames(t); + var values = Enum.GetValues(t); + + for (int i = 0; i < values.Length; ++i) + { + string name = names[i]; + object value = values.GetValue(i); + + result.Add(Normalize(name), value); + + var enumMemberAttribute = t.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true).SingleOrDefault(); + if (enumMemberAttribute != null) + { + result.Add(Normalize(((EnumMemberAttribute)enumMemberAttribute).Value), value); + } + } + + return result; + } + private static string Normalize(string value) { return value.ToLowerInvariant().Replace("-", ""); diff --git a/ReactWindows/ReactNative.Shared/Views/Text/TextDecorationLine.cs b/ReactWindows/ReactNative.Shared/Views/Text/TextDecorationLine.cs new file mode 100644 index 00000000000..94575ed88ce --- /dev/null +++ b/ReactWindows/ReactNative.Shared/Views/Text/TextDecorationLine.cs @@ -0,0 +1,28 @@ +using System.Runtime.Serialization; + +namespace ReactNative.Views.Text +{ + /// + /// TextDecorationLine values. + /// + public enum TextDecorationLine + { + /// + /// Text has no line decoration. + /// + None, + /// + /// Text is Underlined. + /// + Underline, + /// + /// Text is Stroke out. + /// + LineThrough, + /// + /// Text is both Underlined and Stroke out. + /// + [EnumMember(Value = "underline line-through")] + UnderlineLineThrough + } +} From 5de9c8e8877a4fcf836bbc621cfa78389abf44e3 Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Mon, 6 Mar 2017 18:48:20 +0200 Subject: [PATCH 02/12] Underline implementation for UWP --- .../Views/Text/ReactTextViewManager.cs | 84 +++++++++++++++++-- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs index 9d30494b3cd..203de18328d 100644 --- a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs +++ b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs @@ -1,5 +1,7 @@ -using ReactNative.UIManager; +using ReactNative.Reflection; +using ReactNative.UIManager; using ReactNative.UIManager.Annotations; +using System; using System.Linq; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -50,6 +52,76 @@ public void SetSelectable(RichTextBlock view, bool selectable) view.IsTextSelectionEnabled = selectable; } + /// + /// Sets the TextDecorationLine for the node. + /// + /// /// The view. + /// The TextDecorationLine value. + [ReactProp(ViewProps.TextDecorationLine)] + public void SetTextDecorationLine(RichTextBlock view, string textDecorationLineValue) + { + var textDecorationLine = EnumHelpers.ParseNullable(textDecorationLineValue) ?? TextDecorationLine.None; + + if (textDecorationLine != TextDecorationLine.None && textDecorationLine != TextDecorationLine.Underline) + { + throw new NotSupportedException("textDecorationLine = \"Strike-through\" is not implemeted in UWP"); + } + + var firstItemAsUnderline = view.Blocks.OfType().First().Inlines.FirstOrDefault() as Underline; + + switch (textDecorationLine) + { + case TextDecorationLine.None: + { + if (firstItemAsUnderline == null) + break; + + var inlines = GetInlines(view).ToArray(); + var paragraph = view.Blocks.OfType().First(); + paragraph.Inlines.Clear(); + firstItemAsUnderline.Inlines.Clear(); + foreach (Inline i in inlines) + { + paragraph.Inlines.Add(i); + } + break; + } + + case TextDecorationLine.Underline: + { + if (firstItemAsUnderline != null) + break; + + var inlines = GetInlines(view).ToArray(); + var paragraph = view.Blocks.OfType().First(); + paragraph.Inlines.Clear(); + + Underline underline = new Underline(); + foreach (Inline i in inlines) + { + underline.Inlines.Add(i); + } + + paragraph.Inlines.Add(underline); + + break; + } + } + } + + private InlineCollection GetInlines(RichTextBlock textBlock) + { + var inlines = textBlock.Blocks.OfType().First().Inlines; + var firstInnerUnderline = inlines.FirstOrDefault() as Underline; + + if (firstInnerUnderline != null) + { + return firstInnerUnderline.Inlines; + } + + return inlines; + } + /// /// Adds a child at the given index. /// @@ -67,7 +139,7 @@ public override void AddView(RichTextBlock parent, DependencyObject child, int i }; } - parent.Blocks.OfType().First().Inlines.Insert(index, inlineChild); + GetInlines(parent).Insert(index, inlineChild); } /// @@ -87,7 +159,7 @@ public override ReactTextShadowNode CreateShadowNodeInstance() /// The child view. public override DependencyObject GetChildAt(RichTextBlock parent, int index) { - var child = parent.Blocks.OfType().First().Inlines[index]; + var child = GetInlines(parent)[index]; var childInlineContainer = child as InlineUIContainer; if (childInlineContainer != null) { @@ -106,7 +178,7 @@ public override DependencyObject GetChildAt(RichTextBlock parent, int index) /// The number of children. public override int GetChildCount(RichTextBlock parent) { - return parent.Blocks.OfType().First().Inlines.Count; + return GetInlines(parent).Count; } /// @@ -115,7 +187,7 @@ public override int GetChildCount(RichTextBlock parent) /// The view parent. public override void RemoveAllChildren(RichTextBlock parent) { - var inlines = parent.Blocks.OfType().First().Inlines; + var inlines = GetInlines(parent); inlines.Clear(); } @@ -126,7 +198,7 @@ public override void RemoveAllChildren(RichTextBlock parent) /// The index. public override void RemoveChildAt(RichTextBlock parent, int index) { - var inlines = parent.Blocks.OfType().First().Inlines; + var inlines = GetInlines(parent); inlines.RemoveAt(index); } From b4a8fe29209b6864392d89054b8e6822331102d7 Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Mon, 6 Mar 2017 18:57:44 +0200 Subject: [PATCH 03/12] Removed reference to System.Runtime.Serialization --- ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj b/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj index a641102c2d7..9d9aff07740 100644 --- a/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj +++ b/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj @@ -107,7 +107,6 @@ $(SolutionDir)\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll True - From bdc0a983b8a1208c46fbc6f38a74e980299f516b Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Mon, 6 Mar 2017 19:11:26 +0200 Subject: [PATCH 04/12] Styling fixes --- .../Views/Text/ReactTextShadowNode.cs | 27 ++++++++++--------- .../Reflection/EnumHelpers.cs | 2 +- .../Views/Text/ReactTextViewManager.cs | 6 ++--- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs index 7484241f43c..9114b1b68c1 100644 --- a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs +++ b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs @@ -55,19 +55,22 @@ public void SetTextDecorationLine(string textDecorationLineValue) } } - private IEnumerable GetTextDecorationCollection() + private IEnumerable TextDecorationCollection { - switch (_textDecorationLine) + get { - case TextDecorationLine.Underline: - return TextDecorations.Underline; - case TextDecorationLine.LineThrough: - return TextDecorations.Strikethrough; - case TextDecorationLine.UnderlineLineThrough: - return TextDecorations.Underline.Concat(TextDecorations.Strikethrough); - case TextDecorationLine.None: - default: - return Enumerable.Empty(); + switch (_textDecorationLine) + { + case TextDecorationLine.Underline: + return TextDecorations.Underline; + case TextDecorationLine.LineThrough: + return TextDecorations.Strikethrough; + case TextDecorationLine.UnderlineLineThrough: + return TextDecorations.Underline.Concat(TextDecorations.Strikethrough); + case TextDecorationLine.None: + default: + return Enumerable.Empty(); + } } } @@ -272,7 +275,7 @@ private void UpdateTextBlockCore(TextBlock textBlock, bool measureOnly) textBlock.FontSize = _fontSize ?? 15; textBlock.FontStyle = _fontStyle ?? new FontStyle(); textBlock.FontWeight = _fontWeight ?? FontWeights.Normal; - textBlock.TextDecorations = new TextDecorationCollection(GetTextDecorationCollection()); + textBlock.TextDecorations = new TextDecorationCollection(TextDecorationCollection); if (_fontFamily != null) { diff --git a/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs b/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs index 24e7c542177..7798ae6890e 100644 --- a/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs +++ b/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs @@ -41,7 +41,7 @@ public static T Parse(string value) private static Dictionary EnumToDictionary(Type t) { - Dictionary result = new Dictionary(); + var result = new Dictionary(); var names = Enum.GetNames(t); var values = Enum.GetValues(t); diff --git a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs index 203de18328d..1b6024ba007 100644 --- a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs +++ b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs @@ -80,7 +80,7 @@ public void SetTextDecorationLine(RichTextBlock view, string textDecorationLineV var paragraph = view.Blocks.OfType().First(); paragraph.Inlines.Clear(); firstItemAsUnderline.Inlines.Clear(); - foreach (Inline i in inlines) + foreach (var i in inlines) { paragraph.Inlines.Add(i); } @@ -96,8 +96,8 @@ public void SetTextDecorationLine(RichTextBlock view, string textDecorationLineV var paragraph = view.Blocks.OfType().First(); paragraph.Inlines.Clear(); - Underline underline = new Underline(); - foreach (Inline i in inlines) + var underline = new Underline(); + foreach (var i in inlines) { underline.Inlines.Add(i); } From c4b93d3b4ec73b1cbee5d7e2561d85d7f2549823 Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Tue, 7 Mar 2017 12:16:22 +0200 Subject: [PATCH 05/12] Returned back System.Serialization --- ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj b/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj index 9d9aff07740..a641102c2d7 100644 --- a/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj +++ b/ReactWindows/ReactNative.Net46/ReactNative.Net46.csproj @@ -107,6 +107,7 @@ $(SolutionDir)\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll True + From 27f7ce1f743cb74de989d95c72e91979cf621fea Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Tue, 7 Mar 2017 12:16:35 +0200 Subject: [PATCH 06/12] Style changes --- ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs | 8 ++++---- .../ReactNative/Views/Text/ReactTextViewManager.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs b/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs index 7798ae6890e..7e31b7fc41c 100644 --- a/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs +++ b/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs @@ -39,12 +39,12 @@ public static T Parse(string value) return Parse(value); } - private static Dictionary EnumToDictionary(Type t) + private static Dictionary EnumToDictionary(Type type) { var result = new Dictionary(); - var names = Enum.GetNames(t); - var values = Enum.GetValues(t); + var names = Enum.GetNames(type); + var values = Enum.GetValues(type); for (int i = 0; i < values.Length; ++i) { @@ -53,7 +53,7 @@ private static Dictionary EnumToDictionary(Type t) result.Add(Normalize(name), value); - var enumMemberAttribute = t.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true).SingleOrDefault(); + var enumMemberAttribute = type.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true).SingleOrDefault(); if (enumMemberAttribute != null) { result.Add(Normalize(((EnumMemberAttribute)enumMemberAttribute).Value), value); diff --git a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs index 1b6024ba007..3d087188b87 100644 --- a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs +++ b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs @@ -80,9 +80,9 @@ public void SetTextDecorationLine(RichTextBlock view, string textDecorationLineV var paragraph = view.Blocks.OfType().First(); paragraph.Inlines.Clear(); firstItemAsUnderline.Inlines.Clear(); - foreach (var i in inlines) + foreach (var inline in inlines) { - paragraph.Inlines.Add(i); + paragraph.Inlines.Add(inline); } break; } @@ -97,9 +97,9 @@ public void SetTextDecorationLine(RichTextBlock view, string textDecorationLineV paragraph.Inlines.Clear(); var underline = new Underline(); - foreach (var i in inlines) + foreach (var inline in inlines) { - underline.Inlines.Add(i); + underline.Inlines.Add(inline); } paragraph.Inlines.Add(underline); From fdbb0ec15fb8ce0cf175392c04c774790a48f6e8 Mon Sep 17 00:00:00 2001 From: Yurii Musiichuk Date: Tue, 7 Mar 2017 18:09:51 +0200 Subject: [PATCH 07/12] Removed ChakraCore directory --- ChakraCore | 1 - 1 file changed, 1 deletion(-) delete mode 160000 ChakraCore diff --git a/ChakraCore b/ChakraCore deleted file mode 160000 index 322442447fc..00000000000 --- a/ChakraCore +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 322442447fc234caf381bcca542b44f686ba5e2b From 355182ad78e26462b5a304a439897571c4a397a3 Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Thu, 9 Mar 2017 12:27:38 +0200 Subject: [PATCH 08/12] Small EnumHelpers reflection improvement --- ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs b/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs index 7e31b7fc41c..b24165f1efb 100644 --- a/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs +++ b/ReactWindows/ReactNative.Shared/Reflection/EnumHelpers.cs @@ -53,7 +53,7 @@ private static Dictionary EnumToDictionary(Type type) result.Add(Normalize(name), value); - var enumMemberAttribute = type.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true).SingleOrDefault(); + var enumMemberAttribute = type.GetField(name).GetCustomAttribute(typeof(EnumMemberAttribute), false); if (enumMemberAttribute != null) { result.Add(Normalize(((EnumMemberAttribute)enumMemberAttribute).Value), value); From f35c67aca6db7da999f32efd4c865dd7e3b982da Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Thu, 9 Mar 2017 12:44:43 +0200 Subject: [PATCH 09/12] Revert "Underline implementation for UWP" This reverts commit 5de9c8e8877a4fcf836bbc621cfa78389abf44e3. # Conflicts: # ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs --- .../Views/Text/ReactTextViewManager.cs | 398 +++++++----------- 1 file changed, 163 insertions(+), 235 deletions(-) diff --git a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs index 3d087188b87..7732b004e01 100644 --- a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs +++ b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs @@ -1,242 +1,170 @@ -using ReactNative.Reflection; -using ReactNative.UIManager; -using ReactNative.UIManager.Annotations; -using System; -using System.Linq; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Documents; -using Windows.UI.Xaml.Media; - -namespace ReactNative.Views.Text -{ - /// - /// The view manager for text views. - /// - public class ReactTextViewManager : ViewParentManager - { - private static readonly IReactCompoundView s_compoundView = new ReactTextCompoundView(); - - /// - /// The name of the view manager. - /// - public override string Name - { - get - { - return "RCTText"; - } - } - - /// - /// Sets the font color for the node. - /// - /// The view. - /// The masked color value. - [ReactProp(ViewProps.Color, CustomType = "Color")] - public void SetColor(RichTextBlock view, uint? color) - { - view.Foreground = color.HasValue - ? new SolidColorBrush(ColorHelpers.Parse(color.Value)) - : null; - } - - /// - /// Sets whether or not the text is selectable. - /// - /// The view. - /// A flag indicating whether or not the text is selectable. - [ReactProp("selectable")] - public void SetSelectable(RichTextBlock view, bool selectable) - { - view.IsTextSelectionEnabled = selectable; - } - - /// - /// Sets the TextDecorationLine for the node. - /// - /// /// The view. - /// The TextDecorationLine value. - [ReactProp(ViewProps.TextDecorationLine)] - public void SetTextDecorationLine(RichTextBlock view, string textDecorationLineValue) - { - var textDecorationLine = EnumHelpers.ParseNullable(textDecorationLineValue) ?? TextDecorationLine.None; - - if (textDecorationLine != TextDecorationLine.None && textDecorationLine != TextDecorationLine.Underline) +using ReactNative.UIManager; +using ReactNative.UIManager.Annotations; +using System.Linq; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Documents; +using Windows.UI.Xaml.Media; + +namespace ReactNative.Views.Text +{ + /// + /// The view manager for text views. + /// + public class ReactTextViewManager : ViewParentManager + { + private static readonly IReactCompoundView s_compoundView = new ReactTextCompoundView(); + + /// + /// The name of the view manager. + /// + public override string Name + { + get { - throw new NotSupportedException("textDecorationLine = \"Strike-through\" is not implemeted in UWP"); - } - - var firstItemAsUnderline = view.Blocks.OfType().First().Inlines.FirstOrDefault() as Underline; - - switch (textDecorationLine) + return "RCTText"; + } + } + + /// + /// Sets the font color for the node. + /// + /// The view. + /// The masked color value. + [ReactProp(ViewProps.Color, CustomType = "Color")] + public void SetColor(RichTextBlock view, uint? color) + { + view.Foreground = color.HasValue + ? new SolidColorBrush(ColorHelpers.Parse(color.Value)) + : null; + } + + /// + /// Sets whether or not the text is selectable. + /// + /// The view. + /// A flag indicating whether or not the text is selectable. + [ReactProp("selectable")] + public void SetSelectable(RichTextBlock view, bool selectable) + { + view.IsTextSelectionEnabled = selectable; + } + + /// + /// Adds a child at the given index. + /// + /// The parent view. + /// The child view. + /// The index. + public override void AddView(RichTextBlock parent, DependencyObject child, int index) + { + var inlineChild = child as Inline; + if (inlineChild == null) { - case TextDecorationLine.None: - { - if (firstItemAsUnderline == null) - break; - - var inlines = GetInlines(view).ToArray(); - var paragraph = view.Blocks.OfType().First(); - paragraph.Inlines.Clear(); - firstItemAsUnderline.Inlines.Clear(); - foreach (var inline in inlines) - { - paragraph.Inlines.Add(inline); - } - break; - } - - case TextDecorationLine.Underline: - { - if (firstItemAsUnderline != null) - break; - - var inlines = GetInlines(view).ToArray(); - var paragraph = view.Blocks.OfType().First(); - paragraph.Inlines.Clear(); - - var underline = new Underline(); - foreach (var inline in inlines) - { - underline.Inlines.Add(inline); - } - - paragraph.Inlines.Add(underline); - - break; - } - } - } - - private InlineCollection GetInlines(RichTextBlock textBlock) + inlineChild = new InlineUIContainer + { + Child = (UIElement)child, + }; + } + + parent.Blocks.OfType().First().Inlines.Insert(index, inlineChild); + } + + /// + /// Creates the shadow node instance. + /// + /// The shadow node instance. + public override ReactTextShadowNode CreateShadowNodeInstance() { - var inlines = textBlock.Blocks.OfType().First().Inlines; - var firstInnerUnderline = inlines.FirstOrDefault() as Underline; + return new ReactTextShadowNode(); + } - if (firstInnerUnderline != null) + /// + /// Gets the child at the given index. + /// + /// The parent view. + /// The index. + /// The child view. + public override DependencyObject GetChildAt(RichTextBlock parent, int index) + { + var child = parent.Blocks.OfType().First().Inlines[index]; + var childInlineContainer = child as InlineUIContainer; + if (childInlineContainer != null) + { + return childInlineContainer.Child; + } + else { - return firstInnerUnderline.Inlines; + return child; } + } + + /// + /// Gets the number of children in the view parent. + /// + /// The view parent. + /// The number of children. + public override int GetChildCount(RichTextBlock parent) + { + return parent.Blocks.OfType().First().Inlines.Count; + } + + /// + /// Removes all children from the view parent. + /// + /// The view parent. + public override void RemoveAllChildren(RichTextBlock parent) + { + var inlines = parent.Blocks.OfType().First().Inlines; + inlines.Clear(); + } + + /// + /// Removes the child at the given index. + /// + /// The view parent. + /// The index. + public override void RemoveChildAt(RichTextBlock parent, int index) + { + var inlines = parent.Blocks.OfType().First().Inlines; + inlines.RemoveAt(index); + } + + /// + /// Receive extra updates from the shadow node. + /// + /// The root view. + /// The extra data. + public override void UpdateExtraData(RichTextBlock root, object extraData) + { + base.UpdateExtraData(root, extraData); + + var textNode = extraData as ReactTextShadowNode; + if (textNode != null) + { + textNode.UpdateTextBlock(root); + } + } + + /// + /// Creates the view instance. + /// + /// The React context. + /// The view instance. + protected override RichTextBlock CreateViewInstance(ThemedReactContext reactContext) + { + var richTextBlock = new RichTextBlock + { + IsTextSelectionEnabled = false, + TextAlignment = TextAlignment.DetectFromContent, + TextTrimming = TextTrimming.CharacterEllipsis, + TextWrapping = TextWrapping.Wrap, + }; + + richTextBlock.Blocks.Add(new Paragraph()); + richTextBlock.SetReactCompoundView(s_compoundView); - return inlines; - } - - /// - /// Adds a child at the given index. - /// - /// The parent view. - /// The child view. - /// The index. - public override void AddView(RichTextBlock parent, DependencyObject child, int index) - { - var inlineChild = child as Inline; - if (inlineChild == null) - { - inlineChild = new InlineUIContainer - { - Child = (UIElement)child, - }; - } - - GetInlines(parent).Insert(index, inlineChild); - } - - /// - /// Creates the shadow node instance. - /// - /// The shadow node instance. - public override ReactTextShadowNode CreateShadowNodeInstance() - { - return new ReactTextShadowNode(); - } - - /// - /// Gets the child at the given index. - /// - /// The parent view. - /// The index. - /// The child view. - public override DependencyObject GetChildAt(RichTextBlock parent, int index) - { - var child = GetInlines(parent)[index]; - var childInlineContainer = child as InlineUIContainer; - if (childInlineContainer != null) - { - return childInlineContainer.Child; - } - else - { - return child; - } - } - - /// - /// Gets the number of children in the view parent. - /// - /// The view parent. - /// The number of children. - public override int GetChildCount(RichTextBlock parent) - { - return GetInlines(parent).Count; - } - - /// - /// Removes all children from the view parent. - /// - /// The view parent. - public override void RemoveAllChildren(RichTextBlock parent) - { - var inlines = GetInlines(parent); - inlines.Clear(); - } - - /// - /// Removes the child at the given index. - /// - /// The view parent. - /// The index. - public override void RemoveChildAt(RichTextBlock parent, int index) - { - var inlines = GetInlines(parent); - inlines.RemoveAt(index); - } - - /// - /// Receive extra updates from the shadow node. - /// - /// The root view. - /// The extra data. - public override void UpdateExtraData(RichTextBlock root, object extraData) - { - base.UpdateExtraData(root, extraData); - - var textNode = extraData as ReactTextShadowNode; - if (textNode != null) - { - textNode.UpdateTextBlock(root); - } - } - - /// - /// Creates the view instance. - /// - /// The React context. - /// The view instance. - protected override RichTextBlock CreateViewInstance(ThemedReactContext reactContext) - { - var richTextBlock = new RichTextBlock - { - IsTextSelectionEnabled = false, - TextAlignment = TextAlignment.DetectFromContent, - TextTrimming = TextTrimming.CharacterEllipsis, - TextWrapping = TextWrapping.Wrap, - }; - - richTextBlock.Blocks.Add(new Paragraph()); - richTextBlock.SetReactCompoundView(s_compoundView); - - return richTextBlock; - } - } -} + return richTextBlock; + } + } +} From ced568740216cae7dc17061501eec41c56bc5667 Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Thu, 9 Mar 2017 13:04:48 +0200 Subject: [PATCH 10/12] Line endings fix --- .../Views/Text/ReactTextViewManager.cs | 340 +++++++++--------- 1 file changed, 170 insertions(+), 170 deletions(-) diff --git a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs index 7732b004e01..9d30494b3cd 100644 --- a/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs +++ b/ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs @@ -1,170 +1,170 @@ -using ReactNative.UIManager; -using ReactNative.UIManager.Annotations; -using System.Linq; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Documents; -using Windows.UI.Xaml.Media; - -namespace ReactNative.Views.Text -{ - /// - /// The view manager for text views. - /// - public class ReactTextViewManager : ViewParentManager - { - private static readonly IReactCompoundView s_compoundView = new ReactTextCompoundView(); - - /// - /// The name of the view manager. - /// - public override string Name - { - get - { - return "RCTText"; - } - } - - /// - /// Sets the font color for the node. - /// - /// The view. - /// The masked color value. - [ReactProp(ViewProps.Color, CustomType = "Color")] - public void SetColor(RichTextBlock view, uint? color) - { - view.Foreground = color.HasValue - ? new SolidColorBrush(ColorHelpers.Parse(color.Value)) - : null; - } - - /// - /// Sets whether or not the text is selectable. - /// - /// The view. - /// A flag indicating whether or not the text is selectable. - [ReactProp("selectable")] - public void SetSelectable(RichTextBlock view, bool selectable) - { - view.IsTextSelectionEnabled = selectable; - } - - /// - /// Adds a child at the given index. - /// - /// The parent view. - /// The child view. - /// The index. - public override void AddView(RichTextBlock parent, DependencyObject child, int index) - { - var inlineChild = child as Inline; - if (inlineChild == null) - { - inlineChild = new InlineUIContainer - { - Child = (UIElement)child, - }; - } - - parent.Blocks.OfType().First().Inlines.Insert(index, inlineChild); - } - - /// - /// Creates the shadow node instance. - /// - /// The shadow node instance. - public override ReactTextShadowNode CreateShadowNodeInstance() - { - return new ReactTextShadowNode(); - } - - /// - /// Gets the child at the given index. - /// - /// The parent view. - /// The index. - /// The child view. - public override DependencyObject GetChildAt(RichTextBlock parent, int index) - { - var child = parent.Blocks.OfType().First().Inlines[index]; - var childInlineContainer = child as InlineUIContainer; - if (childInlineContainer != null) - { - return childInlineContainer.Child; - } - else - { - return child; - } - } - - /// - /// Gets the number of children in the view parent. - /// - /// The view parent. - /// The number of children. - public override int GetChildCount(RichTextBlock parent) - { - return parent.Blocks.OfType().First().Inlines.Count; - } - - /// - /// Removes all children from the view parent. - /// - /// The view parent. - public override void RemoveAllChildren(RichTextBlock parent) - { - var inlines = parent.Blocks.OfType().First().Inlines; - inlines.Clear(); - } - - /// - /// Removes the child at the given index. - /// - /// The view parent. - /// The index. - public override void RemoveChildAt(RichTextBlock parent, int index) - { - var inlines = parent.Blocks.OfType().First().Inlines; - inlines.RemoveAt(index); - } - - /// - /// Receive extra updates from the shadow node. - /// - /// The root view. - /// The extra data. - public override void UpdateExtraData(RichTextBlock root, object extraData) - { - base.UpdateExtraData(root, extraData); - - var textNode = extraData as ReactTextShadowNode; - if (textNode != null) - { - textNode.UpdateTextBlock(root); - } - } - - /// - /// Creates the view instance. - /// - /// The React context. - /// The view instance. - protected override RichTextBlock CreateViewInstance(ThemedReactContext reactContext) - { - var richTextBlock = new RichTextBlock - { - IsTextSelectionEnabled = false, - TextAlignment = TextAlignment.DetectFromContent, - TextTrimming = TextTrimming.CharacterEllipsis, - TextWrapping = TextWrapping.Wrap, - }; - - richTextBlock.Blocks.Add(new Paragraph()); - richTextBlock.SetReactCompoundView(s_compoundView); - - return richTextBlock; - } - } -} +using ReactNative.UIManager; +using ReactNative.UIManager.Annotations; +using System.Linq; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Documents; +using Windows.UI.Xaml.Media; + +namespace ReactNative.Views.Text +{ + /// + /// The view manager for text views. + /// + public class ReactTextViewManager : ViewParentManager + { + private static readonly IReactCompoundView s_compoundView = new ReactTextCompoundView(); + + /// + /// The name of the view manager. + /// + public override string Name + { + get + { + return "RCTText"; + } + } + + /// + /// Sets the font color for the node. + /// + /// The view. + /// The masked color value. + [ReactProp(ViewProps.Color, CustomType = "Color")] + public void SetColor(RichTextBlock view, uint? color) + { + view.Foreground = color.HasValue + ? new SolidColorBrush(ColorHelpers.Parse(color.Value)) + : null; + } + + /// + /// Sets whether or not the text is selectable. + /// + /// The view. + /// A flag indicating whether or not the text is selectable. + [ReactProp("selectable")] + public void SetSelectable(RichTextBlock view, bool selectable) + { + view.IsTextSelectionEnabled = selectable; + } + + /// + /// Adds a child at the given index. + /// + /// The parent view. + /// The child view. + /// The index. + public override void AddView(RichTextBlock parent, DependencyObject child, int index) + { + var inlineChild = child as Inline; + if (inlineChild == null) + { + inlineChild = new InlineUIContainer + { + Child = (UIElement)child, + }; + } + + parent.Blocks.OfType().First().Inlines.Insert(index, inlineChild); + } + + /// + /// Creates the shadow node instance. + /// + /// The shadow node instance. + public override ReactTextShadowNode CreateShadowNodeInstance() + { + return new ReactTextShadowNode(); + } + + /// + /// Gets the child at the given index. + /// + /// The parent view. + /// The index. + /// The child view. + public override DependencyObject GetChildAt(RichTextBlock parent, int index) + { + var child = parent.Blocks.OfType().First().Inlines[index]; + var childInlineContainer = child as InlineUIContainer; + if (childInlineContainer != null) + { + return childInlineContainer.Child; + } + else + { + return child; + } + } + + /// + /// Gets the number of children in the view parent. + /// + /// The view parent. + /// The number of children. + public override int GetChildCount(RichTextBlock parent) + { + return parent.Blocks.OfType().First().Inlines.Count; + } + + /// + /// Removes all children from the view parent. + /// + /// The view parent. + public override void RemoveAllChildren(RichTextBlock parent) + { + var inlines = parent.Blocks.OfType().First().Inlines; + inlines.Clear(); + } + + /// + /// Removes the child at the given index. + /// + /// The view parent. + /// The index. + public override void RemoveChildAt(RichTextBlock parent, int index) + { + var inlines = parent.Blocks.OfType().First().Inlines; + inlines.RemoveAt(index); + } + + /// + /// Receive extra updates from the shadow node. + /// + /// The root view. + /// The extra data. + public override void UpdateExtraData(RichTextBlock root, object extraData) + { + base.UpdateExtraData(root, extraData); + + var textNode = extraData as ReactTextShadowNode; + if (textNode != null) + { + textNode.UpdateTextBlock(root); + } + } + + /// + /// Creates the view instance. + /// + /// The React context. + /// The view instance. + protected override RichTextBlock CreateViewInstance(ThemedReactContext reactContext) + { + var richTextBlock = new RichTextBlock + { + IsTextSelectionEnabled = false, + TextAlignment = TextAlignment.DetectFromContent, + TextTrimming = TextTrimming.CharacterEllipsis, + TextWrapping = TextWrapping.Wrap, + }; + + richTextBlock.Blocks.Add(new Paragraph()); + richTextBlock.SetReactCompoundView(s_compoundView); + + return richTextBlock; + } + } +} From 5e842a0788f17bf21c6dd22b99faaa4868f36a43 Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Mon, 13 Mar 2017 15:58:01 +0200 Subject: [PATCH 11/12] Moved implementation from ShadowNode to TextViewManager and SpanViewManager, support decoration of inlines --- .../Views/Text/ReactTextShadowNode.cs | 36 ------------------- .../Views/Text/ReactTextViewManager.cs | 32 ++++++++++++++++- .../Views/Text/ReactSpanViewManager.cs | 36 ++++++++++++++++++- 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs index 8a50a84f8aa..4440ebe9d95 100644 --- a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs +++ b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs @@ -27,8 +27,6 @@ public class ReactTextShadowNode : LayoutShadowNode private FontWeight? _fontWeight; private TextAlignment _textAlignment = TextAlignment.Left; - private TextDecorationLine _textDecorationLine = TextDecorationLine.None; - private string _fontFamily; /// @@ -40,39 +38,6 @@ public ReactTextShadowNode() MeasureText(this, node, width, widthMode, height, heightMode); } - /// - /// Sets the TextDecorationLine for the node. - /// - /// The TextDecorationLine value. - [ReactProp(ViewProps.TextDecorationLine)] - public void SetTextDecorationLine(string textDecorationLineValue) - { - var textDecorationLine = EnumHelpers.ParseNullable(textDecorationLineValue) ?? TextDecorationLine.None; - if (_textDecorationLine != textDecorationLine) - { - _textDecorationLine = textDecorationLine; - MarkUpdated(); - } - } - - private IEnumerable TextDecorationCollection - { - get - { - switch (_textDecorationLine) - { - case TextDecorationLine.Underline: - return TextDecorations.Underline; - case TextDecorationLine.LineThrough: - return TextDecorations.Strikethrough; - case TextDecorationLine.UnderlineLineThrough: - return TextDecorations.Underline.Concat(TextDecorations.Strikethrough); - case TextDecorationLine.None: - default: - return Enumerable.Empty(); - } - } - } /// /// Sets the font size for the node. @@ -275,7 +240,6 @@ private void UpdateTextBlockCore(TextBlock textBlock, bool measureOnly) textBlock.FontSize = _fontSize ?? 15; textBlock.FontStyle = _fontStyle ?? new FontStyle(); textBlock.FontWeight = _fontWeight ?? FontWeights.Normal; - textBlock.TextDecorations = new TextDecorationCollection(TextDecorationCollection); if (_fontFamily != null) { diff --git a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextViewManager.cs b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextViewManager.cs index ddfb691e93f..6c442affa82 100644 --- a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextViewManager.cs +++ b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextViewManager.cs @@ -1,7 +1,10 @@ -using ReactNative.UIManager; +using ReactNative.Reflection; +using ReactNative.UIManager; using ReactNative.UIManager.Annotations; using System; using System.Collections; +using System.Collections.Generic; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; @@ -40,6 +43,33 @@ public void SetColor(TextBlock view, uint? color) : null; } + /// + /// Sets the TextDecorationLine for the node. + /// + /// The view. + /// The TextDecorationLine value. + [ReactProp(ViewProps.TextDecorationLine)] + public void SetTextDecorationLine(TextBlock view, string textDecorationLineValue) + { + var textDecorationLine = EnumHelpers.ParseNullable(textDecorationLineValue) ?? TextDecorationLine.None; + switch (textDecorationLine) + { + case TextDecorationLine.Underline: + view.TextDecorations = TextDecorations.Underline; + break; + case TextDecorationLine.LineThrough: + view.TextDecorations = TextDecorations.Strikethrough; + break; + case TextDecorationLine.UnderlineLineThrough: + view.TextDecorations = new TextDecorationCollection(TextDecorations.Underline.Concat(TextDecorations.Strikethrough)); + break; + case TextDecorationLine.None: + default: + view.TextDecorations = null; + break; + } + } + /// /// Sets whether or not the text is selectable. /// diff --git a/ReactWindows/ReactNative.Shared/Views/Text/ReactSpanViewManager.cs b/ReactWindows/ReactNative.Shared/Views/Text/ReactSpanViewManager.cs index 73d0d46828a..ecfd1390773 100644 --- a/ReactWindows/ReactNative.Shared/Views/Text/ReactSpanViewManager.cs +++ b/ReactWindows/ReactNative.Shared/Views/Text/ReactSpanViewManager.cs @@ -1,7 +1,11 @@ -using ReactNative.UIManager; +using ReactNative.Reflection; +using ReactNative.UIManager; using ReactNative.UIManager.Annotations; using System; using System.Collections; +using System.Collections.Generic; +using System.Linq; + #if WINDOWS_UWP using Windows.UI.Xaml; using Windows.UI.Xaml.Documents; @@ -55,6 +59,36 @@ public void SetColor(Span view, uint? color) : null; } +#if !WINDOWS_UWP + /// + /// Sets the TextDecorationLine for the node. + /// + /// The view. + /// The TextDecorationLine value. + [ReactProp(ViewProps.TextDecorationLine)] + public void SetTextDecorationLine(Span view, string textDecorationLineValue) + { + var textDecorationLine = EnumHelpers.ParseNullable(textDecorationLineValue) ?? TextDecorationLine.None; + + switch (textDecorationLine) + { + case TextDecorationLine.Underline: + view.TextDecorations = TextDecorations.Underline; + break; + case TextDecorationLine.LineThrough: + view.TextDecorations = TextDecorations.Strikethrough; + break; + case TextDecorationLine.UnderlineLineThrough: + view.TextDecorations = new TextDecorationCollection(TextDecorations.Underline.Concat(TextDecorations.Strikethrough)); + break; + case TextDecorationLine.None: + default: + view.TextDecorations = null; + break; + } + } +#endif + /// /// Adds a child at the given index. /// From e259858edaab941d116d3ba8fb99476ecfc5382c Mon Sep 17 00:00:00 2001 From: Yuriy Musiychuk Date: Mon, 13 Mar 2017 16:47:22 +0200 Subject: [PATCH 12/12] Returned ReactTextShadowNode.cs to initial state --- .../ReactNative.Net46/Views/Text/ReactTextShadowNode.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs index 4440ebe9d95..e3216dd4694 100644 --- a/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs +++ b/ReactWindows/ReactNative.Net46/Views/Text/ReactTextShadowNode.cs @@ -4,7 +4,6 @@ using ReactNative.UIManager; using ReactNative.UIManager.Annotations; using System; -using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; @@ -38,7 +37,6 @@ public ReactTextShadowNode() MeasureText(this, node, width, widthMode, height, heightMode); } - /// /// Sets the font size for the node. ///