org.jdesktop.swingx.JXButton2 Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jdesktop.swingx;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.ButtonModel;
import javax.swing.CellRendererPane;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.Painter;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import javax.swing.plaf.synth.SynthButtonUI;
import javax.swing.plaf.synth.SynthIcon;
import org.jdesktop.beans.JavaBean;
import org.jdesktop.swingx.graphics.FilterComposite;
import org.jdesktop.swingx.painter.AbstractPainter;
import org.jdesktop.swingx.painter.PainterPaint;
import org.jdesktop.swingx.util.GraphicsUtilities;
import org.jdesktop.swingx.util.PaintUtils;
/**
* A {@link javax.swing.Painter} enabled subclass of {@link javax.swing.JButton}.
* This class supports setting the foreground and background painters of the button separately.
*
* For example, if you wanted to blur just the text on the button, and let everything else be
* handled by the UI delegate for your look and feel, then you could:
*
* JXButton b = new JXButton("Execute");
* AbstractPainter fgPainter = (AbstractPainter)b.getForegroundPainter();
* StackBlurFilter filter = new StackBlurFilter();
* fgPainter.setFilters(filter);
*
*
* If either the foreground painter or the background painter is set,
* then super.paintComponent() is not called. By setting both the foreground and background
* painters to null, you get exactly the same painting behavior as JButton.
*
* @author rbair
* @author rah003
* @author Jan Stola
* @author Karl George Schaefer
*/
@JavaBean
@SuppressWarnings("serial")
public class JXButton2 extends JButton implements BackgroundPaintable {
private static final Logger LOG = Logger.getLogger(JXButton2.class.getName());
private class BackgroundButton extends JButton {
/**
* {@inheritDoc}
*/
@Override
public boolean isDefaultButton() {
return JXButton2.this.isDefaultButton();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getDisabledIcon() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Icon getDisabledSelectedIcon() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public int getDisplayedMnemonicIndex() {
return -1;
}
/**
* {@inheritDoc}
*/
@Override
public int getHorizontalAlignment() {
return JXButton2.this.getHorizontalAlignment();
}
/**
* {@inheritDoc}
*/
@Override
public int getHorizontalTextPosition() {
return JXButton2.this.getHorizontalTextPosition();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getIcon() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public int getIconTextGap() {
return JXButton2.this.getIconTextGap();
}
/**
* {@inheritDoc}
*/
@Override
public Insets getMargin() {
return JXButton2.this.getMargin();
}
/**
* {@inheritDoc}
*/
@Override
public int getMnemonic() {
return -1;
}
/**
* {@inheritDoc}
*/
@Override
public ButtonModel getModel() {
return JXButton2.this.getModel();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getPressedIcon() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Icon getRolloverIcon() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Icon getRolloverSelectedIcon() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public Icon getSelectedIcon() {
return null;
}
/**
* {@inheritDoc}
*/
@Override
public String getText() {
return "";
}
/**
* {@inheritDoc}
*/
@Override
public int getVerticalAlignment() {
return JXButton2.this.getVerticalAlignment();
}
/**
* {@inheritDoc}
*/
@Override
public int getVerticalTextPosition() {
return JXButton2.this.getVerticalTextPosition();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isBorderPainted() {
return JXButton2.this.isBorderPainted();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isContentAreaFilled() {
return JXButton2.this.isContentAreaFilled();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isFocusPainted() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isRolloverEnabled() {
return JXButton2.this.isRolloverEnabled();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSelected() {
return JXButton2.this.isSelected();
}
}
private class ForegroundButton extends JButton {
// private Icon iconBak; // TODO pro Laf dh map,Icon>
// private Map,Icon> iconBak = new HashMap,Icon>();
private Map iconBak; // = new HashMap();
private String iconDescription;
@Override
public void updateUI() {
ComponentUI cui = UIManager.getUI(this);
LOG.info("ForegroundButton UI:"+cui + ", Icon:"+this.getIcon());
if(iconBak==null) {
iconBak = new HashMap();
}
/*
ForegroundButton UI:javax.swing.plaf.metal.MetalButtonUI, Icon:sun.swing.ImageIconUIResource extends ImageIcon implements UIResource
- beim Umschalten nach Nimbus bleibt es bei diesem Icon!
Mögliche Lösung:
- in ImageIcon kann man setDescription hinterlegen:
ic.setDescription(UIManager.getLookAndFeel().getClass().getName() + ":" + key);
- auch beim Umschalten nach Windows bleibt es bei diesem Icon! - dabei hat WindowsLookAndFeel eigene images
ForegroundButton UI:javax.swing.plaf.synth.SynthButtonUI@2865bc56, Icon:javax.swing.plaf.nimbus.NimbusIcon
ForegroundButton UI:javax.swing.plaf.metal.MetalButtonUI@18606a29, Icon:javax.swing.plaf.nimbus.NimbusIcon
class NimbusIcon implements SynthIcon, UIResource
- beim Zurückschalten nach Metal gibt es kein Icon
*/
if(!(cui instanceof SynthButtonUI) && getIcon() instanceof SynthIcon) { // not visible : class NimbusIcon
if(iconDescription==null) {
LOG.warning("ICON geht verloren!!!!!!!! iconDescription="+iconDescription);
} else {
int split = iconDescription.indexOf(':');
String lafClass = iconDescription.substring(0, split);
String key = iconDescription.substring(split+1);
if(iconBak.containsKey("javax.swing.plaf.nimbus.NimbusLookAndFeel")) {
// backup existiert
} else {
iconBak.put("javax.swing.plaf.nimbus.NimbusLookAndFeel", getIcon());
}
this.setIcon(UIManager.getIcon(key));
}
}
if(getIcon() instanceof ImageIcon ic) {
// Icon:sun.swing.ImageIconUIResource extends ImageIcon
if(iconBak.containsKey(UIManager.getLookAndFeel().getClass().getName())
&& iconBak.get(UIManager.getLookAndFeel().getClass().getName())!=getIcon()) {
this.setIcon(iconBak.get(UIManager.getLookAndFeel().getClass().getName()));
// if(iconBak.get(UIManager.getLookAndFeel().getClass())!=null && getIcon()!=iconBak) {
// this.setIcon(iconBak);
} else {
String lafAndName = ic.getDescription();
if(lafAndName!=null) {
int split = lafAndName.indexOf(':');
String lafClass = lafAndName.substring(0, split);
String key = lafAndName.substring(split+1);
LOG.info(":"+lafClass + ", key/name:"+key + " >>>evtl neu:"+UIManager.getIcon(key));
if(!lafClass.equals(UIManager.getLookAndFeel().getClass().getName())) {
// wenn sich laf geändert hat, dann
this.iconDescription = lafAndName;
//this.iconBak = getIcon();
iconBak.put(lafClass, getIcon());
this.setIcon(UIManager.getIcon(key));
}
}
}
}
}
@Override
public void setIcon(Icon icon) {
LOG.info("neu Icon:"+icon);
JXButton2.this.setIcon(icon);
}
@Override
public Font getFont() {
return JXButton2.this.getFont();
}
/**
* {@inheritDoc}
*/
@Override
public Color getForeground() {
if (fgPainter == null) {
return JXButton2.this.getForeground();
}
return PaintUtils.setAlpha(JXButton2.this.getForeground(), 0);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isDefaultButton() {
return JXButton2.this.isDefaultButton();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getDisabledIcon() {
return JXButton2.this.getDisabledIcon();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getDisabledSelectedIcon() {
return JXButton2.this.getDisabledSelectedIcon();
}
/**
* {@inheritDoc}
*/
@Override
public int getDisplayedMnemonicIndex() {
return JXButton2.this.getDisplayedMnemonicIndex();
}
/**
* {@inheritDoc}
*/
@Override
public int getHorizontalAlignment() {
return JXButton2.this.getHorizontalAlignment();
}
/**
* {@inheritDoc}
*/
@Override
public int getHorizontalTextPosition() {
return JXButton2.this.getHorizontalTextPosition();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getIcon() {
return JXButton2.this.getIcon();
}
/**
* {@inheritDoc}
*/
@Override
public int getIconTextGap() {
return JXButton2.this.getIconTextGap();
}
/**
* {@inheritDoc}
*/
@Override
public Insets getMargin() {
return JXButton2.this.getMargin();
}
/**
* {@inheritDoc}
*/
@Override
public int getMnemonic() {
return JXButton2.this.getMnemonic();
}
/**
* {@inheritDoc}
*/
@Override
public ButtonModel getModel() {
return JXButton2.this.getModel();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getPressedIcon() {
return JXButton2.this.getPressedIcon();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getRolloverIcon() {
return JXButton2.this.getRolloverIcon();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getRolloverSelectedIcon() {
return JXButton2.this.getRolloverSelectedIcon();
}
/**
* {@inheritDoc}
*/
@Override
public Icon getSelectedIcon() {
return JXButton2.this.getSelectedIcon();
}
/**
* {@inheritDoc}
*/
@Override
public String getText() {
return JXButton2.this.getText();
}
/**
* {@inheritDoc}
*/
@Override
public int getVerticalAlignment() {
return JXButton2.this.getVerticalAlignment();
}
/**
* {@inheritDoc}
*/
@Override
public int getVerticalTextPosition() {
return JXButton2.this.getVerticalTextPosition();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isBorderPainted() {
return JXButton2.this.isBorderPainted();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isContentAreaFilled() {
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasFocus() {
return JXButton2.this.hasFocus();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isFocusPainted() {
return JXButton2.this.isFocusPainted();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isRolloverEnabled() {
return JXButton2.this.isRolloverEnabled();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSelected() {
return JXButton2.this.isSelected();
}
}
private ForegroundButton fgStamp;
private Painter super JComponent> fgPainter;
private PainterPaint super JComponent> fgPaint;
private BackgroundButton bgStamp;
private Painter super JComponent> bgPainter;
private boolean paintBorderInsets = true;
private Rectangle viewRect = new Rectangle();
private Rectangle textRect = new Rectangle();
private Rectangle iconRect = new Rectangle();
/**
* Creates a button with no set text or icon.
*/
public JXButton2() {
init();
}
/**
* Creates a button with text.
*
* @param text
* the text of the button
*/
public JXButton2(String text) {
super(text);
init();
}
/**
* Creates a button where properties are taken from the {@code Action} supplied.
*
* @param a
* the {@code Action} used to specify the new button
*/
public JXButton2(Action a) {
super(a);
init();
}
/**
* Creates a button with an icon.
*
* @param icon
* the Icon image to display on the button
*/
public JXButton2(Icon icon) {
super(icon);
init();
}
/**
* Creates a button with initial text and an icon.
*
* @param text
* the text of the button
* @param icon
* the Icon image to display on the button
*/
public JXButton2(String text, Icon icon) {
super(text, icon);
init();
}
protected void init(String text, Icon icon) {
// INFORMATION: icon:sun.swing.ImageIconUIResource - extends ImageIcon implements UIResource
// INFORMATION: icon:javax.swing.plaf.nimbus.NimbusIcon - not visible : implements SynthIcon, UIResource
LOG.info("icon:"+icon + " Class:"+(icon==null?"no class":icon.getClass()));
super.init(text, icon);
}
public void setIcon(Icon defaultIcon) {
LOG.info("defaultIcon:"+defaultIcon);
super.setIcon(defaultIcon);
}
private void init() {
fgStamp = new ForegroundButton();
LOG.fine("fgStamp:"+fgStamp);
}
/**
* {@inheritDoc}
*/
@Override
public Painter super JComponent> getBackgroundPainter() {
return bgPainter;
}
/**
* {@inheritDoc}
*/
@Override
public void setBackgroundPainter(Painter super JComponent> p) {
Painter super JComponent> old = getBackgroundPainter();
this.bgPainter = p;
firePropertyChange("backgroundPainter", old, getBackgroundPainter());
repaint();
}
/**
* @return the foreground painter for this button
*/
public Painter super JComponent> getForegroundPainter() {
return fgPainter;
}
/**
* set ForegroundPainter
* @param p the Painter
*/
public void setForegroundPainter(Painter super JComponent> p) {
Painter super JComponent> old = getForegroundPainter();
this.fgPainter = p;
if (fgPainter == null) {
fgPaint = null;
} else {
fgPaint = new PainterPaint(fgPainter, this);
if (bgStamp == null) {
bgStamp = new BackgroundButton();
}
}
firePropertyChange("foregroundPainter", old, getForegroundPainter());
repaint();
}
/**
* 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 initial transform passed to the background painter.
*/
@Override
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 initial transform passed to the background painter.
*
* This is a bound property.
*/
@Override
public void setPaintBorderInsets(boolean paintBorderInsets) {
boolean old = this.isPaintBorderInsets();
this.paintBorderInsets = paintBorderInsets;
firePropertyChange("paintBorderInsets", old, isPaintBorderInsets());
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getPreferredSize() {
if (getComponentCount() == 1 && getComponent(0) instanceof CellRendererPane) {
return BasicGraphicsUtils.getPreferredButtonSize(fgStamp, getIconTextGap());
}
return super.getPreferredSize();
}
/**
* {@inheritDoc}
*/
@Override
protected void paintComponent(Graphics g) {
if (fgPainter == null && bgPainter == null) {
super.paintComponent(g);
} else {
LOG.fine("fgPainter:"+fgPainter + " bgPainter:"+bgPainter);
if (fgPainter == null) {
Graphics2D g2d = (Graphics2D) g.create();
try{
paintWithoutForegroundPainter(g2d);
} finally {
g2d.dispose();
}
} else if (fgPainter instanceof AbstractPainter && ((AbstractPainter>) fgPainter).getFilters().length > 0) {
paintWithForegroundPainterWithFilters(g);
} else {
// bgPainter <> null
Graphics2D g2d = (Graphics2D) g.create();
try {
paintWithForegroundPainterWithoutFilters(g2d);
} finally {
g2d.dispose();
}
}
}
}
private void paintWithoutForegroundPainter(Graphics2D g2d) {
if (bgPainter == null) {
SwingUtilities.paintComponent(g2d, bgStamp, this, 0, 0, getWidth(), getHeight());
} else {
SwingXUtilities.paintBackground(this, g2d);
}
SwingUtilities.paintComponent(g2d, fgStamp, this, 0, 0, getWidth(), getHeight());
}
private void paintWithForegroundPainterWithoutFilters(Graphics2D g2d) {
paintWithoutForegroundPainter(g2d);
if (getText() != null && !getText().isEmpty()) {
Insets i = getInsets();
viewRect.x = i.left;
viewRect.y = i.top;
viewRect.width = getWidth() - (i.right + viewRect.x);
viewRect.height = getHeight() - (i.bottom + viewRect.y);
textRect.x = textRect.y = textRect.width = textRect.height = 0;
iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
// layout the text and icon
String text = SwingUtilities.layoutCompoundLabel(
this, g2d.getFontMetrics(), getText(), getIcon(),
getVerticalAlignment(), getHorizontalAlignment(),
getVerticalTextPosition(), getHorizontalTextPosition(),
viewRect, iconRect, textRect,
getText() == null ? 0 : getIconTextGap());
if (!isPaintBorderInsets()) {
g2d.translate(i.left, i.top);
}
g2d.setPaint(fgPaint);
BasicGraphicsUtils.drawStringUnderlineCharAt(g2d, text, getDisplayedMnemonicIndex(),
textRect.x, textRect.y + g2d.getFontMetrics().getAscent());
}
}
private void paintWithForegroundPainterWithFilters(Graphics g) {
BufferedImage im = GraphicsUtilities.createCompatibleTranslucentImage(getWidth(), getHeight());
Graphics2D g2d = im.createGraphics();
try {
Graphics gfx = getComponentGraphics(g2d);
assert gfx == g2d;
paintWithForegroundPainterWithoutFilters(g2d);
} finally {
g2d.dispose();
}
Graphics2D filtered = (Graphics2D) g.create();
try {
for (BufferedImageOp filter : ((AbstractPainter>) fgPainter).getFilters()) {
filtered.setComposite(new FilterComposite(filtered.getComposite(), filter));
}
filtered.drawImage(im, 0, 0, this);
} finally {
filtered.dispose();
}
}
/**
* Notification from the UIManager
that the LaF has changed.
* Replaces the current UI object with the latest version from the UIManager
.
*
* @see javax.swing.JComponent#updateUI
*/
@Override
public void updateUI() {
super.updateUI();
if (bgStamp != null) {
bgStamp.updateUI();
}
if (fgStamp != null) {
fgStamp.updateUI();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy