1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
package com.explodingpixels.macwidgets.plaf;
import com.explodingpixels.data.Rating;
import com.explodingpixels.macwidgets.ITunesRatingTableCellRenderer;
import com.explodingpixels.macwidgets.ITunesTableHeaderRenderer;
import com.explodingpixels.macwidgets.MacFontUtils;
import com.explodingpixels.widgets.TableHeaderUtils;
import com.explodingpixels.widgets.TableUtils;
import com.explodingpixels.widgets.WindowUtils;
import javax.swing.BorderFactory;
import javax.swing.CellRendererPane;
import javax.swing.DefaultCellEditor;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.TableCellEditor;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
/**
* A UI delegate that renders an iTunes style table.
* <br/>
* <img src="../../../../../graphics/iTunesTable.png">
* <p/>
* Sorting indicators will be rendered if a
* {@link com.explodingpixels.widgets.TableUtils.SortDelegate} is installed on the associated
* {@link JTable} via the
* {@link TableUtils#makeSortable(javax.swing.JTable, com.explodingpixels.widgets.TableUtils.SortDelegate)}
* method.
*/
public class ITunesTableUI extends BasicTableUI {
private static final Color EVEN_ROW_COLOR = new Color(241, 245, 250);
private static final Color TABLE_GRID_COLOR = new Color(0xd9d9d9);
private static final Color SELECTION_ACTIVE_SELECTION_FOREGROUND_COLOR = Color.WHITE;
private static final Color SELECTION_ACTIVE_SELECTION_BACKGROUND_COLOR = new Color(0x3d80df);
private static final Color SELECTION_INACTIVE_SELECTION_FOREGROUND_COLOR = Color.BLACK;
private static final Color SELECTION_INACTIVE_SELECTION_BACKGROUND_COLOR = new Color(0xc0c0c0);
private static final Color SELECTION_ACTIVE_BOTTOM_BORDER_COLOR = new Color(125, 170, 234);
private static final Color SELECTION_INACTIVE_BOTTOM_BORDER_COLOR = new Color(224, 224, 224);
private static final Color TRANSPARENT_COLOR = new Color(0, 0, 0, 0);
@Override
public void installUI(JComponent c) {
super.installUI(c);
table.remove(rendererPane);
rendererPane = createCustomCellRendererPane();
table.add(rendererPane);
// TODO save defaults.
table.setOpaque(false);
table.setFont(MacFontUtils.ITUNES_FONT);
table.setGridColor(TABLE_GRID_COLOR);
table.setIntercellSpacing(new Dimension(0, 0));
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setDefaultRenderer(new ITunesTableHeaderRenderer(table));
table.setShowHorizontalLines(false);
TableHeaderUtils.makeHeaderFillEmptySpace(table);
TableUtils.makeStriped(table, EVEN_ROW_COLOR);
table.setDefaultRenderer(Rating.class, new ITunesRatingTableCellRenderer());
table.setDefaultEditor(Object.class, createDefaultTableCellEditor());
makeTableActive();
WindowUtils.installWeakWindowFocusListener(table, createWindowFocusListener());
}
@Override
protected void installListeners() {
super.installListeners();
}
private void makeTableActive() {
table.setSelectionForeground(SELECTION_ACTIVE_SELECTION_FOREGROUND_COLOR);
table.setSelectionBackground(SELECTION_ACTIVE_SELECTION_BACKGROUND_COLOR);
}
private void makeTableInactive() {
table.setSelectionForeground(SELECTION_INACTIVE_SELECTION_FOREGROUND_COLOR);
table.setSelectionBackground(SELECTION_INACTIVE_SELECTION_BACKGROUND_COLOR);
}
private TableCellEditor createDefaultTableCellEditor() {
JTextField textField = new JTextField();
textField.setFont(MacFontUtils.ITUNES_FONT);
textField.setBorder(BorderFactory.createLineBorder(Color.BLACK));
return new DefaultCellEditor(textField);
}
private WindowFocusListener createWindowFocusListener() {
return new WindowFocusListener() {
public void windowGainedFocus(WindowEvent e) {
makeTableActive();
}
public void windowLostFocus(WindowEvent e) {
makeTableInactive();
}
};
}
private Border getRowBorder() {
return BorderFactory.createEmptyBorder(0, 5, 0, 5);
}
private Border getSelectedRowBorder() {
return BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(0, 0, 1, 0, getSelectedRowBottomHighlight()),
BorderFactory.createEmptyBorder(1, 5, 0, 5));
}
private Color getSelectedRowBottomHighlight() {
return WindowUtils.isParentWindowFocused(table)
? SELECTION_ACTIVE_BOTTOM_BORDER_COLOR : SELECTION_INACTIVE_BOTTOM_BORDER_COLOR;
}
/**
* Creates a custom {@link CellRendererPane} that sets the renderer component to be non-opqaque
* if the associated row isn't selected. This custom {@code CellRendererPane} is needed because
* a table UI delegate has no prepare renderer like {@link JTable} has.
*/
private CellRendererPane createCustomCellRendererPane() {
return new CellRendererPane() {
@Override
public void paintComponent(Graphics graphics, Component component, Container container,
int x, int y, int w, int h, boolean shouldValidate) {
int rowAtPoint = table.rowAtPoint(new Point(x, y));
boolean isSelected = table.isRowSelected(rowAtPoint);
if (component instanceof JComponent) {
JComponent jComponent = (JComponent) component;
jComponent.setOpaque(isSelected);
jComponent.setBorder(isSelected ? getSelectedRowBorder() : getRowBorder());
jComponent.setBackground(isSelected ? jComponent.getBackground() : TRANSPARENT_COLOR);
}
super.paintComponent(graphics, component, container, x, y, w, h, shouldValidate);
}
};
}
}
|