001: /*
002: * Copyright (c) 2005-2008 Substance Kirill Grouchnikov. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of Substance Kirill Grouchnikov nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030: package test.check;
031:
032: import java.awt.*;
033: import java.awt.event.ActionEvent;
034: import java.awt.event.ActionListener;
035: import java.lang.reflect.Method;
036: import java.util.Calendar;
037: import java.util.Date;
038:
039: import javax.swing.*;
040: import javax.swing.event.ChangeEvent;
041: import javax.swing.event.ChangeListener;
042: import javax.swing.table.AbstractTableModel;
043: import javax.swing.table.JTableHeader;
044:
045: import org.jvnet.lafwidget.animation.*;
046: import org.jvnet.lafwidget.utils.LookUtils;
047: import org.jvnet.lafwidget.utils.LafConstants.AnimationKind;
048: import org.jvnet.substance.*;
049: import org.jvnet.substance.theme.SubstanceTheme;
050: import org.jvnet.substance.theme.ThemeInfo;
051: import org.jvnet.substance.utils.SubstanceColorUtilities;
052:
053: import com.jgoodies.forms.builder.DefaultFormBuilder;
054: import com.jgoodies.forms.layout.FormLayout;
055:
056: /**
057: * Test application panel for testing {@link JTable} component.
058: *
059: * @author Kirill Grouchnikov
060: */
061: public class TablePanel extends ControllablePanel {
062: /**
063: * The table.
064: */
065: private JTable table;
066:
067: /**
068: * Custom renderer for columns that contain {@link Color} data.
069: *
070: * @author Kirill Grouchnikov
071: */
072: private static class MyColorTableRenderer extends
073: SubstanceDefaultTableCellRenderer {
074: /*
075: * (non-Javadoc)
076: *
077: * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable,
078: * java.lang.Object, boolean, boolean, int, int)
079: */
080: @Override
081: public Component getTableCellRendererComponent(JTable table,
082: Object value, boolean isSelected, boolean hasFocus,
083: int row, int column) {
084: Color color = (Color) value;
085: this .setForeground(color);
086: this .setBackground(SubstanceColorUtilities
087: .invertColor(color));
088: this .setText("row " + row);
089: return this ;
090: }
091: }
092:
093: /**
094: * Custom renderer for the columns that contain {@link Float} data.
095: *
096: * @author Kirill Grouchnikov
097: */
098: private static class MyFloatTableRenderer extends
099: SubstanceDefaultTableCellRenderer {
100: /*
101: * (non-Javadoc)
102: *
103: * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable,
104: * java.lang.Object, boolean, boolean, int, int)
105: */
106: @Override
107: public Component getTableCellRendererComponent(JTable table,
108: Object value, boolean isSelected, boolean hasFocus,
109: int row, int column) {
110: int c = (10 * row) % 255;
111: Color color = new Color(c, c, c);
112: this .setForeground(new Color(255 - c, 0, 0));
113: this .setBackground(color);
114: this .setText(value.toString());
115: return this ;
116: }
117: }
118:
119: /**
120: * Custom table model.
121: *
122: * @author Kirill Grouchnikov
123: */
124: private static class MyTableModel extends AbstractTableModel {
125: /**
126: * The current row count.
127: */
128: private int rows;
129:
130: /**
131: * The column count.
132: */
133: private int cols = 10;
134:
135: /**
136: * The table data.
137: */
138: private Object[][] data;
139:
140: /**
141: * The table column classes.
142: */
143: private Class<?>[] columns = new Class<?>[] { String.class,
144: JComboBox.class, Boolean.class, Byte.class,
145: Float.class, Double.class, String.class, Date.class,
146: ImageIcon.class, Color.class };
147:
148: /**
149: * Creates the custom table model.
150: *
151: * @param rows
152: * Initial number of rows.
153: */
154: public MyTableModel(int rows) {
155: this .rows = rows;
156: this .data = new Object[rows][this .cols];
157: for (int i = 0; i < rows; i++) {
158: this .data[i][0] = "cell " + i + ":" + 0;
159: this .data[i][1] = "predef";
160: this .data[i][2] = new Boolean(i % 2 == 0);
161: this .data[i][3] = new Byte((byte) i);
162: this .data[i][4] = new Float(i);
163: this .data[i][5] = new Double(i);
164: this .data[i][6] = "cell " + i + ":" + 6;
165: Calendar cal = Calendar.getInstance();
166: cal.set(2000 + i, 1 + i, 1 + i);
167: this .data[i][7] = cal.getTime();
168: int count = 0;
169: if (UIManager.getLookAndFeel() instanceof SubstanceLookAndFeel) {
170: for (ThemeInfo themeInfo : SubstanceLookAndFeel
171: .getAllThemes().values()) {
172: if (count++ == i) {
173: try {
174: this .data[i][8] = SubstanceImageCreator
175: .getHexaMarker(
176: 6,
177: (SubstanceTheme) Class
178: .forName(
179: themeInfo
180: .getClassName())
181: .newInstance());
182: } catch (Exception exc) {
183: }
184: }
185: }
186: }
187:
188: int comp = i * 20;
189: int red = (comp / 3) % 255;
190: int green = (comp / 2) % 255;
191: int blue = comp % 255;
192: this .data[i][9] = new Color(red, green, blue);
193: }
194: }
195:
196: /*
197: * (non-Javadoc)
198: *
199: * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
200: */
201: @Override
202: public Class<?> getColumnClass(int columnIndex) {
203: return this .columns[columnIndex];
204: }
205:
206: /*
207: * (non-Javadoc)
208: *
209: * @see javax.swing.table.TableModel#getColumnCount()
210: */
211: public int getColumnCount() {
212: return this .cols;
213: }
214:
215: /*
216: * (non-Javadoc)
217: *
218: * @see javax.swing.table.TableModel#getRowCount()
219: */
220: public int getRowCount() {
221: return this .rows;
222: }
223:
224: /*
225: * (non-Javadoc)
226: *
227: * @see javax.swing.table.TableModel#getValueAt(int, int)
228: */
229: public Object getValueAt(int row, int col) {
230: return this .data[row][col];
231: }
232:
233: /*
234: * (non-Javadoc)
235: *
236: * @see javax.swing.table.AbstractTableModel#getColumnName(int)
237: */
238: @Override
239: public String getColumnName(int column) {
240: return this .getColumnClass(column).getSimpleName();
241: }
242:
243: /*
244: * (non-Javadoc)
245: *
246: * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int)
247: */
248: @Override
249: public boolean isCellEditable(int rowIndex, int columnIndex) {
250: return (rowIndex % 2 == 0);
251: }
252:
253: /*
254: * (non-Javadoc)
255: *
256: * @see javax.swing.table.AbstractTableModel#setValueAt(java.lang.Object,
257: * int, int)
258: */
259: @Override
260: public void setValueAt(Object value, int row, int col) {
261: this .data[row][col] = value;
262: this .fireTableCellUpdated(row, col);
263: }
264: }
265:
266: /**
267: * Creates a test panel with table.
268: */
269: public TablePanel() {
270: // TableColumnModel columnModel = new DefaultTableColumnModel() {
271: // @Override public int getColumnCount() {
272: // return 10;
273: // }
274: //
275: // @Override public TableColumn getColumn(int columnIndex) {
276: // return new TableColumn(
277: // }
278: // };
279: this .table = new JTable(new MyTableModel(20));
280: this .table.setDefaultRenderer(Color.class,
281: new MyColorTableRenderer());
282: this .table.setDefaultRenderer(Float.class,
283: new MyFloatTableRenderer());
284: final JScrollPane tableScrollpane = new JScrollPane(this .table);
285: tableScrollpane.setName("Main table in table panel");
286:
287: JComboBox combo = new JComboBox(
288: new Object[] { "aa", "bb", "cc" });
289: combo.setBorder(null);
290: this .table.getColumnModel().getColumn(1).setCellEditor(
291: new DefaultCellEditor(combo));
292:
293: this .table
294: .setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
295: // We allow row selection as the default
296: this .table.setCellSelectionEnabled(true);
297: this .table.setRowSelectionAllowed(true);
298: this .table.setColumnSelectionAllowed(false);
299:
300: this .table.setShowGrid(false);
301: this .table.setDragEnabled(false);
302: this .table.setTableHeader(new JTableHeader(this .table
303: .getColumnModel()));
304:
305: this .setLayout(new BorderLayout());
306: this .add(tableScrollpane, BorderLayout.CENTER);
307:
308: final JLabel instructional = new JLabel(
309: "Every odd row is editable");
310: this .add(instructional, BorderLayout.NORTH);
311: // create a looping animation to change the label foreground
312: // from black to blue and back to draw some attention.
313: FadeKind custom = new FadeKind(
314: "substance.testapp.table.instructional");
315: FadeTracker.getInstance().trackFadeLooping(custom,
316: AnimationKind.DEBUG_FAST, instructional, 0, false,
317: new FadeTrackerAdapter() {
318: @Override
319: public void fadePerformed(FadeKind fadeKind,
320: float fadeCycle10) {
321: instructional
322: .setForeground(SubstanceColorUtilities
323: .getInterpolatedColor(
324: Color.black,
325: Color.blue,
326: fadeCycle10 / 10.0));
327: }
328: }, -1, true);
329:
330: FormLayout lm = new FormLayout(
331: "right:pref, 4dlu, fill:pref:grow", "");
332: DefaultFormBuilder builder = new DefaultFormBuilder(lm,
333: new ScrollablePanel());
334:
335: builder.appendSeparator("Table settings");
336: final JCheckBox isEnabled = new JCheckBox("is enabled");
337: isEnabled.setSelected(table.isEnabled());
338: isEnabled.addActionListener(new ActionListener() {
339: public void actionPerformed(ActionEvent e) {
340: table.setEnabled(isEnabled.isSelected());
341: // the table header is not repainted on disabling / enabling :(
342: table.getTableHeader().repaint();
343: }
344: });
345: builder.append("Enabled", isEnabled);
346:
347: JButton changeFirstColumn = new JButton("change 1st column");
348: changeFirstColumn.addActionListener(new ActionListener() {
349: public void actionPerformed(ActionEvent e) {
350: new Thread(new Runnable() {
351: public void run() {
352: for (int i = 0; i < table.getModel()
353: .getRowCount(); i++) {
354: table.getModel().setValueAt(
355: Thread.currentThread().getName()
356: + " " + i, i, 0);
357: try {
358: Thread.sleep(200);
359: } catch (InterruptedException e) {
360: }
361: }
362: }
363: }).start();
364: }
365: });
366: builder.append("Change values", changeFirstColumn);
367:
368: final JSlider rowCountSlider = new JSlider(20, 1000, this .table
369: .getModel().getRowCount());
370: rowCountSlider.setPaintLabels(false);
371: rowCountSlider.setPaintTicks(false);
372: rowCountSlider.addChangeListener(new ChangeListener() {
373: public void stateChanged(ChangeEvent e) {
374: if (rowCountSlider.getValueIsAdjusting())
375: return;
376: TablePanel.this .table.setModel(new MyTableModel(
377: rowCountSlider.getValue()));
378: }
379: });
380: builder.append("Row count", rowCountSlider);
381:
382: final JCheckBox areRowsSelectable = new JCheckBox(
383: "Rows selectable");
384: areRowsSelectable.setSelected(this .table
385: .getRowSelectionAllowed());
386: areRowsSelectable.addActionListener(new ActionListener() {
387: public void actionPerformed(ActionEvent e) {
388: TablePanel.this .table
389: .setRowSelectionAllowed(areRowsSelectable
390: .isSelected());
391: }
392: });
393: builder.append("Selectable", areRowsSelectable);
394:
395: final JCheckBox areColsSelectable = new JCheckBox(
396: "Cols selectable");
397: areColsSelectable.setSelected(this .table
398: .getColumnSelectionAllowed());
399: areColsSelectable.addActionListener(new ActionListener() {
400: public void actionPerformed(ActionEvent e) {
401: TablePanel.this .table
402: .setColumnSelectionAllowed(areColsSelectable
403: .isSelected());
404: }
405: });
406: builder.append("", areColsSelectable);
407:
408: // TODO JDK 6 replace with regular code
409: if (LookUtils.IS_JAVA_6_OR_LATER) {
410: try {
411: final JCheckBox isSorted = new JCheckBox("Sorted");
412: Method isAutoSorter = JTable.class.getDeclaredMethod(
413: "getAutoCreateRowSorter", new Class[0]);
414: isSorted.setSelected((Boolean) isAutoSorter.invoke(
415: this .table, new Object[0]));
416: isSorted.addActionListener(new ActionListener() {
417: public void actionPerformed(ActionEvent e) {
418: try {
419: Method setAutoSorter = JTable.class
420: .getDeclaredMethod(
421: "setAutoCreateRowSorter",
422: new Class[] { boolean.class });
423: setAutoSorter.invoke(table,
424: new Object[] { isSorted
425: .isSelected() });
426: table.repaint();
427: table.getTableHeader().repaint();
428: } catch (Exception exc) {
429: }
430: }
431: });
432: builder.append("Sorted", isSorted);
433: } catch (Exception exc) {
434: }
435: }
436:
437: final JCheckBox watermarkBleed = new JCheckBox(
438: "Watermark bleed");
439: watermarkBleed.addActionListener(new ActionListener() {
440: public void actionPerformed(ActionEvent e) {
441: TablePanel.this .table.putClientProperty(
442: SubstanceLookAndFeel.WATERMARK_TO_BLEED,
443: Boolean.valueOf(watermarkBleed.isSelected()));
444: tableScrollpane.putClientProperty(
445: SubstanceLookAndFeel.WATERMARK_TO_BLEED,
446: Boolean.valueOf(watermarkBleed.isSelected()));
447: tableScrollpane.repaint();
448: }
449: });
450: builder.append("Watermark", watermarkBleed);
451:
452: final JCheckBox linesVertical = new JCheckBox(
453: "Vertical visible");
454: linesVertical.setSelected(this .table.getShowVerticalLines());
455: linesVertical.addActionListener(new ActionListener() {
456: public void actionPerformed(ActionEvent e) {
457: TablePanel.this .table
458: .setShowVerticalLines(linesVertical
459: .isSelected());
460: }
461: });
462: builder.append("Lines", linesVertical);
463: final JCheckBox linesHorizontal = new JCheckBox(
464: "Horizontal visible");
465: linesHorizontal
466: .setSelected(this .table.getShowHorizontalLines());
467: linesHorizontal.addActionListener(new ActionListener() {
468: public void actionPerformed(ActionEvent e) {
469: TablePanel.this .table
470: .setShowHorizontalLines(linesHorizontal
471: .isSelected());
472: }
473: });
474: builder.append("", linesHorizontal);
475:
476: final JComboBox resizeModeCombo = new JComboBox(new Object[] {
477: JTable.AUTO_RESIZE_OFF, JTable.AUTO_RESIZE_NEXT_COLUMN,
478: JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS,
479: JTable.AUTO_RESIZE_LAST_COLUMN,
480: JTable.AUTO_RESIZE_ALL_COLUMNS });
481: resizeModeCombo.setSelectedItem(this .table.getAutoResizeMode());
482: resizeModeCombo
483: .setRenderer(new SubstanceDefaultComboBoxRenderer(
484: resizeModeCombo) {
485: @Override
486: public Component getListCellRendererComponent(
487: JList list, Object value, int index,
488: boolean isSelected, boolean cellHasFocus) {
489: JLabel result = (JLabel) super
490: .getListCellRendererComponent(list,
491: value, index, isSelected,
492: cellHasFocus);
493:
494: int iv = (Integer) value;
495: switch (iv) {
496: case JTable.AUTO_RESIZE_OFF:
497: result.setText("off");
498: break;
499: case JTable.AUTO_RESIZE_NEXT_COLUMN:
500: result.setText("next");
501: break;
502: case JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS:
503: result.setText("subsequent");
504: break;
505: case JTable.AUTO_RESIZE_LAST_COLUMN:
506: result.setText("last");
507: break;
508: case JTable.AUTO_RESIZE_ALL_COLUMNS:
509: result.setText("all");
510: break;
511: }
512:
513: return result;
514: }
515: });
516:
517: resizeModeCombo.addActionListener(new ActionListener() {
518: public void actionPerformed(ActionEvent e) {
519: int selected = (Integer) resizeModeCombo
520: .getSelectedItem();
521: TablePanel.this .table.setAutoResizeMode(selected);
522: }
523: });
524:
525: builder.append("Resize mode", resizeModeCombo);
526:
527: final JCheckBox hasRollovers = new JCheckBox(
528: "Has rollover effect");
529: hasRollovers.setSelected(FadeConfigurationManager.getInstance()
530: .fadeAllowed(FadeKind.ROLLOVER, this .table));
531: hasRollovers.addActionListener(new ActionListener() {
532: public void actionPerformed(ActionEvent e) {
533: if (hasRollovers.isSelected()) {
534: FadeConfigurationManager.getInstance().allowFades(
535: FadeKind.ROLLOVER, TablePanel.this .table);
536: } else {
537: FadeConfigurationManager.getInstance()
538: .disallowFades(FadeKind.ROLLOVER,
539: TablePanel.this .table);
540: }
541: }
542: });
543: builder.append("Rollovers", hasRollovers);
544:
545: final JCheckBox hasSelectionAnimations = new JCheckBox(
546: "Has selection effect");
547: hasSelectionAnimations.setSelected(FadeConfigurationManager
548: .getInstance().fadeAllowed(FadeKind.SELECTION,
549: this .table));
550: hasSelectionAnimations.addActionListener(new ActionListener() {
551: public void actionPerformed(ActionEvent e) {
552: if (hasSelectionAnimations.isSelected()) {
553: FadeConfigurationManager.getInstance().allowFades(
554: FadeKind.SELECTION, TablePanel.this .table);
555: } else {
556: FadeConfigurationManager.getInstance()
557: .disallowFades(FadeKind.SELECTION,
558: TablePanel.this .table);
559: }
560: }
561: });
562: builder.append("Selections", hasSelectionAnimations);
563:
564: builder.appendSeparator("Header settings");
565: final JCheckBox useCurrentTheme = new JCheckBox("Global theme");
566: useCurrentTheme.setSelected(true);
567: useCurrentTheme.addActionListener(new ActionListener() {
568: public void actionPerformed(ActionEvent e) {
569: TablePanel.this .table.getTableHeader()
570: .putClientProperty(
571: SubstanceLookAndFeel.THEME_PROPERTY,
572: (useCurrentTheme.isSelected() ? null
573: : "Bottle Green"));
574: TablePanel.this .table.getTableHeader().repaint();
575: }
576: });
577: builder.append("Theme", useCurrentTheme);
578:
579: final JCheckBox isAlwaysActive = new JCheckBox(
580: "Is always active");
581: isAlwaysActive.setSelected(false);
582: isAlwaysActive.addActionListener(new ActionListener() {
583: public void actionPerformed(ActionEvent e) {
584: TablePanel.this .table
585: .getTableHeader()
586: .putClientProperty(
587: SubstanceLookAndFeel.PAINT_ACTIVE_PROPERTY,
588: (isAlwaysActive.isSelected() ? Boolean.TRUE
589: : null));
590: TablePanel.this .table.getTableHeader().repaint();
591: }
592: });
593: builder.append("Active", isAlwaysActive);
594:
595: builder.appendSeparator("Font settings");
596: JButton tahoma12 = new JButton("Tahoma 12");
597: tahoma12.addActionListener(new ActionListener() {
598: public void actionPerformed(ActionEvent e) {
599: table.setFont(new Font("Tahoma", Font.PLAIN, 12));
600: }
601: });
602: builder.append("Set font", tahoma12);
603:
604: JButton tahoma13 = new JButton("Tahoma 13");
605: tahoma13.addActionListener(new ActionListener() {
606: public void actionPerformed(ActionEvent e) {
607: table.setFont(new Font("Tahoma", Font.PLAIN, 13));
608: }
609: });
610: builder.append("Set font", tahoma13);
611:
612: this.controlPanel = builder.getPanel();
613: }
614: }
|