1 /*
2 * %W% %E%
3 *
4 * Copyright 1997, 1998 Sun Microsystems, Inc. All Rights Reserved.
5 *
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
8 * conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * - Redistribution in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials
16 * provided with the distribution.
17 *
18 * Neither the name of Sun Microsystems, Inc. or the names of
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * This software is provided "AS IS," without a warranty of any
23 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
24 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
26 * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
27 * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR
28 * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE OR
29 * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
30 * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
31 * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
32 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
33 * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS
34 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
35 *
36 * You acknowledge that this software is not designed, licensed or
37 * intended for use in the design, construction, operation or
38 * maintenance of any nuclear facility.
39 */
40
41 package uk.ac.rdg.resc.jstyx.client.browser;
42
43 import javax.swing.*;
44 import javax.swing.tree.*;
45 import javax.swing.table.*;
46
47 import java.awt.Dimension;
48 import java.awt.Component;
49 import java.awt.Graphics;
50 import java.awt.event.MouseListener;
51 import java.awt.event.MouseAdapter;
52 import java.awt.event.MouseEvent;
53
54 import uk.ac.rdg.resc.jstyx.client.CStyxFile;
55
56 /***
57 * This example shows how to create a simple JTreeTable component,
58 * by using a JTree as a renderer (and editor) for the cells in a
59 * particular column in the JTable.
60 *
61 * @version %I% %G%
62 *
63 * @author Philip Milne
64 * @author Scott Violet
65 */
66
67 public class JTreeTable extends JTable
68 {
69 protected TreeTableCellRenderer tree;
70 private StyxBrowserPopupMenu popup;
71
72 public JTreeTable(TreeTableModel treeTableModel)
73 {
74 super();
75
76 // Create the tree. It will be used as a renderer and editor.
77 tree = new TreeTableCellRenderer(treeTableModel);
78
79 // Install a tableModel representing the visible rows in the tree.
80 super.setModel(new TreeTableModelAdapter(treeTableModel, tree));
81
82 // Force the JTable and JTree to share their row selection models.
83 tree.setSelectionModel(new DefaultTreeSelectionModel()
84 {
85 // Extend the implementation of the constructor, as if:
86 /* public this() */ {
87 setSelectionModel(listSelectionModel);
88 }
89 });
90 // Make the tree and table row heights the same.
91 tree.setRowHeight(getRowHeight());
92
93 // Install the tree editor renderer and editor.
94 setDefaultRenderer(TreeTableModel.class, tree);
95 setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
96
97 setShowGrid(false);
98 setIntercellSpacing(new Dimension(0, 0));
99
100 this.popup = new StyxBrowserPopupMenu();
101 this.addMouseListener(ml);
102 }
103
104 /* Workaround for BasicTableUI anomaly. Make sure the UI never tries to
105 * paint the editor. The UI currently uses different techniques to
106 * paint the renderers and editors and overriding setBounds() below
107 * is not the right thing to do for an editor. Returning -1 for the
108 * editing row in this case, ensures the editor is never painted.
109 */
110 public int getEditingRow()
111 {
112 return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 : editingRow;
113 }
114
115 //
116 // The renderer used to display the tree nodes, a JTree.
117 //
118
119 public class TreeTableCellRenderer extends JTree implements TableCellRenderer
120 {
121
122 protected int visibleRow;
123
124 public TreeTableCellRenderer(TreeModel model)
125 {
126 super(model);
127 }
128
129 public void setBounds(int x, int y, int w, int h)
130 {
131 super.setBounds(x, 0, w, JTreeTable.this.getHeight());
132 }
133
134 public void paint(Graphics g)
135 {
136 g.translate(0, -visibleRow * getRowHeight());
137 super.paint(g);
138 }
139
140 public Component getTableCellRendererComponent(JTable table, Object value,
141 boolean isSelected, boolean hasFocus, int row, int column)
142 {
143 if(isSelected)
144 setBackground(table.getSelectionBackground());
145 else
146 setBackground(table.getBackground());
147
148 visibleRow = row;
149 return this;
150 }
151
152 }
153
154 //
155 // The editor used to interact with tree nodes, a JTree.
156 //
157
158 public class TreeTableCellEditor extends AbstractCellEditor implements TableCellEditor
159 {
160 public Component getTableCellEditorComponent(JTable table, Object value,
161 boolean isSelected, int r, int c)
162 {
163 return tree;
164 }
165 }
166
167 // Listens for double-clicks and requests for the pop-up menu.
168 // Note that for platform independence we must check for the popup trigger
169 // in both mousePressed and mouseReleased
170 private MouseListener ml = new MouseAdapter()
171 {
172 public void mousePressed(MouseEvent e)
173 {
174 int selRow = tree.getRowForLocation(e.getX(), e.getY());
175 TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
176 maybeShowPopup(e);
177 if (selRow != -1)
178 {
179 // TODO: should we check for double clicks in mousePressed,
180 // mouseReleased or mouseClicked?
181 if (e.getClickCount() == 2)
182 {
183 // Open default menu option
184 //System.out.println("Double-clicked on " + selRow + ", " + selPath);
185 }
186 }
187 }
188 public void mouseReleased(MouseEvent e)
189 {
190 maybeShowPopup(e);
191 }
192 private void maybeShowPopup(MouseEvent e)
193 {
194 if (e.isPopupTrigger())
195 {
196 TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
197 // If we don't click on something in the tree itself, selPath
198 // will be null
199 if (selPath != null)
200 {
201 // Get the CStyxFile that we have clicked on
202 Object obj = selPath.getLastPathComponent();
203 if (obj instanceof FileNode)
204 {
205 FileNode node = (FileNode)obj;
206 // Show the context menu for this node
207 // TODO: enable this when the popup menu is ready + debugged
208 //popup.showContext(node, e.getComponent(), e.getX(), e.getY());
209 }
210 }
211 }
212 }
213 };
214
215 }
216