/* * Created on 08.12.2010 * */ package org.jdesktop.swingx.rollover; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.AbstractListModel; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.ListModel; import javax.swing.TransferHandler; import javax.swing.table.TableModel; import org.jdesktop.swingx.InteractiveTestCase; import org.jdesktop.swingx.JXFrame; import org.jdesktop.swingx.JXList; import org.jdesktop.swingx.JXTable; import org.jdesktop.swingx.JXTree; import org.jdesktop.swingx.JXTreeTable; import org.jdesktop.swingx.decorator.ColorHighlighter; import org.jdesktop.swingx.decorator.CompoundHighlighter; import org.jdesktop.swingx.decorator.HighlightPredicate; import org.jdesktop.swingx.decorator.HighlightPredicate.AndHighlightPredicate; import org.jdesktop.swingx.decorator.Highlighter; import org.jdesktop.swingx.renderer.DefaultListRenderer; import org.jdesktop.swingx.renderer.DefaultTableRenderer; import org.jdesktop.swingx.renderer.DefaultTreeRenderer; import org.jdesktop.swingx.treetable.FileSystemModel; import org.jdesktop.test.AncientSwingTeam; public class RolloverVisualCheck extends InteractiveTestCase { private TableModel sortableTableModel; private Highlighter backgroundHighlighter; private Highlighter foregroundHighlighter; private ListModel listModel; private FileSystemModel treeTableModel; @SuppressWarnings("unused") private static final Logger LOG = Logger .getLogger(RolloverVisualCheck.class.getName()); public static void main(String[] args) { RolloverVisualCheck test = new RolloverVisualCheck(); try { test.runInteractiveTests(); // test.runInteractive("Drag"); } catch (Exception e) { e.printStackTrace(); } } /** * Issue #1249-swingx: RolloverProducer clears rollover point when inserting child * * Happens f.i. when starting an edit. * */ public void interactiveExitToChild() { JXTable table = new JXTable(new AncientSwingTeam()); table.addHighlighter(new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, Color.MAGENTA, null, Color.MAGENTA, null)); JXFrame frame = wrapWithScrollingInFrame(table, "rollover child"); addStatusMessage(frame, "edit under mouse, move"); show(frame); } /** * Issue #1193-swingx: rollover state not updated on scrolling/mouseWheel * * visualize behaviour on * - scrolling (with mouse wheel) * - resizing (added custom actions) */ public void interactiveTreeRolloverScroll() { final JXTree table = new JXTree(new FileSystemModel()); table.setCellRenderer(new DefaultTreeRenderer()); table.setRolloverEnabled(true); table.addHighlighter(new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, Color.YELLOW, null)); final JXFrame frame = getResizableFrame(table); show(frame); } /** * Issue #1193-swingx: rollover state not updated on scrolling/mouseWheel * * visualize behaviour on * - scrolling (with mouse wheel) * - resizing (added custom actions) */ public void interactiveListRolloverScroll() { final JXList table = new JXList(AncientSwingTeam.createNamedColorListModel()); table.setRolloverEnabled(true); table.addHighlighter(new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, Color.YELLOW, null)); final JXFrame frame = getResizableFrame(table); show(frame); } /** * Issue #1193-swingx: rollover state not updated on scrolling/mouseWheel * * visualize behaviour on * - scrolling (with mouse wheel) * - resizing (added custom actions) */ public void interactiveTableRolloverScroll() { final JXTable table = new JXTable(new AncientSwingTeam()); table.setEditable(false); table.setHorizontalScrollEnabled(true); table.addHighlighter(new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, Color.YELLOW, null)); final JXFrame frame = getResizableFrame(table); show(frame); } /** * @param table * @return */ private JXFrame getResizableFrame(final JComponent table) { final JXFrame frame = wrapWithScrollingInFrame(table, "rollover and wheel"); Action hd = new AbstractAction("horizontalDecrease") { @Override public void actionPerformed(ActionEvent e) { Dimension dim = frame.getSize(); dim.width -= 50; frame.setSize(dim); } }; table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( KeyStroke.getKeyStroke("A"), "horizontalDecrease"); table.getActionMap().put("horizontalDecrease", hd); Action hi = new AbstractAction("horizontalDecrease") { @Override public void actionPerformed(ActionEvent e) { Dimension dim = frame.getSize(); dim.width += 50; frame.setSize(dim); } }; table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( KeyStroke.getKeyStroke("D"), "horizontalIncrease"); table.getActionMap().put("horizontalIncrease", hi); Action vd = new AbstractAction("verticalDecrease") { @Override public void actionPerformed(ActionEvent e) { Dimension dim = frame.getSize(); dim.height -= 20; frame.setSize(dim); } }; table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( KeyStroke.getKeyStroke("W"), "verticalDecrease"); table.getActionMap().put("verticalDecrease", vd); Action vi = new AbstractAction("verticalIncrease") { @Override public void actionPerformed(ActionEvent e) { Dimension dim = frame.getSize(); dim.height += 20; frame.setSize(dim); } }; table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( KeyStroke.getKeyStroke("S"), "verticalIncrease"); table.getActionMap().put("verticalIncrease", vi); addStatusComponent(frame, new JLabel("Horizontal Resize: A <--> D ")); addStatusComponent(frame, new JLabel("Vertical Resize: W <--> S ")); return frame; } public void interactiveTableRollover() { JXTable table = new JXTable(sortableTableModel); final CompoundHighlighter compoundHighlighter = new CompoundHighlighter(foregroundHighlighter); table.setHighlighters(compoundHighlighter); JXFrame frame = wrapWithScrollingInFrame(table, "Table with rollover"); Action toggleAction = new AbstractAction("toggle foreground/background") { boolean isBackground; public void actionPerformed(ActionEvent e) { if (isBackground) { compoundHighlighter.addHighlighter(foregroundHighlighter); compoundHighlighter.removeHighlighter(backgroundHighlighter); } else { compoundHighlighter.addHighlighter(backgroundHighlighter); compoundHighlighter.removeHighlighter(foregroundHighlighter); } isBackground = !isBackground; } }; addAction(frame, toggleAction); frame.setVisible(true); } public void interactiveListRollover() { final JXList table = new JXList(listModel); table.setRolloverEnabled(true); final CompoundHighlighter compoundHighlighter = new CompoundHighlighter(foregroundHighlighter); table.setHighlighters(compoundHighlighter); JXFrame frame = wrapWithScrollingInFrame(table, "List with rollover"); Action toggleAction = new AbstractAction("toggle foreground/background") { boolean isBackground; public void actionPerformed(ActionEvent e) { if (isBackground) { compoundHighlighter.addHighlighter(foregroundHighlighter); compoundHighlighter.removeHighlighter(backgroundHighlighter); } else { compoundHighlighter.addHighlighter(backgroundHighlighter); compoundHighlighter.removeHighlighter(foregroundHighlighter); } isBackground = !isBackground; } }; addAction(frame, toggleAction); frame.setVisible(true); } /** * Issue ??: background highlighter not working in JXTree. * Not really an issue, works fine with SwingX renderer. */ public void interactiveTreeRollover() { final JXTree table = new JXTree(treeTableModel); // Note: we need swingx renderer to make some decorations work reliably. table.setCellRenderer(new DefaultTreeRenderer()); table.setRolloverEnabled(true); table.setComponentPopupMenu(createPopup()); final CompoundHighlighter compoundHighlighter = new CompoundHighlighter(foregroundHighlighter); table.setHighlighters(compoundHighlighter); JTree tree = new JTree(treeTableModel); tree.setComponentPopupMenu(createPopup()); JXFrame frame = wrapWithScrollingInFrame(table, tree, "JXTree (at left) with rollover"); Action toggleAction = new AbstractAction("toggle foreground/background") { boolean isBackground; public void actionPerformed(ActionEvent e) { if (isBackground) { compoundHighlighter.addHighlighter(foregroundHighlighter); compoundHighlighter.removeHighlighter(backgroundHighlighter); } else { compoundHighlighter.addHighlighter(backgroundHighlighter); compoundHighlighter.removeHighlighter(foregroundHighlighter); } isBackground = !isBackground; } }; addAction(frame, toggleAction); addMessage(frame, "background highlight not working in JXTree (with core renderer)"); frame.setVisible(true); } public JPopupMenu createPopup() { JPopupMenu popup = new JPopupMenu(); popup.add("dummy"); return popup; } public void interactiveTreeTableRollover() { final JXTreeTable table = new JXTreeTable(treeTableModel); final CompoundHighlighter compoundHighlighter = new CompoundHighlighter(foregroundHighlighter); table.setHighlighters(compoundHighlighter); JXFrame frame = wrapWithScrollingInFrame(table, "TreeTable with rollover"); Action toggleAction = new AbstractAction("toggle foreground/background") { boolean isBackground; public void actionPerformed(ActionEvent e) { if (isBackground) { compoundHighlighter.addHighlighter(foregroundHighlighter); compoundHighlighter.removeHighlighter(backgroundHighlighter); } else { compoundHighlighter.addHighlighter(backgroundHighlighter); compoundHighlighter.removeHighlighter(foregroundHighlighter); } isBackground = !isBackground; } }; addAction(frame, toggleAction); frame.setVisible(true); } /** * Example for per-cell rollover decoration in JXTreeTable. */ public void interactiveTreeTableRolloverHierarchical() { final JXTreeTable table = new JXTreeTable(treeTableModel); HighlightPredicate andPredicate = new AndHighlightPredicate( new HighlightPredicate.ColumnHighlightPredicate(0), HighlightPredicate.ROLLOVER_ROW ); final Highlighter foregroundHighlighter = new ColorHighlighter(andPredicate, null, Color.MAGENTA); final Highlighter backgroundHighlighter = new ColorHighlighter(andPredicate, Color.YELLOW, null); table.setHighlighters(foregroundHighlighter); JXFrame frame = wrapWithScrollingInFrame(table, "TreeTable with rollover - effect hierarchical column"); Action toggleAction = new AbstractAction("toggle foreground/background") { boolean isBackground; public void actionPerformed(ActionEvent e) { if (isBackground) { table.setHighlighters(foregroundHighlighter); } else { table.setHighlighters(backgroundHighlighter); } isBackground = !isBackground; } }; addAction(frame, toggleAction); frame.setVisible(true); } /** * Issue #456-swingx: Rollover highlighter not showing while dragging. * * Example how to force rollover while dragging (NOT dnd - in that case the visuals * are controlled by the dnd mechanism): subclass JXList to install a custom * RolloverProducer */ public void interactiveEnforceRolloverWhileDragging() { final JXList list = new JXList(AncientSwingTeam.createNamedColorListModel()) { /** * @inherited <p> */ @Override protected RolloverProducer createRolloverProducer() { ListRolloverProducer producer = new ListRolloverProducer() { /** * @inherited <p> */ @Override public void mouseDragged(MouseEvent e) { super.mouseDragged(e); updateRollover(e, ROLLOVER_KEY, false); } }; return producer; } }; list.setVisibleRowCount(list.getElementCount()); list.setRolloverEnabled(true); list.addHighlighter(new ColorHighlighter( HighlightPredicate.ROLLOVER_ROW, Color.MAGENTA, null, Color.MAGENTA, null)); TransferHandler handler = new TransferHandler() { /** * @inherited <p> */ @Override public boolean canImport(TransferSupport support) { return true; } }; list.setTransferHandler(handler); JXFrame frame = wrapWithScrollingInFrame(list, "force Rollover while dragging"); JTextField textField = new JTextField("just something to drag ...", 40); textField.setDragEnabled(true); addStatusComponent(frame, textField); show(frame); } /** * Issue #456-swingx: Rollover highlighter not showing while dragging. * * The expected behaviour: * - don't show the xRollover while dragging during a dnd, * - update the rollover to the released. */ public void interactiveRolloverWhileDragging() { final JXList list = new JXList(AncientSwingTeam.createNamedColorListModel()); list.setVisibleRowCount(list.getElementCount()); list.setRolloverEnabled(true); list.addHighlighter(new ColorHighlighter( HighlightPredicate.ROLLOVER_ROW, Color.MAGENTA, null, Color.MAGENTA, null)); TransferHandler handler = new TransferHandler() { /** * @inherited <p> */ @Override public boolean canImport(TransferSupport support) { return true; } }; list.setTransferHandler(handler); JXFrame frame = wrapWithScrollingInFrame(list, "rollover and drag-enabled (fake drop)"); JTextField textField = new JTextField("just something to drag ...", 40); textField.setDragEnabled(true); addStatusComponent(frame, textField); show(frame); } /** * Issue #1387-swingx: Rollover click-on-release-after drag. * * PENDING JW: what's the expected behaviour? */ public void interactiveRolloverClickAfterDrag() { JXList list = new JXList(AncientSwingTeam.createNamedColorListModel()); list.setVisibleRowCount(list.getElementCount()); list.setRolloverEnabled(true); list.addHighlighter(new ColorHighlighter( HighlightPredicate.ROLLOVER_ROW, Color.MAGENTA, null, Color.MAGENTA, null)); TransferHandler handler = new TransferHandler() { /** * @inherited <p> */ @Override public boolean canImport(TransferSupport support) { return true; } }; list.setTransferHandler(handler); final JXFrame frame = wrapWithScrollingInFrame(list, "release-after-drag must not trigger clicked"); // rollover-enabled default renderer // Note JW: this implicitly changes the cursor to the hand-cursor DefaultListRenderer renderer = new DefaultListRenderer() { @Override public void doClick() { JOptionPane.showMessageDialog(frame, "Clicked"); } @Override public boolean isEnabled() { return true; } }; list.setCellRenderer(renderer); JTextField textField = new JTextField("just something to drag ...", 40); textField.setDragEnabled(true); addStatusComponent(frame, textField); Action action = new AbstractAction("drag into me - am I called on release?") { @Override public void actionPerformed(ActionEvent e) { LOG.info("triggered..." + ((Component) e.getSource()).getName()); } }; JButton button = new JButton(action); button.setName("first"); addStatusComponent(frame, button); JButton other = new JButton(action); other.setName("second"); addStatusComponent(frame, other); show(frame); } /** * Issue #1374-swingx: Rollover click must be disabled if target disabled * * Visual test for JXTable, adapted from reporter's test case */ public void interactiveRolloverDisabledClickList() { JXList table = new JXList(AncientSwingTeam.createNamedColorListModel()); table.setEnabled(false); table.setRolloverEnabled(true); final JXFrame frame = showWithScrollingInFrame(table, "disable list must not trigger rollover renderer"); // rollover-enabled default renderer DefaultListRenderer renderer = new DefaultListRenderer() { @Override public void doClick() { JOptionPane.showMessageDialog(frame, "Click"); } @Override public boolean isEnabled() { return true; } }; table.setCellRenderer(renderer); addEnabledToggle(frame, table); } /** * Issue #1374-swingx: Rollover click must be disabled if target disabled * * Visual test for JXTable, adapted from reporter's test case */ public void interactiveRolloverDisabledClickTree() { JXTree table = new JXTree(); table.setEnabled(false); table.setRolloverEnabled(true); final JXFrame frame = showWithScrollingInFrame(table, "disable tree must not trigger rollover renderer"); // rollover-enabled default renderer DefaultTreeRenderer renderer = new DefaultTreeRenderer() { @Override public void doClick() { JOptionPane.showMessageDialog(frame, "Click"); } @Override public boolean isEnabled() { return true; } }; table.setCellRenderer(renderer); addEnabledToggle(frame, table); } /** * Issue #1374-swingx: Rollover click must be disabled if target disabled * * Visual test for JXTable, adapted from reporter's test case */ public void interactiveRolloverDisabledClickTable() { JXTable table = new JXTable(new AncientSwingTeam()); table.setEditable(false); table.setEnabled(false); final JXFrame frame = showWithScrollingInFrame(table, "disable table must not trigger rollover renderer"); // rollover-enabled default renderer DefaultTableRenderer renderer = new DefaultTableRenderer() { @Override public void doClick() { JOptionPane.showMessageDialog(frame, "Click"); } @Override public boolean isEnabled() { return true; } }; table.setDefaultRenderer(Object.class, renderer); addEnabledToggle(frame, table); } @Override protected void setUp() throws Exception { super.setUp(); sortableTableModel = new AncientSwingTeam(); listModel = new AbstractListModel() { public int getSize() { return sortableTableModel.getRowCount(); } public Object getElementAt(int index) { return sortableTableModel.getValueAt(index, 0); } }; treeTableModel = new FileSystemModel(); foregroundHighlighter = new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, null, Color.MAGENTA); backgroundHighlighter = new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, Color.YELLOW, null); } }