JComponent () { final JBTable table = new JBTable(createFilteringModel()) { @Override public boolean editCellAt(int row, int column, EventObject e) { if (isCellEditable(row, column) && e instanceof MouseEvent) { var pair = (Pair<?, ?>)getValueAt(row, 0); Object key = pair.first; Object value = pair.second; final Ref<Boolean> changed = Ref.create(false); if (value instanceof Color) { ColorChooserService.getInstance().showPopup(null, (Color)value, new ColorListener() { @Override public void colorChanged(Color color, Object source) { if (color != null) { final ColorUIResource colorUIResource = new ColorUIResource(color); // MultiUIDefaults overrides remove but does not override put. // So to avoid duplications we should first remove the value and then put it again. updateValue(pair, colorUIResource, row, column); changed.set(true); } } }); } else if (value instanceof Boolean) { updateValue(pair, !((Boolean)value), row, column); changed.set(true); } else if (value instanceof Integer) { Integer newValue = editNumber(key.toString(), value.toString(), Integer::parseInt); if (newValue != null) { updateValue(pair, newValue, row, column); changed.set(true); } } else if (value instanceof Float) { Float newValue = editNumber(key.toString(), value.toString(), Float::parseFloat); if (newValue != null) { updateValue(pair, newValue, row, column); changed.set(true); } } else if (value instanceof EmptyBorder) { Insets i = ((Border)value).getBorderInsets(null); String oldInsets = String.format("%d,%d,%d,%d", i.top, i.left, i.bottom, i.right); Insets newInsets = editInsets(key.toString(), oldInsets); if (newInsets != null) { updateValue(pair, new JBEmptyBorder(newInsets), row, column); changed.set(true); } } else if (value instanceof Insets i) { String oldInsets = String.format("%d,%d,%d,%d", i.top, i.left, i.bottom, i.right); Insets newInsets = editInsets(key.toString(), oldInsets); if (newInsets != null) { updateValue(pair, newInsets, row, column); changed.set(true); } } else if (value instanceof GrayFilter f) { String oldFilter = String.format("%d,%d,%d", f.getBrightness(), f.getContrast(), f.getAlpha()); GrayFilter newValue = editGrayFilter(key.toString(), oldFilter); if (newValue != null) { updateValue(pair, newValue, row, column); changed.set(true); } } else if (value instanceof Font) { Font newValue = editFontSize(key.toString(), (Font)value); if (newValue != null) { UIManager.getDefaults().remove(key); UIManager.getDefaults().put(key, newValue); setValueAt(newValue, row, column); changed.set(true); } } else if (value instanceof Dimension d) { String oldDimension = String.format("%d,%d", d.width, d.height); Dimension newDimension = editDimension(key.toString(), oldDimension); if (newDimension != null) { updateValue(pair, newDimension, row, column); changed.set(true); } } if (changed.get()) { ApplicationManager.getApplication().invokeLater(() -> { LafManager.getInstance().repaintUI(); }); } PropertiesComponent.getInstance().setValue(ShowUIDefaultsContent.LAST_SELECTED_KEY, key.toString()); } return false; } void updateValue(Pair<?, ?> value, Object newValue, int row, int col) { UIManager.getDefaults().remove(value.first); UIManager.getDefaults().put(value.first, newValue); setValueAt(Pair.create(value.first, newValue), row, col); } }; table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { value = column == 0 ? ((Pair<?, ?>)value).first : ((Pair<?, ?>)value).second; if (value instanceof Boolean) { TableCellRenderer renderer = table.getDefaultRenderer(Boolean.class); if (renderer != null) { JCheckBox box = (JCheckBox)renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); box.setHorizontalAlignment(SwingConstants.LEFT); return box; } } final JLabel label = new JLabel(value == null ? "" : value.toString()); final JPanel panel = simplePanel(label); if (value instanceof Color c) { label.setText( String.format(" [%d,%d,%d] #%s", c.getRed(), c.getGreen(), c.getBlue(), StringUtil.toUpperCase(ColorUtil.toHex(c)))); Color fg = ColorUtil.isDark(c) ? Gray.xFF : Gray.x00; label.setForeground(fg); panel.setBackground(c); return panel; } else if (value instanceof Icon) { try { final Icon icon = new IconWrap((Icon)value); if (icon.getIconHeight() <= 20) { label.setIcon(icon); } label.setText(String.format("(%dx%d) %s)", icon.getIconWidth(), icon.getIconHeight(), label.getText())); } catch (Throwable e1) {// } return panel; } else if (value instanceof Border) { try { final Insets i = ((Border)value).getBorderInsets(null); label.setText(String.format("[%d, %d, %d, %d] %s", i.top, i.left, i.bottom, i.right, label.getText())); return panel; } catch (Exception ignore) { } } return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } }); TableSpeedSearch.installOn(table, (o, cell) -> cell.column == 1 ? null : String.valueOf(o)); table.setShowGrid(false); TableHoverListener.DEFAULT.removeFrom(table); content = new ShowUIDefaultsContent(table); DataProvider provider = dataId -> { if (PlatformDataKeys.COPY_PROVIDER.is(dataId)) { if ((content.searchField.hasFocus() && StringUtil.isEmpty(content.searchField.getSelectedText())) || content.table.hasFocus()) { int[] rows = content.table.getSelectedRows(); if (rows.length > 0) { return new TextCopyProvider() { @Override public @NotNull ActionUpdateThread getActionUpdateThread() { return ActionUpdateThread.EDT; } @Override public Collection<String> getTextLinesToCopy() { List<String> result = new ArrayList<>(); String tail = rows.length > 1 ? "," : ""; for (int row : rows) { var pair = (Pair<?, ?>)content.table.getModel().getValueAt(row, 0); if (pair.second instanceof Color) { result.add("\"" + pair.first.toString() + "\": \"" + ColorUtil.toHtmlColor((Color)pair.second) + "\"" + tail); } else { result.add("\"" + pair.first.toString() + "\": \"" + pair.second + "\"" + tail); } } return result; } }; } } } return null; }; DataManager.registerDataProvider(content.table, provider); DataManager.registerDataProvider(content.searchField, provider); return content.panel; }