/* * Copyright 2001-2013 Stephen Colebourne * * Licensed 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.joda.beans.ui.swing.component; import java.awt.Color; import java.awt.Component.BaselineResizeBehavior; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.util.Objects; import javax.accessibility.Accessible; import javax.swing.JComponent; import javax.swing.plaf.TextUI; import javax.swing.text.BadLocationException; import javax.swing.text.EditorKit; import javax.swing.text.JTextComponent; import javax.swing.text.Position.Bias; import javax.swing.text.View; /** * A UI delegate that exists to indicate that the component is in error. */ public class ErrorBackgroundTextUI extends TextUI { /** * The error background color. */ private static final Color ERROR_BACKGROUND = new Color(255, 219, 219); /** * The size of the error marker. */ private static final int ERROR_SIZE = 8; /** * The size of the error padding. */ private static final int ERROR_PAD = 4; /** * The underlying UI delegate. */ private final TextUI ui; /** * The main component being decorated. * This is specified in cases like {@code JComboBox}. */ private final JComponent component; /** * Creates an instance. * * @param ui the underlying, not null */ public ErrorBackgroundTextUI(TextUI ui) { this(ui, null); } /** * Creates an instance. * * @param ui the underlying, not null * @param component the main component that stores the error status, null to derive */ public ErrorBackgroundTextUI(TextUI ui, JComponent component) { this.ui = Objects.requireNonNull(ui, "ui"); this.component = component; } //------------------------------------------------------------------------- @Override public void installUI(JComponent c) { ui.installUI(c); } @Override public void uninstallUI(JComponent c) { ui.uninstallUI(c); } @Override public void paint(Graphics g, JComponent c) { ui.paint(g, c); } @Override public void update(Graphics g, JComponent c) { JComponent main = (component != null ? component : c); if (SwingUtils.getErrorStatus(main).isError()) { if (c.isOpaque()) { g.setColor(ERROR_BACKGROUND); g.fillRect(0, 0, c.getWidth(), c.getHeight()); c.setOpaque(false); ui.paint(g, c); paintMarker(g, c); c.setOpaque(true); } else { g.setColor(ERROR_BACKGROUND); g.fillRect(0, 0, c.getWidth(), c.getHeight()); ui.paint(g, c); paintMarker(g, c); } } else { ui.update(g, c); } } private void paintMarker(Graphics g, JComponent c) { Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int w = c.getWidth(); int h = c.getHeight(); int x = w - ERROR_PAD - ERROR_SIZE; int y = (h - ERROR_SIZE) / 2; g2.setPaint(Color.red); g2.fillRect(x, y, ERROR_SIZE + 1, ERROR_SIZE + 1); g2.setPaint(Color.white); g2.drawLine(x, y, x + ERROR_SIZE, y + ERROR_SIZE); g2.drawLine(x, y + ERROR_SIZE, x + ERROR_SIZE, y); } @Override public Dimension getPreferredSize(JComponent c) { return ui.getPreferredSize(c); } @Override public Dimension getMinimumSize(JComponent c) { return ui.getMinimumSize(c); } @Override public Dimension getMaximumSize(JComponent c) { return ui.getMaximumSize(c); } @Override public boolean contains(JComponent c, int x, int y) { return ui.contains(c, x, y); } @Override public int getBaseline(JComponent c, int width, int height) { return ui.getBaseline(c, width, height); } @Override public BaselineResizeBehavior getBaselineResizeBehavior(JComponent c) { return ui.getBaselineResizeBehavior(c); } @Override public int getAccessibleChildrenCount(JComponent c) { return ui.getAccessibleChildrenCount(c); } @Override public Accessible getAccessibleChild(JComponent c, int i) { return ui.getAccessibleChild(c, i); } @Override public Rectangle modelToView(JTextComponent t, int pos) throws BadLocationException { return ui.modelToView(t, pos); } @Override public Rectangle modelToView(JTextComponent t, int pos, Bias bias) throws BadLocationException { return ui.modelToView(t, pos, bias); } @Override public int viewToModel(JTextComponent t, Point pt) { return ui.viewToModel(t, pt); } @Override public int viewToModel(JTextComponent t, Point pt, Bias[] biasReturn) { return ui.viewToModel(t, pt, biasReturn); } @Override public int getNextVisualPositionFrom(JTextComponent t, int pos, Bias b, int direction, Bias[] biasRet) throws BadLocationException { return ui.getNextVisualPositionFrom(t, pos, b, direction, biasRet); } @Override public void damageRange(JTextComponent t, int p0, int p1) { ui.damageRange(t, p0, p1); } @Override public void damageRange(JTextComponent t, int p0, int p1, Bias firstBias, Bias secondBias) { ui.damageRange(t, p0, p1, firstBias, secondBias); } @Override public EditorKit getEditorKit(JTextComponent t) { return ui.getEditorKit(t); } @Override public View getRootView(JTextComponent t) { return ui.getRootView(t); } @Override public String getToolTipText(JTextComponent t, Point pt) { return ui.getToolTipText(t, pt); } }