// optional parameters static ThreadLocal> showConceptsTable_dropFields = new ThreadLocal; static new ThreadLocal showConceptsTable_postProcess; // func(L) -> L static new ThreadLocal showConceptsTable_afterUpdate; // voidfunc(JTable) static new ThreadLocal showConceptsTable_concepts; static new ThreadLocal showConceptsTable_latestFirst; static new ThreadLocal showConceptsTable_sorter; // func(Cl) -> Cl static int makeConceptsTable_idWidth = 50; static JTable showConceptsTable(Class c) { JTable table = makeConceptsTable(c); showFrame(plural(shortClassName(c)), table); ret table; } static JTable makeConceptsTable(Class c) { LS dropFields = getAndClearThreadLocal(showConceptsTable_dropFields); O pp = getAndClearThreadLocal(showConceptsTable_postProcess); O afterUpdate = optParam(showConceptsTable_afterUpdate); Concepts concepts = optParam(showConceptsTable_concepts, db_mainConcepts()); bool latestFirst = boolParam(showConceptsTable_latestFirst); O sorter = optParam(showConceptsTable_sorter); bool useStruct = boolParam(dataToTable_useStruct); final L fields = listMinusList(concatLists(ll("id"), conceptFieldsInOrder(c)), dropFields); final JTable table = sexyTable(); tablePopupMenu(table, voidfunc(JPopupMenu menu, final int row) { addMenuItem(menu, "Delete", r { final long id = toLong(getTableCell(table, row, 0)); deleteConcept_sync(concepts, id); }); }); temp tempSetTL(awtOnConceptChanges_concepts, concepts); awtOnConceptChanges(table, r { //print("Updating concept table"); new L data; Cl l = list(concepts, c); if (sorter != null) l = (Cl) callF(sorter, l); for (Concept cc : l) data.add(map(func(S field) { O value = cget(cc, field); ret useStruct ? renderForTable(value) : renderForTable_noStruct(value); }, fields)); if (latestFirst) reverseInPlace(data); data = (L) postProcess(pp, data); fillTableWithData(table, data, map humanizeFormLabel(fields)); if (table.getColumnCount() > 0) table.getColumnModel().getColumn(0).setMaxWidth(makeConceptsTable_idWidth); pcallF(afterUpdate, table); }, true); ret table; } // renderer takes a concept and makes a map for display static JTable makeConceptsTable(final Class cClass, final O renderer) { if (renderer == null) ret makeConceptsTable(cClass); fO pp = optParam(showConceptsTable_postProcess); fO afterUpdate = optParam(showConceptsTable_afterUpdate); final Concepts concepts = optParam(showConceptsTable_concepts, db_mainConcepts()); fbool latestFirst = boolParam(showConceptsTable_latestFirst); O sorter = optParam(showConceptsTable_sorter); bool useStruct = boolParam(dataToTable_useStruct); final JTable table = sexyTable(); temp tempSetTL(awtOnConceptChanges_concepts, concepts); awtOnConceptChanges(table, 1000, r { new L data; Cl l = list(concepts, cClass); if (sorter != null) l = (Cl) callF(sorter, l); for (A c : l) addIfNotNull(data, (Map) pcallF(renderer, c)); if (latestFirst) reverseInPlace(data); data = (L) postProcess(pp, data); ifdef makeConceptsTable_debug printVars makeConceptsTable(+useStruct); endifdef temp tempSetTL(dataToTable_useStruct, useStruct); dataToTable_uneditable(data, table); pcallF(afterUpdate, table); }); ret table; } static JTable showConceptsTable(final Class c, final O f) { JTable table = makeConceptsTable(c, f); showFrame(plural(shortClassName(c)), table); ret table; } static JTable showConceptsTable(S title, Class cClass, O f) { ret setFrameTitle(title, showConceptsTable(cClass, f)); }