using ComPDFKit.Tool.SettingParam;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ComPDFKit.Tool.DrawTool
{
public enum MulitiDrawMoveType
{
Default,
Alone
}
public class MultiSelectedRect : DrawingVisual
{
///
/// Re-layout 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)
{
}
}
}
protected DefaultDrawParam drawParam = new DefaultDrawParam();
protected DrawingContext drawDC { get; set; }
///
/// DataChanging event
///
public event EventHandler DataChanging;
///
/// DataChanged event
///
public event EventHandler DataChanged;
protected SelectedType selectedType = SelectedType.None;
///
/// Minimum width of the rectangle
///
protected int rectMinWidth { get; set; } = 10;
///
/// Minimum height of the rectangle
///
protected int rectMinHeight { get; set; } = 10;
///
/// Identify whether the mouse is pressed
///
protected bool isMouseDown { get; set; }
///
/// Current hit control point
///
protected PointControlType hitControlType { get; set; }
///
/// Location information recorded when the mouse is pressed
///
protected Point mouseDownPoint { get; set; }
///
/// Current set ignore points
///
protected List ignorePoints { get; set; } = new List();
///
/// Current control point coordinates
///
protected List controlPoints { get; set; } = new List();
///
/// Move offset
///
protected Point moveOffset { get; set; } = new Point(0, 0);
///
/// Current PDFVIewer's actual display width
///
protected double PDFViewerActualWidth { get; set; } = 0;
///
/// Current PDFVIewer's actual display height
///
protected double PDFViewerActualHeight { get; set; } = 0;
///
/// Current control point drawing style
///
protected DrawPointType currentDrawPointType { get; set; }
///
/// Current drag drawing style
///
protected DrawMoveType currentDrawMoveType { get; set; }
///
/// Current multi-select drawing style
///
protected MulitiDrawMoveType currentDrawType { get; set; } = MulitiDrawMoveType.Default;
///
/// Control point size
///
protected int pointSize { get; set; } = 4;
///
/// Current drawing rectangle (calculated during operation)
///
protected Rect drawRect { get; set; } = new Rect(0, 0, 0, 0);
///
/// Default outermost rectangle of the drawing style (calculated during operation)
///
protected Rect drawDefaultRect { get; set; } = new Rect(0, 0, 0, 0);
///
/// Padding between the border and the content
///
protected double rectPadding = 5;
///
/// Mouse down cache rectangle
///
protected Rect cacheRect { get; set; } = new Rect(0, 0, 0, 0);
///
/// Current set drawing rectangle (original data)
///
protected Rect setDrawRect { get; set; } = new Rect(0, 0, 0, 0);
///
/// Maximum drawable range
///
protected Rect maxRect { get; set; } = new Rect(0, 0, 0, 0);
///
/// Identify whether the mouse is pressed
///
protected bool isProportionalScaling { get; set; } = false;
///
/// Array passed from outside for multiple selection
///
internal List selectedRects = new List();
protected Dictionary> RelationDict=new Dictionary>();
protected bool isHover = false;
protected bool isSelected = false;
public void SetIsHover(bool hover)
{
isHover = hover;
}
public bool GetIsHover()
{
return isHover;
}
public void SetIsSelected(bool selected)
{
isSelected = selected;
}
public bool GetIsSelected()
{
return isSelected;
}
public MultiSelectedRect(DefaultDrawParam defaultDrawParam, SelectedType type) : base()
{
drawParam = defaultDrawParam;
currentDrawPointType = DrawPointType.Circle;
selectedType = type;
}
public void SetMulitSelectedRect(SelectedRect selectedobject,int pageIndex,int editIndex)
{
selectedRects.Add(selectedobject);
RelationDict[selectedobject] = new KeyValuePair(pageIndex, editIndex);
}
public bool GetRelationKey(SelectedRect selectedobject,out int pageIndex,out int editIndex)
{
pageIndex = -1;
editIndex = -1;
if(RelationDict!=null && RelationDict.ContainsKey(selectedobject))
{
KeyValuePair relateData = RelationDict[selectedobject];
pageIndex = relateData.Key;
editIndex = relateData.Value;
return true;
}
return false;
}
///
/// delete
///
///
public void DelMulitSelectedRect(SelectedRect selectedobject)
{
selectedRects.Remove(selectedobject);
RelationDict.Remove(selectedobject);
}
///
/// get selectedRects Index
///
///
///
public int GetMulitSelectedRectIndex(SelectedRect selectedobject)
{
return selectedRects.IndexOf(selectedobject);
}
public List GetMulitSelectList()
{
return selectedRects==null ? new List() : selectedRects;
}
public SelectedType GetSelectedType()
{
return selectedType;
}
public void SetSelectedType(SelectedType type)
{
if (selectedType != type)
{
selectedRects.Clear();
RelationDict.Clear();
}
selectedType = type;
}
public void CleanMulitSelectedRect()
{
selectedRects.Clear();
RelationDict.Clear();
}
public virtual void OnMouseLeftButtonDown(Point downPoint)
{
isMouseDown = true;
hitControlType = PointControlType.None;
mouseDownPoint = downPoint;
moveOffset = new Point(0, 0);
HitTestResult hitResult = VisualTreeHelper.HitTest(this, downPoint);
if (hitResult != null && hitResult.VisualHit is DrawingVisual)
{
hitControlType = GetHitControlIndex(downPoint);
if (hitControlType != PointControlType.None)
{
cacheRect = drawRect;
}
}
}
public virtual void OnMouseLeftButtonUp(Point upPoint)
{
if (isMouseDown && hitControlType != PointControlType.None)
{
isMouseDown = false;
cacheRect = setDrawRect = drawRect;
Draw();
if ((int)upPoint.X != (int)mouseDownPoint.X || (int)upPoint.Y != (int)mouseDownPoint.Y)
{
InvokeDataChangEvent(true);
}
}
moveOffset = new Point(0, 0);
}
public virtual void OnMouseMove(Point mousePoint, out bool Tag, double width, double height)
{
PDFViewerActualWidth = width;
PDFViewerActualHeight = height;
Tag = false;
if (isMouseDown && hitControlType != PointControlType.None)
{
Tag = isMouseDown;
if (CalcHitPointMove(mousePoint))
{
Draw();
if ((int)mousePoint.X != (int)mouseDownPoint.X || (int)mousePoint.Y != (int)mouseDownPoint.Y)
{
InvokeDataChangEvent(false);
}
}
}
}
public float GetZoomX()
{
return (float)(drawRect.Width / drawDefaultRect.Width);
}
public float GetZoomY()
{
return (float)(drawRect.Height / drawDefaultRect.Height);
}
///
/// Multiple selection of movement distance
///
///
public float GetChangeX()
{
return (float)(drawRect.Width - drawDefaultRect.Width);
}
///
/// Multiple selection of movement distance
///
///
public float GetChangeY()
{
return (float)(drawRect.Height - drawDefaultRect.Height);
}
public void Draw()
{
switch (currentDrawType)
{
case MulitiDrawMoveType.Default:
Dispatcher.Invoke(() =>
{
if (drawDefaultRect.IsEmpty == false && drawDefaultRect.Width > 0 && drawDefaultRect.Height > 0)
{
drawDC = RenderOpen();
CalcControlPoint(drawDefaultRect);
SolidColorBrush solidColorBrush = drawParam.SPDFEditMultiRectFillBrush;
Pen pen = drawParam.SPDFEditMultiRectLinePen;
GetBrushAndPen(ref solidColorBrush, ref pen);
foreach (SelectedRect item in selectedRects)
{
if (!item.IsPath)
{
Rect rect = item.GetRect();
rect.X -= rectPadding;
rect.Y -= rectPadding;
rect.Width += rectPadding;
rect.Height += rectPadding;
drawDC?.DrawRectangle(solidColorBrush, pen, rect);
}
}
SolidColorBrush PointBrush = drawParam.PDFEditMultiPointBorderBrush;
Pen PointPen = drawParam.PDFEditMultiPointPen;
GetPointBrushAndPen(ref PointBrush, ref PointPen);
switch (currentDrawMoveType)
{
case DrawMoveType.kDefault:
break;
case DrawMoveType.kReferenceLine:
if (isMouseDown == true)
{
SolidColorBrush moveBrush = drawParam.PDFEditMultiMoveBrush;
Pen movepen = drawParam.PDFEditMultiMovePen;
GetMoveBrushAndPen(ref moveBrush, ref movepen);
if (selectedType == SelectedType.PDFEdit)
{
DrawMoveBounds(drawDC, hitControlType, movepen, moveBrush, drawRect, drawParam.PDFEditMultiMoveRectPen);
}
else
{
DrawMoveBounds(drawDC, hitControlType, movepen, moveBrush, drawRect);
}
}
drawDC?.DrawRectangle(solidColorBrush, pen, drawDefaultRect);
break;
default:
break;
}
switch (currentDrawPointType)
{
case DrawPointType.Circle:
if (selectedType == SelectedType.PDFEdit)
{
//Edit Settings Frame
DrawCirclePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
}
else
{
DrawCirclePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
}
break;
case DrawPointType.Square:
DrawSquarePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
break;
}
drawDC?.Close();
drawDC = null;
}
});
break;
case MulitiDrawMoveType.Alone:
CalcControlPoint(drawDefaultRect);
foreach (SelectedRect selectRect in selectedRects)
{
selectRect.Draw();
}
break;
default:
break;
}
}
private void GetMoveBrushAndPen(ref SolidColorBrush colorBrush, ref Pen pen)
{
switch (selectedType)
{
case SelectedType.None:
break;
case SelectedType.Annot:
//colorBrush = DrawParam.AnnotMoveBrush;
//pen = DrawParam.AnnotMovePen;
break;
case SelectedType.PDFEdit:
colorBrush = drawParam.PDFEditMultiMoveBrush;
pen = drawParam.PDFEditMultiMovePen;
break;
default:
break;
}
}
private void GetBrushAndPen(ref SolidColorBrush colorBrush, ref Pen pen)
{
switch (selectedType)
{
case SelectedType.None:
break;
case SelectedType.Annot:
//if (isHover)
//{
// colorBrush = DrawParam.AnnotRectFillBrush;
// pen = DrawParam.AnnotRectHoverPen;
//}
//else
//{
// colorBrush = DrawParam.AnnotRectFillBrush;
// pen = DrawParam.AnnotRectLinePen;
//}
break;
case SelectedType.PDFEdit:
if (isHover)
{
colorBrush = drawParam.PDFEditMultiRectFillHoverBrush;
pen = drawParam.PDFEditMultiRectLineHoverPen;
}
else
{
if (isSelected)
{
colorBrush = drawParam.SPDFEditMultiRectFillBrush;
pen = drawParam.SPDFEditMultiRectLinePen;
}
else
{
colorBrush = drawParam.PDFEditMultiRectFillBrush;
pen = drawParam.PDFEditMultiRectLinePen;
}
}
break;
default:
break;
}
}
private void GetPointBrushAndPen(ref SolidColorBrush colorBrush, ref Pen pen)
{
switch (selectedType)
{
case SelectedType.None:
break;
case SelectedType.Annot:
//colorBrush = DrawParam.AnnotPointBorderBrush;
//pen = DrawParam.AnnotPointPen;
break;
case SelectedType.PDFEdit:
if (isHover)
{
colorBrush = drawParam.PDFEditMultiRectFillHoverBrush;
pen = drawParam.PDFEditMultiPointHoverPen;
}
else
{
if (isSelected)
{
colorBrush = drawParam.SPDFEditMultiPointBorderBrush;
pen = drawParam.SPDFEditMultiPointPen;
}
else
{
colorBrush = drawParam.PDFEditMultiPointBorderBrush;
pen = drawParam.PDFEditMultiPointPen;
}
}
break;
default:
break;
}
}
///
/// Internal drawing circle point
///
///
/// Drawing context
///
///
///Collection of positions where points need to be drawn
///
///
/// Point size
///
///
/// Drawing point brush
///
///
/// Brush for drawing point border
///
protected void DrawCirclePoint(DrawingContext drawingContext, List ignoreList, int PointSize, Pen PointPen, SolidColorBrush BorderBrush)
{
GeometryGroup controlGroup = new GeometryGroup();
controlGroup.FillRule = FillRule.Nonzero;
List ignorePointsList = new List();
// Get specific points
foreach (PointControlType type in ignoreList)
{
if ((int)type < controlPoints.Count)
{
ignorePointsList.Add(controlPoints[(int)type]);
}
}
for (int i = 0; i < controlPoints.Count; i++)
{
Point controlPoint = controlPoints[i];
if (ignorePointsList.Contains(controlPoint))
{
continue;
}
EllipseGeometry circlPoint = new EllipseGeometry(controlPoint, PointSize, PointSize);
controlGroup.Children.Add(circlPoint);
}
drawingContext?.DrawGeometry(BorderBrush, PointPen, controlGroup);
}
///
/// Internal drawing square
///
///
/// Drawing context
///
///
/// Collection of positions where points need to be drawn
///
///
/// Size of the point
///
///
/// Brush for drawing point
///
///
/// Border brush for drawing points
///
protected void DrawSquarePoint(DrawingContext drawingContext, List ignoreList, int PointSize, Pen PointPen, SolidColorBrush BorderBrush)
{
GeometryGroup controlGroup = new GeometryGroup();
controlGroup.FillRule = FillRule.Nonzero;
List ignorePointsList = new List();
// Get specific points
foreach (PointControlType type in ignoreList)
{
if ((int)type < controlPoints.Count)
{
ignorePointsList.Add(controlPoints[(int)type]);
}
}
for (int i = 0; i < controlPoints.Count; i++)
{
Point controlPoint = controlPoints[i];
if (ignorePointsList.Contains(controlPoint))
{
continue;
}
RectangleGeometry rectPoint = new RectangleGeometry(new Rect(controlPoint.X - PointSize, controlPoint.Y - PointSize,
PointSize * 2, PointSize * 2), 1, 1);
controlGroup.Children.Add(rectPoint);
}
drawingContext?.DrawGeometry(BorderBrush, PointPen, controlGroup);
}
///
/// Draw the reference line in the moving state
///
///
/// Drawing context
///
///
/// Drawing context
///
///
/// Drawing context
///
///
/// Move brush
///
///
/// Move rectangle
///
protected void DrawMoveBounds(DrawingContext drawDc, PointControlType controltype, Pen activePen, Brush moveBrush, Rect moveRect, Pen RectPen = null)
{
switch (controltype)
{
case PointControlType.LeftTop:
drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
drawDc?.DrawLine(activePen, new Point(moveRect.Left, 0), new Point(moveRect.Left, PDFViewerActualHeight));
break;
case PointControlType.LeftMiddle:
drawDc?.DrawLine(activePen, new Point(moveRect.Left, 0), new Point(moveRect.Left, PDFViewerActualHeight));
break;
case PointControlType.LeftBottom:
drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
drawDc?.DrawLine(activePen, new Point(moveRect.Left, 0), new Point(moveRect.Left, PDFViewerActualHeight));
break;
case PointControlType.MiddlBottom:
drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
break;
case PointControlType.RightBottom:
drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
drawDc?.DrawLine(activePen, new Point(moveRect.Right, 0), new Point(moveRect.Right, PDFViewerActualHeight));
break;
case PointControlType.RightMiddle:
drawDc?.DrawLine(activePen, new Point(moveRect.Right, 0), new Point(moveRect.Right, PDFViewerActualHeight));
break;
case PointControlType.RightTop:
drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
drawDc?.DrawLine(activePen, new Point(moveRect.Right, 0), new Point(moveRect.Right, PDFViewerActualHeight));
break;
case PointControlType.MiddleTop:
drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
break;
case PointControlType.Rotate:
break;
case PointControlType.Body:
case PointControlType.Line:
drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(moveRect.Left, moveRect.Top));
drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
drawDc?.DrawLine(activePen, new Point(moveRect.Left, moveRect.Top), new Point(moveRect.Left, 0));
drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Top), new Point(moveRect.Right, 0));
drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(moveRect.Left, moveRect.Bottom));
drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
drawDc?.DrawLine(activePen, new Point(moveRect.Left, moveRect.Bottom), new Point(moveRect.Left, PDFViewerActualHeight));
drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Bottom), new Point(moveRect.Right, PDFViewerActualHeight));
break;
default:
break;
}
drawDc?.DrawRectangle(moveBrush, RectPen, moveRect);
}
public virtual void ClearDraw()
{
drawDefaultRect = setDrawRect = drawRect = new Rect();
drawDC = RenderOpen();
drawDC?.Close();
drawDC = null;
}
///
/// Calculate the current control point
///
///
/// Target rectangle where the control point is located
///
protected void CalcControlPoint(Rect currentRect)
{
controlPoints.Clear();
int centerX = (int)(currentRect.Left + currentRect.Right) / 2;
int centerY = (int)(currentRect.Top + currentRect.Bottom) / 2;
controlPoints.Add(new Point(currentRect.Left, currentRect.Top));
controlPoints.Add(new Point(currentRect.Left, centerY));
controlPoints.Add(new Point(currentRect.Left, currentRect.Bottom));
controlPoints.Add(new Point(centerX, currentRect.Bottom));
controlPoints.Add(new Point(currentRect.Right, currentRect.Bottom));
controlPoints.Add(new Point(currentRect.Right, centerY));
controlPoints.Add(new Point(currentRect.Right, currentRect.Top));
controlPoints.Add(new Point(centerX, currentRect.Top));
}
///
/// Get the original set Rect, not the one that has been calculated for padding
///
public Rect GetRect()
{
Rect rect = new Rect(drawRect.X + rectPadding, drawRect.Y + rectPadding, Math.Max(0, drawRect.Width - 2 * rectPadding), Math.Max(0, drawRect.Height - 2 * rectPadding));
return rect;
}
public void SetRect(Rect newRect)
{
newRect = new Rect(newRect.X - rectPadding, newRect.Y - rectPadding, newRect.Width + 2 * rectPadding, newRect.Height + 2 * rectPadding);
if (drawDefaultRect != new Rect())
{
newRect.Union(drawDefaultRect);
newRect.Intersect(maxRect);
}
drawDefaultRect = newRect;
setDrawRect = drawRect = newRect;
}
public void SetRectPadding(double rectPadding)
{
this.rectPadding = rectPadding;
}
public double GetRectPadding()
{
return rectPadding;
}
public Rect GetDrawRect()
{
return drawRect;
}
public void SetMaxRect(Rect rect)
{
maxRect = rect;
}
public Rect GetMaxRect()
{
return maxRect;
}
public void SetIsProportionalScaling(bool isProportionalScaling)
{
this.isProportionalScaling = isProportionalScaling;
}
public void SetDrawType(DrawPointType drawType)
{
currentDrawPointType = drawType;
}
public void SetDrawMoveType(DrawMoveType drawType)
{
currentDrawMoveType = drawType;
}
///
/// Set the type that needs to be ignored
///
///
/// Collection of point types that need to be shielded
///
public void SetIgnorePoints(List types)
{
ignorePoints.Clear();
foreach (PointControlType type in types)
{
ignorePoints.Add(type);
}
}
///
/// Set all points to be ignored
///
public void SetIgnorePointsAll()
{
ignorePoints.Clear();
ignorePoints.Add(PointControlType.LeftTop);
ignorePoints.Add(PointControlType.LeftMiddle);
ignorePoints.Add(PointControlType.LeftBottom);
ignorePoints.Add(PointControlType.MiddlBottom);
ignorePoints.Add(PointControlType.RightBottom);
ignorePoints.Add(PointControlType.RightMiddle);
ignorePoints.Add(PointControlType.RightTop);
ignorePoints.Add(PointControlType.MiddleTop);
}
///
/// Disable all functions
///
public void DisableAll()
{
ignorePoints.Clear();
ignorePoints.Add(PointControlType.LeftTop);
ignorePoints.Add(PointControlType.LeftMiddle);
ignorePoints.Add(PointControlType.LeftBottom);
ignorePoints.Add(PointControlType.MiddlBottom);
ignorePoints.Add(PointControlType.RightBottom);
ignorePoints.Add(PointControlType.RightMiddle);
ignorePoints.Add(PointControlType.RightTop);
ignorePoints.Add(PointControlType.MiddleTop);
ignorePoints.Add(PointControlType.Rotate);
ignorePoints.Add(PointControlType.Body);
ignorePoints.Add(PointControlType.Line);
}
///
/// Calculate the movement of the hit point
///
///
/// Current mouse position
///
///
protected bool CalcHitPointMove(Point mousePoint)
{
if (isMouseDown == false || hitControlType == PointControlType.None)
{
return false;
}
return NormalScaling(mousePoint);
}
///
/// Draw the algorithm of the normal scaling form (drag a point, only scale in one direction)
///
///
/// Current mouse position
///
///
protected bool NormalScaling(Point mousePoint)
{
double mLeft = cacheRect.Left;
double mRight = cacheRect.Right;
double mUp = cacheRect.Top;
double mDown = cacheRect.Bottom;
double TmpLeft = mLeft, TmpRight = mRight, TmpUp = mUp, TmpDown = mDown;
Point centerPoint = new Point((cacheRect.Right + cacheRect.Left) / 2, (cacheRect.Bottom + cacheRect.Top) / 2);
Point moveVector = (Point)(mousePoint - centerPoint);
moveVector = ProportionalScalingOffsetPos(moveVector);
switch (hitControlType)
{
case PointControlType.LeftTop:
TmpLeft = centerPoint.X + moveVector.X;
TmpRight = cacheRect.Right;
if (TmpLeft + rectMinWidth > TmpRight)
{
TmpLeft = TmpRight - rectMinWidth;
}
TmpUp = centerPoint.Y + moveVector.Y;
TmpDown = cacheRect.Bottom;
if (TmpUp + rectMinHeight > TmpDown)
{
TmpUp = TmpDown - rectMinHeight;
}
break;
case PointControlType.LeftMiddle:
TmpLeft = centerPoint.X + moveVector.X;
TmpRight = cacheRect.Right;
if (TmpLeft + rectMinWidth > TmpRight)
{
TmpLeft = TmpRight - rectMinWidth;
}
TmpUp = cacheRect.Top;
TmpDown = cacheRect.Bottom;
break;
case PointControlType.LeftBottom:
TmpLeft = centerPoint.X + moveVector.X;
TmpRight = cacheRect.Right;
if (TmpLeft + rectMinWidth > TmpRight)
{
TmpLeft = TmpRight - rectMinWidth;
}
TmpUp = cacheRect.Top;
TmpDown = centerPoint.Y + moveVector.Y;
if (TmpUp + rectMinHeight > TmpDown)
{
TmpDown = TmpUp + rectMinHeight;
}
break;
case PointControlType.MiddlBottom:
TmpLeft = cacheRect.Left;
TmpRight = cacheRect.Right;
TmpUp = cacheRect.Top;
TmpDown = centerPoint.Y + moveVector.Y;
if (TmpUp + rectMinHeight > TmpDown)
{
TmpDown = TmpUp + rectMinHeight;
}
break;
case PointControlType.RightBottom:
TmpLeft = cacheRect.Left;
TmpRight = centerPoint.X + moveVector.X;
if (TmpLeft + rectMinWidth > TmpRight)
{
TmpRight = TmpLeft + rectMinWidth;
}
TmpUp = cacheRect.Top;
TmpDown = centerPoint.Y + moveVector.Y;
if (TmpUp + rectMinHeight > TmpDown)
{
TmpDown = TmpUp + rectMinHeight;
}
break;
case PointControlType.RightMiddle:
TmpLeft = cacheRect.Left;
TmpRight = centerPoint.X + moveVector.X;
if (TmpLeft + rectMinWidth > TmpRight)
{
TmpRight = TmpLeft + rectMinWidth;
}
TmpUp = cacheRect.Top;
TmpDown = cacheRect.Bottom;
break;
case PointControlType.RightTop:
TmpLeft = cacheRect.Left;
TmpRight = centerPoint.X + moveVector.X;
if (TmpLeft + rectMinWidth > TmpRight)
{
TmpRight = TmpLeft + rectMinWidth;
}
TmpUp = centerPoint.Y + moveVector.Y;
TmpDown = cacheRect.Bottom;
if (TmpUp + rectMinHeight > TmpDown)
{
TmpUp = TmpDown - rectMinHeight;
}
break;
case PointControlType.MiddleTop:
TmpLeft = cacheRect.Left;
TmpRight = cacheRect.Right;
TmpUp = centerPoint.Y + moveVector.Y;
TmpDown = cacheRect.Bottom;
if (TmpUp + rectMinHeight > TmpDown)
{
TmpUp = TmpDown - rectMinHeight;
}
break;
case PointControlType.Body:
case PointControlType.Line:
Point OffsetPos = CalcMoveBound(cacheRect, ((Point)(mousePoint - mouseDownPoint)), maxRect);
TmpLeft = cacheRect.Left + OffsetPos.X;
TmpRight = cacheRect.Right + OffsetPos.X;
TmpUp = cacheRect.Top + OffsetPos.Y;
TmpDown = cacheRect.Bottom + OffsetPos.Y;
break;
default:
break;
}
if (TmpLeft < maxRect.Left)
{
TmpLeft = maxRect.Left;
}
if (TmpUp < maxRect.Top)
{
TmpUp = maxRect.Top;
}
if (TmpRight > maxRect.Right)
{
TmpRight = maxRect.Right;
}
if (TmpDown > maxRect.Bottom)
{
TmpDown = maxRect.Bottom;
}
if (TmpRight - TmpLeft < 0.0 || TmpDown - TmpUp < 0.0)
{
return false;
}
drawRect = new Rect(TmpLeft, TmpUp, TmpRight - TmpLeft, TmpDown - TmpUp);
moveOffset = new Point(drawRect.X - cacheRect.X, drawRect.Y - cacheRect.Y);
return true;
}
///
/// Proportional scaling offset calibration
///
///
/// Offset value
///
///
/// Offset value after calibration
///
protected Point ProportionalScalingOffsetPos(Point movePoint)
{
if (isProportionalScaling)
{
Point offsetPos = movePoint;
double ratioX = cacheRect.Width > 0 ? cacheRect.Height / cacheRect.Width : 1;
double ratioY = cacheRect.Height > 0 ? cacheRect.Width / cacheRect.Height : 1;
switch (hitControlType)
{
case PointControlType.LeftTop:
case PointControlType.RightBottom:
offsetPos = new Point(movePoint.X, Math.Abs(movePoint.X) * ratioX * (movePoint.X < 0 ? -1 : 1));
break;
case PointControlType.LeftBottom:
case PointControlType.RightTop:
offsetPos = new Point(movePoint.X, Math.Abs(movePoint.X) * ratioX * (movePoint.X < 0 ? 1 : -1));
break;
case PointControlType.LeftMiddle:
offsetPos = new Point(movePoint.X, Math.Abs(movePoint.X) * ratioX * (movePoint.X < 0 ? 1 : -1));
break;
case PointControlType.RightMiddle:
offsetPos = new Point(movePoint.X, Math.Abs(movePoint.X) * ratioX * (movePoint.X < 0 ? -1 : 1));
break;
case PointControlType.MiddlBottom:
offsetPos = new Point(Math.Abs(movePoint.Y) * ratioY * (movePoint.Y < 0 ? 1 : -1), movePoint.Y);
break;
case PointControlType.MiddleTop:
offsetPos = new Point(Math.Abs(movePoint.Y) * ratioY * (movePoint.Y < 0 ? -1 : 1), movePoint.Y);
break;
default:
break;
}
return offsetPos;
}
else
{
return movePoint;
}
}
///
/// Set left alignment within the set maximum rectangle
///
public virtual void SetAlignLeftForMaxRect()
{
DrawAlignRect(AlignmentsHelp.SetAlignLeft(drawRect, maxRect));
}
///
/// Set horizontal center alignment within the set maximum rectangle
///
public virtual void SetAlignHorizonCenterForMaxRect()
{
DrawAlignRect(AlignmentsHelp.SetAlignHorizonCenter(drawRect, maxRect));
}
///
/// Set right alignment within the set maximum rectangle
///
public virtual void SetAlignRightForMaxRect()
{
DrawAlignRect(AlignmentsHelp.SetAlignRight(drawRect, maxRect));
}
///
/// Set top alignment within the set maximum rectangle
///
public virtual void SetAlignTopForMaxRect()
{
DrawAlignRect(AlignmentsHelp.SetAlignTop(drawRect, maxRect));
}
///
/// Set vertical center alignment within the set maximum rectangle
///
public virtual void SetAlignVerticalCenterForMaxRect()
{
DrawAlignRect(AlignmentsHelp.SetAlignVerticalCenter(drawRect, maxRect));
}
///
/// Set Align center within the set maximum rectangle
///
public virtual void SetAlignHorizonVerticalCenterForMaxRect()
{
DrawAlignRect(AlignmentsHelp.SetAlignHorizonVerticalCenter(drawRect, maxRect));
}
///
/// Set bottom alignment within the set maximum rectangle
///
public virtual void SetAlignBottomForMaxRect()
{
DrawAlignRect(AlignmentsHelp.SetAlignBottom(drawRect, maxRect));
}
///
/// Draw the rectangle of the alignment function
///
///
/// Move distance required for the rectangle obtained by the alignment algorithm
///
private void DrawAlignRect(Point RectMovePoint)
{
double TmpLeft, TmpRight, TmpUp, TmpDown;
Point OffsetPos = CalcMoveBound(drawRect, RectMovePoint, maxRect);
TmpLeft = drawRect.Left + OffsetPos.X;
TmpRight = drawRect.Right + OffsetPos.X;
TmpUp = drawRect.Top + OffsetPos.Y;
TmpDown = drawRect.Bottom + OffsetPos.Y;
setDrawRect = drawRect = new Rect(TmpLeft, TmpUp, TmpRight - TmpLeft, TmpDown - TmpUp);
Draw();
}
///
/// Calculate the offset of the current rectangle within the maximum rectangle range
///
///
/// The rectangle cached when pressed
///
///
/// The offset value equivalent to when pressed
///
///
/// The maximum rectangle range
///
///
/// Offset value after calculation
///
protected Point CalcMoveBound(Rect currentRect, Point offsetPoint, Rect maxRect)
{
double cLeft = currentRect.Left;
double cRight = currentRect.Right;
double cUp = currentRect.Top;
double cDown = currentRect.Bottom;
double TmpLeft = cLeft + offsetPoint.X;
double TmpRight = cRight + offsetPoint.X;
double TmpUp = cUp + offsetPoint.Y;
double TmpDown = cDown + offsetPoint.Y;
if (TmpLeft < maxRect.Left)
{
TmpRight = (cRight - cLeft) + maxRect.Left;
TmpLeft = maxRect.Left;
}
if (TmpUp < maxRect.Top)
{
TmpDown = (cDown - cUp) + maxRect.Top;
TmpUp = maxRect.Top;
}
if (TmpRight > maxRect.Right)
{
TmpLeft = maxRect.Right - (cRight - cLeft);
TmpRight = maxRect.Right;
}
if (TmpDown > maxRect.Bottom)
{
TmpUp = maxRect.Bottom - (cDown - cUp);
TmpDown = maxRect.Bottom;
}
offsetPoint = new Point(TmpLeft - cLeft, TmpUp - cUp);
return offsetPoint;
}
///
/// Used for notification events during the drawing data process/completion.
///
///
/// Identifies whether the data has been changed
///
protected void InvokeDataChangEvent(bool isFinish)
{
if (isFinish)
{
DataChanged?.Invoke(this, moveOffset);
}
else
{
DataChanging?.Invoke(this, moveOffset);
}
}
///
/// Get the current set of ignored points
///
///
/// Dataset of ignored points
///
private List GetIgnorePoints()
{
List IgnorePointsList = new List();
foreach (PointControlType type in ignorePoints)
{
IgnorePointsList.Add(type);
}
return IgnorePointsList;
}
///
/// Get which control point the coordinate is on
///
///
/// Coordinate point
///
///
/// Control point type
///
public PointControlType GetHitControlIndex(Point point)
{
HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
if (hitResult != null && hitResult.VisualHit is DrawingVisual)
{
List ignoreList = GetIgnorePoints();
List IgnorePointsList = new List();
foreach (PointControlType type in ignoreList)
{
if ((int)type < controlPoints.Count)
{
IgnorePointsList.Add(controlPoints[(int)type]);
}
}
for (int i = 0; i < controlPoints.Count; i++)
{
Point checkPoint = controlPoints[i];
if (IgnorePointsList.Contains(checkPoint))
{
continue;
}
switch (currentDrawPointType)
{
case DrawPointType.Circle:
if (IgnorePointsList.Contains(checkPoint))
{
continue;
}
Vector checkVector = checkPoint - point;
double wlen = drawRect.Width;
if (wlen > 50)
{
wlen = 20;
}
else
{
wlen = wlen / 3;
}
double hlen = drawRect.Height;
if (hlen > 50)
{
hlen = 20;
}
else
{
hlen = wlen / 3;
}
if ((PointControlType)i == PointControlType.RightMiddle)
{
if (Math.Abs(point.X - checkPoint.X) < wlen && checkVector.Length < drawRect.Height / 3)
{
return (PointControlType)i;
}
}
if ((PointControlType)i == PointControlType.LeftMiddle)
{
if (Math.Abs(point.X - checkPoint.X) < wlen && checkVector.Length < drawRect.Height / 3)
{
return (PointControlType)i;
}
}
if ((PointControlType)i == PointControlType.MiddleTop)
{
if (Math.Abs(point.Y - checkPoint.Y) < hlen && checkVector.Length < drawRect.Width / 3)
{
return (PointControlType)i;
}
}
if ((PointControlType)i == PointControlType.MiddlBottom)
{
if (Math.Abs(point.Y - checkPoint.Y) < hlen && checkVector.Length < drawRect.Width / 3)
{
return (PointControlType)i;
}
}
if (checkVector.Length < pointSize)
{
return (PointControlType)i;
}
break;
case DrawPointType.Square:
Rect checkRect = new Rect(Math.Max(checkPoint.X - pointSize, 0), Math.Max(checkPoint.Y - pointSize, 0), pointSize * 2, pointSize * 2);
if (checkRect.Contains(point))
{
return (PointControlType)i;
}
break;
default:
break;
}
}
Rect defrect = drawRect;
defrect.X -= rectPadding;
defrect.Y -= rectPadding;
defrect.Width += rectPadding;
defrect.Height += rectPadding;
if (drawRect.Contains(point))
{
Rect rect = new Rect(
Math.Max(drawRect.X + rectPadding, 0),
Math.Max(drawRect.Y + rectPadding, 0),
drawRect.Width - 2 * rectPadding,
drawRect.Height - 2 * rectPadding);
if (rect.Contains(point))
{
if (!ignoreList.Contains(PointControlType.Body))
{
return PointControlType.Body;
}
}
if (!ignoreList.Contains(PointControlType.Body))
{
return PointControlType.Line;
}
}
}
return PointControlType.None;
}
///
/// Get the rectangle where the current point is located
///
///
/// Coordinate point
///
///
/// Control point type
///
public SelectedRect GetHitControlRect(Point point)
{
HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
if (hitResult != null && hitResult.VisualHit is DrawingVisual)
{
foreach (SelectedRect selectedRect in selectedRects) {
Rect defrect = selectedRect.GetRect();
defrect.X -= rectPadding;
defrect.Y -= rectPadding;
defrect.Width += rectPadding;
defrect.Height += rectPadding;
if (defrect.Contains(point))
{
Rect rect = new Rect(
Math.Max(defrect.X + rectPadding, 0),
Math.Max(defrect.Y + rectPadding, 0),
defrect.Width - 2 * rectPadding,
defrect.Height - 2 * rectPadding);
if (rect.Contains(point))
{
return selectedRect;
}
}
}
}
return null;
}
}
}