using ComPDFKit.PDFDocument; using ComPDFKit.PDFDocument.Action; using ComPDFKit.PDFPage; using ComPDFKitViewer.PdfViewer; using PDF_Office.Model; using PDF_Office.Model.BOTA; using Prism.Commands; using Prism.Mvvm; using Prism.Regions; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; namespace PDF_Office.ViewModels.BOTA { class OutLineControlViewModel : BindableBase, INavigationAware { //缩略图相关全局变量,减少内存申请次数 private WriteableBitmap WirteBitmap; private byte[] bmpData; private CPDFViewer PDFViewer; public ObservableCollection Outlinelist { get; set; } private bool isInsertHead = false; public bool IsInsertHead { get { return isInsertHead; } set { SetProperty(ref isInsertHead, value); } } private bool isOnDrop = false; public bool IsOnDrop { get { return isOnDrop; } set { isOnDrop = value; } } public DelegateCommand> CollapseAllCommand { get; set; } public DelegateCommand> ExpandAllCommand { get; set; } public DelegateCommand DeleteAllCommand { get; set; } public DelegateCommand DowngradeCommand { get; set; } public OutLineControlViewModel() { Outlinelist = new ObservableCollection(); DeleteAllCommand = new DelegateCommand(DeleteAll); CollapseAllCommand = new DelegateCommand>(CollapseAll); ExpandAllCommand = new DelegateCommand>(ExpandAll); } public bool IsNavigationTarget(NavigationContext navigationContext) { return true; } public void OnNavigatedFrom(NavigationContext navigationContext) { return; } public void OnNavigatedTo(NavigationContext navigationContext) { navigationContext.Parameters.TryGetValue(ParameterNames.PDFViewer, out PDFViewer); if (PDFViewer == null) { return; } List datasource = PDFViewer.Document.GetOutlineList(); Outlinelist.Clear(); foreach (CPDFOutline item in datasource) { OutlineNode dto = ConvertCPDFToOutlineNode(item, null, false); if (dto != null) { Outlinelist.Add(dto); } } } public void Updata(bool IsMoveData) { PDFViewer.Document.ReleaseOutlineList(); ObservableCollection list = new ObservableCollection(); List datasource = PDFViewer.Document.GetOutlineList(); //遍历,转换UI状态存入临时数组 foreach (CPDFOutline item in datasource) { OutlineNode dto = ConvertCPDFToOutlineNode(item, null, IsMoveData); if (dto != null) { list.Add(dto); } } //清空绑定数组,并填充新数据 Outlinelist.Clear(); foreach (OutlineNode item in list) { Outlinelist.Add(item); } PDFViewer.UndoManager.CanSave = true; } public bool SetTitle(CPDFOutline cPDFOutline, string Title) { if (cPDFOutline == null) { return false; } return cPDFOutline.SetTitle(Title); } public void GoToPage(TreeViewItem treeViewItem) { OutlineNode outline = treeViewItem.DataContext as OutlineNode; if (outline == null) { return; } CPDFAction action = outline.Outline.GetAction(); if (action != null && action.ActionType != C_ACTION_TYPE.ACTION_TYPE_UNKNOWN) PDFViewer.ProcessAction(action); else { Size size = PDFViewer.Document.GetPageSize(Convert.ToInt32(outline.PageIndex) - 1); PDFViewer.GoToPage(Convert.ToInt32(outline.PageIndex) - 1, new Point(size.Width - outline.PositionX, size.Height - outline.PositionY)); } } public void CollapseAll(ObservableCollection outlineNodes) { foreach (var item in outlineNodes) { item.IsExpanded = false; if (item.Chlidlist.Count > 0) { CollapseAll(item.Chlidlist); } } } public void ExpandAll(ObservableCollection outlineNodes) { foreach (var item in outlineNodes) { item.IsExpanded = true; if (item.Chlidlist.Count > 0) { ExpandAll(item.Chlidlist); } } } public void DeleteAll() { foreach (var item in Outlinelist) { item.Outline.RemoveFromParent(this.PDFViewer.Document); } Updata(false); } public void Downgrade(OutlineNode outline) { if (outline != null) { CPDFOutline parent = outline.Outline.GetParent(); int index = GetOutlinesIndexFormParent(parent, outline.Outline); CPDFOutline newparent = parent.ChildList[index - 2]; int insertindex = newparent.ChildList.Count; newparent.MoveChildAtIndex(PDFViewer.Document, outline.Outline, insertindex); Updata(false); } } public void Upgrade(OutlineNode outline) { if (outline != null) { CPDFOutline parent = outline.Outline.GetParent(); CPDFOutline newparent = parent.GetParent(); int index = GetOutlinesIndexFormParent(parent.GetParent(), parent); newparent.MoveChildAtIndex(PDFViewer.Document, outline.Outline, index); Updata(false); } } public void RemoveOutline(OutlineNode outline) { outline.Outline.RemoveFromParent(PDFViewer.Document); Updata(false); } /// /// 插入大纲到目标节点 /// /// 目标节点 /// 需要插入的数据 /// public bool InsertOutLine(OutlineNode target, OutlineNode soure) { bool Tag = true; if (IsInsertHead) { CPDFOutline root = PDFViewer.Document.GetOutlineRoot(); if (root != null) { Tag = root.MoveChildAtIndex(PDFViewer.Document, soure.Outline, 0); } } else { if (target.IsInsertNextLayer) { target.IsExpanded = true; Tag = target.Outline.MoveChildAtIndex(PDFViewer.Document, soure.Outline, target.Outline.ChildList.Count); } else { CPDFOutline parent = target.Outline.GetParent(); if (parent != null && parent.ChildList.Count > 0) { int index = parent.ChildList.IndexOf(target.Outline); int sourceindex = parent.ChildList.IndexOf(soure.Outline); //源数据不在目标节点树中的情况 if (sourceindex == -1) { Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index + 1); } //分向上和向下移动 else if (sourceindex > index) { Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index + 1); } else { Tag = parent.MoveChildAtIndex(PDFViewer.Document, soure.Outline, index); } } } } return Tag; } /// /// 获取对应大纲所需的缩略图数据 /// public WriteableBitmap LoadPreview(OutlineNode outlineNode) { CPDFPage page = PDFViewer.Document.PageAtIndex(Convert.ToInt32(outlineNode.PageIndex) - 1); Size size = PDFViewer.Document.GetPageSize(Convert.ToInt32(outlineNode.PageIndex) - 1); Point zoomXY = new Point(outlineNode.PositionX * outlineNode.Zoom, outlineNode.PositionY * outlineNode.Zoom); //数据校验,暂不确定SDK会不会给垃圾值。说是从底层返回的。 if (zoomXY.X > size.Width || zoomXY.X < 0) { zoomXY.X = 0; } if (zoomXY.Y > size.Height || zoomXY.Y < 0) { zoomXY.Y = 0; } Size zoomSize = new Size((int)(size.Width * outlineNode.Zoom), (int)(size.Height * outlineNode.Zoom)); bmpData = new byte[(int)(zoomSize.Width * zoomSize.Height * 4)]; WirteBitmap = new WriteableBitmap((int)zoomSize.Width, (int)zoomSize.Height, 96, 96, PixelFormats.Bgra32, null); if (!page.IsValid()) { return null; } page.RenderPageBitmapWithMatrix((float)outlineNode.Zoom, new Rect(zoomXY.X, zoomXY.Y, zoomSize.Width, zoomSize.Height), 0xFFFFFFFF, bmpData, 1, true); WirteBitmap.WritePixels(new Int32Rect(0, 0, (int)zoomSize.Width, (int)zoomSize.Height), bmpData, WirteBitmap.BackBufferStride, 0); WirteBitmap.Freeze(); return WirteBitmap; } /// /// 将PDF对象转换为自定义数据类型,并存储 /// private OutlineNode ConvertCPDFToOutlineNode(CPDFOutline outline, OutlineNode parent, bool IsMoveData) { OutlineNode node = new OutlineNode(); if (outline != null) { node.IsInsertNextLayer = false; node.IsInsertCurrentLayer = false; node.IsExpanded = false; node.IsSelected = false; node.Outline = outline; node.CanUp = outline.Level == 0 ? false : true; node.CanAddParent = outline.Level == 0 ? false : true; CPDFAction action = outline.GetAction(); if (action != null) { if (action.ActionType != C_ACTION_TYPE.ACTION_TYPE_URI) { CPDFDestination cPDFDestination = outline.GetDestination(PDFViewer.Document); if (cPDFDestination != null) { //存储大纲相关属性 node.PageIndex = (cPDFDestination.PageIndex + 1).ToString(); node.PositionX = cPDFDestination.Position_X; node.PositionY = cPDFDestination.Position_Y; if (cPDFDestination.Zoom <= 0) { node.Zoom = 1; } else { node.Zoom = cPDFDestination.Zoom; } } else { node.PageIndex = ""; node.PositionX = 0; node.PositionY = 0; node.Zoom = 1; } } else { node.PageIndex = ""; node.PositionX = 0; node.PositionY = 0; node.Zoom = 1; } } else { node.PageIndex = ""; node.PositionX = 0; node.PositionY = 0; node.Zoom = 1; } if (parent != null) { node.Parent = parent; } if (Outlinelist != null && Outlinelist.Count > 0) { OutlineNode oldnode = FindOutlineFromDto(Outlinelist, node.Outline, IsMoveData); if (oldnode != null) { node.IsExpanded = oldnode.IsExpanded; node.IsSelected = oldnode.IsSelected; } } node.Chlidlist = new ObservableCollection(); if (outline.ChildList.Count > 0) { foreach (CPDFOutline item in outline.ChildList) { node.Chlidlist.Add(ConvertCPDFToOutlineNode(item, node, IsMoveData)); } } else { node.CanDown = false; } } return node; } public OutlineNode FindOutlineFromDto(ObservableCollection list, CPDFOutline outline, bool IsMoveData) { foreach (OutlineNode item in list) { CPDFOutline parent = outline.GetParent(); CPDFOutline PARENT = item.Outline.GetParent(); int i = GetIndexFromParent(parent.ChildList, outline); int I = GetIndexFromParent(PARENT.ChildList, item.Outline); if (IsMoveData) { if (item.Outline.Title == outline.Title) { return item; } else if (item.Chlidlist.Count > 0) { OutlineNode retdto = FindOutlineFromDto(item.Chlidlist, outline, IsMoveData); if (retdto != null) { return retdto; } } } else { if (item.Outline.Title == outline.Title && i == I && outline.Level == item.Outline.Level && ((parent.Title == PARENT.Title) || (parent.Title == null && PARENT.Title == null))) { return item; } else if (item.Chlidlist.Count > 0) { OutlineNode retdto = FindOutlineFromDto(item.Chlidlist, outline, IsMoveData); if (retdto != null) { return retdto; } } } } return null; } private int GetIndexFromParent(List parentlist, CPDFOutline outline) { for (int i = 0; i < parentlist.Count; i++) { if (parentlist[i] == outline) { return i; } } return -1; } private int GetOutlinesIndexFormParent(CPDFOutline parentoutline, CPDFOutline outline) { if (parentoutline != null) { if (parentoutline.ChildList.Count > 0) { for (int i = 0; i < parentoutline.ChildList.Count; i++) { if (parentoutline.ChildList[i] == outline) { return i + 1; } } } return parentoutline.ChildList.Count; } return 0; } } }