Browse Source

Improved table cell rendering for booleans.

pull/1/head
weisj 5 years ago
parent
commit
5641b4f07c
  1. 4
      src/main/java/com/weis/darklaf/decorators/CellRenderer.java
  2. 13
      src/main/java/com/weis/darklaf/ui/checkbox/DarkCheckBoxBorder.java
  3. 1
      src/main/java/com/weis/darklaf/ui/checkbox/DarkCheckBoxUI.java
  4. 92
      src/main/java/com/weis/darklaf/ui/table/DarkTableCellEditor.java
  5. 77
      src/main/java/com/weis/darklaf/ui/table/DarkTableCellEditorCheckBox.java
  6. 68
      src/main/java/com/weis/darklaf/ui/table/DarkTableCellRenderer.java
  7. 62
      src/main/java/com/weis/darklaf/ui/table/DarkTableCellRendererCheckBox.java
  8. 35
      src/main/java/com/weis/darklaf/ui/table/DarkTableUI.java
  9. 2
      src/main/java/com/weis/darklaf/ui/text/DarkTextAreaUI.java
  10. 2
      src/main/java/com/weis/darklaf/ui/text/DarkTextFieldUIBridge.java
  11. 32
      src/test/java/UIManagerDefaults.java

4
src/main/java/com/weis/darklaf/decorators/CellRenderer.java

@ -0,0 +1,4 @@
package com.weis.darklaf.decorators;
public interface CellRenderer {
}

13
src/main/java/com/weis/darklaf/ui/checkbox/DarkCheckBoxBorder.java

@ -1,12 +1,14 @@
package com.weis.darklaf.ui.checkbox; package com.weis.darklaf.ui.checkbox;
import com.bulenkov.iconloader.util.SystemInfo; import com.bulenkov.iconloader.util.SystemInfo;
import com.weis.darklaf.decorators.CellRenderer;
import com.weis.darklaf.util.DarkUIUtil; import com.weis.darklaf.util.DarkUIUtil;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.Border; import javax.swing.border.Border;
import javax.swing.plaf.InsetsUIResource; import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.UIResource; import javax.swing.plaf.UIResource;
import javax.swing.table.TableCellRenderer;
import java.awt.*; import java.awt.*;
public class DarkCheckBoxBorder implements Border, UIResource { public class DarkCheckBoxBorder implements Border, UIResource {
@ -18,11 +20,18 @@ public class DarkCheckBoxBorder implements Border, UIResource {
@Override @Override
public Insets getBorderInsets(final Component c) { public Insets getBorderInsets(final Component c) {
final int a = SystemInfo.isMac || DarkUIUtil.getParentOfType(CellRendererPane.class, c) != null ? 2 : 4; if (DarkUIUtil.getParentOfType(CellRendererPane.class, c) != null
|| DarkUIUtil.getParentOfType(TableCellRenderer.class, c) != null
|| DarkUIUtil.getParentOfType(CellRenderer.class, c) != null
|| DarkUIUtil.getParentOfType(CellEditor.class, c) != null) {
return new Insets(2, 5, 2, 5);
}
final int a = SystemInfo.isMac ? 2 : 4;
return new InsetsUIResource(a, a, a, a); return new InsetsUIResource(a, a, a, a);
} }
@Override @Override
public boolean isBorderOpaque() { public boolean isBorderOpaque() {
return false; return false;
}} }
}

1
src/main/java/com/weis/darklaf/ui/checkbox/DarkCheckBoxUI.java

@ -81,6 +81,7 @@ public class DarkCheckBoxUI extends MetalCheckBoxUI {
GraphicsContext config = new GraphicsContext(g); GraphicsContext config = new GraphicsContext(g);
boolean enabled = b.isEnabled(); boolean enabled = b.isEnabled();
g.translate(iconRect.x + ICON_OFF, iconRect.y + ICON_OFF); g.translate(iconRect.x + ICON_OFF, iconRect.y + ICON_OFF);
paintCheckBorder(g, enabled, b.hasFocus()); paintCheckBorder(g, enabled, b.hasFocus());
if (b.isSelected()) { if (b.isSelected()) {
paintCheckArrow(g, enabled); paintCheckArrow(g, enabled);

92
src/main/java/com/weis/darklaf/ui/table/DarkTableCellEditor.java

@ -0,0 +1,92 @@
package com.weis.darklaf.ui.table;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.util.EventObject;
/**
* @author vincencopalazzo
* @author atarw
*/
public class DarkTableCellEditor extends DefaultCellEditor {
private final DarkTableCellEditorCheckBox booleanEditor = new DarkTableCellEditorCheckBox(this);
private boolean value;
private boolean isBooleanEditor;
public DarkTableCellEditor() {
this(new JTextField());
}
public DarkTableCellEditor(final JComboBox<?> comboBox) {
super(comboBox);
}
public DarkTableCellEditor(final JCheckBox checkBox) {
super(checkBox);
}
public DarkTableCellEditor(final JTextField textField) {
super(textField);
textField.setBorder(new DarkTableCellBorder());
}
protected void setValue(final Object value) {
delegate.setValue(value);
if (value instanceof Boolean) {
this.value = (boolean) value;
} else {
isBooleanEditor = false;
}
}
@Override
public Component getTableCellEditorComponent(final JTable table, final Object value,
final boolean isSelected, final int row, final int column) {
if (value instanceof Boolean && DarkTableCellRenderer.isBooleanRenderingEnabled(table)) {
isBooleanEditor = true;
return booleanEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
} else {
isBooleanEditor = false;
}
super.getTableCellEditorComponent(table, value, isSelected, row, column);
boolean alternativeRow = UIManager.getBoolean("Table.alternateRowColor");
Color alternativeRowColor = UIManager.getColor("Table.alternateRowBackground");
Color normalColor = UIManager.getColor("Table.background");
if (alternativeRow) {
if (!isSelected) {
if (row % 2 == 1) {
editorComponent.setBackground(alternativeRowColor);
} else {
editorComponent.setBackground(normalColor);
}
}
}
return editorComponent;
}
@Override
public Object getCellEditorValue() {
if (isBooleanEditor) {
return value;
} else {
return super.getCellEditorValue();
}
}
@Override
public boolean isCellEditable(@NotNull final EventObject anEvent) {
var table = ((JTable) anEvent.getSource());
if (DarkTableCellRenderer.isBooleanRenderingEnabled(table)) {
var p = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(p, table);
var value = table.getValueAt(table.rowAtPoint(p), table.columnAtPoint(p));
if (value instanceof Boolean) return true;
}
return super.isCellEditable(anEvent);
}
}

77
src/main/java/com/weis/darklaf/ui/table/DarkTableCellEditorCheckBox.java

@ -0,0 +1,77 @@
package com.weis.darklaf.ui.table;
import com.weis.darklaf.decorators.CellRenderer;
import javax.swing.*;
import javax.swing.table.TableCellEditor;
import java.awt.*;
import java.util.EventObject;
/**
* @author vincencopalazzo
* @author atarw
*/
public class DarkTableCellEditorCheckBox extends AbstractCellEditor implements TableCellEditor, SwingConstants {
private final JCheckBox checkBox;
public DarkTableCellEditorCheckBox(final DarkTableCellEditor delegate) {
checkBox = new CellEditorCheckBox();
checkBox.addChangeListener(e -> delegate.setValue(checkBox.isSelected()));
}
@Override
public Component getTableCellEditorComponent(final JTable table, final Object value,
final boolean isSelected, final int row, final int column) {
if (value instanceof Boolean) {
checkBox.setSelected((Boolean) value);
}
checkBox.setHorizontalAlignment(table.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT);
boolean alternativeRow = UIManager.getBoolean("Table.alternateRowColor");
Color alternativeRowColor = UIManager.getColor("Table.alternateRowBackground");
Color normalColor = UIManager.getColor("Table.background");
if (alternativeRow) {
if (!isSelected) {
if (row % 2 == 1) {
checkBox.setBackground(alternativeRowColor);
} else {
checkBox.setBackground(normalColor);
}
checkBox.setForeground(table.getForeground());
} else {
checkBox.setForeground(table.getSelectionForeground());
checkBox.setBackground(table.getSelectionBackground());
}
}
return checkBox;
}
@Override
public Object getCellEditorValue() {
return checkBox.isSelected();
}
@Override
public boolean isCellEditable(final EventObject anEvent) {
return true;
}
@Override
public boolean shouldSelectCell(final EventObject anEvent) {
return false;
}
private static class CellEditorCheckBox extends JCheckBox implements CellRenderer {
@Override
public boolean hasFocus() {
return true;
}
@Override
public boolean isFocusOwner() {
return super.hasFocus();
}
}
}

68
src/main/java/com/weis/darklaf/ui/table/DarkTableCellRenderer.java

@ -0,0 +1,68 @@
package com.weis.darklaf.ui.table;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.*;
/**
* @author vincencopalazzo
* @author atarw
*/
public class DarkTableCellRenderer extends DefaultTableCellRenderer {
private final DarkTableCellRendererCheckBox booleanRenderer = new DarkTableCellRendererCheckBox();
protected static boolean isBooleanRenderingEnabled(@NotNull final JTable table) {
return Boolean.TRUE.equals(table.getClientProperty("JTable.renderBooleanAsCheckBox"));
}
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value,
final boolean isSelected, final boolean hasFocus, final int row,
final int column) {
if (value instanceof Boolean && isBooleanRenderingEnabled(table)) {
return booleanRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
JComponent component = (JComponent) super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
row, column);
this.setVerticalAlignment(SwingConstants.CENTER);
setHorizontalAlignment(table.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT);
boolean alternativeRow = UIManager.getBoolean("Table.alternateRowColor");
Color alternativeRowColor = UIManager.getColor("Table.alternateRowBackground");
Color normalColor = UIManager.getColor("Table.background");
if (alternativeRow) {
if (!isSelected) {
if (row % 2 == 1) {
component.setBackground(alternativeRowColor);
setDefaultCellRenderWithAllType(table, value, isSelected, hasFocus, row, column,
alternativeRowColor);
} else {
component.setBackground(normalColor);
setDefaultCellRenderWithAllType(table, value, isSelected, hasFocus, row, column, normalColor);
}
component.setForeground(table.getSelectionForeground());
}
}
return component;
}
// This method setting a MaterialCellRender at the particular class
// With this class not working correctly the color alternate in the Jtable
// in particular the IconImage without this code the cell is painted not correctly or
// in the cell did print the path of the image
protected void setDefaultCellRenderWithAllType(final JTable table, final Object value, final boolean isSelected,
final boolean hasFocus, final int row, final int column,
final Color color) {
if (table == null) {
throw new IllegalArgumentException("Table is null");
}
Component component = table.getDefaultRenderer(ImageIcon.class)
.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
component.setBackground(color);
}
}

62
src/main/java/com/weis/darklaf/ui/table/DarkTableCellRendererCheckBox.java

@ -0,0 +1,62 @@
package com.weis.darklaf.ui.table;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
/**
* @author vincencopalazzo
* @author atarw
*/
public class DarkTableCellRendererCheckBox extends JCheckBox implements TableCellRenderer, SwingConstants {
private boolean hasFocus;
public DarkTableCellRendererCheckBox() {
this(false);
}
public DarkTableCellRendererCheckBox(final boolean selected) {
setSelected(selected);
}
@Override
public boolean hasFocus() {
return hasFocus || super.hasFocus();
}
@Override
public boolean isFocusOwner() {
return super.hasFocus();
}
@Override
public Component getTableCellRendererComponent(final JTable table, final Object value,
final boolean isSelected, final boolean focus,
final int row, final int column) {
if (value instanceof Boolean) {
setSelected((Boolean) value);
}
setHorizontalAlignment(table.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT);
hasFocus = focus;
boolean alternativeRow = UIManager.getBoolean("Table.alternateRowColor");
Color alternativeRowColor = UIManager.getColor("Table.alternateRowBackground");
Color normalColor = UIManager.getColor("Table.background");
if (alternativeRow) {
if (!isSelected) {
if (row % 2 == 1) {
this.setBackground(alternativeRowColor);
} else {
this.setBackground(normalColor);
}
this.setForeground(table.getForeground());
} else {
this.setForeground(table.getSelectionForeground());
this.setBackground(table.getSelectionBackground());
}
}
return this;
}
}

35
src/main/java/com/weis/darklaf/ui/table/DarkTableUI.java

@ -7,7 +7,6 @@ import sun.swing.SwingUtilities2;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource; import javax.swing.plaf.UIResource;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel; import javax.swing.table.TableColumnModel;
import java.awt.*; import java.awt.*;
@ -31,8 +30,12 @@ public class DarkTableUI extends DarkTableUIBridge {
public void focusLost(final FocusEvent e) { public void focusLost(final FocusEvent e) {
var bg = table.getSelectionBackground(); var bg = table.getSelectionBackground();
if (bg instanceof UIResource) { if (bg instanceof UIResource) {
if (table.isEditing()) {
table.setSelectionBackground(table.getBackground());
} else {
table.setSelectionBackground(UIManager.getColor("Table.selectionBackground")); table.setSelectionBackground(UIManager.getColor("Table.selectionBackground"));
} }
}
table.repaint(); table.repaint();
} }
}; };
@ -57,10 +60,22 @@ public class DarkTableUI extends DarkTableUIBridge {
return dist; return dist;
} }
protected static void setupRendererComponents(@NotNull final JTable table) {
var cellRenderer = new DarkTableCellRenderer();
table.setDefaultRenderer(Object.class, cellRenderer);
table.setDefaultRenderer(String.class, cellRenderer);
table.setDefaultRenderer(Integer.class, cellRenderer);
table.setDefaultRenderer(Double.class, cellRenderer);
table.setDefaultRenderer(Float.class, cellRenderer);
table.setDefaultRenderer(Boolean.class, cellRenderer);
}
@Override @Override
protected void installDefaults() { protected void installDefaults() {
super.installDefaults(); super.installDefaults();
table.setRowHeight(ROW_HEIGHT); table.setRowHeight(ROW_HEIGHT);
table.setDefaultEditor(Object.class, new DarkTableCellEditor());
setupRendererComponents(table);
} }
@Override @Override
@ -320,22 +335,6 @@ public class DarkTableUI extends DarkTableUIBridge {
} }
} }
} }
super.paintCell(g, r, row, column, cMin, cMax);
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);
}
} }
} }

2
src/main/java/com/weis/darklaf/ui/text/DarkTextAreaUI.java

@ -1,6 +1,6 @@
package com.weis.darklaf.ui.text; package com.weis.darklaf.ui.text;
import com.weis.darklaf.DarkHTML; import com.weis.darklaf.ui.html.DarkHTML;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

2
src/main/java/com/weis/darklaf/ui/text/DarkTextFieldUIBridge.java

@ -1,6 +1,6 @@
package com.weis.darklaf.ui.text; package com.weis.darklaf.ui.text;
import com.weis.darklaf.DarkHTML; import com.weis.darklaf.ui.html.DarkHTML;
import javax.swing.*; import javax.swing.*;
import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentEvent;

32
src/test/java/UIManagerDefaults.java

@ -5,6 +5,7 @@
import com.weis.darklaf.DarkLafInfo; import com.weis.darklaf.DarkLafInfo;
import com.weis.darklaf.LafManager; import com.weis.darklaf.LafManager;
import com.weis.darklaf.ui.table.DarkTableCellRendererCheckBox;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -23,6 +24,7 @@ import java.awt.event.ItemListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.EventObject;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@ -108,6 +110,7 @@ public class UIManagerDefaults implements ActionListener, ItemListener {
@NotNull @NotNull
private JComponent buildNorthComponent() { private JComponent buildNorthComponent() {
comboBox = new JComboBox<>(); comboBox = new JComboBox<>();
comboBox.setPreferredSize(new Dimension(200, comboBox.getPreferredSize().height));
final JLabel label = new JLabel("Select Item:"); final JLabel label = new JLabel("Select Item:");
label.setDisplayedMnemonic('S'); label.setDisplayedMnemonic('S');
@ -147,17 +150,17 @@ public class UIManagerDefaults implements ActionListener, ItemListener {
table.getColumnModel().getColumn(1).setPreferredWidth(500); table.getColumnModel().getColumn(1).setPreferredWidth(500);
table.getColumnModel().getColumn(2).setPreferredWidth(100); table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(2).setCellRenderer(new SampleRenderer()); table.getColumnModel().getColumn(2).setCellRenderer(new SampleRenderer());
table.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(new JTextField()) {
@Override
public boolean isCellEditable(final EventObject anEvent) {
return false;
}
});
final Dimension d = table.getPreferredSize(); final Dimension d = table.getPreferredSize();
d.height = 350; d.height = 350;
table.setPreferredScrollableViewportSize(d); table.setPreferredScrollableViewportSize(d);
// table.setShowHorizontalLines(false); return new JScrollPane(table);
// table.setShowVerticalLines(false);
// table.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
return new JScrollPane(table) {{
setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
}};
} }
/* /*
@ -180,7 +183,6 @@ public class UIManagerDefaults implements ActionListener, ItemListener {
comboBox.setModel(new DefaultComboBoxModel<>(comboBoxItems)); comboBox.setModel(new DefaultComboBoxModel<>(comboBoxItems));
comboBox.setSelectedIndex(-1); comboBox.setSelectedIndex(-1);
comboBox.addItemListener(this); comboBox.addItemListener(this);
comboBox.requestFocusInWindow();
if (selectedItem != null) { if (selectedItem != null) {
comboBox.setSelectedItem(selectedItem); comboBox.setSelectedItem(selectedItem);
@ -192,7 +194,7 @@ public class UIManagerDefaults implements ActionListener, ItemListener {
* items for each attribute type. * items for each attribute type.
*/ */
@NotNull @NotNull
private TreeMap buildItemsMap() { private TreeMap<String, TreeMap<String, Object>> buildItemsMap() {
final UIDefaults defaults = UIManager.getLookAndFeelDefaults(); final UIDefaults defaults = UIManager.getLookAndFeelDefaults();
// Build of Map of items and a Map of attributes for each item // Build of Map of items and a Map of attributes for each item
for (final Object key : new HashSet<>(defaults.keySet())) { for (final Object key : new HashSet<>(defaults.keySet())) {
@ -362,8 +364,11 @@ public class UIManagerDefaults implements ActionListener, ItemListener {
*/ */
public void actionPerformed(final ActionEvent e) { public void actionPerformed(final ActionEvent e) {
selectedItem = null; selectedItem = null;
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
table.clearSelection();
resetComponents(); resetComponents();
comboBox.requestFocusInWindow();
} }
/* /*
@ -396,7 +401,7 @@ public class UIManagerDefaults implements ActionListener, ItemListener {
final Vector<Object> row = new Vector<>(3); final Vector<Object> row = new Vector<>(3);
row.add(attribute); row.add(attribute);
if (value != null) { if (value != null) {
row.add(value.toString()); row.add(value instanceof Boolean ? value : value.toString());
if (value instanceof Icon) { if (value instanceof Icon) {
value = new SafeIcon((Icon) value); value = new SafeIcon((Icon) value);
} }
@ -540,6 +545,9 @@ public class UIManagerDefaults implements ActionListener, ItemListener {
* Render the value based on its class. * Render the value based on its class.
*/ */
private static final class SampleRenderer extends JLabel implements TableCellRenderer { private static final class SampleRenderer extends JLabel implements TableCellRenderer {
private final DarkTableCellRendererCheckBox booleanRenderer = new DarkTableCellRendererCheckBox();
private SampleRenderer() { private SampleRenderer() {
super(); super();
setHorizontalAlignment(SwingConstants.CENTER); setHorizontalAlignment(SwingConstants.CENTER);
@ -569,6 +577,8 @@ public class UIManagerDefaults implements ActionListener, ItemListener {
setFont((Font) sample); setFont((Font) sample);
} else if (sample instanceof Icon) { } else if (sample instanceof Icon) {
setIcon((Icon) sample); setIcon((Icon) sample);
} else if (sample instanceof Boolean) {
return booleanRenderer.getTableCellRendererComponent(table, sample, isSelected, hasFocus, row, column);
} }
return this; return this;
} }

Loading…
Cancel
Save