OutLineControlViewModel.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. using ComPDFKit.PDFDocument;
  2. using ComPDFKit.PDFDocument.Action;
  3. using ComPDFKit.PDFPage;
  4. using ComPDFKitViewer.PdfViewer;
  5. using PDF_Office.Model;
  6. using PDF_Office.Model.BOTA;
  7. using Prism.Commands;
  8. using Prism.Mvvm;
  9. using Prism.Regions;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Collections.ObjectModel;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. using System.Windows;
  17. using System.Windows.Controls;
  18. using System.Windows.Media;
  19. using System.Windows.Media.Imaging;
  20. namespace PDF_Office.ViewModels.BOTA
  21. {
  22. class OutLineControlViewModel : BindableBase, INavigationAware
  23. {
  24. private string PageDefaultName = "";
  25. //缩略图相关全局变量,减少内存申请次数
  26. private WriteableBitmap WirteBitmap;
  27. private byte[] bmpData;
  28. private CPDFViewer PDFViewer;
  29. public ObservableCollection<OutlineNode> Outlinelist { get; set; }
  30. private bool isInsertHead = false;
  31. /// <summary>
  32. /// 是否为插入最顶部
  33. /// </summary>
  34. public bool IsInsertHead
  35. {
  36. get { return isInsertHead; }
  37. set
  38. {
  39. SetProperty(ref isInsertHead, value);
  40. }
  41. }
  42. private bool isOnDrop = false;
  43. public bool IsOnDrop
  44. {
  45. get { return isOnDrop; }
  46. set { isOnDrop = value; }
  47. }
  48. public DelegateCommand<ObservableCollection<OutlineNode>> CollapseAllCommand { get; set; }
  49. public DelegateCommand<ObservableCollection<OutlineNode>> ExpandAllCommand { get; set; }
  50. public DelegateCommand DeleteAllCommand { get; set; }
  51. public DelegateCommand<OutlineNode> DowngradeCommand { get; set; }
  52. public OutLineControlViewModel()
  53. {
  54. Outlinelist = new ObservableCollection<OutlineNode>();
  55. DeleteAllCommand = new DelegateCommand(DeleteAll);
  56. CollapseAllCommand = new DelegateCommand<ObservableCollection<OutlineNode>>(CollapseAll);
  57. ExpandAllCommand = new DelegateCommand<ObservableCollection<OutlineNode>>(ExpandAll);
  58. }
  59. public bool IsNavigationTarget(NavigationContext navigationContext)
  60. {
  61. return true;
  62. }
  63. public void OnNavigatedFrom(NavigationContext navigationContext)
  64. {
  65. return;
  66. }
  67. public void OnNavigatedTo(NavigationContext navigationContext)
  68. {
  69. navigationContext.Parameters.TryGetValue<CPDFViewer>(ParameterNames.PDFViewer, out PDFViewer);
  70. if (PDFViewer == null)
  71. {
  72. return;
  73. }
  74. List<CPDFOutline> datasource = PDFViewer.Document.GetOutlineList();
  75. Outlinelist.Clear();
  76. foreach (CPDFOutline item in datasource)
  77. {
  78. OutlineNode dto = ConvertCPDFToOutlineNode(item, null, false);
  79. if (dto != null)
  80. {
  81. Outlinelist.Add(dto);
  82. }
  83. }
  84. PDFViewer.GetCreateOutLineInfo();
  85. }
  86. /// <summary>
  87. /// 更新大纲数据,并保存状态设置为true
  88. /// </summary>
  89. public void Updata(bool IsMoveData)
  90. {
  91. PDFViewer.Document.ReleaseOutlineList();
  92. ObservableCollection<OutlineNode> list = new ObservableCollection<OutlineNode>();
  93. List<CPDFOutline> datasource = PDFViewer.Document.GetOutlineList();
  94. //遍历,转换UI状态存入临时数组
  95. foreach (CPDFOutline item in datasource)
  96. {
  97. OutlineNode dto = ConvertCPDFToOutlineNode(item, null, IsMoveData);
  98. if (dto != null)
  99. {
  100. list.Add(dto);
  101. }
  102. }
  103. //清空绑定数组,并填充新数据
  104. Outlinelist.Clear();
  105. foreach (OutlineNode item in list)
  106. {
  107. Outlinelist.Add(item);
  108. }
  109. PDFViewer.UndoManager.CanSave = true;
  110. }
  111. /// <summary>
  112. /// 设置当前大纲对象的Title
  113. /// </summary>
  114. public bool SetTitle(CPDFOutline cPDFOutline, string Title)
  115. {
  116. if (cPDFOutline == null)
  117. {
  118. return false;
  119. }
  120. return cPDFOutline.SetTitle(Title);
  121. }
  122. /// <summary>
  123. /// 跳转到指定位置或者URL动作
  124. /// </summary>
  125. public void GoToPage(TreeViewItem treeViewItem)
  126. {
  127. OutlineNode outline = treeViewItem.DataContext as OutlineNode;
  128. if (outline == null)
  129. {
  130. return;
  131. }
  132. CPDFAction action = outline.Outline.GetAction();
  133. if (action != null && action.ActionType != C_ACTION_TYPE.ACTION_TYPE_UNKNOWN)
  134. PDFViewer.ProcessAction(action);
  135. else
  136. {
  137. Size size = PDFViewer.Document.GetPageSize(Convert.ToInt32(outline.PageIndex) - 1);
  138. PDFViewer.GoToPage(Convert.ToInt32(outline.PageIndex) - 1, new Point(size.Width - outline.PositionX, size.Height - outline.PositionY));
  139. }
  140. }
  141. /// <summary>
  142. /// 收起所有展开
  143. /// </summary>
  144. public void CollapseAll(ObservableCollection<OutlineNode> outlineNodes)
  145. {
  146. foreach (var item in outlineNodes)
  147. {
  148. item.IsExpanded = false;
  149. if (item.Chlidlist.Count > 0)
  150. {
  151. CollapseAll(item.Chlidlist);
  152. }
  153. }
  154. }
  155. /// <summary>
  156. /// 展开所有大纲
  157. /// </summary>
  158. public void ExpandAll(ObservableCollection<OutlineNode> outlineNodes)
  159. {
  160. foreach (var item in outlineNodes)
  161. {
  162. item.IsExpanded = true;
  163. if (item.Chlidlist.Count > 0)
  164. {
  165. ExpandAll(item.Chlidlist);
  166. }
  167. }
  168. }
  169. /// <summary>
  170. /// 更改目标位置
  171. /// </summary>
  172. public void ChangeOutLineDestination(OutlineNode outline)
  173. {
  174. List<TextSelectNode> textSelectNodes = PDFViewer.GetCreateOutLineInfo();
  175. CPDFDestination info = new CPDFDestination();
  176. info.PageIndex = textSelectNodes[0].PageIndex;
  177. Size size = PDFViewer.Document.GetPageSize(textSelectNodes[0].PageIndex);
  178. info.Position_X = (float)(size.Width - textSelectNodes[0].StartPoint.X);
  179. info.Position_Y = (float)(size.Height - textSelectNodes[0].StartPoint.Y);
  180. outline.Outline.SetDestination(PDFViewer.Document, info);
  181. Updata(false);
  182. }
  183. /// <summary>
  184. /// 添加大纲
  185. /// </summary>
  186. public int AddOutLine(OutlineNode outline)
  187. {
  188. int ItemIndex = 0;
  189. List<TextSelectNode> textSelectNodes = PDFViewer.GetCreateOutLineInfo();
  190. CPDFDestination info = new CPDFDestination();
  191. if (textSelectNodes.Count <= 0)
  192. {
  193. //SDK出错了
  194. return -1;
  195. }
  196. info.PageIndex = textSelectNodes[0].PageIndex;
  197. info.Position_X = (float)textSelectNodes[0].StartPoint.X;
  198. info.Position_Y = (float)textSelectNodes[0].StartPoint.Y;
  199. CPDFOutline dto = null;
  200. //当前有选中大纲列表
  201. if (outline != null)
  202. {
  203. CPDFOutline parentoutline = outline.Outline.GetParent();
  204. if (parentoutline == null)
  205. {
  206. //获取父级失败,直接添加在根节点最下方
  207. PDFViewer.Document.GetOutlineList();
  208. CPDFOutline parent = PDFViewer.Document.GetOutlineRoot();
  209. if (!parent.InsertChildAtIndex(PDFViewer.Document, parent.ChildList.Count, ref dto))
  210. {
  211. //SDK出错了
  212. return -1;
  213. }
  214. ItemIndex = parent.ChildList.Count;
  215. }
  216. else
  217. {
  218. //获取父节点成功,添加在父节点中选中项下方
  219. int index = GetOutlinesIndexFormParent(parentoutline, outline.Outline);
  220. parentoutline.InsertChildAtIndex(PDFViewer.Document, index, ref dto);
  221. ItemIndex = index + 1;
  222. }
  223. }
  224. else
  225. {
  226. //未选中数据,直接添加在根节点最下方
  227. PDFViewer.Document.GetOutlineList();
  228. CPDFOutline parent = PDFViewer.Document.GetOutlineRoot();
  229. if (!parent.InsertChildAtIndex(PDFViewer.Document, parent.ChildList.Count, ref dto))
  230. {
  231. //SDK出错了
  232. return -1;
  233. }
  234. ItemIndex = parent.ChildList.Count;
  235. }
  236. ///当前没有选中文字
  237. if (string.IsNullOrEmpty(textSelectNodes[0].SelectText))
  238. {
  239. string addPageName = PageDefaultName + (textSelectNodes[0].PageIndex + 1).ToString();
  240. if (!dto.SetTitle(addPageName))
  241. {
  242. //SDK出错了
  243. return -1;
  244. }
  245. }
  246. else
  247. {
  248. string addPageName = PageDefaultName + textSelectNodes[0].SelectText;
  249. if (!dto.SetTitle(addPageName))
  250. {
  251. //SDK出错了
  252. return -1;
  253. }
  254. }
  255. dto.SetDestination(PDFViewer.Document, info);
  256. Updata(false);
  257. return ItemIndex;
  258. }
  259. /// <summary>
  260. /// 删除所有大纲
  261. /// </summary>
  262. public void DeleteAll()
  263. {
  264. foreach (var item in Outlinelist)
  265. {
  266. item.Outline.RemoveFromParent(this.PDFViewer.Document);
  267. }
  268. Updata(false);
  269. }
  270. /// <summary>
  271. /// 升级当前大纲
  272. /// </summary>
  273. public void Downgrade(OutlineNode outline)
  274. {
  275. if (outline != null)
  276. {
  277. CPDFOutline parent = outline.Outline.GetParent();
  278. int index = GetOutlinesIndexFormParent(parent, outline.Outline);
  279. CPDFOutline newparent = parent.ChildList[index - 2];
  280. int insertindex = newparent.ChildList.Count;
  281. newparent.MoveChildAtIndex(PDFViewer.Document, outline.Outline, insertindex);
  282. Updata(false);
  283. }
  284. }
  285. /// <summary>
  286. /// 降级当前大纲
  287. /// </summary>
  288. public void Upgrade(OutlineNode outline)
  289. {
  290. if (outline != null)
  291. {
  292. CPDFOutline parent = outline.Outline.GetParent();
  293. CPDFOutline newparent = parent.GetParent();
  294. int index = GetOutlinesIndexFormParent(parent.GetParent(), parent);
  295. newparent.MoveChildAtIndex(PDFViewer.Document, outline.Outline, index);
  296. Updata(false);
  297. }
  298. }
  299. /// <summary>
  300. /// 删除当前大纲
  301. /// </summary>
  302. public void RemoveOutline(OutlineNode outline)
  303. {
  304. outline.Outline.RemoveFromParent(PDFViewer.Document);
  305. Updata(false);
  306. }
  307. /// <summary>
  308. /// 插入大纲到目标节点
  309. /// </summary>
  310. /// <param name="target">目标节点</param>
  311. /// <param name="soure">需要插入的数据</param>
  312. /// <returns></returns>
  313. public bool InsertOutLine(OutlineNode target, OutlineNode soure)
  314. {
  315. bool Tag = true;
  316. if (IsInsertHead)
  317. {
  318. CPDFOutline root = PDFViewer.Document.GetOutlineRoot();
  319. if (root != null)
  320. {
  321. Tag = root.MoveChildAtIndex(PDFViewer.Document, soure.Outline, 0);
  322. }
  323. }
  324. else
  325. {
  326. if (target.IsInsertNextLayer)
  327. {
  328. target.IsExpanded = true;
  329. Tag = target.Outline.MoveChildAtIndex(PDFViewer.Document, soure.Outline, target.Outline.ChildList.Count);
  330. }
  331. else
  332. {
  333. CPDFOutline parent = target.Outline.GetParent();
  334. if (parent != null && parent.ChildList.Count > 0)
  335. {
  336. int index = parent.ChildList.IndexOf(target.Outline);
  337. int sourceindex = parent.ChildList.IndexOf(soure.Outline);
  338. //源数据不在目标节点树中的情况
  339. if (sourceindex == -1)
  340. {
  341. Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index + 1);
  342. }
  343. //分向上和向下移动
  344. else if (sourceindex > index)
  345. {
  346. Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index + 1);
  347. }
  348. else
  349. {
  350. Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index);
  351. }
  352. }
  353. }
  354. }
  355. return Tag;
  356. }
  357. /// <summary>
  358. /// 获取对应大纲所需的缩略图数据
  359. /// </summary>
  360. public WriteableBitmap LoadPreview(OutlineNode outlineNode)
  361. {
  362. CPDFPage page = PDFViewer.Document.PageAtIndex(Convert.ToInt32(outlineNode.PageIndex) - 1);
  363. Size size = PDFViewer.Document.GetPageSize(Convert.ToInt32(outlineNode.PageIndex) - 1);
  364. Point zoomXY = new Point(outlineNode.PositionX * outlineNode.Zoom, outlineNode.PositionY * outlineNode.Zoom);
  365. //数据校验,暂不确定SDK会不会给垃圾值。说是从底层返回的。
  366. if (zoomXY.X > size.Width || zoomXY.X < 0)
  367. {
  368. zoomXY.X = 0;
  369. }
  370. if (zoomXY.Y > size.Height || zoomXY.Y < 0)
  371. {
  372. zoomXY.Y = 0;
  373. }
  374. Size zoomSize = new Size((int)(size.Width * outlineNode.Zoom), (int)(size.Height * outlineNode.Zoom));
  375. bmpData = new byte[(int)(zoomSize.Width * zoomSize.Height * 4)];
  376. WirteBitmap = new WriteableBitmap((int)zoomSize.Width, (int)zoomSize.Height, 96, 96, PixelFormats.Bgra32, null);
  377. if (!page.IsValid())
  378. {
  379. return null;
  380. }
  381. page.RenderPageBitmapWithMatrix((float)outlineNode.Zoom, new Rect(zoomXY.X, zoomXY.Y, zoomSize.Width, zoomSize.Height), 0xFFFFFFFF, bmpData, 1, true);
  382. WirteBitmap.WritePixels(new Int32Rect(0, 0, (int)zoomSize.Width, (int)zoomSize.Height), bmpData, WirteBitmap.BackBufferStride, 0);
  383. WirteBitmap.Freeze();
  384. return WirteBitmap;
  385. }
  386. /// <summary>
  387. /// 将PDF对象转换为自定义数据类型,并存储
  388. /// </summary>
  389. private OutlineNode ConvertCPDFToOutlineNode(CPDFOutline outline, OutlineNode parent, bool IsMoveData)
  390. {
  391. OutlineNode node = new OutlineNode();
  392. if (outline != null)
  393. {
  394. node.IsInsertNextLayer = false;
  395. node.IsInsertCurrentLayer = false;
  396. node.IsExpanded = false;
  397. node.IsSelected = false;
  398. node.Outline = outline;
  399. node.CanUp = outline.Level == 0 ? false : true;
  400. node.CanAddParent = outline.Level == 0 ? false : true;
  401. CPDFAction action = outline.GetAction();
  402. if (action != null)
  403. {
  404. if (action.ActionType != C_ACTION_TYPE.ACTION_TYPE_URI)
  405. {
  406. CPDFDestination cPDFDestination = outline.GetDestination(PDFViewer.Document);
  407. if (cPDFDestination != null)
  408. {
  409. //存储大纲相关属性
  410. node.PageIndex = (cPDFDestination.PageIndex + 1).ToString();
  411. node.PositionX = cPDFDestination.Position_X;
  412. node.PositionY = cPDFDestination.Position_Y;
  413. if (cPDFDestination.Zoom <= 0)
  414. {
  415. node.Zoom = 1;
  416. }
  417. else
  418. {
  419. node.Zoom = cPDFDestination.Zoom;
  420. }
  421. }
  422. else
  423. {
  424. node.PageIndex = "";
  425. node.PositionX = 0;
  426. node.PositionY = 0;
  427. node.Zoom = 1;
  428. }
  429. }
  430. else
  431. {
  432. node.PageIndex = "";
  433. node.PositionX = 0;
  434. node.PositionY = 0;
  435. node.Zoom = 1;
  436. }
  437. }
  438. else
  439. {
  440. node.PageIndex = "";
  441. node.PositionX = 0;
  442. node.PositionY = 0;
  443. node.Zoom = 1;
  444. }
  445. if (parent != null)
  446. {
  447. node.Parent = parent;
  448. }
  449. if (Outlinelist != null && Outlinelist.Count > 0)
  450. {
  451. OutlineNode oldnode = FindOutlineFromDto(Outlinelist, node.Outline, IsMoveData);
  452. if (oldnode != null)
  453. {
  454. node.IsExpanded = oldnode.IsExpanded;
  455. node.IsSelected = oldnode.IsSelected;
  456. }
  457. }
  458. node.Chlidlist = new ObservableCollection<OutlineNode>();
  459. if (outline.ChildList.Count > 0)
  460. {
  461. foreach (CPDFOutline item in outline.ChildList)
  462. {
  463. node.Chlidlist.Add(ConvertCPDFToOutlineNode(item, node, IsMoveData));
  464. }
  465. }
  466. else
  467. {
  468. node.CanDown = false;
  469. }
  470. }
  471. return node;
  472. }
  473. /// <summary>
  474. /// 从当前列表中找到和SDK大纲对象相同的数据
  475. /// </summary>
  476. public OutlineNode FindOutlineFromDto(ObservableCollection<OutlineNode> list, CPDFOutline outline, bool IsMoveData)
  477. {
  478. foreach (OutlineNode item in list)
  479. {
  480. CPDFOutline parent = outline.GetParent();
  481. CPDFOutline PARENT = item.Outline.GetParent();
  482. int i = GetIndexFromParent(parent.ChildList, outline);
  483. int I = GetIndexFromParent(PARENT.ChildList, item.Outline);
  484. if (IsMoveData)
  485. {
  486. if (item.Outline.Title == outline.Title)
  487. {
  488. return item;
  489. }
  490. else if (item.Chlidlist.Count > 0)
  491. {
  492. OutlineNode retdto = FindOutlineFromDto(item.Chlidlist, outline, IsMoveData);
  493. if (retdto != null)
  494. {
  495. return retdto;
  496. }
  497. }
  498. }
  499. else
  500. {
  501. if (item.Outline.Title == outline.Title && i == I && outline.Level == item.Outline.Level && ((parent.Title == PARENT.Title) || (parent.Title == null && PARENT.Title == null)))
  502. {
  503. return item;
  504. }
  505. else if (item.Chlidlist.Count > 0)
  506. {
  507. OutlineNode retdto = FindOutlineFromDto(item.Chlidlist, outline, IsMoveData);
  508. if (retdto != null)
  509. {
  510. return retdto;
  511. }
  512. }
  513. }
  514. }
  515. return null;
  516. }
  517. /// <summary>
  518. /// 从当前列表中找到对应的OutlineNode对象
  519. /// </summary>
  520. public OutlineNode FindOutlineFromList(ObservableCollection<OutlineNode> list, OutlineNode outline, int outlineindex)
  521. {
  522. //如果传入比对数据为null,则返回最后一项
  523. if (outline == null)
  524. {
  525. return list.Last();
  526. }
  527. int index = list.IndexOf(outline);
  528. if (index >= 0)
  529. {
  530. if (outlineindex <= index)
  531. {
  532. return list[index];
  533. }
  534. else
  535. {
  536. return list[outlineindex - 1];
  537. }
  538. }
  539. else
  540. {
  541. foreach (var item in list)
  542. {
  543. OutlineNode node = FindOutlineFromList(item.Chlidlist, outline, outlineindex);
  544. if (node != null)
  545. {
  546. return node;
  547. }
  548. }
  549. }
  550. return null;
  551. }
  552. private int GetIndexFromParent(List<CPDFOutline> parentlist, CPDFOutline outline)
  553. {
  554. for (int i = 0; i < parentlist.Count; i++)
  555. {
  556. if (parentlist[i] == outline)
  557. {
  558. return i;
  559. }
  560. }
  561. return -1;
  562. }
  563. private int GetOutlinesIndexFormParent(CPDFOutline parentoutline, CPDFOutline outline)
  564. {
  565. if (parentoutline != null)
  566. {
  567. if (parentoutline.ChildList.Count > 0)
  568. {
  569. for (int i = 0; i < parentoutline.ChildList.Count; i++)
  570. {
  571. if (parentoutline.ChildList[i] == outline)
  572. {
  573. return i + 1;
  574. }
  575. }
  576. }
  577. return parentoutline.ChildList.Count;
  578. }
  579. return 0;
  580. }
  581. }
  582. }