using ComPDFKit.PDFDocument;
using ComPDFKitViewer;
using ComPDFKitViewer.PdfViewer;
using Dropbox.Api.Team;
using ImTools;
using PDF_Master.EventAggregators;
using PDF_Master.Helper;
using PDF_Master.Model.PageEdit;
using PDF_Master.ViewModels.PageEdit;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using WpfToolkit.Controls;
using static Dropbox.Api.TeamLog.AdminAlertSeverityEnum;
namespace PDF_Master.Views.PageEdit
{
///
/// PageEditContent.xaml 的交互逻辑
///
public partial class PageEditContent : UserControl
{
///
/// 用于通知刷新图片的事件
/// 因为目前的图片刷新策略依赖很多UI事件判断,因为将主要判断逻辑放在UI层,VM负责图片刷新,非必要情况尽量不要采用这种形式
///
private IEventAggregator eventor;
///
/// 暂存的唯一索引值,用于区分多页签
///
private string unicode;
///
/// 是否是加载时第一次触发滚动
///
private bool isFirstScrollChange = true;
///
/// 用于判断滚轮停止的计时器
///
private DispatcherTimer timer = new DispatcherTimer();
///
/// 判断是否开始框选
///
private bool startChoose = false;
///
/// 框选的起始位置
///
private Point starPosition = new Point();
///
/// 记录当前滑块的状态
///
private ScrollEventType scrolltype = ScrollEventType.EndScroll;
//鼠标点击时在item中的位置 实现类似点哪拖哪的细节
private double item_x;
private double item_y;
//插入标记代表的插入位置
private int InsertIndex = -1;
//拖动的Item
private PageEditItem tempItem;
///
/// 是否正在拖拽排序中,通过该变量避免单击触发拖动
///
private bool isDraging = false;
//是否正在从外部拖入文件
public bool isDragingEnter { get; set; } = false;
//自动滚动速度
private int speed = 0;
private PageEditContentViewModel viewModel;
private List dropMoveFiles = null;
public PageEditContent()
{
InitializeComponent();
dropMoveFiles = new List();
}
public PageEditContent(IEventAggregator eventAggregator) : this()
{
eventor = eventAggregator;
unicode = App.mainWindowViewModel.SelectedItem.Unicode;
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(0.3);
timer.Tick += Timer_Tick;
viewModel = this.DataContext as PageEditContentViewModel;
viewModel.PageEditItems.CollectionChanged += PageEditItems_CollectionChanged;
//订阅页面刷新事件
eventor.GetEvent().Subscribe(OneNotifyEvent, e => e.Unicode == unicode);
eventAggregator.GetEvent().Subscribe(CleanSelectAll, e => e.Unicode == unicode);
//当退出页面编辑后
//缩略图选中页面,要和当前显示的页面,一致
eventAggregator.GetEvent().Subscribe(OnPageEditSelectedItemRefreshEvent, e => e.Unicode == unicode);
}
private void OnPageEditSelectedItemRefreshEvent(PageEditSelectedItemEventArgs args)
{
if (viewModel.IsBOTAThumb == Visibility.Visible && args.SelectedItemIndex != -1)
{
viewModel.ListSelectedIndex = args.SelectedItemIndex;
ListPageEdit.ScrollIntoView(ListPageEdit.SelectedItem);
}
}
private void Timer_Tick(object sender, EventArgs e)
{
PulishEvent();
timer?.Stop();
}
private void PageEditItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//加入loaded判断,避免显示前频繁进入该事件,影响BOTA切换事件
if (this.IsLoaded)
{
//未选 显示页面大小,插入文件后 会影响
//if (viewModel.IsShowPageSize)
//{
// viewModel.ShowedPageSize = Visibility.Visible;
// viewModel.HidePageSize = Visibility.Collapsed;
//}
//else
//{
// viewModel.ShowedPageSize = Visibility.Collapsed;
// viewModel.HidePageSize = Visibility.Visible;
//}
//BOTA缩略图里 插入子项时,刷新子项大小
if (GridBOTAHeader.Visibility == Visibility.Visible && e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
ItemSuitAcutalWidth(this.ActualWidth);
}
//补充判断条件,修复页数多的文档,在BOTA展开的情况下,切换到页面编辑会卡死的问题
if (GridBOTAHeader.Visibility != Visibility.Visible && !viewModel.Initializing)
{
//页面编辑模式下,页面总数变化后用于通知BOTA面板进行数据集刷新
//只需要页面编辑通知缩略图,不需要缩略图通知页面编辑,因为现在每次导航进去时都会刷新item个数
eventor.GetEvent().Publish(new PageEditNotifyEventArgs(unicode, NotifyType.PageCountChanged));
}
}
}
private void OneNotifyEvent(PageEditNotifyEventArgs e)
{
switch (e.Type)
{
case NotifyType.RefreshPage:
//计算当前区域的页面范围后传递回VM
PulishEvent();
break;
case NotifyType.SelectItems:
int index = 0;
//根据Vm的参数选中部分页面
if (e.PageRange.Count == 1)
{
if (e.PageRange[0] > 0)
{
ListPageEdit.SelectedIndex = e.PageRange[0] - 1;
}
if (ListPageEdit.SelectedItem != null)
{
ListPageEdit.ScrollIntoView(ListPageEdit.SelectedItem);
index = ListPageEdit.SelectedIndex;
viewModel.RightSelectedIndex = index;
}
}
else
{
ListPageEdit.SelectedItems.Clear();
viewModel.RightSelectedIndexs.Clear();
for (int i = 0; i < e.PageRange.Count; i++)
{
index = e.PageRange[i] - 1;
if (index < ListPageEdit.Items.Count)
{
ListPageEdit.SelectedItems.Add(ListPageEdit.Items[index]);
}
if (ListPageEdit.SelectedItems.Count > 0)
{
viewModel.RightSelectedIndex = index;
viewModel.RightSelectedIndexs.Add(index);
}
if (GridBOTAHeader.Visibility == Visibility.Visible)
{
if (ListPageEdit.SelectedItems.Count > 0)
{
if (ListPageEdit.Items.IndexOf(ListPageEdit.SelectedItems[ListPageEdit.SelectedItems.Count - 1]) == -1)
{
ListPageEdit.ScrollIntoView(ListPageEdit.SelectedItem);
}
else
{
ListPageEdit.ScrollIntoView(ListPageEdit.SelectedItems[ListPageEdit.SelectedItems.Count - 1]);
}
}
}
else
{
ListPageEdit.ScrollIntoView(ListPageEdit.SelectedItem);
}
}
}
if (ListPageEdit.SelectedItems.Count > 0)
{
if (ListPageEdit.SelectedItems.Count >= 2)
{
viewModel.maxSelectedIndex = index;
//页码 下拉框 ,选择全选页面、奇数、偶数等情况,偶现IsMultiSelected=false,这里先强制设置一下
viewModel.IsMultiSelected = true;
}
else
{
viewModel.maxSelectedIndex = -1;
viewModel.IsMultiSelected = false;
}
viewModel.IsMouseRightButtonDown = true;
viewModel.IsMouseRightButtonDown = false;
}
//以下方法 实用性不强,会跳转失败
//缩略图 复制粘贴后,选中页面,要与阅读视图 对应
//if (viewModel.viewContentViewModel.isInPageEdit == false && GridBOTAHeader.Visibility == Visibility.Visible)
//{
// viewModel.PDFViewer.GoToPage(index);
//}
break;
case NotifyType.PageCountChanged:
if (GridBOTAHeader.Visibility == Visibility.Visible)
{
viewModel?.GetSourceItems(false);
}
break;
default:
break;
}
}
private void CleanSelectAll(CleanSelectAllArgs obj)
{
ListPageEdit.SelectedItems.Clear();
ListPageEdit.SelectedIndex = viewModel.PDFViewer.CurrentIndex;
}
#region UI事件
///
/// 每次显示的时候就触发事件,刷新所有图片
///
///
///
private void PageEdit_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
//BOTA缩略图模式 需要先计算item宽度,再进行渲染页面的计算
if (GridBOTAHeader.Visibility == Visibility.Visible)
{
ItemSuitAcutalWidth(this.ActualWidth);
}
//当前页面没有发生变化时,刷新图片 这种情况下会拿两次图,需要留意
PulishEvent();
//当前页面发生变化时通过ScrollChanged事件来刷新图片
isFirstScrollChange = true;
}
}
///
/// 鼠标滚轮滚动时触发的事件
///
///
///
public void ListPageEdit_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (isFirstScrollChange)
{
PulishEvent();//第一次加载时触发的Scollchange 直接刷新界面,减少白板显示时间
isFirstScrollChange = false;
return;
}
else
{
if (e.VerticalChange != 0)
timer?.Start();//暂时找不到比较好的 判断Scroller停止的方法,先用计时器粗略判断
}
}
///
/// 拖动右侧滑块时触发的事件
///
///
///
private void ListPageEdit_Scroll(object sender, System.Windows.Controls.Primitives.ScrollEventArgs e)
{
scrolltype = e.ScrollEventType;
if (scrolltype != System.Windows.Controls.Primitives.ScrollEventType.EndScroll)
{
timer?.Stop();
return;
}
PulishEvent();
}
#endregion UI事件
#region 方法
///
/// 发布事件
///
public void PulishEvent()
{
//判空 避免某些乱七八糟的情况下异常
if (ListPageEdit != null & ListPageEdit.Items.Count > 0)
{
var itemSize = new Size((ListPageEdit.Items[0] as PageEditItem).ItemSize.Width + 32, (ListPageEdit.Items[0] as PageEditItem).ItemSize.Height + 30);
var range = GetRoughFromView(ListPageEdit, itemSize, new Thickness(5, 10, 5, 10));
if ((bool)TbnTwoLine.IsChecked)
{
///双列模式下要计算两列item
range = new Tuple(range.Item1, range.Item2 * 2, range.Item3);
}
eventor.GetEvent().Publish(new PageEditRefreshEventArgs() { Unicode = unicode, PageRange = range });
}
}
///
/// 获取滑轨的垂直偏移量,结合item总数和Item尺寸以及间隔,来估算实际展示的item范围
/// 返回值为页面范围 从1开始
///
///
///
///
///
private Tuple GetRoughFromView(ListBox view, Size itemSize, Thickness itemMargin)
{
//var scrollViewer = GetScrollHost(view);
var scrollViewer = CommonHelper.FindVisualChild(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) * ((view.Items.Count + columnCount - 1) / columnCount));//滑动百分比*行数 = 大概的垂直位置
preItemCount = preItemCount * columnCount;
var preEnd = (int)(((scrollViewer.VerticalOffset + scrollViewer.ActualHeight) / scrollViewer.ExtentHeight) * ((view.Items.Count + 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 { }
return new Tuple(0, 0, 0);
}
///
/// 获取listbox里的ScrollViewer对象
/// 留意如果有重写ListBox对象,该方法可能无效
///
///
///
private ScrollViewer GetScrollHost(ListBox listBox)
{
if (VisualTreeHelper.GetChildrenCount(listBox) > 0)
{
int s = VisualTreeHelper.GetChildrenCount(listBox);
Border border = VisualTreeHelper.GetChild(listBox, 0) as Border;
if (border != null)
{
return VisualTreeHelper.GetChild(border, 0) as ScrollViewer;
}
}
return null;
}
#endregion 方法
///
/// 输入框显示时,自动获取焦点
///
///
///
private void TextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
(sender as Control).Focus();
}
}
private void ListPageEdit_PreviewMouseMove(object sender, MouseEventArgs e)
{
try
{
if (e.LeftButton == MouseButtonState.Pressed && !isDragingEnter)
{
//鼠标框选逻辑
if (startChoose)
{
viewModel.IsMouseRightButtonDown = true;
viewModel.IsMouseRightButtonDown = false;
viewModel.RightSelectedIndex = -1;
viewModel.RightSelectedIndexs.Clear();
var position = e.GetPosition(ListPageEdit);
if (position.X < 5 || position.X > ListPageEdit.ActualWidth - 5 || position.Y < 5 || position.Y > ListPageEdit.ActualHeight - 5)
{
startChoose = false;
RectChoose.Visibility = Visibility.Collapsed;
//暂时未想到靠近顶部和底部自动翻滚的好方法,只能先屏蔽这部分功能
Mouse.Capture(null);
return;
}
//矩形框内的item设为选中
DoSelectItems();
return;
}
//拖拽排序的逻辑
else
{
var pos = e.GetPosition(ListPageEdit);
if (pos.Y < 0 || pos.Y > ListPageEdit.ActualHeight)
{
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
return;
}
HitTestResult result = VisualTreeHelper.HitTest(ListPageEdit, pos);
if (result == null)
{
return;
}
var listBoxItem = CommonHelper.FindVisualParent(result.VisualHit);
if (listBoxItem == null)
{
return;
}
isDragingEnter = false;
tempItem = listBoxItem.DataContext as PageEditItem;
var item_pos = e.GetPosition(listBoxItem);
if (item_pos != null)
{
item_x = item_pos.X;
item_y = item_pos.Y;
}
//string filename = Guid.NewGuid().ToString() + ".pdf";
//string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), filename);
//System.IO.File.Create(tempPath);
//string[] files = new string[1];
//files[0] = tempPath;
var scroll = GetScrollHost(ListPageEdit);
//页面 是App内的拖拽 ,还是拖拽 页面 出 App 是一起处理
//将付费锁逻辑提前,避免拖拽出窗体成功
if (!ServiceHelper.IAPBeforeFunction())
{
return;
}
#region 拖拽 页面 到 桌面/文件夹 ,提取文件
//C:\Users\oyxh\AppData\Local\Temp\
string dir = System.IO.Path.Combine(System.IO.Path.GetTempPath());
if (!System.IO.Directory.Exists(dir))
{
System.IO.Directory.CreateDirectory(dir);
}
//string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), filename);
List pages = GetSelectedItems();
pages.Sort();
string[] files = new string[1];
if (pages.Count > 0)
{
//多选页面 提取成一个文件夹
string filename = viewModel.PDFViewer.Document.FileName + " " + "pages " + CommonHelper.GetPageParmFromList(pages) + ".pdf";
string tempPath = System.IO.Path.Combine(dir, filename);
//删除 临时文件的同名文件
if (File.Exists(tempPath))
{
File.Delete(tempPath);
}
string path = CommonHelper.CreateFilePath(tempPath);
files[0] = path;
dropMoveFiles.Add(path);
CPDFDocument savedoc = CPDFDocument.CreateDocument();
string range = String.Join(",", pages);
bool result1 = savedoc.ImportPages(viewModel.PDFViewer.Document, range);
//if (!result1)
//{
// viewModel.ShowToast();
// viewModel.IsLoading = Visibility.Collapsed;
// return;
//}
result1 = savedoc.WriteToFilePath(path);
if (!result1)
{
viewModel.ShowToast();
}
savedoc.Release();//释放内存
}
#region 多选页面 分别生成单独文件
//List pagenums = new List();
//for (int i = 0; i < viewModel.PageEditItems.Count; i++)
//{
// if (viewModel.PageEditItems[i].Selected)
// {
// pagenums.Add(viewModel.PageEditItems[i].PageNumber);
// }
//}
//string[] files = new string[pagenums.Count];
//for (int i = 0; i < pagenums.Count; i++)
//{
// string filename = viewModel.PDFViewer.Document.FileName + " " + pagenums[i] + ".pdf";
// string tempPath = System.IO.Path.Combine(dir, filename);
// string path = CommonHelper.CreateFilePath(tempPath);
// files[i] = path;
// dropMoveFiles.Add(path);
// CPDFDocument savedoc = CPDFDocument.CreateDocument();
// bool result2 = savedoc.ImportPages(viewModel.PDFViewer.Document, pagenums[i].ToString());
// if (!result2)
// {
// savedoc.Release();
// continue;
// }
// result2 = savedoc.WriteToFilePath(path);
// if (!result2)
// {
// savedoc.Release();
// continue;
// }
// savedoc.Release();//释放内存
//}
#endregion 多选页面 分别生成单独文件
//string[] files = new string[1];
//files[0] = tempPath;
DataObject dataObj = new DataObject(DataFormats.FileDrop, files);
#endregion 拖拽 页面 到 桌面/文件夹 ,提取文件
//禁用从窗体拖拽到桌面的方法
//DataObject dataObj = new DataObject(listBoxItem);
//注意!!!目前是通过DragDropEffects类型来区分app内拖拽和外部文件拖入。否则页面文件拖拽页面到PDFViewer,也会新生成一个页签
//如果这里的DragDropEfeects类型有改动,也需要调整ViewContent里UserControl_Drop函数的判断逻辑
DragDrop.DoDragDrop(ListPageEdit, dataObj, DragDropEffects.Copy);
Mouse.Capture(ListPageEdit);
//CleanDropMoveFiles();
return;
}
}
RectChoose.Visibility = Visibility.Collapsed;
startChoose = false;
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
Mouse.Capture(null);
}
catch
{
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
}
}
private List GetSelectedItems()
{
List pages = new List();
for (int i = 0; i < ListPageEdit.SelectedItems.Count; i++)
{
//这样拿 更精准
if (ListPageEdit.SelectedItems[i] is PageEditItem pageEditItem)
{
pages.Add(pageEditItem.PageNumber);
}
}
return pages;
}
///
/// 判断是否开始框选、记录框选起始位置
///
///
///
private void ListPageEdit_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition(ListPageEdit);
HitTestResult result = VisualTreeHelper.HitTest(ListPageEdit, pos);
if (result == null)
{
return;
}
//未选中item 并且不是点击滑轨时 开始框选
var listBoxItem = CommonHelper.FindVisualParent(result.VisualHit);
var scroller = CommonHelper.FindVisualParent(result.VisualHit);
if (listBoxItem == null)
{
viewModel.IsMouseRightButtonDown = true;
viewModel.IsMouseRightButtonDown = false;
viewModel.RightSelectedIndex = -1;
viewModel.RightSelectedIndexs.Clear();
if (scroller != null)
{
startChoose = false;
return;
}
//点击空白处时开始框选
startChoose = true;
if (ListPageEdit.SelectedItems.Count > 0)
{
// 缩略图 点击空白取消选中
if (GridBOTAHeader.Visibility != Visibility.Visible)
{
ListPageEdit.SelectedItems.Clear();
}
}
starPosition = e.GetPosition(ListPageEdit);
starPosition = new Point(starPosition.X, starPosition.Y + GetWrapPanel(ListPageEdit).VerticalOffset);
Mouse.Capture(ListPageEdit);
//点击空白处时 获取焦点;方便跨文件复制粘贴
ListPageEdit.Focus();
return;
}
//选中了item 时,不能框选
startChoose = false;
isDragingEnter = false;
//更改系统的选中规则,选中状态下,鼠标松开后取消选中
//方便实现多选拖拽功能
if (listBoxItem.IsSelected == true && !Keyboard.IsKeyDown(Key.LeftCtrl))
{
e.Handled = true;
}
}
private void ListPageEdit_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition(ListPageEdit);
HitTestResult result = VisualTreeHelper.HitTest(ListPageEdit, pos);
if (result == null)
{
return;
}
var listBoxItem = CommonHelper.FindVisualParent(result.VisualHit);
if (listBoxItem == null)
{
return;
}
//更改系统默认的选中规则,多选后,鼠标单击抬起后再选中单个
//拖拽框选之后的抬起鼠标不进入处理
if (!startChoose && !Keyboard.IsKeyDown(Key.LeftCtrl) && !Keyboard.IsKeyDown(Key.LeftShift))
{
ListPageEdit.SelectedItems.Clear();
ListPageEdit.SelectedItem = listBoxItem;
listBoxItem.IsSelected = true;
return;
}
Mouse.Capture(null);
//结束鼠标框选
startChoose = false;
RectChoose.Visibility = Visibility.Collapsed;
}
///
/// 获取Listobox的Wrappanel容器
///
///
///
public VirtualizingWrapPanel GetWrapPanel(ListBox listBox)
{
Border border = VisualTreeHelper.GetChild(listBox, 0) as Border;
var panel = CommonHelper.FindVisualChild(border);
return panel;
}
///
///根据鼠标拖选的框 选中矩形框里面的Item
///
private void DoSelectItems()
{
var s = GetScrollHost(ListPageEdit);
Point start = new Point();
//通过 实时的垂直偏移量和第一次的偏移量抵消,来获取准确的垂直偏移值。
start = new Point(starPosition.X, starPosition.Y - s.VerticalOffset);
var rec = new Rect(start, Mouse.GetPosition(ListPageEdit));
RectChoose.Margin = new Thickness(rec.Left, rec.Top, 0, 0);
RectChoose.Width = rec.Width;
RectChoose.Height = rec.Height;
RectChoose.Visibility = Visibility.Visible;
Trace.WriteLine(rec.Width);
Trace.WriteLine(rec.Height);
//检测遍历所有项,筛选在矩形框中的Item
for (int i = 0; i < ListPageEdit.Items.Count; i++)
{
var _item = ListPageEdit.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;
//通过这一步来避免重复误选中
var parent = CommonHelper.FindVisualParent(_item);
if (parent == null)
{
continue;
}
var v = VisualTreeHelper.GetOffset(_item);
if (rec.IntersectsWith(new Rect(v.X, v.Y, _item.ActualWidth, _item.ActualHeight)))
{
ListPageEdit.SelectedItems.Add(ListPageEdit.Items[i]);
}
else
{
// 缩略图 点击空白取消选中
if (GridBOTAHeader.Visibility != Visibility.Visible)
{
ListPageEdit.SelectedItems.Remove(ListPageEdit.Items[i]);
}
}
}
return;
}
///
/// 退出拖拽模式
///
private void ExitDraging()
{
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
isDraging = false;
}
///
/// 拖拽释放后的处理逻辑
///
///
///
private async void ListPageEdit_Drop(object sender, DragEventArgs e)
{
//isDragingEnter = false;
if (!isDraging)
{
//未拖拽时隐藏插入标记和虚影
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
return;
}
//拖入非法格式释放时 返回
string[] file = (string[])e.Data.GetData(DataFormats.FileDrop);
if (file != null)
{
#region 从外部拖拽插入文件
if (isDragingEnter)
{
//不能将付费锁 放到 grid_DragOver,会卡顿
//将付费锁逻辑提前,避免因弹窗显示后导致虚影无法消失问题
if (!ServiceHelper.IAPBeforeFunction())
{
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
isDragingEnter = false;
return;
}
//注释从外部拖拽插入文件的功能
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
Array.Reverse(files);
foreach (string item in files)
{
System.IO.FileInfo info = new System.IO.FileInfo(item);
string fileName = viewModel.GetInsertFromFile(item);
//if (System.IO.Path.GetExtension(item).ToLower() == ".pdf" && info.Length > 0)
//{
// int index = InsertIndex == -1 ? 0 : InsertIndex;
// await viewModel.InsertFromFile(index, item);
// viewModel.ReloadAfterOption(true, true, new Tuple(0, ListPageEdit.Items.Count));
//}
if (info.Length > 0 && File.Exists(fileName))
{
int index = InsertIndex == -1 ? 0 : InsertIndex;
//将文档验证是否为空,是否解密,置前,若为空直接退出
bool IsLocked = viewModel.GetDocumentIsDiscryptied(fileName, null, out CPDFDocument doc, out string password);
if (IsLocked == false)
{
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
isDragingEnter = false;
return;
}
ListPageEdit.SelectedItems.Clear();
bool flag = await viewModel.InsertFromFile(index, fileName, doc, password);
if (flag)
{
viewModel.ReloadAfterOption(true, true, new Tuple(0, ListPageEdit.Items.Count));
}
}
}
//其他文件 则新增一个页签打开
// DragAddTab.Invoke(dragingEnterPath, new RoutedEventArgs());//底层库需要加一个 Load(TPDFDocument)的接口
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
isDragingEnter = false;
return;
}
#endregion 从外部拖拽插入文件
//return;
}
var pos = e.GetPosition(ListPageEdit);
var result = VisualTreeHelper.HitTest(ListPageEdit, pos);
if (result == null)
{
//超出当前可控区域
ExitDraging();
return;
}
//查找元数据
//var sourcePerson = e.Data.GetData(typeof(StackPanel)) as StackPanel;
if (tempItem == null)
{
ExitDraging();
return;
}
//查找目标数据
int targetindex = 0;//目标插入位置
if (InsertIndex != -1)
{
//往前移动时 此index 不是准确的,需要处理++
targetindex = InsertIndex;
}
//else//基本不会命中 仅作为保险措施
//{
// var listBoxItem = CommonHelper.FindVisualParent(result.VisualHit);
// if (listBoxItem == null)
// {
// ////鼠标停留在两个item之间或其他无效区域 暂时不做处理(比较麻烦)
// ExitDraging();
// return;
// }
// var targetPerson = listBoxItem;
// targetPerson.Opacity = 1;
// sourcePerson.Opacity = 1;
// if (ReferenceEquals(targetPerson, sourcePerson))
// {
// ExitDraging();
// return;
// }
// targetindex = ListPageEdit.Items.IndexOf(targetPerson);
//}
List list = new List();
List sourceindex = new List();//需要保存每个页面对应的位置
//开始排序
List pages = new List();
//要先对所有选中项 根据页码排序
for (int i = 0; i < ListPageEdit.SelectedItems.Count; i++)
{
var pageindex = ListPageEdit.Items.IndexOf(ListPageEdit.SelectedItems[i] as PageEditItem);
pages.Add(pageindex);//存入的为页码索引值
}
if (pages.Count <= 0)
{
ExitDraging();
return;
}
viewModel.DragToSort(targetindex, pages);
ExitDraging();
isDraging = false;
CleanDropMoveFiles();
}
///
/// 拖拽完成后,清空临时目录 的文件
///
private void CleanDropMoveFiles()
{
if (dropMoveFiles != null)
{
if (dropMoveFiles.Count > 0)
{
for (int i = 0; i < dropMoveFiles.Count; i++)
{
if (File.Exists(dropMoveFiles[i]))
{
File.Delete(dropMoveFiles[i]);
}
}
dropMoveFiles.Clear();
}
}
}
private void MidLane_Drop(object sender, DragEventArgs e)
{
ListPageEdit_Drop(sender, e);
}
private void ImgPicture_Drop(object sender, DragEventArgs e)
{
ListPageEdit_Drop(sender, e);
}
///
/// 拖拽事件写在外部的Grid里,会更加流畅
///
///
///
private void Grid_DragOver(object sender, DragEventArgs e)
{
try
{
Trace.WriteLine("Grid_DragOver 文件拖出App");
//ctrl建按下 不显示插入标记和虚影 因为释放不会响应drop事件
if (e.KeyStates == (DragDropKeyStates.ControlKey | DragDropKeyStates.LeftMouseButton) || e.KeyStates == (DragDropKeyStates.ShiftKey | DragDropKeyStates.LeftMouseButton | DragDropKeyStates.ControlKey))
return;
//从外部拖入文件时 返回
string[] file = (string[])e.Data.GetData(DataFormats.FileDrop);
if (file != null)
{
}
//滚动后有 位置不准确 要减去滚动偏移量
//控制线的位置
var pos = e.GetPosition(ListPageEdit);
var result = VisualTreeHelper.HitTest(ListPageEdit, pos);
if (result == null)
{
return;
//MidLane.Visibility = Visibility.Collapsed;
//return;
}
//获取当前鼠标指针下的容器
var listBoxItem = CommonHelper.FindVisualParent(result.VisualHit);
if (listBoxItem == null)
{
//页面 拖出App后存在极少数情况会显示 标记线、缩略图,注释掉=》item中间不会有虚影,观感不好
//LineInset.Visibility = Visibility.Collapsed;
//ImgPicture.Visibility = Visibility.Collapsed;
//MidLane.Visibility = Visibility.Collapsed;
//return;
}
#region 计算虚影位置
//xaml层 要设置 虚影控件为左上
double xPos = 0;
double yPos = 0;
//内部拖动
if (!isDragingEnter)
{
if (tempItem != null)
{
ImgPicture.Width = tempItem.ItemSize.Width;
ImgPicture.Height = tempItem.ItemSize.Height;
ImgPicture.Source = tempItem.Image;
xPos = e.GetPosition(ListPageEdit).X - item_x;
yPos = e.GetPosition(ListPageEdit).Y - item_y;
ImgPicture.Visibility = Visibility.Visible;
}
}
else
{
ImgPicture.Visibility = Visibility.Collapsed;
DragDropHelper.DragOver(this, e);
//从外部拖入的逻辑
//var pic = ToBitmapSource(dragingEnterPath);
//ShadowPicture.Width = pic.Width;
//ShadowPicture.Height = pic.Height;
//ShadowPicture.Source = pic;
//xPos = e.GetPosition(ListPageEdit).X - pic.Width / 2;
//yPos = e.GetPosition(ListPageEdit).Y - pic.Height / 2;
}
ImgPicture.Margin = new Thickness(xPos, yPos, 0, 0);
#endregion 计算虚影位置
#region 计算插入标记位置
var scroll = GetScrollHost(ListPageEdit);
if (listBoxItem != null)
{
//虚拟化影响到该值计算
var p = VisualTreeHelper.GetOffset(listBoxItem);//计算控件在容器中的偏移(位置)
LineInset.Visibility = Visibility.Visible;
//优化 虚影显示时机,暂时注释这一部分
//if (!isDragingEnter)
//{
// ImgPicture.Visibility = Visibility.Visible;
//}
//else
//{
// ImgPicture.Visibility = Visibility.Collapsed;
//}
var panel = GetWrapPanel(ListPageEdit);
//var item = panel.ItemSize.Width;
//var item = (ListPageEdit.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem).DesiredSize.Width;
var item = listBoxItem.DesiredSize.Width;
int count = (int)(panel.ViewportWidth / item);
var gap = (panel.ViewportWidth - count * item) / (count + 1) * 1.0;
LineInset.X2 = LineInset.X1 = p.X + gap / 2 + listBoxItem.DesiredSize.Width;
if (pos.X < p.X + gap / 2 + listBoxItem.ActualWidth / 2)
{
LineInset.X2 = LineInset.X1 = p.X - gap / 2;
InsertIndex = ListPageEdit.Items.IndexOf(listBoxItem.DataContext as PageEditItem);
}
else
{
InsertIndex = ListPageEdit.Items.IndexOf(listBoxItem.DataContext as PageEditItem) + 1;
}
Console.WriteLine("InsertIndex:{0}\r\n", InsertIndex);
//MidLane.Y1 = p.Y - scroll.VerticalOffset;//向下滑动后要减去滑动值
LineInset.Y1 = p.Y;
if (LineInset.Y1 < 0)//避免超出上边界
{
LineInset.Y1 = 0;
}
//MidLane.Y2 = p.Y + listBoxItem.ActualHeight - scroll.VerticalOffset;//仿智能滚动后可能会导致 垂直滚动偏量不准确
LineInset.Y2 = p.Y + listBoxItem.ActualHeight;
if (LineInset.Y2 < 0)
{
LineInset.Y2 = 0;
}
}
#endregion 计算插入标记位置
//暂时处理 鼠标移出边框时,虚影的显示问题
//230612 拖拽逻辑,为了更好的效果体现,暂时注释
if (pos.Y <= 30 || pos.Y >= ListPageEdit.ActualHeight - 10)
{
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
}
if (pos.X <= 40 || pos.X >= scroll.ViewportWidth - 50)
{
LineInset.Visibility = Visibility.Collapsed;
ImgPicture.Visibility = Visibility.Collapsed;
}
#region 靠近上下边界时,自动滚动,离边界越近,滚动速度越快
speed = 0;
if (pos.Y >= ListPageEdit.ActualHeight - 30)
{
speed = 30 - (int)(ListPageEdit.ActualHeight - pos.Y);
}
else if (pos.Y <= 30)
{
speed = (int)(pos.Y - 30);
}
var v = scroll.VerticalOffset;
scroll.ScrollToVerticalOffset(v + speed);//触发连续滚动
#endregion 靠近上下边界时,自动滚动,离边界越近,滚动速度越快
}
catch
{
}
}
///
/// 右键不会选中页面,不要跳转
///
///
///
private void ListBoxItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
//viewModel.IsAddPages = false;
viewModel.IsMouseRightButtonDown = true;
viewModel.RightSelectedIndex = -1;
viewModel.RightSelectedIndexs.Clear();
var item = (sender as ListBoxItem).DataContext as PageEditItem;
if (item != null)
{
viewModel.RightSelectedIndex = item.PageNumber - 1;
if (ListPageEdit.SelectedItems.Count > 1)
{
viewModel.IsMultiSelected = true;
viewModel.maxSelectedIndex = ListPageEdit.Items.IndexOf(ListPageEdit.SelectedItems[ListPageEdit.SelectedItems.Count - 1]);
foreach (var page in ListPageEdit.SelectedItems)
{
if (page is PageEditItem pageEdit)
{
viewModel.RightSelectedIndexs.Add(pageEdit.PageNumber - 1);
}
}
}
else
{
//页面编辑 右键选中,bota 缩略图 右键不选中也不跳转
viewModel.ListSelectedIndex = viewModel.RightSelectedIndex;
if (viewModel.IsBOTAThumb == Visibility.Visible)
{
viewModel.ListSelectedIndex = -1;
}
viewModel.IsMultiSelected = false;
viewModel.maxSelectedIndex = -1;
}
}
//拦截响应选中事件
e.Handled = true;
}
private void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//viewModel.IsAddPages = false;
viewModel.IsMouseRightButtonDown = true;
viewModel.IsMouseRightButtonDown = false;
viewModel.RightSelectedIndex = -1;
viewModel.RightSelectedIndexs.Clear();
//增加辅助判断,防止误触发 拖动排序
//为了排除 页面 拖出App后,点击选择页面,造成拖动
isDraging = false;
if (GridBOTAHeader.Visibility == Visibility.Visible && viewModel.PDFViewer != null)
{
if (Keyboard.Modifiers == ModifierKeys.Shift || Keyboard.Modifiers == ModifierKeys.Control)
{
return;
}
var item = (sender as ListBoxItem).DataContext as PageEditItem;
if (item != null)
{
viewModel.PDFViewer.GoToPage(item.PageNumber - 1);
}
}
}
private void ListBoxItem_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
//双击回到PDFViewer界面
var item = sender as ListBoxItem;
if (item != null)
{
var index = ListPageEdit.ItemContainerGenerator.IndexFromContainer(item);
//双击事件无法绑定Command 暂时采用这种方式调用VM里的方法
viewModel.BackToPDFViewer(index);
}
}
}
private void PageEdit_SizeChanged(object sender, SizeChangedEventArgs e)
{
//BOTA缩略图模式下需要调整Item宽度
if (GridBOTAHeader.Visibility == Visibility.Visible)
{
ItemSuitAcutalWidth(e.NewSize.Width);
}
if (e.NewSize.Width > 0)
{
//宽度变化后刷新一次视图 修复重复点击缩略图后图片不显示的问题
PulishEvent();
}
}
private void ItemSuitAcutalWidth(double width)
{
//缩略图模式下,保持一列或者两列显示
if ((bool)TbnTwoLine.IsChecked)
{
var itemwidth = (width - 140) / 2;
if (itemwidth < 0)
{
itemwidth = width / 4;
}
var itemHeight = 294 * itemwidth / 208.0;
viewModel.ChangeItemSize(new Size(itemwidth, itemHeight));
}
else
{
var itemwidth = 0.6 * width;
var itemheight = 294 * itemwidth / 208.0;
viewModel.ChangeItemSize(new Size(itemwidth, itemheight));
}
}
private void TbnTwoLine_Click(object sender, RoutedEventArgs e)
{
ItemSuitAcutalWidth(this.ActualWidth);
PulishEvent();
}
///
/// 用来判断是否有外界拖入的事件
///
///
///
private void Grid_PreviewDragEnter(object sender, DragEventArgs e)
{
Trace.WriteLine("Grid_PreviewDragEnter 文件拖出App");
var files = (System.Array)e.Data.GetData(DataFormats.FileDrop);
if (files == null)//为null 表示内部拖动 触发的
{
return;
}
else
{
string temp = System.IO.Path.Combine(System.IO.Path.GetTempPath());
isDragingEnter = false;
foreach (string file in files)
{
if (File.Exists(file))
{
string dic = System.IO.Path.GetDirectoryName(file) + "\\";
//在 App内拖拽,或将 页面 拖出App
if (string.Compare(dic, temp, StringComparison.OrdinalIgnoreCase) == 0)
{
isDragingEnter = false;
}
//从外部 拖文件 进App
else
{
System.IO.FileInfo info = new System.IO.FileInfo(file);
// 文件里包含有pdf格式文件,就允许拖入
string type = System.IO.Path.GetExtension(file).ToLower();
if (viewModel.Txt.Contains(type) ||
viewModel.Word.Contains(type) ||
viewModel.Ppt.Contains(type) ||
viewModel.Excel.Contains(type) ||
viewModel.Html.Contains(type) ||
viewModel.Image.Contains(type) ||
viewModel.Pdf.Contains(type) && info.Length > 0)
{
isDragingEnter = true;
}
//if (System.IO.Path.GetExtension(file).ToLower() == ".pdf" && info.Length > 0)
//{
// isDragingEnter = true;
//}
}
////文件拖出app 最后在这里 结束
//if (isExtractEnter)
//{
// isExtractEnter = false;
// return;
//}
//else
//{
// System.IO.FileInfo info = new System.IO.FileInfo(file);
// //只要拖拽进来的文件里包含有pdf格式文件,就允许拖入
// if (System.IO.Path.GetExtension(file).ToLower() == ".pdf" && info.Length > 0)
// {
// isDragingEnter = true;
// isExtractEnter = false;
// }
//}
}
}
//viewModel.IsAddPages = true;
DragDropHelper.DragEnter(this, e);
}
}
private void Grid_DragLeave(object sender, DragEventArgs e)
{
DragDropHelper.DragLeave();
}
private void Grid_Drop(object sender, DragEventArgs e)
{
DragDropHelper.Drop(this, e);
}
private void ListBoxItem_DragLeave(object sender, DragEventArgs e)
{
//增加辅助判断,防止误触发 拖动排序
//较大幅度拖动才能触发排序
isDraging = true;
}
private void Border_Drop(object sender, DragEventArgs e)
{
}
private async void TextBoxEx_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var text = sender as TextBox;
if (text != null)
{
await Task.Delay(50);
text.Focus();
}
}
private void TextBoxEx_TextChanged(object sender, TextChangedEventArgs e)
{
var text = sender as TextBox;
if (text.Visibility == Visibility.Visible && string.IsNullOrEmpty(text.Text))
{
text.Focus();
}
}
private void TextBoxEx_LostFocus(object sender, RoutedEventArgs e)
{
//因为需要处理点击按钮或者点击列表失去焦点是 不进行弹窗 因此写在cs里,方便获取UI控件
var element = FocusManager.GetFocusedElement(this);
var visual = VisualTreeHelper.HitTest(this, Mouse.GetPosition(this));
//点击其他区域失去焦点时 不响应页码判断逻辑
if (visual != null)
{
var listbox = CommonHelper.FindVisualParent(visual.VisualHit);
if (listbox != null)
{
//点击在listbox列表内
return;
}
var image = CommonHelper.FindVisualParent(visual.VisualHit);
if (image != null)
{
//点击在listbox列表内,具体某一项时,上面的判断调整可能失效,需要补充条件
return;
}
var button = CommonHelper.FindVisualParent