using ComPDFKitDemo.BOTA; using Microsoft.Win32; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using ComPDFKit.PDFDocument; using ComPDFKitViewer.PdfViewer; namespace ComPDFKitDemo.PageEditor { public partial class PageEditControl : UserControl { public class DealPages { public List Pages; public Option Op; public int[] OpInfo; } public enum Option { RightRotate, LeftRotate, Exchange, Insert, Reverser } internal static class Utils { public static T FindVisualParent(DependencyObject obj) where T : class { while (obj != null) { if (obj is T) return obj as T; obj = VisualTreeHelper.GetParent(obj); } return null; } } public async void SetReadModeTip(bool show, string content, bool stayshow) { PageViewTipText.Text = content; if (show) { tip.Visibility = Visibility.Visible; tip.Opacity = 1; if (!stayshow) { await Task.Delay(1000); for (double i = 1; i > 0; i -= 0.05) { await Task.Delay(100); tip.Opacity = i; } tip.Visibility = Visibility.Collapsed; } } else tip.Visibility = Visibility.Collapsed; } public Stack UndoStack = new Stack(); public ObservableCollection BindPageList = new ObservableCollection(); public bool isInitialized = false; private const int THUMBNAIL_WIDTH = 150; private const int THUMBNAIL_HEIGHT = 150; private bool isSelectionChangeProgrammatic = false; private CPDFViewer pdfViewer; private bool IsModefied = false; private List PageThumbnailsToRequest = new List(); private List VisiblePageIndexes = new List(); private int zoomLevel = 2; private bool isZooming = false; private int[] thumbnailSize = {100, 150, 200, 300, 500 }; private ListBoxItem TempItem; private bool isFrontHalf = false; private bool isDraging = false; private bool isDragingEnter = false; public event RoutedEventHandler DragAddTab; public PageEditControl() { InitializeComponent(); } private void CommandBinding_Executed_LeftRotate(object sender, ExecutedRoutedEventArgs e) { DoRotate(-90); } private void CommandBinding_Executed_RightRotate(object sender, ExecutedRoutedEventArgs e) { DoRotate(90); } private void CommandBinding_Executed_Save(object sender, ExecutedRoutedEventArgs e) { DoSave(); UndoStack.Clear(); } private void CommandBinding_Executed_Delete(object sender, ExecutedRoutedEventArgs e) { var list = GetListFromSelectedItems(); DoDelete(list,true); UndoStack.Clear(); } private void CommandBinding_Executed_Copy(object sender, ExecutedRoutedEventArgs e) { DoCopy(); } private void CommandBinding_Executed_Paste(object sender, ExecutedRoutedEventArgs e) { DoPaste(); } private void CommandBinding_Executed_Revoke(object sender, ExecutedRoutedEventArgs e) { if(UndoStack.Count>0) { var pages = UndoStack.Pop(); Undo(pages); } } private void PdfViewer_InfoChanged(object sender, KeyValuePair e) { if (e.Key == "RenderNum") { isSelectionChangeProgrammatic = true; UpdateSelectedIndex(); isSelectionChangeProgrammatic = false; } } private void _pdfviewer_OnThumbnailGenerated(int pageIndex, byte[] thumb, int w, int h) { try { if (PageEditListBox.Items.IsEmpty) { return; } ScrollViewer sv = GetScrollHost(PageEditListBox); ListBoxItem item = PageEditListBox.Items[pageIndex] as ListBoxItem; ListBoxItem listboxitem = PageEditListBox.ItemContainerGenerator.ContainerFromIndex(pageIndex) as ListBoxItem; if (ViewportHelper.IsInViewport(sv, listboxitem)) { Debug.WriteLine("Got thumbnail for page {0}. It is visible, so adding thumb", pageIndex); PixelFormat fmt = PixelFormats.Bgra32; BitmapSource bps = BitmapSource.Create(w, h, 96.0, 96.0, fmt, null, thumb, (w * fmt.BitsPerPixel + 7) / 8); Image image = GetImageElement(PageEditListBox.Items[pageIndex] as ListBoxItem); image.Source = bps; } else { Debug.WriteLine("Got thumbnail for page {0}. It is NOT visible, so ignoring thumb", pageIndex); } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } } private void UserControl_Loaded(object sender, RoutedEventArgs e) { PageEditListBox.Focus(); if (PageEditListBox.HasItems) { PageEditListBox.ScrollIntoView(PageEditListBox.Items[pdfViewer.CurrentIndex < 0 ? 0 : pdfViewer.CurrentIndex]); PageEditListBox.SelectedIndex = pdfViewer.CurrentIndex; } } private void UserControl_Unloaded(object sender, RoutedEventArgs e) { if (IsModefied) { var result = MessageBox.Show("The document has not been saved. Do you want to save it?", null, MessageBoxButton.YesNoCancel); if (result == MessageBoxResult.Yes) { DoSave(); } } } private void UserControl_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { if (Keyboard.IsKeyDown(Key.LeftCtrl)) { int oldZoomLevel = zoomLevel; if (e.Delta < 0) { if (zoomLevel > 0) zoomLevel--; } else { if (zoomLevel < thumbnailSize.Length - 1) zoomLevel++; } if (zoomLevel != oldZoomLevel) { isZooming = true; PopulateThumbnailList(); PageEditListBox.ScrollIntoView(PageEditListBox.Items[pdfViewer.CurrentIndex]); PageEditListBox.SelectedIndex = pdfViewer.CurrentIndex; isZooming = false; } } } private async void PageEditListBox_ScrollChanged(object sender, ScrollChangedEventArgs e) { if (NeedScroll) { await Task.Delay(500); var scroller = GetScrollHost(PageEditListBox); var v = scroller.VerticalOffset; scroller.ScrollToVerticalOffset(v + Speed); return; } if (scrollType != ScrollEventType.EndScroll || isZooming) return; ItemsInViewHitTest(); } private void PageEditListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { } private ScrollEventType scrollType = ScrollEventType.EndScroll; private void PageEditListBox_Scroll(object sender, System.Windows.Controls.Primitives.ScrollEventArgs e) { scrollType = e.ScrollEventType; if (scrollType != ScrollEventType.EndScroll || isZooming) return; ItemsInViewHitTest(); } private bool IskeyDown = false; private void PageEditListBox_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.LeftShift || e.Key == Key.LeftCtrl) { IskeyDown = true; return; } } private Point startPostion = new Point(); private void PageEditListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { NeedScroll = false; var pos = e.GetPosition(PageEditListBox); HitTestResult result = VisualTreeHelper.HitTest(PageEditListBox, pos); if (result == null) { return; } var listBoxItem = Utils.FindVisualParent(result.VisualHit); var scroller = Utils.FindVisualParent(result.VisualHit); if (listBoxItem == null) { if (scroller != null) { startchoose = false; return; } startchoose = true; PageEditListBox.SelectedItems.Clear(); startPostion = e.GetPosition(PageEditListBox); startPostion = new Point(startPostion.X,startPostion.Y+GetScrollHost(PageEditListBox).VerticalOffset); IskeyDown = false; Mouse.Capture(PageEditListBox); return; } startchoose = false; if (listBoxItem.IsSelected == true && !Keyboard.IsKeyDown(Key.LeftCtrl)) { e.Handled = true; } } private void PageEditListBox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { ChooseRect.Visibility = Visibility.Collapsed; var pos = e.GetPosition(PageEditListBox); HitTestResult result = VisualTreeHelper.HitTest(PageEditListBox, pos); if (result == null) { return; } var listBoxItem = Utils.FindVisualParent(result.VisualHit); if (listBoxItem == null) { return; } if (IskeyDown && !Keyboard.IsKeyDown(Key.LeftCtrl)&&!Keyboard.IsKeyDown(Key.LeftShift)) { IskeyDown = false; PageEditListBox.SelectedItems.Clear(); PageEditListBox.SelectedItem = listBoxItem; listBoxItem.IsSelected = true; return; } } private void PageEditListBox_Drop(object sender, DragEventArgs e) { NeedScroll = false; if (!isDraging) { MidLane.Visibility = Visibility.Collapsed; return; } if (isDragingEnter) { CPDFDocument dragDoc = CPDFDocument.InitWithFilePath(dragingEnterPath); if (dragingEnterPath.Substring(dragingEnterPath.LastIndexOf(@".")).ToLower() == ".pdf") { int index = InsertIndex == -1 ? 0 : InsertIndex; pdfViewer.Document.ImportPagesAtIndex(dragDoc, "1-" + dragDoc.PageCount, index); PopulateThumbnailList(); ItemsInViewHitTest(); } else if (!string.IsNullOrEmpty(dragingEnterPath)) DragAddTab.Invoke(dragingEnterPath, new RoutedEventArgs()); MidLane.Visibility = Visibility.Collapsed; isDragingEnter = false; dragingEnterPath = null; return; } var pos = e.GetPosition(PageEditListBox); var result = VisualTreeHelper.HitTest(PageEditListBox, pos); if (result == null) { MidLane.Visibility = Visibility.Collapsed; isDraging = false; return; } var sourcePerson = e.Data.GetData(typeof(StackPanel)) as StackPanel; if (sourcePerson == null) { MidLane.Visibility = Visibility.Collapsed; isDraging = false; return; } int targetindex = 0; if (InsertIndex != -1) { targetindex = InsertIndex; } else { var listBoxItem = Utils.FindVisualParent(result.VisualHit); if (listBoxItem == null) { MidLane.Visibility = Visibility.Collapsed; isDraging = false; return; } var targetPerson = listBoxItem; targetPerson.Opacity = 1; sourcePerson.Opacity = 1; if (ReferenceEquals(targetPerson, sourcePerson)) { MidLane.Visibility = Visibility.Collapsed; isDraging = false; return; } targetindex = PageEditListBox.Items.IndexOf(targetPerson); } List list = new List(); List sourceindex = new List(); List pages = new List(); for (int i = 0; i < PageEditListBox.SelectedItems.Count; i++) { var pageindex = PageEditListBox.Items.IndexOf(PageEditListBox.SelectedItems[i] as ListBoxItem); pages.Add(pageindex); } pages.Sort(); if (targetindex <= pages[0]) { sourceindex.Add(-1); list = new List(); for (int i = 0; i < pages.Count; i++) { list.Add(PageEditListBox.Items[pages[i]] as ListBoxItem); sourceindex.Add(pages[i]); DragToSort(pages[i], targetindex + i); } } else if (targetindex >= pages[pages.Count - 1]) { sourceindex.Add(1); list = new List(); for (int i = 0; i < pages.Count; i++) { list.Add(PageEditListBox.Items[pages[pages.Count - 1 - i]] as ListBoxItem); sourceindex.Add(pages[pages.Count-1-i]); DragToSort(pages[pages.Count - 1 - i], targetindex - 1 - i); } } else { int i, j, k; for (k = 0; k < pages.Count - 1; k++) { if (pages[k] < targetindex && pages[k + 1] >= targetindex) break; } sourceindex.Add(0); list = new List(); for (i = 0; i <= k; i++) { list.Add(PageEditListBox.Items[pages[k - i]] as ListBoxItem); sourceindex.Add(pages[k - i]); DragToSort(pages[k - i], targetindex - 1 - i); } for (j = i; j < pages.Count; j++) { list.Add(PageEditListBox.Items[pages[j]] as ListBoxItem); sourceindex.Add(pages[j]); DragToSort(pages[j], targetindex); targetindex++; } sourceindex.Add(k); } DealPages dealPages = new DealPages() { Pages = list, Op = Option.Exchange, OpInfo = sourceindex.ToArray() }; UndoStack.Push(dealPages); isDraging = false; } private void MidLane_Drop(object sender, DragEventArgs e) { MidLane.Visibility = Visibility.Collapsed; this.PageEditListBox_Drop(sender, e); } private bool startchoose = false; private void PageEditListBox_PreviewMouseMove(object sender, MouseEventArgs e) { try { if (e.LeftButton == MouseButtonState.Pressed) { if (startchoose) { var s = GetScrollHost(PageEditListBox); Point start = new Point(); start = new Point(startPostion.X, startPostion.Y - s.VerticalOffset); var rec = new Rect(start, e.GetPosition(PageEditListBox)); ChooseRect.Margin = new Thickness(rec.Left, rec.Top, 0, 0); ChooseRect.Width = rec.Width; ChooseRect.Height = rec.Height; ChooseRect.Visibility = Visibility.Visible; var item = PageEditListBox.Items[0] as ListBoxItem; var rang = GetRoughViewportRange(PageEditListBox, item.DesiredSize, item.Margin); var scroller = GetScrollHost(PageEditListBox); for (int i =0; i <= PageEditListBox.Items.Count; i++) { var _item = PageEditListBox.Items[i] as ListBoxItem; var v = VisualTreeHelper.GetOffset(_item); if (rec.IntersectsWith(new Rect(v.X, v.Y - scroller.VerticalOffset, _item.ActualWidth, _item.ActualHeight))) PageEditListBox.SelectedItems.Add(_item); else PageEditListBox.SelectedItems.Remove(_item); } return; } var pos = e.GetPosition(PageEditListBox); if (pos.Y < 0 || pos.Y > PageEditListBox.ActualHeight) { MidLane.Visibility = Visibility.Collapsed; return; } HitTestResult result = VisualTreeHelper.HitTest(PageEditListBox, pos); if (result == null) { return; } var listBoxItem = Utils.FindVisualParent(result.VisualHit); if (listBoxItem == null) { return; } isDragingEnter = false; TempItem = listBoxItem; var panel = GetPanel(TempItem); var item_pos = e.GetPosition(panel); if (item_pos != null) { item_x = item_pos.X; item_y = item_pos.Y; } var scroll = GetScrollHost(PageEditListBox); DataObject dataObj = new DataObject(listBoxItem.Content as StackPanel); DragDrop.DoDragDrop(PageEditListBox, dataObj, DragDropEffects.Move); Mouse.Capture(PageEditListBox); return; } ChooseRect.Visibility = Visibility.Collapsed; IskeyDown = true; Mouse.Capture(null); } catch (Exception ex) { } } private bool NeedScroll = false; private int Speed = 0; private double item_x; private double item_y; private int InsertIndex = -1; private void Grid_DragOver(object sender, DragEventArgs e) { if (startchoose) { return; } try { if (e.KeyStates == (DragDropKeyStates.ControlKey | DragDropKeyStates.LeftMouseButton) || e.KeyStates == (DragDropKeyStates.ShiftKey | DragDropKeyStates.LeftMouseButton | DragDropKeyStates.ControlKey)) return; var pos = e.GetPosition(PageEditListBox); var result = VisualTreeHelper.HitTest(PageEditListBox, pos); if (result == null) { } var listBoxItem = Utils.FindVisualParent(result.VisualHit); if (listBoxItem == null) { } double xPos, yPos; if (!isDragingEnter) { Image image = GetImageElement(TempItem); Viewbox viewBox = (TempItem.Content as StackPanel).Children[0] as Viewbox; ShadowPicture.Width = viewBox.ActualWidth; ShadowPicture.Height = viewBox.ActualHeight; ShadowPicture.Source = image.Source; xPos = e.GetPosition(PageEditListBox).X - item_x; yPos = e.GetPosition(PageEditListBox).Y - item_y; } else { var pic = ToBitmapSource(dragingEnterPath); ShadowPicture.Width = pic.Width; ShadowPicture.Height = pic.Height; ShadowPicture.Source = pic; xPos = e.GetPosition(PageEditListBox).X - pic.Width / 2; yPos = e.GetPosition(PageEditListBox).Y - pic.Height / 2; } ShadowPicture.Margin = new Thickness(xPos, yPos, 0, 0); var scroll = GetScrollHost(PageEditListBox); if (listBoxItem != null) { var p = VisualTreeHelper.GetOffset(listBoxItem); MidLane.Visibility = Visibility.Visible; MidLane.X2 = MidLane.X1 = p.X + 10 + listBoxItem.ActualWidth; if (pos.X < p.X + 10 + listBoxItem.ActualWidth / 2) { isFrontHalf = true; MidLane.X2 = MidLane.X1 = p.X; InsertIndex = PageEditListBox.Items.IndexOf(listBoxItem); } else { isFrontHalf = false; InsertIndex = PageEditListBox.Items.IndexOf(listBoxItem) + 1; } MidLane.Y1 = p.Y; if (MidLane.Y1 < 0) MidLane.Y1 = 0; MidLane.Y2 = p.Y + listBoxItem.ActualHeight; if (MidLane.Y2 < 0) { MidLane.Y2 = 0; } } if (pos.Y <= 30 || pos.Y >= PageEditListBox.ActualHeight - 10) { MidLane.Visibility = Visibility.Collapsed; NeedScroll = false; } if (pos.X <= 40 || pos.X >= scroll.ViewportWidth - 50) { MidLane.Visibility = Visibility.Collapsed; NeedScroll = false; } Speed = 0; if (pos.Y >= PageEditListBox.ActualHeight - 30) { Speed = 30 - (int)(PageEditListBox.ActualHeight - pos.Y); NeedScroll = true; } else if (pos.Y <= 30) { Speed = (int)(pos.Y - 30); NeedScroll = true; } else NeedScroll = false; var v = scroll.VerticalOffset; scroll.ScrollToVerticalOffset(v + Speed); } catch (Exception ex) { } } private void ShadowPicture_Drop(object sender, DragEventArgs e) { this.PageEditListBox_Drop(sender, e); } private void ListBoxItem_DragLeave(object sender, DragEventArgs e) { isDraging = true; } private void Save_Click(object sender, RoutedEventArgs e) { DoSave(); UndoStack.Clear(); } private void Delete_Click(object sender, RoutedEventArgs e) { var list = GetListFromSelectedItems(); DoDelete(list, true); UndoStack.Clear(); } private void Rotate_Click(object sender, RoutedEventArgs e) { var item = sender as MenuItem; double step = 90; if (item.Name == "LeftRotate") step = -90; else step = 90; DoRotate(step); } private void Exchange_Click(object sender, RoutedEventArgs e) { List list = new List(); list = GetListFromSelectedItems(); DoExchange(list); DealPages pages = new DealPages() { Pages = list, Op = Option.Reverser }; UndoStack.Push(pages); } private void ListBoxItem_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) { e.GetPosition(PageEditListBox); var pos = e.GetPosition(PageEditListBox); HitTestResult result = VisualTreeHelper.HitTest(PageEditListBox, pos); if (result == null) { return; } var listBoxItem = Utils.FindVisualParent(result.VisualHit); if (listBoxItem != null) { pdfViewer.GoToPage((int)listBoxItem.Tag); } this.Visibility = Visibility.Collapsed; } private void InsertBlank_Click(object sender, RoutedEventArgs e) { var send = sender as MenuItem; switch (send.Name) { case "InsertBlank": DoInsert("Blank"); break; case "InsertFromPDF": var dialog = new OpenFileDialog(); dialog.Multiselect = false; dialog.Filter = ComPDFKitDemo.Properties.Resources.OpenDialogFilter; if (dialog.ShowDialog() == true) { var index = PageEditListBox.Items.IndexOf(PageEditListBox.SelectedItem) + 1; DoAddFromOtherPdf(dialog.FileName, "all", index, 2); } break; default: break; } } private void Extract_Click(object sender, RoutedEventArgs e) { string page = PageEditListBox.SelectedItems.Count > 1 ? " pages " : " page "; SaveFileDialog save = new SaveFileDialog(); save.FileName = pdfViewer.Document.FileName + page + GetPageParam() + " .pdf"; if ((bool)save.ShowDialog()) { DoExtract(save.FileName); } } private void Replace_Click(object sender, RoutedEventArgs e) { DoReplace(); } private void Split_Click(object sender, RoutedEventArgs e) { } private void Paste_Click(object sender, RoutedEventArgs e) { DoPaste(); } private void Copy_Click(object sender, RoutedEventArgs e) { DoCopy(); } private void PageEditListBox_SizeChanged(object sender, SizeChangedEventArgs e) { PageEditListBox.ScrollIntoView(PageEditListBox.SelectedItem); } private void PageEditor_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { ListBoxItem item = PageEditListBox.Items[pdfViewer.CurrentIndex] as ListBoxItem; PageEditListBox.ScrollIntoView(PageEditListBox.SelectedItem); PageEditListBox.SelectedItem = item; } private async void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var item = sender as ListBoxItem; Image img = GetImageElement(item); int itemindex = PageEditListBox.Items.IndexOf(item); if (img.Source == null) { await pdfViewer.GetThumbnail(itemindex, (int)img.Width, (int)img.Height); } } private String dragingEnterPath; private void PageGrid_PreviewDragEnter(object sender, DragEventArgs e) { var file = (System.Array)e.Data.GetData(DataFormats.FileDrop); if (file == null || file.Length > 1) { return; } foreach (var f in file) { dragingEnterPath = f.ToString(); if (dragingEnterPath != null) { isDragingEnter = true; } } } private void ContextMenu_Loaded(object sender, RoutedEventArgs e) { if (App.CopyDoc == null) { var s = sender as ContextMenu; foreach (var item in s.Items) { if ((item as MenuItem).Name == "Paste") { (item as MenuItem).IsEnabled = false; } } } } #region Method public void Undo(DealPages dealPages) { var pages = dealPages.Pages; switch (dealPages.Op) { case Option.RightRotate: for (int i = 0; i < pages.Count; i++) { try { if(!PageEditListBox.Items.Contains(pages[i])) return; var image = GetImageElement(pages[i]); double angle = (double)image.LayoutTransform.GetValue(RotateTransform.AngleProperty); angle += -90; angle = angle % 360; image.LayoutTransform = new RotateTransform(angle, image.ActualWidth / 2, image.ActualHeight / 2); var index = PageEditListBox.Items.IndexOf(PageEditListBox.SelectedItems[i]); pdfViewer.Document.RotatePage(index, (int)-90 / 90); IsModefied = true; if (VisiblePageIndexes.Contains(index)) VisiblePageIndexes.Remove(index); } catch(Exception ex) { } } ItemsInViewHitTest(); break; case Option.LeftRotate: for (int i = 0; i < pages.Count; i++) { try { if (!PageEditListBox.Items.Contains(pages[i])) return; var image = GetImageElement(pages[i]); double angle = (double)image.LayoutTransform.GetValue(RotateTransform.AngleProperty); angle += 90; angle = angle % 360; image.LayoutTransform = new RotateTransform(angle, image.ActualWidth / 2, image.ActualHeight / 2); var index = PageEditListBox.Items.IndexOf(PageEditListBox.SelectedItems[i]); pdfViewer.Document.RotatePage(index, (int)90 / 90); IsModefied = true; if (VisiblePageIndexes.Contains(index)) VisiblePageIndexes.Remove(index); } catch (Exception ex) { } } ItemsInViewHitTest(); break; case Option.Exchange: UndoExchange(dealPages.Pages,dealPages.OpInfo.ToList()); break; case Option.Insert: DoDelete(dealPages.Pages,false); break; case Option.Reverser: DoExchange(dealPages.Pages); break; default: break; } } private void UndoExchange(List list,Listsourceindex) { int type = sourceindex[0]; switch (type) { case -1: case 1: for (int i = 0; i < list.Count; i++) { int nowindex = PageEditListBox.Items.IndexOf(list[list.Count - 1 - i]); DragToSort(nowindex, sourceindex[sourceindex.Count - 1 - i]); } break; case 0: for (int i = 0; i < list.Count; i++) { int nowindex = PageEditListBox.Items.IndexOf(list[list.Count - 1 - i]); DragToSort(nowindex, sourceindex[sourceindex.Count - 2 - i]); } break; default: break; } } public void LoadThumbnails(CPDFViewer viewer) { if (viewer == null || viewer.Document == null) return; pdfViewer = viewer; if (!isInitialized) { this.PopulateThumbnailList(); isInitialized = true; pdfViewer.OnThumbnailGenerated += _pdfviewer_OnThumbnailGenerated; } if(pdfViewer.CurrentIndex>=0) { PageEditListBox.ScrollIntoView(PageEditListBox.Items[pdfViewer.CurrentIndex]); (PageEditListBox.Items[pdfViewer.CurrentIndex] as ListBoxItem).IsSelected = true; } ItemsInViewHitTest(); } public void PopulateThumbnailList() { PageEditListBox.Items.Clear(); VisiblePageIndexes.Clear(); BindPageList.Clear(); GC.Collect(); int thumbnailWidth = thumbnailSize[zoomLevel]; for (int i = 0; i < pdfViewer.Document.PageCount; i++) { Size pageSize = pdfViewer.Document.GetPageSize(i); int imageWidth = pageSize.Width > pageSize.Height ? thumbnailWidth * 2 : (int)(pageSize.Width / pageSize.Height * thumbnailWidth * 2); int imageHeight = pageSize.Height > pageSize.Width ? thumbnailWidth * 2 : (int)(pageSize.Height / pageSize.Width * thumbnailWidth * 2); Image img = new Image() { Margin = new Thickness(0, 0, 5, 0), Width = imageWidth, Height = imageHeight, Stretch = Stretch.Uniform, }; Border border = new Border() { BorderThickness = new Thickness(2), BorderBrush = Brushes.Black, Child = img, }; Viewbox viewBox = new Viewbox() { Margin = new Thickness(0, 5, 0, 0), Stretch = System.Windows.Media.Stretch.Uniform, Width = thumbnailWidth, Height = thumbnailWidth, Child = border, }; TextBlock text = new TextBlock() { HorizontalAlignment = System.Windows.HorizontalAlignment.Center, Text = (i + 1).ToString(), Foreground = Brushes.Black }; StackPanel panel = new StackPanel(); panel.Children.Add(viewBox); panel.Children.Add(text); ListBoxItem item = new ListBoxItem(); item.Content = panel; item.Tag = i; item.Margin = new Thickness(5, 5, 5, 5); BindPageList.Add(item); } PageEditListBox.ItemsSource = BindPageList; } public ListBoxItem GetNewItem(int ItemIndex) { int thumbnailWidth = thumbnailSize[zoomLevel]; Size pageSize = pdfViewer.Document.GetPageSize(ItemIndex); if(pageSize.Width==0||pageSize.Height==0) { pageSize = new Size(228,300); } int imageWidth = pageSize.Width > pageSize.Height ? thumbnailWidth * 2 : (int)(pageSize.Width / pageSize.Height * thumbnailWidth * 2); int imageHeight = pageSize.Height > pageSize.Width ? thumbnailWidth * 2 : (int)(pageSize.Height / pageSize.Width * thumbnailWidth * 2); Image img = new Image() { Margin = new Thickness(0, 0, 5, 0), Width = imageWidth, Height = imageHeight, Stretch = Stretch.Uniform, }; Border border = new Border() { BorderThickness = new Thickness(2), BorderBrush = Brushes.Black, Child = img, }; Viewbox viewBox = new Viewbox() { Margin = new Thickness(0, 5, 0, 0), Stretch = System.Windows.Media.Stretch.Uniform, Width = thumbnailWidth, Height = thumbnailWidth, Child = border, }; TextBlock text = new TextBlock() { HorizontalAlignment = System.Windows.HorizontalAlignment.Center, Text = (ItemIndex + 1).ToString(), Foreground = Brushes.Black }; StackPanel panel = new StackPanel(); panel.Children.Add(viewBox); panel.Children.Add(text); ListBoxItem item = new ListBoxItem(); item.Content = panel; item.Tag = ItemIndex; item.Margin = new Thickness(5, 5, 5, 5); return item; } public void AddBlankPages(int pagecount, int insertindex) { for (int i = 0; i < pagecount; i++) { var item = GetNewItem(insertindex + i); BindPageList.Insert(insertindex + i, item); if (VisiblePageIndexes.Contains(insertindex + i)) VisiblePageIndexes.Remove(insertindex + i); } PageEditListBox.UpdateLayout(); } private async void ItemsInViewHitTest() { try { ScrollViewer sv = GetScrollHost(PageEditListBox); if (sv == null) return; if (VisualTreeHelper.GetParent(this) == null) return; List pagesOnScreen = new List(); PageThumbnailsToRequest.Clear(); for (int i = 0; i < PageEditListBox.Items.Count; ++i) { ListBoxItem item = PageEditListBox.Items[i] as ListBoxItem; Image img = GetImageElement(item); if (ViewportHelper.IsInViewport(sv, item)) { if (img.Source == null && !VisiblePageIndexes.Contains(i)) { VisiblePageIndexes.Add(i); await pdfViewer.GetThumbnail(i, (int)img.Width, (int)img.Height); Debug.WriteLine("Page {0} is visible, asking for thumb", (i + 1)); } else if (img.Source == null) { await pdfViewer.GetThumbnail(i, (int)img.Width, (int)img.Height); Debug.WriteLine("Page { 0} is visible, asking for thumb", (i + 1)); } } else { if (VisiblePageIndexes.Contains(i)) { Image image = GetImageElement(PageEditListBox.Items[i] as ListBoxItem); if (image.Source != null) { image.Source = null; Debug.WriteLine("Page {0} is out of range, removed thumb", (i + 1)); } else { Debug.WriteLine("Page {0} is out of range, but had no thumb", (i + 1)); } VisiblePageIndexes.Remove(i); } } } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } } private void UpdateSelectedIndex() { if (PageEditListBox.Items.Count == 0) PageEditListBox.SelectedIndex = -1; else if (PageEditListBox.Items.Count <= pdfViewer.CurrentIndex) this.PageEditListBox.SelectedIndex = 0; else if (PageEditListBox.SelectedIndex != pdfViewer.CurrentIndex) PageEditListBox.SelectedIndex = pdfViewer.CurrentIndex; } private Image GetImageElement(ListBoxItem item) { Viewbox viewBox = (item.Content as StackPanel).Children[0] as Viewbox; Image img = (viewBox.Child as Border).Child as Image; return img; } private StackPanel GetPanel(ListBoxItem item) { StackPanel panel = item.Content as StackPanel; return panel; } private TextBlock GetPageNumTextBlock(ListBoxItem item) { TextBlock text = (item.Content as StackPanel).Children[1] as TextBlock; return text; } private ScrollViewer GetScrollHost(ListBox listBox) { if (VisualTreeHelper.GetChildrenCount(listBox) > 0) { Border border = VisualTreeHelper.GetChild(listBox, 0) as Border; if (border != null) { return VisualTreeHelper.GetChild(border, 0) as ScrollViewer; } } return null; } private void DragToSort(int sourceindex, int targetindex) { if (targetindex == sourceindex) { MidLane.Visibility = Visibility.Collapsed; return; } var source = PageEditListBox.Items[sourceindex]; BindPageList.RemoveAt(sourceindex); MidLane.Visibility = Visibility.Collapsed; BindPageList.Insert(targetindex, source as ListBoxItem); PageEditListBox.SelectedItems.Add(source); var result = pdfViewer.Document.MovePage(sourceindex,targetindex); if(!result) { throw new Exception(); } IsModefied = true; UpdateSortedPageNum(sourceindex,targetindex); } private void UpdateSortedPageNum(int sourceIndex,int targetIndex) { int sum = sourceIndex + targetIndex; targetIndex = targetIndex > sourceIndex ? targetIndex : sourceIndex; sourceIndex = sum - targetIndex; sourceIndex = sourceIndex <= 0 ? 0 : sourceIndex; targetIndex = targetIndex+1> PageEditListBox.Items.Count ? PageEditListBox.Items.Count-1:targetIndex; for (int i = sourceIndex; i <= targetIndex; i++) { var item = PageEditListBox.Items[i] as ListBoxItem; TextBlock pagenum = GetPageNumTextBlock(item); pagenum.Text = (i + 1).ToString(); } } private void UpdateAllPageNum() { for(int i=0;i insertIndex) insertIndex = pageindex; } } Viewbox box = ((PageEditListBox.Items[insertIndex] as ListBoxItem).Content as StackPanel).Children[0] as Viewbox; ListBoxItem item = PageEditListBox.Items[insertIndex] as ListBoxItem; switch (pagetype) { case "Blank": pdfViewer.Document.InsertPage(insertIndex + 1,504, 661.4, null); pdfViewer.ReloadDocument(); ListBoxItem listBoxItem = GetNewItem(insertIndex + 1); BindPageList.Insert(insertIndex + 1, listBoxItem); List list = new List(); list.Add(PageEditListBox.Items[insertIndex + 1] as ListBoxItem); DealPages pages = new DealPages() { Pages = list, Op = Option.Insert }; UndoStack.Push(pages); break; default: break; } ItemsInViewHitTest(); UpdateAllPageNum(); } private void DoReplace() { OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = false; dialog.Filter = ComPDFKitDemo.Properties.Resources.OpenDialogFilter; if ((bool)dialog.ShowDialog()) { CPDFDocument doc = CPDFDocument.InitWithFilePath(dialog.FileName); int pagecount = doc.PageCount; int insertindex = PageEditListBox.Items.IndexOf(PageEditListBox.SelectedItem); if (insertindex == -1) insertindex = 0; pdfViewer.Document.ImportPagesAtIndex(doc, "1-" + pagecount, insertindex); doc.Release(); for (int i = 0; i < pagecount; i++) { var item = GetNewItem(insertindex + i); BindPageList.Insert(insertindex + i, item); if (VisiblePageIndexes.Contains(insertindex + i)) VisiblePageIndexes.Remove(insertindex + i); } IsModefied = true; ItemsInViewHitTest(); var list = GetListFromSelectedItems(); DoDelete(list,false); UpdateAllPageNum(); } } private void DoRotate(double angleStep) { List pages = new List(); for (int i = 0; i < PageEditListBox.SelectedItems.Count; i++) { var image = GetImageElement(PageEditListBox.SelectedItems[i] as ListBoxItem); pages.Add(PageEditListBox.SelectedItems[i] as ListBoxItem); double angle = (double)image.LayoutTransform.GetValue(RotateTransform.AngleProperty); angle += angleStep; angle = angle % 360; image.LayoutTransform = new RotateTransform(angle, image.ActualWidth / 2, image.ActualHeight / 2); var index = PageEditListBox.Items.IndexOf(PageEditListBox.SelectedItems[i]); pdfViewer.Document.RotatePage(index, (int)angleStep/90); pdfViewer.Document.ReleasePages(index); IsModefied = true; if (VisiblePageIndexes.Contains(index)) VisiblePageIndexes.Remove(index); } pdfViewer.ReloadDocument(); DealPages dealPages = new DealPages() { Pages = pages, Op=angleStep>0?Option.RightRotate:Option.LeftRotate }; UndoStack.Push(dealPages); ItemsInViewHitTest(); } private void DoExtract(string path) { CPDFDocument savedoc = CPDFDocument.CreateDocument(); string pagerange = GetPageParam(); bool result = savedoc.ImportPages(pdfViewer.Document, pagerange); if (!result) { SetReadModeTip(true, "Extraction exception, please try again later", false); } result = savedoc.WriteToFilePath(path); if (!result) { SetReadModeTip(true, "Save exception, please try again later", false); } IsModefied = true; savedoc.Release(); } private void DoPaste() { if (App.CopyDoc == null) { SetReadModeTip(true, "Please copy the page first", false); } int insertindex = PageEditListBox.Items.IndexOf(PageEditListBox.SelectedItem) + 1; int pagecount = App.CopyDoc.PageCount; bool result = pdfViewer.Document.ImportPagesAtIndex(App.CopyDoc, "1-" + pagecount, insertindex); if (!result) { SetReadModeTip(true, "Replication failed. Please try again later", false); return; } pdfViewer.ReloadDocument(); AddBlankPages(pagecount, insertindex); IsModefied = true; ItemsInViewHitTest(); List pageList = new List(); for (int i = 0; i < pagecount; i++) { pageList.Add(PageEditListBox.Items[insertindex + i] as ListBoxItem); } DealPages dealPages = new DealPages() { Pages = pageList, Op = Option.Insert }; UndoStack.Push(dealPages); UpdateAllPageNum(); } private void DoCopy() { App.CopyDoc = null; App.CopyDoc = CPDFDocument.CreateDocument(); string pageparm = GetPageParam(); bool result = App.CopyDoc.ImportPages(pdfViewer.Document, pageparm); if (!result) { SetReadModeTip(true, "Replication failed. Please try again later", false); return; } } private void DoExchange(List pageLists) { if (pageLists.Count <= 1) { SetReadModeTip(true, "Select multiple pages for operation", false); return; } List pages = new List(); for (int i = 0; i < pageLists.Count; i++) { int pageIndex = PageEditListBox.Items.IndexOf(pageLists[i] as ListBoxItem); pages.Add(pageIndex); } pages.Sort(); for (int i = 0; i < pages.Count; i++) { int preindex = pages[i]; int laterIndex = pages[pages.Count - i - 1]; if (laterIndex <= preindex) return; var sourceitem = PageEditListBox.Items[preindex] as ListBoxItem; var targetitem = PageEditListBox.Items[laterIndex] as ListBoxItem; BindPageList.Remove(sourceitem); BindPageList.Remove(targetitem); BindPageList.Insert(preindex, targetitem); BindPageList.Insert(laterIndex, sourceitem); pdfViewer.Document.ExchangePage(preindex, laterIndex); IsModefied = true; PageEditListBox.SelectedItems.Add(targetitem); PageEditListBox.SelectedItems.Add(sourceitem); } pdfViewer.ReloadDocument(); } private void DoDelete(List pageLists,bool tip) { if (pageLists.Count == PageEditListBox.Items.Count) { SetReadModeTip(true, "Unable to delete all pages, need to keep at least one!", false); return; } MessageBoxResult result = MessageBoxResult.OK; if (tip) { result = MessageBox.Show("Are you sure you want to delete the selected page?", null, MessageBoxButton.OKCancel); } if (result == MessageBoxResult.OK || !tip) { List pages = new List(); for (int i = 0; i < pageLists.Count; i++) { var index = PageEditListBox.Items.IndexOf(pageLists[i]); pages.Add(index); } pages.Sort(); for (int i = pages.Count - 1; i >= 0; i--) { BindPageList.RemoveAt(pages[i]); } var r = pdfViewer.Document.RemovePages(pages.ToArray()); if (!r) { SetReadModeTip(true, "The deletion fails because the operation is abnormal. Please try again later!", false); return; } pdfViewer.ReloadDocument(); IsModefied = true; UpdateAllPageNum(); } } private List GetListFromSelectedItems() { List itemlists = new List(); for(int i=0;i lists = new List(); for(int i=0;i pagesList = new List(); for (int i = 0; i < PageEditListBox.SelectedItems.Count; i++) { var item = PageEditListBox.SelectedItems[i] as ListBoxItem; var page = GetPageNumTextBlock(item); if (page != null) { pagesList.Add(int.Parse(page.Text)); } } if (pagesList.Count != 0) { pagesList.Sort(); for (int i = 0; i < pagesList.Count; i++) { if (i == 0) { pageParam += pagesList[0].ToString(); } else { if (pagesList[i] == pagesList[i - 1] + 1) { if (i >= 2) { if (pagesList[i - 1] != pagesList[i - 2] + 1) pageParam += "-"; } else pageParam += "-"; if (i == pagesList.Count - 1) { pageParam += pagesList[i].ToString(); } } else { if (i >= 2) { if (pagesList[i - 1] == pagesList[i - 2] + 1) pageParam += pagesList[i - 1].ToString(); } pageParam += "," + pagesList[i].ToString(); } } } } return pageParam; } public static BitmapSource ToBitmapSource(string path) { System.Drawing.Icon ico = System.Drawing.Icon.ExtractAssociatedIcon(path); System.Drawing.Bitmap bitmap = ico.ToBitmap(); BitmapSource returnSource; try { returnSource =System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } catch { returnSource = null; } return returnSource; } private Tuple GetRoughViewportRange(ListBox view, Size itemSize, Thickness itemMargin) { var scrollViewer = GetScrollHost(view); if (scrollViewer == null || scrollViewer.ActualHeight == 0 || scrollViewer.ActualWidth == 0) return new Tuple(0, 0, 0); try { var currentHeight = scrollViewer.ActualHeight - view.Padding.Top; var currentWidth = scrollViewer.ActualWidth; var columnCount = (int)(currentWidth / (itemSize.Width + itemMargin.Left)); var rowCount = (int)Math.Ceiling(currentHeight / (itemSize.Height + itemMargin.Bottom)); var preItemCount = (int)((scrollViewer.VerticalOffset / scrollViewer.ExtentHeight) * ((pdfViewer.Document.PageCount + columnCount - 1) / columnCount));//滑动百分比*行数 = 大概的垂直位置 preItemCount = preItemCount * columnCount; var preEnd = (int)(((scrollViewer.VerticalOffset + scrollViewer.ActualHeight) / scrollViewer.ExtentHeight) * ((pdfViewer.Document.PageCount + columnCount - 1) / columnCount)); preEnd = preEnd * columnCount + columnCount - 1; var middle = (int)Math.Ceiling(preItemCount + preEnd / 2d); return new Tuple( Math.Max(preItemCount, 0), Math.Min(view.Items.Count, preEnd), middle); } catch (Exception ex) { } return new Tuple(0, 0, 0); } #endregion } }