473 lines
17 KiB
C#
473 lines
17 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.Linq;
|
||
using System.Windows.Forms;
|
||
|
||
namespace BoxPacker3D
|
||
{
|
||
/// <summary>
|
||
/// Modal dialog for managing the item template database.
|
||
/// Allows adding, editing, and deleting saved item templates.
|
||
/// </summary>
|
||
public class ItemDatabaseEditor : Form
|
||
{
|
||
private ItemDatabase _db;
|
||
private DataGridView _grid;
|
||
private TextBox _txtSearch;
|
||
private Button _btnAdd, _btnEdit, _btnDelete, _btnClose;
|
||
private List<ItemTemplate> _allTemplates = new List<ItemTemplate>();
|
||
|
||
public ItemDatabaseEditor(ItemDatabase db)
|
||
{
|
||
_db = db;
|
||
BuildUI();
|
||
LoadData();
|
||
}
|
||
|
||
private void BuildUI()
|
||
{
|
||
this.Text = "Správa databázy kusov";
|
||
this.Size = new Size(700, 500);
|
||
this.MinimumSize = new Size(600, 400);
|
||
this.StartPosition = FormStartPosition.CenterParent;
|
||
this.BackColor = Color.FromArgb(30, 30, 40);
|
||
this.AutoScaleMode = AutoScaleMode.Dpi;
|
||
|
||
// Bottom panel with Close button (add FIRST for proper docking)
|
||
var pnlBottom = new Panel
|
||
{
|
||
Dock = DockStyle.Bottom,
|
||
Height = 50,
|
||
BackColor = Color.FromArgb(25, 25, 35),
|
||
Padding = new Padding(10, 8, 10, 8)
|
||
};
|
||
|
||
_btnClose = MakeButton("✖ Zavrieť", Color.FromArgb(60, 60, 80));
|
||
_btnClose.Dock = DockStyle.Right;
|
||
_btnClose.Width = 120;
|
||
_btnClose.Click += (s, e) => this.Close();
|
||
pnlBottom.Controls.Add(_btnClose);
|
||
this.Controls.Add(pnlBottom);
|
||
|
||
// DataGridView (add SECOND so it fills remaining space)
|
||
_grid = new DataGridView
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
BackgroundColor = Color.FromArgb(40, 40, 55),
|
||
GridColor = Color.FromArgb(60, 60, 80),
|
||
BorderStyle = BorderStyle.None,
|
||
RowHeadersVisible = false,
|
||
AllowUserToAddRows = false,
|
||
AllowUserToDeleteRows = false,
|
||
ReadOnly = true,
|
||
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
|
||
MultiSelect = false,
|
||
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill,
|
||
EnableHeadersVisualStyles = false
|
||
};
|
||
|
||
_grid.DefaultCellStyle.BackColor = Color.FromArgb(40, 40, 55);
|
||
_grid.DefaultCellStyle.ForeColor = Color.White;
|
||
_grid.DefaultCellStyle.SelectionBackColor = Color.FromArgb(60, 100, 160);
|
||
_grid.DefaultCellStyle.SelectionForeColor = Color.White;
|
||
|
||
_grid.ColumnHeadersDefaultCellStyle.BackColor = Color.FromArgb(30, 30, 45);
|
||
_grid.ColumnHeadersDefaultCellStyle.ForeColor = Color.FromArgb(100, 200, 255);
|
||
_grid.ColumnHeadersDefaultCellStyle.Font = new Font("Segoe UI", 9f, FontStyle.Bold);
|
||
|
||
_grid.Columns.Add("Id", "ID");
|
||
_grid.Columns.Add("Name", "Názov");
|
||
_grid.Columns.Add("Width", "Šírka (mm)");
|
||
_grid.Columns.Add("Height", "Výška (mm)");
|
||
_grid.Columns.Add("Depth", "Dĺžka (mm)");
|
||
|
||
_grid.Columns[0].Width = 60; // ID column narrow
|
||
|
||
_grid.DoubleClick += (s, e) => BtnEdit_Click(s, e); // double-click = edit
|
||
|
||
this.Controls.Add(_grid);
|
||
|
||
// Search panel (add THIRD - will dock at top but below button panel)
|
||
var pnlSearch = new Panel
|
||
{
|
||
Dock = DockStyle.Top,
|
||
Height = 45,
|
||
BackColor = Color.FromArgb(30, 30, 40),
|
||
Padding = new Padding(10, 8, 10, 8)
|
||
};
|
||
|
||
var lblSearch = new Label
|
||
{
|
||
Text = "🔍 Hľadať:",
|
||
ForeColor = Color.FromArgb(180, 180, 200),
|
||
AutoSize = true,
|
||
Location = new Point(10, 13)
|
||
};
|
||
|
||
_txtSearch = new TextBox
|
||
{
|
||
BackColor = Color.FromArgb(45, 45, 60),
|
||
ForeColor = Color.White,
|
||
BorderStyle = BorderStyle.FixedSingle,
|
||
Font = new Font("Segoe UI", 10f),
|
||
Location = new Point(95, 10),
|
||
Width = 300
|
||
};
|
||
_txtSearch.TextChanged += (s, e) => ApplyFilter(_txtSearch.Text);
|
||
|
||
pnlSearch.Controls.Add(lblSearch);
|
||
pnlSearch.Controls.Add(_txtSearch);
|
||
this.Controls.Add(pnlSearch);
|
||
|
||
// Top panel with buttons (add LAST - will be at the very top)
|
||
var pnlTop = new Panel
|
||
{
|
||
Dock = DockStyle.Top,
|
||
Height = 50,
|
||
BackColor = Color.FromArgb(25, 25, 35),
|
||
Padding = new Padding(10, 8, 10, 8)
|
||
};
|
||
|
||
var flow = new FlowLayoutPanel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
FlowDirection = FlowDirection.LeftToRight,
|
||
WrapContents = false,
|
||
AutoSize = false
|
||
};
|
||
|
||
_btnAdd = MakeButton("➕ Pridať nový kus", Color.FromArgb(40, 120, 60));
|
||
_btnAdd.Click += BtnAdd_Click;
|
||
|
||
_btnEdit = MakeButton("✏️ Upraviť vybraný", Color.FromArgb(60, 100, 160));
|
||
_btnEdit.Click += BtnEdit_Click;
|
||
|
||
_btnDelete = MakeButton("🗑 Zmazať vybraný", Color.FromArgb(140, 40, 40));
|
||
_btnDelete.Click += BtnDelete_Click;
|
||
|
||
flow.Controls.Add(_btnAdd);
|
||
flow.Controls.Add(_btnEdit);
|
||
flow.Controls.Add(_btnDelete);
|
||
pnlTop.Controls.Add(flow);
|
||
this.Controls.Add(pnlTop);
|
||
}
|
||
|
||
private Button MakeButton(string text, Color bg)
|
||
{
|
||
return new Button
|
||
{
|
||
Text = text,
|
||
BackColor = bg,
|
||
ForeColor = Color.White,
|
||
FlatStyle = FlatStyle.Flat,
|
||
Font = new Font("Segoe UI", 9f, FontStyle.Bold),
|
||
Height = 34,
|
||
Width = 160,
|
||
Margin = new Padding(0, 0, 8, 0),
|
||
Cursor = Cursors.Hand
|
||
};
|
||
}
|
||
|
||
private void LoadData()
|
||
{
|
||
_grid.Rows.Clear();
|
||
_allTemplates.Clear();
|
||
if (_db == null) return;
|
||
|
||
try
|
||
{
|
||
_allTemplates = _db.GetAll();
|
||
ApplyFilter(_txtSearch?.Text ?? "");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Chyba pri načítaní databázy:\n{ex.Message}", "Chyba",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
|
||
private void ApplyFilter(string searchText)
|
||
{
|
||
_grid.Rows.Clear();
|
||
|
||
var filtered = string.IsNullOrWhiteSpace(searchText)
|
||
? _allTemplates
|
||
: _allTemplates.Where(t => t.Name.Contains(searchText, StringComparison.OrdinalIgnoreCase)).ToList();
|
||
|
||
foreach (var t in filtered)
|
||
_grid.Rows.Add(t.Id, t.Name, t.Width, t.Height, t.Depth);
|
||
}
|
||
|
||
private void BtnAdd_Click(object sender, EventArgs e)
|
||
{
|
||
using (var dlg = new ItemEditDialog(null))
|
||
{
|
||
if (dlg.ShowDialog(this) == DialogResult.OK)
|
||
{
|
||
try
|
||
{
|
||
// Check for duplicates
|
||
var duplicate = _db.FindDuplicate(dlg.Template);
|
||
if (duplicate != null)
|
||
{
|
||
string msg;
|
||
if (duplicate.Name.Equals(dlg.Template.Name, StringComparison.OrdinalIgnoreCase))
|
||
msg = $"Kus s názvom \"{duplicate.Name}\" už existuje v databáze.\n\nRozmery: {duplicate.Width}×{duplicate.Height}×{duplicate.Depth} mm";
|
||
else
|
||
msg = $"Kus s rovnakými rozmermi ({duplicate.Width}×{duplicate.Height}×{duplicate.Depth} mm) už existuje v databáze pod názvom \"{duplicate.Name}\".";
|
||
|
||
MessageBox.Show(msg, "Duplikát", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
_db.Upsert(dlg.Template);
|
||
LoadData();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Chyba pri ukladaní:\n{ex.Message}", "Chyba",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void BtnEdit_Click(object sender, EventArgs e)
|
||
{
|
||
if (_grid.SelectedRows.Count == 0)
|
||
{
|
||
MessageBox.Show("Vyberte kus na úpravu.", "Upozornenie",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var row = _grid.SelectedRows[0];
|
||
var template = new ItemTemplate
|
||
{
|
||
Id = Convert.ToInt32(row.Cells[0].Value),
|
||
Name = row.Cells[1].Value?.ToString() ?? "",
|
||
Width = Convert.ToDouble(row.Cells[2].Value),
|
||
Height = Convert.ToDouble(row.Cells[3].Value),
|
||
Depth = Convert.ToDouble(row.Cells[4].Value)
|
||
};
|
||
|
||
using (var dlg = new ItemEditDialog(template))
|
||
{
|
||
if (dlg.ShowDialog(this) == DialogResult.OK)
|
||
{
|
||
try
|
||
{
|
||
// Check for duplicates (excluding self)
|
||
var duplicate = _db.FindDuplicate(dlg.Template);
|
||
if (duplicate != null && duplicate.Id != dlg.Template.Id)
|
||
{
|
||
string msg;
|
||
if (duplicate.Name.Equals(dlg.Template.Name, StringComparison.OrdinalIgnoreCase))
|
||
msg = $"Kus s názvom \"{duplicate.Name}\" už existuje v databáze.\n\nRozmery: {duplicate.Width}×{duplicate.Height}×{duplicate.Depth} mm";
|
||
else
|
||
msg = $"Kus s rovnakými rozmermi ({duplicate.Width}×{duplicate.Height}×{duplicate.Depth} mm) už existuje v databáze pod názvom \"{duplicate.Name}\".";
|
||
|
||
MessageBox.Show(msg, "Duplikát", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
_db.Upsert(dlg.Template);
|
||
LoadData();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Chyba pri ukladaní:\n{ex.Message}", "Chyba",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void BtnDelete_Click(object sender, EventArgs e)
|
||
{
|
||
if (_grid.SelectedRows.Count == 0)
|
||
{
|
||
MessageBox.Show("Vyberte kus na zmazanie.", "Upozornenie",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||
return;
|
||
}
|
||
|
||
var row = _grid.SelectedRows[0];
|
||
string name = row.Cells[1].Value?.ToString() ?? "";
|
||
|
||
var dr = MessageBox.Show(
|
||
$"Naozaj zmazať kus \"{name}\" z databázy?\n\nTáto akcia je nevratná.",
|
||
"Potvrdenie zmazania",
|
||
MessageBoxButtons.YesNo,
|
||
MessageBoxIcon.Warning);
|
||
|
||
if (dr == DialogResult.Yes)
|
||
{
|
||
try
|
||
{
|
||
_db.DeleteByName(name);
|
||
LoadData();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
MessageBox.Show($"Chyba pri mazaní:\n{ex.Message}", "Chyba",
|
||
MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Small dialog for adding/editing a single item template.
|
||
/// </summary>
|
||
internal class ItemEditDialog : Form
|
||
{
|
||
public ItemTemplate Template { get; private set; }
|
||
|
||
private TextBox _txtName;
|
||
private NumericUpDown _nudW, _nudH, _nudD;
|
||
|
||
public ItemEditDialog(ItemTemplate existing)
|
||
{
|
||
Template = existing ?? new ItemTemplate();
|
||
BuildUI();
|
||
}
|
||
|
||
private void BuildUI()
|
||
{
|
||
this.Text = Template.Id == 0 ? "Nový kus" : "Úprava kusu";
|
||
this.Size = new Size(400, 280);
|
||
this.StartPosition = FormStartPosition.CenterParent;
|
||
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
||
this.MaximizeBox = false;
|
||
this.MinimizeBox = false;
|
||
this.BackColor = Color.FromArgb(35, 35, 48);
|
||
this.AutoScaleMode = AutoScaleMode.Dpi;
|
||
|
||
var tbl = new TableLayoutPanel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
ColumnCount = 2,
|
||
RowCount = 5,
|
||
Padding = new Padding(15)
|
||
};
|
||
tbl.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 120));
|
||
tbl.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
|
||
tbl.RowStyles.Add(new RowStyle(SizeType.AutoSize));
|
||
tbl.RowStyles.Add(new RowStyle(SizeType.AutoSize));
|
||
tbl.RowStyles.Add(new RowStyle(SizeType.AutoSize));
|
||
tbl.RowStyles.Add(new RowStyle(SizeType.AutoSize));
|
||
tbl.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
|
||
|
||
tbl.Controls.Add(MakeLabel("Názov:"), 0, 0);
|
||
_txtName = new TextBox
|
||
{
|
||
Text = Template.Name,
|
||
Dock = DockStyle.Fill,
|
||
BackColor = Color.FromArgb(45, 45, 60),
|
||
ForeColor = Color.White,
|
||
BorderStyle = BorderStyle.FixedSingle,
|
||
Margin = new Padding(0, 3, 0, 8)
|
||
};
|
||
tbl.Controls.Add(_txtName, 1, 0);
|
||
|
||
tbl.Controls.Add(MakeLabel("Šírka (mm):"), 0, 1);
|
||
_nudW = MakeNUD(Template.Width);
|
||
tbl.Controls.Add(_nudW, 1, 1);
|
||
|
||
tbl.Controls.Add(MakeLabel("Výška (mm):"), 0, 2);
|
||
_nudH = MakeNUD(Template.Height);
|
||
tbl.Controls.Add(_nudH, 1, 2);
|
||
|
||
tbl.Controls.Add(MakeLabel("Dĺžka (mm):"), 0, 3);
|
||
_nudD = MakeNUD(Template.Depth);
|
||
tbl.Controls.Add(_nudD, 1, 3);
|
||
|
||
// Buttons
|
||
var pnlButtons = new FlowLayoutPanel
|
||
{
|
||
Dock = DockStyle.Fill,
|
||
FlowDirection = FlowDirection.RightToLeft,
|
||
Margin = new Padding(0, 10, 0, 0)
|
||
};
|
||
|
||
var btnOk = new Button
|
||
{
|
||
Text = "✔ Uložiť",
|
||
DialogResult = DialogResult.OK,
|
||
BackColor = Color.FromArgb(40, 120, 60),
|
||
ForeColor = Color.White,
|
||
FlatStyle = FlatStyle.Flat,
|
||
Font = new Font("Segoe UI", 9f, FontStyle.Bold),
|
||
Width = 100,
|
||
Height = 32
|
||
};
|
||
btnOk.Click += (s, e) =>
|
||
{
|
||
if (string.IsNullOrWhiteSpace(_txtName.Text))
|
||
{
|
||
MessageBox.Show("Názov nemôže byť prázdny.", "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||
this.DialogResult = DialogResult.None;
|
||
return;
|
||
}
|
||
Template.Name = _txtName.Text.Trim();
|
||
Template.Width = (double)_nudW.Value;
|
||
Template.Height = (double)_nudH.Value;
|
||
Template.Depth = (double)_nudD.Value;
|
||
};
|
||
|
||
var btnCancel = new Button
|
||
{
|
||
Text = "✖ Zrušiť",
|
||
DialogResult = DialogResult.Cancel,
|
||
BackColor = Color.FromArgb(80, 80, 100),
|
||
ForeColor = Color.White,
|
||
FlatStyle = FlatStyle.Flat,
|
||
Font = new Font("Segoe UI", 9f),
|
||
Width = 100,
|
||
Height = 32,
|
||
Margin = new Padding(0, 0, 8, 0)
|
||
};
|
||
|
||
pnlButtons.Controls.Add(btnOk);
|
||
pnlButtons.Controls.Add(btnCancel);
|
||
tbl.Controls.Add(pnlButtons, 0, 4);
|
||
tbl.SetColumnSpan(pnlButtons, 2);
|
||
|
||
this.Controls.Add(tbl);
|
||
this.AcceptButton = btnOk;
|
||
this.CancelButton = btnCancel;
|
||
}
|
||
|
||
private Label MakeLabel(string text)
|
||
{
|
||
return new Label
|
||
{
|
||
Text = text,
|
||
ForeColor = Color.FromArgb(180, 180, 200),
|
||
AutoSize = true,
|
||
Anchor = AnchorStyles.Left,
|
||
Margin = new Padding(0, 8, 8, 0)
|
||
};
|
||
}
|
||
|
||
private NumericUpDown MakeNUD(double val)
|
||
{
|
||
return new NumericUpDown
|
||
{
|
||
Value = (decimal)Math.Max(1, val),
|
||
Minimum = 1,
|
||
Maximum = 100000,
|
||
DecimalPlaces = 0,
|
||
Increment = 10,
|
||
BackColor = Color.FromArgb(45, 45, 60),
|
||
ForeColor = Color.White,
|
||
BorderStyle = BorderStyle.FixedSingle,
|
||
Dock = DockStyle.Fill,
|
||
Margin = new Padding(0, 3, 0, 8)
|
||
};
|
||
}
|
||
}
|
||
}
|