//============================================================================== // // Copyright (c) 2002- // Authors: // * Mark Kattenbelt (University of Oxford, formerly University of Birmingham) // //------------------------------------------------------------------------------ // // This file is part of PRISM. // // PRISM is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // PRISM is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with PRISM; if not, write to the Free Software Foundation, // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //============================================================================== package userinterface.util; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; /** * An object to represent a grouped TableHeader. It extends JTableHeader, but actually consists of two separate * JTableHeaders. Some of this could be tidied up, but it is build more or less to Swings concepts. */ @SuppressWarnings("serial") public class GUIGroupedTableHeader extends JTableHeader implements TableColumnModelListener, MouseListener { private JTableHeader bottomHeader; private JTableHeader topHeader; private GUIGroupedTableModel tableModel; /** * Creates a new GUIGroupedTableHeader. * @param model The column model that is the basis of this table header (must be grouped). */ public GUIGroupedTableHeader(GUIGroupedTableColumnModel model, GUIGroupedTableModel tableModel, GUIGroupedTable table) { super(); removeAll(); this.tableModel = tableModel; topHeader = new JTableHeader(model.getGroupTableColumnModel()); topHeader.setResizingAllowed(false); topHeader.setReorderingAllowed(false); final TableCellRenderer renderer = topHeader.getDefaultRenderer(); topHeader.setDefaultRenderer(new TableCellRenderer() { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component component = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); component.setFont(topHeader.getFont().deriveFont(Font.BOLD)); return component; } }); bottomHeader = new JTableHeader(model); bottomHeader.setReorderingAllowed(false); topHeader.setTable(table); bottomHeader.setTable(table); setLayout(new GridLayout(2,1)); add(topHeader); add(bottomHeader); model.updateGroups(); this.setPreferredSize(new Dimension(bottomHeader.getPreferredSize().width, bottomHeader.getPreferredSize().height * 2)); this.setMinimumSize(new Dimension(bottomHeader.getMinimumSize().width, bottomHeader.getMinimumSize().height * 2)); this.setMaximumSize(new Dimension(bottomHeader.getMaximumSize().width, bottomHeader.getMaximumSize().height * 2)); Component[] cs = this.getComponents(); for (int i = 0; i < cs.length; i++) { cs[i].addMouseListener(this); } topHeader.addMouseMotionListener(new MouseMotionAdapter() { private TableColumn lastColumn; public void mouseMoved(MouseEvent e) { bottomHeader.setToolTipText(null); TableColumn currentColumn; int column = topHeader.getColumnModel().getColumnIndexAtX(e.getX()); if (column >= 0) { currentColumn = topHeader.getColumnModel().getColumn(column); if (currentColumn != lastColumn) { topHeader.setToolTipText((GUIGroupedTableHeader.this).tableModel.getGroupToolTip(column)); lastColumn = currentColumn; } } } }); bottomHeader.addMouseMotionListener(new MouseMotionAdapter() { private TableColumn lastColumn; public void mouseMoved(MouseEvent e) { topHeader.setToolTipText(null); TableColumn currentColumn; int column = bottomHeader.getColumnModel().getColumnIndexAtX(e.getX()); if (column >= 0) { currentColumn = bottomHeader.getColumnModel().getColumn(column); if (currentColumn != lastColumn) { bottomHeader.setToolTipText((GUIGroupedTableHeader.this).tableModel.getColumnToolTip(column)); lastColumn = currentColumn; } } } }); //topHeader.setToolTipText(null); //bottomHeader.setToolTipText(null); } /** * A fairly ugly hack to prevent a CellRenderer to be added to this container. More elegant solutions are welcome. * @see java.awt.Container#addImpl(java.awt.Component, java.lang.Object, int) */ @Override protected void addImpl(Component comp, Object constraints, int index) { // TODO Auto-generated method stub if (this.getComponents().length < 2) { super.addImpl(comp, constraints, index); } } /** * Overwritten to never allow reordering. * @see javax.swing.table.JTableHeader#setReorderingAllowed(boolean) */ @Override public void setReorderingAllowed(boolean reorderingAllowed) { super.setReorderingAllowed(false); } /** * Overwritten to always return the resizing column of the bottom JTableHeader. * @see javax.swing.table.JTableHeader#getResizingColumn() */ @Override public TableColumn getResizingColumn() { return bottomHeader.getResizingColumn(); } /** * Overwritten to give the JTableHeaders a change to resize as well. * @see javax.swing.table.JTableHeader#resizeAndRepaint() */ @Override public void resizeAndRepaint() { if (topHeader != null && bottomHeader != null) { this.setPreferredSize(new Dimension(bottomHeader.getPreferredSize().width, bottomHeader.getPreferredSize().height * 2)); this.setMinimumSize(new Dimension(bottomHeader.getMinimumSize().width, bottomHeader.getMinimumSize().height * 2)); this.setMaximumSize(new Dimension(bottomHeader.getMaximumSize().width, bottomHeader.getMaximumSize().height * 2)); this.doLayout(); } super.resizeAndRepaint(); } /** * Set the column model. * @param columnModel The grouped column model to use. */ public void setColumnModel(GUIGroupedTableColumnModel columnModel) { topHeader.setColumnModel(columnModel.getGroupTableColumnModel()); bottomHeader.setColumnModel(columnModel); this.resizeAndRepaint(); columnModel.updateGroups(); super.setColumnModel(columnModel); } /** * Overwritten to catch events of child components. */ public void mouseClicked(MouseEvent e) { this.dispatchEvent(new MouseEvent(this, e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY() + ((Component)e.getSource()).getBounds().y, e.getClickCount(), e.isPopupTrigger())); } /** * Overwritten to catch events of child components. */ public void mouseEntered(MouseEvent e) { this.dispatchEvent(new MouseEvent(this, e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY() + ((Component)e.getSource()).getBounds().y, e.getClickCount(), e.isPopupTrigger())); } /** * Overwritten to catch events of child components. */ public void mouseExited(MouseEvent e) { this.dispatchEvent(new MouseEvent(this, e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY() + ((Component)e.getSource()).getBounds().y, e.getClickCount(), e.isPopupTrigger())); } /** * Overwritten to catch events of child components. */ public void mousePressed(MouseEvent e) { this.dispatchEvent(new MouseEvent(this, e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY() + ((Component)e.getSource()).getBounds().y, e.getClickCount(), e.isPopupTrigger())); } /** * Overwritten to catch events of child components. */ public void mouseReleased(MouseEvent e) { this.dispatchEvent(new MouseEvent(this, e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY() + ((Component)e.getSource()).getBounds().y, e.getClickCount(), e.isPopupTrigger())); } }