using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace TradeApp.WinForms.V08; public sealed partial class ProductEditForm : Form { private readonly DatabaseClient _db; private readonly ProductView _product; private readonly string _originalImagePath; public ProductEditForm(DatabaseClient db, ProductView? product) { _db = db; _product = product ?? new ProductView(); _originalImagePath = _product.ImagePath; InitializeComponent(); Text = product is null ? "Добавление товара" : "Редактирование товара"; LoadLookups(); Fill(); } private void ChooseImageButton_Click(object? sender, EventArgs e) { using var dialog = new OpenFileDialog { Filter = "Изображения|*.jpg;*.jpeg;*.png;*.bmp" }; if (dialog.ShowDialog(this) != DialogResult.OK) { return; } var targetDir = Path.Combine(AppContext.BaseDirectory, "Images"); Directory.CreateDirectory(targetDir); var targetName = Path.GetFileName(dialog.FileName); var targetPath = Path.Combine(targetDir, targetName); if (!string.Equals(Path.GetFullPath(dialog.FileName), Path.GetFullPath(targetPath), StringComparison.OrdinalIgnoreCase)) { SaveProductImage(dialog.FileName, targetPath); } imageTextBox.Text = targetName; } private void SaveButton_Click(object? sender, EventArgs e) { if (string.IsNullOrWhiteSpace(articleTextBox.Text) || string.IsNullOrWhiteSpace(nameTextBox.Text)) { MessageBox.Show("Артикул и название обязательны.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } _product.Article = articleTextBox.Text.Trim(); _product.Name = nameTextBox.Text.Trim(); _product.Unit = unitComboBox.Text.Trim(); _product.Price = priceNumeric.Value; _product.Supplier = supplierComboBox.Text.Trim(); _product.Manufacturer = manufacturerComboBox.Text.Trim(); _product.Category = categoryComboBox.Text.Trim(); _product.DiscountPercent = discountNumeric.Value; _product.StockQuantity = (int)stockNumeric.Value; _product.Description = descriptionTextBox.Text.Trim(); _product.ImagePath = string.IsNullOrWhiteSpace(imageTextBox.Text) ? "picture.png" : imageTextBox.Text.Trim(); _db.SaveProduct(_product); DeleteReplacedImage(_originalImagePath, _product.ImagePath); DialogResult = DialogResult.OK; } private void LoadLookups() { unitComboBox.Items.AddRange(_db.LoadUnits().Cast().ToArray()); supplierComboBox.Items.AddRange(_db.LoadSuppliers().Cast().ToArray()); manufacturerComboBox.Items.AddRange(_db.LoadManufacturers().Cast().ToArray()); categoryComboBox.Items.AddRange(_db.LoadCategories().Cast().ToArray()); } private void Fill() { articleTextBox.Text = _product.Article; nameTextBox.Text = _product.Name; unitComboBox.Text = _product.Unit; priceNumeric.Value = Clamp(_product.Price, priceNumeric.Minimum, priceNumeric.Maximum); supplierComboBox.Text = _product.Supplier; manufacturerComboBox.Text = _product.Manufacturer; categoryComboBox.Text = _product.Category; discountNumeric.Value = Clamp(_product.DiscountPercent, discountNumeric.Minimum, discountNumeric.Maximum); stockNumeric.Value = Clamp(_product.StockQuantity, stockNumeric.Minimum, stockNumeric.Maximum); descriptionTextBox.Text = _product.Description; imageTextBox.Text = string.IsNullOrWhiteSpace(_product.ImagePath) ? "picture.png" : _product.ImagePath; } private static decimal Clamp(decimal value, decimal minimum, decimal maximum) { return Math.Min(Math.Max(value, minimum), maximum); } private static void SaveProductImage(string sourcePath, string targetPath) { using var source = Image.FromFile(sourcePath); var scale = Math.Min(1d, Math.Min(300d / source.Width, 200d / source.Height)); var width = Math.Max(1, (int)Math.Round(source.Width * scale)); var height = Math.Max(1, (int)Math.Round(source.Height * scale)); using var resized = new Bitmap(width, height); resized.SetResolution(source.HorizontalResolution, source.VerticalResolution); using (var graphics = Graphics.FromImage(resized)) { graphics.Clear(Color.Transparent); graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.DrawImage(source, 0, 0, width, height); } if (File.Exists(targetPath)) { File.Delete(targetPath); } resized.Save(targetPath, source.RawFormat); } private void DeleteReplacedImage(string oldImagePath, string newImagePath) { if (string.IsNullOrWhiteSpace(oldImagePath) || oldImagePath.Equals(newImagePath, StringComparison.OrdinalIgnoreCase) || oldImagePath.Equals("picture.png", StringComparison.OrdinalIgnoreCase) || _db.ProductImageIsUsed(oldImagePath, _product.ProductId)) { return; } var path = Path.Combine(AppContext.BaseDirectory, "Images", oldImagePath); if (!File.Exists(path)) { return; } try { File.Delete(path); } catch (IOException) { MessageBox.Show("Старое фото сохранено, потому что файл сейчас занят.", "Фото товара", MessageBoxButtons.OK, MessageBoxIcon.Warning); } catch (UnauthorizedAccessException) { MessageBox.Show("Старое фото не удалено: нет доступа к файлу.", "Фото товара", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } }