using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using System.Windows.Threading; using InABox.Clients; using InABox.Core; using InABox.Dxf; using InABox.WPF; using Microsoft.Win32; namespace InABox.DynamicGrid { public class DynamicImagePreviewColumn : DynamicImageColumn where T : BaseObject { private static readonly BitmapImage _preview = Wpf.Resources.doc_png.AsBitmapImage(); protected static Expression> Property { get; private set; } protected static string ImageIDProperty => Property != null ? CoreUtils.GetFullPropertyName(Property, ".") + ".ID" : ""; public DynamicImagePreviewColumn(Expression> property) : base(PreviewImage) { Property = property; Image = PreviewImage; Filters = new[] { "Image Present", "Blank Image" }; FilterRecord = DoFilterImages; ToolTip = CreateImageToolTip; } private static BitmapImage? PreviewImage(CoreRow? arg) { if (arg is null || arg.Get(ImageIDProperty) == Guid.Empty) return null; return _preview; } protected Bitmap? LoadBitmapFromDatabase(Guid imageid) { if (imageid == Guid.Empty) return null; Bitmap? result = null; var image = new Client().Query( new Filter(x => x.ID).IsEqualTo(imageid), new Columns(x => x.ID, x => x.Data) ).Rows.FirstOrDefault(); if (image != null) { var ms = new MemoryStream(image.Get(x => x.Data)); result = new Bitmap(ms); } return result; } private FrameworkElement? CreateImageToolTip(DynamicActionColumn column, CoreRow? arg) { if (arg is null) return null; FrameworkElement? result = null; var imageid = arg.Get(ImageIDProperty); if (!imageid.Equals(Guid.Empty)) using (new WaitCursor()) { var bmp = LoadBitmapFromDatabase(imageid); result = ImageToolTip(bmp?.AsBitmapImage(false)); } return result; } private bool DoFilterImages(CoreRow row, string[] filter) { var hasimage = row.Get(ImageIDProperty) != Guid.Empty; if (filter.Contains("Image Present") && hasimage) return true; if (filter.Contains("Blank Image") && !hasimage) return true; return false; } } public class DynamicImageManagerColumn : DynamicImagePreviewColumn where T : Entity, IRemotable, IPersistent, new() { private readonly bool _canupdate; private readonly IDynamicGrid _parent; private static string _imagefilename => Property != null ? CoreUtils.GetFullPropertyName(Property, ".") + ".FileName" : ""; public DynamicImageManagerColumn(IDynamicGrid parent, Expression> property, bool canupdate) : base(property) { _parent = parent; _canupdate = canupdate; ContextMenu = CreateImageMenu; } private MenuItem CreateMenu(string caption, RoutedEventHandler click) { var item = new MenuItem(); item.Header = caption; item.Click += click; return item; } private void SaveBitmapToDatabase(CoreRow row, Guid id, string filename, Bitmap? bitmap) { var docid = id; if (bitmap != null && docid == Guid.Empty) { byte[] data; using (var ms = new MemoryStream()) { bitmap.Save(ms, ImageFormat.Png); data = ms.GetBuffer(); } var crc = CoreUtils.CalculateCRC(data); var doc = new Client().Query( new Filter(x => x.FileName).IsEqualTo(Path.GetFileName(filename)).And(x => x.CRC).IsEqualTo(crc), new Columns(x => x.ID) ).Rows.FirstOrDefault()?.ToObject(); if (doc == null) { doc = new Document { FileName = Path.GetFileName(filename), CRC = crc, TimeStamp = DateTime.Now, Data = data }; new Client().Save(doc, ""); } docid = doc.ID; } var item = row.ToObject(); CoreUtils.SetPropertyValue(item, ImageIDProperty, docid); CoreUtils.SetPropertyValue(item, _imagefilename, Path.GetFileName(filename)); new Client().Save(item, "", (p, err) => { }); // False here to prevent Refreshing and losing the selected row record _parent.UpdateRow(row, ImageIDProperty, docid, false); _parent.UpdateRow(row, _imagefilename, Path.GetFileName(filename)); } private ContextMenu? CreateImageMenu(CoreRow[]? rows) { if (rows == null || rows.Length != 1) return null; var hasimage = rows[0].Get(ImageIDProperty) != Guid.Empty; var canpaste = (_canupdate && Clipboard.ContainsData("ProductImage")) || Clipboard.ContainsImage(); var result = new ContextMenu(); if (_canupdate) result.Items.Add(CreateMenu("Load From File", (o, e) => LoadImage(rows[0]))); if (hasimage) result.Items.Add(CreateMenu("Save To File", (o, e) => SaveImage(rows[0]))); if (hasimage || canpaste) result.Items.Add(new Separator()); if (hasimage) result.Items.Add(CreateMenu("Copy To Clipboard", (o, e) => CopyImage(rows[0]))); if (canpaste) result.Items.Add(CreateMenu("Paste From Clipboard", (o, e) => PasteImage(rows[0]))); if (_canupdate && hasimage) { result.Items.Add(new Separator()); result.Items.Add(CreateMenu("Clear Image", (o, e) => ClearImage(rows[0]))); } return result; } private void LoadImage(CoreRow row) { var dlg = new OpenFileDialog(); dlg.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|DXF Files (*.dxf)|*.dxf"; if (dlg.ShowDialog() == true) using (new WaitCursor()) { var filename = dlg.FileName.ToLower(); Bitmap bmp; if (Path.GetExtension(filename).ToLower().Equals(".dxf")) { DxfUtils.OnProcessError += ((message) => { MessageBox.Show("Error - " + message); }); bmp = DxfUtils.DXFToBitmap(filename); } else bmp = (System.Drawing.Image.FromFile(filename) as Bitmap)!; SaveBitmapToDatabase(row, Guid.Empty, filename, bmp); //_parent?.Refresh(false, false); } } private void SaveImage(CoreRow row) { var imageid = row.Get(ImageIDProperty); if (imageid == Guid.Empty) return; var filename = row.Get(_imagefilename); var dlg = new SaveFileDialog(); dlg.Filter = "Image Files (*.png)|*.png"; dlg.FileName = filename; if (dlg.ShowDialog() == true) { var bmp = LoadBitmapFromDatabase(imageid); bmp?.Save(dlg.FileName); } } private void CopyImage(CoreRow row) { var bmp = LoadBitmapFromDatabase(row.Get(ImageIDProperty)); var data = new Tuple( row.Get(ImageIDProperty), row.Get(_imagefilename), bmp ); Clipboard.SetData("ProductImage", data); } private void PasteImage(CoreRow row) { if (row.Get(ImageIDProperty) != Guid.Empty) if (MessageBox.Show("Are you sure you wish to update the image for the selected items(s)?", "Update Images", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes) return; var id = Guid.Empty; var filename = ""; Bitmap? bitmap = null; if (Clipboard.ContainsData("ProductImage") && Clipboard.GetData("ProductImage") is Tuple data) { id = data.Item1; filename = data.Item2; bitmap = data.Item3; } else if (Clipboard.ContainsImage()) { var dataImage = Clipboard.GetImage(); bitmap = dataImage.AsBitmap2(); filename = string.Format("clip{0:yyyyMMddhhmmss}.png", DateTime.Now); if (Clipboard.ContainsFileDropList()) { var list = Clipboard.GetFileDropList(); if (list.Count > 0) filename = Path.ChangeExtension(Path.GetFileName(list[0]!), ".png"); } //filename = String.Format("clip{0:yyyyMMddhhmmss}.png",DateTime.Now); //bitmap.Save(filename); id = Guid.Empty; } if (bitmap is null) { MessageBox.Show("Unable to paste data from clipboard"); return; } using (new WaitCursor()) { SaveBitmapToDatabase(row, id, filename, bitmap); } //_parent?.Refresh(false, false); } private void ClearImage(CoreRow row) { if (MessageBox.Show("Are you sure you wish to clear the image for the selected product(s)?", "Clear Images", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes) return; using (new WaitCursor()) { SaveBitmapToDatabase(row, Guid.Empty, "", null); } //_parent?.Refresh(false, false); } } }