1 | sclass JConceptsTable<A extends Concept> implements Swingable { |
2 | Class<? extends A> conceptClass; |
3 | Concepts concepts; |
4 | JTable table; |
5 | |
6 | // options |
7 | MapSO filters; // fields to filter by/add to new objects |
8 | S hID = "ID"; // Column header for concept ID |
9 | settable LS dropFields; |
10 | IF1<L> postProcess; |
11 | Runnable afterUpdate; |
12 | bool latestFirst; |
13 | IF1<Cl<A>> sorter = lambda1 defaultSort; |
14 | int idWidth = 50; |
15 | settable int updateInterval = 100; |
16 | int firstUpdateInterval = 100; |
17 | bool humanizeFieldNames = true; |
18 | Float tableFontSize; |
19 | Int tableRowHeight; |
20 | settable bool addCountToEnclosingTab; |
21 | settable bool useNewChangeHandler; |
22 | |
23 | AWTOnConceptChanges changeHandler; |
24 | AWTOnConceptChangesByClass newChangeHandler; |
25 | |
26 | *() {} |
27 | *(Class<? extends A> *conceptClass) {} |
28 | *(Concepts *concepts, Class<? extends A> *conceptClass) {} |
29 | |
30 | swappable MapSO itemToMap(A a) { |
31 | ret putAll(specialFieldsForItem(a), mapValues renderForTable_noStruct(itemToMap_inner2(a))); |
32 | } |
33 | |
34 | swappable MapSO itemToMap_inner2(A a) { |
35 | ret allConceptFieldsAsMapExcept(a, dropFields); |
36 | } |
37 | |
38 | // shown on the left (usually) |
39 | swappable MapSO specialFieldsForItem(A a) { |
40 | MapSO map = litorderedmap(hID, str(a.id)); |
41 | mapPut(map, "Java Class", javaClassDescForItem(a)); |
42 | ret map; |
43 | } |
44 | |
45 | S javaClassDescForItem(A a) { |
46 | S className = dynShortClassName(a); |
47 | if (neq(className, shortClassName(conceptClass))) { |
48 | S text = className; |
49 | S realClass = shortClassName(a); |
50 | if (neq(className, realClass)) |
51 | text += " as " + realClass; |
52 | ret text; |
53 | } |
54 | null; |
55 | } |
56 | |
57 | S defaultTitle() { |
58 | ret plural(shortClassName(conceptClass)); |
59 | } |
60 | |
61 | void showAsFrame(S title default defaultTitle()) { |
62 | makeTable(); |
63 | showFrame(title, table); |
64 | } |
65 | |
66 | void makeTable { |
67 | if (table != null) ret; |
68 | if (concepts == null) concepts = db_mainConcepts(); |
69 | |
70 | table = sexyTable(); |
71 | if (tableFontSize != null) { |
72 | setTableFontSizes(tableFontSize, table); |
73 | if (tableRowHeight == null) |
74 | tableRowHeight = iround(tableFontSize*1.5); |
75 | } |
76 | if (tableRowHeight != null) setRowHeight(table, tableRowHeight); |
77 | |
78 | if (useNewChangeHandler) { |
79 | newChangeHandler = new AWTOnConceptChangesByClass(concepts, conceptClass, table, lambda0 _update) |
80 | .delay(updateInterval) |
81 | .firstDelay(firstUpdateInterval); |
82 | newChangeHandler.install(); |
83 | } else { |
84 | changeHandler = new AWTOnConceptChanges(concepts, table, lambda0 _update) |
85 | .delay(updateInterval) |
86 | .firstDelay(firstUpdateInterval); |
87 | changeHandler.install(); |
88 | } |
89 | } |
90 | |
91 | // e.g. to update enclosing tab when hidden |
92 | void update { |
93 | swing { _update(); } |
94 | } |
95 | |
96 | void _update { |
97 | if (table == null) ret; |
98 | new L<Map> data; |
99 | Set<Long> selection = toSet(selectedConceptIDs()); |
100 | Cl<? extends A> l = conceptsWhere(concepts, conceptClass, mapToParams(filters)); |
101 | l = postProcess(sorter, l); |
102 | for (A c : l) |
103 | addIfNotNull(data, itemToMap(c)); |
104 | if (latestFirst) reverseInPlace(data); |
105 | data = (L) postProcess(postProcess, data); |
106 | dataToTable_uneditable(data, table); |
107 | if (humanizeFieldNames) |
108 | humanizeTableColumns(); |
109 | tableColumnMaxWidth(table, 0, idWidth); |
110 | |
111 | restoreSelection(selection); |
112 | |
113 | if (addCountToEnclosingTab) |
114 | updateEnclosingTabTitle(); |
115 | |
116 | pcallF(afterUpdate); |
117 | } |
118 | |
119 | void updateEnclosingTabTitle { |
120 | updateEnclosingTabTitleWithCount(table, countConcepts(concepts, conceptClass)); |
121 | } |
122 | |
123 | void humanizeTableColumns { |
124 | int n = tableColumnCount(table); |
125 | for i to n: |
126 | setColumnName(table, i, humanizeFormLabel(getColumnName(table, i))); |
127 | }; |
128 | |
129 | visual table(); |
130 | |
131 | JTable table() { |
132 | makeTable(); |
133 | ret table; |
134 | } |
135 | |
136 | A selectedConcept() { |
137 | ret (A) concepts.getConcept(toLong(selectedTableCell(table, 0))); |
138 | } |
139 | |
140 | A selected() { ret selectedConcept(); } |
141 | |
142 | long getItemID(int row) { |
143 | ret toLong(getTableCell(table, row, 0)); |
144 | } |
145 | |
146 | A getItem(int row) { |
147 | ret (A) concepts.getConcept(getItemID(row)); |
148 | } |
149 | |
150 | int indexOfConcept(final A c) { |
151 | if (c == null) ret -1; |
152 | ret swing(func -> int { |
153 | int n = tableRowCount(table); |
154 | for row to n: |
155 | if (toLong(getTableCell(table, row, 0)) == c.id) |
156 | ret row; |
157 | ret -1; |
158 | }); |
159 | } |
160 | |
161 | L<A> selectedConcepts() { |
162 | ret swing(-> { |
163 | int[] rows = table.getSelectedRows(); |
164 | new L<A> l; |
165 | for (int row : rows) |
166 | l.add(getItem(row)); |
167 | ret l; |
168 | }); |
169 | } |
170 | |
171 | L<Long> selectedConceptIDs() { |
172 | ret swing(-> { |
173 | int[] rows = table.getSelectedRows(); |
174 | L<Long> l = emptyList(l(rows)); |
175 | for (int row : rows) |
176 | l.add(getItemID(row)); |
177 | ret l; |
178 | }); |
179 | } |
180 | |
181 | void restoreSelection(Set<Long> selection) swing { |
182 | int n = tableRowCount(table); |
183 | new IntBuffer toSelect; |
184 | for row to n: |
185 | if (selection.contains(getItemID(row))) |
186 | toSelect.add(row); |
187 | selectTableRows(table, toSelect.toIntArray()); |
188 | } |
189 | |
190 | Cl<A> defaultSort(Cl<A> l) { |
191 | ret sortByConceptID(l); |
192 | } |
193 | |
194 | selfType addFilter(S field, O value) { |
195 | filters = orderedMapPutOrCreate(filters, field, value); |
196 | this; |
197 | } |
198 | |
199 | // call AFTER table was made |
200 | void onSelectionChanged(Runnable r) { |
201 | if (table == null) warn("Call onSelectionChanged after making table"); |
202 | onTableSelectionChanged(table, r); |
203 | } |
204 | |
205 | void onSelectionChangedAndNow(Runnable r) { |
206 | if (r == null) ret; |
207 | onSelectionChanged(r); |
208 | r.run(); |
209 | } |
210 | } |
Began life as a copy of #1030725
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1034339 |
Snippet name: | JConceptsTable (backup before new selection change listener mechanism) |
Eternal ID of this version: | #1034339/1 |
Text MD5: | 1e39c94b0f6b1f1f46de0741ab237a1b |
Author: | stefan |
Category: | javax / gui / concepts |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-02-03 00:27:25 |
Source code size: | 5655 bytes / 210 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 131 / 148 |
Referenced in: | [show references] |