1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.chainsaw.color;
19
20 import org.apache.log4j.chainsaw.ApplicationPreferenceModel;
21 import org.apache.log4j.chainsaw.ChainsawConstants;
22 import org.apache.log4j.chainsaw.ExpressionRuleContext;
23 import org.apache.log4j.chainsaw.filter.FilterModel;
24 import org.apache.log4j.chainsaw.helper.SwingHelper;
25 import org.apache.log4j.chainsaw.icons.ChainsawIcons;
26 import org.apache.log4j.rule.ColorRule;
27 import org.apache.log4j.rule.ExpressionRule;
28 import org.apache.log4j.rule.Rule;
29
30 import javax.swing.*;
31 import javax.swing.border.Border;
32 import javax.swing.table.DefaultTableModel;
33 import javax.swing.table.TableCellRenderer;
34 import java.awt.*;
35 import java.awt.event.ActionEvent;
36 import java.awt.event.ActionListener;
37 import java.awt.event.ItemEvent;
38 import java.awt.event.ItemListener;
39 import java.util.*;
40 import java.util.List;
41
42
43
44
45
46
47
48
49
50
51 public class ColorPanel extends JPanel {
52 private static final String DEFAULT_STATUS = "<html>Double click a rule field to edit the rule</html>";
53 private final String currentRuleSet = "Default";
54
55 private RuleColorizer colorizer;
56 private JPanel rulesPanel;
57 private FilterModel filterModel;
58 private DefaultTableModel tableModel;
59 private JScrollPane tableScrollPane;
60 private JTable table;
61 private ActionListener closeListener;
62 private JLabel statusBar;
63 private Vector<String> columns;
64 private final String noTab = "None";
65 private DefaultComboBoxModel logPanelColorizersModel;
66 private Map<String, RuleColorizer> allLogPanelColorizers;
67 private RuleColorizer currentLogPanelColorizer;
68 private JTable searchTable;
69 private DefaultTableModel searchTableModel;
70 private Vector<String> searchColumns;
71 private Vector<Vector<Color>> searchDataVector;
72 private Vector<Color> searchDataVectorEntry;
73
74 private JTable alternatingColorTable;
75 private DefaultTableModel alternatingColorTableModel;
76 private Vector<String> alternatingColorColumns;
77 private Vector<Vector<Color>> alternatingColorDataVector;
78 private Vector<Color> alternatingColorDataVectorEntry;
79 private ApplicationPreferenceModel applicationPreferenceModel;
80 private JCheckBox bypassSearchColorsCheckBox;
81
82 public ColorPanel(final RuleColorizer currentLogPanelColorizer, final FilterModel filterModel,
83 final Map<String, RuleColorizer> allLogPanelColorizers, final ApplicationPreferenceModel applicationPreferenceModel) {
84 super(new BorderLayout());
85
86 this.currentLogPanelColorizer = currentLogPanelColorizer;
87 this.colorizer = currentLogPanelColorizer;
88 this.filterModel = filterModel;
89 this.allLogPanelColorizers = allLogPanelColorizers;
90 this.applicationPreferenceModel = applicationPreferenceModel;
91
92 currentLogPanelColorizer.addPropertyChangeListener(
93 "colorrule",
94 evt -> updateColors());
95
96 tableModel = new DefaultTableModel();
97 table = new JTable(tableModel);
98 table.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
99
100 searchTableModel = new DefaultTableModel();
101 searchTable = new JTable(searchTableModel);
102 searchTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
103 searchTable.setPreferredScrollableViewportSize(new Dimension(30, 30));
104
105 alternatingColorTableModel = new DefaultTableModel();
106 alternatingColorTable = new JTable(alternatingColorTableModel);
107 alternatingColorTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
108 alternatingColorTable.setPreferredScrollableViewportSize(new Dimension(30, 30));
109
110 columns = new Vector<>();
111 columns.add("Expression");
112 columns.add("Background");
113 columns.add("Foreground");
114
115 searchColumns = new Vector<>();
116 searchColumns.add("Background");
117 searchColumns.add("Foreground");
118
119 alternatingColorColumns = new Vector<>();
120 alternatingColorColumns.add("Background");
121 alternatingColorColumns.add("Foreground");
122
123
124 searchDataVector = new Vector<>();
125 searchDataVectorEntry = new Vector<>();
126 searchDataVectorEntry.add(applicationPreferenceModel.getSearchBackgroundColor());
127 searchDataVectorEntry.add(applicationPreferenceModel.getSearchForegroundColor());
128 searchDataVector.add(searchDataVectorEntry);
129 searchTableModel.setDataVector(searchDataVector, searchColumns);
130
131 alternatingColorDataVector = new Vector<>();
132 alternatingColorDataVectorEntry = new Vector<>();
133 alternatingColorDataVectorEntry.add(applicationPreferenceModel.getAlternatingColorBackgroundColor());
134 alternatingColorDataVectorEntry.add(applicationPreferenceModel.getAlternatingColorForegroundColor());
135 alternatingColorDataVector.add(alternatingColorDataVectorEntry);
136 alternatingColorTableModel.setDataVector(alternatingColorDataVector, alternatingColorColumns);
137
138 table.setPreferredScrollableViewportSize(new Dimension(525, 200));
139 tableScrollPane = new JScrollPane(table);
140
141 Vector<Vector<java.io.Serializable>> data = getColorizerVector();
142 tableModel.setDataVector(data, columns);
143
144 table.sizeColumnsToFit(0);
145 table.getColumnModel().getColumn(1).setPreferredWidth(80);
146 table.getColumnModel().getColumn(2).setPreferredWidth(80);
147 table.getColumnModel().getColumn(1).setMaxWidth(80);
148 table.getColumnModel().getColumn(2).setMaxWidth(80);
149
150 searchTable.sizeColumnsToFit(0);
151 searchTable.getColumnModel().getColumn(0).setPreferredWidth(80);
152 searchTable.getColumnModel().getColumn(1).setPreferredWidth(80);
153 searchTable.getColumnModel().getColumn(0).setMaxWidth(80);
154 searchTable.getColumnModel().getColumn(1).setMaxWidth(80);
155
156 SwingHelper.invokeOnEDT(() -> configureSingleEntryColorTable(searchTable));
157
158 alternatingColorTable.sizeColumnsToFit(0);
159 alternatingColorTable.getColumnModel().getColumn(0).setPreferredWidth(80);
160 alternatingColorTable.getColumnModel().getColumn(1).setPreferredWidth(80);
161 alternatingColorTable.getColumnModel().getColumn(0).setMaxWidth(80);
162 alternatingColorTable.getColumnModel().getColumn(1).setMaxWidth(80);
163
164 SwingHelper.invokeOnEDT(() -> configureSingleEntryColorTable(alternatingColorTable));
165
166 configureTable();
167
168 statusBar = new JLabel(DEFAULT_STATUS);
169
170 rulesPanel = buildRulesPanel();
171 rulesPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
172
173 JPanel rightPanel = new JPanel(new BorderLayout());
174
175 JPanel rightOuterPanel = new JPanel();
176 rightOuterPanel.setLayout(
177 new BoxLayout(rightOuterPanel, BoxLayout.X_AXIS));
178 rightOuterPanel.add(Box.createHorizontalStrut(10));
179
180 JPanel southPanel = new JPanel();
181 southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.Y_AXIS));
182 southPanel.add(Box.createVerticalStrut(5));
183 southPanel.add(Box.createVerticalStrut(5));
184 JPanel searchAndAlternatingColorPanel = buildSearchAndAlternatingColorPanel();
185 JPanel bypassSearchColorsPanel = buildBypassSearchColorsPanel();
186 bypassSearchColorsCheckBox.setSelected(applicationPreferenceModel.isBypassSearchColors());
187
188 JPanel globalLabelPanel = new JPanel();
189 globalLabelPanel.setLayout(new BoxLayout(globalLabelPanel, BoxLayout.X_AXIS));
190 JLabel globalLabel = new JLabel("Global colors:");
191 globalLabelPanel.add(globalLabel);
192 globalLabelPanel.add(Box.createHorizontalGlue());
193 southPanel.add(globalLabelPanel);
194 southPanel.add(searchAndAlternatingColorPanel);
195 southPanel.add(bypassSearchColorsPanel);
196 southPanel.add(Box.createVerticalStrut(5));
197 JPanel closePanel = buildClosePanel();
198 southPanel.add(closePanel);
199
200 JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
201 statusPanel.add(statusBar);
202 southPanel.add(statusPanel);
203 rightPanel.add(rulesPanel, BorderLayout.CENTER);
204 rightPanel.add(southPanel, BorderLayout.SOUTH);
205 rightOuterPanel.add(rightPanel);
206
207 JPanel topPanel = new JPanel();
208 topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS));
209
210 JLabel selectText = new JLabel("Apply a tab's colors");
211 topPanel.add(selectText);
212 topPanel.add(Box.createHorizontalStrut(5));
213
214 logPanelColorizersModel = new DefaultComboBoxModel();
215 final JComboBox loadPanelColorizersComboBox = new JComboBox(logPanelColorizersModel);
216 loadLogPanelColorizers();
217
218 topPanel.add(loadPanelColorizersComboBox);
219
220 topPanel.add(Box.createHorizontalStrut(5));
221 final Action copyRulesAction = new AbstractAction() {
222 public void actionPerformed(ActionEvent e) {
223 tableModel.getDataVector().clear();
224 Object selectedItem = loadPanelColorizersComboBox.getSelectedItem();
225 if (selectedItem != null) {
226 RuleColorizer sourceColorizer = allLogPanelColorizers.get(selectedItem.toString());
227 colorizer.setRules(sourceColorizer.getRules());
228 updateColors();
229 }
230 }
231 };
232
233 loadPanelColorizersComboBox.addActionListener(e -> {
234 Object selectedItem = loadPanelColorizersComboBox.getSelectedItem();
235 if (selectedItem != null) {
236 String selectedColorizerName = selectedItem.toString();
237 copyRulesAction.setEnabled(!(noTab.equals(selectedColorizerName)));
238 }
239 });
240
241 copyRulesAction.putValue(Action.NAME, "Copy color rules");
242 copyRulesAction.setEnabled(!(noTab.equals(loadPanelColorizersComboBox.getSelectedItem())));
243
244 JButton copyRulesButton = new JButton(copyRulesAction);
245 topPanel.add(copyRulesButton);
246
247 add(topPanel, BorderLayout.NORTH);
248 add(rightOuterPanel, BorderLayout.CENTER);
249 if (table.getRowCount() > 0) {
250 table.getSelectionModel().setSelectionInterval(0, 0);
251 }
252 }
253
254 public void loadLogPanelColorizers() {
255 if (logPanelColorizersModel.getIndexOf(noTab) == -1) {
256 logPanelColorizersModel.addElement(noTab);
257 }
258 for (Object o : allLogPanelColorizers.entrySet()) {
259 Map.Entry entry = (Map.Entry) o;
260 if (!entry.getValue().equals(currentLogPanelColorizer) && (logPanelColorizersModel.getIndexOf(entry.getKey()) == -1)) {
261 logPanelColorizersModel.addElement(entry.getKey());
262 }
263 }
264
265 searchDataVectorEntry.set(0, applicationPreferenceModel.getSearchBackgroundColor());
266 searchDataVectorEntry.set(1, applicationPreferenceModel.getSearchForegroundColor());
267 alternatingColorDataVectorEntry.set(0, applicationPreferenceModel.getAlternatingColorBackgroundColor());
268 alternatingColorDataVectorEntry.set(1, applicationPreferenceModel.getAlternatingColorForegroundColor());
269 }
270
271 public JPanel buildBypassSearchColorsPanel() {
272 JPanel panel = new JPanel();
273 panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
274
275 bypassSearchColorsCheckBox = new JCheckBox("Don't use a search color for matching rows");
276 panel.add(bypassSearchColorsCheckBox);
277 return panel;
278 }
279
280 public JPanel buildSearchAndAlternatingColorPanel() {
281 JPanel panel = new JPanel();
282 panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
283
284 JLabel defineSearchColorsLabel = new JLabel("Find colors");
285
286 panel.add(defineSearchColorsLabel);
287
288 panel.add(Box.createHorizontalStrut(10));
289 JScrollPane searchPane = new JScrollPane(searchTable);
290 searchPane.setBorder(BorderFactory.createEmptyBorder());
291 panel.add(searchPane);
292
293 panel.add(Box.createHorizontalStrut(10));
294 JLabel defineAlternatingColorLabel = new JLabel("Alternating colors");
295
296 panel.add(defineAlternatingColorLabel);
297
298 panel.add(Box.createHorizontalStrut(10));
299 JScrollPane alternatingColorPane = new JScrollPane(alternatingColorTable);
300 alternatingColorPane.setBorder(BorderFactory.createEmptyBorder());
301
302 panel.add(alternatingColorPane);
303 panel.setBorder(BorderFactory.createEtchedBorder());
304 panel.add(Box.createHorizontalGlue());
305 return panel;
306 }
307
308 public void updateColors() {
309 tableModel.getDataVector().clear();
310 tableModel.getDataVector().addAll(getColorizerVector());
311 tableModel.fireTableDataChanged();
312 }
313
314 private Vector<Vector<java.io.Serializable>> getColorizerVector() {
315 Vector<Vector<java.io.Serializable>> data = new Vector<>();
316 Map map = colorizer.getRules();
317 for (Object o1 : map.entrySet()) {
318 Map.Entry entry = (Map.Entry) o1;
319
320 if (entry.getKey().equals(currentRuleSet)) {
321
322 for (Object o : ((List) entry.getValue())) {
323 ColorRule rule = (ColorRule) o;
324 Vector<java.io.Serializable> v = new Vector<>();
325 v.add(rule.getExpression());
326 v.add(rule.getBackgroundColor());
327 v.add(rule.getForegroundColor());
328 data.add(v);
329 }
330 }
331 }
332 return data;
333 }
334
335 private void configureTable() {
336 table.setToolTipText("Double click to edit");
337 table.setRowHeight(20);
338 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
339 table.setColumnSelectionAllowed(false);
340
341 Vector backgroundColors = colorizer.getDefaultColors();
342 Vector foregroundColors = colorizer.getDefaultColors();
343 backgroundColors.add("Browse...");
344 foregroundColors.add("Browse...");
345
346 JComboBox background = new JComboBox(backgroundColors);
347 background.setMaximumRowCount(15);
348 background.setRenderer(new ColorListCellRenderer());
349
350 JComboBox foreground = new JComboBox(foregroundColors);
351 foreground.setMaximumRowCount(15);
352 foreground.setRenderer(new ColorListCellRenderer());
353
354 DefaultCellEditor backgroundEditor = new DefaultCellEditor(background);
355 DefaultCellEditor foregroundEditor = new DefaultCellEditor(foreground);
356 JTextField textField = new JTextField();
357 textField.addKeyListener(
358 new ExpressionRuleContext(filterModel, textField));
359 table.getColumnModel().getColumn(0).setCellEditor(
360 new DefaultCellEditor(textField));
361 table.getColumnModel().getColumn(1).setCellEditor(backgroundEditor);
362 table.getColumnModel().getColumn(2).setCellEditor(foregroundEditor);
363
364 background.addItemListener(new ColorItemListener(background));
365 foreground.addItemListener(new ColorItemListener(foreground));
366
367 table.getColumnModel().getColumn(0).setCellRenderer(
368 new ExpressionTableCellRenderer());
369 table.getColumnModel().getColumn(1).setCellRenderer(
370 new ColorTableCellRenderer());
371 table.getColumnModel().getColumn(2).setCellRenderer(
372 new ColorTableCellRenderer());
373 }
374
375 private void configureSingleEntryColorTable(JTable thisTable) {
376 thisTable.setToolTipText("Double click to edit");
377 thisTable.setRowHeight(20);
378 thisTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
379 thisTable.setColumnSelectionAllowed(false);
380
381 Vector backgroundColors = colorizer.getDefaultColors();
382 Vector foregroundColors = colorizer.getDefaultColors();
383 backgroundColors.add("Browse...");
384 foregroundColors.add("Browse...");
385
386 JComboBox background = new JComboBox(backgroundColors);
387 background.setMaximumRowCount(15);
388 background.setRenderer(new ColorListCellRenderer());
389
390 JComboBox foreground = new JComboBox(foregroundColors);
391 foreground.setMaximumRowCount(15);
392 foreground.setRenderer(new ColorListCellRenderer());
393
394 DefaultCellEditor backgroundEditor = new DefaultCellEditor(background);
395 DefaultCellEditor foregroundEditor = new DefaultCellEditor(foreground);
396 thisTable.getColumnModel().getColumn(0).setCellEditor(backgroundEditor);
397 thisTable.getColumnModel().getColumn(1).setCellEditor(foregroundEditor);
398
399 background.addItemListener(new ColorItemListener(background));
400 foreground.addItemListener(new ColorItemListener(foreground));
401
402 thisTable.getColumnModel().getColumn(0).setCellRenderer(
403 new ColorTableCellRenderer());
404 thisTable.getColumnModel().getColumn(1).setCellRenderer(
405 new ColorTableCellRenderer());
406 }
407
408 public void setCloseActionListener(ActionListener listener) {
409 closeListener = listener;
410 }
411
412 public void hidePanel() {
413 if (closeListener != null) {
414 closeListener.actionPerformed(null);
415 }
416 }
417
418 void applyRules(String ruleSet, RuleColorizer applyingColorizer) {
419 table.getColumnModel().getColumn(0).getCellEditor().stopCellEditing();
420
421 List list = new ArrayList();
422 Vector vector = tableModel.getDataVector();
423 StringBuilder result = new StringBuilder();
424
425 for (int i = 0; i < vector.size(); i++) {
426 Vector v = (Vector) vector.elementAt(i);
427
428 try {
429 Rule expressionRule = ExpressionRule.getRule((String) v.elementAt(0));
430 Color background = getBackground();
431 Color foreground = getForeground();
432
433 if (v.elementAt(1) instanceof Color) {
434 background = (Color) v.elementAt(1);
435 }
436
437 if (v.elementAt(2) instanceof Color) {
438 foreground = (Color) v.elementAt(2);
439 }
440
441 ColorRule r = new ColorRule((String) v.elementAt(0), expressionRule, background, foreground);
442 list.add(r);
443 } catch (IllegalArgumentException iae) {
444 if (!result.toString().equals("")) {
445 result.append("<br>");
446 }
447
448 result.append(iae.getMessage());
449 }
450 }
451
452
453 if (result.toString().equals("")) {
454 ((ExpressionTableCellRenderer) table.getColumnModel().getColumn(0).getCellRenderer())
455 .setToolTipText("Double click to edit");
456 statusBar.setText(DEFAULT_STATUS);
457
458
459 Map map = new HashMap();
460 map.put(ruleSet, list);
461 applyingColorizer.setRules(map);
462
463 } else {
464 statusBar.setText("Errors - see expression tooltip (color filters won't be active until errors are resolved)");
465 ((ExpressionTableCellRenderer) table.getColumnModel().getColumn(0).getCellRenderer())
466 .setToolTipText("<html>" + result.toString() + "</html>");
467 }
468 }
469
470 JPanel buildClosePanel() {
471 JPanel panel = new JPanel();
472 panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
473 panel.add(Box.createHorizontalGlue());
474
475 JButton saveAsDefaultButton = new JButton(" Save as default ");
476
477 saveAsDefaultButton.addActionListener(
478 new AbstractAction() {
479 public void actionPerformed(ActionEvent evt) {
480 RuleColorizer defaultColorizer = allLogPanelColorizers.get(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
481 applyRules(currentRuleSet, defaultColorizer);
482 }
483 });
484
485 panel.add(saveAsDefaultButton);
486
487 JButton applyButton = new JButton(" Apply ");
488
489 applyButton.addActionListener(
490 new AbstractAction() {
491 public void actionPerformed(ActionEvent evt) {
492 applyRules(currentRuleSet, colorizer);
493 saveSearchColors();
494 saveAlternatingColors();
495 saveBypassFlag();
496 }
497 });
498
499 panel.add(Box.createHorizontalStrut(10));
500 panel.add(applyButton);
501
502 JButton closeButton = new JButton(" Close ");
503
504 closeButton.addActionListener(
505 new AbstractAction() {
506 public void actionPerformed(ActionEvent evt) {
507 hidePanel();
508 }
509 });
510 panel.add(Box.createHorizontalStrut(10));
511 panel.add(closeButton);
512
513 return panel;
514 }
515
516 private void saveSearchColors() {
517 Vector thisVector = (Vector) searchTableModel.getDataVector().get(0);
518 applicationPreferenceModel.setSearchBackgroundColor((Color) thisVector.get(0));
519 applicationPreferenceModel.setSearchForegroundColor((Color) thisVector.get(1));
520 }
521
522 private void saveAlternatingColors() {
523 Vector thisVector = (Vector) alternatingColorTableModel.getDataVector().get(0);
524 applicationPreferenceModel.setAlternatingBackgroundColor((Color) thisVector.get(0));
525 Color alternatingColorForegroundColor = (Color) thisVector.get(1);
526 applicationPreferenceModel.setAlternatingForegroundColor(alternatingColorForegroundColor);
527 }
528
529 private void saveBypassFlag() {
530 applicationPreferenceModel.setBypassSearchColors(bypassSearchColorsCheckBox.isSelected());
531 }
532
533 JPanel buildUpDownPanel() {
534 JPanel panel = new JPanel(new BorderLayout());
535 JPanel innerPanel = new JPanel();
536 innerPanel.setLayout(new GridLayout(5, 1));
537
538 final JButton upButton = new JButton(ChainsawIcons.ICON_UP);
539 upButton.setToolTipText("Move selected rule up");
540
541 final JButton downButton = new JButton(ChainsawIcons.ICON_DOWN);
542 downButton.setToolTipText("Move selected rule down");
543 upButton.setEnabled(false);
544 downButton.setEnabled(false);
545
546 table.getSelectionModel().addListSelectionListener(
547 e -> {
548 if (!e.getValueIsAdjusting()) {
549 int index = table.getSelectionModel().getMaxSelectionIndex();
550
551 if (index < 0) {
552 downButton.setEnabled(false);
553 upButton.setEnabled(false);
554 } else if ((index == 0) && (tableModel.getRowCount() == 1)) {
555 downButton.setEnabled(false);
556 upButton.setEnabled(false);
557 } else if ((index == 0) && (tableModel.getRowCount() > 1)) {
558 downButton.setEnabled(true);
559 upButton.setEnabled(false);
560 } else if (index == (tableModel.getRowCount() - 1)) {
561 downButton.setEnabled(false);
562 upButton.setEnabled(true);
563 } else {
564 downButton.setEnabled(true);
565 upButton.setEnabled(true);
566 }
567 }
568 });
569
570 JPanel upPanel = new JPanel();
571
572 upPanel.add(upButton);
573
574 JPanel downPanel = new JPanel();
575 downPanel.add(downButton);
576
577 innerPanel.add(new JLabel(""));
578 innerPanel.add(upPanel);
579 innerPanel.add(new JLabel(""));
580 innerPanel.add(downPanel);
581 panel.add(innerPanel, BorderLayout.CENTER);
582
583 upButton.addActionListener(
584 new AbstractAction() {
585 public void actionPerformed(ActionEvent evt) {
586 int index = table.getSelectionModel().getMaxSelectionIndex();
587
588 if (index > 0) {
589 Vector v = tableModel.getDataVector();
590 Vector row = (Vector) v.elementAt(index);
591 tableModel.removeRow(index);
592 index = index - 1;
593 tableModel.insertRow(index, row);
594 table.getSelectionModel().setSelectionInterval(index, index);
595 }
596 }
597 });
598
599 downButton.addActionListener(
600 new AbstractAction() {
601 public void actionPerformed(ActionEvent evt) {
602 int index = table.getSelectionModel().getMaxSelectionIndex();
603
604 if ((index > -1) && (index < (tableModel.getRowCount() - 1))) {
605 Vector v = tableModel.getDataVector();
606 Vector row = (Vector) v.elementAt(index);
607
608 tableModel.removeRow(index);
609 index = index + 1;
610 tableModel.insertRow(index, row);
611 table.getSelectionModel().setSelectionInterval(index, index);
612 }
613 }
614 });
615
616 return panel;
617 }
618
619 JPanel buildRulesPanel() {
620 JPanel listPanel = new JPanel(new BorderLayout());
621 JPanel panel = new JPanel();
622 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
623
624 panel.add(Box.createVerticalStrut(10));
625
626 JLabel rulesLabel = new JLabel("Rules:");
627
628 panel.add(rulesLabel);
629
630 JPanel buttonPanel = new JPanel(new GridLayout(0, 2));
631 buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
632
633 JPanel newPanel = new JPanel();
634 JButton newButton = new JButton(" New ");
635 newButton.addActionListener(
636 new AbstractAction() {
637 public void actionPerformed(ActionEvent evt) {
638 int currentRow = table.getSelectedRow();
639 Vector<java.io.Serializable> v = new Vector<>();
640 v.add("");
641 v.add(Color.white);
642 v.add(Color.black);
643
644 if (currentRow < 0) {
645 tableModel.addRow(v);
646 currentRow = table.getRowCount() - 1;
647 } else {
648 tableModel.insertRow(currentRow, v);
649 }
650
651 table.getSelectionModel().setSelectionInterval(
652 currentRow, currentRow);
653 }
654 });
655
656 newPanel.add(newButton);
657
658 JPanel deletePanel = new JPanel();
659 final JButton deleteButton = new JButton(" Delete ");
660 deleteButton.setEnabled(false);
661
662 deleteButton.addActionListener(
663 new AbstractAction() {
664 public void actionPerformed(ActionEvent evt) {
665 int index = table.getSelectionModel().getMaxSelectionIndex();
666
667 if ((index > -1) && (index < table.getRowCount())) {
668 tableModel.removeRow(index);
669
670 if (index > 0) {
671 index = index - 1;
672 }
673
674 if (tableModel.getRowCount() > 0) {
675 table.getSelectionModel().setSelectionInterval(index, index);
676 }
677 }
678 }
679 });
680
681 table.getSelectionModel().addListSelectionListener(
682 e -> {
683 if (!e.getValueIsAdjusting()) {
684 int index = table.getSelectionModel().getMaxSelectionIndex();
685
686 if (index < 0) {
687 deleteButton.setEnabled(false);
688 } else {
689 deleteButton.setEnabled(true);
690 }
691 }
692 });
693
694 deletePanel.add(deleteButton);
695
696 buttonPanel.add(newPanel);
697 buttonPanel.add(deletePanel);
698
699 listPanel.add(panel, BorderLayout.NORTH);
700
701 JPanel tablePanel = new JPanel(new BorderLayout());
702 tableScrollPane.setBorder(BorderFactory.createEtchedBorder());
703 tablePanel.add(tableScrollPane, BorderLayout.CENTER);
704 tablePanel.add(buildUpDownPanel(), BorderLayout.EAST);
705 listPanel.add(tablePanel, BorderLayout.CENTER);
706 listPanel.add(buttonPanel, BorderLayout.SOUTH);
707
708 return listPanel;
709 }
710
711 class ColorListCellRenderer extends JLabel implements ListCellRenderer {
712 ColorListCellRenderer() {
713 setOpaque(true);
714 }
715
716 public Component getListCellRendererComponent(
717 JList list, Object value, int index, boolean isSelected,
718 boolean cellHasFocus) {
719 setText(" ");
720
721 if (isSelected && (index > -1)) {
722 setBorder(BorderFactory.createLineBorder(Color.black, 2));
723 } else {
724 setBorder(BorderFactory.createEmptyBorder());
725 }
726
727 if (value instanceof Color) {
728 setBackground((Color) value);
729 } else {
730 setBackground(Color.white);
731
732 if (value != null) {
733 setText(value.toString());
734 }
735 }
736
737 return this;
738 }
739 }
740
741 class ColorItemListener implements ItemListener {
742 JComboBox box;
743 JDialog dialog;
744 JColorChooser colorChooser;
745 Color lastColor;
746
747 ColorItemListener(final JComboBox box) {
748 this.box = box;
749 colorChooser = new JColorChooser();
750 dialog =
751 JColorChooser.createDialog(
752 box, "Pick a Color", true,
753 colorChooser,
754 e -> {
755 box.insertItemAt(colorChooser.getColor(), 0);
756 box.setSelectedIndex(0);
757 },
758 e -> box.setSelectedItem(lastColor));
759 dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
760 }
761
762 public void itemStateChanged(ItemEvent e) {
763 if (e.getStateChange() == ItemEvent.SELECTED) {
764 if (box.getSelectedItem() instanceof Color) {
765 box.setBackground((Color) box.getSelectedItem());
766 repaint();
767 } else {
768 box.setBackground(Color.white);
769 int selectedRow = table.getSelectedRow();
770 int selectedColumn = table.getSelectedColumn();
771 if (selectedRow != -1 && selectedColumn != -1) {
772 colorChooser.setColor((Color) table.getValueAt(selectedRow, selectedColumn));
773 lastColor = (Color) table.getValueAt(selectedRow, selectedColumn);
774 }
775 dialog.setVisible(true);
776 }
777 }
778 }
779 }
780
781 class ColorTableCellRenderer implements TableCellRenderer {
782 Border border;
783 JPanel panel;
784
785 ColorTableCellRenderer() {
786 panel = new JPanel();
787 panel.setOpaque(true);
788 }
789
790 public Color getCurrentColor() {
791 return panel.getBackground();
792 }
793
794 public Component getTableCellRendererComponent(
795 JTable thisTable, Object value, boolean isSelected, boolean hasFocus, int row,
796 int column) {
797 if (value instanceof Color) {
798 panel.setBackground((Color) value);
799 }
800 if (border == null) {
801 border = BorderFactory.createMatteBorder(2, 2, 2, 2, table.getBackground());
802 }
803
804 panel.setBorder(border);
805
806 return panel;
807 }
808 }
809
810 class ExpressionTableCellRenderer implements TableCellRenderer {
811 JPanel panel = new JPanel();
812 JLabel expressionLabel = new JLabel();
813 JLabel iconLabel = new JLabel();
814 Icon selectedIcon = new SelectedIcon(true);
815 Icon unselectedIcon = new SelectedIcon(false);
816
817 ExpressionTableCellRenderer() {
818 panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
819 panel.setOpaque(true);
820 panel.add(iconLabel);
821 panel.add(Box.createHorizontalStrut(5));
822 panel.add(expressionLabel);
823 }
824
825 void setToolTipText(String text) {
826 panel.setToolTipText(text);
827 }
828
829 public Component getTableCellRendererComponent(
830 JTable thisTable, Object value, boolean isSelected, boolean hasFocus, int row,
831 int column) {
832 if (value == null) {
833 return panel;
834 }
835
836 Vector v = tableModel.getDataVector();
837 Vector r = (Vector) v.elementAt(row);
838 expressionLabel.setText(value.toString());
839
840 if (r.elementAt(1) instanceof Color) {
841 expressionLabel.setBackground((Color) r.elementAt(1));
842 panel.setBackground((Color) r.elementAt(1));
843 }
844
845 if (r.elementAt(2) instanceof Color) {
846 expressionLabel.setForeground((Color) r.elementAt(2));
847 panel.setForeground((Color) r.elementAt(2));
848 }
849
850 if (isSelected) {
851 iconLabel.setIcon(selectedIcon);
852 } else {
853 iconLabel.setIcon(unselectedIcon);
854 }
855
856 return panel;
857 }
858 }
859
860 class SelectedIcon implements Icon {
861 private boolean isSelected;
862 private int width = 9;
863 private int height = 18;
864 private int[] xPoints = new int[4];
865 private int[] yPoints = new int[4];
866
867 public SelectedIcon(boolean isSelected) {
868 this.isSelected = isSelected;
869 xPoints[0] = 0;
870 yPoints[0] = -1;
871 xPoints[1] = 0;
872 yPoints[1] = height;
873 xPoints[2] = width;
874 yPoints[2] = height / 2;
875 xPoints[3] = width;
876 yPoints[3] = (height / 2) - 1;
877 }
878
879 public int getIconHeight() {
880 return height;
881 }
882
883 public int getIconWidth() {
884 return width;
885 }
886
887 public void paintIcon(Component c, Graphics g, int x, int y) {
888 if (isSelected) {
889 int length = xPoints.length;
890 int[] newXPoints = new int[length];
891 int[] newYPoints = new int[length];
892
893 for (int i = 0; i < length; i++) {
894 newXPoints[i] = xPoints[i] + x;
895 newYPoints[i] = yPoints[i] + y;
896 }
897
898 g.setColor(Color.black);
899
900 g.fillPolygon(newXPoints, newYPoints, length);
901 }
902 }
903 }
904 }