KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > explorer > view > TableSheet


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.openide.explorer.view;
20
21 import org.openide.explorer.propertysheet.*;
22 import org.openide.nodes.Node;
23 import org.openide.nodes.Node.Property;
24
25 import java.awt.*;
26 import java.awt.event.MouseEvent JavaDoc;
27
28 import java.beans.*;
29
30 import javax.swing.*;
31 import javax.swing.border.*;
32 import javax.swing.event.*;
33
34
35 /** Table view of node properties. Table header displays property display names and each cell
36 * contains (<code>PropertyPanel</code>) for displaying/editting of properties. Each property
37 * row belongs to one node.
38 *
39 * @author Jan Rojcek
40 */

41 class TableSheet extends JScrollPane {
42     /** table */
43     transient protected JTable table;
44
45     /** model */
46     transient private NodeTableModel tableModel;
47
48     /** Create table view with default table model.
49      */

50     public TableSheet() {
51         tableModel = new NodeTableModel();
52         initializeView();
53     }
54
55     /** Create table view with users table model.
56      */

57     public TableSheet(NodeTableModel tableModel) {
58         this.tableModel = tableModel;
59         initializeView();
60     }
61
62     private void initializeView() {
63         table = createTable();
64         initializeTable();
65
66         setViewportView(table);
67
68         // do not care about focus
69
setRequestFocusEnabled(false);
70
71         table.getAccessibleContext().setAccessibleName(
72             org.openide.util.NbBundle.getBundle(TableSheet.class).getString("ACS_TableSheet")
73         );
74         table.getAccessibleContext().setAccessibleDescription(
75             org.openide.util.NbBundle.getBundle(TableSheet.class).getString("ACSD_TableSheet")
76         );
77     }
78
79     /** Set rows.
80      * @param props rows
81      */

82     public void setNodes(Node[] nodes) {
83         tableModel.setNodes(nodes);
84     }
85
86     /** Set columns.
87      * @param nodes columns
88      */

89     public void setProperties(Property[] props) {
90         tableModel.setProperties(props);
91     }
92
93     /** Sets resize mode of table.
94      *
95      * @param mode - One of 5 legal values: <pre>JTable.AUTO_RESIZE_OFF,
96      * JTable.AUTO_RESIZE_NEXT_COLUMN,
97      * JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS,
98      * JTable.AUTO_RESIZE_LAST_COLUMN,
99      * JTable.AUTO_RESIZE_ALL_COLUMNS</pre>
100      */

101     public final void setAutoResizeMode(int mode) {
102         table.setAutoResizeMode(mode);
103     }
104
105     /** Sets resize mode of table.
106      *
107      * @param mode - One of 5 legal values: <pre>JTable.AUTO_RESIZE_OFF,
108      * JTable.AUTO_RESIZE_NEXT_COLUMN,
109      * JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS,
110      * JTable.AUTO_RESIZE_LAST_COLUMN,
111      * JTable.AUTO_RESIZE_ALL_COLUMNS</pre>
112      */

113     public final int getAutoResizeMode() {
114         return table.getAutoResizeMode();
115     }
116
117     /** Sets preferred width of table column
118      * @param index column index
119      * @param width preferred column width
120      */

121     public final void setColumnPreferredWidth(int index, int width) {
122         table.getColumnModel().getColumn(index).setPreferredWidth(width);
123
124         table.setPreferredScrollableViewportSize(table.getPreferredSize());
125     }
126
127     /** Gets preferred width of table column
128      * @param index column index
129      * @param width preferred column width
130      */

131     public final int getColumnPreferredWidth(int index) {
132         return table.getColumnModel().getColumn(index).getPreferredWidth();
133     }
134
135     /** Allows to subclasses provide its own table.
136      * @param tm node table model
137      * @return table which will be placed into scroll pane
138      */

139     JTable createTable() {
140         return new JTable();
141     }
142
143     /** Allows to subclasses initialize table
144      * @param t
145      */

146     private void initializeTable() {
147         table.setModel(tableModel);
148
149         TableSheetCell tableCell = new TableSheetCell(tableModel);
150         table.setDefaultRenderer(Node.Property.class, tableCell);
151         table.setDefaultEditor(Node.Property.class, tableCell);
152         table.getTableHeader().setDefaultRenderer(tableCell);
153
154         table.setShowGrid(false);
155         table.setIntercellSpacing(new Dimension(0, 0));
156
157         table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
158         table.getTableHeader().setReorderingAllowed(false);
159
160         if (UIManager.getColor("Panel.background") != null) { // NOI18N
161
table.setBackground(UIManager.getColor("Panel.background")); // NOI18N
162
table.setSelectionBackground(UIManager.getColor("Panel.background")); // NOI18N
163
}
164     }
165
166     private static String JavaDoc getString(String JavaDoc key) {
167         return org.openide.util.NbBundle.getBundle(TableSheet.class).getString(key);
168     }
169
170     /** Synchronized table view with other view (TreeView, ListView). Two views (scroll panes)
171      * have only one vertical scroll bar. Right view is allways table view, left view could be any
172      * scroll pane. Use ControlledTableView.compoundScrollPane() to get compound view.
173      */

174     static class ControlledTableView extends TableSheet {
175         /** Scroll pane which controls vertical scroll bar */
176         JScrollPane controllingView;
177
178         /** Table like header of controlling view */
179         Component header;
180
181         /** Compound scroll pane used in MouseDragHandler */
182         JPanel compoundScrollPane;
183
184         /** Creates controlled scroll pane with <code>contView</code> on the left, table view
185          * on the right
186          */

187         ControlledTableView(JScrollPane contrView) {
188             super();
189             this.controllingView = contrView;
190             initializeView();
191         }
192
193         /** Creates controlled scroll pane with <code>contView</code> on the left, table view
194          * on the right.
195          */

196         ControlledTableView(JScrollPane contrView, NodeTableModel ntm) {
197             super(ntm);
198             this.controllingView = contrView;
199             initializeView();
200         }
201
202         /** Validate root is outer scroll pane. */
203         public boolean isValidateRoot() {
204             return false;
205         }
206
207         /** initialize view
208          */

209         private void initializeView() {
210             // adjustment of controlling view
211
Component comp = controllingView.getViewport().getView();
212             controllingView.setViewportView(comp);
213
214             if (UIManager.getColor("Table.background") != null) { // NOI18N
215
getViewport().setBackground(UIManager.getColor("Table.background")); // NOI18N
216
}
217
218             // both views share one vertical scrollbar
219
setVerticalScrollBar(controllingView.getVerticalScrollBar());
220
221             ScrollPaneLayout spl = new EnablingScrollPaneLayout(controllingView);
222             setLayout(spl);
223             spl.syncWithScrollPane(this);
224
225             spl = new EnablingScrollPaneLayout(this);
226             controllingView.setLayout(spl);
227             spl.syncWithScrollPane(controllingView);
228
229             table.setBorder(null);
230
231             // table like header
232
header = new JTable().getTableHeader().getDefaultRenderer().getTableCellRendererComponent(
233                     null, " ", false, false, 0, 0
234                 ); // NOI18N
235

236             MouseInputListener mouseHandler = new MouseDragHandler();
237             header.addMouseListener(mouseHandler);
238             header.addMouseMotionListener(mouseHandler);
239         }
240
241         /** Overriden to return table with controlled height
242          * @param tm table model
243          * @return table
244          */

245         JTable createTable() {
246             return new ATable();
247         }
248
249         JTable getTable() {
250             return table;
251         }
252
253         /** Overriden because I can't set border to null by calling setBorder(null).
254          * @param border
255          */

256         public void setBorder(Border border) {
257             super.setBorder(null);
258         }
259
260         /** Is used to synchronize table row height with left view.
261          */

262         void setRowHeight(int h) {
263             table.setRowHeight(h);
264             getVerticalScrollBar().setUnitIncrement(h);
265         }
266
267         /** Sets text of table like header above left scroll pane.
268          */

269         void setHeaderText(String JavaDoc text) {
270             if (header instanceof JLabel) {
271                 ((JLabel) header).setText(text);
272             }
273         }
274
275         /** Sets preferred size of left scroll pane.
276          */

277         void setControllingViewWidth(int width) {
278             controllingView.setPreferredSize(new Dimension(width, 0));
279         }
280
281         /** Gets preferred size of left scroll pane.
282          */

283         int getControllingViewWidth() {
284             return controllingView.getPreferredSize().width;
285         }
286
287         /*
288                 public void setPreferredSize(Dimension prefSize) {
289                     table.setPreferredScrollableViewportSize(prefSize);
290                 }
291         */

292
293         /** Returns component which contains two synchronized scroll panes. Above left one is
294          * placed table like header.
295          */

296         JComponent compoundScrollPane() {
297             JPanel leftPanel = new JPanel(new BorderLayout());
298             leftPanel.add(header, BorderLayout.NORTH);
299             leftPanel.add(controllingView, BorderLayout.CENTER);
300
301             compoundScrollPane = new CompoundScrollPane();
302             compoundScrollPane.setLayout(new BorderLayout());
303             compoundScrollPane.add(leftPanel, BorderLayout.CENTER);
304             compoundScrollPane.add(this, BorderLayout.EAST);
305
306             return compoundScrollPane;
307         }
308
309         private class ATable extends JTable {
310             private boolean trytorevalidate = true;
311
312             public ATable() {
313                 // fix for JTable bug - JTable consumes Esc key which is wrong
314
// after JDK bug 4624483 is fixed this workaround can
315
// be removed
316
getActionMap().put("cancel", new OurCancelEditingAction()); // NOI18N
317
}
318
319             public Dimension getPreferredScrollableViewportSize() {
320                 Dimension pref = super.getPreferredScrollableViewportSize();
321
322                 if ((this.getAutoResizeMode() != JTable.AUTO_RESIZE_OFF) && (getParent() != null)) {
323                     Insets insets = getParent().getInsets();
324                     Dimension size = getParent().getSize();
325                     pref.height = size.height - insets.top - insets.bottom;
326                 }
327
328                 return pref;
329             }
330
331             /** Try to revalidate once again because we want table to have
332              * width that it asked for.
333              */

334             public void setBounds(int x, int y, int width, int height) {
335                 super.setBounds(x, y, width, height);
336
337                 if (this.getAutoResizeMode() == JTable.AUTO_RESIZE_OFF) {
338                     return;
339                 }
340
341                 if (trytorevalidate && (width != getPreferredScrollableViewportSize().width)) {
342                     trytorevalidate = false;
343                     compoundScrollPane.validate();
344                     trytorevalidate = true;
345                 }
346             }
347
348             private class OurCancelEditingAction extends AbstractAction {
349                 OurCancelEditingAction() {
350                 }
351
352                 public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
353                     JTable table = (JTable) e.getSource();
354                     table.removeEditor();
355                 }
356
357                 public boolean isEnabled() {
358                     return ATable.this.isEditing();
359                 }
360             }
361         }
362
363         private class MouseDragHandler extends MouseInputAdapter {
364             boolean dragging = false;
365             int lastMouseX;
366
367             MouseDragHandler() {
368             }
369
370             public void mousePressed(MouseEvent JavaDoc e) {
371                 Point p = e.getPoint();
372                 dragging = canResize(p);
373                 lastMouseX = p.x;
374             }
375
376             private void setCursor(Cursor c) {
377                 if (header.getCursor() != c) {
378                     header.setCursor(c);
379                 }
380             }
381
382             private boolean canResize(Point mousePoint) {
383                 return mousePoint.x >= (header.getSize().width - 3);
384             }
385
386             public void mouseMoved(MouseEvent JavaDoc e) {
387                 if (canResize(e.getPoint()) || dragging) {
388                     setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
389                 } else {
390                     setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
391                 }
392             }
393
394             public void mouseDragged(MouseEvent JavaDoc e) {
395                 int mouseX = e.getX();
396                 int deltaX = lastMouseX - mouseX;
397
398                 if (deltaX == 0) {
399                     return;
400                 }
401
402                 if (dragging) {
403                     Dimension size = table.getPreferredScrollableViewportSize();
404                     int parentWidth = compoundScrollPane.getWidth();
405                     int tableMinWidth = table.getMinimumSize().width;
406
407                     int newWidth;
408
409                     if ((size.width + deltaX) > (parentWidth - 20)) {
410                         newWidth = parentWidth - 20;
411                     } else if ((size.width + deltaX) < tableMinWidth) {
412                         newWidth = tableMinWidth;
413                     } else {
414                         newWidth = size.width + deltaX;
415                     }
416
417                     table.setPreferredScrollableViewportSize(new Dimension(newWidth, size.height));
418                     lastMouseX = lastMouseX - (newWidth - size.width);
419
420                     table.revalidate();
421                     table.repaint();
422                 } else {
423                     lastMouseX = mouseX;
424                 }
425             }
426
427             public void mouseReleased(MouseEvent JavaDoc e) {
428                 dragging = false;
429             }
430         }
431     }
432
433     /** Scrollable (better say not scrollable) pane. Used as container for
434      * left (controlling) and rigth (controlled) scroll panes.
435      */

436     private static class CompoundScrollPane extends JPanel implements Scrollable {
437         CompoundScrollPane() {
438         }
439
440         public boolean getScrollableTracksViewportWidth() {
441             return true;
442         }
443
444         public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
445             return 10;
446         }
447
448         public boolean getScrollableTracksViewportHeight() {
449             return true;
450         }
451
452         public Dimension getPreferredScrollableViewportSize() {
453             return getPreferredSize();
454         }
455
456         public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
457             return 10;
458         }
459     }
460
461     /** Makes visible horizontal scroll bar of dependent scrollpane. Enables/disables
462      * horizontal scrollbar of parent scrollpane.
463      */

464     private static final class EnablingScrollPaneLayout extends ScrollPaneLayout {
465         JScrollPane dependentScrollPane;
466
467         public EnablingScrollPaneLayout(JScrollPane scrollPane) {
468             dependentScrollPane = scrollPane;
469         }
470
471         public void layoutContainer(Container parent) {
472             super.layoutContainer(parent);
473
474             Component view = (viewport != null) ? viewport.getView() : null;
475             Dimension viewPrefSize = (view != null) ? view.getPreferredSize() : new Dimension(0, 0);
476             Dimension extentSize = (viewport != null) ? viewport.toViewCoordinates(viewport.getSize())
477                                                       : new Dimension(0, 0);
478
479             boolean viewTracksViewportWidth = (view instanceof Scrollable) &&
480                 ((Scrollable) view).getScrollableTracksViewportWidth();
481             boolean hsbNeeded = !viewTracksViewportWidth && (viewPrefSize.width > extentSize.width);
482
483             // enable horizontal scrollbar only if it is needed
484
if (hsb != null) {
485                 hsb.setEnabled(hsbNeeded);
486             }
487
488             // make dependent horizontal scrollbar visible by setting scrollbar policy
489
JScrollPane scrollPane = (JScrollPane) parent;
490
491             if (scrollPane.getHorizontalScrollBarPolicy() != JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS) {
492                 int newPolicy = hsbNeeded ? JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS
493                                           : JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
494
495                 if (newPolicy != dependentScrollPane.getHorizontalScrollBarPolicy()) {
496                     dependentScrollPane.setHorizontalScrollBarPolicy(newPolicy);
497                     dependentScrollPane.getViewport().invalidate();
498                 }
499             }
500         }
501     }
502 }
503
Popular Tags