/* * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.ui.components; import javax.swing.*; import javax.swing.border.Border; import javax.swing.table.TableCellRenderer; import java.awt.*; import java.awt.event.KeyEvent; /** * @author Konstantin Bulenkov */ public class MultiColumnList extends JTable { private final ListModel myModel; private ListCellRenderer myRenderer; private JList myList; private Dimension myPrefSize; public MultiColumnList(ListModel model) { super(new FixedRowsModel(model, 25)); myModel = model; setRowHeight(20); setShowGrid(false); setCellSelectionEnabled(true); setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); //noinspection UndesirableClassUsage myList = new JList(model) { @Override public void setBorder(Border border) { super.setBorder(border); MultiColumnList.this.setBorder(border); } @Override public void repaint() { MultiColumnList.this.repaint(); } @Override public void setCellRenderer(ListCellRenderer cellRenderer) { super.setCellRenderer(cellRenderer); if (myRenderer != cellRenderer) { MultiColumnList.this.setCellRenderer(cellRenderer); } } }; getColumnModel().setColumnMargin(0); } @Override protected void processKeyEvent(KeyEvent e) { final int key = e.getKeyCode(); final int col = getSelectedColumn(); final int row = getSelectedRow(); final MultiColumnListModel model = getModel(); int r = row; int c = col; if (key == KeyEvent.VK_RIGHT) { if (c + 1 < getColumnCount()) { c++; } } else if (key == KeyEvent.VK_DOWN) { if (r + 1 < getRowCount()) { r++; if (model.toListIndex(r, c ) >= model.getSize()) { r = 0; c++; } } else { r = 0; c++; } } if (col != c || row != r) { if (e.getID() == KeyEvent.KEY_RELEASED) return; int index = model.toListIndex(r, c); if (index >= model.getSize() || r >= getRowCount() || c >= getColumnCount()) { e.consume(); final int last = model.getSize() - 1; changeSelection(model.getRow(last), model.getColumn(last), false, false); } else { changeSelection(r, c, false, false); e.consume(); } } else { super.processKeyEvent(e); } } public MultiColumnList(Object...elements) { this(createListModel(elements)); } private static ListModel createListModel(Object...elements) { final DefaultListModel model = new DefaultListModel(); for (Object element : elements) { model.addElement(element); } return model; } public void setCellRenderer(ListCellRenderer renderer) { myRenderer = renderer; setDefaultRenderer(Object.class, new TableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final int index = getModel().toListIndex(row, column); if (isSelected) { myList.addSelectionInterval(index, index); } else { myList.removeSelectionInterval(index, index); } return myRenderer.getListCellRendererComponent(myList, value, index, isSelected, hasFocus); } }); } public void setFixedRowsMode(int maxRows) { if (maxRows < 1) { throw new IllegalArgumentException("Should be greater than 0"); } setModel(new FixedRowsModel(myModel, maxRows)); getModel().fireTableStructureChanged(); } @Override public MultiColumnListModel getModel() { return (MultiColumnListModel)super.getModel(); } public void setFixedColumnsMode(int maxColumns) { if (maxColumns < 1) { throw new IllegalArgumentException("Should be greater than 0"); } setModel(new FixedColumnsModel(myModel, maxColumns)); getModel().fireTableStructureChanged(); } public JList getDelegate() { return myList; } @Override public Dimension getPreferredSize() { if (myPrefSize == null) { Dimension dimension = new Dimension(); int rowHeight = 0; for (int column = 0; column < getColumnCount(); column++) { int columnWidth = 0; for (int row = 0; row < getRowCount(); row++) { final TableCellRenderer renderer = getCellRenderer(row, column); if (renderer != null) { final Object value = getValueAt(row, column); final Component component = renderer.getTableCellRendererComponent(this, value, true, true, row, column); if (component != null) { final Dimension size = component.getPreferredSize(); rowHeight = Math.max(size.height, rowHeight); columnWidth = Math.max(size.width, columnWidth); } } } getColumnModel().getColumn(column).setWidth(columnWidth + 5); dimension.width += columnWidth + 5; } dimension.height = getRowCount() * rowHeight; myPrefSize = dimension; } return myPrefSize; } public static void main(String[] args) { final JFrame frame = new JFrame("Test"); frame.setSize(300, 300); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); final MultiColumnList list = new MultiColumnList("1", 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13); list.setFixedColumnsMode(5); frame.getContentPane().add(list); frame.setVisible(true); } }