/*
* $Id$
*
* 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.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import org.jdesktop.swingx.action.AbstractActionExt;
import org.jdesktop.swingx.painter.ImagePainter;
import org.jdesktop.swingx.painter.MattePainter;
import org.jdesktop.swingx.test.XTestUtils;
import org.jdesktop.swingx.util.PaintUtils;
import com.sun.java.swing.Painter;
/**
* Contains methods to visually test JXPanel.
*
* @author Jeanette Winzenburg
*/
public class JXPanelVisualCheck extends InteractiveTestCase {
public static void main(String args[]) {
final JXPanelVisualCheck test = new JXPanelVisualCheck();
setLAF("Nimbus");
// UIManager.put("JXPanel.patch", Boolean.TRUE);
try {
// test.runInteractiveTests();
test.runInteractiveTests("interactiveBackgroundAlphaToggleOpaque");
// test.runInteractive("PanelPainter");
// test.runInteractive("BackgroundAndAlphaCheck");
// test.runInteractive("FrameArtefacts");
} catch (Exception e) {
System.err.println("exception when executing interactive tests:");
e.printStackTrace();
}
}
/**
* Issue #1515-swingx: painting artefacts in a JXFrame (which uses JXPanel
* as rootPane)
*
* If the upper frame contains a JXPanel with alpha, the lower background is
* painted only below the area of the upper frame. All fine without alpha on
* the upper. The exact outcome is erractic (sometimes half or even fully
* painted). On/off EDT doesn't seem to make a difference.
*/
public void interactiveXPanelInFrameArtefacts() {
JPanel panel = new JPanel();
Color red = Color.RED;
panel.setBackground(red);
JXFrame frame = wrapInFrame(panel,
"plain panel added to contentPane of a xframe");
show(frame, 400, 400);
JXPanel other = new JXPanel();
other.setAlpha(.5f);
JXFrame otherFrame = wrapInFrame(other,
"xpanel with alpha, showing on top of first");
show(otherFrame, 100, 100);
}
/**
* Issue #1516-swingx: need feature to _not_ paint the background if alpha
* and not-opaque
*
*
*/
public void interactiveBackgroundAlphaToggleOpaque() {
JPanel container = new JPanel(new GridLayout(0, 3));
Color base = Color.RED;
Color alpha = PaintUtils.setAlpha(base, 100);
final JPanel p = new JPanel();
p.setBorder(BorderFactory.createTitledBorder("core (alpha back)"));
p.setBackground(alpha);
final JLabel coreLabel = new JLabel("is-opaque: " + p.isOpaque());
p.add(coreLabel);
final JXPanel xp1 = new JXPanel();
xp1.setBorder(BorderFactory.createTitledBorder("x (alpha back)"));
xp1.setBackground(alpha);
final JLabel xbackAlpha = new JLabel("is-opaque: " + xp1.isOpaque());
xp1.add(xbackAlpha);
final JXPanel xp2 = new JXPanel();
xp2.setBorder(BorderFactory.createTitledBorder("x (alpha container)"));
xp2.setBackground(base);
xp2.setAlpha(100f / 255f);
final JLabel xcontainerAlpha = new JLabel("is-opaque: "
+ xp2.isOpaque());
xp2.add(xcontainerAlpha);
container.add(p);
container.add(xp1);
container.add(xp2);
JXFrame frame = wrapInFrame(container,
"opaque with alpha " + System.getProperty("java.version") + " "
+ UIManager.get("JXPanel.patch"));
Action action = new AbstractAction("toggle opaque (is on)") {
boolean realOpaque = true;
@Override
public void actionPerformed(ActionEvent e) {
realOpaque = !realOpaque;
putValue(Action.NAME, realOpaque ? "toggle opaque (is on)"
: "toggle opaque (is off)");
p.setOpaque(realOpaque);
xp1.setOpaque(realOpaque);
xp2.setOpaque(realOpaque);
coreLabel.setText("is-opaque: " + p.isOpaque());
xbackAlpha.setText("is-opaque: " + xbackAlpha.isOpaque());
xcontainerAlpha.setText("is-opaque: "
+ xcontainerAlpha.isOpaque());
p.repaint();
xp1.repaint();
xp2.repaint();
}
};
addAction(frame, action);
show(frame, 400, 400);
}
/**
* Issue 1517-swingx: JXPanel - background color depends on opaqueness prior
* to setting
*/
public void interactiveBackgroundAlphaColorDependsOnOpaque() {
JPanel container = new JPanel(new GridLayout(0, 2));
Color alpha = PaintUtils.setAlpha(Color.RED, 100);
JXPanel opaque = new JXPanel();
opaque.setBorder(BorderFactory
.createTitledBorder("xpanel (alpha color, real opaque)"));
opaque.setBackground(alpha);
JXPanel nonOpaque = new JXPanel();
nonOpaque.setOpaque(false);
nonOpaque.setBorder(BorderFactory
.createTitledBorder("xpanel (alpha color, real !opaque)"));
nonOpaque.setBackground(alpha);
container.add(opaque);
container.add(nonOpaque);
show(wrapInFrame(container,
"compare alpha background: opaque <-> not opaque"), 400, 400);
}
/**
* Issue ??-swingx: support core painters in synth-based LAFs
*
* In synth-based LAFs (core) painters are applied on top of the background
* fill and below the foreground (== content) painting. SwingX painters are
* applied on top of the background but below the core painter.
*
* The example below has:
*
* - yellowish background color - SwingX ImagePainter - core painter which
* paints a diagonal line (top left to bottom right) - a label as content
*
* With Nimbus, all three "background" layers should be visible
*
* Actions:
*
* - toggle opaqueness: if false, the background color must not be painted
* - toggle alpha of background color: must not show any artefacts
* - toggle alpha of containter: must not show any artefacts, must respect the
* background filling or not (opaqueness on/off), background alpha must be
* unchanged
*/
public void interactiveCustomPanelPainter() {
final JXPanel panel = new JXPanel(new BorderLayout());
final Color background = Color.YELLOW;
final Color backgroundTrans = PaintUtils.setAlpha(background, 100);
panel.setBackground(background);
panel.setBackgroundPainter(new ImagePainter(XTestUtils
.loadDefaultImage("moon.jpg")));
JLabel label = new JLabel(" seeing something");
label.setHorizontalAlignment(JLabel.CENTER);
label.setFont(label.getFont().deriveFont(55f));
panel.add(label);
UIDefaults defaults = new UIDefaults();
defaults.put("Panel.backgroundPainter", new CrossPainter());
panel.putClientProperty("Nimbus.Overrides", defaults);
panel.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
JXFrame frame = wrapInFrame(panel, "background");
Action opaque = new AbstractAction("toggle opaque (is: true)") {
boolean isOpaque = true;
@Override
public void actionPerformed(ActionEvent e) {
isOpaque = !isOpaque;
panel.setOpaque(isOpaque);
putValue(NAME, "toggle opaque (is: " + isOpaque);
panel.repaint();
}
};
addAction(frame, opaque);
Action containerAlpha = new AbstractAction("toggle container alpha") {
@Override
public void actionPerformed(ActionEvent e) {
float alpha = panel.getAlpha();
panel.setAlpha(alpha < 1f ? 1f : 0.5f);
}
};
addAction(frame, containerAlpha);
Action backgroundAlpha = new AbstractAction("toggle background alpha") {
@Override
public void actionPerformed(ActionEvent e) {
Color back = panel.getBackground();
panel.setBackground(back.getAlpha() < 255 ? background
: backgroundTrans);
}
};
addAction(frame, backgroundAlpha);
show(frame, 800, 1000);
}
public static class CrossPainter implements Painter<JComponent> {
BasicStroke stroke = new BasicStroke(20f);
@Override
public void paint(Graphics2D g, JComponent comp, int width, int height) {
g.setColor(Color.MAGENTA);
g.setStroke(stroke);
g.drawLine(0, 0, comp.getWidth(), comp.getHeight());
}
}
/**
* Issue #1199-swingx: JXPanel - must repaint on changes to background
* painter.
*/
public void interactivePainterUpdate() {
JXPanel panel = new JXPanel();
final MattePainter painter = new MattePainter(Color.RED);
panel.setBackgroundPainter(painter);
JXFrame frame = wrapInFrame(panel, "background");
Action toggleColor = new AbstractAction("toggle background") {
@Override
public void actionPerformed(ActionEvent e) {
Paint old = painter.getFillPaint();
painter.setFillPaint(old == Color.RED ? Color.YELLOW
: Color.RED);
}
};
addAction(frame, toggleColor);
show(frame, 200, 200);
}
/**
* Issue #1187-swingx: default scrollable tracks property prevents
* scrolling. Problem are the implementations of scrollableTracks: they
* unconditionally return true, so forcing the viewport/scrollpane to the
* size of the contained component.
*/
public void interactiveScrolling() {
final JXPanel panel = new JXPanel(new BorderLayout());
panel.add(createScrollableContent(20));
JXFrame frame = wrapWithScrollingInFrame(panel,
"scrollbar must be showing");
Action toggleHeightTrack = new AbstractActionExt("track height: "
+ panel.getScrollableHeightHint()) {
ScrollableSizeHint[] tracks = new ScrollableSizeHint[] {
ScrollableSizeHint.FIT, ScrollableSizeHint.NONE,
ScrollableSizeHint.PREFERRED_STRETCH };
int position;
@Override
public void actionPerformed(ActionEvent e) {
position++;
if (position >= tracks.length)
position = 0;
panel.setScrollableHeightHint(tracks[position]);
setName("track height: " + tracks[position]);
}
};
addAction(frame, toggleHeightTrack);
show(frame, 400, 400);
}
/**
* @return
*/
private JComponent createScrollableContent(int rows) {
JPanel component = new JPanel();
component.setPreferredSize(new Dimension(400, 400));
component.setMinimumSize(new Dimension(200, 200));
component.setMaximumSize(new Dimension(600, 600));
component.setBorder(BorderFactory.createLineBorder(Color.RED, 5));
// JButton component = new JButton("gotcha!");
// JXTable table = new JXTable(rows, 6);
// for (int i = 0; i < table.getRowCount(); i++) {
// table.setValueAt("row: " + i, i, 0);
// }
return component;
}
/**
* See a painter at work.
*
* Plus Issue ??-swingx: setting opaqueness _after_ the painter leads to
* painting artefacts.
*
* Here: run this check with several tests active so that the frame create
* here is overlapped by others, the click on its title to move to front.
* The background is not uniform: the formerly covered part is grey, the
* formerly exposed part is white.
*
* Update: probably similar to #1515
*
* @throws Exception
*/
public void interactiveIconPainter() throws Exception {
ImagePainter imagePainter = new ImagePainter(ImageIO.read(JXPanel.class
.getResource("resources/images/kleopatra.jpg")));
JXPanel panel = new JXPanel();
panel.setBackgroundPainter(imagePainter);
// uncomment to see the painting glitch. Move to before setting the
// background painter and
// all is fine.
panel.setOpaque(false);
panel.setPreferredSize(new Dimension(200, 200));
showWithScrollingInFrame(panel, "icon painter in jxpanel");
}
public void interactiveAlphaCheck() {
JXPanel xp = new JXPanel();
xp.setBackgroundPainter(new MattePainter(PaintUtils.AERITH, true));
xp.setAlpha(.5f);
xp.add(new JButton("Press Me"));
JPanel p = new JPanel(new BorderLayout());
p.setBackground(Color.BLACK);
p.add(xp);
show(wrapInFrame(p, "Alpha Check"), 200, 200);
}
public void interactiveBackgroundAndAlphaCheck() {
final JXPanel xp = new JXPanel();
xp.setBackground(Color.RED);
xp.setAlpha(.5f);
xp.add(new JButton("Press Me"));
JPanel p = new JPanel(new BorderLayout());
p.setBackground(Color.BLACK);
p.add(xp);
show(wrapInFrame(p, "Alpha Check"), 200, 200);
}
/**
* do-nothing method - suppress warning if there are no other test fixtures
* to run.
*
*/
public void testDummy() {
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger.getLogger(JXPanelVisualCheck.class
.getName());
}