/* * Copyright (c) 2009 Kathryn Huxtable and Kenneth Orr. * * This file is part of the SeaGlass Pluggable Look and Feel. * * 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. * * $Id$ */ package com.seaglasslookandfeel.painter; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Shape; import javax.swing.JComponent; import javax.swing.JTextArea; import javax.swing.plaf.ColorUIResource; import com.seaglasslookandfeel.effect.SeaGlassInternalShadowEffect; import com.seaglasslookandfeel.painter.util.ShapeGenerator.CornerSize; /** * TextComponentPainter implementation. */ public final class TextComponentPainter extends AbstractCommonColorsPainter { /** * Control state. */ public static enum Which { BACKGROUND_DISABLED, BACKGROUND_ENABLED, BACKGROUND_SOLID_DISABLED, BACKGROUND_SOLID_ENABLED, BACKGROUND_SELECTED, BORDER_DISABLED, BORDER_FOCUSED, BORDER_ENABLED, } private Color defaultBackground = decodeColor("seaGlassLightBackground"); // Rossi: All round corners like all other text components and added support for separators lines private Color lineSeparatorEnabled = new ColorUIResource(0xebf5fc); private SeaGlassInternalShadowEffect internalShadow = new SeaGlassInternalShadowEffect(); private Which state; private PaintContext ctx; private CommonControlState type; private boolean focused; // Array of current component colors, updated in each paint call private Object[] componentColors; /** * Creates a new TextComponentPainter object. * * @param state the control state to paint. */ public TextComponentPainter(Which state) { super(); this.state = state; this.ctx = new PaintContext(AbstractRegionPainter.PaintContext.CacheMode.FIXED_SIZES); type = (state == Which.BACKGROUND_DISABLED || state == Which.BACKGROUND_SOLID_DISABLED || state == Which.BORDER_DISABLED) ? CommonControlState.DISABLED : CommonControlState.ENABLED; focused = (state == Which.BORDER_FOCUSED); } /** * {@inheritDoc} */ protected void doPaint(Graphics2D g, JComponent c, int width, int height, Object[] extendedCacheKeys) { // Populate componentColors array with colors calculated in getExtendedCacheKeys call. componentColors = extendedCacheKeys; int x = focusInsets.left; int y = focusInsets.top; width -= focusInsets.left + focusInsets.right; height -= focusInsets.top + focusInsets.bottom; switch (state) { case BACKGROUND_DISABLED: case BACKGROUND_ENABLED: case BACKGROUND_SELECTED: paintBackground(g, c, x, y, width, height); break; case BACKGROUND_SOLID_DISABLED: case BACKGROUND_SOLID_ENABLED: paintBackgroundSolid(g, c, x, y, width, height); break; case BORDER_DISABLED: case BORDER_ENABLED: case BORDER_FOCUSED: paintBorder(g, c, x, y, width, height); break; } } /** * {@inheritDoc} */ protected Object[] getExtendedCacheKeys(JComponent c) { Object[] extendedCacheKeys = null; if (state == Which.BACKGROUND_ENABLED) { extendedCacheKeys = new Object[] { getComponentColor(c, "background", defaultBackground, 0.0f, 0.0f, 0) }; } return extendedCacheKeys; } /** * {@inheritDoc} */ protected PaintContext getPaintContext() { return ctx; } /** * Paint the background of an editable control. * * @param g DOCUMENT ME! * @param c DOCUMENT ME! * @param x DOCUMENT ME! * @param y DOCUMENT ME! * @param width DOCUMENT ME! * @param height DOCUMENT ME! */ private void paintBackground(Graphics2D g, JComponent c, int x, int y, int width, int height) { Color color = c.getBackground(); if (state == Which.BACKGROUND_ENABLED) { color = (Color) componentColors[0]; } else if (type == CommonControlState.DISABLED) { color = new Color(color.getRed(), color.getGreen(), color.getBlue(), 0x80); } Shape s = shapeGenerator.createRoundRectangle(x + 1, y + 1, width - 2, height - 2, CornerSize.BORDER); g.setPaint(color); g.fill(s); if (isPaintLineSeperators(c)) { paintLineSeparator(g, c, width, height); } } /** * Test if we should also paint the line seperators. * @param c * @return */ private boolean isPaintLineSeperators(JComponent c) { boolean paintLines = c instanceof JTextArea; // Global settings String globalOverride = System.getProperty("SeaGlass.JTextArea.drawLineSeparator"); if (globalOverride != null && globalOverride.length() > 0) { paintLines = Boolean.valueOf(globalOverride); } // Settings per component Boolean overrideProperty = (Boolean) c.getClientProperty("SeaGlass.JTextArea.drawLineSeparator"); if (overrideProperty != null) { paintLines = overrideProperty; } return paintLines; } /** * Paint the background of an uneditable control, e.g. a JLabel. * * @param g DOCUMENT ME! * @param c DOCUMENT ME! * @param x DOCUMENT ME! * @param y DOCUMENT ME! * @param width DOCUMENT ME! * @param height DOCUMENT ME! */ private void paintBackgroundSolid(Graphics2D g, JComponent c, int x, int y, int width, int height) { Color color = c.getBackground(); if (type == CommonControlState.DISABLED) { color = new Color(color.getRed(), color.getGreen(), color.getBlue(), 0x80); } Shape s = shapeGenerator.createRoundRectangle(x-2, y-2, width+4, height+4, CornerSize.BORDER); g.setPaint(color); g.fill(s); if (isPaintLineSeperators(c)) { paintLineSeparator(g, c, width, height); } } /** * @param g * @param c * @param width * @param height */ private void paintLineSeparator(Graphics2D g, JComponent c, int width, int height) { g.setPaint(lineSeparatorEnabled); int lineYIncrement = g.getFontMetrics(c.getFont()).getHeight(); int lineY = lineYIncrement+c.getInsets().top-1; while (lineY < height) { g.drawLine(c.getInsets().left, lineY, width-c.getInsets().right, lineY); lineY += lineYIncrement; } } /** * Paint the border. * * @param g DOCUMENT ME! * @param c DOCUMENT ME! * @param x DOCUMENT ME! * @param y DOCUMENT ME! * @param width DOCUMENT ME! * @param height DOCUMENT ME! */ private void paintBorder(Graphics2D g, JComponent c, int x, int y, int width, int height) { boolean useToolBarColors = isInToolBar(c); Shape s; if (focused) { s = shapeGenerator.createRoundRectangle(x - 2, y - 2, width + 3, height + 3, CornerSize.OUTER_FOCUS); g.setPaint(getFocusPaint(s, FocusType.OUTER_FOCUS, useToolBarColors)); g.draw(s); s = shapeGenerator.createRoundRectangle(x - 1, y - 1, width + 1, height + 1, CornerSize.INNER_FOCUS); g.setPaint(getFocusPaint(s, FocusType.INNER_FOCUS, useToolBarColors)); g.draw(s); } if (type != CommonControlState.DISABLED) { s = shapeGenerator.createRoundRectangle(x + 1, x + 1, width - 2, height - 2, CornerSize.BORDER); internalShadow.fill(g, s, false, true); } s = shapeGenerator.createRoundRectangle(x, y, width - 1, height - 1, CornerSize.BORDER); g.setPaint(getTextBorderPaint(type, !focused && useToolBarColors)); g.draw(s); } }