RichTextEditor.xaml.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Documents;
  11. using System.Windows.Media;
  12. using HtmlAgilityPack;
  13. using InABox.Core;
  14. using InABox.WPF;
  15. using NPOI.SS.Formula.Functions;
  16. using Syncfusion.Windows.Controls.RichTextBoxAdv;
  17. namespace InABox.DynamicGrid
  18. {
  19. public delegate void RichTextEditorChanged(object sender);
  20. public class ButtonVisibleConverter : AbstractConverter<RichTextEditorButtons, Visibility>
  21. {
  22. public Visibility Set { get; set; } = Visibility.Visible;
  23. public Visibility Unset { get; set; } = Visibility.Collapsed;
  24. public RichTextEditorButtons Flag { get; set; } = RichTextEditorButtons.None;
  25. public override Visibility Convert(RichTextEditorButtons value)
  26. {
  27. return value != RichTextEditorButtons.None && value.HasFlag(Flag) ? Set : Unset;
  28. }
  29. }
  30. /// <summary>
  31. /// Interaction logic for RichTextEditorControl.xaml
  32. /// </summary>
  33. public partial class RichTextEditor : UserControl
  34. {
  35. // public static readonly DependencyProperty HideToolbarProperty =
  36. // DependencyProperty.Register(nameof(HideToolbar), typeof(bool), typeof(RichTextEditor));
  37. public static readonly DependencyProperty ZoomFactorProperty =
  38. DependencyProperty.Register(nameof(ZoomFactor), typeof(double), typeof(RichTextEditor));
  39. public static readonly DependencyProperty ColorProperty =
  40. DependencyProperty.Register(
  41. "Color",
  42. typeof(Color),
  43. typeof(RichTextEditor),
  44. new PropertyMetadata(default(Color), OnBackgroundPropertyChanged));
  45. private bool bdirty;
  46. private bool bReady;
  47. private string curvalue = "";
  48. public RichTextEditorButtons VisibleButtons
  49. {
  50. get => ViewModel.VisibleButtons;
  51. set => ViewModel.VisibleButtons = value;
  52. }
  53. public RichTextEditor()
  54. {
  55. InitializeComponent();
  56. Bold.SmallIcon = Wpf.Resources.Bold16.AsBitmapImage(16, 16);
  57. Italic.SmallIcon = Wpf.Resources.Italic16.AsBitmapImage(16, 16);
  58. Underline.SmallIcon = Wpf.Resources.Underline16.AsBitmapImage(16, 16);
  59. AlignLeft.SmallIcon = Wpf.Resources.AlignTextLeft16.AsBitmapImage(16, 16);
  60. AlignCentre.SmallIcon = Wpf.Resources.AlignTextCenter16.AsBitmapImage(16, 16);
  61. AlignRight.SmallIcon = Wpf.Resources.AlignTextRight16.AsBitmapImage(16, 16);
  62. AlignJustify.SmallIcon = Wpf.Resources.AlignTextJustify16.AsBitmapImage(16, 16);
  63. Hyperlink.SmallIcon = Wpf.Resources.Hyperlink16.AsBitmapImage(16, 16);
  64. Picture.SmallIcon = Wpf.Resources.Picture16.AsBitmapImage(16, 16);
  65. Table.SmallIcon = Wpf.Resources.Table16.AsBitmapImage(16, 16);
  66. ZoomIn.SmallIcon = Wpf.Resources.zoomin.AsBitmapImage(16, 16);
  67. ZoomOut.SmallIcon = Wpf.Resources.zoomout.AsBitmapImage(16, 16);
  68. Editor.CaretBrush = new SolidColorBrush(Colors.Black);
  69. Editor.FontFamily = new FontFamily("Calibri");
  70. Editor.FontSize = 10.0F;
  71. Editor.Foreground = new SolidColorBrush(Colors.Black);
  72. ZoomFactor = 150;
  73. Text = "";
  74. }
  75. // public bool HideToolbar
  76. // {
  77. // get => (bool)GetValue(HideToolbarProperty);
  78. // set
  79. // {
  80. // SetValue(HideToolbarProperty, value);
  81. // Toolbar.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
  82. // }
  83. // }
  84. public double ZoomFactor
  85. {
  86. get => (double)GetValue(ZoomFactorProperty);
  87. set
  88. {
  89. SetValue(ZoomFactorProperty, value);
  90. Editor.ZoomFactor = value;
  91. }
  92. }
  93. public string Text
  94. {
  95. get => Save();
  96. set => Load(value);
  97. }
  98. public RichTextEditorChanged? OnChanged { get; set; }
  99. public Color Color
  100. {
  101. get => (Color)GetValue(ColorProperty);
  102. set
  103. {
  104. SetValue(ColorProperty, value);
  105. Editor.Background = new SolidColorBrush(value);
  106. }
  107. }
  108. public void Load(string content)
  109. {
  110. if (content == null)
  111. content = "";
  112. content = HTMLUtils.TextToHtml(content);
  113. using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(content)))
  114. {
  115. Editor.Load(ms, FormatType.Html);
  116. }
  117. VerticalAlignment = VerticalAlignment.Top;
  118. VerticalAlignment = VerticalAlignment.Stretch;
  119. curvalue = content;
  120. bdirty = false;
  121. }
  122. public string Save()
  123. {
  124. if (bdirty)
  125. {
  126. using (var ms = new MemoryStream())
  127. {
  128. Editor.Save(ms, FormatType.Html);
  129. curvalue = Encoding.UTF8.GetString(ms.GetBuffer());
  130. curvalue = HTMLUtils.HtmlToText(curvalue);
  131. }
  132. bdirty = false;
  133. }
  134. return curvalue;
  135. }
  136. private void RichTextBoxAdv_ContentChanged(object obj, ContentChangedEventArgs args)
  137. {
  138. bdirty = true;
  139. }
  140. public void SetColor(Color color)
  141. {
  142. Editor.Background = new SolidColorBrush(color);
  143. }
  144. private static void OnBackgroundPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  145. {
  146. if (d is not RichTextEditor source) return;
  147. source.SetColor((Color)e.NewValue);
  148. }
  149. private void RichTextBoxAdv_LostFocus(object sender, RoutedEventArgs e)
  150. {
  151. if (bReady)
  152. OnChanged?.Invoke(this);
  153. bReady = true;
  154. }
  155. private void ZoomIn_Click(object sender, RoutedEventArgs e)
  156. {
  157. Editor.ZoomFactor = Editor.ZoomFactor * 1.5F;
  158. }
  159. private void ZoomOut_Click(object sender, RoutedEventArgs e)
  160. {
  161. Editor.ZoomFactor = Editor.ZoomFactor / 1.5F;
  162. }
  163. private void Editor_RequestNavigate(object obj, RequestNavigateEventArgs args)
  164. {
  165. var processStartInfo = new ProcessStartInfo(args.Hyperlink.NavigationLink);
  166. processStartInfo.UseShellExecute = true;
  167. Process.Start(processStartInfo);
  168. }
  169. /// <summary>
  170. /// Handles the ImageNodeVisited event of the richTextBoxAdv control.
  171. /// We are setting the image "source" property to empty to save the image inline
  172. /// See: https://help.syncfusion.com/uwp/richtextbox/faq-section/how-to-export-the-inserted-image-as-an-embedded-image-in-html-in-sfrichtextboxadv
  173. /// </summary>
  174. /// <param name="obj">The source of the event.</param>
  175. /// <param name="args">The <see cref="ImageNodeVisitedEventArgs"/> instance containing the event data.</param>
  176. private void HtmlImportExportSettings_OnImageNodeVisited(object obj, ImageNodeVisitedEventArgs args)
  177. {
  178. if (args.IsSaving)
  179. args.Source = string.Empty;
  180. }
  181. }
  182. }