diff options
Diffstat (limited to 'src/items_pane.cpp')
-rw-r--r-- | src/items_pane.cpp | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/items_pane.cpp b/src/items_pane.cpp new file mode 100644 index 0000000..055eec0 --- /dev/null +++ b/src/items_pane.cpp | |||
@@ -0,0 +1,145 @@ | |||
1 | #include "items_pane.h" | ||
2 | |||
3 | #include <map> | ||
4 | |||
5 | namespace { | ||
6 | |||
7 | enum SortInstruction { | ||
8 | SI_NONE = 0, | ||
9 | SI_ASC = 1 << 0, | ||
10 | SI_DESC = 1 << 1, | ||
11 | SI_NAME = 1 << 2, | ||
12 | SI_AMOUNT = 1 << 3, | ||
13 | SI_ORDER = 1 << 4, | ||
14 | }; | ||
15 | |||
16 | inline SortInstruction operator|(SortInstruction lhs, SortInstruction rhs) { | ||
17 | return static_cast<SortInstruction>(static_cast<int>(lhs) | | ||
18 | static_cast<int>(rhs)); | ||
19 | } | ||
20 | |||
21 | template <typename T> | ||
22 | int ItemCompare(const T& lhs, const T& rhs, bool ascending) { | ||
23 | if (lhs < rhs) { | ||
24 | return ascending ? -1 : 1; | ||
25 | } else if (lhs > rhs) { | ||
26 | return ascending ? 1 : -1; | ||
27 | } else { | ||
28 | return 0; | ||
29 | } | ||
30 | } | ||
31 | |||
32 | int wxCALLBACK RowCompare(wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData) { | ||
33 | const ItemState& lhs = *reinterpret_cast<const ItemState*>(item1); | ||
34 | const ItemState& rhs = *reinterpret_cast<const ItemState*>(item2); | ||
35 | SortInstruction instruction = static_cast<SortInstruction>(sortData); | ||
36 | |||
37 | bool ascending = (instruction & SI_ASC) != 0; | ||
38 | if ((instruction & SI_NAME) != 0) { | ||
39 | return ItemCompare(lhs.name, rhs.name, ascending); | ||
40 | } else if ((instruction & SI_AMOUNT) != 0) { | ||
41 | return ItemCompare(lhs.amount, rhs.amount, ascending); | ||
42 | } else if ((instruction & SI_ORDER) != 0) { | ||
43 | return ItemCompare(lhs.index, rhs.index, ascending); | ||
44 | } else { | ||
45 | return 0; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | } // namespace | ||
50 | |||
51 | ItemsPane::ItemsPane(wxWindow* parent) | ||
52 | : wxListView(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, | ||
53 | wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_HRULES) { | ||
54 | AppendColumn("Item", wxLIST_FORMAT_LEFT, wxLIST_AUTOSIZE_USEHEADER); | ||
55 | AppendColumn("Amount", wxLIST_FORMAT_LEFT, wxLIST_AUTOSIZE_USEHEADER); | ||
56 | AppendColumn("Order", wxLIST_FORMAT_LEFT, wxLIST_AUTOSIZE_USEHEADER); | ||
57 | |||
58 | Bind(wxEVT_LIST_COL_CLICK, &ItemsPane::OnColClick, this); | ||
59 | Bind(wxEVT_DPI_CHANGED, &ItemsPane::OnDPIChanged, this); | ||
60 | } | ||
61 | |||
62 | void ItemsPane::ResetIndicators() { | ||
63 | DeleteAllItems(); | ||
64 | items_.clear(); | ||
65 | } | ||
66 | |||
67 | void ItemsPane::UpdateIndicators(const std::vector<ItemState>& items) { | ||
68 | std::map<std::string, ItemState> items_by_name; | ||
69 | |||
70 | for (const ItemState& item : items) { | ||
71 | items_by_name[item.name] = item; | ||
72 | } | ||
73 | |||
74 | for (int i = 0; i < GetItemCount(); i++) { | ||
75 | std::string item_name = GetItemText(i).utf8_string(); | ||
76 | auto it = items_by_name.find(item_name); | ||
77 | |||
78 | if (it != items_by_name.end()) { | ||
79 | SetItem(i, 1, std::to_string(it->second.amount)); | ||
80 | SetItem(i, 2, std::to_string(it->second.index)); | ||
81 | |||
82 | *reinterpret_cast<ItemState*>(GetItemData(i)) = it->second; | ||
83 | |||
84 | items_by_name.erase(item_name); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | for (const auto& [name, item] : items_by_name) { | ||
89 | int i = InsertItem(GetItemCount(), name); | ||
90 | SetItem(i, 1, std::to_string(item.amount)); | ||
91 | SetItem(i, 2, std::to_string(item.index)); | ||
92 | |||
93 | auto item_ptr = std::make_unique<ItemState>(item); | ||
94 | SetItemPtrData(i, reinterpret_cast<wxUIntPtr>(item_ptr.get())); | ||
95 | items_.push_back(std::move(item_ptr)); | ||
96 | } | ||
97 | |||
98 | SetColumnWidth(0, wxLIST_AUTOSIZE); | ||
99 | SetColumnWidth(1, wxLIST_AUTOSIZE_USEHEADER); | ||
100 | SetColumnWidth(2, wxLIST_AUTOSIZE_USEHEADER); | ||
101 | |||
102 | if (GetSortIndicator() != -1) { | ||
103 | DoSort(GetSortIndicator(), IsAscendingSortIndicator()); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | void ItemsPane::OnColClick(wxListEvent& event) { | ||
108 | int col = event.GetColumn(); | ||
109 | if (col == -1) { | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | bool ascending = GetUpdatedAscendingSortIndicator(col); | ||
114 | |||
115 | DoSort(col, ascending); | ||
116 | } | ||
117 | |||
118 | void ItemsPane::OnDPIChanged(wxDPIChangedEvent& event) { | ||
119 | SetColumnWidth(0, wxLIST_AUTOSIZE); | ||
120 | SetColumnWidth(1, wxLIST_AUTOSIZE_USEHEADER); | ||
121 | SetColumnWidth(2, wxLIST_AUTOSIZE_USEHEADER); | ||
122 | |||
123 | event.Skip(); | ||
124 | } | ||
125 | |||
126 | void ItemsPane::DoSort(int col, bool ascending) { | ||
127 | SortInstruction instruction = SI_NONE; | ||
128 | if (ascending) { | ||
129 | instruction = instruction | SI_ASC; | ||
130 | } else { | ||
131 | instruction = instruction | SI_DESC; | ||
132 | } | ||
133 | |||
134 | if (col == 0) { | ||
135 | instruction = instruction | SI_NAME; | ||
136 | } else if (col == 1) { | ||
137 | instruction = instruction | SI_AMOUNT; | ||
138 | } else if (col == 2) { | ||
139 | instruction = instruction | SI_ORDER; | ||
140 | } | ||
141 | |||
142 | if (SortItems(RowCompare, instruction)) { | ||
143 | ShowSortIndicator(col, ascending); | ||
144 | } | ||
145 | } | ||