abstract sclass DynScoreMatrix extends DynObjectTable { transient JTable tblDetails; transient Map detailsMap; transient O detailToMap = func(O test, double score) -> Map { Map map = litorderedmap( "Score" := str(score), "Test" := strOrNull(test)); putAll(map, (Map) callOpt(test, 'extraColumns)); ret map; }; srecord noeq Entry( O candidate, double score, S comment, Map individualScores) {} start { itemToMap = func(Entry e) -> Map { long time = timeSum(keys(e.individualScores)); O size = getOpt size(e.candidate); ret litorderedmap( "Candidate" := str(e.candidate), "Score" := formatDouble(e.score, 2), "Comment" := nullIfEmpty(e.comment), "Size" := size instanceof Long ? toK_str((Long) size) : size, "Time" := time == 0 ? null : renderElapsedTimePleasantly(time), "Tests performed" := nullIfZero(l(e.individualScores))); }; } long timeSum(Iterable l) { ret longSum(collect time(l)); } O comparator() { ret func(Entry a, Entry b) { cmp(b.score, a.score) }; } void add(Entry a) { syncAddToSortedList(comparator(), data, a); fireDataChanged(); if (selected() == null) selectItem(first(data)); } void setData(Cl l) { super.setData(sorted(l, comparator()); } visualize { JComponent sup = super.visualize(); popupMenuItem_top("Export structure", vf exportStructure); onTableSelectionChanged(table, r { showDetails(selected()) }); JComponent c = jvsplit(sup, detailsSection()); onDoubleClickAndEnter(tblDetails, voidfunc(int row) { virtual TestResult item = _get(keysList(detailsMap), row); if (item == null) ret; thread { showDetails(item); } }); ret c; } JComponent detailsSection() { ret jCenteredSection("Details (click on item above to show)", jscroll(tblDetails = sexyTable())); } void showDetails(Entry e) enter { if (e == null) { detailsMap = null; clearTable(tblDetails); } else { detailsMap = sortMapByValue(e.individualScores); dataToTable(tblDetails, map(detailsMap, detailToMap)); } } void exportStructure(Entry e) { S s = wordWrappedStruct(e.candidate); showText(str(e.candidate) + " [" + nChars(s) + "]", s); } // override me void showDetails(virtual TestResult item) { callOpt(item, 'showDetails); } // API Entry newEntry( O candidate, double score, S comment, Map individualScores) { ret new Entry(candidate, score, comment, individualScores); } Entry newEntry( O candidate, double score, Map individualScores) { ret new Entry(candidate, score, null, individualScores); } }