CPDFSearchResultUI.xaml.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Collections.ObjectModel;
  5. using System.ComponentModel;
  6. using System.Globalization;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Text.RegularExpressions;
  10. using System.Threading.Tasks;
  11. using System.Windows;
  12. using System.Windows.Controls;
  13. using System.Windows.Data;
  14. using System.Windows.Documents;
  15. using System.Windows.Input;
  16. using System.Windows.Media;
  17. using System.Windows.Media.Imaging;
  18. using System.Windows.Navigation;
  19. using System.Windows.Shapes;
  20. namespace Compdfkit_Tools.PDFControlUI
  21. {
  22. public partial class CPDFSearchResultUI : UserControl
  23. {
  24. public event EventHandler<int> SelectionChanged;
  25. private ObservableCollection<TextBindData> searchResults;
  26. public CPDFSearchResultUI()
  27. {
  28. InitializeComponent();
  29. searchResults = new ObservableCollection<TextBindData>();
  30. ICollectionView groupView = CollectionViewSource.GetDefaultView(searchResults);
  31. groupView.GroupDescriptions.Add(new PropertyGroupDescription(nameof(TextBindData.ShowPageIndex)));
  32. }
  33. private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
  34. {
  35. InvokeSelectionChangedEvent(ResultListControl.SelectedIndex);
  36. }
  37. public void SetSearchResult(List<BindSearchResult> results)
  38. {
  39. searchResults.Clear();
  40. if (results == null || results.Count == 0)
  41. {
  42. ResultListControl.ItemsSource = null;
  43. NoResultText.Visibility = Visibility.Visible;
  44. return;
  45. }
  46. foreach (BindSearchResult item in results)
  47. {
  48. searchResults.Add(new TextBindData()
  49. {
  50. BindProperty = item
  51. });
  52. }
  53. ResultListControl.ItemsSource = searchResults;
  54. ResultListControl.Visibility = Visibility.Visible;
  55. NoResultText.Visibility = Visibility.Collapsed;
  56. }
  57. public BindSearchResult GetSelectItem()
  58. {
  59. TextBindData bindData = ResultListControl.SelectedItem as TextBindData;
  60. if (bindData != null)
  61. {
  62. return bindData.BindProperty;
  63. }
  64. return null;
  65. }
  66. public BindSearchResult GetItem(int index)
  67. {
  68. if (index < 0)
  69. {
  70. return null;
  71. }
  72. if (ResultListControl.HasItems && ResultListControl.Items.Count > index)
  73. {
  74. TextBindData bindData = ResultListControl.Items[index] as TextBindData;
  75. if (bindData != null)
  76. {
  77. return bindData.BindProperty;
  78. }
  79. }
  80. return null;
  81. }
  82. /// <summary>
  83. /// 清除选中结果
  84. /// </summary>
  85. public void ClearSelection()
  86. {
  87. int oldSelectionIndex = ResultListControl.SelectedIndex;
  88. ResultListControl.UnselectAll();
  89. if (oldSelectionIndex != ResultListControl.SelectedIndex)
  90. {
  91. InvokeSelectionChangedEvent(ResultListControl.SelectedIndex);
  92. }
  93. }
  94. /// <summary>
  95. /// 设置选中结果
  96. /// </summary>
  97. /// <param name="selectIndex">选中索引</param>
  98. public void SelectItem(int selectIndex)
  99. {
  100. if (ResultListControl.SelectedIndex != selectIndex)
  101. {
  102. ResultListControl.SelectedIndex = selectIndex;
  103. }
  104. }
  105. internal void InvokeSelectionChangedEvent(int selectionIndex)
  106. {
  107. SelectionChanged?.Invoke(this, selectionIndex);
  108. }
  109. }
  110. public class BindSearchResult
  111. {
  112. /// <summary>
  113. /// 页面索引
  114. /// </summary>
  115. public int PageIndex { get; set; }
  116. /// <summary>
  117. /// 搜索文字结果
  118. /// </summary>
  119. public string TextContent { get; set; }
  120. /// <summary>
  121. /// 搜索高亮颜色
  122. /// </summary>
  123. public Color HighLightColor { get; set; }
  124. /// <summary>
  125. /// 搜索关键字
  126. /// </summary>
  127. public string SearchWord { get; set; }
  128. /// <summary>
  129. /// 搜索结果范围区域
  130. /// </summary>
  131. public Rect TextRect { get; set; }
  132. /// <summary>
  133. /// 页面旋转角度
  134. /// </summary>
  135. public int PageRotate { get; set; }
  136. }
  137. internal class TextBindData
  138. {
  139. public int ShowPageIndex { get { return BindProperty.PageIndex + 1; } set { BindProperty.PageIndex = value; } }
  140. public BindSearchResult BindProperty { get; set; }
  141. public TextBindData()
  142. {
  143. BindProperty = new BindSearchResult();
  144. }
  145. }
  146. internal class SearchResultBindHelper : DependencyObject
  147. {
  148. public static FlowDocument GetDocumentBind(DependencyObject obj)
  149. {
  150. return (FlowDocument)obj.GetValue(DocumentBindProperty);
  151. }
  152. public static void SetDocumentBind(DependencyObject obj, FlowDocument value)
  153. {
  154. obj.SetValue(DocumentBindProperty, value);
  155. }
  156. public static readonly DependencyProperty DocumentBindProperty =
  157. DependencyProperty.RegisterAttached("DocumentBind",
  158. typeof(BindSearchResult),
  159. typeof(SearchResultBindHelper),
  160. new FrameworkPropertyMetadata
  161. {
  162. BindsTwoWayByDefault = false,
  163. PropertyChangedCallback = (obj, e) =>
  164. {
  165. RichTextBox richTextBox = obj as RichTextBox;
  166. BindSearchResult bindItem = e.NewValue as BindSearchResult;
  167. if (richTextBox != null && bindItem != null)
  168. {
  169. richTextBox.Document = GetFlowDocument(bindItem.TextContent.Trim(), bindItem.SearchWord, bindItem.HighLightColor);
  170. }
  171. }
  172. });
  173. /// <summary>
  174. /// Get document stream data
  175. /// </summary>
  176. /// <param name="content">Search text results</param>
  177. /// <param name="keyword">Search for keywords</param>
  178. /// <param name="textColor">Highlight text color</param>
  179. /// <returns>Document flow data</returns>
  180. public static FlowDocument GetFlowDocument(string content, string keyword, Color textColor)
  181. {
  182. FlowDocument Document = new FlowDocument();
  183. Paragraph textPara = new Paragraph();
  184. Document.Blocks.Add(textPara);
  185. List<int> indexList = new List<int>();
  186. content = Regex.Replace(content, "[\r\n]", " ");
  187. if (keyword.Length > 0)
  188. {
  189. for (int i = 0; i < content.Length && i >= 0;)
  190. {
  191. i = content.IndexOf(keyword, i, StringComparison.OrdinalIgnoreCase);
  192. if (i == -1)
  193. {
  194. break;
  195. }
  196. if (indexList.Contains(i) == false)
  197. {
  198. indexList.Add(i);
  199. }
  200. i += keyword.Length;
  201. }
  202. }
  203. List<string> splitList = new List<string>();
  204. int lastIndex = -1;
  205. foreach (int index in indexList)
  206. {
  207. string prevStr = string.Empty;
  208. if (lastIndex == -1)
  209. {
  210. prevStr = content.Substring(0, index);
  211. }
  212. else
  213. {
  214. prevStr = content.Substring(lastIndex + keyword.Length, index - lastIndex - 1);
  215. }
  216. if (prevStr != string.Empty)
  217. {
  218. splitList.Add(prevStr);
  219. }
  220. splitList.Add(content.Substring(index, keyword.Length));
  221. lastIndex = index;
  222. }
  223. if (indexList.Count > 0)
  224. {
  225. lastIndex = indexList[indexList.Count - 1];
  226. if (content.Length > lastIndex + keyword.Length)
  227. {
  228. splitList.Add(content.Substring(lastIndex + keyword.Length));
  229. }
  230. }
  231. TextBlock addBlock = new TextBlock();
  232. foreach (string textappend in splitList)
  233. {
  234. Run textRun = new Run(textappend);
  235. if (textappend.Equals(keyword, StringComparison.OrdinalIgnoreCase))
  236. {
  237. textRun.Background = new SolidColorBrush(textColor);
  238. }
  239. addBlock.Inlines.Add(textRun);
  240. }
  241. addBlock.TextTrimming = TextTrimming.CharacterEllipsis;
  242. textPara.Inlines.Add(addBlock);
  243. return Document;
  244. }
  245. }
  246. }