From 784e5073b4d2868506bce2a724535b269cdad17d Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 29 Sep 2015 14:06:33 +0300 Subject: [PATCH] use text field in color panel to paint focus ring --- .../src/com/intellij/ui/ColorPanel.java | 137 ++++++++++++++---- .../ui/laf/darcula/ui/DarculaTextBorder.java | 5 + .../src/messages/UIBundle.properties | 1 + 3 files changed, 116 insertions(+), 27 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/ColorPanel.java b/platform/platform-api/src/com/intellij/ui/ColorPanel.java index 910ee7fdef7b..44e5ab7ea433 100644 --- a/platform/platform-api/src/com/intellij/ui/ColorPanel.java +++ b/platform/platform-api/src/com/intellij/ui/ColorPanel.java @@ -15,31 +15,43 @@ */ package com.intellij.ui; +import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.text.BadLocationException; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import static java.beans.EventHandler.create; +import static java.util.Locale.ENGLISH; public class ColorPanel extends JComponent { private final List myListeners = new CopyOnWriteArrayList(); + private final JTextField myTextField = new JTextField(); private boolean myEditable; private ActionEvent myEvent; private Color myColor; public ColorPanel() { + addImpl(myTextField, null, 0); setEditable(true); setMinimumSize(JBUI.size(10, 10)); - addMouseListener(create(MouseListener.class, this, "onPressed", null, "mousePressed")); - addKeyListener(create(KeyListener.class, this, "onPressed", "keyCode", "keyPressed")); - addFocusListener(create(FocusListener.class, this, "repaint")); + myTextField.addMouseListener(create(MouseListener.class, this, "onPressed", null, "mousePressed")); + myTextField.addKeyListener(create(KeyListener.class, this, "onPressed", "keyCode", "keyPressed")); + myTextField.setEditable(false); + RelativeFont.TINY.install(myTextField); + Painter.BACKGROUND.install(myTextField, true); } + @SuppressWarnings("unused") // used from event handler public void onPressed(int keyCode) { if (keyCode == KeyEvent.VK_SPACE) { onPressed(); @@ -67,13 +79,10 @@ public class ColorPanel extends JComponent { } @Override - protected void paintComponent(Graphics g) { - g.setColor(hasFocus() ? JBColor.BLACK : JBColor.border()); - g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); - if (myColor != null && isEnabled()) { - g.setColor(myColor); - g.fillRect(2, 2, getWidth() - 4, getHeight() - 4); - } + public void doLayout() { + Rectangle bounds = new Rectangle(getWidth(), getHeight()); + JBInsets.removeFrom(bounds, getInsets()); + myTextField.setBounds(bounds); } @Override @@ -81,26 +90,21 @@ public class ColorPanel extends JComponent { if (isPreferredSizeSet()) { return super.getPreferredSize(); } - Font font = getFont(); + Dimension size = new Dimension(); + Font font = myTextField.getFont(); if (font != null) { - int size = font.getSize(); - if (size > 6) { - return new Dimension(4 + 2 * size, 4 + size); - } + FontMetrics fm = myTextField.getFontMetrics(font); + size.width = fm.stringWidth(" 000000 "); + size.height = fm.getHeight(); } - return getMinimumSize(); + JBInsets.addTo(size, myTextField.getInsets()); + JBInsets.addTo(size, getInsets()); + return size; } @Override public String getToolTipText() { - if (myColor == null || !isEnabled()) { - return null; - } - StringBuilder buffer = new StringBuilder("0x").append(ColorUtil.toHex(myColor).toUpperCase()); - if (myEditable && isEnabled()) { - buffer.append(" (Click to customize)"); - } - return buffer.toString(); + return myTextField.getToolTipText(); } public void removeActionListener(ActionListener actionlistener) { @@ -118,12 +122,91 @@ public class ColorPanel extends JComponent { public void setSelectedColor(@Nullable Color color) { myColor = color; - repaint(); + updateSelectedColor(); + } + + @SuppressWarnings("UseJBColor") + private void updateSelectedColor() { + boolean enabled = isEnabled(); + if (enabled && myEditable) { + myTextField.setEnabled(true); + myTextField.setToolTipText(UIBundle.message("color.panel.select.color.tooltip.text")); + } + else { + myTextField.setEnabled(false); + myTextField.setToolTipText(null); + } + Color color = enabled ? myColor : null; + if (color != null) { + myTextField.setText(' ' + ColorUtil.toHex(color).toUpperCase(ENGLISH) + ' '); + } + else { + myTextField.setText(null); + color = getBackground(); + } + myTextField.setBackground(color); + myTextField.setSelectedTextColor(color); + if (color != null) { + int gray = (int)(0.212656 * color.getRed() + 0.715158 * color.getGreen() + 0.072186 * color.getBlue()); + int delta = gray < 0x20 ? 0x60 : gray < 0x50 ? 0x40 : gray < 0x80 ? 0x20 : gray < 0xB0 ? -0x20 : gray < 0xE0 ? -0x40 : -0x60; + gray += delta; + color = new Color(gray, gray, gray); + myTextField.setDisabledTextColor(color); + myTextField.setSelectionColor(color); + gray += delta; + color = new Color(gray, gray, gray); + myTextField.setForeground(color); + } } public void setEditable(boolean editable) { myEditable = editable; - setFocusable(editable); - repaint(); + updateSelectedColor(); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + updateSelectedColor(); + } + + @Override + public void repaint() { + super.repaint(); + } + + private static class Painter implements Highlighter.HighlightPainter, PropertyChangeListener { + private static final String PROPERTY = "highlighter"; + private static final Painter BACKGROUND = new Painter(); + + @Override + public void paint(Graphics g, int p0, int p1, Shape shape, JTextComponent component) { + Color color = component.getBackground(); + if (color != null) { + g.setColor(color); + Rectangle bounds = shape instanceof Rectangle ? (Rectangle)shape : shape.getBounds(); + g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); + } + } + + @Override + public void propertyChange(PropertyChangeEvent event) { + Object source = event.getSource(); + if ((source instanceof JTextComponent) && PROPERTY.equals(event.getPropertyName())) { + install((JTextComponent)source, false); + } + } + + private void install(JTextComponent component, boolean listener) { + try { + Highlighter highlighter = component.getHighlighter(); + if (highlighter != null) highlighter.addHighlight(0, 0, this); + } + catch (BadLocationException ignored) { + } + if (listener) { + component.addPropertyChangeListener(PROPERTY, this); + } + } } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java index 44635c4d9748..ac1b5ceac5a8 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java @@ -17,10 +17,12 @@ package com.intellij.ide.ui.laf.darcula.ui; import com.intellij.ide.ui.laf.darcula.DarculaUIUtil; import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.ui.ColorPanel; import com.intellij.ui.Gray; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; +import javax.swing.JTextField; import javax.swing.border.Border; import javax.swing.plaf.UIResource; import javax.swing.text.JTextComponent; @@ -39,6 +41,9 @@ public class DarculaTextBorder implements Border, UIResource { else if (TextFieldWithPopupHandlerUI.isSearchField(c)) { return JBUI.insets(vOffset, 4 + 16 + 3, vOffset, 7 + 16).asUIResource(); } + else if (c instanceof JTextField && c.getParent() instanceof ColorPanel) { + return JBUI.insets(3, 3, 2, 2).asUIResource(); + } else { return JBUI.insets(vOffset, 7, vOffset, 7).asUIResource(); } diff --git a/platform/platform-resources-en/src/messages/UIBundle.properties b/platform/platform-resources-en/src/messages/UIBundle.properties index 015de411bde1..c814bcc17cff 100644 --- a/platform/platform-resources-en/src/messages/UIBundle.properties +++ b/platform/platform-resources-en/src/messages/UIBundle.properties @@ -1,4 +1,5 @@ color.panel.select.color.dialog.description=Select Color +color.panel.select.color.tooltip.text=Click to customize insert.file.path.to.text.action.name=Insert Path order.entries.panel.export.column.name=Export tree.view.expand.all.action.name=Expand All