Skip to main content

SwingX 1.6.5-1 Released

6 replies [Last post]
kschaefe
Offline
Joined: 2006-06-08
Points: 0

Just released the code into Java.net Maven repo. Sync to Central to be down within four hours.

Karl

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
oscarl0208
Offline
Joined: 2013-04-17
Points: 0

public class TestJXButton
{

static public final Color black40 = new Color(0,0,0,40);
static public final Color black40t = new Color(0,0,0,100);
static private final Color SYSTEM_OUTLINE_COLOR = new Color(90, 135, 165);
static public enum SEGMENT {BEGIN,SEGMENT,END,SOLO};
private static final BufferedImage prefsIcon = loadImage("/com/neovest/fa/resources/images/goptions.png");
protected static Dimension menuOptionsButtonSize = new Dimension(36, 48);

/**
* @param args
*/
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setTitle("Test JXButton");
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
JPanel panel2 = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.black));
panel2.setBorder(BorderFactory.createLineBorder(Color.black));
JXButton button = createUtilButton(prefsIcon, menuOptionsButtonSize, menuOptionsButtonSize, black40t, false);
panel.add(button, BorderLayout.EAST);

//old method
JXButton button2 = createUtilButton(prefsIcon, menuOptionsButtonSize, menuOptionsButtonSize, black40, true);
panel2.add(button2, BorderLayout.EAST);

frame.add(panel, BorderLayout.NORTH);
frame.add(panel2, BorderLayout.SOUTH);
frame.setVisible(true);

}

static public JXButton createUtilButton(final Image image, final Dimension minSize, final Dimension prefSize, final Color buttonColor, boolean oldButton)
{

JXButton button;
if (oldButton)
{
button = new JXXButton();
}
else
{
button = new JXButton();

}

button.setPreferredSize(prefSize);
button.setMinimumSize(minSize);
button.setBorder(BorderFactory.createEmptyBorder());
button.setOpaque(false);
button.setFocusPainted(false);

Paint paint = buttonColor;
Shape shape;

shape = constructSegmentedBeginShape(prefSize, 2.1f);

float fgStartingAlpha = 0.05f;

final ShapePainter borderPainter = new ShapePainter();
borderPainter.setShape(shape);
borderPainter.setFillPaint(paint);
borderPainter.setAntialiasing(true);
borderPainter.setBorderWidth(2.1f);
borderPainter.setBorderPaint(SYSTEM_OUTLINE_COLOR);

final ShadowPathEffect shadow = new ShadowPathEffect();
borderPainter.setAreaEffects(shadow);
shadow.setEffectWidth(2);
shadow.setBrushColor(Color.black);
shadow.setShouldFillShape(true);
shadow.setRenderInsideShape(true);
shadow.setOffset(new Point2D.Float(0f, 2f));
shadow.setBrushSteps(4);

final ShadowPathEffect shadow1 = new ShadowPathEffect();
borderPainter.setAreaEffects(shadow1);
shadow1.setEffectWidth(1);
shadow1.setBrushColor(Color.white);
shadow1.setShouldFillShape(true);
shadow1.setRenderInsideShape(true);
shadow1.setOffset(new Point2D.Float(0f, -0.5f));
shadow1.setBrushSteps(4);

final AlphaPainter fgAlphaPainter = new AlphaPainter();
fgAlphaPainter.setPainters(borderPainter);

BufferedImage bImage = toBufferedImage( new ImageIcon(image));

final ImageInterpolatorPainter imagePainter = new ImageInterpolatorPainter();
imagePainter.setPrimaryImage(bImage);
imagePainter.setSecondaryImage(bImage);
imagePainter.setAlpha(fgStartingAlpha);

final CompoundPainter bgPainter = new CompoundPainter();
bgPainter.setPainters(fgAlphaPainter, imagePainter);

button.setBackgroundPainter(bgPainter);
return button;
}

public static BufferedImage toBufferedImage(ImageIcon imageIcon)
{
Image image = imageIcon.getImage();

BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);

Graphics2D g = bimage.createGraphics();

g.drawImage(image, 0, 0, null);
g.dispose();

return bimage;

}

public static BufferedImage loadImage(String resource)
{
try
{
return GraphicsUtilities.loadCompatibleImage(TestJXButton.class.getResource(resource));
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}

static private Shape constructSegmentedBeginShape(final Dimension bounds, final float lineWidth)
{
final double startX = bounds.getWidth()/2;
final double startY = 0;
final double endX = (bounds.getWidth()*2-lineWidth);
final double endY = bounds.getHeight()-lineWidth;

final Arc2D.Double arc = new Arc2D.Double(startX, startY, endX, endY, 90, 180, Arc2D.OPEN);
return arc;
}

@SuppressWarnings("serial")
static private class JXXButton extends org.jdesktop.swingx.JXButton
{
// properties used to split foreground and background painting.
// overwritten to suppress event notification while painting
private String text = "";
private boolean borderPainted;
private boolean contentAreaFilled;

private Painter fgPainter = new DefaultForegroundPainter();
private Painter bgPainter = new DefaultBackgroundPainter();

/** Creates a new instance of JXButton */
public JXXButton()
{
}

@Override
protected void init(String text, Icon icon)
{
borderPainted = true;
contentAreaFilled = true;
super.init(text, icon);
}

@Override
public void setText(String text)
{
this.text = text;
super.setText(text);
}

@Override
public void repaint()
{
if (painting)
{
// skip repaint requests while painting
return;
}
super.repaint();
}

@Override
public String getText()
{
return this.text;
}

@Override
public void setBorderPainted(boolean b)
{
this.borderPainted = b;
super.setBorderPainted(b);
}

@Override
public boolean isBorderPainted()
{
return this.borderPainted;
}

@Override
public void setContentAreaFilled(boolean b)
{
this.contentAreaFilled = b;
super.setContentAreaFilled(b);
}

@Override
public boolean isContentAreaFilled()
{
return this.contentAreaFilled;
}

public Painter getBackgroundPainter()
{
return bgPainter;
}

public void setBackgroundPainter(Painter p)
{
Painter old = getBackgroundPainter();
this.bgPainter = p;
firePropertyChange("backgroundPainter", old, getBackgroundPainter());
repaint();
}

public Painter getForegroundPainter()
{
return fgPainter;
}

public void setForegroundPainter(Painter p)
{
Painter old = getForegroundPainter();
this.fgPainter = p;
firePropertyChange("foregroundPainter", old, getForegroundPainter());
repaint();
}

private boolean paintBorderInsets = true;
private boolean painting;
private boolean opaque = true;

/**
* Returns true if the background painter should paint where the border is
* or false if it should only paint inside the border. This property is true
* by default. This property affects the width, height, and intial transform
* passed to the background painter.
*/
public boolean isPaintBorderInsets()
{
return paintBorderInsets;
}

/**
* Sets the paintBorderInsets property. Set to true if the background
* painter should paint where the border is or false if it should only paint
* inside the border. This property is true by default. This property
* affects the width, height, and intial transform passed to the background
* painter.
*
* This is a bound property.
*/
public void setPaintBorderInsets(boolean paintBorderInsets)
{
boolean old = this.isPaintBorderInsets();
this.paintBorderInsets = paintBorderInsets;
firePropertyChange("paintBorderInsets", old, isPaintBorderInsets());
}

@Override
public boolean isOpaque()
{
return painting ? opaque : super.isOpaque();
}

@Override
protected void paintComponent(Graphics g)
{
Painter bgPainter = getBackgroundPainter();
Painter fgPainter = getForegroundPainter();
if (painting || (bgPainter == null && fgPainter == null))
{
super.paintComponent(g);
}
else
{
invokePainter(g, bgPainter);
invokePainter(g, fgPainter);
}
}

private void invokePainter(Graphics g, Painter ptr)
{
if (ptr == null)
return;

Graphics2D g2d = (Graphics2D) g.create();

try
{
if (isPaintBorderInsets())
{
ptr.paint(g2d, this, getWidth(), getHeight());
}
else
{
Insets ins = this.getInsets();
g2d.translate(ins.left, ins.top);
ptr.paint(g2d, this, this.getWidth() - ins.left - ins.right, this.getHeight() - ins.top - ins.bottom);
}
}
finally
{
g2d.dispose();
}
}

protected void setPainting(boolean b)
{
painting = b;
}
}

// paint anything but text and icon
private final static class DefaultBackgroundPainter extends AbstractPainter
{
@Override
protected void doPaint(Graphics2D g, JXButton b, int width, int height)
{
JXXButton bb = (JXXButton) b;
boolean op = bb.isOpaque();
// have to read this before setting painting == true !!!
bb.setOpaque(bb.isOpaque());
bb.setPainting(true);
String tmp = bb.text;
// #swingx-874
Icon tmpIcon = bb.getIcon();
bb.setIcon(null);
bb.text = "";
try
{
b.paint(g);
}
finally
{
// restore original values no matter what
bb.opaque = op;
bb.text = tmp;
bb.setIcon(tmpIcon);
bb.setPainting(false);
}
}

// if any of the state of the JButton that affects the background has
// changed,
// then I must clear the cache. This is really hard to get right, there
// are
// bound to be bugs. An alternative is to NEVER cache.
@Override
protected boolean shouldUseCache()
{
return false;
}
}

// paint only a text and icon (if any)
private final static class DefaultForegroundPainter extends AbstractPainter
{
@Override
protected void doPaint(Graphics2D g, JXButton b, int width, int height)
{
JXXButton bb = (JXXButton) b;
bb.setPainting(true);
boolean t1 = bb.isBorderPainted();
boolean t2 = bb.isContentAreaFilled();
boolean op = bb.opaque;
bb.borderPainted = false;
bb.contentAreaFilled = false;
bb.opaque = false;
try
{
b.paint(g);
}
finally
{
// restore original values no matter what
bb.opaque = op;
bb.borderPainted = t1;
bb.contentAreaFilled = t2;
bb.setPainting(false);
}
}

// if any of the state of the JButton that affects the foreground has
// changed,
// then I must clear the cache. This is really hard to get right, there
// are
// bound to be bugs. An alternative is to NEVER cache.
@Override
protected boolean shouldUseCache()
{
return false;
}
}

public static class ImageInterpolatorPainter extends AbstractAreaPainter

{ /** * The image to draw */ private transient BufferedImage primaryImage; private transient BufferedImage secondaryImage;

private boolean horizontalRepeat;
private boolean verticalRepeat;

private boolean scaleToFit = false;
private ScaleType scaleType = ScaleType.InsideFit;

private float alpha = 0.0f;

public enum ScaleType
{
InsideFit, OutsideFit, Distort
}

public ImageInterpolatorPainter()
{
super();
setCacheable(true);
this.setVerticalAlignment(VerticalAlignment.CENTER);
this.setHorizontalAlignment(HorizontalAlignment.CENTER);
this.setFillPaint(null);
this.setBorderPaint(null);
}

/**
* Sets the first image to paint with.
*
* @param image
* if null, clears the image. Otherwise, this will set the image
* to be painted.
*/
public void setPrimaryImage(BufferedImage image)
{
if (primaryImage != image)
{
final Image oldImage = primaryImage;
primaryImage = image;
setDirty(true);
firePropertyChange("primary.image", oldImage, image); //$NON-NLS-1$
}
}

/**
* Sets the first image to paint with.
*
* @param image
* if null, clears the image. Otherwise, this will set the image
* to be painted.
*/
public void setSecondaryImage(BufferedImage image)
{
if (secondaryImage != image)
{
final Image oldImage = secondaryImage;
secondaryImage = image;
setDirty(true);
firePropertyChange("secondary.image", oldImage, image); //$NON-NLS-1$
}
}

/**
* Gets the current image used for painting.
*
* @return the image used for painting
*/
public BufferedImage getPrimaryImage()
{
return primaryImage;
}

public BufferedImage getSecondaryImage()
{
return secondaryImage;
}

public float getAlpha()
{
return alpha;
}

public void setAlpha(float alpha)
{
final float oldAlpha = this.alpha;
if (oldAlpha != alpha)
{
this.alpha = alpha;
setDirty(true);
firePropertyChange("alpha", oldAlpha, alpha); //$NON-NLS-1$
}
}

/**
* {@inheritDoc}
*/
@Override
protected void doPaint(Graphics2D g, Object component, int width, int height)
{
Shape shape = provideShape(g, component, width, height);
switch (getStyle())
{
case BOTH:
drawBackground(g, shape, width, height);
drawBorder(g, shape);
break;
case FILLED:
drawBackground(g, shape, width, height);
break;
case OUTLINE:
drawBorder(g, shape);
break;
case NONE:
break;
}
}

private void drawBackground(Graphics2D g, Shape shape, int width, int height)
{
Paint p = getFillPaint();

if (p != null)
{
if (isPaintStretched())
{
p = PaintUtils.resizeGradient(p, width, height);
}
g.setPaint(p);
g.fill(shape);
}

if (getAreaEffects() != null)
{
for (AreaEffect ef : getAreaEffects())
{
ef.apply(g, shape, width, height);
}
}
final float alpha = getAlpha();
if (alpha < 1.0f)
{
drawImage(g, primaryImage, width, height);
}
if (alpha > 0.0f)
{
final Composite oldComposite = g.getComposite();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
drawImage(g, secondaryImage, width, height);
g.setComposite(oldComposite);
}
}

private void drawBorder(Graphics2D g, Shape shape)
{
if (getBorderPaint() != null)
{
g.setPaint(getBorderPaint());
g.setStroke(new BasicStroke(getBorderWidth()));
g.draw(shape);
}
}

private void drawImage(Graphics2D g2, BufferedImage drawImage, int width, int height)
{
if (drawImage == null)
{
return;
}
int imgWidth = drawImage.getWidth(null);
int imgHeight = drawImage.getHeight(null);

if ((imgWidth < 0) || (imgHeight < 0))
{
return;
}

Rectangle rect = calculateLayout(imgWidth, imgHeight, width, height);
if (verticalRepeat || horizontalRepeat)
{
Shape oldClip = g2.getClip();
Shape clip = g2.getClip();
if (clip == null)
{
clip = new Rectangle(0, 0, width, height);
}
Area area = new Area(clip);
TexturePaint tp = new TexturePaint(drawImage, rect);
if (verticalRepeat && horizontalRepeat)
{
area.intersect(new Area(new Rectangle(0, 0, width, height)));
g2.setClip(area);
}
else
if (verticalRepeat)
{
area.intersect(new Area(new Rectangle(rect.x, 0, rect.width, height)));
g2.setClip(area);
}
else
{
area.intersect(new Area(new Rectangle(0, rect.y, width, rect.height)));
g2.setClip(area);
}
g2.setPaint(tp);
g2.fillRect(0, 0, width, height);
g2.setClip(oldClip);
}
else
{
if (scaleToFit)
{
int sw = imgWidth;
int sh = imgHeight;
if (scaleType == ScaleType.InsideFit)
{
if (sw > width)
{
float scale = (float) width / (float) sw;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
if (sh > height)
{
float scale = (float) height / (float) sh;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
}
if (scaleType == ScaleType.OutsideFit)
{
if (sw > width)
{
float scale = (float) width / (float) sw;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
if (sh < height)
{
float scale = (float) height / (float) sh;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
}
if (scaleType == ScaleType.Distort)
{
sw = width;
sh = height;
}
int x = 0;
int y = 0;
switch (getHorizontalAlignment())
{
case CENTER:
x = (width / 2) - (sw / 2);
break;
case RIGHT:
x = width - sw;
break;
}
switch (getVerticalAlignment())
{
case CENTER:
y = (height / 2) - (sh / 2);
break;
case BOTTOM:
y = height - sh;
break;
}
g2.drawImage(drawImage, x, y, sw, sh, null);
}
else
{
int sw = rect.width;
int sh = rect.height;
if (imageScale != 1.0)
{
sw = (int) (sw * imageScale);
sh = (int) (sh * imageScale);
}
g2.drawImage(drawImage, rect.x, rect.y, sw, sh, null);
}
}
}

public void setScaleToFit(boolean scaleToFit)
{
boolean old = isScaleToFit();
this.scaleToFit = scaleToFit;
setDirty(true);
firePropertyChange("scale.to.fit", old, isScaleToFit()); //$NON-NLS-1$
}

public boolean isScaleToFit()
{
return scaleToFit;
}

private double imageScale = 1.0;
/**
* Sets the scaling factor used when drawing the image
*
* @param imageScale
* the new image scaling factor
*/
public void setImageScale(double imageScale)
{
double old = getImageScale();
this.imageScale = imageScale;
setDirty(true);
firePropertyChange("image.scale", old, this.imageScale); //$NON-NLS-1$
}

/**
* Gets the current scaling factor used when drawing an image.
*
* @return the current scaling factor
*/
public double getImageScale()
{
return imageScale;
}

private String imageString;

/**
* Used by the persistence mechanism.
*/
public String getImageString()
{
return imageString;
}


/**
* Indicates if the image will be repeated horizontally.
*
* @return if the image will be repeated horizontally
*/
public boolean isHorizontalRepeat()
{
return horizontalRepeat;
}

/**
* Sets if the image should be repeated horizontally.
*
* @param horizontalRepeat
* the new horizontal repeat value
*/
public void setHorizontalRepeat(boolean horizontalRepeat)
{
boolean old = this.isHorizontalRepeat();
this.horizontalRepeat = horizontalRepeat;
setDirty(true);
firePropertyChange("horizontal.repeat", old, this.horizontalRepeat); //$NON-NLS-1$
}

/**
* Indicates if the image will be repeated vertically.
*
* @return if the image will be repeated vertically
*/
public boolean isVerticalRepeat()
{
return verticalRepeat;
}

/**
* Sets if the image should be repeated vertically.
*
* @param verticalRepeat
* new value for the vertical repeat
*/
public void setVerticalRepeat(boolean verticalRepeat)
{
boolean old = this.isVerticalRepeat();
this.verticalRepeat = verticalRepeat;
setDirty(true);
firePropertyChange("vertical.repeat", old, this.verticalRepeat); //$NON-NLS-1$
}

/**
*
*/
protected Shape provideShape(Graphics2D g, Object comp, int width, int height)
{
if (getPrimaryImage() != null)
{
BufferedImage img = getPrimaryImage();
int imgWidth = img.getWidth();
int imgHeight = img.getHeight();

return calculateLayout(imgWidth, imgHeight, width, height);
}
return new Rectangle(0, 0, 0, 0);

}

public ScaleType getScaleType()
{
return scaleType;
}

public void setScaleType(ScaleType scaleType)
{
ScaleType old = getScaleType();
this.scaleType = scaleType;
setDirty(true);
firePropertyChange("scale.type", old, getScaleType()); //$NON-NLS-1$
}
}
}

oscarl0208
Offline
Joined: 2013-04-17
Points: 0

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.TexturePaint;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jdesktop.swingx.JXButton;
import org.jdesktop.swingx.painter.AbstractAreaPainter;
import org.jdesktop.swingx.painter.AbstractPainter;
import org.jdesktop.swingx.painter.AlphaPainter;
import org.jdesktop.swingx.painter.CompoundPainter;
import org.jdesktop.swingx.painter.Painter;
import org.jdesktop.swingx.painter.ShapePainter;
import org.jdesktop.swingx.painter.effects.AreaEffect;
import org.jdesktop.swingx.painter.effects.ShadowPathEffect;
import org.jdesktop.swingx.util.GraphicsUtilities;
import org.jdesktop.swingx.util.PaintUtils;

public class TestJXButton
{

static public final Color black40 = new Color(0,0,0,40);
static public final Color black40t = new Color(0,0,0,100);
static private final Color SYSTEM_OUTLINE_COLOR = new Color(90, 135, 165);
static public enum SEGMENT {BEGIN,SEGMENT,END,SOLO};
private static final BufferedImage prefsIcon = loadImage("/com/neovest/fa/resources/images/goptions.png");
protected static Dimension menuOptionsButtonSize = new Dimension(36, 48);

/**
* @param args
*/
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setTitle("Test JXButton");
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
JPanel panel2 = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.black));
panel2.setBorder(BorderFactory.createLineBorder(Color.black));
JXButton button = createUtilButton(prefsIcon, menuOptionsButtonSize, menuOptionsButtonSize, black40t, false);
panel.add(button, BorderLayout.EAST);

//old method
JXButton button2 = createUtilButton(prefsIcon, menuOptionsButtonSize, menuOptionsButtonSize, black40, true);
panel2.add(button2, BorderLayout.EAST);

frame.add(panel, BorderLayout.NORTH);
frame.add(panel2, BorderLayout.SOUTH);
frame.setVisible(true);

}

static public JXButton createUtilButton(final Image image, final Dimension minSize, final Dimension prefSize, final Color buttonColor, boolean oldButton)
{

JXButton button;
if (oldButton)
{
button = new JXXButton();
}
else
{
button = new JXButton();

}

button.setPreferredSize(prefSize);
button.setMinimumSize(minSize);
button.setBorder(BorderFactory.createEmptyBorder());
button.setOpaque(false);
button.setFocusPainted(false);

Paint paint = buttonColor;
Shape shape;

shape = constructSegmentedBeginShape(prefSize, 2.1f);

float fgStartingAlpha = 0.05f;

final ShapePainter borderPainter = new ShapePainter();
borderPainter.setShape(shape);
borderPainter.setFillPaint(paint);
borderPainter.setAntialiasing(true);
borderPainter.setBorderWidth(2.1f);
borderPainter.setBorderPaint(SYSTEM_OUTLINE_COLOR);

final ShadowPathEffect shadow = new ShadowPathEffect();
borderPainter.setAreaEffects(shadow);
shadow.setEffectWidth(2);
shadow.setBrushColor(Color.black);
shadow.setShouldFillShape(true);
shadow.setRenderInsideShape(true);
shadow.setOffset(new Point2D.Float(0f, 2f));
shadow.setBrushSteps(4);

final ShadowPathEffect shadow1 = new ShadowPathEffect();
borderPainter.setAreaEffects(shadow1);
shadow1.setEffectWidth(1);
shadow1.setBrushColor(Color.white);
shadow1.setShouldFillShape(true);
shadow1.setRenderInsideShape(true);
shadow1.setOffset(new Point2D.Float(0f, -0.5f));
shadow1.setBrushSteps(4);

final AlphaPainter fgAlphaPainter = new AlphaPainter();
fgAlphaPainter.setPainters(borderPainter);

BufferedImage bImage = toBufferedImage( new ImageIcon(image));

final ImageInterpolatorPainter imagePainter = new ImageInterpolatorPainter();
imagePainter.setPrimaryImage(bImage);
imagePainter.setSecondaryImage(bImage);
imagePainter.setAlpha(fgStartingAlpha);

final CompoundPainter bgPainter = new CompoundPainter();
bgPainter.setPainters(fgAlphaPainter, imagePainter);

button.setBackgroundPainter(bgPainter);
return button;
}

public static BufferedImage toBufferedImage(ImageIcon imageIcon)
{
Image image = imageIcon.getImage();

BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);

Graphics2D g = bimage.createGraphics();

g.drawImage(image, 0, 0, null);
g.dispose();

return bimage;

}

public static BufferedImage loadImage(String resource)
{
try
{
return GraphicsUtilities.loadCompatibleImage(TestJXButton.class.getResource(resource));
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}

static private Shape constructSegmentedBeginShape(final Dimension bounds, final float lineWidth)
{
final double startX = bounds.getWidth()/2;
final double startY = 0;
final double endX = (bounds.getWidth()*2-lineWidth);
final double endY = bounds.getHeight()-lineWidth;

final Arc2D.Double arc = new Arc2D.Double(startX, startY, endX, endY, 90, 180, Arc2D.OPEN);
return arc;
}

@SuppressWarnings("serial")
static private class JXXButton extends org.jdesktop.swingx.JXButton
{
// properties used to split foreground and background painting.
// overwritten to suppress event notification while painting
private String text = "";
private boolean borderPainted;
private boolean contentAreaFilled;

private Painter fgPainter = new DefaultForegroundPainter();
private Painter bgPainter = new DefaultBackgroundPainter();

/** Creates a new instance of JXButton */
public JXXButton()
{
}

@Override
protected void init(String text, Icon icon)
{
borderPainted = true;
contentAreaFilled = true;
super.init(text, icon);
}

@Override
public void setText(String text)
{
this.text = text;
super.setText(text);
}

@Override
public void repaint()
{
if (painting)
{
// skip repaint requests while painting
return;
}
super.repaint();
}

@Override
public String getText()
{
return this.text;
}

@Override
public void setBorderPainted(boolean b)
{
this.borderPainted = b;
super.setBorderPainted(b);
}

@Override
public boolean isBorderPainted()
{
return this.borderPainted;
}

@Override
public void setContentAreaFilled(boolean b)
{
this.contentAreaFilled = b;
super.setContentAreaFilled(b);
}

@Override
public boolean isContentAreaFilled()
{
return this.contentAreaFilled;
}

public Painter getBackgroundPainter()
{
return bgPainter;
}

public void setBackgroundPainter(Painter p)
{
Painter old = getBackgroundPainter();
this.bgPainter = p;
firePropertyChange("backgroundPainter", old, getBackgroundPainter());
repaint();
}

public Painter getForegroundPainter()
{
return fgPainter;
}

public void setForegroundPainter(Painter p)
{
Painter old = getForegroundPainter();
this.fgPainter = p;
firePropertyChange("foregroundPainter", old, getForegroundPainter());
repaint();
}

private boolean paintBorderInsets = true;
private boolean painting;
private boolean opaque = true;

/**
* Returns true if the background painter should paint where the border is
* or false if it should only paint inside the border. This property is true
* by default. This property affects the width, height, and intial transform
* passed to the background painter.
*/
public boolean isPaintBorderInsets()
{
return paintBorderInsets;
}

/**
* Sets the paintBorderInsets property. Set to true if the background
* painter should paint where the border is or false if it should only paint
* inside the border. This property is true by default. This property
* affects the width, height, and intial transform passed to the background
* painter.
*
* This is a bound property.
*/
public void setPaintBorderInsets(boolean paintBorderInsets)
{
boolean old = this.isPaintBorderInsets();
this.paintBorderInsets = paintBorderInsets;
firePropertyChange("paintBorderInsets", old, isPaintBorderInsets());
}

@Override
public boolean isOpaque()
{
return painting ? opaque : super.isOpaque();
}

@Override
protected void paintComponent(Graphics g)
{
Painter bgPainter = getBackgroundPainter();
Painter fgPainter = getForegroundPainter();
if (painting || (bgPainter == null && fgPainter == null))
{
super.paintComponent(g);
}
else
{
invokePainter(g, bgPainter);
invokePainter(g, fgPainter);
}
}

private void invokePainter(Graphics g, Painter ptr)
{
if (ptr == null)
return;

Graphics2D g2d = (Graphics2D) g.create();

try
{
if (isPaintBorderInsets())
{
ptr.paint(g2d, this, getWidth(), getHeight());
}
else
{
Insets ins = this.getInsets();
g2d.translate(ins.left, ins.top);
ptr.paint(g2d, this, this.getWidth() - ins.left - ins.right, this.getHeight() - ins.top - ins.bottom);
}
}
finally
{
g2d.dispose();
}
}

protected void setPainting(boolean b)
{
painting = b;
}
}

// paint anything but text and icon
private final static class DefaultBackgroundPainter extends AbstractPainter
{
@Override
protected void doPaint(Graphics2D g, JXButton b, int width, int height)
{
JXXButton bb = (JXXButton) b;
boolean op = bb.isOpaque();
// have to read this before setting painting == true !!!
bb.setOpaque(bb.isOpaque());
bb.setPainting(true);
String tmp = bb.text;
// #swingx-874
Icon tmpIcon = bb.getIcon();
bb.setIcon(null);
bb.text = "";
try
{
b.paint(g);
}
finally
{
// restore original values no matter what
bb.opaque = op;
bb.text = tmp;
bb.setIcon(tmpIcon);
bb.setPainting(false);
}
}

// if any of the state of the JButton that affects the background has
// changed,
// then I must clear the cache. This is really hard to get right, there
// are
// bound to be bugs. An alternative is to NEVER cache.
@Override
protected boolean shouldUseCache()
{
return false;
}
}

// paint only a text and icon (if any)
private final static class DefaultForegroundPainter extends AbstractPainter
{
@Override
protected void doPaint(Graphics2D g, JXButton b, int width, int height)
{
JXXButton bb = (JXXButton) b;
bb.setPainting(true);
boolean t1 = bb.isBorderPainted();
boolean t2 = bb.isContentAreaFilled();
boolean op = bb.opaque;
bb.borderPainted = false;
bb.contentAreaFilled = false;
bb.opaque = false;
try
{
b.paint(g);
}
finally
{
// restore original values no matter what
bb.opaque = op;
bb.borderPainted = t1;
bb.contentAreaFilled = t2;
bb.setPainting(false);
}
}

// if any of the state of the JButton that affects the foreground has
// changed,
// then I must clear the cache. This is really hard to get right, there
// are
// bound to be bugs. An alternative is to NEVER cache.
@Override
protected boolean shouldUseCache()
{
return false;
}
}

public static class ImageInterpolatorPainter extends AbstractAreaPainter

{ /** * The image to draw */ private transient BufferedImage primaryImage; private transient BufferedImage secondaryImage;

private boolean horizontalRepeat;
private boolean verticalRepeat;

private boolean scaleToFit = false;
private ScaleType scaleType = ScaleType.InsideFit;

private float alpha = 0.0f;

public enum ScaleType
{
InsideFit, OutsideFit, Distort
}

public ImageInterpolatorPainter()
{
super();
setCacheable(true);
this.setVerticalAlignment(VerticalAlignment.CENTER);
this.setHorizontalAlignment(HorizontalAlignment.CENTER);
this.setFillPaint(null);
this.setBorderPaint(null);
}

/**
* Sets the first image to paint with.
*
* @param image
* if null, clears the image. Otherwise, this will set the image
* to be painted.
*/
public void setPrimaryImage(BufferedImage image)
{
if (primaryImage != image)
{
final Image oldImage = primaryImage;
primaryImage = image;
setDirty(true);
firePropertyChange("primary.image", oldImage, image); //$NON-NLS-1$
}
}

/**
* Sets the first image to paint with.
*
* @param image
* if null, clears the image. Otherwise, this will set the image
* to be painted.
*/
public void setSecondaryImage(BufferedImage image)
{
if (secondaryImage != image)
{
final Image oldImage = secondaryImage;
secondaryImage = image;
setDirty(true);
firePropertyChange("secondary.image", oldImage, image); //$NON-NLS-1$
}
}

/**
* Gets the current image used for painting.
*
* @return the image used for painting
*/
public BufferedImage getPrimaryImage()
{
return primaryImage;
}

public BufferedImage getSecondaryImage()
{
return secondaryImage;
}

public float getAlpha()
{
return alpha;
}

public void setAlpha(float alpha)
{
final float oldAlpha = this.alpha;
if (oldAlpha != alpha)
{
this.alpha = alpha;
setDirty(true);
firePropertyChange("alpha", oldAlpha, alpha); //$NON-NLS-1$
}
}

/**
* {@inheritDoc}
*/
@Override
protected void doPaint(Graphics2D g, Object component, int width, int height)
{
Shape shape = provideShape(g, component, width, height);
switch (getStyle())
{
case BOTH:
drawBackground(g, shape, width, height);
drawBorder(g, shape);
break;
case FILLED:
drawBackground(g, shape, width, height);
break;
case OUTLINE:
drawBorder(g, shape);
break;
case NONE:
break;
}
}

private void drawBackground(Graphics2D g, Shape shape, int width, int height)
{
Paint p = getFillPaint();

if (p != null)
{
if (isPaintStretched())
{
p = PaintUtils.resizeGradient(p, width, height);
}
g.setPaint(p);
g.fill(shape);
}

if (getAreaEffects() != null)
{
for (AreaEffect ef : getAreaEffects())
{
ef.apply(g, shape, width, height);
}
}
final float alpha = getAlpha();
if (alpha < 1.0f)
{
drawImage(g, primaryImage, width, height);
}
if (alpha > 0.0f)
{
final Composite oldComposite = g.getComposite();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
drawImage(g, secondaryImage, width, height);
g.setComposite(oldComposite);
}
}

private void drawBorder(Graphics2D g, Shape shape)
{
if (getBorderPaint() != null)
{
g.setPaint(getBorderPaint());
g.setStroke(new BasicStroke(getBorderWidth()));
g.draw(shape);
}
}

private void drawImage(Graphics2D g2, BufferedImage drawImage, int width, int height)
{
if (drawImage == null)
{
return;
}
int imgWidth = drawImage.getWidth(null);
int imgHeight = drawImage.getHeight(null);

if ((imgWidth < 0) || (imgHeight < 0))
{
return;
}

Rectangle rect = calculateLayout(imgWidth, imgHeight, width, height);
if (verticalRepeat || horizontalRepeat)
{
Shape oldClip = g2.getClip();
Shape clip = g2.getClip();
if (clip == null)
{
clip = new Rectangle(0, 0, width, height);
}
Area area = new Area(clip);
TexturePaint tp = new TexturePaint(drawImage, rect);
if (verticalRepeat && horizontalRepeat)
{
area.intersect(new Area(new Rectangle(0, 0, width, height)));
g2.setClip(area);
}
else
if (verticalRepeat)
{
area.intersect(new Area(new Rectangle(rect.x, 0, rect.width, height)));
g2.setClip(area);
}
else
{
area.intersect(new Area(new Rectangle(0, rect.y, width, rect.height)));
g2.setClip(area);
}
g2.setPaint(tp);
g2.fillRect(0, 0, width, height);
g2.setClip(oldClip);
}
else
{
if (scaleToFit)
{
int sw = imgWidth;
int sh = imgHeight;
if (scaleType == ScaleType.InsideFit)
{
if (sw > width)
{
float scale = (float) width / (float) sw;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
if (sh > height)
{
float scale = (float) height / (float) sh;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
}
if (scaleType == ScaleType.OutsideFit)
{
if (sw > width)
{
float scale = (float) width / (float) sw;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
if (sh < height)
{
float scale = (float) height / (float) sh;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
}
if (scaleType == ScaleType.Distort)
{
sw = width;
sh = height;
}
int x = 0;
int y = 0;
switch (getHorizontalAlignment())
{
case CENTER:
x = (width / 2) - (sw / 2);
break;
case RIGHT:
x = width - sw;
break;
}
switch (getVerticalAlignment())
{
case CENTER:
y = (height / 2) - (sh / 2);
break;
case BOTTOM:
y = height - sh;
break;
}
g2.drawImage(drawImage, x, y, sw, sh, null);
}
else
{
int sw = rect.width;
int sh = rect.height;
if (imageScale != 1.0)
{
sw = (int) (sw * imageScale);
sh = (int) (sh * imageScale);
}
g2.drawImage(drawImage, rect.x, rect.y, sw, sh, null);
}
}
}

public void setScaleToFit(boolean scaleToFit)
{
boolean old = isScaleToFit();
this.scaleToFit = scaleToFit;
setDirty(true);
firePropertyChange("scale.to.fit", old, isScaleToFit()); //$NON-NLS-1$
}

public boolean isScaleToFit()
{
return scaleToFit;
}

private double imageScale = 1.0;
/**
* Sets the scaling factor used when drawing the image
*
* @param imageScale
* the new image scaling factor
*/
public void setImageScale(double imageScale)
{
double old = getImageScale();
this.imageScale = imageScale;
setDirty(true);
firePropertyChange("image.scale", old, this.imageScale); //$NON-NLS-1$
}

/**
* Gets the current scaling factor used when drawing an image.
*
* @return the current scaling factor
*/
public double getImageScale()
{
return imageScale;
}

private String imageString;

/**
* Used by the persistence mechanism.
*/
public String getImageString()
{
return imageString;
}


/**
* Indicates if the image will be repeated horizontally.
*
* @return if the image will be repeated horizontally
*/
public boolean isHorizontalRepeat()
{
return horizontalRepeat;
}

/**
* Sets if the image should be repeated horizontally.
*
* @param horizontalRepeat
* the new horizontal repeat value
*/
public void setHorizontalRepeat(boolean horizontalRepeat)
{
boolean old = this.isHorizontalRepeat();
this.horizontalRepeat = horizontalRepeat;
setDirty(true);
firePropertyChange("horizontal.repeat", old, this.horizontalRepeat); //$NON-NLS-1$
}

/**
* Indicates if the image will be repeated vertically.
*
* @return if the image will be repeated vertically
*/
public boolean isVerticalRepeat()
{
return verticalRepeat;
}

/**
* Sets if the image should be repeated vertically.
*
* @param verticalRepeat
* new value for the vertical repeat
*/
public void setVerticalRepeat(boolean verticalRepeat)
{
boolean old = this.isVerticalRepeat();
this.verticalRepeat = verticalRepeat;
setDirty(true);
firePropertyChange("vertical.repeat", old, this.verticalRepeat); //$NON-NLS-1$
}

/**
*
*/
protected Shape provideShape(Graphics2D g, Object comp, int width, int height)
{
if (getPrimaryImage() != null)
{
BufferedImage img = getPrimaryImage();
int imgWidth = img.getWidth();
int imgHeight = img.getHeight();

return calculateLayout(imgWidth, imgHeight, width, height);
}
return new Rectangle(0, 0, 0, 0);

}

public ScaleType getScaleType()
{
return scaleType;
}

public void setScaleType(ScaleType scaleType)
{
ScaleType old = getScaleType();
this.scaleType = scaleType;
setDirty(true);
firePropertyChange("scale.type", old, getScaleType()); //$NON-NLS-1$
}
}
}

oscarl0208
Offline
Joined: 2013-04-17
Points: 0

This is not really small, because I included the old JXButton as comparison and we images in our buttons. But here is a program that will display the same button in a different manner.

import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.TexturePaint;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jdesktop.swingx.JXButton;
import org.jdesktop.swingx.painter.AbstractAreaPainter;
import org.jdesktop.swingx.painter.AbstractPainter;
import org.jdesktop.swingx.painter.AlphaPainter;
import org.jdesktop.swingx.painter.CompoundPainter;
import org.jdesktop.swingx.painter.Painter;
import org.jdesktop.swingx.painter.ShapePainter;
import org.jdesktop.swingx.painter.effects.AreaEffect;
import org.jdesktop.swingx.painter.effects.ShadowPathEffect;
import org.jdesktop.swingx.util.GraphicsUtilities;
import org.jdesktop.swingx.util.PaintUtils;

public class TestJXButton
{

static public final Color black40 = new Color(0,0,0,40);
static public final Color black40t = new Color(0,0,0,100);
static private final Color SYSTEM_OUTLINE_COLOR = new Color(90, 135, 165);
static public enum SEGMENT {BEGIN,SEGMENT,END,SOLO};
private static final BufferedImage prefsIcon = loadImage("/com/neovest/fa/resources/images/goptions.png");
protected static Dimension menuOptionsButtonSize = new Dimension(36, 48);

/**
* @param args
*/
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setTitle("Test JXButton");
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
JPanel panel2 = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.black));
panel2.setBorder(BorderFactory.createLineBorder(Color.black));
JXButton button = createUtilButton(prefsIcon, menuOptionsButtonSize, menuOptionsButtonSize, black40t, false);
panel.add(button, BorderLayout.EAST);

//old method
JXButton button2 = createUtilButton(prefsIcon, menuOptionsButtonSize, menuOptionsButtonSize, black40, true);
panel2.add(button2, BorderLayout.EAST);

frame.add(panel, BorderLayout.NORTH);
frame.add(panel2, BorderLayout.SOUTH);
frame.setVisible(true);

}

static public JXButton createUtilButton(final Image image, final Dimension minSize, final Dimension prefSize, final Color buttonColor, boolean oldButton)
{

JXButton button;
if (oldButton)
{
button = new JXXButton();
}
else
{
button = new JXButton();

}

button.setPreferredSize(prefSize);
button.setMinimumSize(minSize);
button.setBorder(BorderFactory.createEmptyBorder());
button.setOpaque(false);
button.setFocusPainted(false);

Paint paint = buttonColor;
Shape shape;

shape = constructSegmentedBeginShape(prefSize, 2.1f);

float fgStartingAlpha = 0.05f;

final ShapePainter borderPainter = new ShapePainter();
borderPainter.setShape(shape);
borderPainter.setFillPaint(paint);
borderPainter.setAntialiasing(true);
borderPainter.setBorderWidth(2.1f);
borderPainter.setBorderPaint(SYSTEM_OUTLINE_COLOR);

final ShadowPathEffect shadow = new ShadowPathEffect();
borderPainter.setAreaEffects(shadow);
shadow.setEffectWidth(2);
shadow.setBrushColor(Color.black);
shadow.setShouldFillShape(true);
shadow.setRenderInsideShape(true);
shadow.setOffset(new Point2D.Float(0f, 2f));
shadow.setBrushSteps(4);

final ShadowPathEffect shadow1 = new ShadowPathEffect();
borderPainter.setAreaEffects(shadow1);
shadow1.setEffectWidth(1);
shadow1.setBrushColor(Color.white);
shadow1.setShouldFillShape(true);
shadow1.setRenderInsideShape(true);
shadow1.setOffset(new Point2D.Float(0f, -0.5f));
shadow1.setBrushSteps(4);

final AlphaPainter fgAlphaPainter = new AlphaPainter();
fgAlphaPainter.setPainters(borderPainter);

BufferedImage bImage = toBufferedImage( new ImageIcon(image));

final ImageInterpolatorPainter imagePainter = new ImageInterpolatorPainter();
imagePainter.setPrimaryImage(bImage);
imagePainter.setSecondaryImage(bImage);
imagePainter.setAlpha(fgStartingAlpha);

final CompoundPainter bgPainter = new CompoundPainter();
bgPainter.setPainters(fgAlphaPainter, imagePainter);

button.setBackgroundPainter(bgPainter);
return button;
}

public static BufferedImage toBufferedImage(ImageIcon imageIcon)
{
Image image = imageIcon.getImage();

BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);

Graphics2D g = bimage.createGraphics();

g.drawImage(image, 0, 0, null);
g.dispose();

return bimage;

}

public static BufferedImage loadImage(String resource)
{
try
{
return GraphicsUtilities.loadCompatibleImage(TestJXButton.class.getResource(resource));
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}

static private Shape constructSegmentedBeginShape(final Dimension bounds, final float lineWidth)
{
final double startX = bounds.getWidth()/2;
final double startY = 0;
final double endX = (bounds.getWidth()*2-lineWidth);
final double endY = bounds.getHeight()-lineWidth;

final Arc2D.Double arc = new Arc2D.Double(startX, startY, endX, endY, 90, 180, Arc2D.OPEN);
return arc;
}

@SuppressWarnings("serial")
static private class JXXButton extends org.jdesktop.swingx.JXButton
{
// properties used to split foreground and background painting.
// overwritten to suppress event notification while painting
private String text = "";
private boolean borderPainted;
private boolean contentAreaFilled;

private Painter fgPainter = new DefaultForegroundPainter();
private Painter bgPainter = new DefaultBackgroundPainter();

/** Creates a new instance of JXButton */
public JXXButton()
{
}

@Override
protected void init(String text, Icon icon)
{
borderPainted = true;
contentAreaFilled = true;
super.init(text, icon);
}

@Override
public void setText(String text)
{
this.text = text;
super.setText(text);
}

@Override
public void repaint()
{
if (painting)
{
// skip repaint requests while painting
return;
}
super.repaint();
}

@Override
public String getText()
{
return this.text;
}

@Override
public void setBorderPainted(boolean b)
{
this.borderPainted = b;
super.setBorderPainted(b);
}

@Override
public boolean isBorderPainted()
{
return this.borderPainted;
}

@Override
public void setContentAreaFilled(boolean b)
{
this.contentAreaFilled = b;
super.setContentAreaFilled(b);
}

@Override
public boolean isContentAreaFilled()
{
return this.contentAreaFilled;
}

public Painter getBackgroundPainter()
{
return bgPainter;
}

public void setBackgroundPainter(Painter p)
{
Painter old = getBackgroundPainter();
this.bgPainter = p;
firePropertyChange("backgroundPainter", old, getBackgroundPainter());
repaint();
}

public Painter getForegroundPainter()
{
return fgPainter;
}

public void setForegroundPainter(Painter p)
{
Painter old = getForegroundPainter();
this.fgPainter = p;
firePropertyChange("foregroundPainter", old, getForegroundPainter());
repaint();
}

private boolean paintBorderInsets = true;
private boolean painting;
private boolean opaque = true;

/**
* Returns true if the background painter should paint where the border is
* or false if it should only paint inside the border. This property is true
* by default. This property affects the width, height, and intial transform
* passed to the background painter.
*/
public boolean isPaintBorderInsets()
{
return paintBorderInsets;
}

/**
* Sets the paintBorderInsets property. Set to true if the background
* painter should paint where the border is or false if it should only paint
* inside the border. This property is true by default. This property
* affects the width, height, and intial transform passed to the background
* painter.
*
* This is a bound property.
*/
public void setPaintBorderInsets(boolean paintBorderInsets)
{
boolean old = this.isPaintBorderInsets();
this.paintBorderInsets = paintBorderInsets;
firePropertyChange("paintBorderInsets", old, isPaintBorderInsets());
}

@Override
public boolean isOpaque()
{
return painting ? opaque : super.isOpaque();
}

@Override
protected void paintComponent(Graphics g)
{
Painter bgPainter = getBackgroundPainter();
Painter fgPainter = getForegroundPainter();
if (painting || (bgPainter == null && fgPainter == null))
{
super.paintComponent(g);
}
else
{
invokePainter(g, bgPainter);
invokePainter(g, fgPainter);
}
}

private void invokePainter(Graphics g, Painter ptr)
{
if (ptr == null)
return;

Graphics2D g2d = (Graphics2D) g.create();

try
{
if (isPaintBorderInsets())
{
ptr.paint(g2d, this, getWidth(), getHeight());
}
else
{
Insets ins = this.getInsets();
g2d.translate(ins.left, ins.top);
ptr.paint(g2d, this, this.getWidth() - ins.left - ins.right, this.getHeight() - ins.top - ins.bottom);
}
}
finally
{
g2d.dispose();
}
}

protected void setPainting(boolean b)
{
painting = b;
}
}

// paint anything but text and icon
private final static class DefaultBackgroundPainter extends AbstractPainter
{
@Override
protected void doPaint(Graphics2D g, JXButton b, int width, int height)
{
JXXButton bb = (JXXButton) b;
boolean op = bb.isOpaque();
// have to read this before setting painting == true !!!
bb.setOpaque(bb.isOpaque());
bb.setPainting(true);
String tmp = bb.text;
// #swingx-874
Icon tmpIcon = bb.getIcon();
bb.setIcon(null);
bb.text = "";
try
{
b.paint(g);
}
finally
{
// restore original values no matter what
bb.opaque = op;
bb.text = tmp;
bb.setIcon(tmpIcon);
bb.setPainting(false);
}
}

// if any of the state of the JButton that affects the background has
// changed,
// then I must clear the cache. This is really hard to get right, there
// are
// bound to be bugs. An alternative is to NEVER cache.
@Override
protected boolean shouldUseCache()
{
return false;
}
}

// paint only a text and icon (if any)
private final static class DefaultForegroundPainter extends AbstractPainter
{
@Override
protected void doPaint(Graphics2D g, JXButton b, int width, int height)
{
JXXButton bb = (JXXButton) b;
bb.setPainting(true);
boolean t1 = bb.isBorderPainted();
boolean t2 = bb.isContentAreaFilled();
boolean op = bb.opaque;
bb.borderPainted = false;
bb.contentAreaFilled = false;
bb.opaque = false;
try
{
b.paint(g);
}
finally
{
// restore original values no matter what
bb.opaque = op;
bb.borderPainted = t1;
bb.contentAreaFilled = t2;
bb.setPainting(false);
}
}

// if any of the state of the JButton that affects the foreground has
// changed,
// then I must clear the cache. This is really hard to get right, there
// are
// bound to be bugs. An alternative is to NEVER cache.
@Override
protected boolean shouldUseCache()
{
return false;
}
}

public static class ImageInterpolatorPainter extends AbstractAreaPainter

{ /** * The image to draw */ private transient BufferedImage primaryImage; private transient BufferedImage secondaryImage;

private boolean horizontalRepeat;
private boolean verticalRepeat;

private boolean scaleToFit = false;
private ScaleType scaleType = ScaleType.InsideFit;

private float alpha = 0.0f;

public enum ScaleType
{
InsideFit, OutsideFit, Distort
}

public ImageInterpolatorPainter()
{
super();
setCacheable(true);
this.setVerticalAlignment(VerticalAlignment.CENTER);
this.setHorizontalAlignment(HorizontalAlignment.CENTER);
this.setFillPaint(null);
this.setBorderPaint(null);
}

/**
* Sets the first image to paint with.
*
* @param image
* if null, clears the image. Otherwise, this will set the image
* to be painted.
*/
public void setPrimaryImage(BufferedImage image)
{
if (primaryImage != image)
{
final Image oldImage = primaryImage;
primaryImage = image;
setDirty(true);
firePropertyChange("primary.image", oldImage, image); //$NON-NLS-1$
}
}

/**
* Sets the first image to paint with.
*
* @param image
* if null, clears the image. Otherwise, this will set the image
* to be painted.
*/
public void setSecondaryImage(BufferedImage image)
{
if (secondaryImage != image)
{
final Image oldImage = secondaryImage;
secondaryImage = image;
setDirty(true);
firePropertyChange("secondary.image", oldImage, image); //$NON-NLS-1$
}
}

/**
* Gets the current image used for painting.
*
* @return the image used for painting
*/
public BufferedImage getPrimaryImage()
{
return primaryImage;
}

public BufferedImage getSecondaryImage()
{
return secondaryImage;
}

public float getAlpha()
{
return alpha;
}

public void setAlpha(float alpha)
{
final float oldAlpha = this.alpha;
if (oldAlpha != alpha)
{
this.alpha = alpha;
setDirty(true);
firePropertyChange("alpha", oldAlpha, alpha); //$NON-NLS-1$
}
}

/**
* {@inheritDoc}
*/
@Override
protected void doPaint(Graphics2D g, Object component, int width, int height)
{
Shape shape = provideShape(g, component, width, height);
switch (getStyle())
{
case BOTH:
drawBackground(g, shape, width, height);
drawBorder(g, shape);
break;
case FILLED:
drawBackground(g, shape, width, height);
break;
case OUTLINE:
drawBorder(g, shape);
break;
case NONE:
break;
}
}

private void drawBackground(Graphics2D g, Shape shape, int width, int height)
{
Paint p = getFillPaint();

if (p != null)
{
if (isPaintStretched())
{
p = PaintUtils.resizeGradient(p, width, height);
}
g.setPaint(p);
g.fill(shape);
}

if (getAreaEffects() != null)
{
for (AreaEffect ef : getAreaEffects())
{
ef.apply(g, shape, width, height);
}
}
final float alpha = getAlpha();
if (alpha < 1.0f)
{
drawImage(g, primaryImage, width, height);
}
if (alpha > 0.0f)
{
final Composite oldComposite = g.getComposite();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
drawImage(g, secondaryImage, width, height);
g.setComposite(oldComposite);
}
}

private void drawBorder(Graphics2D g, Shape shape)
{
if (getBorderPaint() != null)
{
g.setPaint(getBorderPaint());
g.setStroke(new BasicStroke(getBorderWidth()));
g.draw(shape);
}
}

private void drawImage(Graphics2D g2, BufferedImage drawImage, int width, int height)
{
if (drawImage == null)
{
return;
}
int imgWidth = drawImage.getWidth(null);
int imgHeight = drawImage.getHeight(null);

if ((imgWidth < 0) || (imgHeight < 0))
{
return;
}

Rectangle rect = calculateLayout(imgWidth, imgHeight, width, height);
if (verticalRepeat || horizontalRepeat)
{
Shape oldClip = g2.getClip();
Shape clip = g2.getClip();
if (clip == null)
{
clip = new Rectangle(0, 0, width, height);
}
Area area = new Area(clip);
TexturePaint tp = new TexturePaint(drawImage, rect);
if (verticalRepeat && horizontalRepeat)
{
area.intersect(new Area(new Rectangle(0, 0, width, height)));
g2.setClip(area);
}
else
if (verticalRepeat)
{
area.intersect(new Area(new Rectangle(rect.x, 0, rect.width, height)));
g2.setClip(area);
}
else
{
area.intersect(new Area(new Rectangle(0, rect.y, width, rect.height)));
g2.setClip(area);
}
g2.setPaint(tp);
g2.fillRect(0, 0, width, height);
g2.setClip(oldClip);
}
else
{
if (scaleToFit)
{
int sw = imgWidth;
int sh = imgHeight;
if (scaleType == ScaleType.InsideFit)
{
if (sw > width)
{
float scale = (float) width / (float) sw;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
if (sh > height)
{
float scale = (float) height / (float) sh;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
}
if (scaleType == ScaleType.OutsideFit)
{
if (sw > width)
{
float scale = (float) width / (float) sw;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
if (sh < height)
{
float scale = (float) height / (float) sh;
sw = (int) (sw * scale);
sh = (int) (sh * scale);
}
}
if (scaleType == ScaleType.Distort)
{
sw = width;
sh = height;
}
int x = 0;
int y = 0;
switch (getHorizontalAlignment())
{
case CENTER:
x = (width / 2) - (sw / 2);
break;
case RIGHT:
x = width - sw;
break;
}
switch (getVerticalAlignment())
{
case CENTER:
y = (height / 2) - (sh / 2);
break;
case BOTTOM:
y = height - sh;
break;
}
g2.drawImage(drawImage, x, y, sw, sh, null);
}
else
{
int sw = rect.width;
int sh = rect.height;
if (imageScale != 1.0)
{
sw = (int) (sw * imageScale);
sh = (int) (sh * imageScale);
}
g2.drawImage(drawImage, rect.x, rect.y, sw, sh, null);
}
}
}

public void setScaleToFit(boolean scaleToFit)
{
boolean old = isScaleToFit();
this.scaleToFit = scaleToFit;
setDirty(true);
firePropertyChange("scale.to.fit", old, isScaleToFit()); //$NON-NLS-1$
}

public boolean isScaleToFit()
{
return scaleToFit;
}

private double imageScale = 1.0;
/**
* Sets the scaling factor used when drawing the image
*
* @param imageScale
* the new image scaling factor
*/
public void setImageScale(double imageScale)
{
double old = getImageScale();
this.imageScale = imageScale;
setDirty(true);
firePropertyChange("image.scale", old, this.imageScale); //$NON-NLS-1$
}

/**
* Gets the current scaling factor used when drawing an image.
*
* @return the current scaling factor
*/
public double getImageScale()
{
return imageScale;
}

private String imageString;

/**
* Used by the persistence mechanism.
*/
public String getImageString()
{
return imageString;
}


/**
* Indicates if the image will be repeated horizontally.
*
* @return if the image will be repeated horizontally
*/
public boolean isHorizontalRepeat()
{
return horizontalRepeat;
}

/**
* Sets if the image should be repeated horizontally.
*
* @param horizontalRepeat
* the new horizontal repeat value
*/
public void setHorizontalRepeat(boolean horizontalRepeat)
{
boolean old = this.isHorizontalRepeat();
this.horizontalRepeat = horizontalRepeat;
setDirty(true);
firePropertyChange("horizontal.repeat", old, this.horizontalRepeat); //$NON-NLS-1$
}

/**
* Indicates if the image will be repeated vertically.
*
* @return if the image will be repeated vertically
*/
public boolean isVerticalRepeat()
{
return verticalRepeat;
}

/**
* Sets if the image should be repeated vertically.
*
* @param verticalRepeat
* new value for the vertical repeat
*/
public void setVerticalRepeat(boolean verticalRepeat)
{
boolean old = this.isVerticalRepeat();
this.verticalRepeat = verticalRepeat;
setDirty(true);
firePropertyChange("vertical.repeat", old, this.verticalRepeat); //$NON-NLS-1$
}

/**
*
*/
protected Shape provideShape(Graphics2D g, Object comp, int width, int height)
{
if (getPrimaryImage() != null)
{
BufferedImage img = getPrimaryImage();
int imgWidth = img.getWidth();
int imgHeight = img.getHeight();

return calculateLayout(imgWidth, imgHeight, width, height);
}
return new Rectangle(0, 0, 0, 0);

}

public ScaleType getScaleType()
{
return scaleType;
}

public void setScaleType(ScaleType scaleType)
{
ScaleType old = getScaleType();
this.scaleType = scaleType;
setDirty(true);
firePropertyChange("scale.type", old, getScaleType()); //$NON-NLS-1$
}
}
}

oscarl0208
Offline
Joined: 2013-04-17
Points: 0

I'm not sure this is the correct forum, but I installed swingx-all-1.6.5-1 and we ran into an issue with JXButton. JXButton is consider AlphaPaintable and SwingXUtilities paints the background if the look and feel is "Nimbus". This occurs when JXButton calls paintBackground in SwingxUtilities. My question, I don't see any to set the Alpha in JXButton for it to not paint the background. Is there another way to make this happen? Or will JXButton at sometime implement AlphaPaintable?

kschaefe
Offline
Joined: 2006-06-08
Points: 0

JXButton is not AlphaPaintable; it is BackgroundPaintable. Nimbus always paints the background color, so if you have a non-opaque Nimbus component where you actually want the background to be transparent, you need to set the alpha channel on the background color.

Karl

oscarl0208
Offline
Joined: 2013-04-17
Points: 0

Thank you for your response. I will look into the alpha channel, but we ran in to a few others issues. JXButton is using SwingUtilities.paintComponent to paint the component, but components without foreground painters are not aligning correctly on the window. We also experiencing issues with the text in the JXButton not rendering correctly. We had to fall back to the old version JXButton which allows the painter to paint the component. I did a test, I used the latest JXButton and commented out the call to SwingUtilities and replaced it with painter.paint call and everything works correctly. We haven't tried the components with filters, but I will shortly.

I'm not sure SwingUtilities.paintComponent is recognizing border Insets. Also when the component is repainted it moves the graphic in the panel.

Any ideas on why SwingUtilities.paintComponent is not working, I would appreciate it.

kschaefe
Offline
Joined: 2006-06-08
Points: 0

Can you provide a small, runnable example?

Karl

oscarl0208
Offline
Joined: 2013-04-17
Points: 0

Hi Karl,

I have a program for you to use for testing, but I keep getting blocked by the spam filter. I can send it to you in a email, if you can give me your email address.

oscarl0208
Offline
Joined: 2013-04-17
Points: 0

Hi Karl,

I sent it to the email address for issues with SwingLabs. I hope it gets to you.