001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.admin.common;
005:
006: import com.tc.util.runtime.Os;
007:
008: import java.awt.BorderLayout;
009: import java.awt.Component;
010: import java.awt.Dimension;
011: import java.awt.event.ActionEvent;
012: import java.awt.event.ActionListener;
013: import java.awt.event.MouseAdapter;
014: import java.awt.event.MouseEvent;
015: import java.lang.reflect.Method;
016: import java.util.prefs.Preferences;
017:
018: import javax.swing.JComponent;
019: import javax.swing.JTable;
020: import javax.swing.UIManager;
021: import javax.swing.border.BevelBorder;
022: import javax.swing.border.Border;
023: import javax.swing.table.JTableHeader;
024: import javax.swing.table.TableCellEditor;
025: import javax.swing.table.TableColumn;
026: import javax.swing.table.TableColumnModel;
027: import javax.swing.table.TableModel;
028:
029: public class XObjectTable extends XTable {
030: protected int sortColumn;
031: protected int sortDirection;
032:
033: private TableColumnRenderer columnRenderer;
034:
035: public static final int UP = XObjectTableModel.UP;
036: public static final int DOWN = XObjectTableModel.DOWN;
037:
038: private ArrowLabel arrowLabel;
039:
040: private static final String SORT_COLUMN_PREF_KEY = "SortColumn";
041: private static final String SORT_DIRECTION_PREF_KEY = "SortDirection";
042:
043: public XObjectTable() {
044: super ();
045: init();
046: }
047:
048: public XObjectTable(TableModel model) {
049: super (model);
050: init();
051: }
052:
053: private void init() {
054: sortColumn = -1;
055: sortDirection = DOWN;
056:
057: arrowLabel = new ArrowLabel();
058:
059: setDefaultRenderer(Method.class, new MethodRenderer());
060: setDefaultEditor(Method.class, new MethodEditor());
061:
062: getTableHeader().addMouseListener(new MouseAdapter() {
063: public void mouseClicked(MouseEvent me) {
064: if (me.getClickCount() == 2) {
065: int col = columnAtPoint(me.getPoint());
066:
067: if (((XObjectTableModel) getModel())
068: .isColumnSortable(col)) {
069: setSortDirection(toggleSortDirection());
070: setSortColumn(col);
071: }
072: }
073: }
074: });
075: columnRenderer = new TableColumnRenderer();
076:
077: getTableHeader().setDefaultRenderer(columnRenderer);
078: }
079:
080: public void createDefaultColumnsFromModel() {
081: super .createDefaultColumnsFromModel();
082:
083: XObjectTableModel tableModel = (XObjectTableModel) getModel();
084: TableColumnModel colModel = getColumnModel();
085: TableColumn column;
086:
087: for (int i = 0; i < colModel.getColumnCount(); i++) {
088: column = colModel.getColumn(i);
089: column.setHeaderRenderer(columnRenderer);
090: column.setIdentifier(tableModel.getFieldName(i));
091: }
092: }
093:
094: public void addNotify() {
095: super .addNotify();
096: loadSortPrefs();
097: }
098:
099: private class TableColumnRenderer extends XTableCellRenderer {
100: private JComponent sortView;
101: private Border border;
102:
103: public TableColumnRenderer() {
104: super ();
105: sortView = new JComponent() {/**/
106: };
107: sortView.setLayout(new BorderLayout());
108:
109: border = Os.isMac() ? new BevelBorder(BevelBorder.RAISED)
110: : UIManager.getBorder("TableHeader.cellBorder");
111: }
112:
113: public Component getTableCellRendererComponent(JTable table,
114: Object value, boolean isSelected, boolean hasFocus,
115: int row, int column) {
116: if (table != null) {
117: JTableHeader header = table.getTableHeader();
118:
119: if (header != null) {
120: setForeground(header.getForeground());
121: setBackground(header.getBackground());
122: setFont(header.getFont());
123: }
124: }
125:
126: String text = (value == null) ? "" : value.toString();
127: setText(text);
128:
129: if (sortColumn != -1) {
130: if (column == sortColumn) {
131: arrowLabel.setDirection(sortDirection);
132:
133: setBorder(null);
134: setOpaque(false);
135:
136: sortView.setForeground(null);
137: sortView.setBackground(null);
138: sortView.setFont(null);
139:
140: sortView.add(this , BorderLayout.WEST);
141: sortView.add(arrowLabel, BorderLayout.EAST);
142: sortView.setBorder(border);
143: return sortView;
144: }
145: }
146:
147: setBorder(border);
148: return this ;
149: }
150: }
151:
152: private void internalSetSortColumn(int columnIndex) {
153: if ((sortColumn = columnIndex) != -1) {
154: sort();
155: }
156: }
157:
158: public void setSortColumn(int columnIndex) {
159: internalSetSortColumn(columnIndex);
160: storeSortPrefs();
161: }
162:
163: public int getSortColumn() {
164: return sortColumn;
165: }
166:
167: public void sort() {
168: if (sortColumn != -1) {
169: TableModel model = getModel();
170: JTableHeader header = getTableHeader();
171:
172: if (model != null && model instanceof XObjectTableModel) {
173: Object[] selection = getSelection();
174:
175: ((XObjectTableModel) model).sortColumn(sortColumn,
176: sortDirection);
177:
178: if (header != null) {
179: header.repaint();
180: }
181:
182: setSelection(selection);
183: }
184: }
185: }
186:
187: private void internalSetSortDirection(int direction) {
188: sortDirection = direction;
189: }
190:
191: public void setSortDirection(int direction) {
192: internalSetSortDirection(direction);
193: storeSortPrefs();
194: }
195:
196: public int getSortDirection() {
197: return sortDirection;
198: }
199:
200: public int toggleSortDirection() {
201: return sortDirection == UP ? DOWN : UP;
202: }
203:
204: public Object[] getSelection() {
205: XObjectTableModel model = (XObjectTableModel) getModel();
206: int[] rows = getSelectedRows();
207: Object[] result = new Object[rows.length];
208:
209: for (int i = 0; i < rows.length; i++) {
210: result[i] = model.getObjectAt(rows[i]);
211: }
212:
213: return result;
214: }
215:
216: public void setSelection(Object[] selection) {
217: XObjectTableModel model = (XObjectTableModel) getModel();
218: int index;
219:
220: clearSelection();
221:
222: for (int i = 0; i < selection.length; i++) {
223: index = model.getObjectIndex(selection[i]);
224: addRowSelectionInterval(index, index);
225: }
226: }
227:
228: protected TableModel createDefaultDataModel() {
229: return new XObjectTableModel();
230: }
231:
232: public void setModel(TableModel model) {
233: super .setModel(model);
234: if (sortColumn != -1) {
235: sortColumn = Math.min(sortColumn,
236: model.getColumnCount() - 1);
237: sort();
238: }
239: }
240:
241: public void showColumnsExclusive(String[] fieldNames) {
242: Object[] selection = getSelection();
243: XObjectTableModel model = (XObjectTableModel) getModel();
244:
245: model.showColumnsExclusive(fieldNames);
246: setSelection(selection);
247: }
248:
249: public void showColumn(String fieldName) {
250: Object[] selection = getSelection();
251: XObjectTableModel model = (XObjectTableModel) getModel();
252:
253: model.showColumn(fieldName);
254: setSelection(selection);
255: }
256:
257: public void hideColumn(String fieldName) {
258: Object[] selection = getSelection();
259: XObjectTableModel model = (XObjectTableModel) getModel();
260:
261: model.hideColumn(fieldName);
262: if (getSortColumn() >= getColumnCount()) {
263: setSortColumn(getColumnCount() - 1);
264: }
265: setSelection(selection);
266: }
267:
268: public TableColumn findColumn(String fieldName) {
269: XObjectTableModel model = (XObjectTableModel) getModel();
270: int index = model.getShowingFieldIndex(fieldName);
271:
272: return index != -1 ? getColumnModel().getColumn(index) : null;
273: }
274:
275: public int getShowingFieldCount() {
276: return getColumnCount();
277: }
278:
279: public String[] getShowingFields() {
280: return ((XObjectTableModel) getModel()).getShowingFields();
281: }
282:
283: public boolean isColumnShowing(String fieldName) {
284: return ((XObjectTableModel) getModel())
285: .isColumnShowing(fieldName);
286: }
287:
288: class MethodRenderer extends XTableCellRenderer {
289: protected TableCellEditor m_editor;
290:
291: public MethodRenderer() {
292: super ();
293: m_editor = createCellEditor();
294: }
295:
296: protected TableCellEditor createCellEditor() {
297: return new MethodEditor();
298: }
299:
300: public java.awt.Component getTableCellRendererComponent(
301: JTable table, Object value, boolean isSelected,
302: boolean hasFocus, int row, int col) {
303: return m_editor.getTableCellEditorComponent(table, value,
304: false, row, col);
305: }
306: }
307:
308: class MethodEditor extends XCellEditor {
309: InvokerButton button;
310:
311: MethodEditor() {
312: super (new XCheckBox());
313:
314: m_editorComponent = button = new InvokerButton();
315: button.addActionListener(new ActionListener() {
316: public void actionPerformed(ActionEvent ae) {
317: int row = button.getRow();
318: int col = button.getCol();
319: XObjectTableModel model = (XObjectTableModel) getModel();
320: Method method = (Method) model.getValueAt(row, col);
321: Object obj = model.getObjectAt(row);
322:
323: try {
324: method.invoke(obj, new Object[] {});
325: XObjectTable.this .repaint();
326: } catch (Exception e) {
327: e.printStackTrace();
328: }
329: }
330: });
331: m_clicksToStart = 1;
332: }
333:
334: public java.awt.Component getTableCellEditorComponent(
335: JTable table, Object value, boolean isSelected,
336: int row, int col) {
337: super .getTableCellEditorComponent(table, value, isSelected,
338: row, col);
339:
340: XObjectTableModel model = (XObjectTableModel) table
341: .getModel();
342: Method method = (Method) model.getValueAt(row, col);
343:
344: button.setText(method.getName());
345: button.setCell(row, col);
346: button.setForeground(table.getForeground());
347: button.setBackground(table.getBackground());
348: button.setFont(table.getFont());
349:
350: return button;
351: }
352: }
353:
354: protected void loadSortPrefs() {
355: PrefsHelper helper = PrefsHelper.getHelper();
356: Preferences prefs = helper.userNodeForClass(getClass());
357: String s;
358:
359: // It's important that we set the sortDirection prior to the sortColumn
360: // because the latter does an actual sort.
361:
362: if ((s = prefs.get(SORT_DIRECTION_PREF_KEY, null)) != null) {
363: try {
364: internalSetSortDirection(Integer.parseInt(s));
365: } catch (NumberFormatException nfe) {/**/
366: }
367: }
368:
369: if ((s = prefs.get(SORT_COLUMN_PREF_KEY, null)) != null) {
370: try {
371: internalSetSortColumn(Integer.parseInt(s));
372: } catch (NumberFormatException nfe) {/**/
373: }
374: }
375: }
376:
377: protected void storeSortPrefs() {
378: PrefsHelper helper = PrefsHelper.getHelper();
379: Preferences prefs = helper.userNodeForClass(getClass());
380:
381: prefs.put(SORT_COLUMN_PREF_KEY, Integer
382: .toString(getSortColumn()));
383: prefs.put(SORT_DIRECTION_PREF_KEY, Integer
384: .toString(getSortDirection()));
385:
386: helper.flush(prefs);
387: }
388:
389: class InvokerButton extends XButton {
390: private int row;
391: private int col;
392: private boolean ignoreNextMouseEvent;
393:
394: public InvokerButton() {
395: super ();
396:
397: setFocusable(false);
398: setOpaque(true);
399: }
400:
401: void setCell(int row, int col) {
402: setRow(row);
403: setCol(col);
404: }
405:
406: void setRow(int row) {
407: this .row = row;
408: }
409:
410: int getRow() {
411: return row;
412: }
413:
414: void setCol(int col) {
415: this .col = col;
416: }
417:
418: int getCol() {
419: return col;
420: }
421:
422: void setIgnoreNextEvent(boolean b) {
423: ignoreNextMouseEvent = b;
424: }
425:
426: boolean getIgnoreNextEvent() {
427: return ignoreNextMouseEvent;
428: }
429:
430: public Dimension _getPreferredSize() {
431: Dimension d = super .getPreferredSize();
432:
433: if (true || System.getProperty("os.name")
434: .equals("Mac OS X")) {
435: d.height = 20;
436: }
437:
438: return d;
439: }
440:
441: protected void processMouseEvent(MouseEvent e) {
442: if (!ignoreNextMouseEvent) {
443: super .processMouseEvent(e);
444: } else {
445: requestFocus();
446: }
447:
448: ignoreNextMouseEvent = false;
449: }
450: }
451: }
|