CPDFViewerTool.AnnotSelector.cs 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. using ComPDFKit.Import;
  2. using ComPDFKit.PDFAnnotation;
  3. using ComPDFKit.PDFAnnotation.Form;
  4. using ComPDFKit.Tool.DrawTool;
  5. using ComPDFKit.Tool.Help;
  6. using ComPDFKit.Tool.UndoManger;
  7. using ComPDFKitViewer;
  8. using ComPDFKitViewer.BaseObject;
  9. using ComPDFKitViewer.Helper;
  10. using ComPDFKitViewer.Layer;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Linq;
  14. using System.Windows;
  15. using System.Windows.Input;
  16. using System.Windows.Media;
  17. namespace ComPDFKit.Tool
  18. {
  19. public partial class CPDFViewerTool
  20. {
  21. private class AnnotSelectAreaData
  22. {
  23. public Point HitAreaPos { get; set; }
  24. public Point MoveAreaPos { get; set; }
  25. public Rect HitAreaBound { get; set; }
  26. public int HitPageIndex { get; set; } = -1;
  27. }
  28. private int AnnotSelectorIndex { get; set; } = -1;
  29. private AnnotSelector Selector { get; set; }
  30. private AnnotSelectAreaData AreaDrawData { get; set; } = new AnnotSelectAreaData();
  31. private AnnotSelectAreaData AreaMoveData { get; set; } = new AnnotSelectAreaData();
  32. private bool DrawSelect { get; set; } = true;
  33. private bool AllowMultiSelect { get; set; }
  34. private bool AllowAreaSelect { get; set; }
  35. private bool IsMoved { get; set; } = false;
  36. private Point OffsetPos { get; set; } = new Point(0, 0);
  37. private List<AnnotParam> AnnotParamList { get; set; } = new List<AnnotParam>();
  38. private void AnnotSelectInsert()
  39. {
  40. Selector = new AnnotSelector();
  41. Selector.PDFViewer = PDFViewer;
  42. int annotViewindex = PDFViewer.GetMaxViewIndex();
  43. PDFViewer.InsertView(annotViewindex, Selector);
  44. AnnotSelectorIndex = Selector.GetResTag();
  45. }
  46. private void AnnotSelectUpdate()
  47. {
  48. if (!AllowMultiSelect)
  49. {
  50. return;
  51. }
  52. if (Selector == null || Selector.SelectAnnots == null)
  53. {
  54. return;
  55. }
  56. if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null)
  57. {
  58. Selector?.ClearItem();
  59. Selector?.CleanDraw();
  60. return;
  61. }
  62. List<AnnotData> annotDatas = PDFViewer.CurrentRenderFrame.AnnotDataList;
  63. if (annotDatas == null || annotDatas.Count == 0)
  64. {
  65. return;
  66. }
  67. foreach (AnnotData checkItem in Selector.SelectAnnots.ToList())
  68. {
  69. AnnotData saveItem = annotDatas.Where(x => x.PageIndex == checkItem.PageIndex && x.AnnotIndex == checkItem.AnnotIndex).FirstOrDefault();
  70. if (saveItem != null)
  71. {
  72. Selector.RemoveItem(checkItem);
  73. Selector.AddItem(saveItem);
  74. }
  75. }
  76. }
  77. public void SetAnnotAllowMultiSelect(bool isAllow)
  78. {
  79. AllowMultiSelect = isAllow;
  80. AllowAreaSelect = isAllow;
  81. }
  82. private void AnnotSelectDraw()
  83. {
  84. if (!AllowMultiSelect)
  85. {
  86. return;
  87. }
  88. if (DrawSelect == false)
  89. {
  90. return;
  91. }
  92. if (Selector?.GetSelectCount() > 1)
  93. {
  94. Selector?.Draw();
  95. return;
  96. }
  97. Selector?.CleanDraw();
  98. }
  99. private void AnnotSelectAddItem(AnnotData annotData, bool clean = true)
  100. {
  101. if (!AllowMultiSelect || annotData == null)
  102. {
  103. return;
  104. }
  105. if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
  106. {
  107. if (Selector?.HasItem(annotData) == true)
  108. {
  109. if (Selector?.GetSelectCount() != 1)
  110. {
  111. Selector?.RemoveItem(annotData);
  112. }
  113. }
  114. else
  115. {
  116. Selector?.AddItem(annotData);
  117. }
  118. return;
  119. }
  120. if (clean)
  121. {
  122. Selector?.ClearItem();
  123. //Selector?.AddItem(annotData);
  124. }
  125. }
  126. private void AnnotSelectAreaHit()
  127. {
  128. if (!AllowMultiSelect)
  129. {
  130. return;
  131. }
  132. AreaDrawData.HitPageIndex = -1;
  133. if (PDFViewer == null || Selector == null || !AllowAreaSelect)
  134. {
  135. return;
  136. }
  137. AreaDrawData.HitAreaPos = Mouse.GetPosition(PDFViewer);
  138. AreaDrawData.MoveAreaPos = AreaDrawData.HitAreaPos;
  139. PDFViewer.GetPointPageInfo(AreaDrawData.HitAreaPos, out int pageIndex, out Rect paintRect, out Rect pageBound);
  140. if (pageIndex >= 0)
  141. {
  142. AreaDrawData.HitPageIndex = pageIndex;
  143. AreaDrawData.HitAreaBound = pageBound;
  144. PDFViewer.CanHorizontallyScroll = false;
  145. PDFViewer.CanVerticallyScroll = false;
  146. PDFViewer.EnableZoom(false);
  147. DrawSelect = false;
  148. }
  149. }
  150. private void AnnotSelectMoveHit()
  151. {
  152. if (!AllowMultiSelect)
  153. {
  154. return;
  155. }
  156. AreaMoveData.HitPageIndex = -1;
  157. if (PDFViewer == null || Selector == null)
  158. {
  159. return;
  160. }
  161. AreaMoveData.HitAreaPos = Mouse.GetPosition(PDFViewer);
  162. AreaMoveData.MoveAreaPos = AreaMoveData.HitAreaPos;
  163. PDFViewer.GetPointPageInfo(AreaMoveData.HitAreaPos, out int pageIndex, out Rect paintRect, out Rect pageBound);
  164. if (pageIndex >= 0)
  165. {
  166. AreaMoveData.HitPageIndex = pageIndex;
  167. AreaMoveData.HitAreaBound = pageBound;
  168. }
  169. }
  170. private void AnnotSelectAreaDraw()
  171. {
  172. if (!AllowMultiSelect)
  173. {
  174. return;
  175. }
  176. if (AreaDrawData.HitPageIndex < 0 || PDFViewer == null || Selector == null)
  177. {
  178. return;
  179. }
  180. AreaDrawData.MoveAreaPos = Mouse.GetPosition(PDFViewer);
  181. Rect moveRect = new Rect(AreaDrawData.HitAreaPos, AreaDrawData.MoveAreaPos);
  182. moveRect.Intersect(AreaDrawData.HitAreaBound);
  183. DrawingContext drawDC = Selector.RenderOpen();
  184. drawDC.DrawRectangle(Selector.DrawBrush, Selector.DrawPen, moveRect);
  185. drawDC.Close();
  186. }
  187. private bool AnnotSelectAreaSelect(bool onlyWidget = false, bool onlyAnnot = false)
  188. {
  189. if (!AllowMultiSelect)
  190. {
  191. return false;
  192. }
  193. if (AreaDrawData.HitPageIndex < 0 || PDFViewer == null || Selector == null)
  194. {
  195. return false;
  196. }
  197. PDFViewer.CanHorizontallyScroll = true;
  198. PDFViewer.CanVerticallyScroll = true;
  199. PDFViewer.EnableZoom(true);
  200. Selector.ClearItem();
  201. Selector.CleanDraw();
  202. AreaDrawData.HitPageIndex = -1;
  203. DrawSelect = true;
  204. if (PDFViewer.CurrentRenderFrame != null && PDFViewer.CurrentRenderFrame.AnnotDataList != null)
  205. {
  206. Rect areaRect = new Rect(AreaDrawData.HitAreaPos, AreaDrawData.MoveAreaPos);
  207. areaRect.Intersect(AreaDrawData.HitAreaBound);
  208. foreach (AnnotData checkItem in PDFViewer.CurrentRenderFrame.AnnotDataList)
  209. {
  210. if (onlyWidget && checkItem.AnnotType != C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET)
  211. {
  212. continue;
  213. }
  214. if (onlyAnnot && checkItem.AnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET)
  215. {
  216. continue;
  217. }
  218. if (areaRect.IntersectsWith(checkItem.PaintRect))
  219. {
  220. Selector.AddItem(checkItem);
  221. }
  222. }
  223. Selector.Draw();
  224. }
  225. return true;
  226. }
  227. private BaseAnnot AnnotSelectGetAnnot()
  228. {
  229. if (PDFViewer != null && Selector != null && Selector.SelectAnnots != null && Selector.SelectAnnots.Count == 1)
  230. {
  231. AnnotData annotData = Selector.SelectAnnots[0];
  232. BaseLayer checkLayer = PDFViewer.GetViewForTag(PDFViewer.GetAnnotViewTag());
  233. if (checkLayer != null && checkLayer is AnnotLayer)
  234. {
  235. AnnotLayer annotLayer = (AnnotLayer)checkLayer;
  236. return annotLayer.GetAnnotForIndex(annotData.PageIndex, annotData.AnnotIndex);
  237. }
  238. }
  239. return null;
  240. }
  241. public List<AnnotData> GetAnnotSelectsData()
  242. {
  243. if (PDFViewer != null && Selector != null && Selector.SelectAnnots != null && Selector.SelectAnnots.Count >= 1)
  244. {
  245. return Selector.SelectAnnots;
  246. }
  247. return null;
  248. }
  249. public AnnotSelector GetAnnotSelectsRect()
  250. {
  251. if (PDFViewer != null && Selector != null && Selector.SelectAnnots != null && Selector.SelectAnnots.Count >= 1)
  252. {
  253. return Selector;
  254. }
  255. return null;
  256. }
  257. private int AnnotSelectGetCount()
  258. {
  259. if (Selector != null)
  260. {
  261. return Selector.GetSelectCount();
  262. }
  263. return 0;
  264. }
  265. private void AnnotSelectAreaHover()
  266. {
  267. if (!AllowMultiSelect)
  268. {
  269. return;
  270. }
  271. if (PDFViewer == null || Selector == null || Selector.GetSelectCount() < 2)
  272. {
  273. return;
  274. }
  275. Point movePos = Mouse.GetPosition(PDFViewer);
  276. PointControlType hitPoint = Selector.GetHitControlIndex(movePos);
  277. Cursor oldCursor = this.Cursor;
  278. Cursor newCursor = this.Cursor;
  279. switch (hitPoint)
  280. {
  281. case PointControlType.LeftTop:
  282. case PointControlType.RightBottom:
  283. newCursor = Cursors.SizeNWSE;
  284. break;
  285. case PointControlType.LeftMiddle:
  286. case PointControlType.RightMiddle:
  287. newCursor = Cursors.SizeWE;
  288. break;
  289. case PointControlType.LeftBottom:
  290. case PointControlType.RightTop:
  291. newCursor = Cursors.SizeNESW;
  292. break;
  293. case PointControlType.MiddleBottom:
  294. case PointControlType.MiddleTop:
  295. newCursor = Cursors.SizeNS;
  296. break;
  297. case PointControlType.Body:
  298. newCursor = Cursors.SizeAll;
  299. break;
  300. default:
  301. newCursor = Cursors.Arrow;
  302. break;
  303. }
  304. if (oldCursor != newCursor)
  305. {
  306. PDFViewer.Cursor = newCursor;
  307. this.Cursor = newCursor;
  308. }
  309. }
  310. private bool AnnotSelectAreaHitTest()
  311. {
  312. if (!AllowMultiSelect)
  313. {
  314. return false;
  315. }
  316. if (PDFViewer == null || Selector == null || Selector.GetSelectCount() < 2)
  317. {
  318. return false;
  319. }
  320. Point movePos = Mouse.GetPosition(PDFViewer);
  321. HitTestResult hitResult = VisualTreeHelper.HitTest(PDFViewer, movePos);
  322. if (hitResult != null && hitResult.VisualHit is AnnotSelector)
  323. {
  324. return true;
  325. }
  326. return false;
  327. }
  328. private bool AnnotSelectMoveDraw()
  329. {
  330. if (!AllowMultiSelect)
  331. {
  332. return false;
  333. }
  334. if (AreaMoveData.HitPageIndex < 0 || PDFViewer == null || Selector == null || Selector.GetSelectCount() < 2)
  335. {
  336. return false;
  337. }
  338. if (Mouse.LeftButton != MouseButtonState.Pressed)
  339. {
  340. return false;
  341. }
  342. Point movePos = Mouse.GetPosition(PDFViewer);
  343. Point moveOffset = new Point(movePos.X - AreaMoveData.HitAreaPos.X, movePos.Y - AreaMoveData.HitAreaPos.Y);
  344. PointControlType hitPointType = Selector.GetHitControlIndex(AreaMoveData.HitAreaPos);
  345. switch (hitPointType)
  346. {
  347. default:
  348. case PointControlType.None:
  349. return false;
  350. case PointControlType.Body:
  351. AnnotSelectMove();
  352. return true;
  353. case PointControlType.LeftTop:
  354. case PointControlType.LeftMiddle:
  355. case PointControlType.LeftBottom:
  356. case PointControlType.MiddleBottom:
  357. case PointControlType.RightBottom:
  358. case PointControlType.RightMiddle:
  359. case PointControlType.RightTop:
  360. case PointControlType.MiddleTop:
  361. if (CanResize(hitPointType, moveOffset, Selector.GetOutBoundRect(), AreaMoveData.HitAreaBound))
  362. {
  363. AnnotSelectResize(hitPointType, moveOffset, Selector.GetOutBoundRect(), AreaMoveData.HitAreaBound);
  364. }
  365. return true;
  366. }
  367. }
  368. private void AnnotSelectMove()
  369. {
  370. Point movePos = Mouse.GetPosition(PDFViewer);
  371. Vector offset = movePos - AreaMoveData.HitAreaPos;
  372. Rect boundRect = Selector.GetOutBoundRect();
  373. Point boundCenter = new Point(boundRect.Left + boundRect.Width / 2, boundRect.Top + boundRect.Height / 2);
  374. Point moveCenter = new Point(boundCenter.X + offset.X, boundCenter.Y + offset.Y);
  375. moveCenter.X = Math.Max(AreaMoveData.HitAreaBound.Left + boundRect.Width / 2, moveCenter.X);
  376. moveCenter.X = Math.Min(AreaMoveData.HitAreaBound.Right - boundRect.Width / 2, moveCenter.X);
  377. moveCenter.Y = Math.Max(AreaMoveData.HitAreaBound.Top + boundRect.Height / 2, moveCenter.Y);
  378. moveCenter.Y = Math.Min(AreaMoveData.HitAreaBound.Bottom - boundRect.Height / 2, moveCenter.Y);
  379. Rect moveRect = new Rect(moveCenter.X - boundRect.Width / 2, moveCenter.Y - boundRect.Height / 2, boundRect.Width, boundRect.Height);
  380. OffsetPos = new Point(moveCenter.X - boundCenter.X, moveCenter.Y - boundCenter.Y);
  381. DrawingContext drawDC = Selector.RenderOpen();
  382. Selector.DrawOutBound(drawDC);
  383. Selector.DrawIndividual(drawDC);
  384. Selector.DrawControlPoint(drawDC);
  385. drawDC.DrawRectangle(Selector.DrawBrush, Selector.DrawPen, moveRect);
  386. foreach (AnnotData checkItem in Selector.SelectAnnots)
  387. {
  388. Rect childRect = new Rect(checkItem.PaintRect.X + OffsetPos.X, checkItem.PaintRect.Y + OffsetPos.Y, checkItem.PaintRect.Width, checkItem.PaintRect.Height);
  389. drawDC.DrawRectangle(Selector.DrawBrush, Selector.DrawPen, childRect);
  390. }
  391. drawDC.Close();
  392. }
  393. private void AnnotSelectResize(PointControlType controlType, Point moveOffset, Rect maxRect, Rect boundRect)
  394. {
  395. if (maxRect == Rect.Empty || maxRect.Width == 0 || maxRect.Height == 0)
  396. {
  397. return;
  398. }
  399. double ratioX = maxRect.Width > 0 ? maxRect.Height / maxRect.Width : 1;
  400. double ratioY = maxRect.Height > 0 ? maxRect.Width / maxRect.Height : 1;
  401. Point offsetPos = moveOffset;
  402. switch (controlType)
  403. {
  404. case PointControlType.LeftTop:
  405. case PointControlType.RightBottom:
  406. offsetPos = new Point(moveOffset.X, Math.Abs(moveOffset.X) * ratioX * (moveOffset.X < 0 ? -1 : 1));
  407. break;
  408. case PointControlType.LeftBottom:
  409. case PointControlType.RightTop:
  410. offsetPos = new Point(moveOffset.X, Math.Abs(moveOffset.X) * ratioX * (moveOffset.X < 0 ? 1 : -1));
  411. break;
  412. case PointControlType.LeftMiddle:
  413. offsetPos = new Point(moveOffset.X, Math.Abs(moveOffset.X) * ratioX * (moveOffset.X < 0 ? 1 : -1));
  414. break;
  415. case PointControlType.RightMiddle:
  416. offsetPos = new Point(moveOffset.X, Math.Abs(moveOffset.X) * ratioX * (moveOffset.X < 0 ? -1 : 1));
  417. break;
  418. case PointControlType.MiddleBottom:
  419. offsetPos = new Point(Math.Abs(moveOffset.Y) * ratioY * (moveOffset.Y < 0 ? 1 : -1), moveOffset.Y);
  420. break;
  421. case PointControlType.MiddleTop:
  422. offsetPos = new Point(Math.Abs(moveOffset.Y) * ratioY * (moveOffset.Y < 0 ? -1 : 1), moveOffset.Y);
  423. break;
  424. }
  425. OffsetPos = offsetPos;
  426. double left = maxRect.Left;
  427. double top = maxRect.Top;
  428. double right = maxRect.Right;
  429. double bottom = maxRect.Bottom;
  430. switch (controlType)
  431. {
  432. case PointControlType.LeftTop://左上
  433. left += offsetPos.X;
  434. top += offsetPos.Y;
  435. break;
  436. case PointControlType.LeftMiddle://左中
  437. left += offsetPos.X;
  438. top -= offsetPos.Y / 2;
  439. bottom += offsetPos.Y / 2;
  440. break;
  441. case PointControlType.LeftBottom://左下
  442. left += offsetPos.X;
  443. bottom += offsetPos.Y;
  444. break;
  445. case PointControlType.MiddleBottom://中下
  446. bottom += offsetPos.Y;
  447. left += offsetPos.X / 2;
  448. right -= offsetPos.X / 2;
  449. break;
  450. case PointControlType.RightBottom://右下
  451. right += offsetPos.X;
  452. bottom += offsetPos.Y;
  453. break;
  454. case PointControlType.RightMiddle://右中
  455. right += offsetPos.X;
  456. top -= offsetPos.Y / 2;
  457. bottom += offsetPos.Y / 2;
  458. break;
  459. case PointControlType.RightTop://右上
  460. right += offsetPos.X;
  461. top += offsetPos.Y;
  462. break;
  463. case PointControlType.MiddleTop://中上
  464. top += offsetPos.Y;
  465. left += offsetPos.X / 2;
  466. right -= offsetPos.X / 2;
  467. break;
  468. default:
  469. break;
  470. }
  471. Rect newRect = new Rect(new Point(left, top), new Point(right, bottom));
  472. DrawingContext drawDC = Selector.RenderOpen();
  473. Selector.DrawOutBound(drawDC);
  474. Selector.DrawIndividual(drawDC);
  475. Selector.DrawControlPoint(drawDC);
  476. drawDC.DrawRectangle(Selector.DrawBrush, Selector.DrawPen, newRect);
  477. foreach (AnnotData checkItem in Selector.SelectAnnots)
  478. {
  479. double distanceLeft = checkItem.PaintRect.Left - maxRect.Left;
  480. double newLeft = newRect.Width * distanceLeft / maxRect.Width + newRect.Left;
  481. double distanceRight = maxRect.Right - checkItem.PaintRect.Right;
  482. double newRight = newRect.Right - newRect.Width / maxRect.Width * distanceRight;
  483. double distanceTop = checkItem.PaintRect.Top - maxRect.Top;
  484. double newTop = newRect.Height * distanceTop / maxRect.Height + newRect.Top;
  485. double distanceBottom = maxRect.Bottom - checkItem.PaintRect.Bottom;
  486. double newBottom = newRect.Bottom - newRect.Height / maxRect.Height * distanceBottom;
  487. Rect newClient = new Rect(newLeft, newTop, newRight - newLeft, newBottom - newTop);
  488. if (newClient != Rect.Empty && newClient.Width > 0 && newClient.Height > 0)
  489. {
  490. drawDC.DrawRectangle(Selector.DrawBrush, Selector.DrawPen, newClient);
  491. }
  492. }
  493. drawDC.Close();
  494. }
  495. private bool CanResize(PointControlType controlType, Point moveOffset, Rect maxRect, Rect boundRect)
  496. {
  497. if (maxRect == Rect.Empty || maxRect.Width == 0 || maxRect.Height == 0)
  498. {
  499. return false;
  500. }
  501. double ratioX = maxRect.Width > 0 ? maxRect.Height / maxRect.Width : 1;
  502. double ratioY = maxRect.Height > 0 ? maxRect.Width / maxRect.Height : 1;
  503. Point offsetPos = moveOffset;
  504. switch (controlType)
  505. {
  506. case PointControlType.LeftTop:
  507. case PointControlType.RightBottom:
  508. offsetPos = new Point(moveOffset.X, Math.Abs(moveOffset.X) * ratioX * (moveOffset.X < 0 ? -1 : 1));
  509. break;
  510. case PointControlType.LeftBottom:
  511. case PointControlType.RightTop:
  512. offsetPos = new Point(moveOffset.X, Math.Abs(moveOffset.X) * ratioX * (moveOffset.X < 0 ? 1 : -1));
  513. break;
  514. case PointControlType.LeftMiddle:
  515. offsetPos = new Point(moveOffset.X, Math.Abs(moveOffset.X) * ratioX * (moveOffset.X < 0 ? 1 : -1));
  516. break;
  517. case PointControlType.RightMiddle:
  518. offsetPos = new Point(moveOffset.X, Math.Abs(moveOffset.X) * ratioX * (moveOffset.X < 0 ? -1 : 1));
  519. break;
  520. case PointControlType.MiddleBottom:
  521. offsetPos = new Point(Math.Abs(moveOffset.Y) * ratioY * (moveOffset.Y < 0 ? 1 : -1), moveOffset.Y);
  522. break;
  523. case PointControlType.MiddleTop:
  524. offsetPos = new Point(Math.Abs(moveOffset.Y) * ratioY * (moveOffset.Y < 0 ? -1 : 1), moveOffset.Y);
  525. break;
  526. }
  527. double left = maxRect.Left;
  528. double top = maxRect.Top;
  529. double right = maxRect.Right;
  530. double bottom = maxRect.Bottom;
  531. switch (controlType)
  532. {
  533. case PointControlType.LeftTop://左上
  534. left += offsetPos.X;
  535. top += offsetPos.Y;
  536. break;
  537. case PointControlType.LeftMiddle://左中
  538. left += offsetPos.X;
  539. top -= offsetPos.Y / 2;
  540. bottom += offsetPos.Y / 2;
  541. break;
  542. case PointControlType.LeftBottom://左下
  543. left += offsetPos.X;
  544. bottom += offsetPos.Y;
  545. break;
  546. case PointControlType.MiddleBottom://中下
  547. bottom += offsetPos.Y;
  548. left += offsetPos.X / 2;
  549. right -= offsetPos.X / 2;
  550. break;
  551. case PointControlType.RightBottom://右下
  552. right += offsetPos.X;
  553. bottom += offsetPos.Y;
  554. break;
  555. case PointControlType.RightMiddle://右中
  556. right += offsetPos.X;
  557. top -= offsetPos.Y / 2;
  558. bottom += offsetPos.Y / 2;
  559. break;
  560. case PointControlType.RightTop://右上
  561. right += offsetPos.X;
  562. top += offsetPos.Y;
  563. break;
  564. case PointControlType.MiddleTop://中上
  565. top += offsetPos.Y;
  566. left += offsetPos.X / 2;
  567. right -= offsetPos.X / 2;
  568. break;
  569. default:
  570. break;
  571. }
  572. Rect newRect = new Rect(new Point(left, top), new Point(right, bottom));
  573. if (newRect.Left < boundRect.Left || newRect.Top < boundRect.Top || newRect.Bottom > boundRect.Bottom || newRect.Right > boundRect.Right)
  574. {
  575. return false;
  576. }
  577. return true;
  578. }
  579. private void AnnotSelectSave()
  580. {
  581. if (!AllowMultiSelect)
  582. {
  583. return;
  584. }
  585. if (AreaMoveData.HitPageIndex < 0 || PDFViewer == null || Selector == null || Selector.GetSelectCount() < 2)
  586. {
  587. return;
  588. }
  589. if (!IsMoved)
  590. {
  591. return;
  592. }
  593. PointControlType hitPointType = Selector.GetHitControlIndex(AreaMoveData.HitAreaPos);
  594. switch (hitPointType)
  595. {
  596. default:
  597. case PointControlType.None:
  598. return;
  599. case PointControlType.Body:
  600. AnnotSelectMoveSave();
  601. PDFViewer?.UpdateRenderFrame();
  602. return;
  603. case PointControlType.LeftTop:
  604. case PointControlType.LeftMiddle:
  605. case PointControlType.LeftBottom:
  606. case PointControlType.MiddleBottom:
  607. case PointControlType.RightBottom:
  608. case PointControlType.RightMiddle:
  609. case PointControlType.RightTop:
  610. case PointControlType.MiddleTop:
  611. AnnotSelectResizeSave(hitPointType, OffsetPos, Selector.GetOutBoundRect(), AreaMoveData.HitAreaBound);
  612. PDFViewer?.UpdateRenderFrame();
  613. return;
  614. }
  615. }
  616. private void AnnotSelectMoveSave()
  617. {
  618. GroupHistory historyGroup = new GroupHistory();
  619. var list = new List<C_ANNOTATION_TYPE>() { C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT, C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE, C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY, C_ANNOTATION_TYPE.C_ANNOTATION_STRIKEOUT, C_ANNOTATION_TYPE.C_ANNOTATION_LINK , C_ANNOTATION_TYPE.C_ANNOTATION_REDACT };
  620. foreach (AnnotData checkItem in Selector.SelectAnnots)
  621. {
  622. if (checkItem.Annot == null || checkItem.Annot.IsValid() == false)
  623. {
  624. continue;
  625. }
  626. if (list.Contains(checkItem.Annot.Type))
  627. {
  628. continue;
  629. }
  630. Rect childRect = new Rect(checkItem.PaintRect.X + OffsetPos.X, checkItem.PaintRect.Y + OffsetPos.Y, checkItem.PaintRect.Width, checkItem.PaintRect.Height);
  631. Rect saveRect = new Rect(
  632. childRect.Left - checkItem.PaintOffset.Left + checkItem.CropLeft * checkItem.CurrentZoom,
  633. childRect.Top - checkItem.PaintOffset.Top + checkItem.CropTop * checkItem.CurrentZoom,
  634. childRect.Width,
  635. childRect.Height);
  636. Rect noZoomRect = new Rect(
  637. saveRect.Left / checkItem.CurrentZoom,
  638. saveRect.Top / checkItem.CurrentZoom,
  639. saveRect.Width / checkItem.CurrentZoom,
  640. saveRect.Height / checkItem.CurrentZoom);
  641. Rect rawRect = DpiHelper.StandardRectToPDFRect(noZoomRect);
  642. AnnotHistory historyItem = ParamConverter.CreateHistory(checkItem.Annot);
  643. AnnotParam prevParam = ParamConverter.CPDFDataConverterToAnnotParam(PDFViewer.GetDocument(), checkItem.PageIndex, checkItem.Annot);
  644. checkItem.Annot.SetRect(new CRect((float)rawRect.Left, (float)rawRect.Bottom, (float)rawRect.Right, (float)rawRect.Top));
  645. AnnotParam currentParam = ParamConverter.CPDFDataConverterToAnnotParam(PDFViewer.GetDocument(), checkItem.PageIndex, checkItem.Annot);
  646. historyItem.PreviousParam = prevParam;
  647. historyItem.CurrentParam = currentParam;
  648. historyItem.Action = HistoryAction.Update;
  649. historyItem.PDFDoc = PDFViewer.GetDocument();
  650. historyGroup.Histories.Add(historyItem);
  651. }
  652. if (historyGroup.Histories.Count > 0 && PDFViewer != null)
  653. {
  654. PDFViewer.UndoManager?.AddHistory(historyGroup);
  655. PDFViewer.UpdateAnnotFrame();
  656. }
  657. }
  658. private void AnnotSelectResizeSave(PointControlType controlType, Point offsetPos, Rect maxRect, Rect boundRect)
  659. {
  660. double left = maxRect.Left;
  661. double top = maxRect.Top;
  662. double right = maxRect.Right;
  663. double bottom = maxRect.Bottom;
  664. switch (controlType)
  665. {
  666. case PointControlType.LeftTop://左上
  667. left += offsetPos.X;
  668. top += offsetPos.Y;
  669. break;
  670. case PointControlType.LeftMiddle://左中
  671. left += offsetPos.X;
  672. top -= offsetPos.Y / 2;
  673. bottom += offsetPos.Y / 2;
  674. break;
  675. case PointControlType.LeftBottom://左下
  676. left += offsetPos.X;
  677. bottom += offsetPos.Y;
  678. break;
  679. case PointControlType.MiddleBottom://中下
  680. bottom += offsetPos.Y;
  681. left += offsetPos.X / 2;
  682. right -= offsetPos.X / 2;
  683. break;
  684. case PointControlType.RightBottom://右下
  685. right += offsetPos.X;
  686. bottom += offsetPos.Y;
  687. break;
  688. case PointControlType.RightMiddle://右中
  689. right += offsetPos.X;
  690. top -= offsetPos.Y / 2;
  691. bottom += offsetPos.Y / 2;
  692. break;
  693. case PointControlType.RightTop://右上
  694. right += offsetPos.X;
  695. top += offsetPos.Y;
  696. break;
  697. case PointControlType.MiddleTop://中上
  698. top += offsetPos.Y;
  699. left += offsetPos.X / 2;
  700. right -= offsetPos.X / 2;
  701. break;
  702. default:
  703. break;
  704. }
  705. Rect newRect = new Rect(new Point(left, top), new Point(right, bottom));
  706. GroupHistory historyGroup = new GroupHistory();
  707. foreach (AnnotData checkItem in Selector.SelectAnnots)
  708. {
  709. if (checkItem.Annot == null || checkItem.Annot.IsValid() == false)
  710. {
  711. continue;
  712. }
  713. double distanceLeft = checkItem.PaintRect.Left - maxRect.Left;
  714. double newLeft = newRect.Width * distanceLeft / maxRect.Width + newRect.Left;
  715. double distanceRight = maxRect.Right - checkItem.PaintRect.Right;
  716. double newRight = newRect.Right - newRect.Width / maxRect.Width * distanceRight;
  717. double distanceTop = checkItem.PaintRect.Top - maxRect.Top;
  718. double newTop = newRect.Height * distanceTop / maxRect.Height + newRect.Top;
  719. double distanceBottom = maxRect.Bottom - checkItem.PaintRect.Bottom;
  720. double newBottom = newRect.Bottom - newRect.Height / maxRect.Height * distanceBottom;
  721. Rect newClient = new Rect(newLeft, newTop, newRight - newLeft, newBottom - newTop);
  722. if (newClient != Rect.Empty && newClient.Width > 0 && newClient.Height > 0)
  723. {
  724. Rect saveRect = new Rect(
  725. newClient.Left - checkItem.PaintOffset.Left + checkItem.CropLeft * checkItem.CurrentZoom,
  726. newClient.Top - checkItem.PaintOffset.Top + checkItem.CropTop * checkItem.CurrentZoom,
  727. newClient.Width,
  728. newClient.Height);
  729. Rect noZoomRect = new Rect(
  730. saveRect.Left / checkItem.CurrentZoom,
  731. saveRect.Top / checkItem.CurrentZoom,
  732. saveRect.Width / checkItem.CurrentZoom,
  733. saveRect.Height / checkItem.CurrentZoom);
  734. Rect rawRect = DpiHelper.StandardRectToPDFRect(noZoomRect);
  735. AnnotHistory historyItem = ParamConverter.CreateHistory(checkItem.Annot);
  736. AnnotParam prevParam = ParamConverter.CPDFDataConverterToAnnotParam(PDFViewer.GetDocument(), checkItem.PageIndex, checkItem.Annot);
  737. checkItem.Annot.SetRect(new CRect((float)rawRect.Left, (float)rawRect.Bottom, (float)rawRect.Right, (float)rawRect.Top));
  738. AnnotParam currentParam = ParamConverter.CPDFDataConverterToAnnotParam(PDFViewer.GetDocument(), checkItem.PageIndex, checkItem.Annot);
  739. historyItem.PreviousParam = prevParam;
  740. historyItem.CurrentParam = currentParam;
  741. historyItem.Action = HistoryAction.Update;
  742. historyItem.PDFDoc = PDFViewer.GetDocument();
  743. historyGroup.Histories.Add(historyItem);
  744. }
  745. }
  746. if (historyGroup.Histories.Count > 0 && PDFViewer != null)
  747. {
  748. PDFViewer.UndoManager?.AddHistory(historyGroup);
  749. PDFViewer.UpdateAnnotFrame();
  750. }
  751. }
  752. private void AnnotSelectClean()
  753. {
  754. Selector?.CleanDraw();
  755. Selector?.ClearItem();
  756. }
  757. private bool AnnotSelectCommandSupport(RoutedUICommand uiCmd)
  758. {
  759. if (!AllowMultiSelect)
  760. {
  761. return false;
  762. }
  763. if (uiCmd == null || PDFViewer == null || Selector == null)
  764. {
  765. return false;
  766. }
  767. switch (uiCmd.Name)
  768. {
  769. case "Copy":
  770. case "Cut":
  771. case "Delete":
  772. return Selector.GetSelectCount() >= 2;
  773. case "Paste":
  774. return AnnotParamList.Count() >= 2;
  775. default:
  776. break;
  777. }
  778. return false;
  779. }
  780. private void AnnotSelectCommandExecute(RoutedUICommand uiCmd)
  781. {
  782. if (!AllowMultiSelect)
  783. {
  784. return;
  785. }
  786. if (uiCmd == null || string.IsNullOrEmpty(uiCmd.Name) || PDFViewer == null || Selector == null)
  787. {
  788. return;
  789. }
  790. switch (uiCmd.Name)
  791. {
  792. case "Copy":
  793. AnnotSelectCopy();
  794. break;
  795. case "Cut":
  796. AnnotSelectCopy();
  797. AnnotSelectDelete();
  798. break;
  799. case "Delete":
  800. AnnotSelectDelete();
  801. break;
  802. case "Paste":
  803. AnnotSelectPaste();
  804. break;
  805. default:
  806. return;
  807. }
  808. }
  809. private void AnnotSelectCopy()
  810. {
  811. AnnotParamList?.Clear();
  812. if (!AllowMultiSelect)
  813. {
  814. return;
  815. }
  816. if (Selector.GetSelectCount() < 2)
  817. {
  818. return;
  819. }
  820. foreach (AnnotData checkItem in Selector.SelectAnnots)
  821. {
  822. if (checkItem == null || checkItem.Annot == null || checkItem.Annot.IsValid() == false)
  823. {
  824. continue;
  825. }
  826. AnnotParam prevParam = ParamConverter.CPDFDataConverterToAnnotParam(PDFViewer.GetDocument(), checkItem.PageIndex, checkItem.Annot);
  827. if (prevParam == null)
  828. {
  829. continue;
  830. }
  831. AnnotParamList.Add(prevParam);
  832. }
  833. }
  834. private void AnnotSelectDelete()
  835. {
  836. if (!AllowMultiSelect)
  837. {
  838. return;
  839. }
  840. if (Selector.GetSelectCount() < 2)
  841. {
  842. return;
  843. }
  844. GroupHistory historyGroup = new GroupHistory();
  845. Dictionary<AnnotHistory, CPDFAnnotation> removeDict = new Dictionary<AnnotHistory, CPDFAnnotation>();
  846. foreach (AnnotData checkItem in Selector.SelectAnnots)
  847. {
  848. if (checkItem == null || checkItem.Annot == null || checkItem.Annot.IsValid() == false)
  849. {
  850. continue;
  851. }
  852. AnnotHistory historyItem = ParamConverter.CreateHistory(checkItem.Annot);
  853. AnnotParam prevParam = ParamConverter.CPDFDataConverterToAnnotParam(PDFViewer.GetDocument(), checkItem.PageIndex, checkItem.Annot);
  854. if (prevParam == null || historyItem == null)
  855. {
  856. continue;
  857. }
  858. historyItem.CurrentParam = prevParam;
  859. historyItem.Action = HistoryAction.Remove;
  860. historyItem.PDFDoc = PDFViewer.GetDocument();
  861. removeDict[historyItem] = checkItem.Annot;
  862. }
  863. foreach (AnnotHistory annotKey in removeDict.Keys)
  864. {
  865. CPDFAnnotation removeAnnot = removeDict[annotKey];
  866. if (removeAnnot.RemoveAnnot())
  867. {
  868. historyGroup.Histories.Add(annotKey);
  869. }
  870. }
  871. if (historyGroup.Histories.Count > 0)
  872. {
  873. CleanSelectedRect();
  874. AnnotSelectClean();
  875. PDFViewer?.UndoManager.AddHistory(historyGroup);
  876. PDFViewer?.UpdateAnnotFrame();
  877. PDFViewer?.UpdateRenderFrame();
  878. }
  879. }
  880. private void AnnotSelectPaste()
  881. {
  882. if (!AllowMultiSelect)
  883. {
  884. return;
  885. }
  886. double left = 0;
  887. double right = 0;
  888. double top = 0;
  889. double bottom = 0;
  890. Point point = rightPressPoint;
  891. rightPressPoint = new Point(-1, -1);
  892. for (int i = 0; i < AnnotParamList.Count; i++)
  893. {
  894. AnnotParam checkParam = AnnotParamList[i];
  895. if (i == 0)
  896. {
  897. left = checkParam.ClientRect.left;
  898. top = checkParam.ClientRect.top;
  899. bottom = checkParam.ClientRect.bottom;
  900. right = checkParam.ClientRect.right;
  901. continue;
  902. }
  903. left = Math.Min(left, checkParam.ClientRect.left);
  904. right = Math.Max(right, checkParam.ClientRect.right);
  905. top = Math.Min(top, checkParam.ClientRect.top);
  906. bottom = Math.Max(bottom, checkParam.ClientRect.bottom);
  907. }
  908. Point offsetPos = new Point(25, 25);
  909. PDFViewer.GetPointPageInfo(point, out int pageIndex, out Rect paintRect, out Rect pageBound);
  910. if (pageIndex >= 0)
  911. {
  912. Point zoomPoint = new Point((point.X - pageBound.X) / currentZoom, (point.Y - pageBound.Y) / currentZoom);
  913. Point rawPoint = DpiHelper.StandardPointToPDFPoint(zoomPoint);
  914. double rawWidth = DpiHelper.StandardNumToPDFNum(pageBound.Width / currentZoom);
  915. double rawHeight = DpiHelper.StandardNumToPDFNum(pageBound.Height / currentZoom);
  916. offsetPos = new Point(rawPoint.X, rawPoint.Y);
  917. if (rawPoint.X + right - left > rawWidth)
  918. {
  919. offsetPos.X = rawWidth + left - right;
  920. }
  921. if (rawPoint.Y + bottom - top > rawHeight)
  922. {
  923. offsetPos.Y = rawHeight + top - bottom;
  924. }
  925. }
  926. GroupHistory historyGroup = new GroupHistory();
  927. foreach (AnnotParam annotParam in AnnotParamList)
  928. {
  929. AnnotParam cloneItem = CloneAnnotParam(annotParam);
  930. if (cloneItem == null)
  931. {
  932. continue;
  933. }
  934. Rect saveRect = new Rect(cloneItem.ClientRect.left, cloneItem.ClientRect.top, cloneItem.ClientRect.width(), cloneItem.ClientRect.height());
  935. saveRect.X = saveRect.Left - left + offsetPos.X;
  936. saveRect.Y = saveRect.Top - top + offsetPos.Y;
  937. cloneItem.PageIndex = pageIndex;
  938. cloneItem.ClientRect = new CRect((float)saveRect.Left, (float)saveRect.Bottom, (float)saveRect.Right, (float)saveRect.Top);
  939. AnnotHistory historyItem = ParamConverter.CreateHistory(annotParam);
  940. historyItem.CurrentParam = cloneItem;
  941. historyItem.PDFDoc = PDFViewer.GetDocument();
  942. historyItem.Add();
  943. historyGroup.Histories.Add(historyItem);
  944. }
  945. if (historyGroup.Histories.Count > 0 && PDFViewer != null)
  946. {
  947. CleanSelectedRect();
  948. AnnotSelectClean();
  949. PDFViewer.UndoManager?.AddHistory(historyGroup);
  950. PDFViewer.UpdateAnnotFrame();
  951. }
  952. }
  953. private AnnotParam CloneAnnotParam(AnnotParam oldParam)
  954. {
  955. if (oldParam != null)
  956. {
  957. AnnotParam newParam = new AnnotParam();
  958. switch (oldParam.CurrentType)
  959. {
  960. case C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE:
  961. newParam = new CircleParam();
  962. oldParam.CopyTo(newParam);
  963. break;
  964. case C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT:
  965. newParam = new FreeTextParam();
  966. oldParam.CopyTo(newParam);
  967. break;
  968. case C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT:
  969. newParam = new HighlightParam();
  970. oldParam.CopyTo(newParam);
  971. break;
  972. case C_ANNOTATION_TYPE.C_ANNOTATION_INK:
  973. newParam = new InkParam();
  974. oldParam.CopyTo(newParam);
  975. break;
  976. case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
  977. newParam = new LineParam();
  978. oldParam.CopyTo(newParam);
  979. break;
  980. case C_ANNOTATION_TYPE.C_ANNOTATION_LINK:
  981. newParam = new LinkParam();
  982. oldParam.CopyTo(newParam);
  983. break;
  984. case C_ANNOTATION_TYPE.C_ANNOTATION_CARET:
  985. newParam = new RedactParam();
  986. oldParam.CopyTo(newParam);
  987. break;
  988. case C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE:
  989. newParam = new SquareParam();
  990. oldParam.CopyTo(newParam);
  991. break;
  992. case C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY:
  993. newParam = new SquareParam();
  994. oldParam.CopyTo(newParam);
  995. break;
  996. case C_ANNOTATION_TYPE.C_ANNOTATION_STAMP:
  997. newParam = new StampParam();
  998. oldParam.CopyTo(newParam);
  999. break;
  1000. case C_ANNOTATION_TYPE.C_ANNOTATION_TEXT:
  1001. newParam = new StickyNoteParam();
  1002. oldParam.CopyTo(newParam);
  1003. break;
  1004. case C_ANNOTATION_TYPE.C_ANNOTATION_STRIKEOUT:
  1005. newParam = new StickyNoteParam();
  1006. oldParam.CopyTo(newParam);
  1007. break;
  1008. case C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE:
  1009. newParam = new UnderlineParam();
  1010. oldParam.CopyTo(newParam);
  1011. break;
  1012. case C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET:
  1013. WidgetParm widgetParam = oldParam as WidgetParm;
  1014. if (widgetParam != null)
  1015. {
  1016. switch (widgetParam.WidgetType)
  1017. {
  1018. case C_WIDGET_TYPE.WIDGET_CHECKBOX:
  1019. newParam = new CheckBoxParam();
  1020. oldParam.CopyTo(newParam);
  1021. break;
  1022. case C_WIDGET_TYPE.WIDGET_COMBOBOX:
  1023. newParam = new ComboBoxParam();
  1024. oldParam.CopyTo(newParam);
  1025. break;
  1026. case C_WIDGET_TYPE.WIDGET_LISTBOX:
  1027. newParam = new ListBoxParam();
  1028. oldParam.CopyTo(newParam);
  1029. break;
  1030. case C_WIDGET_TYPE.WIDGET_PUSHBUTTON:
  1031. newParam = new PushButtonParam();
  1032. oldParam.CopyTo(newParam);
  1033. break;
  1034. case C_WIDGET_TYPE.WIDGET_RADIOBUTTON:
  1035. newParam = new RadioButtonParam();
  1036. oldParam.CopyTo(newParam);
  1037. break;
  1038. case C_WIDGET_TYPE.WIDGET_SIGNATUREFIELDS:
  1039. newParam = new SignatureParam();
  1040. oldParam.CopyTo(newParam);
  1041. break;
  1042. case C_WIDGET_TYPE.WIDGET_TEXTFIELD:
  1043. newParam = new TextBoxParam();
  1044. oldParam.CopyTo(newParam);
  1045. break;
  1046. default:
  1047. return null;
  1048. }
  1049. }
  1050. break;
  1051. default:
  1052. return null;
  1053. }
  1054. return newParam;
  1055. }
  1056. return null;
  1057. }
  1058. }
  1059. }