abstract sclass DynObjectTable extends DynModule { new L data; transient JTable table; transient F1 itemToMap; transient VF1 defaultAction; transient bool debug; start { itemToMap = func(A a) -> Map { a instanceof S ? litorderedmap("" := (S) a) : humanizeKeys(objectToMap(a)) }; onChange(r updateTable); } JComponent visualize() { table = dataToTable_uneditable(sexyTable(), map(itemToMap, data)); onDoubleClickOrEnter(table, voidfunc(int row) { temp enter(); A a = _get(data, row); if (a != null) onDoubleClick(a); }); ret table; } void unvisualize() { table = null; } void onDoubleClick(A line) { callF(defaultAction, line); } void updateTable() { temp enter(); if (table != null) { dataToTable_uneditable(table, map(itemToMap, data)); if (debug) print("dataToTable done"); } } void dontPersist() { _persistenceInfo = mapPlus(_persistenceInfo, data := false); } void clear() { syncClear(data); change(); } void add(A a) { syncAdd(data, a); change(); } void setData(Collection data) { if (isFalse(mapGet(_persistenceInfo, 'data))) { if (neq(this.data, data)) { this.data = cloneList(data); updateTable(); } } else setField(data := cloneList(data)); } A selected() { ret syncGet(data, selectedTableRow(table)); } // r : Runnable or VF1 // run only in visualize()! void popupMenuItem(S text, O r) { tablePopupMenuItemsThreaded(table, text, r); } void popupMenuItem_top(S text, O r) { tablePopupMenuItemsThreaded_top(table, text, r); } }