mirror of https://github.com/weisJ/darklaf.git
weisj
5 years ago
9 changed files with 2008 additions and 28 deletions
@ -1,28 +0,0 @@
|
||||
package com.weis.darklaf.ui; |
||||
|
||||
import com.weis.darklaf.components.border.AdaptiveLineBorder; |
||||
|
||||
import java.awt.*; |
||||
|
||||
/** |
||||
* Table cell border. Prevents content to be shifted when selected. |
||||
* |
||||
* @author Jannis Weis |
||||
* @since 2018 |
||||
*/ |
||||
public class MimaTableCellBorder extends AdaptiveLineBorder { |
||||
|
||||
/** |
||||
* Create new Cell border. |
||||
*/ |
||||
public MimaTableCellBorder() { |
||||
super(1, 1, 1, 1, "Border.line1"); |
||||
} |
||||
|
||||
@Override |
||||
public Insets getBorderInsets(final Component c) { |
||||
var i = super.getBorderInsets(c); |
||||
i.left += 1; |
||||
return i; |
||||
} |
||||
} |
@ -0,0 +1,30 @@
|
||||
package com.weis.darklaf.ui.table; |
||||
|
||||
import com.weis.darklaf.components.border.MutableLineBorder; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.plaf.UIResource; |
||||
import java.awt.*; |
||||
|
||||
public class DarkTableBorder extends MutableLineBorder implements UIResource { |
||||
|
||||
public DarkTableBorder() { |
||||
super(1, 1, 1, 1, null); |
||||
} |
||||
|
||||
@Override |
||||
public void paintBorder(final Component c, final Graphics g, final int x, final int y, |
||||
final int width, final int height) { |
||||
setColor(getBorderColor()); |
||||
super.paintBorder(c, g, x, y, width, height); |
||||
} |
||||
|
||||
protected Color getBorderColor() { |
||||
return UIManager.getColor("TableHeader.borderColor"); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isBorderOpaque() { |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
package com.weis.darklaf.ui.table; |
||||
|
||||
import javax.swing.border.EmptyBorder; |
||||
import javax.swing.plaf.UIResource; |
||||
|
||||
/** |
||||
* Table cell border. Prevents content to be shifted when selected. |
||||
* |
||||
* @author Jannis Weis |
||||
* @since 2018 |
||||
*/ |
||||
public class DarkTableCellBorder extends EmptyBorder implements UIResource { |
||||
|
||||
public DarkTableCellBorder() { |
||||
super(2, 5, 2, 5); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
|
||||
package com.weis.darklaf.ui.table; |
||||
|
||||
import com.weis.darklaf.components.border.MutableLineBorder; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.plaf.UIResource; |
||||
import java.awt.*; |
||||
|
||||
public class DarkTableHeaderBorder extends MutableLineBorder implements UIResource { |
||||
|
||||
public DarkTableHeaderBorder() { |
||||
super(0, 0, 1, 0, null); |
||||
} |
||||
|
||||
@Override |
||||
public void paintBorder(final Component c, final Graphics g, final int x, final int y, |
||||
final int width, final int height) { |
||||
setColor(getBorderColor()); |
||||
super.paintBorder(c, g, x, y, width, height); |
||||
} |
||||
|
||||
protected Color getBorderColor() { |
||||
return UIManager.getColor("TableHeader.borderColor"); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isBorderOpaque() { |
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,26 @@
|
||||
package com.weis.darklaf.ui.table; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.plaf.UIResource; |
||||
import java.awt.*; |
||||
|
||||
public class DarkTableHeaderCorner extends JComponent implements UIResource { |
||||
|
||||
@Override |
||||
protected void paintComponent(final Graphics g) { |
||||
super.paintComponent(g); |
||||
g.setColor(getHeaderBackground()); |
||||
g.fillRect(0, 0, getWidth(), getHeight()); |
||||
|
||||
g.setColor(getBorderColor()); |
||||
g.fillRect(0, getHeight() - 1, getWidth(), 1); |
||||
} |
||||
|
||||
protected Color getBorderColor() { |
||||
return UIManager.getColor("TableHeader.borderColor"); |
||||
} |
||||
|
||||
protected Color getHeaderBackground() { |
||||
return UIManager.getColor("TableHeader.background"); |
||||
} |
||||
} |
@ -0,0 +1,231 @@
|
||||
package com.weis.darklaf.ui.table; |
||||
|
||||
import com.bulenkov.iconloader.util.GraphicsConfig; |
||||
import org.jetbrains.annotations.Contract; |
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.plaf.ComponentUI; |
||||
import javax.swing.plaf.UIResource; |
||||
import javax.swing.table.DefaultTableCellRenderer; |
||||
import javax.swing.table.TableColumn; |
||||
import javax.swing.table.TableColumnModel; |
||||
import java.awt.*; |
||||
|
||||
public class DarkTableHeaderUI extends DarkTableHeaderUIBridge { |
||||
|
||||
private static final int HEADER_HEIGHT = 26; |
||||
|
||||
@NotNull |
||||
@Contract("_ -> new") |
||||
public static ComponentUI createUI(final JComponent c) { |
||||
return new DarkTableHeaderUI(); |
||||
} |
||||
|
||||
@Override |
||||
public void installUI(final JComponent c) { |
||||
super.installUI(c); |
||||
var dim = header.getPreferredSize(); |
||||
header.setPreferredSize(new Dimension(dim.width, Math.max(dim.height, HEADER_HEIGHT))); |
||||
if (header.getDefaultRenderer() instanceof DefaultTableCellRenderer) { |
||||
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) header.getDefaultRenderer(); |
||||
renderer.setHorizontalAlignment(SwingConstants.LEADING); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void installDefaults() { |
||||
super.installDefaults(); |
||||
LookAndFeel.installBorder(header, "TableHeader.border"); |
||||
} |
||||
|
||||
@Override |
||||
protected void uninstallDefaults() { |
||||
super.uninstallDefaults(); |
||||
if (header.getBorder() instanceof UIResource) { |
||||
LookAndFeel.uninstallBorder(header); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void paint(final Graphics g2, final @NotNull JComponent c) { |
||||
final Graphics2D g = (Graphics2D) g2; |
||||
final GraphicsConfig config = new GraphicsConfig(g); |
||||
|
||||
int h = c.getHeight(); |
||||
int w = c.getWidth(); |
||||
|
||||
g.setColor(getHeaderBackground()); |
||||
g.fillRect(0, 0, w, h); |
||||
|
||||
if (header.getColumnModel().getColumnCount() <= 0) { |
||||
return; |
||||
} |
||||
boolean ltr = header.getComponentOrientation().isLeftToRight(); |
||||
|
||||
Rectangle clip = g.getClipBounds(); |
||||
Point left = clip.getLocation(); |
||||
Point right = new Point(clip.x + clip.width - 1, clip.y); |
||||
TableColumnModel cm = header.getColumnModel(); |
||||
int cMin = header.columnAtPoint(ltr ? left : right); |
||||
int cMax = header.columnAtPoint(ltr ? right : left); |
||||
// This should never happen.
|
||||
if (cMin == -1) { |
||||
cMin = 0; |
||||
} |
||||
// If the table does not have enough columns to fill the view we'll get -1.
|
||||
// Replace this with the index of the last column.
|
||||
if (cMax == -1) { |
||||
cMax = cm.getColumnCount() - 1; |
||||
} |
||||
|
||||
Color borderColor = c.getBorder() instanceof DarkTableBorder |
||||
? ((DarkTableBorder) c.getBorder()).getBorderColor() |
||||
: getBorderColor(); |
||||
g.setColor(borderColor); |
||||
|
||||
TableColumn draggedColumn = header.getDraggedColumn(); |
||||
int columnWidth; |
||||
Rectangle cellRect = header.getHeaderRect(ltr ? cMin : cMax); |
||||
TableColumn aColumn; |
||||
if (ltr) { |
||||
for (int column = cMin; column <= cMax; column++) { |
||||
aColumn = cm.getColumn(column); |
||||
columnWidth = aColumn.getWidth(); |
||||
cellRect.width = columnWidth; |
||||
if (aColumn != draggedColumn) { |
||||
paintCell(g, cellRect, column); |
||||
} |
||||
cellRect.x += columnWidth; |
||||
if (column != cMax) { |
||||
g.setColor(borderColor); |
||||
g.fillRect(cellRect.x - 1, 0, 1, h); |
||||
} |
||||
} |
||||
} else { |
||||
for (int column = cMax; column >= cMin; column--) { |
||||
aColumn = cm.getColumn(column); |
||||
columnWidth = aColumn.getWidth(); |
||||
cellRect.width = columnWidth; |
||||
if (aColumn != draggedColumn) { |
||||
paintCell(g, cellRect, column); |
||||
} |
||||
cellRect.x += columnWidth; |
||||
if (column != cMin) { |
||||
g.setColor(borderColor); |
||||
g.fillRect(cellRect.x - 1, 0, 1, h); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Paint the dragged column if we are dragging.
|
||||
if (draggedColumn != null) { |
||||
int draggedColumnIndex = viewIndexForColumn(draggedColumn); |
||||
boolean scrollPaneRtl = isScrollPaneRtl(); |
||||
Rectangle draggedCellRect = header.getHeaderRect(draggedColumnIndex); |
||||
int dist = DarkTableUI.adjustDistance(header.getDraggedDistance(), draggedCellRect, header.getTable()); |
||||
// Draw a gray well in place of the moving column.
|
||||
g.setColor(header.getParent().getBackground()); |
||||
g.fillRect(draggedCellRect.x, draggedCellRect.y, |
||||
draggedCellRect.width, draggedCellRect.height); |
||||
g.setColor(borderColor); |
||||
if (scrollBarVisible()) { |
||||
if (ltr) { |
||||
if (!scrollPaneRtl) { |
||||
g.fillRect(draggedCellRect.x + draggedCellRect.width - 1, draggedCellRect.y, |
||||
1, draggedCellRect.height); |
||||
} else { |
||||
if (draggedColumnIndex != cMax) { |
||||
g.fillRect(draggedCellRect.x + draggedCellRect.width - 1, draggedCellRect.y, |
||||
1, draggedCellRect.height); |
||||
} |
||||
if (draggedColumnIndex == cMin) { |
||||
g.fillRect(draggedCellRect.x, draggedCellRect.y, 1, draggedCellRect.height); |
||||
} |
||||
} |
||||
} else { |
||||
if (!scrollPaneRtl) { |
||||
g.fillRect(draggedCellRect.x + draggedCellRect.width - 1, draggedCellRect.y, |
||||
1, draggedCellRect.height); |
||||
} else { |
||||
if (draggedColumnIndex != cMin) { |
||||
g.fillRect(draggedCellRect.x + draggedCellRect.width - 1, draggedCellRect.y, |
||||
1, draggedCellRect.height); |
||||
} |
||||
if (draggedColumnIndex == cMax) { |
||||
g.fillRect(draggedCellRect.x, draggedCellRect.y, 1, draggedCellRect.height); |
||||
} |
||||
} |
||||
} |
||||
} else { |
||||
if (ltr) { |
||||
if (draggedColumnIndex != cMax) { |
||||
g.fillRect(draggedCellRect.x + draggedCellRect.width - 1, draggedCellRect.y, |
||||
1, draggedCellRect.height); |
||||
} |
||||
} else { |
||||
if (draggedColumnIndex != cMin) { |
||||
g.fillRect(draggedCellRect.x + draggedCellRect.width - 1, draggedCellRect.y, |
||||
1, draggedCellRect.height); |
||||
} |
||||
} |
||||
} |
||||
|
||||
draggedCellRect.x += dist; |
||||
|
||||
// Fill the background.
|
||||
g.setColor(header.getBackground()); |
||||
g.fillRect(draggedCellRect.x, draggedCellRect.y, |
||||
draggedCellRect.width, draggedCellRect.height); |
||||
paintCell(g, draggedCellRect, draggedColumnIndex); |
||||
|
||||
g.setColor(borderColor); |
||||
|
||||
boolean onLeftEdge = ltr ? draggedColumnIndex == cMin : draggedColumnIndex == cMax; |
||||
boolean onRightEdge = ltr ? draggedColumnIndex == cMax : draggedColumnIndex == cMin; |
||||
//left
|
||||
if (dist != 0 || !onLeftEdge) { |
||||
g.fillRect(draggedCellRect.x - 1, draggedCellRect.y, 1, draggedCellRect.height); |
||||
} |
||||
//right
|
||||
if (dist != 0 || !onRightEdge) { |
||||
g.fillRect(draggedCellRect.x + draggedCellRect.width - 1, draggedCellRect.y, |
||||
1, draggedCellRect.height); |
||||
} |
||||
} |
||||
|
||||
// Remove all components in the rendererPane.
|
||||
rendererPane.removeAll(); |
||||
config.restore(); |
||||
} |
||||
|
||||
protected boolean isScrollPaneRtl() { |
||||
if (!isInScrollPane()) return false; |
||||
Container comp = SwingUtilities.getUnwrappedParent(header).getParent(); |
||||
return !comp.getComponentOrientation().isLeftToRight(); |
||||
} |
||||
|
||||
protected boolean scrollBarVisible() { |
||||
Container comp = SwingUtilities.getUnwrappedParent(header); |
||||
if (comp != null) { |
||||
comp = comp.getParent(); |
||||
} |
||||
return comp instanceof JScrollPane && ((JScrollPane) comp).getVerticalScrollBar().isVisible(); |
||||
} |
||||
|
||||
protected boolean isInScrollPane() { |
||||
Container comp = SwingUtilities.getUnwrappedParent(header); |
||||
if (comp != null) { |
||||
comp = comp.getParent(); |
||||
} |
||||
return comp instanceof JScrollPane; |
||||
} |
||||
|
||||
protected Color getBorderColor() { |
||||
return UIManager.getColor("TableHeader.borderColor"); |
||||
} |
||||
|
||||
protected Color getHeaderBackground() { |
||||
return UIManager.getColor("TableHeader.background"); |
||||
} |
||||
} |
@ -0,0 +1,901 @@
|
||||
package com.weis.darklaf.ui.table; |
||||
|
||||
import com.weis.darklaf.util.DarkUIUtil; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import sun.swing.SwingUtilities2; |
||||
import sun.swing.UIAction; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.event.MouseInputListener; |
||||
import javax.swing.plaf.ComponentUI; |
||||
import javax.swing.plaf.basic.BasicTableHeaderUI; |
||||
import javax.swing.table.JTableHeader; |
||||
import javax.swing.table.TableCellRenderer; |
||||
import javax.swing.table.TableColumn; |
||||
import javax.swing.table.TableColumnModel; |
||||
import java.awt.*; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.FocusEvent; |
||||
import java.awt.event.FocusListener; |
||||
import java.awt.event.MouseEvent; |
||||
import java.util.Enumeration; |
||||
|
||||
public class DarkTableHeaderUIBridge extends BasicTableHeaderUI { |
||||
|
||||
protected static Cursor resizeCursor = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR); |
||||
|
||||
//
|
||||
// Instance Variables
|
||||
//
|
||||
protected static FocusListener focusListener = new FocusListener() { |
||||
public void focusGained(@NotNull final FocusEvent e) { |
||||
repaintHeader(e.getSource()); |
||||
} |
||||
|
||||
public void focusLost(@NotNull final FocusEvent e) { |
||||
repaintHeader(e.getSource()); |
||||
} |
||||
|
||||
protected void repaintHeader(final Object source) { |
||||
if (source instanceof JTableHeader) { |
||||
JTableHeader th = (JTableHeader) source; |
||||
DarkTableHeaderUIBridge ui = |
||||
(DarkTableHeaderUIBridge) DarkUIUtil.getUIOfType(th.getUI(), DarkTableHeaderUIBridge.class); |
||||
if (ui == null) { |
||||
return; |
||||
} |
||||
th.repaint(th.getHeaderRect(ui.getSelectedColumnIndex())); |
||||
} |
||||
} |
||||
}; |
||||
// The column header over which the mouse currently is.
|
||||
protected int rolloverColumn = -1; |
||||
// The column that should be highlighted when the table header has the focus.
|
||||
protected int selectedColumnIndex = 0; // Read ONLY via getSelectedColumnIndex!
|
||||
|
||||
/** |
||||
* Returns a new instance of {@code DarkTableHeaderUIBridge}. |
||||
* |
||||
* @param h a component. |
||||
* @return a new instance of {@code DarkTableHeaderUIBridge} |
||||
*/ |
||||
public static ComponentUI createUI(final JComponent h) { |
||||
return new DarkTableHeaderUIBridge(); |
||||
} |
||||
|
||||
//
|
||||
// Factory methods for the Listeners
|
||||
//
|
||||
|
||||
protected static boolean canResize(final TableColumn column, |
||||
final JTableHeader header) { |
||||
return (column != null) && header.getResizingAllowed() |
||||
&& column.getResizable(); |
||||
} |
||||
|
||||
//
|
||||
// The installation/uninstall procedures and support
|
||||
//
|
||||
|
||||
/** |
||||
* Creates the mouse listener for the {@code JTableHeader}. |
||||
* |
||||
* @return the mouse listener for the {@code JTableHeader} |
||||
*/ |
||||
protected MouseInputListener createMouseInputListener() { |
||||
return new DarkTableHeaderUIBridge.MouseInputHandler(); |
||||
} |
||||
|
||||
// Installation
|
||||
|
||||
public void installUI(final JComponent c) { |
||||
super.installUI(c); |
||||
} |
||||
|
||||
/** |
||||
* Initializes JTableHeader properties such as font, foreground, and background. |
||||
* The font, foreground, and background properties are only set if their |
||||
* current value is either null or a UIResource, other properties are set |
||||
* if the current value is null. |
||||
* |
||||
* @see #installUI |
||||
*/ |
||||
protected void installDefaults() { |
||||
LookAndFeel.installColorsAndFont(header, "TableHeader.background", |
||||
"TableHeader.foreground", "TableHeader.font"); |
||||
LookAndFeel.installProperty(header, "opaque", Boolean.TRUE); |
||||
} |
||||
|
||||
/** |
||||
* Attaches listeners to the JTableHeader. |
||||
*/ |
||||
protected void installListeners() { |
||||
mouseInputListener = createMouseInputListener(); |
||||
|
||||
header.addMouseListener(mouseInputListener); |
||||
header.addMouseMotionListener(mouseInputListener); |
||||
header.addFocusListener(focusListener); |
||||
} |
||||
|
||||
// Uninstall methods
|
||||
|
||||
public void uninstallUI(final JComponent c) { |
||||
uninstallDefaults(); |
||||
uninstallListeners(); |
||||
uninstallKeyboardActions(); |
||||
|
||||
header.remove(rendererPane); |
||||
rendererPane = null; |
||||
header = null; |
||||
} |
||||
|
||||
/** |
||||
* Uninstalls default properties |
||||
*/ |
||||
protected void uninstallDefaults() { |
||||
} |
||||
|
||||
/** |
||||
* Unregisters listeners. |
||||
*/ |
||||
protected void uninstallListeners() { |
||||
header.removeMouseListener(mouseInputListener); |
||||
header.removeMouseMotionListener(mouseInputListener); |
||||
header.removeFocusListener(focusListener); |
||||
|
||||
mouseInputListener = null; |
||||
} |
||||
|
||||
/** |
||||
* Unregisters default key actions. |
||||
*/ |
||||
protected void uninstallKeyboardActions() { |
||||
SwingUtilities.replaceUIInputMap(header, JComponent.WHEN_FOCUSED, null); |
||||
SwingUtilities.replaceUIActionMap(header, null); |
||||
} |
||||
|
||||
//
|
||||
// Support for mouse rollover
|
||||
//
|
||||
|
||||
/** |
||||
* Returns the index of the column header over which the mouse |
||||
* currently is. When the mouse is not over the table header, |
||||
* -1 is returned. |
||||
* |
||||
* @return the index of the current rollover column |
||||
* @see #rolloverColumnUpdated(int, int) |
||||
* @since 1.6 |
||||
*/ |
||||
protected int getRolloverColumn() { |
||||
return rolloverColumn; |
||||
} |
||||
|
||||
/** |
||||
* This method gets called every time when a rollover column in the table |
||||
* header is updated. Every look and feel that supports a rollover effect |
||||
* in a table header should override this method and repaint the header. |
||||
* |
||||
* @param oldColumn the index of the previous rollover column or -1 if the |
||||
* mouse was not over a column |
||||
* @param newColumn the index of the new rollover column or -1 if the mouse |
||||
* is not over a column |
||||
* @see #getRolloverColumn() |
||||
* @see JTableHeader#getHeaderRect(int) |
||||
* @since 1.6 |
||||
*/ |
||||
protected void rolloverColumnUpdated(final int oldColumn, final int newColumn) { |
||||
} |
||||
|
||||
protected void updateRolloverColumn(final MouseEvent e) { |
||||
if (header.getDraggedColumn() == null && |
||||
header.contains(e.getPoint())) { |
||||
|
||||
int col = header.columnAtPoint(e.getPoint()); |
||||
if (col != rolloverColumn) { |
||||
int oldRolloverColumn = rolloverColumn; |
||||
rolloverColumn = col; |
||||
rolloverColumnUpdated(oldRolloverColumn, rolloverColumn); |
||||
} |
||||
} |
||||
} |
||||
|
||||
//
|
||||
// Support for keyboard and mouse access
|
||||
//
|
||||
protected int selectNextColumn(final boolean doIt) { |
||||
int newIndex = getSelectedColumnIndex(); |
||||
if (newIndex < header.getColumnModel().getColumnCount() - 1) { |
||||
newIndex++; |
||||
if (doIt) { |
||||
selectColumn(newIndex); |
||||
} |
||||
} |
||||
return newIndex; |
||||
} |
||||
|
||||
protected int selectPreviousColumn(final boolean doIt) { |
||||
int newIndex = getSelectedColumnIndex(); |
||||
if (newIndex > 0) { |
||||
newIndex--; |
||||
if (doIt) { |
||||
selectColumn(newIndex); |
||||
} |
||||
} |
||||
return newIndex; |
||||
} |
||||
|
||||
/** |
||||
* Selects the specified column in the table header. Repaints the |
||||
* affected header cells and makes sure the newly selected one is visible. |
||||
*/ |
||||
void selectColumn(final int newColIndex) { |
||||
selectColumn(newColIndex, true); |
||||
} |
||||
|
||||
void selectColumn(final int newColIndex, final boolean doScroll) { |
||||
Rectangle repaintRect = header.getHeaderRect(selectedColumnIndex); |
||||
header.repaint(repaintRect); |
||||
selectedColumnIndex = newColIndex; |
||||
repaintRect = header.getHeaderRect(newColIndex); |
||||
header.repaint(repaintRect); |
||||
if (doScroll) { |
||||
scrollToColumn(newColIndex); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
/** |
||||
* Used by selectColumn to scroll horizontally, if necessary, |
||||
* to ensure that the newly selected column is visible. |
||||
*/ |
||||
protected void scrollToColumn(final int col) { |
||||
Container container; |
||||
JTable table; |
||||
|
||||
//Test whether the header is in a scroll pane and has a table.
|
||||
if ((header.getParent() == null) || |
||||
((container = header.getParent().getParent()) == null) || |
||||
!(container instanceof JScrollPane) || |
||||
((table = header.getTable()) == null)) { |
||||
return; |
||||
} |
||||
|
||||
//Now scroll, if necessary.
|
||||
Rectangle vis = table.getVisibleRect(); |
||||
Rectangle cellBounds = table.getCellRect(0, col, true); |
||||
vis.x = cellBounds.x; |
||||
vis.width = cellBounds.width; |
||||
table.scrollRectToVisible(vis); |
||||
} |
||||
|
||||
protected int getSelectedColumnIndex() { |
||||
int numCols = header.getColumnModel().getColumnCount(); |
||||
if (selectedColumnIndex >= numCols && numCols > 0) { |
||||
selectedColumnIndex = numCols - 1; |
||||
} |
||||
return selectedColumnIndex; |
||||
} |
||||
|
||||
protected int changeColumnWidth(final TableColumn resizingColumn, |
||||
final JTableHeader th, |
||||
final int oldWidth, final int newWidth) { |
||||
resizingColumn.setWidth(newWidth); |
||||
|
||||
Container container; |
||||
JTable table; |
||||
|
||||
if ((th.getParent() == null) || |
||||
((container = th.getParent().getParent()) == null) || |
||||
!(container instanceof JScrollPane) || |
||||
((table = th.getTable()) == null)) { |
||||
return 0; |
||||
} |
||||
|
||||
if (!container.getComponentOrientation().isLeftToRight() && |
||||
!th.getComponentOrientation().isLeftToRight()) { |
||||
JViewport viewport = ((JScrollPane) container).getViewport(); |
||||
int viewportWidth = viewport.getWidth(); |
||||
int diff = newWidth - oldWidth; |
||||
int newHeaderWidth = table.getWidth() + diff; |
||||
|
||||
/* Resize a table */ |
||||
Dimension tableSize = table.getSize(); |
||||
tableSize.width += diff; |
||||
table.setSize(tableSize); |
||||
|
||||
/* If this table is in AUTO_RESIZE_OFF mode and |
||||
* has a horizontal scrollbar, we need to update |
||||
* a view's position. |
||||
*/ |
||||
if ((newHeaderWidth >= viewportWidth) && |
||||
(table.getAutoResizeMode() == JTable.AUTO_RESIZE_OFF)) { |
||||
Point p = viewport.getViewPosition(); |
||||
p.x = Math.max(0, Math.min(newHeaderWidth - viewportWidth, |
||||
p.x + diff)); |
||||
viewport.setViewPosition(p); |
||||
return diff; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
/** |
||||
* Returns the baseline. |
||||
* |
||||
* @throws NullPointerException {@inheritDoc} |
||||
* @throws IllegalArgumentException {@inheritDoc} |
||||
* @see javax.swing.JComponent#getBaseline(int, int) |
||||
* @since 1.6 |
||||
*/ |
||||
public int getBaseline(final JComponent c, final int width, final int height) { |
||||
super.getBaseline(c, width, height); |
||||
int baseline = -1; |
||||
TableColumnModel columnModel = header.getColumnModel(); |
||||
for (int column = 0; column < columnModel.getColumnCount(); |
||||
column++) { |
||||
TableColumn aColumn = columnModel.getColumn(column); |
||||
Component comp = getHeaderRenderer(column); |
||||
Dimension pref = comp.getPreferredSize(); |
||||
int columnBaseline = comp.getBaseline(pref.width, height); |
||||
if (columnBaseline >= 0) { |
||||
if (baseline == -1) { |
||||
baseline = columnBaseline; |
||||
} else if (baseline != columnBaseline) { |
||||
baseline = -1; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
return baseline; |
||||
} |
||||
|
||||
//
|
||||
// Baseline
|
||||
//
|
||||
|
||||
public void paint(final Graphics g, final JComponent c) { |
||||
if (header.getColumnModel().getColumnCount() <= 0) { |
||||
return; |
||||
} |
||||
boolean ltr = header.getComponentOrientation().isLeftToRight(); |
||||
|
||||
Rectangle clip = g.getClipBounds(); |
||||
Point left = clip.getLocation(); |
||||
Point right = new Point(clip.x + clip.width - 1, clip.y); |
||||
TableColumnModel cm = header.getColumnModel(); |
||||
int cMin = header.columnAtPoint(ltr ? left : right); |
||||
int cMax = header.columnAtPoint(ltr ? right : left); |
||||
// This should never happen.
|
||||
if (cMin == -1) { |
||||
cMin = 0; |
||||
} |
||||
// If the table does not have enough columns to fill the view we'll get -1.
|
||||
// Replace this with the index of the last column.
|
||||
if (cMax == -1) { |
||||
cMax = cm.getColumnCount() - 1; |
||||
} |
||||
|
||||
TableColumn draggedColumn = header.getDraggedColumn(); |
||||
int columnWidth; |
||||
Rectangle cellRect = header.getHeaderRect(ltr ? cMin : cMax); |
||||
TableColumn aColumn; |
||||
if (ltr) { |
||||
for (int column = cMin; column <= cMax; column++) { |
||||
aColumn = cm.getColumn(column); |
||||
columnWidth = aColumn.getWidth(); |
||||
cellRect.width = columnWidth; |
||||
if (aColumn != draggedColumn) { |
||||
paintCell(g, cellRect, column); |
||||
} |
||||
cellRect.x += columnWidth; |
||||
} |
||||
} else { |
||||
for (int column = cMax; column >= cMin; column--) { |
||||
aColumn = cm.getColumn(column); |
||||
columnWidth = aColumn.getWidth(); |
||||
cellRect.width = columnWidth; |
||||
if (aColumn != draggedColumn) { |
||||
paintCell(g, cellRect, column); |
||||
} |
||||
cellRect.x += columnWidth; |
||||
} |
||||
} |
||||
|
||||
// Paint the dragged column if we are dragging.
|
||||
if (draggedColumn != null) { |
||||
int draggedColumnIndex = viewIndexForColumn(draggedColumn); |
||||
Rectangle draggedCellRect = header.getHeaderRect(draggedColumnIndex); |
||||
|
||||
// Draw a gray well in place of the moving column.
|
||||
g.setColor(header.getParent().getBackground()); |
||||
g.fillRect(draggedCellRect.x, draggedCellRect.y, |
||||
draggedCellRect.width, draggedCellRect.height); |
||||
|
||||
draggedCellRect.x += header.getDraggedDistance(); |
||||
|
||||
// Fill the background.
|
||||
g.setColor(header.getBackground()); |
||||
g.fillRect(draggedCellRect.x, draggedCellRect.y, |
||||
draggedCellRect.width, draggedCellRect.height); |
||||
|
||||
paintCell(g, draggedCellRect, draggedColumnIndex); |
||||
} |
||||
|
||||
// Remove all components in the rendererPane.
|
||||
rendererPane.removeAll(); |
||||
} |
||||
|
||||
//
|
||||
// Paint Methods and support
|
||||
//
|
||||
|
||||
protected Component getHeaderRenderer(final int columnIndex) { |
||||
TableColumn aColumn = header.getColumnModel().getColumn(columnIndex); |
||||
TableCellRenderer renderer = aColumn.getHeaderRenderer(); |
||||
if (renderer == null) { |
||||
renderer = header.getDefaultRenderer(); |
||||
} |
||||
|
||||
boolean hasFocus = !header.isPaintingForPrint() |
||||
&& (columnIndex == getSelectedColumnIndex()) |
||||
&& header.hasFocus(); |
||||
return renderer.getTableCellRendererComponent(header.getTable(), |
||||
aColumn.getHeaderValue(), |
||||
false, hasFocus, |
||||
-1, columnIndex); |
||||
} |
||||
|
||||
protected void paintCell(final Graphics g, final Rectangle cellRect, final int columnIndex) { |
||||
Component component = getHeaderRenderer(columnIndex); |
||||
rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y, |
||||
cellRect.width, cellRect.height, true); |
||||
} |
||||
|
||||
protected int viewIndexForColumn(final TableColumn aColumn) { |
||||
TableColumnModel cm = header.getColumnModel(); |
||||
for (int column = 0; column < cm.getColumnCount(); column++) { |
||||
if (cm.getColumn(column) == aColumn) { |
||||
return column; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
protected int getHeaderHeight() { |
||||
int height = 0; |
||||
boolean accomodatedDefault = false; |
||||
TableColumnModel columnModel = header.getColumnModel(); |
||||
for (int column = 0; column < columnModel.getColumnCount(); column++) { |
||||
TableColumn aColumn = columnModel.getColumn(column); |
||||
boolean isDefault = (aColumn.getHeaderRenderer() == null); |
||||
|
||||
if (!isDefault || !accomodatedDefault) { |
||||
Component comp = getHeaderRenderer(column); |
||||
int rendererHeight = comp.getPreferredSize().height; |
||||
height = Math.max(height, rendererHeight); |
||||
|
||||
// Configuring the header renderer to calculate its preferred size
|
||||
// is expensive. Optimise this by assuming the default renderer
|
||||
// always has the same height as the first non-zero height that
|
||||
// it returns for a non-null/non-empty value.
|
||||
if (isDefault && rendererHeight > 0) { |
||||
Object headerValue = aColumn.getHeaderValue(); |
||||
if (headerValue != null) { |
||||
headerValue = headerValue.toString(); |
||||
|
||||
if (headerValue != null && !headerValue.equals("")) { |
||||
accomodatedDefault = true; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return height; |
||||
} |
||||
|
||||
//
|
||||
// Size Methods
|
||||
//
|
||||
|
||||
protected Dimension createHeaderSize(long width) { |
||||
// None of the callers include the intercell spacing, do it here.
|
||||
if (width > Integer.MAX_VALUE) { |
||||
width = Integer.MAX_VALUE; |
||||
} |
||||
return new Dimension((int) width, getHeaderHeight()); |
||||
} |
||||
|
||||
/** |
||||
* Return the minimum size of the header. The minimum width is the sum |
||||
* of the minimum widths of each column (plus inter-cell spacing). |
||||
*/ |
||||
public Dimension getMinimumSize(final JComponent c) { |
||||
long width = 0; |
||||
Enumeration<TableColumn> enumeration = header.getColumnModel().getColumns(); |
||||
while (enumeration.hasMoreElements()) { |
||||
TableColumn aColumn = enumeration.nextElement(); |
||||
width = width + aColumn.getMinWidth(); |
||||
} |
||||
return createHeaderSize(width); |
||||
} |
||||
|
||||
/** |
||||
* Return the preferred size of the header. The preferred height is the |
||||
* maximum of the preferred heights of all of the components provided |
||||
* by the header renderers. The preferred width is the sum of the |
||||
* preferred widths of each column (plus inter-cell spacing). |
||||
*/ |
||||
public Dimension getPreferredSize(final JComponent c) { |
||||
long width = 0; |
||||
Enumeration<TableColumn> enumeration = header.getColumnModel().getColumns(); |
||||
while (enumeration.hasMoreElements()) { |
||||
TableColumn aColumn = enumeration.nextElement(); |
||||
width = width + aColumn.getPreferredWidth(); |
||||
} |
||||
return createHeaderSize(width); |
||||
} |
||||
|
||||
/** |
||||
* Return the maximum size of the header. The maximum width is the sum |
||||
* of the maximum widths of each column (plus inter-cell spacing). |
||||
*/ |
||||
public Dimension getMaximumSize(final JComponent c) { |
||||
long width = 0; |
||||
Enumeration<TableColumn> enumeration = header.getColumnModel().getColumns(); |
||||
while (enumeration.hasMoreElements()) { |
||||
TableColumn aColumn = enumeration.nextElement(); |
||||
width = width + aColumn.getMaxWidth(); |
||||
} |
||||
return createHeaderSize(width); |
||||
} |
||||
|
||||
protected static class Actions extends UIAction { |
||||
public static final String TOGGLE_SORT_ORDER = |
||||
"toggleSortOrder"; |
||||
public static final String SELECT_COLUMN_TO_LEFT = |
||||
"selectColumnToLeft"; |
||||
public static final String SELECT_COLUMN_TO_RIGHT = |
||||
"selectColumnToRight"; |
||||
public static final String MOVE_COLUMN_LEFT = |
||||
"moveColumnLeft"; |
||||
public static final String MOVE_COLUMN_RIGHT = |
||||
"moveColumnRight"; |
||||
public static final String RESIZE_LEFT = |
||||
"resizeLeft"; |
||||
public static final String RESIZE_RIGHT = |
||||
"resizeRight"; |
||||
public static final String FOCUS_TABLE = |
||||
"focusTable"; |
||||
|
||||
public Actions(final String name) { |
||||
super(name); |
||||
} |
||||
|
||||
@Override |
||||
public boolean accept(final Object sender) { |
||||
if (sender instanceof JTableHeader) { |
||||
JTableHeader th = (JTableHeader) sender; |
||||
TableColumnModel cm = th.getColumnModel(); |
||||
if (cm.getColumnCount() <= 0) { |
||||
return false; |
||||
} |
||||
|
||||
String key = getName(); |
||||
DarkTableHeaderUIBridge ui = |
||||
(DarkTableHeaderUIBridge) DarkUIUtil.getUIOfType(th.getUI(), DarkTableHeaderUIBridge.class); |
||||
if (ui != null) { |
||||
if (key == MOVE_COLUMN_LEFT) { |
||||
return th.getReorderingAllowed() |
||||
&& maybeMoveColumn(true, th, ui, false); |
||||
} else if (key == MOVE_COLUMN_RIGHT) { |
||||
return th.getReorderingAllowed() |
||||
&& maybeMoveColumn(false, th, ui, false); |
||||
} else if (key == RESIZE_LEFT || |
||||
key == RESIZE_RIGHT) { |
||||
return canResize(cm.getColumn(ui.getSelectedColumnIndex()), th); |
||||
} else if (key == FOCUS_TABLE) { |
||||
return (th.getTable() != null); |
||||
} |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
public void actionPerformed(final ActionEvent e) { |
||||
JTableHeader th = (JTableHeader) e.getSource(); |
||||
DarkTableHeaderUIBridge ui = |
||||
(DarkTableHeaderUIBridge) DarkUIUtil.getUIOfType(th.getUI(), DarkTableHeaderUIBridge.class); |
||||
if (ui == null) { |
||||
return; |
||||
} |
||||
|
||||
String name = getName(); |
||||
if (TOGGLE_SORT_ORDER == name) { |
||||
JTable table = th.getTable(); |
||||
RowSorter<?> sorter = table == null ? null : table.getRowSorter(); |
||||
if (sorter != null) { |
||||
int columnIndex = ui.getSelectedColumnIndex(); |
||||
columnIndex = table.convertColumnIndexToModel( |
||||
columnIndex); |
||||
sorter.toggleSortOrder(columnIndex); |
||||
} |
||||
} else if (SELECT_COLUMN_TO_LEFT == name) { |
||||
if (th.getComponentOrientation().isLeftToRight()) { |
||||
ui.selectPreviousColumn(true); |
||||
} else { |
||||
ui.selectNextColumn(true); |
||||
} |
||||
} else if (SELECT_COLUMN_TO_RIGHT == name) { |
||||
if (th.getComponentOrientation().isLeftToRight()) { |
||||
ui.selectNextColumn(true); |
||||
} else { |
||||
ui.selectPreviousColumn(true); |
||||
} |
||||
} else if (MOVE_COLUMN_LEFT == name) { |
||||
moveColumn(true, th, ui); |
||||
} else if (MOVE_COLUMN_RIGHT == name) { |
||||
moveColumn(false, th, ui); |
||||
} else if (RESIZE_LEFT == name) { |
||||
resize(true, th, ui); |
||||
} else if (RESIZE_RIGHT == name) { |
||||
resize(false, th, ui); |
||||
} else if (FOCUS_TABLE == name) { |
||||
JTable table = th.getTable(); |
||||
if (table != null) { |
||||
table.requestFocusInWindow(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected void moveColumn(final boolean leftArrow, final JTableHeader th, |
||||
final DarkTableHeaderUIBridge ui) { |
||||
maybeMoveColumn(leftArrow, th, ui, true); |
||||
} |
||||
|
||||
protected boolean maybeMoveColumn(final boolean leftArrow, final JTableHeader th, |
||||
final DarkTableHeaderUIBridge ui, final boolean doIt) { |
||||
int oldIndex = ui.getSelectedColumnIndex(); |
||||
int newIndex; |
||||
|
||||
if (th.getComponentOrientation().isLeftToRight()) { |
||||
newIndex = leftArrow ? ui.selectPreviousColumn(doIt) |
||||
: ui.selectNextColumn(doIt); |
||||
} else { |
||||
newIndex = leftArrow ? ui.selectNextColumn(doIt) |
||||
: ui.selectPreviousColumn(doIt); |
||||
} |
||||
|
||||
if (newIndex != oldIndex) { |
||||
if (doIt) { |
||||
th.getColumnModel().moveColumn(oldIndex, newIndex); |
||||
} else { |
||||
return true; // we'd do the move if asked
|
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
protected void resize(final boolean leftArrow, final JTableHeader th, |
||||
final DarkTableHeaderUIBridge ui) { |
||||
int columnIndex = ui.getSelectedColumnIndex(); |
||||
TableColumn resizingColumn = |
||||
th.getColumnModel().getColumn(columnIndex); |
||||
|
||||
th.setResizingColumn(resizingColumn); |
||||
int oldWidth = resizingColumn.getWidth(); |
||||
int newWidth = oldWidth; |
||||
|
||||
if (th.getComponentOrientation().isLeftToRight()) { |
||||
newWidth = newWidth + (leftArrow ? -1 : 1); |
||||
} else { |
||||
newWidth = newWidth + (leftArrow ? 1 : -1); |
||||
} |
||||
|
||||
ui.changeColumnWidth(resizingColumn, th, oldWidth, newWidth); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This class should be treated as a "protected" inner class. |
||||
* Instantiate it only within subclasses of {@code DarkTableHeaderUIBridge}. |
||||
*/ |
||||
public class MouseInputHandler implements MouseInputListener { |
||||
|
||||
protected int mouseXOffset; |
||||
protected Cursor otherCursor = resizeCursor; |
||||
|
||||
public void mouseClicked(final MouseEvent e) { |
||||
if (!header.isEnabled()) { |
||||
return; |
||||
} |
||||
if (e.getClickCount() % 2 == 1 && |
||||
SwingUtilities.isLeftMouseButton(e)) { |
||||
JTable table = header.getTable(); |
||||
RowSorter<?> sorter; |
||||
if (table != null && (sorter = table.getRowSorter()) != null) { |
||||
int columnIndex = header.columnAtPoint(e.getPoint()); |
||||
if (columnIndex != -1) { |
||||
columnIndex = table.convertColumnIndexToModel( |
||||
columnIndex); |
||||
sorter.toggleSortOrder(columnIndex); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected TableColumn getResizingColumn(final Point p) { |
||||
return getResizingColumn(p, header.columnAtPoint(p)); |
||||
} |
||||
|
||||
protected TableColumn getResizingColumn(final Point p, final int column) { |
||||
if (column == -1) { |
||||
return null; |
||||
} |
||||
Rectangle r = header.getHeaderRect(column); |
||||
r.grow(-3, 0); |
||||
if (r.contains(p)) { |
||||
return null; |
||||
} |
||||
int midPoint = r.x + r.width / 2; |
||||
int columnIndex; |
||||
if (header.getComponentOrientation().isLeftToRight()) { |
||||
columnIndex = (p.x < midPoint) ? column - 1 : column; |
||||
} else { |
||||
columnIndex = (p.x < midPoint) ? column : column - 1; |
||||
} |
||||
if (columnIndex == -1) { |
||||
return null; |
||||
} |
||||
return header.getColumnModel().getColumn(columnIndex); |
||||
} |
||||
|
||||
public void mousePressed(final MouseEvent e) { |
||||
if (!header.isEnabled()) { |
||||
return; |
||||
} |
||||
header.setDraggedColumn(null); |
||||
header.setResizingColumn(null); |
||||
header.setDraggedDistance(0); |
||||
|
||||
Point p = e.getPoint(); |
||||
|
||||
// First find which header cell was hit
|
||||
TableColumnModel columnModel = header.getColumnModel(); |
||||
int index = header.columnAtPoint(p); |
||||
|
||||
if (index != -1) { |
||||
// The last 3 pixels + 3 pixels of next column are for resizing
|
||||
TableColumn resizingColumn = getResizingColumn(p, index); |
||||
if (canResize(resizingColumn, header)) { |
||||
header.setResizingColumn(resizingColumn); |
||||
if (header.getComponentOrientation().isLeftToRight()) { |
||||
mouseXOffset = p.x - resizingColumn.getWidth(); |
||||
} else { |
||||
mouseXOffset = p.x + resizingColumn.getWidth(); |
||||
} |
||||
} else if (header.getReorderingAllowed()) { |
||||
TableColumn hitColumn = columnModel.getColumn(index); |
||||
header.setDraggedColumn(hitColumn); |
||||
mouseXOffset = p.x; |
||||
} |
||||
} |
||||
|
||||
if (header.getReorderingAllowed()) { |
||||
int oldRolloverColumn = rolloverColumn; |
||||
rolloverColumn = -1; |
||||
rolloverColumnUpdated(oldRolloverColumn, rolloverColumn); |
||||
} |
||||
} |
||||
|
||||
protected void swapCursor() { |
||||
Cursor tmp = header.getCursor(); |
||||
header.setCursor(otherCursor); |
||||
otherCursor = tmp; |
||||
} |
||||
|
||||
public void mouseMoved(final MouseEvent e) { |
||||
if (!header.isEnabled()) { |
||||
return; |
||||
} |
||||
if (canResize(getResizingColumn(e.getPoint()), header) != |
||||
(header.getCursor() == resizeCursor)) { |
||||
swapCursor(); |
||||
} |
||||
updateRolloverColumn(e); |
||||
} |
||||
|
||||
public void mouseDragged(final MouseEvent e) { |
||||
if (!header.isEnabled()) { |
||||
return; |
||||
} |
||||
int mouseX = e.getX(); |
||||
|
||||
TableColumn resizingColumn = header.getResizingColumn(); |
||||
TableColumn draggedColumn = header.getDraggedColumn(); |
||||
|
||||
boolean headerLeftToRight = header.getComponentOrientation().isLeftToRight(); |
||||
|
||||
if (resizingColumn != null) { |
||||
int oldWidth = resizingColumn.getWidth(); |
||||
int newWidth; |
||||
if (headerLeftToRight) { |
||||
newWidth = mouseX - mouseXOffset; |
||||
} else { |
||||
newWidth = mouseXOffset - mouseX; |
||||
} |
||||
mouseXOffset += changeColumnWidth(resizingColumn, header, |
||||
oldWidth, newWidth); |
||||
} else if (draggedColumn != null) { |
||||
TableColumnModel cm = header.getColumnModel(); |
||||
int draggedDistance = mouseX - mouseXOffset; |
||||
int direction = (draggedDistance < 0) ? -1 : 1; |
||||
int columnIndex = viewIndexForColumn(draggedColumn); |
||||
int newColumnIndex = columnIndex + (headerLeftToRight ? direction : -direction); |
||||
if (0 <= newColumnIndex && newColumnIndex < cm.getColumnCount()) { |
||||
int width = cm.getColumn(newColumnIndex).getWidth(); |
||||
if (Math.abs(draggedDistance) > (width / 2)) { |
||||
|
||||
mouseXOffset = mouseXOffset + direction * width; |
||||
header.setDraggedDistance(draggedDistance - direction * width); |
||||
|
||||
//Cache the selected column.
|
||||
int selectedIndex = SwingUtilities2.convertColumnIndexToModel(header.getColumnModel(), |
||||
getSelectedColumnIndex()); |
||||
|
||||
//Now do the move.
|
||||
cm.moveColumn(columnIndex, newColumnIndex); |
||||
|
||||
//Update the selected index.
|
||||
selectColumn(SwingUtilities2.convertColumnIndexToView(header.getColumnModel(), selectedIndex), |
||||
false); |
||||
|
||||
return; |
||||
} |
||||
} |
||||
setDraggedDistance(draggedDistance, columnIndex); |
||||
} |
||||
|
||||
updateRolloverColumn(e); |
||||
} |
||||
|
||||
public void mouseReleased(final MouseEvent e) { |
||||
if (!header.isEnabled()) { |
||||
return; |
||||
} |
||||
setDraggedDistance(0, viewIndexForColumn(header.getDraggedColumn())); |
||||
|
||||
header.setResizingColumn(null); |
||||
header.setDraggedColumn(null); |
||||
|
||||
updateRolloverColumn(e); |
||||
} |
||||
|
||||
public void mouseEntered(final MouseEvent e) { |
||||
if (!header.isEnabled()) { |
||||
return; |
||||
} |
||||
updateRolloverColumn(e); |
||||
} |
||||
|
||||
public void mouseExited(final MouseEvent e) { |
||||
if (!header.isEnabled()) { |
||||
return; |
||||
} |
||||
int oldRolloverColumn = rolloverColumn; |
||||
rolloverColumn = -1; |
||||
rolloverColumnUpdated(oldRolloverColumn, rolloverColumn); |
||||
} |
||||
//
|
||||
// Protected & protected Methods
|
||||
//
|
||||
|
||||
protected void setDraggedDistance(final int draggedDistance, final int column) { |
||||
header.setDraggedDistance(draggedDistance); |
||||
if (column != -1) { |
||||
header.getColumnModel().moveColumn(column, column); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,341 @@
|
||||
package com.weis.darklaf.ui.table; |
||||
|
||||
import org.jetbrains.annotations.Contract; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import sun.swing.SwingUtilities2; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.plaf.ComponentUI; |
||||
import javax.swing.plaf.UIResource; |
||||
import javax.swing.table.TableCellRenderer; |
||||
import javax.swing.table.TableColumn; |
||||
import javax.swing.table.TableColumnModel; |
||||
import java.awt.*; |
||||
import java.awt.event.FocusEvent; |
||||
import java.awt.event.FocusListener; |
||||
|
||||
public class DarkTableUI extends DarkTableUIBridge { |
||||
|
||||
private static final int ROW_HEIGHT = 22; |
||||
private final FocusListener focusListener = new FocusListener() { |
||||
@Override |
||||
public void focusGained(final FocusEvent e) { |
||||
var bg = table.getSelectionBackground(); |
||||
if (bg instanceof UIResource) { |
||||
table.setSelectionBackground(UIManager.getColor("Table.focusSelectionBackground")); |
||||
} |
||||
table.repaint(); |
||||
} |
||||
|
||||
@Override |
||||
public void focusLost(final FocusEvent e) { |
||||
var bg = table.getSelectionBackground(); |
||||
if (bg instanceof UIResource) { |
||||
table.setSelectionBackground(UIManager.getColor("Table.selectionBackground")); |
||||
} |
||||
table.repaint(); |
||||
} |
||||
}; |
||||
|
||||
@NotNull |
||||
@Contract("_ -> new") |
||||
public static ComponentUI createUI(final JComponent c) { |
||||
return new DarkTableUI(); |
||||
} |
||||
|
||||
protected static int adjustDistance(final int distance, @NotNull final Rectangle rect, |
||||
@NotNull final JTable comp) { |
||||
int dist = distance; |
||||
int min = 0; |
||||
int max = comp.getX() + comp.getWidth(); |
||||
if (rect.x + dist <= min) { |
||||
dist = min - rect.x; |
||||
} |
||||
if (rect.x + rect.width + dist >= max) { |
||||
dist = max - rect.x - rect.width; |
||||
} |
||||
return dist; |
||||
} |
||||
|
||||
@Override |
||||
protected void installDefaults() { |
||||
super.installDefaults(); |
||||
table.setRowHeight(ROW_HEIGHT); |
||||
} |
||||
|
||||
@Override |
||||
protected void installListeners() { |
||||
super.installListeners(); |
||||
table.addFocusListener(focusListener); |
||||
} |
||||
|
||||
@Override |
||||
protected void uninstallListeners() { |
||||
super.uninstallListeners(); |
||||
table.removeFocusListener(focusListener); |
||||
} |
||||
|
||||
@Override |
||||
protected void paintDraggedArea(@NotNull final Graphics g, final int rMin, final int rMax, |
||||
final int cMin, final int cMax, |
||||
final TableColumn draggedColumn, final int distance) { |
||||
int draggedColumnIndex = viewIndexForColumn(draggedColumn); |
||||
|
||||
Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true); |
||||
Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true); |
||||
|
||||
Rectangle vacatedColumnRect = minCell.union(maxCell); |
||||
|
||||
int dist = adjustDistance(distance, vacatedColumnRect, table); |
||||
|
||||
// Paint a gray well in place of the moving column.
|
||||
g.setColor(table.getParent().getBackground()); |
||||
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y, |
||||
vacatedColumnRect.width - 1, vacatedColumnRect.height); |
||||
|
||||
|
||||
// Move to the where the cell has been dragged.
|
||||
vacatedColumnRect.x += dist; |
||||
|
||||
boolean scrollVisible = scrollBarVisible(); |
||||
boolean drawBottomBorder = !table.getShowHorizontalLines() && !scrollVisible; |
||||
boolean ltr = table.getComponentOrientation().isLeftToRight(); |
||||
|
||||
// Fill the background.
|
||||
g.setColor(table.getBackground()); |
||||
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y, |
||||
vacatedColumnRect.width, vacatedColumnRect.height); |
||||
|
||||
|
||||
// Paint the vertical grid lines if necessary.
|
||||
if (table.getShowVerticalLines()) { |
||||
g.setColor(table.getGridColor()); |
||||
int x1 = vacatedColumnRect.x; |
||||
int y1 = vacatedColumnRect.y; |
||||
int x2 = x1 + vacatedColumnRect.width - 1; |
||||
int y2 = y1 + vacatedColumnRect.height - 1; |
||||
|
||||
boolean onLeftEdge = ltr ? draggedColumnIndex == cMin : draggedColumnIndex == cMax; |
||||
boolean onRightEdge = ltr ? draggedColumnIndex == cMax : draggedColumnIndex == cMin; |
||||
if (scrollBarVisible()) { |
||||
if (isScrollPaneRtl()) { |
||||
onLeftEdge = false; |
||||
} else { |
||||
onRightEdge = false; |
||||
} |
||||
} |
||||
// Left
|
||||
if (dist != 0 || !onLeftEdge) { |
||||
if (draggedColumnIndex == cMin && scrollBarVisible() && isScrollPaneRtl()) x1++; |
||||
g.fillRect(x1 - 1, y1, 1, y2 - y1); |
||||
} |
||||
// Right
|
||||
if (dist != 0 || !onRightEdge) { |
||||
g.fillRect(x2, y1, 1, y2 - y1); |
||||
} |
||||
} |
||||
|
||||
for (int row = rMin; row <= rMax; row++) { |
||||
// Render the cell value
|
||||
Rectangle r = table.getCellRect(row, draggedColumnIndex, false); |
||||
r.x += dist; |
||||
paintCell(g, r, row, draggedColumnIndex, cMin, cMax); |
||||
|
||||
// Paint the (lower) horizontal grid line if necessary.
|
||||
if (table.getShowHorizontalLines() || (!scrollVisible && row == rMax)) { |
||||
g.setColor(table.getGridColor()); |
||||
if (drawBottomBorder) { |
||||
g.setColor(getBorderColor()); |
||||
} |
||||
Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true); |
||||
rcr.x += dist; |
||||
int x1 = rcr.x - 1; |
||||
int y1 = rcr.y; |
||||
int x2 = x1 + rcr.width + 1; |
||||
int y2 = y1 + rcr.height - 1; |
||||
g.fillRect(x1, y2, x2 - x1, 1); |
||||
} |
||||
} |
||||
if (drawBottomBorder) { |
||||
var rect = table.getCellRect(rMax, draggedColumnIndex, true); |
||||
int y = rect.y + rect.height - 1; |
||||
g.setColor(getBorderColor()); |
||||
g.fillRect(rect.x, y, rect.width, 1); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void paintGrid(@NotNull final Graphics g, |
||||
final int rMin, final int rMax, final int cMin, final int cMax) { |
||||
g.setColor(table.getGridColor()); |
||||
|
||||
Rectangle minCell = table.getCellRect(rMin, cMin, true); |
||||
Rectangle maxCell = table.getCellRect(rMax, cMax, true); |
||||
Rectangle damagedArea = minCell.union(maxCell); |
||||
|
||||
int draggedIndex = viewIndexForColumn(table.getTableHeader().getDraggedColumn()); |
||||
if (table.getShowHorizontalLines()) { |
||||
int tableWidth = damagedArea.x + damagedArea.width; |
||||
if (table.getComponentOrientation().isLeftToRight()) { |
||||
if (draggedIndex == cMax) { |
||||
tableWidth -= 1; |
||||
} |
||||
} else { |
||||
if (draggedIndex == cMin) { |
||||
tableWidth -= 1; |
||||
} |
||||
} |
||||
int y = damagedArea.y; |
||||
for (int row = rMin; row <= rMax; row++) { |
||||
y += table.getRowHeight(row); |
||||
SwingUtilities2.drawHLine(g, damagedArea.x, tableWidth - 1, y - 1); |
||||
} |
||||
} |
||||
|
||||
boolean scrollPaneRtl = isScrollPaneRtl(); |
||||
boolean scrollVisible = scrollBarVisible(); |
||||
if (table.getShowVerticalLines()) { |
||||
TableColumnModel cm = table.getColumnModel(); |
||||
int tableHeight = damagedArea.y + damagedArea.height; |
||||
int x; |
||||
boolean ltr = table.getComponentOrientation().isLeftToRight(); |
||||
if (ltr) { |
||||
x = damagedArea.x; |
||||
if (scrollPaneRtl && scrollBarVisible()) { |
||||
SwingUtilities2.drawVLine(g, x, 0, tableHeight - 1); |
||||
} |
||||
for (int column = cMin; column <= cMax; column++) { |
||||
int w = cm.getColumn(column).getWidth(); |
||||
x += w; |
||||
if (showVerticalLine(true, scrollVisible, !scrollPaneRtl, column, draggedIndex, cMin, cMax)) { |
||||
SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1); |
||||
} |
||||
} |
||||
} else { |
||||
x = damagedArea.x; |
||||
if (scrollPaneRtl && scrollBarVisible()) { |
||||
SwingUtilities2.drawVLine(g, x, 0, tableHeight - 1); |
||||
} |
||||
for (int column = cMax; column >= cMin; column--) { |
||||
int w = cm.getColumn(column).getWidth(); |
||||
x += w; |
||||
if (showVerticalLine(false, scrollVisible, !scrollPaneRtl, column, draggedIndex, cMin, cMax)) { |
||||
SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
if (!table.getShowHorizontalLines() && table.getRowCount() != 0 && !scrollVisible) { |
||||
g.setColor(getBorderColor()); |
||||
int y = table.getHeight() - 1; |
||||
g.fillRect(0, y, table.getWidth(), 1); |
||||
} |
||||
} |
||||
|
||||
protected Color getBorderColor() { |
||||
return UIManager.getColor("TableHeader.borderColor"); |
||||
} |
||||
|
||||
protected boolean isScrollPaneRtl() { |
||||
if (!isInScrollPane()) return false; |
||||
Container comp = SwingUtilities.getUnwrappedParent(table).getParent(); |
||||
return !comp.getComponentOrientation().isLeftToRight(); |
||||
} |
||||
|
||||
protected boolean scrollBarVisible() { |
||||
Container comp = SwingUtilities.getUnwrappedParent(table); |
||||
if (comp != null) { |
||||
comp = comp.getParent(); |
||||
} |
||||
return comp instanceof JScrollPane && ((JScrollPane) comp).getVerticalScrollBar().isVisible(); |
||||
} |
||||
|
||||
protected boolean isInScrollPane() { |
||||
Container comp = SwingUtilities.getUnwrappedParent(table); |
||||
if (comp != null) { |
||||
comp = comp.getParent(); |
||||
} |
||||
return comp instanceof JScrollPane; |
||||
} |
||||
|
||||
protected boolean showVerticalLine(final boolean ltr, final boolean scrollVisible, |
||||
final boolean scrollLtR, final int column, final int draggedIndex, |
||||
final int cMin, final int cMax) { |
||||
int dist = adjustDistance(table.getTableHeader().getDraggedDistance(), |
||||
table.getCellRect(0, draggedIndex, true), |
||||
table); |
||||
boolean isDragged = column == draggedIndex && dist != 0; |
||||
if (!scrollVisible) { |
||||
if (ltr) { |
||||
return column != cMax; |
||||
} else { |
||||
return column != cMin; |
||||
} |
||||
} else { |
||||
if (ltr) { |
||||
if (scrollLtR) { |
||||
return column != cMax || !isDragged; |
||||
} else { |
||||
return column != cMax; |
||||
} |
||||
} else { |
||||
if (scrollLtR) { |
||||
return column != cMin || !isDragged; |
||||
} else { |
||||
return column != cMin; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void paintCell(final Graphics g, final Rectangle cellRect, final int row, final int column, |
||||
final int cMin, final int cMax) { |
||||
boolean scrollLtR = !isScrollPaneRtl(); |
||||
boolean ltr = table.getComponentOrientation().isLeftToRight(); |
||||
int draggedIndex = viewIndexForColumn(table.getTableHeader().getDraggedColumn()); |
||||
int dist = adjustDistance(table.getTableHeader().getDraggedDistance(), |
||||
table.getCellRect(row, draggedIndex, true), |
||||
table); |
||||
boolean isDragged = column == draggedIndex && dist != 0; |
||||
var r = new Rectangle(cellRect); |
||||
if (!scrollBarVisible()) { |
||||
if (ltr) { |
||||
if (column == cMax && !isDragged) r.width += 1; |
||||
} else { |
||||
if (column == cMin && !isDragged) r.width += 1; |
||||
} |
||||
} else if (!scrollLtR) { |
||||
if (ltr) { |
||||
if (column == cMax && !isDragged) r.width += 1; |
||||
if (column == cMin && !isDragged) { |
||||
r.width -= 1; |
||||
r.x += 1; |
||||
} |
||||
} else { |
||||
if (column == cMin && !isDragged) r.width += 1; |
||||
if (column == cMax && !isDragged) { |
||||
r.width -= 1; |
||||
r.x += 1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (table.isEditing() && table.getEditingRow() == row && |
||||
table.getEditingColumn() == column) { |
||||
Component component = table.getEditorComponent(); |
||||
if (component instanceof JComponent) { |
||||
//Todo
|
||||
var border = UIManager.getBorder("Table.cellEditorBorder"); |
||||
((JComponent) component).setBorder(border); |
||||
} |
||||
component.setBounds(r); |
||||
component.validate(); |
||||
} else { |
||||
TableCellRenderer renderer = table.getCellRenderer(row, column); |
||||
Component component = table.prepareRenderer(renderer, row, column); |
||||
rendererPane.paintComponent(g, component, table, r.x, r.y, |
||||
r.width, r.height, true); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,432 @@
|
||||
package com.weis.darklaf.ui.table; |
||||
|
||||
import org.jetbrains.annotations.NotNull; |
||||
import sun.swing.SwingUtilities2; |
||||
|
||||
import javax.swing.*; |
||||
import javax.swing.plaf.basic.BasicTableUI; |
||||
import javax.swing.table.JTableHeader; |
||||
import javax.swing.table.TableCellRenderer; |
||||
import javax.swing.table.TableColumn; |
||||
import javax.swing.table.TableColumnModel; |
||||
import java.awt.*; |
||||
|
||||
public class DarkTableUIBridge extends BasicTableUI { |
||||
|
||||
protected static int getAdjustedLead(final JTable table, |
||||
final boolean row, |
||||
final ListSelectionModel model) { |
||||
|
||||
int index = model.getLeadSelectionIndex(); |
||||
int compare = row ? table.getRowCount() : table.getColumnCount(); |
||||
return index < compare ? index : -1; |
||||
} |
||||
|
||||
protected static int getAdjustedLead(final JTable table, final boolean row) { |
||||
return row ? getAdjustedLead(table, row, table.getSelectionModel()) |
||||
: getAdjustedLead(table, row, table.getColumnModel().getSelectionModel()); |
||||
} |
||||
|
||||
/** |
||||
* Paint a representation of the <code>table</code> instance |
||||
* that was set in installUI(). |
||||
*/ |
||||
public void paint(@NotNull final Graphics g, final JComponent c) { |
||||
Rectangle clip = g.getClipBounds(); |
||||
|
||||
Rectangle bounds = table.getBounds(); |
||||
// account for the fact that the graphics has already been translated
|
||||
// into the table's bounds
|
||||
bounds.x = bounds.y = 0; |
||||
|
||||
if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 || |
||||
// this check prevents us from painting the entire table
|
||||
// when the clip doesn't intersect our bounds at all
|
||||
!bounds.intersects(clip)) { |
||||
|
||||
paintDropLines(g); |
||||
return; |
||||
} |
||||
|
||||
boolean ltr = table.getComponentOrientation().isLeftToRight(); |
||||
Point upperLeft, lowerRight; |
||||
// compute the visible part of table which needs to be painted
|
||||
Rectangle visibleBounds = clip.intersection(bounds); |
||||
upperLeft = visibleBounds.getLocation(); |
||||
lowerRight = new Point(visibleBounds.x + visibleBounds.width - 1, |
||||
visibleBounds.y + visibleBounds.height - 1); |
||||
|
||||
int rMin = table.rowAtPoint(upperLeft); |
||||
int rMax = table.rowAtPoint(lowerRight); |
||||
// This should never happen (as long as our bounds intersect the clip,
|
||||
// which is why we bail above if that is the case).
|
||||
if (rMin == -1) { |
||||
rMin = 0; |
||||
} |
||||
// If the table does not have enough rows to fill the view we'll get -1.
|
||||
// (We could also get -1 if our bounds don't intersect the clip,
|
||||
// which is why we bail above if that is the case).
|
||||
// Replace this with the index of the last row.
|
||||
if (rMax == -1) { |
||||
rMax = table.getRowCount() - 1; |
||||
} |
||||
|
||||
// For FIT_WIDTH, all columns should be printed irrespective of
|
||||
// how many columns are visible. So, we used clip which is already set to
|
||||
// total col width instead of visible region
|
||||
// Since JTable.PrintMode is not accessible
|
||||
// from here, we aet "Table.printMode" in TablePrintable#print and
|
||||
// access from here.
|
||||
Object printMode = table.getClientProperty("Table.printMode"); |
||||
if ((printMode == JTable.PrintMode.FIT_WIDTH)) { |
||||
upperLeft = clip.getLocation(); |
||||
lowerRight = new Point(clip.x + clip.width - 1, |
||||
clip.y + clip.height - 1); |
||||
} |
||||
int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight); |
||||
int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft); |
||||
// This should never happen.
|
||||
if (cMin == -1) { |
||||
cMin = 0; |
||||
} |
||||
// If the table does not have enough columns to fill the view we'll get -1.
|
||||
// Replace this with the index of the last column.
|
||||
if (cMax == -1) { |
||||
cMax = table.getColumnCount() - 1; |
||||
} |
||||
|
||||
Container comp = SwingUtilities.getUnwrappedParent(table); |
||||
if (comp != null) { |
||||
comp = comp.getParent(); |
||||
} |
||||
|
||||
if (comp != null && !(comp instanceof JViewport) && !(comp instanceof JScrollPane)) { |
||||
// We did rMax-1 to paint the same number of rows that are drawn on console
|
||||
// otherwise 1 extra row is printed per page than that are displayed
|
||||
// when there is no scrollPane and we do printing of table
|
||||
// but not when rmax is already pointing to index of last row
|
||||
// and if there is any selected rows
|
||||
if (rMax != (table.getRowCount() - 1) && |
||||
(table.getSelectedRow() == -1)) { |
||||
// Do not decrement rMax if rMax becomes
|
||||
// less than or equal to rMin
|
||||
// else cells will not be painted
|
||||
if (rMax - rMin > 1) { |
||||
rMax = rMax - 1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Paint the grid.
|
||||
paintGrid(g, rMin, rMax, cMin, cMax); |
||||
|
||||
// Paint the cells.
|
||||
paintCells(g, rMin, rMax, cMin, cMax); |
||||
|
||||
paintDropLines(g); |
||||
} |
||||
|
||||
protected void paintDropLines(final Graphics g) { |
||||
JTable.DropLocation loc = table.getDropLocation(); |
||||
if (loc == null) { |
||||
return; |
||||
} |
||||
|
||||
Color color = UIManager.getColor("Table.dropLineColor"); |
||||
Color shortColor = UIManager.getColor("Table.dropLineShortColor"); |
||||
if (color == null && shortColor == null) { |
||||
return; |
||||
} |
||||
|
||||
Rectangle rect; |
||||
|
||||
rect = getHDropLineRect(loc); |
||||
if (rect != null) { |
||||
int x = rect.x; |
||||
int w = rect.width; |
||||
if (color != null) { |
||||
extendRect(rect, true); |
||||
g.setColor(color); |
||||
g.fillRect(rect.x, rect.y, rect.width, rect.height); |
||||
} |
||||
if (!loc.isInsertColumn() && shortColor != null) { |
||||
g.setColor(shortColor); |
||||
g.fillRect(x, rect.y, w, rect.height); |
||||
} |
||||
} |
||||
|
||||
rect = getVDropLineRect(loc); |
||||
if (rect != null) { |
||||
int y = rect.y; |
||||
int h = rect.height; |
||||
if (color != null) { |
||||
extendRect(rect, false); |
||||
g.setColor(color); |
||||
g.fillRect(rect.x, rect.y, rect.width, rect.height); |
||||
} |
||||
if (!loc.isInsertRow() && shortColor != null) { |
||||
g.setColor(shortColor); |
||||
g.fillRect(rect.x, y, rect.width, h); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected Rectangle getHDropLineRect(final JTable.DropLocation loc) { |
||||
if (!loc.isInsertRow()) { |
||||
return null; |
||||
} |
||||
|
||||
int row = loc.getRow(); |
||||
int col = loc.getColumn(); |
||||
if (col >= table.getColumnCount()) { |
||||
col--; |
||||
} |
||||
|
||||
Rectangle rect = table.getCellRect(row, col, true); |
||||
|
||||
if (row >= table.getRowCount()) { |
||||
row--; |
||||
Rectangle prevRect = table.getCellRect(row, col, true); |
||||
rect.y = prevRect.y + prevRect.height; |
||||
} |
||||
|
||||
if (rect.y == 0) { |
||||
rect.y = -1; |
||||
} else { |
||||
rect.y -= 2; |
||||
} |
||||
|
||||
rect.height = 3; |
||||
|
||||
return rect; |
||||
} |
||||
|
||||
protected Rectangle getVDropLineRect(final JTable.DropLocation loc) { |
||||
if (!loc.isInsertColumn()) { |
||||
return null; |
||||
} |
||||
|
||||
boolean ltr = table.getComponentOrientation().isLeftToRight(); |
||||
int col = loc.getColumn(); |
||||
Rectangle rect = table.getCellRect(loc.getRow(), col, true); |
||||
|
||||
if (col >= table.getColumnCount()) { |
||||
col--; |
||||
rect = table.getCellRect(loc.getRow(), col, true); |
||||
if (ltr) { |
||||
rect.x = rect.x + rect.width; |
||||
} |
||||
} else if (!ltr) { |
||||
rect.x = rect.x + rect.width; |
||||
} |
||||
|
||||
if (rect.x == 0) { |
||||
rect.x = -1; |
||||
} else { |
||||
rect.x -= 2; |
||||
} |
||||
|
||||
rect.width = 3; |
||||
|
||||
return rect; |
||||
} |
||||
|
||||
protected Rectangle extendRect(final Rectangle rect, final boolean horizontal) { |
||||
if (rect == null) { |
||||
return rect; |
||||
} |
||||
|
||||
if (horizontal) { |
||||
rect.x = 0; |
||||
rect.width = table.getWidth(); |
||||
} else { |
||||
rect.y = 0; |
||||
|
||||
if (table.getRowCount() != 0) { |
||||
Rectangle lastRect = table.getCellRect(table.getRowCount() - 1, 0, true); |
||||
rect.height = lastRect.y + lastRect.height; |
||||
} else { |
||||
rect.height = table.getHeight(); |
||||
} |
||||
} |
||||
|
||||
return rect; |
||||
} |
||||
|
||||
/* |
||||
* Paints the grid lines within <I>aRect</I>, using the grid |
||||
* color set with <I>setGridColor</I>. Paints vertical lines |
||||
* if <code>getShowVerticalLines()</code> returns true and paints |
||||
* horizontal lines if <code>getShowHorizontalLines()</code> |
||||
* returns true. |
||||
*/ |
||||
protected void paintGrid(final Graphics g, final int rMin, final int rMax, final int cMin, final int cMax) { |
||||
g.setColor(table.getGridColor()); |
||||
|
||||
Rectangle minCell = table.getCellRect(rMin, cMin, true); |
||||
Rectangle maxCell = table.getCellRect(rMax, cMax, true); |
||||
Rectangle damagedArea = minCell.union(maxCell); |
||||
|
||||
if (table.getShowHorizontalLines()) { |
||||
int tableWidth = damagedArea.x + damagedArea.width; |
||||
int y = damagedArea.y; |
||||
for (int row = rMin; row <= rMax; row++) { |
||||
y += table.getRowHeight(row); |
||||
SwingUtilities2.drawHLine(g, damagedArea.x, tableWidth - 1, y - 1); |
||||
} |
||||
} |
||||
if (table.getShowVerticalLines()) { |
||||
TableColumnModel cm = table.getColumnModel(); |
||||
int tableHeight = damagedArea.y + damagedArea.height; |
||||
int x; |
||||
if (table.getComponentOrientation().isLeftToRight()) { |
||||
x = damagedArea.x; |
||||
for (int column = cMin; column <= cMax; column++) { |
||||
int w = cm.getColumn(column).getWidth(); |
||||
x += w; |
||||
SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1); |
||||
} |
||||
} else { |
||||
x = damagedArea.x; |
||||
for (int column = cMax; column >= cMin; column--) { |
||||
int w = cm.getColumn(column).getWidth(); |
||||
x += w; |
||||
SwingUtilities2.drawVLine(g, x - 1, 0, tableHeight - 1); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected int viewIndexForColumn(final TableColumn aColumn) { |
||||
TableColumnModel cm = table.getColumnModel(); |
||||
for (int column = 0; column < cm.getColumnCount(); column++) { |
||||
if (cm.getColumn(column) == aColumn) { |
||||
return column; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
protected void paintCells(final Graphics g, final int rMin, final int rMax, final int cMin, final int cMax) { |
||||
JTableHeader header = table.getTableHeader(); |
||||
TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn(); |
||||
|
||||
TableColumnModel cm = table.getColumnModel(); |
||||
int columnMargin = cm.getColumnMargin(); |
||||
|
||||
Rectangle cellRect; |
||||
TableColumn aColumn; |
||||
int columnWidth; |
||||
if (table.getComponentOrientation().isLeftToRight()) { |
||||
for (int row = rMin; row <= rMax; row++) { |
||||
cellRect = table.getCellRect(row, cMin, false); |
||||
for (int column = cMin; column <= cMax; column++) { |
||||
aColumn = cm.getColumn(column); |
||||
columnWidth = aColumn.getWidth(); |
||||
cellRect.width = columnWidth - columnMargin; |
||||
if (aColumn != draggedColumn) { |
||||
paintCell(g, cellRect, row, column, cMin, cMax); |
||||
} |
||||
cellRect.x += columnWidth; |
||||
} |
||||
} |
||||
} else { |
||||
for (int row = rMin; row <= rMax; row++) { |
||||
cellRect = table.getCellRect(row, cMin, false); |
||||
aColumn = cm.getColumn(cMin); |
||||
if (aColumn != draggedColumn) { |
||||
columnWidth = aColumn.getWidth(); |
||||
cellRect.width = columnWidth - columnMargin; |
||||
paintCell(g, cellRect, row, cMin, cMin, cMax); |
||||
} |
||||
for (int column = cMin + 1; column <= cMax; column++) { |
||||
aColumn = cm.getColumn(column); |
||||
columnWidth = aColumn.getWidth(); |
||||
cellRect.width = columnWidth - columnMargin; |
||||
cellRect.x -= columnWidth; |
||||
if (aColumn != draggedColumn) { |
||||
paintCell(g, cellRect, row, column, cMin, cMax); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Paint the dragged column if we are dragging.
|
||||
if (draggedColumn != null) { |
||||
paintDraggedArea(g, rMin, rMax, cMin, cMax, draggedColumn, header.getDraggedDistance()); |
||||
} |
||||
|
||||
// Remove any renderers that may be left in the rendererPane.
|
||||
rendererPane.removeAll(); |
||||
} |
||||
|
||||
protected void paintDraggedArea(final Graphics g, final int rMin, final int rMax, final int cMin, final int cMax, |
||||
final TableColumn draggedColumn, final int distance) { |
||||
int draggedColumnIndex = viewIndexForColumn(draggedColumn); |
||||
|
||||
Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true); |
||||
Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true); |
||||
|
||||
Rectangle vacatedColumnRect = minCell.union(maxCell); |
||||
|
||||
// Paint a gray well in place of the moving column.
|
||||
g.setColor(table.getParent().getBackground()); |
||||
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y, |
||||
vacatedColumnRect.width, vacatedColumnRect.height); |
||||
|
||||
// Move to the where the cell has been dragged.
|
||||
vacatedColumnRect.x += distance; |
||||
|
||||
// Fill the background.
|
||||
g.setColor(table.getBackground()); |
||||
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y, |
||||
vacatedColumnRect.width, vacatedColumnRect.height); |
||||
|
||||
// Paint the vertical grid lines if necessary.
|
||||
if (table.getShowVerticalLines()) { |
||||
g.setColor(table.getGridColor()); |
||||
int x1 = vacatedColumnRect.x; |
||||
int y1 = vacatedColumnRect.y; |
||||
int x2 = x1 + vacatedColumnRect.width - 1; |
||||
int y2 = y1 + vacatedColumnRect.height - 1; |
||||
// Left
|
||||
g.fillRect(x1 - 1, y1, 1, y2 - y1); |
||||
// Right
|
||||
g.fillRect(x2 - 1, y1, 1, y2 - y1); |
||||
} |
||||
|
||||
for (int row = rMin; row <= rMax; row++) { |
||||
// Render the cell value
|
||||
Rectangle r = table.getCellRect(row, draggedColumnIndex, false); |
||||
r.x += distance; |
||||
paintCell(g, r, row, draggedColumnIndex, cMin, cMax); |
||||
|
||||
// Paint the (lower) horizontal grid line if necessary.
|
||||
if (table.getShowHorizontalLines()) { |
||||
g.setColor(table.getGridColor()); |
||||
Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true); |
||||
rcr.x += distance; |
||||
int x1 = rcr.x; |
||||
int y1 = rcr.y; |
||||
int x2 = x1 + rcr.width - 1; |
||||
int y2 = y1 + rcr.height - 1; |
||||
g.fillRect(x1 - 1, y2 - 1, x2 - x1, 1); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected void paintCell(final Graphics g, final Rectangle cellRect, final int row, final int column, |
||||
final int cMin, final int cMax) { |
||||
if (table.isEditing() && table.getEditingRow() == row && |
||||
table.getEditingColumn() == column) { |
||||
Component component = table.getEditorComponent(); |
||||
component.setBounds(cellRect); |
||||
component.validate(); |
||||
} else { |
||||
TableCellRenderer renderer = table.getCellRenderer(row, column); |
||||
Component component = table.prepareRenderer(renderer, row, column); |
||||
rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y, |
||||
cellRect.width, cellRect.height, true); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue