annotate foosdk/sdk/libPPUI/CListControlSimple.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 // ================================================================================
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 // CListControlSimple
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 // Simplified CListControl interface; a ready-to-use class that can be instantiated
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 // without subclassing or setting callback objects.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 // Use when you don't need advanced features such as buttons or editing.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 // Maintains its own data.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 // ================================================================================
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 #include "CListControlComplete.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 #include <functional>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 #include <vector>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 #include <map>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 #include <string>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 #include <algorithm>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 class CListControlSimple : public CListControlReadOnly {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 // Events
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 std::function<void()> onReordered; // if not set, list reordering is disabled
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 std::function<void()> onRemoved; // if not set, list item removal is disabled
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 std::function<void(size_t)> onItemAction; // optional, handle item double click or enter key
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 std::function<void()> onSelChange; // optional, handle selectionchange
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 std::function<void(size_t)> onColumnHeaderClick; // optional, handle column header click, if not set sorting will happen
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 size_t GetItemCount() const override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 return m_lines.size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 void SetItemCount( size_t count ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 m_lines.resize( count );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 ReloadData();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 void SetItemText(size_t item, size_t subItem, const char * text, bool bRedraw = true) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 if ( item < m_lines.size() ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 m_lines[item].text[subItem] = text;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 if ( bRedraw ) ReloadItem( item );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 PFC_ASSERT(!"CListControlSimple: item index out of range, call SetItemCount() first");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 bool GetSubItemText(size_t item, size_t subItem, pfc::string_base & out) const override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 if ( item < m_lines.size() ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 auto & l = m_lines[item].text;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 auto iter = l.find( subItem );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 if ( iter != l.end() ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 out = iter->second.c_str();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 uint32_t QueryDragDropTypes() const override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 return (onReordered != nullptr) ? dragDrop_reorder : 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 void RequestReorder( const size_t * order, size_t count) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 if ( onReordered == nullptr ) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 _Reorder(order, count);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 void RequestRemoveSelection() override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 if (onRemoved == nullptr) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 auto mask = this->GetSelectionMask();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 size_t oldCount = m_lines.size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 pfc::remove_mask_t( m_lines, mask );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 this->OnItemsRemoved( mask, oldCount );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 onRemoved();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 void ExecuteDefaultAction( size_t idx ) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 if (onItemAction != nullptr) onItemAction(idx);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 void SetItemUserData( size_t item, size_t user ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 if ( item < m_lines.size() ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 m_lines[item].user = user;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 size_t GetItemUserData( size_t item ) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 size_t ret = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 if ( item < m_lines.size() ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 ret = m_lines[item].user;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 void RemoveAllItems() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 RemoveItems(pfc::bit_array_true());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 void RemoveItems( pfc::bit_array const & mask ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 const auto oldCount = m_lines.size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 pfc::remove_mask_t( m_lines, mask );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 this->OnItemsRemoved( mask, oldCount );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 void RemoveItem( size_t which ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 RemoveItems( pfc::bit_array_one( which ) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 size_t InsertItem( size_t insertAt, const char * textCol0 = nullptr ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 if ( insertAt > m_lines.size() ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 insertAt = m_lines.size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 line_t data;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 if ( textCol0 != nullptr ) data.text[0] = textCol0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 m_lines.insert( m_lines.begin() + insertAt, std::move(data) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 this->OnItemsInserted( insertAt, 1, false );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 return insertAt;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 size_t AddItem( const char * textCol0 = nullptr ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 return InsertItem( SIZE_MAX, textCol0 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 size_t InsertItems( size_t insertAt, size_t count ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 if ( insertAt > m_lines.size() ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 insertAt = m_lines.size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 line_t val;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 m_lines.insert( m_lines.begin() + insertAt, count, val );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 this->OnItemsInserted( insertAt, count, false );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 return insertAt;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 void SortBy(size_t column, bool descending) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 std::vector<size_t> order; order.resize(m_lines.size());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 for (size_t walk = 0; walk < order.size(); ++walk) order[walk] = walk;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 auto pred = [column, descending](const line_t& l1, const line_t& l2) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 int ret = pfc::winNaturalSortCompare(l1.at(column), l2.at(column));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 if (!descending) ret = -ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 return ret > 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 auto pred_order = [&](size_t i1, size_t i2) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 return pred(m_lines[i1], m_lines[i2]);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 std::sort(order.begin(), order.end(), pred_order);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 this->_Reorder(order.data(), order.size());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 this->SetSortIndicator(column, descending);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 void SortBy(size_t column) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 HDITEM item = { HDI_FORMAT };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 if (this->GetHeaderCtrl().GetItem((int)column, &item)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 bool bDescending = (item.fmt & HDF_SORTDOWN) != 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 this->SortBy(column, bDescending);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 void OnSelectionChanged(pfc::bit_array const & affected, pfc::bit_array const & status) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 __super::OnSelectionChanged(affected, status);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 if ( onSelChange ) onSelChange();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 void OnColumnHeaderClick(t_size index) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 __super::OnColumnHeaderClick(index);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 if (onColumnHeaderClick) onColumnHeaderClick(index);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 else this->SortBy(index);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 void _Reorder(const size_t* order, size_t count) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 pfc::reorder_t(m_lines, order, count);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 this->OnItemsReordered(order, count);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 if (onReordered) onReordered();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166 struct line_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 std::map<size_t, std::string> text;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 size_t user = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 const char* at(size_t i) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 auto iter = text.find(i);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 if (iter == text.end()) return "";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 return iter->second.c_str();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 std::vector<line_t> m_lines;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 };