Files
NethackHelper/NethackHelper/ItemDisplay.cs
2025-09-24 00:56:17 -05:00

178 lines
7.2 KiB
C#

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<ItemAttribute, Func<Item, string>> 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<int, string> CostFormatter { get; set; } = cost => cost.ToString();
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public List<ItemDisplayColumn> Columns { get; set; } = new();
private int[] GroupCosts { get; set; } = [];
private Dictionary<string, string?> AppearanceMap { get; set; } = new();
public ItemDisplay() {
InitializeComponent();
this.itemListView.ListViewItemSorter = Comparer<ListViewItem>.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<int, ListViewGroup>();
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<ItemRecord> 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; }
}
}