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 InABox.Clients; using InABox.Core; using InABox.Dxf; using InABox.DynamicGrid.Properties; using InABox.WPF; using Microsoft.Win32; namespace InABox.DynamicGrid { public class DynamicImageColumn : DynamicActionColumn where T : Entity, IRemotable, IPersistent, new() { private static readonly BitmapImage _preview = Resources.doc_png.AsBitmapImage(); private static Expression> _property; private readonly bool _canupdate; private readonly IDynamicGrid _parent; public DynamicImageColumn(IDynamicGrid parent, Expression> property, bool canupdate) : base(PreviewImage) { _parent = parent; _property = property; _canupdate = canupdate; Image = PreviewImage; Filters = new[] { "Image Present", "Blank Image" }; FilterRecord = DoFilterImages; ContextMenu = CreateImageMenu; ToolTip = CreateImageToolTip; } private static string _imageid => _property != null ? CoreUtils.GetFullPropertyName(_property, ".") + ".ID" : ""; private static string _imagefilename => _property != null ? CoreUtils.GetFullPropertyName(_property, ".") + ".FileName" : ""; private static BitmapImage PreviewImage(CoreRow arg) { if (arg == null || arg.Get(_imageid) == Guid.Empty) return null; return _preview; } private MenuItem CreateMenu(string caption, RoutedEventHandler click) { var item = new MenuItem(); item.Header = caption; item.Click += click; return item; } private 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 void SaveBitmapToDatabase(CoreRow row, Guid id, string filename, Bitmap bitmap) { var docid = id; if (bitmap != null && docid == Guid.Empty) { byte[] data = null; 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, _imageid, 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, _imageid, 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(_imageid) != 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 = null; if (Path.GetExtension(filename).ToLower().Equals(".dxf")) 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(_imageid); 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(_imageid)); var data = new Tuple( row.Get(_imageid), row.Get(_imagefilename), bmp ); Clipboard.SetData("ProductImage", data); } private void PasteImage(CoreRow row) { if (row.Get(_imageid) != 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")) { var data = Clipboard.GetData("ProductImage") as Tuple; id = data.Item1; filename = data.Item2; bitmap = data.Item3; } else if (Clipboard.ContainsImage()) { var data = Clipboard.GetImage(); bitmap = data.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 == 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); } private bool DoFilterImages(CoreRow row, string[] filter) { var hasimage = row.Get(_imageid) != Guid.Empty; if (filter.Contains("Image Present") && hasimage) return true; if (filter.Contains("Blank Image") && !hasimage) return true; return false; } private FrameworkElement CreateImageToolTip(DynamicActionColumn column, CoreRow arg) { FrameworkElement result = null; var imageid = arg.Get(_imageid); if (!imageid.Equals(Guid.Empty)) using (new WaitCursor()) { var bmp = LoadBitmapFromDatabase(imageid); result = ImageToolTip(bmp?.AsBitmapImage(false)); } return result; } } }