View Javadoc

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