001 /* 002 * Copyright (C) 2008-2010 by Holger Arndt 003 * 004 * This file is part of the Universal Java Matrix Package (UJMP). 005 * See the NOTICE file distributed with this work for additional 006 * information regarding copyright ownership and licensing. 007 * 008 * UJMP is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation; either version 2 011 * of the License, or (at your option) any later version. 012 * 013 * UJMP is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public 019 * License along with UJMP; if not, write to the 020 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 021 * Boston, MA 02110-1301 USA 022 */ 023 024 package org.ujmp.gui.panels; 025 026 import java.awt.Component; 027 import java.awt.Font; 028 import java.awt.GridBagConstraints; 029 import java.awt.GridBagLayout; 030 import java.awt.Insets; 031 import java.awt.Rectangle; 032 import java.awt.event.KeyEvent; 033 import java.awt.event.KeyListener; 034 import java.awt.event.MouseEvent; 035 import java.awt.event.MouseListener; 036 037 import javax.swing.AbstractListModel; 038 import javax.swing.BorderFactory; 039 import javax.swing.JLabel; 040 import javax.swing.JList; 041 import javax.swing.JPanel; 042 import javax.swing.JPopupMenu; 043 import javax.swing.JScrollPane; 044 import javax.swing.JTable; 045 import javax.swing.JViewport; 046 import javax.swing.ListCellRenderer; 047 import javax.swing.ListSelectionModel; 048 import javax.swing.UIManager; 049 import javax.swing.border.Border; 050 import javax.swing.event.ListSelectionEvent; 051 import javax.swing.event.ListSelectionListener; 052 import javax.swing.event.TableModelEvent; 053 import javax.swing.event.TableModelListener; 054 import javax.swing.table.DefaultTableModel; 055 import javax.swing.table.JTableHeader; 056 import javax.swing.table.TableModel; 057 058 import org.ujmp.gui.MatrixGUIObject; 059 import org.ujmp.gui.editor.MatrixTableCellEditor; 060 import org.ujmp.gui.menu.MatrixPopupMenu; 061 import org.ujmp.gui.renderer.MatrixValueTableCellRenderer; 062 063 public class MatrixTableEditorPanel extends JPanel implements TableModelListener, MouseListener, KeyListener, 064 ListSelectionListener { 065 private static final long serialVersionUID = -1794955656888362574L; 066 067 private MatrixGUIObject dataModel = null; 068 069 private final TableModel emptyModel = new DefaultTableModel(); 070 071 private JTable jTable = null; 072 073 private JList rowHeader = null; 074 075 private JScrollPane scrollPane = null; 076 077 private boolean scroll = true; 078 079 public MatrixTableEditorPanel(MatrixGUIObject m) { 080 this(); 081 setMatrix(m); 082 } 083 084 public MatrixTableEditorPanel() { 085 setBorder(BorderFactory.createTitledBorder("Matrix Editor")); 086 setLayout(new GridBagLayout()); 087 088 jTable = new JTable(); 089 jTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 090 jTable.getTableHeader().setReorderingAllowed(false); 091 jTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); 092 jTable.setColumnSelectionAllowed(true); 093 jTable.setDefaultRenderer(Object.class, new MatrixValueTableCellRenderer()); 094 jTable.setDefaultEditor(Object.class, new MatrixTableCellEditor()); 095 jTable.addMouseListener(this); 096 jTable.addKeyListener(this); 097 jTable.getSelectionModel().addListSelectionListener(this); 098 099 rowHeader = new JList(); 100 rowHeader.setOpaque(true); 101 rowHeader.setFixedCellHeight(jTable.getRowHeight()); 102 rowHeader.setCellRenderer(new RowHeaderRenderer(jTable)); 103 104 scrollPane = new JScrollPane(jTable); 105 106 this.addMouseListener(this); 107 108 this.add(jTable.getTableHeader(), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, 109 GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); 110 this.add(scrollPane, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.EAST, 111 GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); 112 } 113 114 public void tableChanged(TableModelEvent e) { 115 } 116 117 public void mouseClicked(MouseEvent e) { 118 if (e.getButton() == MouseEvent.BUTTON3) { 119 int row = jTable.rowAtPoint(e.getPoint()); 120 int col = jTable.columnAtPoint(e.getPoint()); 121 JPopupMenu popup = new MatrixPopupMenu(null, dataModel, row, col); 122 popup.show(jTable, e.getX(), e.getY()); 123 } 124 } 125 126 public void mouseEntered(MouseEvent e) { 127 } 128 129 public void mouseExited(MouseEvent e) { 130 } 131 132 public void mousePressed(MouseEvent e) { 133 scroll = false; 134 } 135 136 public void mouseReleased(MouseEvent e) { 137 scroll = true; 138 } 139 140 public void keyPressed(KeyEvent e) { 141 } 142 143 public void keyReleased(KeyEvent e) { 144 } 145 146 public void keyTyped(KeyEvent e) { 147 } 148 149 public void valueChanged(ListSelectionEvent e) { 150 if (scroll && e.getValueIsAdjusting() == false) { 151 int minRow = jTable.getSelectionModel().getMinSelectionIndex(); 152 int minCol = jTable.getColumnModel().getSelectionModel().getMinSelectionIndex(); 153 int maxRow = jTable.getSelectionModel().getMaxSelectionIndex(); 154 int maxCol = jTable.getColumnModel().getSelectionModel().getMaxSelectionIndex(); 155 if (minRow == maxRow && minCol == maxCol) { 156 JViewport viewport = (JViewport) jTable.getParent(); 157 Rectangle rect = jTable.getCellRect(minRow, minCol, true); 158 Rectangle viewRect = viewport.getViewRect(); 159 rect.setLocation(rect.x - viewRect.x, rect.y - viewRect.y); 160 int centerX = (viewRect.width - rect.width) / 2; 161 int centerY = (viewRect.height - rect.height) / 2; 162 if (rect.x < centerX) { 163 centerX = -centerX; 164 } 165 if (rect.y < centerY) { 166 centerY = -centerY; 167 } 168 rect.translate(centerX, centerY); 169 viewport.scrollRectToVisible(rect); 170 } 171 } 172 } 173 174 175 protected void finalize() throws Throwable { 176 super.finalize(); 177 if (dataModel != null) 178 dataModel.removeTableModelListener(this); 179 } 180 181 public void setMatrix(MatrixGUIObject m) { 182 if (dataModel != null) { 183 dataModel.removeTableModelListener(this); 184 dataModel.getRowSelectionModel().removeListSelectionListener(this); 185 dataModel.getColumnSelectionModel().removeListSelectionListener(this); 186 } 187 188 dataModel = m; 189 190 if (dataModel != null) { 191 jTable.setModel(dataModel); 192 jTable.setSelectionModel(dataModel.getRowSelectionModel()); 193 jTable.getColumnModel().setSelectionModel(dataModel.getColumnSelectionModel()); 194 dataModel.getRowSelectionModel().addListSelectionListener(this); 195 dataModel.getColumnSelectionModel().addListSelectionListener(this); 196 if (dataModel.getRowCount() <= 100000) { 197 AbstractListModel rowListModel = new RowListModel(dataModel); 198 rowHeader.setModel(rowListModel); 199 scrollPane.setRowHeaderView(rowHeader); 200 } else { 201 scrollPane.setRowHeaderView(null); 202 } 203 } else { 204 jTable.setModel(emptyModel); 205 scrollPane.setRowHeaderView(null); 206 } 207 } 208 209 } 210 211 class RowListModel extends AbstractListModel { 212 private static final long serialVersionUID = 508583105448562780L; 213 214 private MatrixGUIObject model = null; 215 216 public RowListModel(MatrixGUIObject m) { 217 this.model = m; 218 } 219 220 public Object getElementAt(int index) { 221 return model.getRowName(index); 222 } 223 224 public int getSize() { 225 return model.getRowCount(); 226 } 227 228 } 229 230 class RowHeaderRenderer extends JLabel implements ListCellRenderer { 231 private static final long serialVersionUID = -9181159352100487913L; 232 233 private final JTable table; 234 235 private final Border selectedBorder; 236 237 private final Border normalBorder; 238 239 private final Font selectedFont; 240 241 private final Font normalFont; 242 243 final JTableHeader header; 244 245 RowHeaderRenderer(JTable table) { 246 this.table = table; 247 normalBorder = UIManager.getBorder("TableHeader.cellBorder"); 248 selectedBorder = BorderFactory.createRaisedBevelBorder(); 249 header = table.getTableHeader(); 250 normalFont = header.getFont(); 251 // selectedFont = normalFont.deriveFont(normalFont.getStyle() | 252 // Font.BOLD); 253 selectedFont = normalFont; 254 setForeground(header.getForeground()); 255 setBackground(header.getBackground()); 256 setOpaque(true); 257 setHorizontalAlignment(RIGHT); 258 } 259 260 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, 261 boolean cellHasFocus) { 262 if (table.getSelectionModel().isSelectedIndex(index)) { 263 setFont(selectedFont); 264 // setBackground(Color.blue); 265 // setBorder(selectedBorder); 266 } else { 267 setFont(normalFont); 268 setBackground(header.getBackground()); 269 // setBorder(normalBorder); 270 } 271 String label = String.valueOf(value); 272 setText(label + " "); 273 return this; 274 } 275 }