001: package org.gui4j.core.swing;
002:
003: // Chris's entension of JTable
004: //
005: // Inspired by the RowHeaderExample by Nobuo Tamemasa.
006: //
007: // known problems:
008: // - Doesn't enable/disable row header when table row selection is
009: // enabled/disabled
010: // - Dragging on the list of row headers doesn't scroll the table. (I
011: // - can't figure out a good way to catch list scrolling events.)
012: //
013:
014: import java.awt.Color;
015: import java.awt.Component;
016: import java.awt.Container;
017: import java.awt.Font;
018: import java.beans.PropertyChangeEvent;
019: import java.beans.PropertyChangeListener;
020: import java.beans.PropertyDescriptor;
021: import java.lang.reflect.Method;
022:
023: import javax.swing.AbstractListModel;
024: import javax.swing.JLabel;
025: import javax.swing.JList;
026: import javax.swing.JScrollPane;
027: import javax.swing.JViewport;
028: import javax.swing.ListCellRenderer;
029: import javax.swing.SwingConstants;
030: import javax.swing.UIManager;
031: import javax.swing.border.Border;
032: import javax.swing.table.JTableHeader;
033: import javax.swing.table.TableModel;
034:
035: public class RowHeaderTable extends Gui4jJTable {
036: protected JList rowHeader;
037: protected RowHeaderTable.RowHeaderListModel rowHeaderModel;// former: ListModel
038:
039: // duplicate most of JTable's constructors for convenience
040:
041: public RowHeaderTable(RowHeaderTableModel dm,
042: Gui4jTableListener gui4jTableListener) {
043: super (dm, gui4jTableListener);
044: initUI();
045: }
046:
047: protected void initUI() {
048: buildRowHeaders();
049: }
050:
051: protected TableModel createDefaultDataModel() {
052: return new RowHeaderDefaultTableModel();
053: }
054:
055: public RowHeaderTable.RowHeaderListModel getRowHeaderModel() {
056: return rowHeaderModel;
057: }
058:
059: protected void buildRowHeaders() {
060: if (rowHeader == null) {
061: rowHeaderModel = new RowHeaderListModel();/*AbstractListModel()
062: {
063: private boolean ignoreBackground = false;
064: public int getSize()
065: {
066: return (getModel() == null) ? 0 : getModel().getRowCount();
067: }
068: public Object getElementAt(int index)
069: {
070: TableModel dm = getModel();
071: if (dm == null)
072: {
073: return null;
074: }
075: return ((RowHeaderTableModel) dm).getRowName(index);
076: }
077: public void setIgnoreBackgound(boolean flag)
078: {
079: ignoreBackground = flag;
080: }
081: public boolean ignoreBackground(boolean flag)
082: {
083: return ignoreBackground;
084: }
085: };
086: */
087: rowHeader = new JList(rowHeaderModel);
088: rowHeader.setFocusable(false);
089: rowHeader.setSelectionModel(getSelectionModel());
090: rowHeader.setFixedCellWidth(100);
091: JTableHeader columnHeader = getTableHeader();
092: rowHeader.setForeground(columnHeader.getForeground());
093: rowHeader.setBackground(columnHeader.getBackground());
094: rowHeader.setFont(columnHeader.getFont());
095:
096: rowHeader.setFixedCellHeight(getRowHeight() // + getRowMargin()
097: /*+
098: getIntercellSpacing().height*/
099: );
100: rowHeader.setCellRenderer(new RowHeaderRenderer());
101:
102: columnHeader
103: .addPropertyChangeListener(new PropertyChangeListener() {
104: public void propertyChange(
105: PropertyChangeEvent event) {
106: try {
107: PropertyDescriptor propDesc = new PropertyDescriptor(
108: event.getPropertyName(),
109: JList.class);
110: Method writeMethod = propDesc
111: .getWriteMethod();
112: Object[] params = { event.getNewValue() };
113: writeMethod.invoke(rowHeader, params);
114: } catch (Exception e) {
115: /* fail silently
116: System.err.println("Couldn't forward prop change for prop '" +
117: event.getPropertyName() + "':" + e);
118: */
119: }
120: }
121: });
122: }
123: }
124:
125: protected void configureEnclosingScrollPane() {
126: super .configureEnclosingScrollPane();
127: Container parent = getParent();
128: if (parent instanceof JViewport) {
129: Container grandParent = parent.getParent();
130: if (grandParent instanceof JScrollPane) {
131: JScrollPane scrollPane = (JScrollPane) grandParent;
132: // Make certain we are the viewPort's view and not, for
133: // example, the rowHeaderView of the scrollPane -
134: // an implementor of fixed columns might do this.
135: JViewport viewport = scrollPane.getViewport();
136: if (viewport == null || viewport.getView() != this ) {
137: return;
138: }
139: scrollPane.setRowHeaderView(rowHeader);
140: rowHeader.setBackground(scrollPane.getBackground());
141: }
142: }
143: }
144:
145: public void setRowHeaderWidth(int width) {
146: rowHeader.setFixedCellWidth(width);
147: }
148:
149: public void setRowHeaderHeight(int height) {
150: rowHeader.setFixedCellHeight(height);
151: }
152:
153: /*
154: public void setRowPreferredScrollableHeight(int height)
155: {
156: rowHeader.getPreferredScrollableViewportSize().height = height;
157: }
158: */
159:
160: public void setRowHeaderFont(Font font) {
161: rowHeader.setFont(font);
162: ((RowHeaderRenderer) rowHeader.getCellRenderer()).setFont(font);
163: }
164:
165: public void refreshRowHeaders() {
166: if (rowHeader != null) {
167: rowHeader.repaint();
168: }
169: }
170:
171: // ***************************************************************************
172:
173: public class RowHeaderRenderer implements ListCellRenderer {
174:
175: private final Border border;
176: private final Color foreground;
177: private Color background;
178: private Font font;
179: private final JLabel label;
180:
181: RowHeaderRenderer() {
182: JTableHeader header = RowHeaderTable.this .getTableHeader();
183: border = UIManager.getBorder("TableHeader.cellBorder");
184: foreground = header.getForeground();
185: background = header.getBackground();
186: font = header.getFont();
187: label = new JLabel();
188: }
189:
190: public void setBackground(Color background) {
191: this .background = background;
192: }
193:
194: public Component getListCellRendererComponent(JList list,
195: Object value, int index, boolean isSelected,
196: boolean cellHasFocus) {
197: Component result;
198: if (value instanceof Component) {
199: result = (Component) value;
200: } else {
201: label.setText((value == null) ? "" : value.toString());
202: label.setOpaque(true);
203: label.setHorizontalAlignment(SwingConstants.LEFT);
204: label.setForeground(foreground);
205: if (!rowHeaderModel.ignoreBackgound()) {
206: label.setBackground(background);
207: } else {
208: label.setBackground(Color.white);
209: }
210: label.setBorder(border);
211: label.setFont(font);
212: result = label;
213: }
214: return result;
215: }
216:
217: public void setFont(Font font) {
218: this .font = font;
219: }
220: }
221:
222: /**
223: * Returns the rowHeader.
224: * @return JList
225: */
226: public JList getRowHeader() {
227: return rowHeader;
228: }
229:
230: public class RowHeaderListModel extends AbstractListModel {
231: private boolean ignoreBackground = false;
232:
233: public int getSize() {
234: return (getModel() == null) ? 0 : getModel().getRowCount();
235: }
236:
237: public Object getElementAt(int index) {
238: TableModel dm = getModel();
239: if (dm == null) {
240: return null;
241: }
242: return ((RowHeaderTableModel) dm).getRowName(index);
243: }
244:
245: public void setIgnoreBackgound(boolean flag) {
246: ignoreBackground = flag;
247: }
248:
249: public boolean ignoreBackground(boolean flag) {
250: return ignoreBackground;
251: }
252:
253: public boolean ignoreBackgound() {
254: return ignoreBackground;
255: }
256: }
257:
258: }
|