CaretVisual.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. using ComPDFKit.Import;
  2. using ComPDFKit.PDFPage;
  3. using ComPDFKit.PDFPage.Edit;
  4. using ComPDFKit.Tool.SettingParam;
  5. using ComPDFKit.Viewer.Helper;
  6. using ComPDFKitViewer.Helper;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Timers;
  10. using System.Windows;
  11. using System.Windows.Controls;
  12. using System.Windows.Media;
  13. using System.Windows.Threading;
  14. namespace ComPDFKit.Tool.DrawTool
  15. {
  16. /// <summary>
  17. /// Use to draw the cursor and selected effect of text editing
  18. /// </summary>
  19. internal class CaretVisual : DrawingVisual
  20. {
  21. #region Attributes
  22. private Timer caretTimer;
  23. protected DefaultDrawParam drawParam = new DefaultDrawParam();
  24. private bool lastShow = true;
  25. private Point caretHeight = new Point(0, 0);
  26. private Point cursorPoint = new Point(0, 0);
  27. private double currentZoom = 1;
  28. private Rect paintOffset { get; set; }
  29. /// <summary>
  30. /// Selected text's collection of drawn rectangles.
  31. /// </summary>
  32. List<Rect> selectRects { get; set; } = new List<Rect>();
  33. #endregion
  34. #region Timer
  35. public void StartTimer()
  36. {
  37. if (caretTimer.Enabled == false)
  38. {
  39. caretTimer.Start();
  40. }
  41. }
  42. public void StopTimer()
  43. {
  44. caretTimer.Stop();
  45. cursorPoint = new Point(0, 0);
  46. caretHeight = new Point(0, 0);
  47. currentZoom = 0;
  48. paintOffset = new Rect();
  49. }
  50. private void CaretTimerElapsed(object sender, ElapsedEventArgs e)
  51. {
  52. if ((cursorPoint - caretHeight).Length > 0)
  53. {
  54. Dispatcher.InvokeAsync(() =>
  55. {
  56. Draw(lastShow);
  57. });
  58. }
  59. }
  60. #endregion
  61. /// <summary>
  62. /// Re-locate the child elements
  63. /// </summary>
  64. public void Arrange()
  65. {
  66. foreach (Visual child in Children)
  67. {
  68. if (!(child is UIElement))
  69. {
  70. continue;
  71. }
  72. UIElement checkChild = child as UIElement;
  73. try
  74. {
  75. double left = Canvas.GetLeft(checkChild);
  76. double top = Canvas.GetTop(checkChild);
  77. double width = (double)checkChild.GetValue(FrameworkElement.WidthProperty);
  78. double height = (double)checkChild.GetValue(FrameworkElement.HeightProperty);
  79. checkChild.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
  80. checkChild.Arrange(new Rect(
  81. double.IsNaN(left) ? 0 : left,
  82. double.IsNaN(top) ? 0 : top,
  83. double.IsNaN(width) ? checkChild.DesiredSize.Width : width,
  84. double.IsNaN(height) ? checkChild.DesiredSize.Height : height));
  85. }
  86. catch (Exception ex)
  87. {
  88. }
  89. }
  90. }
  91. public CaretVisual(DefaultDrawParam defaultDrawParam)
  92. {
  93. caretTimer = new Timer(500);
  94. caretTimer.Elapsed += CaretTimerElapsed;
  95. caretTimer.AutoReset = true;
  96. drawParam = defaultDrawParam;
  97. }
  98. /// <summary>
  99. /// Set the selected text effect area in text editing
  100. /// </summary>
  101. /// <param name="SelectLineRects">
  102. /// Rect of PDF
  103. /// </param>
  104. public void SetSelectRect(List<Rect> SelectLineRects)
  105. {
  106. selectRects.Clear();
  107. for (int i = 0; i < SelectLineRects.Count; i++)
  108. {
  109. selectRects.Add(DpiHelper.PDFRectToStandardRect(SelectLineRects[i]));
  110. }
  111. }
  112. public void SetZoom(double Zoom)
  113. {
  114. currentZoom = Zoom;
  115. }
  116. /// <summary>
  117. /// Set the current page drawing area (standard DPI)
  118. /// </summary>
  119. /// <param name="paintOffset">
  120. /// The current page drawing area (standard DPI)
  121. /// </param>
  122. public void SetPaintOffset(Rect paintOffset)
  123. {
  124. this.paintOffset = paintOffset;
  125. }
  126. /// <summary>
  127. /// Set the current cursor position
  128. /// </summary>
  129. /// <param name="EditArea">
  130. /// Data object being edited
  131. /// </param>
  132. /// <param name="Zoom">
  133. /// Current zoom factor
  134. /// </param>
  135. /// <param name="paintRect">
  136. /// Current text box drawing area (standard DPI)
  137. /// </param>
  138. /// <param name="paintOffset">
  139. /// Current page drawing area (standard DPI)
  140. /// </param>
  141. /// <returns>
  142. /// Set error return false
  143. /// </returns>
  144. public bool SetCaretVisualArea(CPDFEditArea EditArea, double Zoom, Rect paintOffset, Point mousePoint)
  145. {
  146. if (EditArea.Type == CPDFEditType.EditText)
  147. {
  148. cursorPoint = new Point(0, 0);
  149. // Mouse coordinates on the current page (PDF).
  150. Point pagePoint = new Point(((mousePoint.X - paintOffset.X) / Zoom),
  151. ((mousePoint.Y - paintOffset.Y) / Zoom));
  152. // Call the SDK interface to set the coordinates and get the current cursor position and height
  153. pagePoint = DpiHelper.StandardPointToPDFPoint(pagePoint);
  154. (EditArea as CPDFEditTextArea).SelectCharItemAtPos(DataConversionForWPF.PointConversionForCPoint(pagePoint));
  155. CPoint caretCPoint = new CPoint(0, 0);
  156. CPoint HighCpoint = new CPoint(0, 0);
  157. (EditArea as CPDFEditTextArea).GetTextCursorPoints(ref caretCPoint, ref HighCpoint);
  158. Point caretPoint = DataConversionForWPF.CPointConversionForPoint(caretCPoint);
  159. Point pointHigh = DataConversionForWPF.CPointConversionForPoint(HighCpoint);
  160. // Converting SDK return values into data required for drawing
  161. //CaretHeight = DpiHelper.PDFNumToStandardNum((caretPoint - pointHigh).Length);
  162. //Rect caretRect = new Rect(caretPoint, pointHigh);
  163. caretHeight = DpiHelper.PDFPointToStandardPoint(pointHigh);
  164. cursorPoint = DpiHelper.PDFPointToStandardPoint(caretPoint);
  165. currentZoom = Zoom;
  166. this.paintOffset = paintOffset;
  167. return true;
  168. }
  169. return false;
  170. }
  171. /// <summary>
  172. /// Set the current cursor position
  173. /// </summary>
  174. /// <param name="paintOffset">
  175. /// The lowPoint obtained from the SDK
  176. /// </param>
  177. /// <param name="mousePoint">
  178. ///The lowPoint obtained from the SDK.
  179. /// </param>
  180. /// <returns>
  181. /// Set error return false
  182. /// </returns>
  183. public bool SetCaretVisualArea(Point lowPoint, Point highPoint)
  184. {
  185. caretHeight = DpiHelper.PDFPointToStandardPoint(lowPoint);
  186. cursorPoint = DpiHelper.PDFPointToStandardPoint(highPoint);
  187. return true;
  188. }
  189. /// <summary>
  190. /// The low point of the cursor (96 DPI).
  191. /// </summary>
  192. /// <returns>
  193. /// The low point of the cursor (96 DPI).
  194. /// </returns>
  195. public Point GetCaretLowPoint()
  196. {
  197. return cursorPoint;
  198. }
  199. /// <summary>
  200. /// The high point of the cursor (96 DPI).
  201. /// </summary>
  202. /// <returns>
  203. /// The high point of the cursor (96 DPI).
  204. /// </returns>
  205. public Point GetCaretHighPoint()
  206. {
  207. return caretHeight;
  208. }
  209. /// <summary>
  210. /// Draw method.
  211. /// </summary>
  212. /// <param name="isLastShow">
  213. /// Indicates whether to immediately refresh
  214. /// </param>
  215. /// <param name="isShowCaret">
  216. /// Indicates whether to draw the cursor.
  217. /// </param>
  218. public void Draw(bool isLastShow, bool isShowCaret = true)
  219. {
  220. using (DrawingContext dc = RenderOpen())
  221. {
  222. RectangleGeometry clipGeometry = new RectangleGeometry();
  223. Point CaretPos = new Point(
  224. cursorPoint.X * currentZoom + paintOffset.X,
  225. cursorPoint.Y * currentZoom + paintOffset.Y);
  226. Point CaretHeight = new Point(
  227. caretHeight.X * currentZoom + paintOffset.X,
  228. caretHeight.Y * currentZoom + paintOffset.Y);
  229. if (isLastShow)
  230. {
  231. if (isShowCaret)
  232. {
  233. dc.DrawLine(drawParam.CaretPen, CaretPos, CaretHeight);
  234. }
  235. }
  236. foreach (Rect selectRect in selectRects)
  237. {
  238. Rect paintRect = new Rect(
  239. (int)(selectRect.X * currentZoom + paintOffset.X),
  240. (int)(selectRect.Y * currentZoom + paintOffset.Y),
  241. (int)(selectRect.Width * currentZoom),
  242. (int)(selectRect.Height * currentZoom));
  243. dc?.DrawRectangle(drawParam.CaretBrush, null, paintRect);
  244. }
  245. dc.Close();
  246. }
  247. lastShow = !isLastShow;
  248. }
  249. public void CleanDraw()
  250. {
  251. DrawingContext dc = RenderOpen();
  252. dc.Close();
  253. }
  254. public void CleanSelectRectDraw()
  255. {
  256. selectRects.Clear();
  257. Draw(true);
  258. }
  259. public void StopCaret()
  260. {
  261. caretTimer.Stop();
  262. }
  263. }
  264. }