using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Linq; using System.Windows.Forms; using static System.Windows.Forms.ListViewItem; using System.ComponentModel; namespace NethackHelper { public partial class ItemDisplay : UserControl { public const string UNIDENTIFIED = "[randomized]"; public static readonly Color SELECTED_COLOR = Color.Black; public static readonly Color UNSELECTED_COLOR = Color.Gray; private static readonly Dictionary> COLUMN_MAP = new() { [ItemAttribute.Name] = item => item.Name, [ItemAttribute.Cost] = item => item.Cost.ToString(), [ItemAttribute.Ink] = item => item.Ink.ToString(), [ItemAttribute.Appearance] = item => item.Appearance ?? UNIDENTIFIED, }; [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Func CostFormatter { get; set; } = cost => cost.ToString(); [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public List Columns { get; set; } = new(); private int[] GroupCosts { get; set; } = []; private Dictionary AppearanceMap { get; set; } = new(); public ItemDisplay() { InitializeComponent(); this.itemListView.ListViewItemSorter = Comparer.Create(CompareItems); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); if (this.Columns != null) { this.itemListView.Columns.Clear(); foreach (var column in this.Columns) { this.itemListView.Columns.Add(column.Attribute.ToString(), column.Width); } } } public void DisplayItemList(ItemList itemList, IdentificationRecord? idRecord) { this.itemListView.Groups.Clear(); this.itemListView.Items.Clear(); this.AppearanceMap.Clear(); this.GroupCosts = itemList.Items.Select(item => item.Cost).Distinct().Order().ToArray(); var costDictionary = new Dictionary(); foreach (var cost in this.GroupCosts) { var group = new ListViewGroup(this.CostFormatter.Invoke(cost), HorizontalAlignment.Center); this.itemListView.Groups.Add(group); costDictionary.Add(cost, group); } foreach (var item in itemList.Items) { bool identified = false; ItemRecord record = default; if (idRecord != null) { if (idRecord.TryGetValue(item.Name, out var identity)) { record = identity; identified = true; } } else if (item.Appearance != null) { record = new ItemRecord() { Name = item.Name, Appearance = item.Appearance, }; identified = true; } AppearanceMap[item.Name] = record.Appearance; var columns = this.Columns.Select(col => COLUMN_MAP[col.Attribute].Invoke(item)).ToArray(); var listViewItem = new ListViewItem(columns, costDictionary[item.Cost]); listViewItem.UseItemStyleForSubItems = false; var baseFont = new Font(this.itemListView.Font, FontStyle.Regular); var baseColor = UNSELECTED_COLOR; if (!identified) { baseFont = new Font(baseFont, FontStyle.Bold); baseColor = SELECTED_COLOR; } listViewItem.Checked = identified; listViewItem.Font = baseFont; listViewItem.ForeColor = baseColor; foreach (ListViewSubItem subItem in listViewItem.SubItems) { subItem.Font = baseFont; subItem.ForeColor = baseColor; } if (record.Appearance == null) { var fontStyle = FontStyle.Italic; if (!identified) { fontStyle |= FontStyle.Bold; } for (var i = 0; i < this.Columns.Count; i++) { if (this.Columns[i].Attribute == ItemAttribute.Appearance) { listViewItem.SubItems[i].Font = new Font(baseFont, fontStyle); } } } this.itemListView.Items.Add(listViewItem); } } public IdentificationRecord Export() { List records = []; foreach (ListViewItem item in this.itemListView.Items) { if (item.Checked) { string? appearance = this.AppearanceMap[item.Text]; records.Add(new() { Name = item.Text, Appearance = appearance, }); } } return new(records); } public void UpdateCostHeaders() { for (int i = 0; i < this.GroupCosts.Length; i++) { this.itemListView.Groups[i].Header = this.CostFormatter.Invoke(this.GroupCosts[i]); } } private void itemListView_MouseDoubleClick(object sender, MouseEventArgs e) { if (this.itemListView.SelectedItems.Count == 1) { var item = this.itemListView.SelectedItems[0]; item.Checked = !item.Checked; var baseFont = item.Font; foreach (ListViewSubItem subItem in item.SubItems) { if (item.Checked) { if (subItem.Font.Italic) { subItem.Font = new Font(baseFont, FontStyle.Italic); } else { subItem.Font = new Font(baseFont, FontStyle.Regular); } subItem.ForeColor = UNSELECTED_COLOR; } else { if (subItem.Font.Italic) { subItem.Font = new Font(baseFont, FontStyle.Bold | FontStyle.Italic); } else { subItem.Font = new Font(baseFont, FontStyle.Bold | FontStyle.Regular); } subItem.ForeColor = SELECTED_COLOR; } } this.itemListView.Sort(); } } private static int CompareItems(ListViewItem a, ListViewItem b) { if (a.Checked != b.Checked) { return a.Checked.CompareTo(b.Checked); } else { return a.Text.CompareTo(b.Text); } } } [Serializable] public class ItemDisplayColumn { [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ItemAttribute Attribute { get; set; } [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public int Width { get; set; } } }