blob: 3d0789bc63dd09d6f47b26dc19c076893075ce38 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.log4j.chainsaw.color;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import org.apache.log4j.chainsaw.ApplicationPreferenceModel;
import org.apache.log4j.chainsaw.ChainsawConstants;
import org.apache.log4j.chainsaw.ExpressionRuleContext;
import org.apache.log4j.chainsaw.filter.FilterModel;
import org.apache.log4j.chainsaw.helper.SwingHelper;
import org.apache.log4j.chainsaw.icons.ChainsawIcons;
import org.apache.log4j.rule.ColorRule;
import org.apache.log4j.rule.ExpressionRule;
import org.apache.log4j.rule.Rule;
/**
* Panel which updates a RuleColorizer, allowing the user to build expression-based
* color rules.
*
* TODO: examine ColorPanel/RuleColorizer/LogPanel listeners and interactions
*
* @author Scott Deboy <sdeboy@apache.org>
*/
public class ColorPanel extends JPanel
{
private static final String DEFAULT_STATUS = "<html>Double click a rule field to edit the rule</html>";
private final String currentRuleSet = "Default";
private RuleColorizer colorizer;
private JPanel rulesPanel;
private FilterModel filterModel;
private DefaultTableModel tableModel;
private JScrollPane tableScrollPane;
private JTable table;
private ActionListener closeListener;
private JLabel statusBar;
private Vector<String> columns;
private final String noTab = "None";
private DefaultComboBoxModel logPanelColorizersModel;
private Map<String, RuleColorizer> allLogPanelColorizers;
private RuleColorizer currentLogPanelColorizer;
private JTable searchTable;
private DefaultTableModel searchTableModel;
private Vector<String> searchColumns;
private Vector<Vector<Color>> searchDataVector;
private Vector<Color> searchDataVectorEntry;
private JTable alternatingColorTable;
private DefaultTableModel alternatingColorTableModel;
private Vector<String> alternatingColorColumns;
private Vector<Vector<Color>> alternatingColorDataVector;
private Vector<Color> alternatingColorDataVectorEntry;
private ApplicationPreferenceModel applicationPreferenceModel;
private JCheckBox bypassSearchColorsCheckBox;
public ColorPanel(final RuleColorizer currentLogPanelColorizer, final FilterModel filterModel,
final Map<String, RuleColorizer> allLogPanelColorizers, final ApplicationPreferenceModel applicationPreferenceModel) {
super(new BorderLayout());
this.currentLogPanelColorizer = currentLogPanelColorizer;
this.colorizer = currentLogPanelColorizer;
this.filterModel = filterModel;
this.allLogPanelColorizers = allLogPanelColorizers;
this.applicationPreferenceModel = applicationPreferenceModel;
currentLogPanelColorizer.addPropertyChangeListener(
"colorrule",
evt -> updateColors());
tableModel = new DefaultTableModel();
table = new JTable(tableModel);
table.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
searchTableModel = new DefaultTableModel();
searchTable = new JTable(searchTableModel);
searchTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
searchTable.setPreferredScrollableViewportSize(new Dimension(30, 30));
alternatingColorTableModel = new DefaultTableModel();
alternatingColorTable = new JTable(alternatingColorTableModel);
alternatingColorTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
alternatingColorTable.setPreferredScrollableViewportSize(new Dimension(30, 30));
columns = new Vector<>();
columns.add("Expression");
columns.add("Background");
columns.add("Foreground");
searchColumns = new Vector<>();
searchColumns.add("Background");
searchColumns.add("Foreground");
alternatingColorColumns = new Vector<>();
alternatingColorColumns.add("Background");
alternatingColorColumns.add("Foreground");
//searchtable contains only a single-entry vector containing a two-item vector (foreground, background)
searchDataVector = new Vector<>();
searchDataVectorEntry = new Vector<>();
searchDataVectorEntry.add(applicationPreferenceModel.getSearchBackgroundColor());
searchDataVectorEntry.add(applicationPreferenceModel.getSearchForegroundColor());
searchDataVector.add(searchDataVectorEntry);
searchTableModel.setDataVector(searchDataVector, searchColumns);
alternatingColorDataVector = new Vector<>();
alternatingColorDataVectorEntry = new Vector<>();
alternatingColorDataVectorEntry.add(applicationPreferenceModel.getAlternatingColorBackgroundColor());
alternatingColorDataVectorEntry.add(applicationPreferenceModel.getAlternatingColorForegroundColor());
alternatingColorDataVector.add(alternatingColorDataVectorEntry);
alternatingColorTableModel.setDataVector(alternatingColorDataVector, alternatingColorColumns);
table.setPreferredScrollableViewportSize(new Dimension(525, 200));
tableScrollPane = new JScrollPane(table);
Vector<Vector<java.io.Serializable>> data = getColorizerVector();
tableModel.setDataVector(data, columns);
table.sizeColumnsToFit(0);
table.getColumnModel().getColumn(1).setPreferredWidth(80);
table.getColumnModel().getColumn(2).setPreferredWidth(80);
table.getColumnModel().getColumn(1).setMaxWidth(80);
table.getColumnModel().getColumn(2).setMaxWidth(80);
searchTable.sizeColumnsToFit(0);
searchTable.getColumnModel().getColumn(0).setPreferredWidth(80);
searchTable.getColumnModel().getColumn(1).setPreferredWidth(80);
searchTable.getColumnModel().getColumn(0).setMaxWidth(80);
searchTable.getColumnModel().getColumn(1).setMaxWidth(80);
//building color choosers needs to be done on the EDT
SwingHelper.invokeOnEDT(() -> configureSingleEntryColorTable(searchTable));
alternatingColorTable.sizeColumnsToFit(0);
alternatingColorTable.getColumnModel().getColumn(0).setPreferredWidth(80);
alternatingColorTable.getColumnModel().getColumn(1).setPreferredWidth(80);
alternatingColorTable.getColumnModel().getColumn(0).setMaxWidth(80);
alternatingColorTable.getColumnModel().getColumn(1).setMaxWidth(80);
//building color choosers needs to be done on the EDT
SwingHelper.invokeOnEDT(() -> configureSingleEntryColorTable(alternatingColorTable));
configureTable();
statusBar = new JLabel(DEFAULT_STATUS);
rulesPanel = buildRulesPanel();
rulesPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
JPanel rightPanel = new JPanel(new BorderLayout());
JPanel rightOuterPanel = new JPanel();
rightOuterPanel.setLayout(
new BoxLayout(rightOuterPanel, BoxLayout.X_AXIS));
rightOuterPanel.add(Box.createHorizontalStrut(10));
JPanel southPanel = new JPanel();
southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.Y_AXIS));
southPanel.add(Box.createVerticalStrut(5));
southPanel.add(Box.createVerticalStrut(5));
JPanel searchAndAlternatingColorPanel = buildSearchAndAlternatingColorPanel();
JPanel bypassSearchColorsPanel = buildBypassSearchColorsPanel();
bypassSearchColorsCheckBox.setSelected(applicationPreferenceModel.isBypassSearchColors());
JPanel globalLabelPanel = new JPanel();
globalLabelPanel.setLayout(new BoxLayout(globalLabelPanel, BoxLayout.X_AXIS));
JLabel globalLabel = new JLabel("Global colors:");
globalLabelPanel.add(globalLabel);
globalLabelPanel.add(Box.createHorizontalGlue());
southPanel.add(globalLabelPanel);
southPanel.add(searchAndAlternatingColorPanel);
southPanel.add(bypassSearchColorsPanel);
southPanel.add(Box.createVerticalStrut(5));
JPanel closePanel = buildClosePanel();
southPanel.add(closePanel);
JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
statusPanel.add(statusBar);
southPanel.add(statusPanel);
rightPanel.add(rulesPanel, BorderLayout.CENTER);
rightPanel.add(southPanel, BorderLayout.SOUTH);
rightOuterPanel.add(rightPanel);
JPanel topPanel = new JPanel();
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS));
JLabel selectText = new JLabel("Apply a tab's colors");
topPanel.add(selectText);
topPanel.add(Box.createHorizontalStrut(5));
logPanelColorizersModel = new DefaultComboBoxModel();
final JComboBox loadPanelColorizersComboBox = new JComboBox(logPanelColorizersModel);
loadLogPanelColorizers();
topPanel.add(loadPanelColorizersComboBox);
topPanel.add(Box.createHorizontalStrut(5));
final Action copyRulesAction = new AbstractAction() {
public void actionPerformed(ActionEvent e)
{
tableModel.getDataVector().clear();
Object selectedItem = loadPanelColorizersComboBox.getSelectedItem();
if (selectedItem != null) {
RuleColorizer sourceColorizer = allLogPanelColorizers.get(selectedItem.toString());
colorizer.setRules(sourceColorizer.getRules());
updateColors();
}
}
};
loadPanelColorizersComboBox.addActionListener(e -> {
Object selectedItem = loadPanelColorizersComboBox.getSelectedItem();
if (selectedItem != null) {
String selectedColorizerName = selectedItem.toString();
copyRulesAction.setEnabled(!(noTab.equals(selectedColorizerName)));
}
});
copyRulesAction.putValue(Action.NAME, "Copy color rules");
copyRulesAction.setEnabled(!(noTab.equals(loadPanelColorizersComboBox.getSelectedItem())));
JButton copyRulesButton = new JButton(copyRulesAction);
topPanel.add(copyRulesButton);
add(topPanel, BorderLayout.NORTH);
add(rightOuterPanel, BorderLayout.CENTER);
if (table.getRowCount() > 0) {
table.getSelectionModel().setSelectionInterval(0, 0);
}
}
public void loadLogPanelColorizers() {
if (logPanelColorizersModel.getIndexOf(noTab) == -1) {
logPanelColorizersModel.addElement(noTab);
}
for (Object o : allLogPanelColorizers.entrySet()) {
Map.Entry entry = (Map.Entry) o;
if (!entry.getValue().equals(currentLogPanelColorizer) && (logPanelColorizersModel.getIndexOf(entry.getKey()) == -1)) {
logPanelColorizersModel.addElement(entry.getKey());
}
}
//update search and alternating colors, since they may have changed from another color panel
searchDataVectorEntry.set(0, applicationPreferenceModel.getSearchBackgroundColor());
searchDataVectorEntry.set(1, applicationPreferenceModel.getSearchForegroundColor());
alternatingColorDataVectorEntry.set(0, applicationPreferenceModel.getAlternatingColorBackgroundColor());
alternatingColorDataVectorEntry.set(1, applicationPreferenceModel.getAlternatingColorForegroundColor());
}
public JPanel buildBypassSearchColorsPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
bypassSearchColorsCheckBox = new JCheckBox("Don't use a search color for matching rows");
panel.add(bypassSearchColorsCheckBox);
return panel;
}
public JPanel buildSearchAndAlternatingColorPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
JLabel defineSearchColorsLabel = new JLabel("Find colors");
panel.add(defineSearchColorsLabel);
panel.add(Box.createHorizontalStrut(10));
JScrollPane searchPane = new JScrollPane(searchTable);
searchPane.setBorder(BorderFactory.createEmptyBorder());
panel.add(searchPane);
panel.add(Box.createHorizontalStrut(10));
JLabel defineAlternatingColorLabel = new JLabel("Alternating colors");
panel.add(defineAlternatingColorLabel);
panel.add(Box.createHorizontalStrut(10));
JScrollPane alternatingColorPane = new JScrollPane(alternatingColorTable);
alternatingColorPane.setBorder(BorderFactory.createEmptyBorder());
panel.add(alternatingColorPane);
panel.setBorder(BorderFactory.createEtchedBorder());
panel.add(Box.createHorizontalGlue());
return panel;
}
public void updateColors() {
tableModel.getDataVector().clear();
tableModel.getDataVector().addAll(getColorizerVector());
tableModel.fireTableDataChanged();
}
private Vector<Vector<java.io.Serializable>> getColorizerVector() {
Vector<Vector<java.io.Serializable>> data = new Vector<>();
Map map = colorizer.getRules();
for (Object o1 : map.entrySet()) {
Map.Entry entry = (Map.Entry) o1;
//update ruleset list
if (entry.getKey().equals(currentRuleSet)) {
for (Object o : ((List) entry.getValue())) {
ColorRule rule = (ColorRule) o;
Vector<java.io.Serializable> v = new Vector<>();
v.add(rule.getExpression());
v.add(rule.getBackgroundColor());
v.add(rule.getForegroundColor());
data.add(v);
}
}
}
return data;
}
private void configureTable() {
table.setToolTipText("Double click to edit");
table.setRowHeight(20);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setColumnSelectionAllowed(false);
Vector backgroundColors = colorizer.getDefaultColors();
Vector foregroundColors = colorizer.getDefaultColors();
backgroundColors.add("Browse...");
foregroundColors.add("Browse...");
JComboBox background = new JComboBox(backgroundColors);
background.setMaximumRowCount(15);
background.setRenderer(new ColorListCellRenderer());
JComboBox foreground = new JComboBox(foregroundColors);
foreground.setMaximumRowCount(15);
foreground.setRenderer(new ColorListCellRenderer());
DefaultCellEditor backgroundEditor = new DefaultCellEditor(background);
DefaultCellEditor foregroundEditor = new DefaultCellEditor(foreground);
JTextField textField = new JTextField();
textField.addKeyListener(
new ExpressionRuleContext(filterModel, textField));
table.getColumnModel().getColumn(0).setCellEditor(
new DefaultCellEditor(textField));
table.getColumnModel().getColumn(1).setCellEditor(backgroundEditor);
table.getColumnModel().getColumn(2).setCellEditor(foregroundEditor);
background.addItemListener(new ColorItemListener(background));
foreground.addItemListener(new ColorItemListener(foreground));
table.getColumnModel().getColumn(0).setCellRenderer(
new ExpressionTableCellRenderer());
table.getColumnModel().getColumn(1).setCellRenderer(
new ColorTableCellRenderer());
table.getColumnModel().getColumn(2).setCellRenderer(
new ColorTableCellRenderer());
}
private void configureSingleEntryColorTable(JTable thisTable) {
thisTable.setToolTipText("Double click to edit");
thisTable.setRowHeight(20);
thisTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
thisTable.setColumnSelectionAllowed(false);
Vector backgroundColors = colorizer.getDefaultColors();
Vector foregroundColors = colorizer.getDefaultColors();
backgroundColors.add("Browse...");
foregroundColors.add("Browse...");
JComboBox background = new JComboBox(backgroundColors);
background.setMaximumRowCount(15);
background.setRenderer(new ColorListCellRenderer());
JComboBox foreground = new JComboBox(foregroundColors);
foreground.setMaximumRowCount(15);
foreground.setRenderer(new ColorListCellRenderer());
DefaultCellEditor backgroundEditor = new DefaultCellEditor(background);
DefaultCellEditor foregroundEditor = new DefaultCellEditor(foreground);
thisTable.getColumnModel().getColumn(0).setCellEditor(backgroundEditor);
thisTable.getColumnModel().getColumn(1).setCellEditor(foregroundEditor);
background.addItemListener(new ColorItemListener(background));
foreground.addItemListener(new ColorItemListener(foreground));
thisTable.getColumnModel().getColumn(0).setCellRenderer(
new ColorTableCellRenderer());
thisTable.getColumnModel().getColumn(1).setCellRenderer(
new ColorTableCellRenderer());
}
public void setCloseActionListener(ActionListener listener) {
closeListener = listener;
}
public void hidePanel() {
if (closeListener != null) {
closeListener.actionPerformed(null);
}
}
void applyRules(String ruleSet, RuleColorizer applyingColorizer) {
table.getColumnModel().getColumn(0).getCellEditor().stopCellEditing();
List list = new ArrayList();
Vector vector = tableModel.getDataVector();
StringBuilder result = new StringBuilder();
for (int i = 0; i < vector.size(); i++) {
Vector v = (Vector) vector.elementAt(i);
try {
Rule expressionRule = ExpressionRule.getRule((String) v.elementAt(0));
Color background = getBackground();
Color foreground = getForeground();
if (v.elementAt(1) instanceof Color) {
background = (Color) v.elementAt(1);
}
if (v.elementAt(2) instanceof Color) {
foreground = (Color) v.elementAt(2);
}
ColorRule r = new ColorRule((String)v.elementAt(0), expressionRule, background, foreground);
list.add(r);
} catch (IllegalArgumentException iae) {
if (!result.toString().equals("")) {
result.append("<br>");
}
result.append(iae.getMessage());
}
}
//all rules are valid, they can be applied
if (result.toString().equals("")) {
((ExpressionTableCellRenderer) table.getColumnModel().getColumn(0).getCellRenderer())
.setToolTipText("Double click to edit");
statusBar.setText(DEFAULT_STATUS);
//only update rules if there were no errors
Map map = new HashMap();
map.put(ruleSet, list);
applyingColorizer.setRules(map);
} else {
statusBar.setText("Errors - see expression tooltip (color filters won't be active until errors are resolved)");
((ExpressionTableCellRenderer) table.getColumnModel().getColumn(0).getCellRenderer())
.setToolTipText("<html>" + result.toString() + "</html>");
}
}
JPanel buildClosePanel() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(Box.createHorizontalGlue());
JButton saveAsDefaultButton = new JButton(" Save as default ");
saveAsDefaultButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
RuleColorizer defaultColorizer = allLogPanelColorizers.get(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
applyRules(currentRuleSet, defaultColorizer);
}
});
panel.add(saveAsDefaultButton);
JButton applyButton = new JButton(" Apply ");
applyButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
applyRules(currentRuleSet, colorizer);
saveSearchColors();
saveAlternatingColors();
saveBypassFlag();
}
});
panel.add(Box.createHorizontalStrut(10));
panel.add(applyButton);
JButton closeButton = new JButton(" Close ");
closeButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
hidePanel();
}
});
panel.add(Box.createHorizontalStrut(10));
panel.add(closeButton);
return panel;
}
private void saveSearchColors() {
Vector thisVector = (Vector) searchTableModel.getDataVector().get(0);
applicationPreferenceModel.setSearchBackgroundColor((Color)thisVector.get(0));
applicationPreferenceModel.setSearchForegroundColor((Color)thisVector.get(1));
}
private void saveAlternatingColors() {
Vector thisVector = (Vector) alternatingColorTableModel.getDataVector().get(0);
applicationPreferenceModel.setAlternatingBackgroundColor((Color)thisVector.get(0));
Color alternatingColorForegroundColor = (Color) thisVector.get(1);
applicationPreferenceModel.setAlternatingForegroundColor(alternatingColorForegroundColor);
}
private void saveBypassFlag() {
applicationPreferenceModel.setBypassSearchColors(bypassSearchColorsCheckBox.isSelected());
}
JPanel buildUpDownPanel() {
JPanel panel = new JPanel(new BorderLayout());
JPanel innerPanel = new JPanel();
innerPanel.setLayout(new GridLayout(5, 1));
final JButton upButton = new JButton(ChainsawIcons.ICON_UP);
upButton.setToolTipText("Move selected rule up");
final JButton downButton = new JButton(ChainsawIcons.ICON_DOWN);
downButton.setToolTipText("Move selected rule down");
upButton.setEnabled(false);
downButton.setEnabled(false);
table.getSelectionModel().addListSelectionListener(
e -> {
if (!e.getValueIsAdjusting()) {
int index = table.getSelectionModel().getMaxSelectionIndex();
if (index < 0) {
downButton.setEnabled(false);
upButton.setEnabled(false);
} else if ((index == 0) && (tableModel.getRowCount() == 1)) {
downButton.setEnabled(false);
upButton.setEnabled(false);
} else if ((index == 0) && (tableModel.getRowCount() > 1)) {
downButton.setEnabled(true);
upButton.setEnabled(false);
} else if (index == (tableModel.getRowCount() - 1)) {
downButton.setEnabled(false);
upButton.setEnabled(true);
} else {
downButton.setEnabled(true);
upButton.setEnabled(true);
}
}
});
JPanel upPanel = new JPanel();
upPanel.add(upButton);
JPanel downPanel = new JPanel();
downPanel.add(downButton);
innerPanel.add(new JLabel(""));
innerPanel.add(upPanel);
innerPanel.add(new JLabel(""));
innerPanel.add(downPanel);
panel.add(innerPanel, BorderLayout.CENTER);
upButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
int index = table.getSelectionModel().getMaxSelectionIndex();
if (index > 0) {
Vector v = tableModel.getDataVector();
Vector row = (Vector) v.elementAt(index);
tableModel.removeRow(index);
index = index - 1;
tableModel.insertRow(index, row);
table.getSelectionModel().setSelectionInterval(index, index);
}
}
});
downButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
int index = table.getSelectionModel().getMaxSelectionIndex();
if ((index > -1) && (index < (tableModel.getRowCount() - 1))) {
Vector v = tableModel.getDataVector();
Vector row = (Vector) v.elementAt(index);
tableModel.removeRow(index);
index = index + 1;
tableModel.insertRow(index, row);
table.getSelectionModel().setSelectionInterval(index, index);
}
}
});
return panel;
}
JPanel buildRulesPanel() {
JPanel listPanel = new JPanel(new BorderLayout());
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(Box.createVerticalStrut(10));
JLabel rulesLabel = new JLabel("Rules:");
panel.add(rulesLabel);
JPanel buttonPanel = new JPanel(new GridLayout(0, 2));
buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
JPanel newPanel = new JPanel();
JButton newButton = new JButton(" New ");
newButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
int currentRow = table.getSelectedRow();
Vector<java.io.Serializable> v = new Vector<>();
v.add("");
v.add(Color.white);
v.add(Color.black);
if (currentRow < 0) {
tableModel.addRow(v);
currentRow = table.getRowCount() - 1;
} else {
tableModel.insertRow(currentRow, v);
}
table.getSelectionModel().setSelectionInterval(
currentRow, currentRow);
}
});
newPanel.add(newButton);
JPanel deletePanel = new JPanel();
final JButton deleteButton = new JButton(" Delete ");
deleteButton.setEnabled(false);
deleteButton.addActionListener(
new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
int index = table.getSelectionModel().getMaxSelectionIndex();
if ((index > -1) && (index < table.getRowCount())) {
tableModel.removeRow(index);
if (index > 0) {
index = index - 1;
}
if (tableModel.getRowCount() > 0) {
table.getSelectionModel().setSelectionInterval(index, index);
}
}
}
});
table.getSelectionModel().addListSelectionListener(
e -> {
if (!e.getValueIsAdjusting()) {
int index = table.getSelectionModel().getMaxSelectionIndex();
if (index < 0) {
deleteButton.setEnabled(false);
} else {
deleteButton.setEnabled(true);
}
}
});
deletePanel.add(deleteButton);
buttonPanel.add(newPanel);
buttonPanel.add(deletePanel);
listPanel.add(panel, BorderLayout.NORTH);
JPanel tablePanel = new JPanel(new BorderLayout());
tableScrollPane.setBorder(BorderFactory.createEtchedBorder());
tablePanel.add(tableScrollPane, BorderLayout.CENTER);
tablePanel.add(buildUpDownPanel(), BorderLayout.EAST);
listPanel.add(tablePanel, BorderLayout.CENTER);
listPanel.add(buttonPanel, BorderLayout.SOUTH);
return listPanel;
}
class ColorListCellRenderer extends JLabel implements ListCellRenderer {
ColorListCellRenderer() {
setOpaque(true);
}
public Component getListCellRendererComponent(
JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
setText(" ");
if (isSelected && (index > -1)) {
setBorder(BorderFactory.createLineBorder(Color.black, 2));
} else {
setBorder(BorderFactory.createEmptyBorder());
}
if (value instanceof Color) {
setBackground((Color) value);
} else {
setBackground(Color.white);
if (value != null) {
setText(value.toString());
}
}
return this;
}
}
class ColorItemListener implements ItemListener {
JComboBox box;
JDialog dialog;
JColorChooser colorChooser;
Color lastColor;
ColorItemListener(final JComboBox box) {
this.box = box;
colorChooser = new JColorChooser();
dialog =
JColorChooser.createDialog(
box, "Pick a Color", true, //modal
colorChooser,
e -> {
box.insertItemAt(colorChooser.getColor(), 0);
box.setSelectedIndex(0);
}, //OK button handler
e -> box.setSelectedItem(lastColor)); //CANCEL button handler
dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
}
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if (box.getSelectedItem() instanceof Color) {
box.setBackground((Color) box.getSelectedItem());
repaint();
} else {
box.setBackground(Color.white);
int selectedRow = table.getSelectedRow();
int selectedColumn = table.getSelectedColumn();
if (selectedRow != -1 && selectedColumn != -1) {
colorChooser.setColor((Color)table.getValueAt(selectedRow, selectedColumn));
lastColor = (Color)table.getValueAt(selectedRow, selectedColumn);
}
dialog.setVisible(true);
}
}
}
}
class ColorTableCellRenderer implements TableCellRenderer {
Border border;
JPanel panel;
ColorTableCellRenderer() {
panel = new JPanel();
panel.setOpaque(true);
}
public Color getCurrentColor() {
return panel.getBackground();
}
public Component getTableCellRendererComponent(
JTable thisTable, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
if (value instanceof Color) {
panel.setBackground((Color) value);
}
if (border == null) {
border = BorderFactory.createMatteBorder(2, 2, 2, 2, table.getBackground());
}
panel.setBorder(border);
return panel;
}
}
class ExpressionTableCellRenderer implements TableCellRenderer {
JPanel panel = new JPanel();
JLabel expressionLabel = new JLabel();
JLabel iconLabel = new JLabel();
Icon selectedIcon = new SelectedIcon(true);
Icon unselectedIcon = new SelectedIcon(false);
ExpressionTableCellRenderer() {
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.setOpaque(true);
panel.add(iconLabel);
panel.add(Box.createHorizontalStrut(5));
panel.add(expressionLabel);
}
void setToolTipText(String text) {
panel.setToolTipText(text);
}
public Component getTableCellRendererComponent(
JTable thisTable, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
if (value == null) {
return panel;
}
Vector v = tableModel.getDataVector();
Vector r = (Vector) v.elementAt(row);
expressionLabel.setText(value.toString());
if (r.elementAt(1) instanceof Color) {
expressionLabel.setBackground((Color) r.elementAt(1));
panel.setBackground((Color) r.elementAt(1));
}
if (r.elementAt(2) instanceof Color) {
expressionLabel.setForeground((Color) r.elementAt(2));
panel.setForeground((Color) r.elementAt(2));
}
if (isSelected) {
iconLabel.setIcon(selectedIcon);
} else {
iconLabel.setIcon(unselectedIcon);
}
return panel;
}
}
class SelectedIcon implements Icon {
private boolean isSelected;
private int width = 9;
private int height = 18;
private int[] xPoints = new int[4];
private int[] yPoints = new int[4];
public SelectedIcon(boolean isSelected) {
this.isSelected = isSelected;
xPoints[0] = 0;
yPoints[0] = -1;
xPoints[1] = 0;
yPoints[1] = height;
xPoints[2] = width;
yPoints[2] = height / 2;
xPoints[3] = width;
yPoints[3] = (height / 2) - 1;
}
public int getIconHeight() {
return height;
}
public int getIconWidth() {
return width;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
if (isSelected) {
int length = xPoints.length;
int[] newXPoints = new int[length];
int[] newYPoints = new int[length];
for (int i = 0; i < length; i++) {
newXPoints[i] = xPoints[i] + x;
newYPoints[i] = yPoints[i] + y;
}
g.setColor(Color.black);
g.fillPolygon(newXPoints, newYPoints, length);
}
}
}
}