001: package com.xoetrope.swing.table;
002:
003: import java.awt.Color;
004: import java.awt.Component;
005: import java.awt.Dimension;
006: import java.awt.Font;
007: import java.awt.Graphics;
008: import java.awt.Graphics2D;
009: import java.awt.GradientPaint;
010: import java.awt.Image;
011: import java.awt.Rectangle;
012: import java.awt.event.MouseEvent;
013: import java.awt.event.MouseListener;
014: import java.awt.event.MouseMotionListener;
015: import java.awt.image.ImageObserver;
016: import javax.swing.JTable;
017: import javax.swing.table.DefaultTableCellRenderer;
018: import javax.swing.table.JTableHeader;
019: import javax.swing.border.BevelBorder;
020: import javax.swing.border.SoftBevelBorder;
021: import javax.swing.text.View;
022: import net.xoetrope.xui.XProjectManager;
023: import net.xoetrope.xui.helper.XTranslator;
024: import net.xoetrope.xui.helper.XuiUtilities;
025:
026: /**
027: * A renderer for table headers that includes translation of the header text.
028: *
029: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
030: * the GNU Public License (GPL), please see license.txt for more details. If
031: * you make commercial use of this software you must purchase a commercial
032: * license from Xoetrope.</p>
033: * <p> $Revision: 1.12 $</p>
034: */
035: public class XTableHeaderRenderer extends DefaultTableCellRenderer
036: implements MouseListener, MouseMotionListener {
037: protected XTranslator translator;
038: private int fontHeight = 0;
039: private JTableHeader tableHeader;
040: private int rolloverColumn;
041: private boolean focused, enabled;
042: private String keyText;
043:
044: private Color bkColor;
045: private Color lightColor, darkColor;
046: private Color lightColorDisabled, darkColorDisabled;
047:
048: /**
049: * @deprecated - use other constructor
050: */
051: public XTableHeaderRenderer(Color back, Color fore, Font font) {
052: translator = XProjectManager.getCurrentProject()
053: .getTranslator();
054: }
055:
056: /**
057: * Create a new header renderer
058: * @param th the header being rendered
059: */
060: public XTableHeaderRenderer(JTableHeader th) {
061: tableHeader = th;
062:
063: rolloverColumn = -1;
064: translator = XProjectManager.getCurrentProject()
065: .getTranslator();
066: tableHeader.addMouseListener(this );
067: tableHeader.addMouseMotionListener(this );
068: setBorder(new SoftBevelBorder(BevelBorder.RAISED));
069: }
070:
071: /**
072: * Repaints the component when the image has changed.
073: * This <code>imageUpdate</code> method of an <code>ImageObserver</code>
074: * is called when more information about an
075: * image which had been previously requested using an asynchronous
076: * routine such as the <code>drawImage</code> method of
077: * <code>Graphics</code> becomes available.
078: * See the definition of <code>imageUpdate</code> for
079: * more information on this method and its arguments.
080: * <p>
081: * The <code>imageUpdate</code> method of <code>Component</code>
082: * incrementally draws an image on the component as more of the bits
083: * of the image are available.
084: * <p>
085: * If the system property <code>awt.image.incrementaldraw</code>
086: * is missing or has the value <code>true</code>, the image is
087: * incrementally drawn. If the system property has any other value,
088: * then the image is not drawn until it has been completely loaded.
089: * <p>
090: * Also, if incremental drawing is in effect, the value of the
091: * system property <code>awt.image.redrawrate</code> is interpreted
092: * as an integer to give the maximum redraw rate, in milliseconds. If
093: * the system property is missing or cannot be interpreted as an
094: * integer, the redraw rate is once every 100ms.
095: * <p>
096: * The interpretation of the <code>x</code>, <code>y</code>,
097: * <code>width</code>, and <code>height</code> arguments depends on
098: * the value of the <code>infoflags</code> argument.
099: *
100: * @param img the image being observed
101: * @param infoFlags see <code>imageUpdate</code> for more information
102: * @param x the <i>x</i> coordinate
103: * @param y the <i>y</i> coordinate
104: * @param width the width
105: * @param height the height
106: * @return <code>false</code> if the infoflags indicate that the
107: * image is completely loaded; <code>true</code> otherwise.
108: *
109: * @see java.awt.image.ImageObserver
110: * @see Graphics#drawImage(Image, int, int, Color, java.awt.image.ImageObserver)
111: * @see Graphics#drawImage(Image, int, int, java.awt.image.ImageObserver)
112: * @see Graphics#drawImage(Image, int, int, int, int, Color, java.awt.image.ImageObserver)
113: * @see Graphics#drawImage(Image, int, int, int, int, java.awt.image.ImageObserver)
114: * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
115: * @since JDK1.0
116: */
117: public boolean imageUpdate(Image img, int infoFlags, int x, int y,
118: int width, int height) {
119: repaint();
120:
121: // Check the flags and return the correct value
122: if ((infoFlags & ImageObserver.ALLBITS) != 0)
123: return false;
124:
125: return true;
126: }
127:
128: /**
129: *
130: * Returns the default table cell renderer.
131: *
132: * @param table the <code>JTable</code>
133: * @param value the value to assign to the cell at
134: * <code>[row, column]</code>
135: * @param isSelected true if cell is selected
136: * @param hasFocus true if cell has focus
137: * @param row the row of the cell to render
138: * @param column the column of the cell to render
139: * @return the default table cell renderer
140: */
141: public Component getTableCellRendererComponent(JTable table,
142: Object value, boolean isSelected, boolean hasFocus,
143: int row, int column) {
144: setValue(value);
145: if ((column >= 0) && ((hasFocus) || (rolloverColumn == column))) {
146: super .setBackground(tableHeader.getBackground().brighter());
147: focused = true;
148: } else {
149: super .setBackground(tableHeader.getBackground());
150: focused = false;
151: }
152:
153: enabled = table.isEnabled();
154: if (!enabled)
155: super .setBackground(XuiUtilities.unsaturateColor(
156: tableHeader.getBackground(), 50));
157:
158: setForeground(tableHeader.getForeground());
159: return this ;
160: }
161:
162: /**
163: * Chnage the enabled state
164: * @param state the new state
165: */
166: public void setEnabled(boolean state) {
167: super .setEnabled(state);
168: bkColor = null;
169: }
170:
171: /**
172: * The backgound color has changed
173: * @param c the new color
174: */
175: public void setBackground(Color c) {
176: bkColor = null;
177: super .setBackground(c);
178: }
179:
180: /**
181: * Update the graphics
182: */
183: public void update(Graphics g) {
184: paintComponent(g);
185: }
186:
187: /**
188: * Paint the component
189: * @param g the graphics context
190: */
191: public void paintComponent(Graphics g) {
192: Graphics2D g2d = ((Graphics2D) g);
193:
194: Rectangle rect = getBounds();
195: String key = getText();
196:
197: // Fill the background
198: if (bkColor == null) {
199: bkColor = getBackground();
200: lightColor = bkColor.brighter();
201: darkColor = bkColor.darker();
202: lightColorDisabled = XuiUtilities.unsaturateColor(
203: lightColor, 50);
204: darkColorDisabled = XuiUtilities.unsaturateColor(darkColor,
205: 50);
206: }
207: bkColor = getBackground();
208: g.setColor(bkColor);
209: if (g instanceof Graphics2D) {
210: Color color1 = enabled ? lightColor : lightColorDisabled;
211: Color color2 = enabled ? darkColor : darkColorDisabled;
212: GradientPaint gradient = new GradientPaint(0.0F, 0.0F,
213: color1, (float) rect.height / 2,
214: (float) rect.width / 2, color2, true);
215: g2d.setPaint(gradient);
216: g2d.fill(new Rectangle(0, 0, rect.width - 1, rect.height));
217: } else
218: g.fillRect(0, 0, rect.width, rect.height);
219:
220: if (enabled && focused) {
221: g.setColor(Color.green);
222: g.fillRect(1, rect.height - 2, rect.width - 1, 1);
223: }
224:
225: g.setColor(getForeground());
226: View v = (View) getClientProperty("html");
227: if (v != null) {
228: Dimension sz = getSize();
229: Rectangle textRect = new Rectangle(6, 4, rect.width,
230: rect.height);
231: v.paint(g, textRect);
232: } else if (key != null)
233: g.drawString(key, 6, 4 + (rect.height - fontHeight) / 2);
234:
235: if (focused) {
236: g.setColor(tableHeader.getBackground().brighter()
237: .brighter());
238: g.fillRect(rect.width - 2, rect.y, 2, rect.height);
239: }
240: }
241:
242: /**
243: * Set the header value. Translates the value if possible
244: * @param value the raw header value
245: */
246: public void setValue(Object value) {
247: if (value != null) {
248: String text = value.toString();
249: if ((keyText == null) || !keyText.equals(text)) {
250: keyText = text;
251: if (translator != null)
252: text = translator.translate(text);
253: setText(text);
254: }
255: } else
256: setText("");
257: }
258:
259: private void updateRolloverColumn(MouseEvent e) {
260: int col = tableHeader.columnAtPoint(e.getPoint());
261: if (col != rolloverColumn) {
262: rolloverColumn = col;
263: tableHeader.repaint();
264: }
265: }
266:
267: /**
268: * Invoked when the mouse button has been clicked (pressed
269: * and released) on a component.
270: */
271: public void mouseClicked(MouseEvent e) {
272: }
273:
274: /**
275: * Invoked when a mouse button has been pressed on a component.
276: */
277: public void mousePressed(MouseEvent e) {
278: rolloverColumn = -1;
279: tableHeader.repaint();
280: }
281:
282: /**
283: * Invoked when a mouse button has been released on a component.
284: */
285: public void mouseReleased(MouseEvent e) {
286: updateRolloverColumn(e);
287: }
288:
289: /**
290: * Invoked when the mouse enters a component.
291: */
292: public void mouseEntered(MouseEvent e) {
293: updateRolloverColumn(e);
294: }
295:
296: /**
297: * Invoked when the mouse exits a component.
298: */
299: public void mouseExited(MouseEvent e) {
300: rolloverColumn = -1;
301: tableHeader.repaint();
302: }
303:
304: /**
305: * Invoked when a mouse button is pressed on a component and then
306: * dragged. <code>MOUSE_DRAGGED</code> events will continue to be
307: * delivered to the component where the drag originated until the
308: * mouse button is released (regardless of whether the mouse position
309: * is within the bounds of the component).
310: * <p>
311: * Due to platform-dependent Drag&Drop implementations,
312: * <code>MOUSE_DRAGGED</code> events may not be delivered during a native
313: * Drag&Drop operation.
314: */
315: public void mouseDragged(MouseEvent e) {
316: }
317:
318: /**
319: * Invoked when the mouse cursor has been moved onto a component
320: * but no buttons have been pushed.
321: */
322: public void mouseMoved(MouseEvent e) {
323: updateRolloverColumn(e);
324: }
325: }
|