using ComPDFKit.Import;
using ComPDFKit.PDFPage;
using ComPDFKit.PDFPage.Edit;
using ComPDFKit.Tool.SettingParam;
using ComPDFKit.Viewer.Helper;
using ComPDFKitViewer.Helper;
using System;
using System.Collections.Generic;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
namespace ComPDFKit.Tool.DrawTool
{
///
/// Use to draw the cursor and selected effect of text editing
///
internal class CaretVisual : DrawingVisual
{
#region Attributes
private Timer caretTimer;
protected DefaultDrawParam drawParam = new DefaultDrawParam();
private bool lastShow = true;
private Point caretHeight = new Point(0, 0);
private Point cursorPoint = new Point(0, 0);
private double currentZoom = 1;
private Rect paintOffset { get; set; }
///
/// Selected text's collection of drawn rectangles.
///
List selectRects { get; set; } = new List();
#endregion
#region Timer
public void StartTimer()
{
if (caretTimer.Enabled == false)
{
caretTimer.Start();
}
}
public void StopTimer()
{
caretTimer.Stop();
cursorPoint = new Point(0, 0);
caretHeight = new Point(0, 0);
currentZoom = 0;
paintOffset = new Rect();
}
private void CaretTimerElapsed(object sender, ElapsedEventArgs e)
{
if ((cursorPoint - caretHeight).Length > 0)
{
Dispatcher.InvokeAsync(() =>
{
Draw(lastShow);
});
}
}
#endregion
///
/// Re-locate the child elements
///
public void Arrange()
{
foreach (Visual child in Children)
{
if (!(child is UIElement))
{
continue;
}
UIElement checkChild = child as UIElement;
try
{
double left = Canvas.GetLeft(checkChild);
double top = Canvas.GetTop(checkChild);
double width = (double)checkChild.GetValue(FrameworkElement.WidthProperty);
double height = (double)checkChild.GetValue(FrameworkElement.HeightProperty);
checkChild.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
checkChild.Arrange(new Rect(
double.IsNaN(left) ? 0 : left,
double.IsNaN(top) ? 0 : top,
double.IsNaN(width) ? checkChild.DesiredSize.Width : width,
double.IsNaN(height) ? checkChild.DesiredSize.Height : height));
}
catch (Exception ex)
{
}
}
}
public CaretVisual(DefaultDrawParam defaultDrawParam)
{
caretTimer = new Timer(500);
caretTimer.Elapsed += CaretTimerElapsed;
caretTimer.AutoReset = true;
drawParam = defaultDrawParam;
}
///
/// Set the selected text effect area in text editing
///
///
/// Rect of PDF
///
public void SetSelectRect(List SelectLineRects)
{
selectRects.Clear();
for (int i = 0; i < SelectLineRects.Count; i++)
{
selectRects.Add(DpiHelper.PDFRectToStandardRect(SelectLineRects[i]));
}
}
public void SetZoom(double Zoom)
{
currentZoom = Zoom;
}
///
/// Set the current page drawing area (standard DPI)
///
///
/// The current page drawing area (standard DPI)
///
public void SetPaintOffset(Rect paintOffset)
{
this.paintOffset = paintOffset;
}
///
/// Set the current cursor position
///
///
/// Data object being edited
///
///
/// Current zoom factor
///
///
/// Current text box drawing area (standard DPI)
///
///
/// Current page drawing area (standard DPI)
///
///
/// Set error return false
///
public bool SetCaretVisualArea(CPDFEditArea EditArea, double Zoom, Rect paintOffset, Point mousePoint)
{
if (EditArea.Type == CPDFEditType.EditText)
{
cursorPoint = new Point(0, 0);
// Mouse coordinates on the current page (PDF).
Point pagePoint = new Point(((mousePoint.X - paintOffset.X) / Zoom),
((mousePoint.Y - paintOffset.Y) / Zoom));
// Call the SDK interface to set the coordinates and get the current cursor position and height
pagePoint = DpiHelper.StandardPointToPDFPoint(pagePoint);
(EditArea as CPDFEditTextArea).SelectCharItemAtPos(DataConversionForWPF.PointConversionForCPoint(pagePoint));
CPoint caretCPoint = new CPoint(0, 0);
CPoint HighCpoint = new CPoint(0, 0);
(EditArea as CPDFEditTextArea).GetTextCursorPoints(ref caretCPoint, ref HighCpoint);
Point caretPoint = DataConversionForWPF.CPointConversionForPoint(caretCPoint);
Point pointHigh = DataConversionForWPF.CPointConversionForPoint(HighCpoint);
// Converting SDK return values into data required for drawing
//CaretHeight = DpiHelper.PDFNumToStandardNum((caretPoint - pointHigh).Length);
//Rect caretRect = new Rect(caretPoint, pointHigh);
caretHeight = DpiHelper.PDFPointToStandardPoint(pointHigh);
cursorPoint = DpiHelper.PDFPointToStandardPoint(caretPoint);
currentZoom = Zoom;
this.paintOffset = paintOffset;
return true;
}
return false;
}
///
/// Set the current cursor position
///
///
/// The lowPoint obtained from the SDK
///
///
///The lowPoint obtained from the SDK.
///
///
/// Set error return false
///
public bool SetCaretVisualArea(Point lowPoint, Point highPoint)
{
caretHeight = DpiHelper.PDFPointToStandardPoint(lowPoint);
cursorPoint = DpiHelper.PDFPointToStandardPoint(highPoint);
return true;
}
///
/// The low point of the cursor (96 DPI).
///
///
/// The low point of the cursor (96 DPI).
///
public Point GetCaretLowPoint()
{
return cursorPoint;
}
///
/// The high point of the cursor (96 DPI).
///
///
/// The high point of the cursor (96 DPI).
///
public Point GetCaretHighPoint()
{
return caretHeight;
}
///
/// Draw method.
///
///
/// Indicates whether to immediately refresh
///
///
/// Indicates whether to draw the cursor.
///
public void Draw(bool isLastShow, bool isShowCaret = true)
{
using (DrawingContext dc = RenderOpen())
{
RectangleGeometry clipGeometry = new RectangleGeometry();
Point CaretPos = new Point(
cursorPoint.X * currentZoom + paintOffset.X,
cursorPoint.Y * currentZoom + paintOffset.Y);
Point CaretHeight = new Point(
caretHeight.X * currentZoom + paintOffset.X,
caretHeight.Y * currentZoom + paintOffset.Y);
if (isLastShow)
{
if (isShowCaret)
{
dc.DrawLine(drawParam.CaretPen, CaretPos, CaretHeight);
}
}
foreach (Rect selectRect in selectRects)
{
Rect paintRect = new Rect(
(int)(selectRect.X * currentZoom + paintOffset.X),
(int)(selectRect.Y * currentZoom + paintOffset.Y),
(int)(selectRect.Width * currentZoom),
(int)(selectRect.Height * currentZoom));
dc?.DrawRectangle(drawParam.CaretBrush, null, paintRect);
}
dc.Close();
}
lastShow = !isLastShow;
}
public void CleanDraw()
{
DrawingContext dc = RenderOpen();
dc.Close();
}
public void CleanSelectRectDraw()
{
selectRects.Clear();
Draw(true);
}
public void StopCaret()
{
caretTimer.Stop();
}
}
}