//----------------------------------------------------------------------------// // // // U n i t T r e e T a b l e // // // //----------------------------------------------------------------------------// // <editor-fold defaultstate="collapsed" desc="hdr"> // // Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. // // This software is released under the GNU General Public License. // // Goto http://kenai.com/projects/audiveris to report bugs or suggestions. // //----------------------------------------------------------------------------// // </editor-fold> package omr.constant; import omr.ui.treetable.JTreeTable; import omr.ui.treetable.TreeTableModelAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.Rectangle; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.UIManager; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumnModel; import javax.swing.tree.TreePath; /** * Class {@code UnitTreeTable} is a user interface that combines a tree * to display the hierarchy of Units, that contains ConstantSets, * and a table to display and edit the various Constants in * each ConstantSet. * * @author Hervé Bitteur */ public class UnitTreeTable extends JTreeTable { //~ Static fields/initializers --------------------------------------------- /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger(UnitTreeTable.class); /** Alternate color for zebra appearance */ private static final Color zebraColor = new Color(248, 248, 255); //~ Instance fields -------------------------------------------------------- private TableCellRenderer valueRenderer = new ValueRenderer(); private TableCellRenderer pixelRenderer = new PixelRenderer(); //~ Constructors ----------------------------------------------------------- //---------------// // UnitTreeTable // //---------------// /** * Create a User Interface JTreeTable dedicated to the handling of * unit constants. * * @param model the corresponding data model */ public UnitTreeTable (UnitModel model) { super(model); setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // Zebra UIManager.put("Table.alternateRowColor", zebraColor); setFillsViewportHeight(true); // Show grid? //setShowGrid(true); // Specify column widths adjustColumns(); // Customize the tree aspect tree.setRootVisible(false); tree.setShowsRootHandles(true); // Pre-expand all package nodes preExpandPackages(); } //~ Methods ---------------------------------------------------------------- //---------------// // getCellEditor // //---------------// @Override public TableCellEditor getCellEditor (int row, int col) { UnitModel.Column column = UnitModel.Column.values()[col]; switch (column) { case MODIF: { Object node = nodeForRow(row); if (node instanceof Constant) { return getDefaultEditor(Boolean.class); } } break; case VALUE: { Object obj = getModel().getValueAt(row, col); if (obj instanceof Boolean) { return getDefaultEditor(Boolean.class); } } break; default: } // Default cell editor (determined by column class) return super.getCellEditor(row, col); } //-----------------// // getCellRenderer // //-----------------// /** * Used by the UI to get the proper renderer for each given cell in * the table. * * @param row row in the table * @param col column in the table * @return the best renderer for the cell. */ @Override public TableCellRenderer getCellRenderer (int row, int col) { UnitModel.Column column = UnitModel.Column.values()[col]; switch (column) { case MODIF: { Object obj = getModel().getValueAt(row, col); if (obj instanceof Boolean) { // A constant => Modif flag return getDefaultRenderer(Boolean.class); } else { // A node (unit or package) return getDefaultRenderer(Object.class); } } case VALUE: { Object obj = getModel().getValueAt(row, col); if (obj instanceof Boolean) { return getDefaultRenderer(Boolean.class); } else { return valueRenderer; } } case PIXEL: return pixelRenderer; default: return getDefaultRenderer(getColumnClass(col)); } } //--------------------// // scrollRowToVisible // //--------------------// /** * Scroll so that the provided row gets visible * * @param row the provided row */ public void scrollRowToVisible (int row) { final int height = tree.getRowHeight(); Rectangle rect = new Rectangle(0, row * height, 0, 0); if (getParent() instanceof JComponent) { JComponent comp = (JComponent) getParent(); rect.grow(0, comp.getHeight() / 2); } else { rect.grow(0, height); } scrollRectToVisible(rect); } //-------------------// // setNodesSelection // //-------------------// /** * Select the rows that correspond to the provided nodes * * @param matches the nodes to select * @return the relevant rows */ public List<Integer> setNodesSelection (Collection<Object> matches) { List<TreePath> paths = new ArrayList<>(); for (Object object : matches) { if (object instanceof Constant) { Constant constant = (Constant) object; TreePath path = getPath(constant, constant.getQualifiedName()); paths.add(path); } else if (object instanceof Node) { Node node = (Node) object; TreePath path = getPath(node, node.getName()); paths.add(path); } } // Selection on tree side tree.setSelectionPaths(paths.toArray(new TreePath[paths.size()])); // Selection on table side clearSelection(); List<Integer> rows = new ArrayList<>(); for (TreePath path : paths) { int row = tree.getRowForPath(path); if (row != -1) { rows.add(row); addRowSelectionInterval(row, row); } } Collections.sort(rows); return rows; } //---------------// // adjustColumns // //---------------// /** * Allows to adjust the related columnModel, for each and every * column * * @param cModel the proper table column model */ private void adjustColumns () { TableColumnModel cModel = getColumnModel(); // Columns widths for (UnitModel.Column c : UnitModel.Column.values()) { cModel.getColumn(c.ordinal()).setPreferredWidth(c.getWidth()); } } //---------// // getPath // //---------// private TreePath getPath (Object object, String fullName) { UnitManager unitManager = UnitManager.getInstance(); List<Object> objects = new ArrayList<>(); objects.add(unitManager.getRoot()); int dotPos = -1; while ((dotPos = fullName.indexOf('.', dotPos + 1)) != -1) { String path = fullName.substring(0, dotPos); objects.add(unitManager.getNode(path)); } objects.add(object); logger.debug("path to {} objects:{}", fullName, objects); return new TreePath(objects.toArray()); } //------------// // nodeForRow // //------------// /** * Return the tree node facing the provided table row * * @param row the provided row * @return the corresponding tree node */ private Object nodeForRow (int row) { return ((TreeTableModelAdapter) getModel()).nodeForRow(row); } //-------------------// // preExpandPackages // //-------------------// /** * Before displaying the tree, expand all nodes that correspond to * packages (PackageNode). */ private void preExpandPackages () { for (int row = 0; row < tree.getRowCount(); row++) { if (tree.isCollapsed(row)) { tree.expandRow(row); } } } //~ Inner Classes ---------------------------------------------------------- //---------------// // PixelRenderer // //---------------// private static class PixelRenderer extends DefaultTableCellRenderer { //~ Methods ------------------------------------------------------------ @Override public Component getTableCellRendererComponent (JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column); // Use right alignment setHorizontalAlignment(SwingConstants.RIGHT); return this; } } //---------------// // ValueRenderer // //---------------// private static class ValueRenderer extends DefaultTableCellRenderer { //~ Methods ------------------------------------------------------------ @Override public Component getTableCellRendererComponent (JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent( table, value, isSelected, hasFocus, row, column); // Use a bold font setFont(table.getFont().deriveFont(Font.BOLD).deriveFont(12.0f)); // Use center alignment setHorizontalAlignment(SwingConstants.CENTER); return this; } } }