| package org.jetbrains.plugins.gradle.ui; |
| |
| import com.intellij.ui.ScrollPaneFactory; |
| import com.intellij.ui.table.JBTable; |
| import org.jetbrains.annotations.NotNull; |
| |
| import javax.swing.*; |
| import javax.swing.table.*; |
| import java.awt.*; |
| import java.util.Arrays; |
| |
| /** |
| * Allows to build control that shows target matrix-like information. |
| * <p/> |
| * <code>'Matrix-like'</code> here means that there is a set of columns and a number of rows where every row contains values for |
| * every column. |
| * <p/> |
| * Example: |
| * <pre> |
| * | Column1 name | Column2 name |
| * ---------------------------|----------------- |
| * Row1 name | Value11 | Value12 |
| * ---------------------------|----------------- |
| * Row2 name | Value21 | Value22 |
| * ---------------------------|----------------- |
| * </pre> |
| * <p/> |
| * Not thread-safe. |
| * |
| * @author Denis Zhdanov |
| * @since 3/14/12 3:52 PM |
| */ |
| public class MatrixControlBuilder { |
| |
| private final DefaultTableModel myModel = new DefaultTableModel() { |
| @Override |
| public boolean isCellEditable(int row, int column) { |
| return false; |
| } |
| }; |
| |
| private final JBTable myTable; |
| private final JComponent myResult; |
| private final int[] myColumnWidths; |
| private final FontMetrics myFontMetrics; |
| |
| public MatrixControlBuilder(@NotNull String ... columns) { |
| myModel.addColumn(""); // Row name |
| for (String column : columns) { |
| myModel.addColumn(column); |
| } |
| myTable = new JBTable(myModel) { |
| @Override |
| public Dimension getPreferredScrollableViewportSize() { |
| return getPreferredSize(); |
| } |
| }; |
| myTable.setFocusable(false); |
| myTable.setStriped(true); |
| DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); |
| renderer.setHorizontalAlignment(SwingConstants.CENTER); |
| for (int i = 0, max = myTable.getColumnCount(); i < max; i++) { |
| final TableColumn column = myTable.getColumnModel().getColumn(i); |
| if (i > 0) { |
| // Don't align row name. |
| column.setCellRenderer(renderer); |
| } |
| final TableCellRenderer headerRenderer = column.getHeaderRenderer(); |
| if (headerRenderer instanceof JLabel) { |
| ((JLabel)headerRenderer).setHorizontalAlignment(SwingConstants.CENTER); |
| } |
| } |
| myResult = ScrollPaneFactory.createScrollPane(myTable); |
| |
| myColumnWidths = new int[columns.length + 1/*'name' column*/]; |
| myFontMetrics = myTable.getFontMetrics(myTable.getFont()); |
| for (int i = 0; i < columns.length; i++) { |
| myColumnWidths[i + 1] = myFontMetrics.stringWidth(columns[i]); |
| } |
| } |
| |
| /** |
| * Supplies current builder within the information to use during the new row representation. |
| * |
| * @param name new row now |
| * @param values new row values |
| * @throws IllegalArgumentException if given row values imply number of columns that differs from the number of already configured one |
| */ |
| public void addRow(@NotNull String name, @NotNull Object... values) throws IllegalArgumentException { |
| if (values.length != myModel.getColumnCount() - 1) { |
| StringBuilder columns = new StringBuilder(); |
| for (int i = 1, max = myModel.getColumnCount(); i < max; i++) { |
| columns.append(myModel.getColumnName(i)).append(", "); |
| } |
| if (columns.length() > 2) { |
| columns.setLength(columns.length() - 2); |
| } |
| throw new IllegalArgumentException(String.format( |
| "Can't add row '%s' to the matrix control. Reason: the row specifies incorrect number of values (%d, expected %d). " |
| + "Registered columns: %s. Given values: %s", name, values.length, myModel.getColumnCount() - 1, columns, Arrays.toString(values) |
| )); |
| } |
| Object[] rowData = new Object[values.length + 1]; |
| rowData[0] = name; |
| System.arraycopy(values, 0, rowData, 1, values.length); |
| myModel.addRow(rowData); |
| |
| for (int i = 0; i < rowData.length; i++) { |
| myColumnWidths[i] = Math.max(myFontMetrics.stringWidth(rowData[i].toString()), myColumnWidths[i]); |
| } |
| } |
| |
| @NotNull |
| public JComponent build() { |
| final TableColumnModel columnModel = myTable.getColumnModel(); |
| for (int i = 0; i < myColumnWidths.length; i++) { |
| columnModel.getColumn(i).setMinWidth(myColumnWidths[i] + 4); |
| } |
| return myResult; |
| } |
| } |