ProductLookupDock.xaml.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Imaging;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Input;
  9. using System.Windows.Media.Imaging;
  10. using Comal.Classes;
  11. using InABox.Clients;
  12. using InABox.Configuration;
  13. using InABox.Core;
  14. using InABox.Dxf;
  15. using InABox.Wpf;
  16. using InABox.WPF;
  17. using Microsoft.Win32;
  18. namespace PRSDesktop;
  19. public class ProductDockFilterButton : FilterButton<Product>
  20. {
  21. public ProductDockFilterButton() : base(
  22. new GlobalConfiguration<CoreFilterDefinitions>("ProductDock.Product"),
  23. new UserConfiguration<CoreFilterDefinitions>("ProductDock.Product"))
  24. {
  25. }
  26. }
  27. /// <summary>
  28. /// Interaction logic for ProductLookup.xaml
  29. /// </summary>
  30. public partial class ProductLookupDock : UserControl, IDockPanel
  31. {
  32. private ProductHoldingControl? _holdings;
  33. private Product[] Products = Array.Empty<Product>();
  34. public ProductLookupDock()
  35. {
  36. InitializeComponent();
  37. }
  38. public void Setup()
  39. {
  40. if (!Security.CanView<StockLocation>())
  41. return;
  42. if (_holdings == null)
  43. {
  44. _holdings = new ProductHoldingControl();
  45. HoldingsTab.Content = _holdings;
  46. HoldingsTab.Visibility = Visibility.Visible;
  47. }
  48. _holdings.Refresh(true, false);
  49. }
  50. public void Refresh()
  51. {
  52. }
  53. private Filter<Product>? GetSearchFilter()
  54. {
  55. var search = Search.Text;
  56. if (!string.IsNullOrEmpty(search))
  57. {
  58. return new Filter<Product>(x => x.Code).Contains(Search.Text).Or(x => x.Name).Contains(search);
  59. }
  60. else
  61. {
  62. return null;
  63. }
  64. }
  65. private void Reload()
  66. {
  67. var filters = new Filters<Product>();
  68. filters.Add(GetSearchFilter());
  69. filters.Add(FilterButton.GetFilter());
  70. var filter = filters.Combine() ?? new Filter<Product>().None();
  71. using (new WaitCursor())
  72. {
  73. Products = Client.Query(
  74. filter,
  75. Columns.Required<Product>().Add(x => x.ID, x => x.Code, x => x.Name, x => x.Image.ID, x => x.Image.FileName),
  76. new SortOrder<Product>(x => x.Code))
  77. .ToObjects<Product>().ToArray();
  78. Items.ItemsSource = Products;
  79. if (Products.Any())
  80. {
  81. Items.Focus();
  82. Items.SelectedIndex = 0;
  83. var listBoxItem = (ListBoxItem)Items.ItemContainerGenerator.ContainerFromItem(Items.SelectedItem);
  84. listBoxItem?.Focus();
  85. }
  86. }
  87. }
  88. private void Search_TextChanged(object sender, TextChangedEventArgs e)
  89. {
  90. }
  91. private void Search_KeyUp(object sender, KeyEventArgs e)
  92. {
  93. if (e.Key == Key.Enter)
  94. {
  95. Reload();
  96. }
  97. else if (e.Key == Key.Down)
  98. {
  99. if (Products.Any())
  100. {
  101. Items.Focus();
  102. //Items.SelectedValue = items.First();
  103. Items.SelectedIndex = 0;
  104. var listBoxItem = (ListBoxItem)Items.ItemContainerGenerator.ContainerFromItem(Items.SelectedItem);
  105. listBoxItem.Focus();
  106. }
  107. }
  108. }
  109. private void Items_SelectionChanged(object sender, SelectionChangedEventArgs e)
  110. {
  111. Image.Source = null;
  112. if (e.AddedItems.Count > 0)
  113. {
  114. var item = e.AddedItems[0] as Product;
  115. if (!item.Image.ID.Equals(Guid.Empty))
  116. new Client<Document>().Query(
  117. new Filter<Document>(x => x.ID).IsEqualTo(item.Image.ID),
  118. Columns.None<Document>().Add(x => x.ID, x => x.Data),
  119. null,
  120. CoreRange.All,
  121. (docs, error) =>
  122. {
  123. var row = docs.Rows.FirstOrDefault();
  124. if (row != null)
  125. {
  126. var id = row.Get<Document, Guid>(x => x.ID);
  127. var data = row.Get<Document, byte[]>(x => x.Data);
  128. if (data?.Any() == true)
  129. {
  130. var ms = new MemoryStream(data);
  131. var bmp = new Bitmap(ms);
  132. Dispatcher.BeginInvoke(
  133. new Action<Guid>(o =>
  134. {
  135. if (Items.SelectedValue != null)
  136. {
  137. var sel = (Product)Items.SelectedValue;
  138. if (sel.Image.ID == o)
  139. Image.Source = bmp.AsBitmapImage(false);
  140. }
  141. }), id
  142. );
  143. }
  144. }
  145. }
  146. );
  147. else
  148. Image.Source = null;
  149. if (Security.CanView<StockLocation>())
  150. {
  151. _holdings.Product = item;
  152. _holdings.Refresh(false, true);
  153. }
  154. }
  155. else
  156. {
  157. Image.Source = null;
  158. }
  159. }
  160. private void Items_KeyUp(object sender, KeyEventArgs e)
  161. {
  162. }
  163. private void Items_KeyDown(object sender, KeyEventArgs e)
  164. {
  165. if (e.Key == Key.Up)
  166. if (Items.SelectedIndex == 0)
  167. Search.Focus();
  168. }
  169. private void ImageMenu_Opened(object sender, RoutedEventArgs e)
  170. {
  171. var pdi = Items.SelectedItem as Product;
  172. var anyproducts = pdi != null;
  173. var validimage = pdi != null && pdi.Image.ID != Guid.Empty;
  174. LoadImageFromFile.IsEnabled = anyproducts;
  175. SaveImageToFile.IsEnabled = validimage;
  176. CopyImageToClipboard.IsEnabled = validimage;
  177. PasteImageFromClipboard.IsEnabled = anyproducts && (Clipboard.ContainsData("ProductImage") || Clipboard.ContainsImage());
  178. ClearImage.IsEnabled = anyproducts;
  179. }
  180. private string SelectedProducts()
  181. {
  182. var product = Items.SelectedItem as Product;
  183. return product != null ? product.Code : "";
  184. }
  185. private void UpdateProductImages(Guid id, string filename, Bitmap? bitmap)
  186. {
  187. var product = Items.SelectedItem as Product;
  188. if (product == null)
  189. return;
  190. var docid = id;
  191. if (bitmap != null && docid == Guid.Empty)
  192. {
  193. byte[] data = null;
  194. using (var ms = new MemoryStream())
  195. {
  196. bitmap.Save(ms, ImageFormat.Png);
  197. data = ms.GetBuffer();
  198. }
  199. var crc = CoreUtils.CalculateCRC(data);
  200. var doc = new Client<Document>().Query(
  201. new Filter<Document>(x => x.FileName).IsEqualTo(Path.GetFileName(filename)).And(x => x.CRC).IsEqualTo(crc),
  202. Columns.None<Document>().Add(x => x.ID)
  203. ).Rows.FirstOrDefault()?.ToObject<Document>();
  204. if (doc == null)
  205. {
  206. doc = new Document
  207. {
  208. FileName = Path.GetFileName(filename),
  209. CRC = crc,
  210. TimeStamp = DateTime.Now,
  211. Data = data
  212. };
  213. new Client<Document>().Save(doc, "");
  214. }
  215. docid = doc.ID;
  216. }
  217. product.Image.ID = CoreUtils.FullGuid;
  218. product.CommitChanges();
  219. product.Image.ID = docid;
  220. product.Image.FileName = Path.GetFileName(filename);
  221. new Client<Product>().Save(product, "Cleared Product Image", (p, err) => { });
  222. Image.Source = bitmap?.AsBitmapImage();
  223. }
  224. private Bitmap? ConvertDXFFile(string filename)
  225. {
  226. Bitmap? result = null;
  227. using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
  228. {
  229. //String newfile = Path.ChangeExtension(Path.GetFileName(filename), "png");
  230. try
  231. {
  232. result = DxfUtils.ProcessImage(stream);
  233. }
  234. catch (Exception e)
  235. {
  236. MessageWindow.ShowError("Could not load DXF file", e);
  237. result = null;
  238. }
  239. }
  240. return result;
  241. }
  242. private void LoadImageFromFile_Click(object sender, RoutedEventArgs e)
  243. {
  244. var product = Items.SelectedItem as Product;
  245. if (product == null)
  246. return;
  247. var dlg = new OpenFileDialog();
  248. dlg.Filter = "Image Files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|DXF Files (*.dxf)|*.dxf";
  249. if (dlg.ShowDialog() == true)
  250. {
  251. var filename = dlg.FileName.ToLower();
  252. Progress.Show("Updating Images: " + Path.GetFileName(filename));
  253. Bitmap? bmp = null;
  254. if (Path.GetExtension(filename).ToLower().Equals(".dxf"))
  255. bmp = ConvertDXFFile(filename);
  256. else
  257. bmp = System.Drawing.Image.FromFile(filename) as Bitmap;
  258. UpdateProductImages(Guid.Empty, filename, bmp);
  259. Progress.Close();
  260. MessageBox.Show(string.Format("Imported [{0}] into [{1}]", Path.GetFileName(dlg.FileName), SelectedProducts()));
  261. }
  262. }
  263. private void SaveImageToFile_Click(object sender, RoutedEventArgs e)
  264. {
  265. var product = Items.SelectedItem as Product;
  266. if (product == null)
  267. return;
  268. var bmp = (Image.Source as BitmapImage).AsBitmap();
  269. var dlg = new SaveFileDialog();
  270. dlg.Filter = "Image Files (*.png)|*.png";
  271. dlg.FileName = product.Image.FileName;
  272. if (dlg.ShowDialog() == true)
  273. bmp.Save(dlg.FileName);
  274. }
  275. private void CopyImageToClipboard_Click(object sender, RoutedEventArgs e)
  276. {
  277. var product = Items.SelectedItem as Product;
  278. if (product == null)
  279. return;
  280. var bmp = (Image.Source as BitmapImage).AsBitmap();
  281. var data = new Tuple<Guid, string, Bitmap>(
  282. product.Image.ID,
  283. product.Image.FileName,
  284. bmp
  285. );
  286. Clipboard.SetData("ProductImage", data);
  287. }
  288. private void PasteImageFromClipboard_Click(object sender, RoutedEventArgs e)
  289. {
  290. if (Items.SelectedItem is not Product product)
  291. return;
  292. if (MessageBox.Show("Are you sure you wish to update the image for the selected product?", "Update Image", MessageBoxButton.YesNo,
  293. MessageBoxImage.Question) != MessageBoxResult.Yes)
  294. return;
  295. Progress.Show("Updating Images");
  296. var id = Guid.Empty;
  297. var filename = "";
  298. Bitmap? bitmap = null;
  299. if (Clipboard.ContainsData("ProductImage"))
  300. {
  301. if(Clipboard.GetData("ProductImage") is Tuple<Guid, string, Bitmap> data)
  302. {
  303. id = data.Item1;
  304. filename = data.Item2;
  305. bitmap = data.Item3;
  306. }
  307. }
  308. else if (Clipboard.ContainsImage())
  309. {
  310. var data = Clipboard.GetImage();
  311. bitmap = data.AsBitmap2();
  312. filename = string.Format("clip{0:yyyyMMddhhmmss}.png", DateTime.Now);
  313. if (Clipboard.ContainsFileDropList())
  314. {
  315. var list = Clipboard.GetFileDropList();
  316. if (list.Count > 0)
  317. filename = Path.ChangeExtension(Path.GetFileName(list[0]), ".png");
  318. }
  319. //filename = String.Format("clip{0:yyyyMMddhhmmss}.png",DateTime.Now);
  320. //bitmap.Save(filename);
  321. id = Guid.Empty;
  322. }
  323. if (bitmap == null)
  324. {
  325. MessageBox.Show("Unable to paste data from clipboard");
  326. return;
  327. }
  328. Progress.Show("");
  329. UpdateProductImages(id, filename, bitmap);
  330. Progress.Close();
  331. MessageBox.Show(string.Format("Pasted [{0}] into [{1}]", Path.GetFileName(filename), SelectedProducts()));
  332. }
  333. private void ClearImage_Click(object sender, RoutedEventArgs e)
  334. {
  335. if (MessageWindow.ShowYesNo("Are you sure you wish to clear the image for the selected product?", "Clear Image"))
  336. return;
  337. Progress.Show("Clearing Image");
  338. UpdateProductImages(Guid.Empty, "", null);
  339. Progress.Close();
  340. MessageBox.Show(string.Format("Cleared image from [{0}]", string.Join(", ", SelectedProducts())));
  341. }
  342. private void Grid_MouseMove(object sender, MouseEventArgs e)
  343. {
  344. if(sender is not Grid grid || grid.Tag is not Product product || e.LeftButton != MouseButtonState.Pressed)
  345. {
  346. return;
  347. }
  348. DragDrop.DoDragDrop(grid, product, DragDropEffects.Copy);
  349. }
  350. private void FilterButton_OnFilterRefresh()
  351. {
  352. Reload();
  353. }
  354. }