From: <gda...@us...> - 2007-07-26 13:34:35
|
Revision: 2463 http://abbot.svn.sourceforge.net/abbot/?rev=2463&view=rev Author: gdavison Date: 2007-07-26 06:34:04 -0700 (Thu, 26 Jul 2007) Log Message: ----------- This fix looks to improve storage of references to cells in lists, tree and tables that are using renderers that are not derrived from JLabel. If the custom renderer doesn't derrive from JLabel it instead uses reflection to look for a method of the signature "getText() : String". This works by default with component that derrive from AbstractButton and JTextComponent; but it is relatively trivial to retrofit to other custom renderers. A more complicated scheme using AccessibleText was rejected because of the complication of implementation. The original test case for this bug was the WSDL editor in JDeveloper which used a TruncatingCellRenderer component which placed the elipses in the center rather than the end of long text entries. It was a simple step to a getText method to this implementation. Modified Paths: -------------- abbot/trunk/build.xml abbot/trunk/src/abbot/tester/JComponentTester.java abbot/trunk/src/abbot/tester/JListTester.java abbot/trunk/src/abbot/tester/JTableTester.java abbot/trunk/src/abbot/tester/JTreeTester.java abbot/trunk/test/abbot/tester/JListTesterTest.java abbot/trunk/test/abbot/tester/JTableTesterTest.java abbot/trunk/test/abbot/tester/JTreeTesterTest.java Modified: abbot/trunk/build.xml =================================================================== --- abbot/trunk/build.xml 2007-07-19 20:55:41 UTC (rev 2462) +++ abbot/trunk/build.xml 2007-07-26 13:34:04 UTC (rev 2463) @@ -249,6 +249,24 @@ </copy> </target> + <!-- Build just the src zips for use by IDE tools --> + + <target name="zip-src" + depends="resources,i18n" + description="Build abbot.jar, the primary jar file for the framework" + unless="-jar"> + <jar jarfile="${build}/abbot-src.zip" filesonly="true"> + <fileset dir="${src}"><patternset refid="core-contents"/></fileset> + </jar> + <jar jarfile="${build}/costello-src.zip" filesonly="true"> + <fileset dir="${src}"><patternset refid="scripting-contents"/></fileset> + </jar> + <copy file="logo32.gif" toFile="${build}/example"/> + <jar jarfile="${build}/example-src.zip" filesonly="true"> + <fileset dir="${ext.src}"><patternset refid="example-contents"/></fileset> + </jar> + </target> + <target name="compile-tests" depends="compile"> <javac classpathref="test.classpath" source="${jdk}" Modified: abbot/trunk/src/abbot/tester/JComponentTester.java =================================================================== --- abbot/trunk/src/abbot/tester/JComponentTester.java 2007-07-19 20:55:41 UTC (rev 2462) +++ abbot/trunk/src/abbot/tester/JComponentTester.java 2007-07-26 13:34:04 UTC (rev 2463) @@ -10,8 +10,14 @@ import abbot.*; import abbot.i18n.Strings; + +import abbot.script.ArgumentParser; + import abbot.util.AWT; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + /** Provides auto-scrolling prior to events for JComponent-derived classes. */ // NOTE may eventually need to push ComponentLocation up to Robot, so that // only mousePress and actionDrop need to be overridden. This would be mostly @@ -288,4 +294,70 @@ public static JComponentTester getTester(JComponent c) { return (JComponentTester)ComponentTester.getTester(JComponent.class); } + + + /** + * @param cr A custom cell renderer + * @return Either the name in the case or a label, or uses reflection to + * call "getText" which covers a range of other components and custom + * renderers + */ + + public static String convertRendererToString(Component cr) { + String string = null; + if (cr instanceof JLabel) { + String label = ((JLabel)cr).getText(); + if (label != null) + label = label.trim(); + if (!"".equals(label) + && !ArgumentParser.isDefaultToString(label)) { + string = label; + } + } else { + + // Fall back to looking for a generic getText call + // This will work for JTextField and JButton for examples + // and provides an extension point for other renderes + // + + try { + Method method; + method = cr.getClass().getMethod("getText", new Class[0]); + if (method != null) { + String label; + + label = (String)method.invoke(cr, new Object[0]); + if (label != null) + label = label.trim(); + if (!"".equals(label)) { + string = label; + } + } + } catch (IllegalAccessException e) { + Log.log("Error calling getText on " + + cr.getClass().getSimpleName(), e); + } catch (InvocationTargetException e) { + Log.log("Error calling getText on " + + cr.getClass().getSimpleName(), e); + } catch (NoSuchMethodException e) { + Log.log("Cannot find getText method on render " + + cr.getClass().getSimpleName(), e); + } + } + + // If we have a string do the argument converter thing + // + + if (string!=null) { + String parsed = ArgumentParser.toString(string); + String filtered = parsed == ArgumentParser.DEFAULT_TOSTRING ? null : parsed; + return filtered; + } + else { + return null; + } + } + + + } Modified: abbot/trunk/src/abbot/tester/JListTester.java =================================================================== --- abbot/trunk/src/abbot/tester/JListTester.java 2007-07-19 20:55:41 UTC (rev 2462) +++ abbot/trunk/src/abbot/tester/JListTester.java 2007-07-26 13:34:04 UTC (rev 2463) @@ -33,18 +33,8 @@ Object value = list.getModel().getElementAt(index); Component cr = list.getCellRenderer(). getListCellRendererComponent(list, value, index, false, false); - String string = null; - if (cr instanceof javax.swing.JLabel) { - string = ((javax.swing.JLabel)cr).getText(); - if (string != null) - string = string.trim(); - if (!"".equals(string) - && !ArgumentParser.isDefaultToString(string)) - return string; - } - string = ArgumentParser.toString(value); - return string == ArgumentParser.DEFAULT_TOSTRING - ? null : string; + String string = convertRendererToString(cr); + return string; } /** JList doesn't provide direct access to its contents, so make up for @@ -136,7 +126,7 @@ }, delay); // Select the location - // + // int index = location.getIndex(list); if (index < 0 || index >= list.getModel().getSize()) { Modified: abbot/trunk/src/abbot/tester/JTableTester.java =================================================================== --- abbot/trunk/src/abbot/tester/JTableTester.java 2007-07-19 20:55:41 UTC (rev 2462) +++ abbot/trunk/src/abbot/tester/JTableTester.java 2007-07-26 13:34:04 UTC (rev 2463) @@ -26,18 +26,8 @@ Component cr = table.getCellRenderer(row, col). getTableCellRendererComponent(table, value, false, false, row, col); - if (cr instanceof javax.swing.JLabel) { - String label = ((javax.swing.JLabel)cr).getText(); - if (label == null) - label = ""; - label = label.trim(); - if (!"".equals(label) - && !ArgumentParser.isDefaultToString(label)) - return label; - } - String toString = ArgumentParser.toString(value); - return toString == ArgumentParser.DEFAULT_TOSTRING - ? null : toString; + String string = convertRendererToString(cr); + return string; } /** Select the given cell, if not already. */ Modified: abbot/trunk/src/abbot/tester/JTreeTester.java =================================================================== --- abbot/trunk/src/abbot/tester/JTreeTester.java 2007-07-19 20:55:41 UTC (rev 2462) +++ abbot/trunk/src/abbot/tester/JTreeTester.java 2007-07-26 13:34:04 UTC (rev 2463) @@ -1,8 +1,14 @@ package abbot.tester; +import abbot.Log; + import java.awt.*; import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; + +import javax.accessibility.AccessibleContext; + import javax.swing.JLabel; import javax.swing.JTree; import javax.swing.tree.*; @@ -14,6 +20,13 @@ import abbot.util.AWT; import abbot.i18n.Strings; + +import java.lang.reflect.Method; + +import javax.accessibility.AccessibleText; + +import javax.swing.JComponent; + /** Provide operations on a JTree component. The JTree substructure is a "row", and JTreeLocation provides different identifiers for a row. @@ -84,6 +97,9 @@ return valueToString(tree, path, true); } + + + /** Return the {@link String} representation of the final component of the * given {@link TreePath}, or <code>null</code> if one can not be * obtained. Assumes the path is visible. @@ -98,16 +114,8 @@ tree.isExpanded(row), tree.getModel().isLeaf(value), row, false); - String string = null; - if (cr instanceof JLabel) { - String label = ((JLabel)cr).getText(); - if (label != null) - label = label.trim(); - if (!"".equals(label) - && !ArgumentParser.isDefaultToString(label)) { - string = label; - } - } + String string = convertRendererToString(cr); + if (string == null) { string = tree.convertValueToText(value, false, tree.isExpanded(row), @@ -116,10 +124,12 @@ if (ArgumentParser.isDefaultToString(string)) string = null; } + if (string == null) { String s = ArgumentParser.toString(value); string = s == ArgumentParser.DEFAULT_TOSTRING ? null : s; } + if (includeIndex) { // If there are preceding siblings which produce the same // string value, obtain one that is unique by adding an index @@ -132,12 +142,23 @@ Object child = tree.getModel().getChild(parent, i); TreePath childPath = parentPath.pathByAddingChild(child); String text = valueToString(tree, childPath, false); - if (string.equals(text)) { + // string == text deals with double null null case + if ((string==text) || (string!=null && string.equals(text))) { ++count; } } - if (count > 0) { - string += "[" + count + "]"; + + // If the string is null then ensure that we at least + // traces something out + // + + if (count > 0 || string == null) { + if (string!=null) { + string += "[" + count + "]"; + } + else { + string = "[" + count + "]"; + } } } } Modified: abbot/trunk/test/abbot/tester/JListTesterTest.java =================================================================== --- abbot/trunk/test/abbot/tester/JListTesterTest.java 2007-07-19 20:55:41 UTC (rev 2462) +++ abbot/trunk/test/abbot/tester/JListTesterTest.java 2007-07-26 13:34:04 UTC (rev 2463) @@ -10,6 +10,12 @@ import junit.extensions.abbot.Timer; import abbot.util.ExtendedComparator; +import java.awt.Component; + +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreePath; + /** Unit test to verify the JListTester class.<p> */ public class JListTesterTest extends ComponentTestFixture { @@ -143,8 +149,44 @@ tester.actionSelectIndex(list, 1); assertEquals("Cell Not Selected", list.getSelectedIndex(), 1); } + + + public void testGetTextRenderer() { + + class OtherRenderer extends JTextField + implements ListCellRenderer { + public Component getListCellRendererComponent(JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) { + + setText(value.toString()); + return this; + } + } + // + + + list.setCellRenderer(new OtherRenderer()); + + assertEquals( + "Must return the correct child text for non JLabel renderers", + JListTester.valueToString( + list , 0), + "zero"); + assertEquals( + "Must return the correct child text for non JLabel renderers", + JListTester.valueToString( + list , 1), + "one"); + + + } + + public static void main(String[] args) { RepeatHelper.runTests(args, JListTesterTest.class); } Modified: abbot/trunk/test/abbot/tester/JTableTesterTest.java =================================================================== --- abbot/trunk/test/abbot/tester/JTableTesterTest.java 2007-07-19 20:55:41 UTC (rev 2462) +++ abbot/trunk/test/abbot/tester/JTableTesterTest.java 2007-07-26 13:34:04 UTC (rev 2463) @@ -1,10 +1,13 @@ package abbot.tester; +import java.awt.Component; import java.awt.Dimension; import java.util.Vector; import javax.swing.*; +import javax.swing.table.TableCellRenderer; + import junit.extensions.abbot.*; /** Unit test to verify the JTableTester class.<p> */ @@ -85,7 +88,46 @@ assertEquals("Wrong row selected", 0, table.getSelectedRow()); assertEquals("Wrong column selected", 0, table.getSelectedColumn()); } + + + /** Ensure custom renderers work **/ + public void testGetTextRenderer() { + class OtherRenderer extends JTextField + implements TableCellRenderer { + + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + setText(value.toString()); + return this; + } + } + + // + + + table.setDefaultRenderer( + String.class, new OtherRenderer()); + + assertEquals( + "Must return the correct child text for non JLabel renderers", + JTableTester.valueToString( + table , 0 , 0), + "0 one"); + assertEquals( + "Must return the correct child text for non JLabel renderers", + JTableTester.valueToString( + table , 3,3), + "3 four"); + + + } + + public static void main(String[] args) { RepeatHelper.runTests(args, JTableTesterTest.class); } Modified: abbot/trunk/test/abbot/tester/JTreeTesterTest.java =================================================================== --- abbot/trunk/test/abbot/tester/JTreeTesterTest.java 2007-07-19 20:55:41 UTC (rev 2462) +++ abbot/trunk/test/abbot/tester/JTreeTesterTest.java 2007-07-26 13:34:04 UTC (rev 2463) @@ -1,4 +1,6 @@ package abbot.tester; + + import java.awt.event.ActionEvent; import java.awt.*; @@ -286,7 +288,118 @@ new JTreeLocation(path)); } + + /** + * Ensure that we don't see null pointer exceptions when recording with + * abbot for poorley implemented renders and model. + */ + + public void testDumbRenderer() { + + class DumbRenderer extends Component + implements TreeCellRenderer { + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean selected, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + return this; + } + } + + class DumbObject { + public DumbObject(String obj) { + + } + } + + + + DefaultMutableTreeNode root = new DefaultMutableTreeNode(new DumbObject("root")); + DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(new DumbObject("child 1")); + DefaultMutableTreeNode child2 = new DefaultMutableTreeNode(new DumbObject("child 2")); + root.add(child1); + root.add(child2); + + tree = new JTree(root); + tree.setCellRenderer(new DumbRenderer()); + + assertEquals( + "Must not return null in simple first child case", + JTreeTester.valueToString( + tree , new TreePath(new Object[] {root, child1})), + "[0]"); + + assertEquals( + "Must not return null in simple second child case", + JTreeTester.valueToString( + tree , new TreePath(new Object[] {root, child2})), + "[1]"); + } + + + /** + * Ensure that we try to use a "getText" method for non JLabel renderers + */ + + public void testGetTextRenderer() { + + class OtherObject { + + public String _obj; + + public OtherObject(String obj) { + _obj = obj; + } + } + + + class OtherRenderer extends JTextField + implements TreeCellRenderer { + + public Component getTreeCellRendererComponent(JTree tree, + Object value, + boolean selected, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + DefaultMutableTreeNode n = (DefaultMutableTreeNode)value; + setText(((OtherObject)n.getUserObject())._obj); + return this; + } + } + + + + + + DefaultMutableTreeNode root = new DefaultMutableTreeNode(new OtherObject("root")); + DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(new OtherObject("child 1")); + DefaultMutableTreeNode child2 = new DefaultMutableTreeNode(new OtherObject("child 2")); + root.add(child1); + root.add(child2); + + tree = new JTree(root); + tree.setCellRenderer(new OtherRenderer()); + + assertEquals( + "Must return the correct child text for non JLabel renderers", + JTreeTester.valueToString( + tree , new TreePath(new Object[] {root, child1})), + "child 1"); + + assertEquals( + "Must return the correct child text for non JLabel renderers", + JTreeTester.valueToString( + tree , new TreePath(new Object[] {root, child2})), + "child 2"); + } + + /** Create a new test case with the given name. */ public JTreeTesterTest(String name) { super(name); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |