001    /* JAPI - (Yet another (hopefully) useful) Java API
002     *
003     * Copyright (C) 2004-2006 Christian Hujer
004     *
005     * This program is free software; you can redistribute it and/or
006     * modify it under the terms of the GNU General Public License as
007     * published by the Free Software Foundation; either version 2 of the
008     * License, or (at your option) any later version.
009     *
010     * This program is distributed in the hope that it will be useful, but
011     * WITHOUT ANY WARRANTY; without even the implied warranty of
012     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013     * General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program; if not, write to the Free Software
017     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
018     * 02111-1307, USA.
019     */
020    
021    package net.sf.japi.swing.treetable;
022    
023    import java.awt.Component;
024    import java.awt.Dimension;
025    import java.awt.Graphics;
026    import javax.swing.AbstractCellEditor;
027    import javax.swing.JTable;
028    import javax.swing.JTree;
029    import javax.swing.table.TableCellEditor;
030    import javax.swing.table.TableCellRenderer;
031    import javax.swing.tree.DefaultTreeSelectionModel;
032    import javax.swing.tree.TreeModel;
033    
034    /** This example shows how to create a simple JTreeTable component,
035     * by using a JTree as a renderer (and editor) for the cells in a
036     * particular column in the JTable.
037     * @warning DO NOT RELY ON THE INHERITANCE!
038     */
039    public class JTreeTable<R, T> extends JTable {
040    
041        /** TreeTableCellRenderer. */
042        private TreeTableCellRenderer tree;
043    
044        /** The TreeTableModel for this JTreeTable. */
045        private TreeTableModel<R, T> treeTableModel;
046    
047        /** Create a JTreeTable. */
048        public JTreeTable(final TreeTableModel<R, T> treeTableModel) {
049            this.treeTableModel = treeTableModel;
050            tree = new TreeTableCellRenderer(new TreeTableModelTreeModelAdapter<R, T>(treeTableModel));
051            super.setModel(new TreeTableModelTableModelAdapter(treeTableModel, tree));
052    
053            // Force the JTable and JTree to share their row selection models.
054            tree.setSelectionModel(new DefaultTreeSelectionModel() {
055                {
056                    setSelectionModel(listSelectionModel);
057                }
058            });
059            // Make the tree and table row heights the same.
060            tree.setRowHeight(getRowHeight());
061    
062            // Install the tree editor renderer and editor.
063            setDefaultRenderer(TreeTableModel.class, tree);
064            setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
065    
066            setShowGrid(false);
067            setIntercellSpacing(new Dimension(0, 0));
068        }
069    
070        /** Returns the TreeTableModel for this JTreeTable.
071         * @return the TreeTableModel for this JTreeTable.
072         */
073        public TreeTableModel<R, T> getTreeTableModel() {
074            return treeTableModel;
075        }
076    
077        /* Workaround for BasicTableUI anomaly. Make sure the UI never tries to
078         * paint the editor. The UI currently uses different techniques to
079         * paint the renderers and editors and overriding setBounds() below
080         * is not the right thing to do for an editor. Returning -1 for the
081         * editing row in this case, ensures the editor is never painted.
082         */
083        @Override public int getEditingRow() {
084            return getColumnClass(editingColumn) == TreeTableModel.class ? -1 : editingRow;
085        }
086    
087        /** Sets the TreeTableModel for this JTreeTable.
088         * @param treeTableModel the TreeTableModel for this JTreeTable.
089         */
090        public void setTreeTableModel(final TreeTableModel<R, T> treeTableModel) {
091            this.treeTableModel = treeTableModel;
092            super.setModel(new TreeTableModelTableModelAdapter(treeTableModel, tree));
093        }
094    
095        /** Renderer for TreeTableCells. */
096        public class TreeTableCellRenderer extends JTree implements TableCellRenderer {
097    
098            private int visibleRow;
099    
100            public TreeTableCellRenderer(final TreeModel model) {
101                super(model);
102            }
103    
104            @Override public void setBounds(final int x, final int y, final int width, final int height) {
105                super.setBounds(x, 0, width, JTreeTable.this.getHeight());
106            }
107    
108            @Override public void paint(final Graphics g) {
109                g.translate(0, -visibleRow * getRowHeight());
110                super.paint(g);
111            }
112    
113            public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) {
114                if (isSelected) {
115                    setBackground(table.getSelectionBackground());
116                } else {
117                    setBackground(table.getBackground());
118                }
119    
120                visibleRow = row;
121                return this;
122            }
123    
124        } // class TreeTableCellRenderer
125    
126        /** Editor for TreeTableCells. */
127        public class TreeTableCellEditor extends AbstractCellEditor implements TableCellEditor {
128    
129            /** {@inheritDoc} */
130            public Component getTableCellEditorComponent(final JTable table, final Object value, final boolean isSelected, final int row, final int column) {
131                return tree;
132            }
133    
134            /** {@inheritDoc} */
135            public Object getCellEditorValue() {
136                return ""; //TODO
137            }
138    
139        } // class TreeTableCellEditor
140    
141    } // class JTreeTable