Transpiled version (17745L) is out of date.
1 | sclass JObjectTable<A> is Swingable { |
2 | new L<A> data; |
3 | |
4 | transient IF1<A, Map> itemToMap; |
5 | transient Set<S> hideFields; |
6 | transient bool debug, fieldsInOrder = true, withSearcher; |
7 | settable IVF1<A> defaultAction; |
8 | |
9 | transient gettable JTable table; |
10 | transient TableSearcher searcher; |
11 | transient bool useStruct = false; // possible breaking change for older modules |
12 | |
13 | event listChanged; |
14 | |
15 | *() { |
16 | itemToMap = a -> { |
17 | if (a instanceof S) ret litorderedmap("" := (S) a); |
18 | Map map = humanizeKeys(fieldsInOrder ? objectToMap_inOrder_withoutFields(a, hideFields) : objectToMap(a)); |
19 | if (!useStruct) map = mapValues strOrEmpty(map); |
20 | ret map; |
21 | }; |
22 | } |
23 | |
24 | void onListChangedAndNow(Runnable r) { |
25 | if (r == null) ret; |
26 | onListChanged(r); |
27 | r.run(); |
28 | } |
29 | |
30 | cachedVisualize { |
31 | L<Map> l = map(itemToMap, data); |
32 | table = dataToTable_uneditable(sexyTable(), l); |
33 | onDoubleClickOrEnter(table, voidfunc(int row) { |
34 | A a = _get(data, row); |
35 | if (a != null) defaultAction?.get(a); |
36 | }); |
37 | if (withSearcher) |
38 | ret (searcher = tableWithSearcher2(table)).panel; |
39 | ret jscroll(table); |
40 | } |
41 | |
42 | void updateTable() { |
43 | if (table != null) swing { |
44 | Point scrollPosition = enclosingViewPosition(table); |
45 | if (debug) print("Scroll position: " + scrollPosition); |
46 | dataToTable_uneditable(table, map(itemToMap, data)); |
47 | setEnclosingViewPosition(table, scrollPosition); |
48 | if (searcher != null) searcher.rowIndices = null; |
49 | if (debug) print("dataToTable done, alerting " + n2(onListChanged, "listener")); |
50 | } |
51 | listChanged(); |
52 | } |
53 | |
54 | void clear() { syncClear(data); fireDataChanged(); } |
55 | void add(A a) { syncAdd(data, a); fireDataChanged(); } |
56 | A addAndReturn(A a) { add(a); ret a; } |
57 | void add(int idx, A a) { syncAdd(data, idx, a); fireDataChanged(); } |
58 | void addAll(Collection<A> l) { if (empty(l)) ret; syncAddAll(data, l); fireDataChanged(); } |
59 | void addAndScrollDown(A a) { add(a); scrollDown(); } |
60 | void remove(A a) { syncRemove(data, a); fireDataChanged(); } |
61 | void removeAll(L<A> a) { syncRemoveAll(data, a); fireDataChanged(); } |
62 | void setList(Iterable<A> data) { setData(data); } |
63 | void removeSelected() { removeAll(allSelected()); } |
64 | |
65 | void setData(Iterable<A> data, bool force default false) { |
66 | swing { |
67 | int[] selection = selectedTableRows_array(table); |
68 | L<A> cloned = cloneList(data); |
69 | if (force || !eq(this.data, cloned)) { |
70 | this.data = cloned; |
71 | updateTable(); |
72 | } |
73 | selectTableRows(table, selection); |
74 | } |
75 | } |
76 | int count() { ret syncL(data); } |
77 | |
78 | void setData_force(Iterable<A> data) { setData(data, true); } |
79 | |
80 | // tries to keep selection |
81 | void fireDataChanged() { setData_force(data); } |
82 | |
83 | int rowFromSearcher(int i) { |
84 | ret searcher == null || searcher.rowIndices == null ? i : or(get(searcher.rowIndices, i), -1); |
85 | } |
86 | |
87 | A selected() { ret syncGet(data, rowFromSearcher(selectedTableRowInModel(table))); } |
88 | L<A> allSelected() { ret syncListGetMulti(data, selectedIndices()); } |
89 | int selectedIndex() { ret selectedTableRow(table); } |
90 | L<Int> selectedIndices() { ret map(i -> rowFromSearcher(i), selectedTableRowsInModel(table)); } |
91 | bool selectItem(A a) { int i = indexOf(data, a); selectRow(table, i); ret i >= 0; } // true if item exists |
92 | void doubleClickItem(A a) { if (selectItem(a)) defaultAction?.get(a); } |
93 | |
94 | // run only after visualized! |
95 | void popupMenuItem(S text, IVF1<A> r) { |
96 | tablePopupMenuItemsThreaded(table, text, _convertRunnable(r)); |
97 | } |
98 | |
99 | void popupMenuItem_top(S text, IVF1<A> r) { |
100 | tablePopupMenuItemsThreaded_top(table, text, _convertRunnable(r)); |
101 | } |
102 | |
103 | // row index => element |
104 | IVF1<Int> _convertRunnable(IVF1<A> r) { |
105 | ret r == null ?: idx -> r.get(syncGet(data, idx)); |
106 | } |
107 | |
108 | void hideFields(S... fields) { |
109 | if (hideFields == null) hideFields = new Set; |
110 | _addAll(hideFields, fields); |
111 | } |
112 | |
113 | A getRow(int row) { ret get(data, row); } |
114 | |
115 | void scrollDown { scrollTableDownNow(table); } |
116 | |
117 | void onSelect(IVF1<A> r) { |
118 | visualize(); |
119 | onTableSelectionChanged(table, -> pcallF_typed(r, selected())); |
120 | } |
121 | |
122 | L<A> getList() { ret data; } |
123 | } |
Began life as a copy of #1030725
download show line numbers debug dex old transpilations
Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1034021 |
Snippet name: | JObjectTable - like JConceptsTable but for any kind of object |
Eternal ID of this version: | #1034021/17 |
Text MD5: | 91b330004687208503c65f877bcc487d |
Author: | stefan |
Category: | javax / gui / concepts |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-03-25 22:59:05 |
Source code size: | 4268 bytes / 123 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 179 / 350 |
Version history: | 16 change(s) |
Referenced in: | [show references] |