001: /* ========================================================================
002: * JCommon : a free general purpose class library for the Java(tm) platform
003: * ========================================================================
004: *
005: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jcommon/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * -----------------------
028: * SortButtonRenderer.java
029: * -----------------------
030: * (C) Copyright 2000-2004, by Nobuo Tamemasa and Contributors.
031: *
032: * Original Author: Nobuo Tamemasa;
033: * Contributor(s): David Gilbert (for Object Refinery Limited);
034: * Gareth Davis;
035: *
036: * $Id: SortButtonRenderer.java,v 1.6 2005/11/16 15:58:41 taqua Exp $
037: *
038: * Changes (from 26-Oct-2001)
039: * --------------------------
040: * 26-Oct-2001 : Changed package to com.jrefinery.ui.* (DG);
041: * 26-Jun-2002 : Removed unnecessary import (DG);
042: * 14-Oct-2002 : Fixed errors reported by Checkstyle (DG);
043: *
044: */
045:
046: package org.jfree.ui;
047:
048: import java.awt.Component;
049: import java.awt.Insets;
050: import javax.swing.JButton;
051: import javax.swing.JComponent;
052: import javax.swing.JLabel;
053: import javax.swing.JTable;
054: import javax.swing.SwingConstants;
055: import javax.swing.UIManager;
056: import javax.swing.border.Border;
057: import javax.swing.table.JTableHeader;
058: import javax.swing.table.TableCellRenderer;
059:
060: /**
061: * A table cell renderer for table headings - uses one of three JButton instances to indicate the
062: * sort order for the table column.
063: * <P>
064: * This class (and also BevelArrowIcon) is adapted from original code by Nobuo Tamemasa (version
065: * 1.0, 26-Feb-1999) posted on www.codeguru.com.
066: *
067: * @author David Gilbert
068: */
069: public class SortButtonRenderer implements TableCellRenderer {
070:
071: /**
072: * Useful constant indicating NO sorting.
073: */
074: public static final int NONE = 0;
075:
076: /**
077: * Useful constant indicating ASCENDING (that is, arrow pointing down) sorting in the table.
078: */
079: public static final int DOWN = 1;
080:
081: /**
082: * Useful constant indicating DESCENDING (that is, arrow pointing up) sorting in the table.
083: */
084: public static final int UP = 2;
085:
086: /**
087: * The current pressed column (-1 for no column).
088: */
089: private int pressedColumn = -1;
090:
091: /**
092: * The three buttons that are used to render the table header cells.
093: */
094: private JButton normalButton;
095:
096: /**
097: * The three buttons that are used to render the table header cells.
098: */
099: private JButton ascendingButton;
100:
101: /**
102: * The three buttons that are used to render the table header cells.
103: */
104: private JButton descendingButton;
105:
106: /**
107: * Used to allow the class to work out whether to use the buttuns
108: * or labels. Labels are required when using the aqua look and feel cos the
109: * buttons won't fit.
110: */
111: private boolean useLabels;
112:
113: /**
114: * The normal label (only used with MacOSX).
115: */
116: private JLabel normalLabel;
117:
118: /**
119: * The ascending label (only used with MacOSX).
120: */
121: private JLabel ascendingLabel;
122:
123: /**
124: * The descending label (only used with MacOSX).
125: */
126: private JLabel descendingLabel;
127:
128: /**
129: * Creates a new button renderer.
130: */
131: public SortButtonRenderer() {
132:
133: this .pressedColumn = -1;
134: this .useLabels = UIManager.getLookAndFeel().getID().equals(
135: "Aqua");
136:
137: final Border border = UIManager
138: .getBorder("TableHeader.cellBorder");
139:
140: if (this .useLabels) {
141: this .normalLabel = new JLabel();
142: this .normalLabel
143: .setHorizontalAlignment(SwingConstants.LEADING);
144:
145: this .ascendingLabel = new JLabel();
146: this .ascendingLabel
147: .setHorizontalAlignment(SwingConstants.LEADING);
148: this .ascendingLabel
149: .setHorizontalTextPosition(SwingConstants.LEFT);
150: this .ascendingLabel.setIcon(new BevelArrowIcon(
151: BevelArrowIcon.DOWN, false, false));
152:
153: this .descendingLabel = new JLabel();
154: this .descendingLabel
155: .setHorizontalAlignment(SwingConstants.LEADING);
156: this .descendingLabel
157: .setHorizontalTextPosition(SwingConstants.LEFT);
158: this .descendingLabel.setIcon(new BevelArrowIcon(
159: BevelArrowIcon.UP, false, false));
160:
161: this .normalLabel.setBorder(border);
162: this .ascendingLabel.setBorder(border);
163: this .descendingLabel.setBorder(border);
164: } else {
165: this .normalButton = new JButton();
166: this .normalButton.setMargin(new Insets(0, 0, 0, 0));
167: this .normalButton
168: .setHorizontalAlignment(SwingConstants.LEADING);
169:
170: this .ascendingButton = new JButton();
171: this .ascendingButton.setMargin(new Insets(0, 0, 0, 0));
172: this .ascendingButton
173: .setHorizontalAlignment(SwingConstants.LEADING);
174: this .ascendingButton
175: .setHorizontalTextPosition(SwingConstants.LEFT);
176: this .ascendingButton.setIcon(new BevelArrowIcon(
177: BevelArrowIcon.DOWN, false, false));
178: this .ascendingButton.setPressedIcon(new BevelArrowIcon(
179: BevelArrowIcon.DOWN, false, true));
180:
181: this .descendingButton = new JButton();
182: this .descendingButton.setMargin(new Insets(0, 0, 0, 0));
183: this .descendingButton
184: .setHorizontalAlignment(SwingConstants.LEADING);
185: this .descendingButton
186: .setHorizontalTextPosition(SwingConstants.LEFT);
187: this .descendingButton.setIcon(new BevelArrowIcon(
188: BevelArrowIcon.UP, false, false));
189: this .descendingButton.setPressedIcon(new BevelArrowIcon(
190: BevelArrowIcon.UP, false, true));
191:
192: this .normalButton.setBorder(border);
193: this .ascendingButton.setBorder(border);
194: this .descendingButton.setBorder(border);
195:
196: }
197:
198: }
199:
200: /**
201: * Returns the renderer component.
202: *
203: * @param table the table.
204: * @param value the value.
205: * @param isSelected selected?
206: * @param hasFocus focussed?
207: * @param row the row.
208: * @param column the column.
209: * @return the renderer.
210: */
211: public Component getTableCellRendererComponent(final JTable table,
212: final Object value, final boolean isSelected,
213: final boolean hasFocus, final int row, final int column) {
214:
215: if (table == null) {
216: throw new NullPointerException("Table must not be null.");
217: }
218:
219: final JComponent component;
220: final SortableTableModel model = (SortableTableModel) table
221: .getModel();
222: final int cc = table.convertColumnIndexToModel(column);
223: final boolean isSorting = (model.getSortingColumn() == cc);
224: final boolean isAscending = model.isAscending();
225:
226: final JTableHeader header = table.getTableHeader();
227: final boolean isPressed = (cc == this .pressedColumn);
228:
229: if (this .useLabels) {
230: final JLabel label = getRendererLabel(isSorting,
231: isAscending);
232: label.setText((value == null) ? "" : value.toString());
233: component = label;
234: } else {
235: final JButton button = getRendererButton(isSorting,
236: isAscending);
237: button.setText((value == null) ? "" : value.toString());
238: button.getModel().setPressed(isPressed);
239: button.getModel().setArmed(isPressed);
240: component = button;
241: }
242:
243: if (header != null) {
244: component.setForeground(header.getForeground());
245: component.setBackground(header.getBackground());
246: component.setFont(header.getFont());
247: }
248: return component;
249: }
250:
251: /**
252: * Returns the correct button component.
253: *
254: * @param isSorting whether the render component represents the sort column.
255: * @param isAscending whether the model is ascending.
256: * @return either the ascending, descending or normal button.
257: */
258: private JButton getRendererButton(final boolean isSorting,
259: final boolean isAscending) {
260: if (isSorting) {
261: if (isAscending) {
262: return ascendingButton;
263: } else {
264: return descendingButton;
265: }
266: } else {
267: return normalButton;
268: }
269: }
270:
271: /**
272: * Returns the correct label component.
273: *
274: * @param isSorting whether the render component represents the sort column.
275: * @param isAscending whether the model is ascending.
276: * @return either the ascending, descending or normal label.
277: */
278: private JLabel getRendererLabel(final boolean isSorting,
279: final boolean isAscending) {
280: if (isSorting) {
281: if (isAscending) {
282: return ascendingLabel;
283: } else {
284: return descendingLabel;
285: }
286: } else {
287: return normalLabel;
288: }
289: }
290:
291: /**
292: * Sets the pressed column.
293: *
294: * @param column the column.
295: */
296: public void setPressedColumn(final int column) {
297: this.pressedColumn = column;
298: }
299:
300: }
|