com.jgoodies.looks.plastic.PlasticXPIconFactory Maven / Gradle / Ivy
Show all versions of jgoodies-looks Show documentation
/*
* Copyright (c) 2001-2012 JGoodies Karsten Lentzsch. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of JGoodies Karsten Lentzsch nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jgoodies.looks.plastic;
import java.awt.*;
import java.io.Serializable;
import javax.swing.*;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.metal.MetalLookAndFeel;
import com.jgoodies.common.base.Strings;
import com.jgoodies.looks.LookUtils;
/**
* Factory class that vends {@code Icon}s for the JGoodies
* Plastic XP look&feel.
* These icons are used extensively in PlasticXP via the defaults mechanism.
* While other look and feels often use GIFs for icons, creating icons
* in code facilitates switching to other themes.
*
* Each method in this class returns either an {@code Icon} or
* {@code null}, where {@code null} implies that there is
* no default icon.
*
* @author Karsten Lentzsch
* @version $Revision: 1.13 $
*/
public final class PlasticXPIconFactory {
private static CheckBoxIcon checkBoxIcon;
private static RadioButtonIcon radioButtonIcon;
private PlasticXPIconFactory() {
// Overrides default constructor; prevents instantiation.
}
/**
* Lazily creates and returns the check box icon.
*
* @return the check box icon
*/
static Icon getCheckBoxIcon() {
if (checkBoxIcon == null) {
checkBoxIcon = new CheckBoxIcon();
}
return checkBoxIcon;
}
/**
* Lazily creates and returns the radio button icon.
*
* @return the check box icon
*/
static Icon getRadioButtonIcon() {
if (radioButtonIcon == null) {
radioButtonIcon = new RadioButtonIcon();
}
return radioButtonIcon;
}
/**
* Paints the the icon and focus border for Plastic XP check boxes.
*/
private static final class CheckBoxIcon implements Icon, UIResource, Serializable {
private static final int SIZE = LookUtils.IS_LOW_RESOLUTION ? 13 : 15;
@Override
public int getIconWidth() { return SIZE; }
@Override
public int getIconHeight() { return SIZE; }
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
JCheckBox cb = (JCheckBox) c;
ButtonModel model = cb.getModel();
Graphics2D g2 = (Graphics2D) g;
boolean paintFocus = model.isArmed() && !model.isPressed()
|| cb.hasFocus() && Strings.isBlank(cb.getText());
final RenderingHints.Key key = RenderingHints.KEY_ANTIALIASING;
Object newAAHint = RenderingHints.VALUE_ANTIALIAS_ON;
Object oldAAHint = g2.getRenderingHint(key);
if (newAAHint != oldAAHint) {
g2.setRenderingHint(key, newAAHint);
} else {
oldAAHint = null;
}
drawBorder(g2, model.isEnabled(), x, y, SIZE - 1, SIZE - 1);
drawFill(g2, model.isPressed(), x + 1, y + 1, SIZE - 2, SIZE - 2);
if (paintFocus) {
drawFocus(g2, x + 1, y + 1, SIZE - 3, SIZE - 3);
}
if (model.isSelected()) {
drawCheck(g2, model.isEnabled(), x + 3, y + 3, SIZE - 7, SIZE - 7);
}
if (oldAAHint != null) {
g2.setRenderingHint(key, oldAAHint);
}
}
private static void drawBorder(Graphics2D g2, boolean enabled, int x, int y, int width, int height) {
g2.setColor(enabled
? PlasticLookAndFeel.getControlDarkShadow()
: MetalLookAndFeel.getControlDisabled());
g2.drawRect(x, y, width, height);
}
private static void drawCheck(Graphics2D g2, boolean enabled, int x, int y, int width, int height) {
g2.setColor(enabled
? UIManager.getColor("CheckBox.check")
: MetalLookAndFeel.getControlDisabled());
int right = x + width;
int bottom = y + height;
int startY = y + height / 3;
int turnX = x + width / 2 - 2;
g2.drawLine(x , startY , turnX, bottom-3);
g2.drawLine(x , startY + 1, turnX, bottom-2);
g2.drawLine(x , startY + 2, turnX, bottom-1);
g2.drawLine(turnX + 1, bottom - 2, right, y );
g2.drawLine(turnX + 1, bottom - 1, right, y + 1 );
g2.drawLine(turnX + 1, bottom , right, y + 2 );
}
private static void drawFill(Graphics2D g2, boolean pressed, int x, int y, int w, int h) {
Color upperLeft;
Color lowerRight;
if (pressed) {
upperLeft = MetalLookAndFeel.getControlShadow();
lowerRight = PlasticLookAndFeel.getControlHighlight();
} else {
upperLeft = PlasticLookAndFeel.getControl();
lowerRight = PlasticLookAndFeel.getControlHighlight().brighter();
}
g2.setPaint(new GradientPaint(x, y, upperLeft, x + w, y + h, lowerRight));
g2.fillRect(x, y, w, h);
}
private static void drawFocus(Graphics2D g2, int x, int y, int width, int height) {
g2.setPaint(new GradientPaint(
x,
y,
PlasticLookAndFeel.getFocusColor().brighter(),
width,
height,
PlasticLookAndFeel.getFocusColor() /*.darker()*/
));
g2.drawRect(x, y, width, height);
g2.drawRect(x + 1, y + 1, width - 2, height - 2);
}
}
/**
* Paints the the icon and focus border for Plastic XP check boxes.
*/
private static final class RadioButtonIcon implements Icon, UIResource, Serializable {
private static final int SIZE = LookUtils.IS_LOW_RESOLUTION ? 13 : 15;
private static final Stroke FOCUS_STROKE = new BasicStroke(2);
@Override
public int getIconWidth() { return SIZE; }
@Override
public int getIconHeight() { return SIZE; }
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D g2 = (Graphics2D) g;
AbstractButton rb = (AbstractButton) c;
ButtonModel model = rb.getModel();
boolean paintFocus = model.isArmed() && !model.isPressed()
|| rb.hasFocus() && Strings.isBlank(rb.getText());
final RenderingHints.Key key = RenderingHints.KEY_ANTIALIASING;
Object newAAHint = RenderingHints.VALUE_ANTIALIAS_ON;
Object oldAAHint = g2.getRenderingHint(key);
if (newAAHint != oldAAHint) {
g2.setRenderingHint(key, newAAHint);
} else {
oldAAHint = null;
}
drawFill(g2, model.isPressed(), x, y, SIZE - 1, SIZE - 1);
if (paintFocus) {
drawFocus(g2, x + 1, y + 1, SIZE - 3, SIZE - 3);
}
if (model.isSelected()) {
drawCheck(g2, c, model.isEnabled(), x + 4, y + 4, SIZE - 8, SIZE - 8);
}
drawBorder(g2, model.isEnabled(), x, y, SIZE-1, SIZE-1);
if (oldAAHint != null) {
g2.setRenderingHint(key, oldAAHint);
}
}
private static void drawBorder(Graphics2D g2, boolean enabled, int x, int y, int w, int h) {
g2.setColor(enabled
? PlasticLookAndFeel.getControlDarkShadow()
: MetalLookAndFeel.getControlDisabled());
g2.drawOval(x, y, w, h);
}
private static void drawCheck(Graphics2D g2, Component c, boolean enabled, int x, int y, int w, int h) {
g2.translate(x,y);
if (enabled) {
g2.setColor(UIManager.getColor("RadioButton.check"));
g2.fillOval(0,0,w,h);
UIManager.getIcon("RadioButton.checkIcon").paintIcon(c, g2, 0,0);
} else {
g2.setColor(MetalLookAndFeel.getControlDisabled());
g2.fillOval(0,0,w,h);
}
g2.translate(-x, -y);
}
private static void drawFill(Graphics2D g2, boolean pressed, int x, int y, int w, int h) {
Color upperLeft;
Color lowerRight;
if (pressed) {
upperLeft = MetalLookAndFeel.getControlShadow();
lowerRight = PlasticLookAndFeel.getControlHighlight();
} else {
upperLeft = PlasticLookAndFeel.getControl();
lowerRight = PlasticLookAndFeel.getControlHighlight().brighter();
}
g2.setPaint(new GradientPaint(x, y, upperLeft, x + w, y + h, lowerRight));
g2.fillOval(x, y, w, h);
}
private static void drawFocus(Graphics2D g2, int x, int y, int w, int h) {
g2.setPaint(
new GradientPaint(
x,
y,
PlasticLookAndFeel.getFocusColor().brighter(),
w,
h,
PlasticLookAndFeel.getFocusColor()));
Stroke stroke = g2.getStroke();
g2.setStroke(FOCUS_STROKE);
g2.drawOval(x, y, w, h);
g2.setStroke(stroke);
}
}
}