package com.jetbrains.actionscript.profiler.base; import com.intellij.util.ui.tree.TreeUtil; import com.jetbrains.actionscript.profiler.util.JTreeUtil; import javax.swing.*; import javax.swing.table.TableColumnModel; import javax.swing.table.TableRowSorter; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import java.util.ArrayList; import java.util.Comparator; import java.util.List; public class TreeTableRowSorter extends TableRowSorter { private final BaseSortableTreeTable table; private List<? extends SortKey> sortKeys = new ArrayList<>(); public TreeTableRowSorter(BaseSortableTreeTable table) { super(table.getModel()); this.table = table; } @Override public List<? extends SortKey> getSortKeys() { return sortKeys; } @Override public void setSortKeys(List sortKeys) { if (sortKeys == null) { return; } this.sortKeys = sortKeys; sort(); } @Override public void sort() { if (sortKeys.size() > 0) { sortOnKey(sortKeys.get(0)); } } private void sortOnKey(SortKey key) { if (key.getSortOrder() == SortOrder.UNSORTED) { return; } final int columnModelIndex = key.getColumn(); TableColumnModel colModel = table.getColumnModel(); int modelIndex = colModel.getColumn(columnModelIndex).getModelIndex(); if (modelIndex < 0 || getComparator(modelIndex) == null) { return; } final Comparator<TreeNode> comparator = new ComparatorWrapper<>(getComparator(modelIndex), key.getSortOrder() == SortOrder.ASCENDING); final List<TreePath> paths = TreeUtil.collectExpandedPaths(table.getTree()); if (JTreeUtil.isSorted(paths, comparator, table.getTableModel())) { return; } for (TreePath path : paths) { Object node = path.getLastPathComponent(); if (!(node instanceof DefaultMutableTreeNode)) { continue; } JTreeUtil.sortChildren((DefaultMutableTreeNode)node, comparator, table.getTableModel().getChildCount(node)); } table.reload(); TreeUtil.restoreExpandedPaths(table.getTree(), paths); } private static class ComparatorWrapper<T> implements Comparator<T> { private final Comparator<T> comparator; private final boolean reverse; public ComparatorWrapper(Comparator<T> comparator, boolean reverse) { this.comparator = comparator; this.reverse = reverse; } @Override public int compare(T o1, T o2) { return reverse ? -comparator.compare(o1, o2) : comparator.compare(o1, o2); } } }