KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > swing > popupswitcher > SwitcherTable


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
20 package org.netbeans.swing.popupswitcher;
21
22 import java.awt.Color JavaDoc;
23 import java.awt.Component JavaDoc;
24 import java.awt.Dimension JavaDoc;
25 import java.awt.Font JavaDoc;
26 import java.awt.FontMetrics JavaDoc;
27 import java.awt.Graphics JavaDoc;
28 import java.awt.Graphics2D JavaDoc;
29 import java.awt.image.BufferedImage JavaDoc;
30 import java.lang.ref.SoftReference JavaDoc;
31 import javax.swing.BorderFactory JavaDoc;
32 import javax.swing.Icon JavaDoc;
33 import javax.swing.JTable JavaDoc;
34 import javax.swing.UIManager JavaDoc;
35 import javax.swing.border.Border JavaDoc;
36 import javax.swing.table.DefaultTableCellRenderer JavaDoc;
37 import javax.swing.table.TableCellRenderer JavaDoc;
38 import org.openide.util.Utilities;
39
40 /**
41  * This class is used as a content for PopupSwitcher classes (see below). It
42  * appropriately displays its contents (<code>SwitcherTableItem</code>s)
43  * according to screen size, given position, used font, number of items, etc.
44  * and inteligently consider number of rows and columns to be used.
45  *
46  * @see SwitcherTableItem
47  *
48  * @author mkrauskopf
49  */

50 public class SwitcherTable extends JTable JavaDoc {
51     
52     private static final Border JavaDoc rendererBorder =
53             BorderFactory.createEmptyBorder(2, 5, 0, 5);
54     
55     private Icon JavaDoc nullIcon = new NullIcon();
56     private Color JavaDoc foreground;
57     private Color JavaDoc background;
58     private Color JavaDoc selForeground;
59     private Color JavaDoc selBackground;
60     
61     /** Cached preferred size value */
62     private Dimension JavaDoc prefSize;
63     
64     /** Current NetBeans LookAndFreel id */
65     /**
66      * Flag indicating that the fixed row height has not yet been calculated -
67      * this is for fontsize support
68      */

69     private boolean needCalcRowHeight = true;
70     
71     /**
72      * Creates a new instance of SwitcherTable. Created table will be as high
73      * as possible. Height will be used during the number of row computing.
74      */

75     public SwitcherTable(SwitcherTableItem[] items) {
76         this(items, 0);
77     }
78     
79     /**
80      * Creates a new instance of SwitcherTable. Height of created table will be
81      * computed according to given y coordinate. Height will be used during the
82      * number of row computing.
83      */

84     public SwitcherTable(SwitcherTableItem[] items, int y) {
85         super();
86         init();
87         // get rid of the effect when popup seems to be higher that screen height
88
int gap = (y == 0 ? 10 : 5);
89         int height = Utilities.getUsableScreenBounds().height - y - gap;
90         setModel(new SwitcherTableModel(items, getRowHeight(), height));
91         getSelectionModel().clearSelection();
92         getSelectionModel().setAnchorSelectionIndex(-1);
93         getSelectionModel().setLeadSelectionIndex(-1);
94     }
95     
96     private void init() {
97         setBorder(BorderFactory.createLineBorder(getForeground()));
98         setShowHorizontalLines(false);
99         // Calc row height here so that TableModel can adjust number of columns.
100
calcRowHeight(getOffscreenGraphics());
101     }
102     
103     public void updateUI() {
104         needCalcRowHeight = true;
105         super.updateUI();
106     }
107     
108     public void setFont(Font JavaDoc f) {
109         needCalcRowHeight = true;
110         super.setFont(f);
111     }
112     
113     public Component JavaDoc prepareRenderer(
114             TableCellRenderer JavaDoc renderer,
115             int row,
116             int column) {
117         
118         SwitcherTableItem item
119                 = (SwitcherTableItem) getSwitcherTableModel().getValueAt(row, column);
120         
121         boolean selected = row == getSelectedRow() &&
122                 column == getSelectedColumn() && item != null;
123         
124         DefaultTableCellRenderer JavaDoc ren = (DefaultTableCellRenderer JavaDoc)
125         renderer.getTableCellRendererComponent(this, item,
126                 selected, selected, row, column);
127         
128         if (item == null) {
129             // it's a filler space, we're done
130
ren.setOpaque(false);
131             ren.setIcon(null);
132             return ren;
133         }
134         
135         Icon JavaDoc icon = item.getIcon();
136         if (icon == null ) {
137             icon = nullIcon;
138         }
139         ren.setText(selected || item.isActive() ? item.getName() : item.getHtmlName());
140         ren.setIcon(icon);
141         ren.setBorder(rendererBorder);
142         ren.setIconTextGap(26 - icon.getIconWidth());
143         
144         if (item.isActive()) {
145             // don't use deriveFont() - see #49973 for details
146
ren.setFont(new Font JavaDoc(getFont().getName(), Font.BOLD, getFont().getSize()));
147         }
148         
149         ren.setOpaque(true);
150         
151         return ren;
152     }
153     
154     private static class NullIcon implements Icon JavaDoc {
155         public int getIconWidth() { return 0; }
156         public int getIconHeight() { return 0; }
157         public void paintIcon(Component JavaDoc c, Graphics JavaDoc g, int x, int y) {}
158     }
159     
160     public Color JavaDoc getForeground() {
161         if (foreground == null) {
162             foreground = UIManager.getColor("ComboBox.foreground");
163         }
164         return foreground != null ? foreground : super.getForeground();
165     }
166     
167     public Color JavaDoc getBackground() {
168         if (background == null) {
169             background = UIManager.getColor("ComboBox.background");
170         }
171         return background != null ? background : super.getBackground();
172     }
173     
174     public Color JavaDoc getSelectionForeground() {
175         if (selForeground == null) {
176             selForeground = UIManager.getColor("ComboBox.selectionForeground");
177         }
178         return selForeground != null ? selForeground : super.getSelectionForeground();
179     }
180     
181     public Color JavaDoc getSelectionBackground() {
182         if (selBackground == null) {
183             selBackground = UIManager.getColor("ComboBox.selectionBackground");
184         }
185         return selBackground != null ? selBackground : super.getSelectionBackground();
186     }
187     
188     /**
189      * Calculate the height of rows based on the current font. This is done
190      * when the first paint occurs, to ensure that a valid Graphics object is
191      * available.
192      *
193      * @since 1.25
194      */

195     private void calcRowHeight(Graphics JavaDoc g) {
196         Font JavaDoc f = getFont();
197         FontMetrics JavaDoc fm = g.getFontMetrics(f);
198         // As icons are displayed use maximum from font and icon height
199
int rowHeight = Math.max(fm.getHeight(), 16) + 4;
200         needCalcRowHeight = false;
201         setRowHeight(rowHeight);
202     }
203     
204     private static SoftReference JavaDoc<BufferedImage JavaDoc> ctx = null;
205     
206     /**
207      * Provides an offscreen graphics context so that widths based on character
208      * size can be calculated correctly before the component is shown
209      */

210     private static Graphics2D JavaDoc getOffscreenGraphics() {
211         BufferedImage JavaDoc result = null;
212         // XXX multi-monitors w/ different resolution may have problems; Better
213
// to call Toolkit to create a screen graphics
214
if (ctx != null) {
215             result = ctx.get();
216         }
217         if (result == null) {
218             result = new BufferedImage JavaDoc(10, 10, BufferedImage.TYPE_INT_RGB);
219             ctx = new SoftReference JavaDoc<BufferedImage JavaDoc>(result);
220         }
221         return (Graphics2D JavaDoc) result.getGraphics();
222     }
223     
224     /**
225      * Overridden to calculate a preferred size based on the current optimal
226      * number of columns, and set up the preferred width for each column based
227      * on the maximum width item & icon displayed in it
228      */

229     public Dimension JavaDoc getPreferredSize() {
230         if (prefSize == null) {
231             int cols = getColumnCount();
232             int rows = getRowCount();
233             
234             // Iterate all rows and find the widest cell of a whole table
235
int columnWidth = 0;
236             for (int i = 0; i < cols; i++) {
237                 for (int j = 0; j < rows; j++) {
238                     TableCellRenderer JavaDoc ren = getCellRenderer(j,i);
239                     Component JavaDoc c = prepareRenderer(ren, j, i);
240                     // sometime adding of one pixel is needed to prevent "..." truncating
241
columnWidth = Math.max(
242                             c.getPreferredSize().width + 1, columnWidth);
243                 }
244             }
245             columnWidth = Math.min(columnWidth, 250);
246             // Set the same (maximum) widht to all columns
247
for (int i = 0; i < cols; i++) {
248                 getColumnModel().getColumn(i).setPreferredWidth(columnWidth);
249             }
250             // Rows will be fixed height, so just multiply it out
251
prefSize = new Dimension JavaDoc(columnWidth * cols, rows * getRowHeight());
252         }
253         return prefSize;
254     }
255     
256     private SwitcherTableModel getSwitcherTableModel() {
257         return (SwitcherTableModel) getModel();
258     }
259     
260     public SwitcherTableItem getSelectedItem() {
261         return (SwitcherTableItem) getValueAt(getSelectedRow(), getSelectedColumn());
262     }
263     
264     public void paint(Graphics JavaDoc g) {
265         if (needCalcRowHeight) {
266             calcRowHeight(g);
267         }
268         super.paint(g);
269     }
270     
271     /**
272      * Returns the last valid row in the last collumn.
273      *
274      * @return index of last non-null value in the last collumn or -1 when all
275      * values are null.
276      */

277     public int getLastValidRow() {
278         int lastColIdx = getColumnCount() - 1;
279         for (int i = getRowCount() - 1; i >= 0; i--) {
280             if (getValueAt(i, lastColIdx) != null) {
281                 return i;
282             }
283         }
284         return -1;
285     }
286 }
287
Popular Tags