diff --git a/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java b/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java index acd141c1c4ad04b10d4329d1641b4c1564815290..f8c163d5d2d00054bed3ae11521c5d6353be18ab 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,7 +113,6 @@ public class BasicColorChooserUI extends ColorChooserUI previewPanelHolder.setBorder(new TitledBorder(previewString)); } previewPanelHolder.setInheritsPopupMenu(true); - chooser.add(previewPanelHolder, BorderLayout.SOUTH); installPreviewPanel(); chooser.applyComponentOrientation(c.getComponentOrientation()); @@ -126,13 +125,9 @@ public class BasicColorChooserUI extends ColorChooserUI uninstallDefaultChoosers(); uninstallListeners(); + uninstallPreviewPanel(); uninstallDefaults(); - previewPanelHolder.remove(previewPanel); - if (previewPanel instanceof UIResource) { - chooser.setPreviewPanel(null); - } - previewPanelHolder = null; previewPanel = null; defaultChoosers = null; @@ -143,29 +138,37 @@ public class BasicColorChooserUI extends ColorChooserUI } protected void installPreviewPanel() { - if (previewPanel != null) { - previewPanelHolder.remove(previewPanel); - previewPanel.removeMouseListener(getHandler()); + JComponent previewPanel = this.chooser.getPreviewPanel(); + if (previewPanel == null) { + previewPanel = ColorChooserComponentFactory.getPreviewPanel(); } - - previewPanel = chooser.getPreviewPanel(); - Dimension layoutSize = new Dimension(); // fix for bug 4759306 - if (previewPanel != null) { - layoutSize = new BorderLayout().minimumLayoutSize(previewPanel); - if ((previewPanelHolder != null) && (chooser != null) && - (layoutSize.getWidth() + layoutSize.getHeight() == 0)) { - chooser.remove(previewPanelHolder); - return; + else { + Dimension size = new BorderLayout().minimumLayoutSize(previewPanel); + if ((size.width == 0) && (size.height == 0)) { + previewPanel = null; } } - if (previewPanel == null || previewPanel instanceof UIResource) { - previewPanel = ColorChooserComponentFactory.getPreviewPanel(); // get from table? - chooser.setPreviewPanel(previewPanel); + this.previewPanel = previewPanel; + if (previewPanel != null) { + chooser.add(previewPanelHolder, BorderLayout.SOUTH); + previewPanel.setForeground(chooser.getColor()); + previewPanelHolder.add(previewPanel); + previewPanel.addMouseListener(getHandler()); + previewPanel.setInheritsPopupMenu(true); } - previewPanel.setForeground(chooser.getColor()); - previewPanelHolder.add(previewPanel); - previewPanel.addMouseListener(getHandler()); - previewPanel.setInheritsPopupMenu(true); + } + + /** + * Removes installed preview panel from the UI delegate. + * + * @since 1.7 + */ + protected void uninstallPreviewPanel() { + if (this.previewPanel != null) { + this.previewPanel.removeMouseListener(getHandler()); + this.previewPanelHolder.remove(this.previewPanel); + } + this.chooser.remove(this.previewPanelHolder); } protected void installDefaults() { @@ -209,7 +212,6 @@ public class BasicColorChooserUI extends ColorChooserUI chooser.removePropertyChangeListener( propertyChangeListener ); chooser.getSelectionModel().removeChangeListener(previewListener); previewListener = null; - previewPanel.removeMouseListener(getHandler()); } private void selectionChanged(ColorSelectionModel model) { @@ -312,9 +314,8 @@ public class BasicColorChooserUI extends ColorChooserUI } } else if (prop == JColorChooser.PREVIEW_PANEL_PROPERTY) { - if (evt.getNewValue() != previewPanel) { - installPreviewPanel(); - } + uninstallPreviewPanel(); + installPreviewPanel(); } else if (prop == JColorChooser.SELECTION_MODEL_PROPERTY) { ColorSelectionModel oldModel = (ColorSelectionModel) evt.getOldValue(); @@ -352,5 +353,4 @@ public class BasicColorChooserUI extends ColorChooserUI super("color"); } } - } diff --git a/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java b/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java index 077c15b9d4a9c73e8fb092ed99fdccc42e03e580..803e4d01bda8dd082f56c9c76798a8c2c8eac6c8 100644 --- a/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java +++ b/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java @@ -202,8 +202,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { * Implementation of ComboPopup.show(). */ public void show() { + comboBox.firePopupMenuWillBecomeVisible(); setListSelection(comboBox.getSelectedIndex()); - Point location = getPopupLocation(); show( comboBox, location.x, location.y ); } @@ -344,7 +344,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected void firePopupMenuWillBecomeVisible() { super.firePopupMenuWillBecomeVisible(); - comboBox.firePopupMenuWillBecomeVisible(); + // comboBox.firePopupMenuWillBecomeVisible() is called from BasicComboPopup.show() method + // to let the user change the popup menu from the PopupMenuListener.popupMenuWillBecomeVisible() } protected void firePopupMenuWillBecomeInvisible() { diff --git a/src/share/classes/javax/swing/text/DefaultFormatter.java b/src/share/classes/javax/swing/text/DefaultFormatter.java index d6e47c5fdf91b2892fd0320d22076745a84be168..75c3481678ef1a562c50216ce9478adc3781209c 100644 --- a/src/share/classes/javax/swing/text/DefaultFormatter.java +++ b/src/share/classes/javax/swing/text/DefaultFormatter.java @@ -570,7 +570,9 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter direction = -1; } - if (getOverwriteMode() && rh.text != null) { + if (getOverwriteMode() && rh.text != null && + getFormattedTextField().getSelectedText() == null) + { rh.length = Math.min(Math.max(rh.length, rh.text.length()), rh.fb.getDocument().getLength() - rh.offset); } diff --git a/src/share/classes/javax/swing/text/InternationalFormatter.java b/src/share/classes/javax/swing/text/InternationalFormatter.java index c511b20e281f07191f92a66a21b53dc8ca332cf5..b49fed2e3ce54b0298c2fa0f9de2954935579b8c 100644 --- a/src/share/classes/javax/swing/text/InternationalFormatter.java +++ b/src/share/classes/javax/swing/text/InternationalFormatter.java @@ -622,18 +622,8 @@ public class InternationalFormatter extends DefaultFormatter { /** * Overriden in an attempt to honor the literals. - *

- * If we do - * not allow invalid values and are in overwrite mode, this does the - * following for each character in the replacement range: - *

    - *
  1. If the character is a literal, add it to the string to replace - * with. If there is text to insert and it doesn't match the - * literal, then insert the literal in the the middle of the insert - * text. This allows you to either paste in literals or not and - * get the same behavior. - *
  2. If there is no text to insert, replace it with ' '. - *
+ *

If we do not allow invalid values and are in overwrite mode, this + * {@code rh.length} is corrected as to preserve trailing literals. * If not in overwrite mode, and there is text to insert it is * inserted at the next non literal index going forward. If there * is only text to remove, it is removed from the next non literal @@ -643,61 +633,27 @@ public class InternationalFormatter extends DefaultFormatter { if (!getAllowsInvalid()) { String text = rh.text; int tl = (text != null) ? text.length() : 0; + JTextComponent c = getFormattedTextField(); - if (tl == 0 && rh.length == 1 && getFormattedTextField(). - getSelectionStart() != rh.offset) { + if (tl == 0 && rh.length == 1 && c.getSelectionStart() != rh.offset) { // Backspace, adjust to actually delete next non-literal. rh.offset = getNextNonliteralIndex(rh.offset, -1); - } - if (getOverwriteMode()) { - StringBuffer replace = null; - - for (int counter = 0, textIndex = 0, - max = Math.max(tl, rh.length); counter < max; - counter++) { - if (isLiteral(rh.offset + counter)) { - if (replace != null) { - replace.append(getLiteral(rh.offset + - counter)); - } - if (textIndex < tl && text.charAt(textIndex) == - getLiteral(rh.offset + counter)) { - textIndex++; - } - else if (textIndex == 0) { - rh.offset++; - rh.length--; - counter--; - max--; - } - else if (replace == null) { - replace = new StringBuffer(max); - replace.append(text.substring(0, textIndex)); - replace.append(getLiteral(rh.offset + - counter)); - } - } - else if (textIndex < tl) { - if (replace != null) { - replace.append(text.charAt(textIndex)); - } - textIndex++; - } - else { - // Nothing to replace it with, assume ' ' - if (replace == null) { - replace = new StringBuffer(max); - if (textIndex > 0) { - replace.append(text.substring(0, textIndex)); - } - } - if (replace != null) { - replace.append(' '); - } + } else if (getOverwriteMode()) { + int pos = rh.offset; + int textPos = pos; + boolean overflown = false; + + for (int i = 0; i < rh.length; i++) { + while (isLiteral(pos)) pos++; + if (pos >= string.length()) { + pos = textPos; + overflown = true; + break; } + textPos = ++pos; } - if (replace != null) { - rh.text = replace.toString(); + if (overflown || c.getSelectedText() == null) { + rh.length = pos - rh.offset; } } else if (tl > 0) { diff --git a/test/java/beans/XMLEncoder/Test4631471.java b/test/java/beans/XMLEncoder/Test4631471.java index 9c67e60e3d981a74c43bc43e48dbfb57ac684332..0b3b107f7c69dde0b7ea6e5963b483f5a4929792 100644 --- a/test/java/beans/XMLEncoder/Test4631471.java +++ b/test/java/beans/XMLEncoder/Test4631471.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4631471 + * @bug 4631471 6972468 * @summary Tests DefaultTreeModel encoding * @author Sergey Malenkov, Mark Davidson */ @@ -37,6 +37,12 @@ import javax.swing.tree.TreeNode; public abstract class Test4631471 extends AbstractTest { public static void main(String[] args) throws Exception { + main(); + System.setSecurityManager(new SecurityManager()); + main(); + } + + private static void main() throws Exception { // the DefaultMutableTreeNode will archive correctly new Test4631471() { protected Object getObject() { diff --git a/test/java/beans/XMLEncoder/Test4903007.java b/test/java/beans/XMLEncoder/Test4903007.java index 82583720934be58f8ab09011c5cd933647aebf95..02ba9a6a939414e71e00ddbfacbd1059bfed61e4 100644 --- a/test/java/beans/XMLEncoder/Test4903007.java +++ b/test/java/beans/XMLEncoder/Test4903007.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4903007 + * @bug 4903007 6972468 * @summary Tests encoding of container with boxes and BoxLayout * @author Sergey Malenkov, Mark Davidson */ @@ -36,7 +36,7 @@ import javax.swing.JPanel; public class Test4903007 extends AbstractTest { public static void main(String[] args) throws Exception { - new Test4903007().test(false); // TODO: could not encode with security manager + new Test4903007().test(true); } protected JPanel getObject() { diff --git a/test/java/beans/XMLEncoder/javax_swing_JLayeredPane.java b/test/java/beans/XMLEncoder/javax_swing_JLayeredPane.java index 05c90ba15dc9e77a9c3dcbd8b8a10d74d37e02ad..1e41bc41e7bccbefa20b30c3371b7aea31d21949 100644 --- a/test/java/beans/XMLEncoder/javax_swing_JLayeredPane.java +++ b/test/java/beans/XMLEncoder/javax_swing_JLayeredPane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 5023552 + * @bug 5023552 6972468 * @summary Tests JLayeredPane encoding * @author Sergey Malenkov */ @@ -35,7 +35,7 @@ import javax.swing.JPanel; public final class javax_swing_JLayeredPane extends AbstractTest { public static void main(String[] args) { - new javax_swing_JLayeredPane().test(false); // TODO: could not encode with security manager + new javax_swing_JLayeredPane().test(true); } private static void init(JLayeredPane pane, int layer, int x, int y, int w, int h, Color color) { diff --git a/test/javax/swing/JColorChooser/Test6199676.java b/test/javax/swing/JColorChooser/Test6199676.java new file mode 100644 index 0000000000000000000000000000000000000000..19bb68b49005cd5cb68f2b1d24c71fbc0f6a3160 --- /dev/null +++ b/test/javax/swing/JColorChooser/Test6199676.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6199676 + * @summary Tests preview panel after L&F changing + * @author Sergey Malenkov + */ + +import java.awt.Component; +import java.awt.Container; +import javax.swing.JColorChooser; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; + +public class Test6199676 implements Runnable { + public static void main(String[] args) { + SwingUtilities.invokeLater(new Test6199676()); + } + + private static void exit(String error) { + if (error != null) { + System.err.println(error); + System.exit(1); + } + else { + System.exit(0); + } + } + + private static Component getPreview(Container container) { + String name = "ColorChooser.previewPanelHolder"; + for (Component component : container.getComponents()) { + if (!name.equals(component.getName())) { + component = (component instanceof Container) + ? getPreview((Container) component) + : null; + } + if (component instanceof Container) { + container = (Container) component; + return 1 == container.getComponentCount() + ? container.getComponent(0) + : null; + } + } + return null; + } + + private static boolean isShowing(Component component) { + return (component != null) && component.isShowing(); + } + + private int index; + private boolean updated; + private JColorChooser chooser; + + public synchronized void run() { + if (this.chooser == null) { + this.chooser = new JColorChooser(); + + JFrame frame = new JFrame(getClass().getName()); + frame.add(this.chooser); + frame.setVisible(true); + } + else if (this.updated) { + if (isShowing(this.chooser.getPreviewPanel())) { + exit("custom preview panel is showing"); + } + exit(null); + } + else { + Component component = this.chooser.getPreviewPanel(); + if (component == null) { + component = getPreview(this.chooser); + } + if (!isShowing(component)) { + exit("default preview panel is not showing"); + } + this.updated = true; + this.chooser.setPreviewPanel(new JPanel()); + } + LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels(); + LookAndFeelInfo info = infos[++this.index % infos.length]; + try { + UIManager.setLookAndFeel(info.getClassName()); + } + catch (Exception exception) { + exit("could not change L&F"); + } + SwingUtilities.updateComponentTreeUI(this.chooser); + SwingUtilities.invokeLater(this); + } +} diff --git a/test/javax/swing/JComboBox/4743225/bug4743225.java b/test/javax/swing/JComboBox/4743225/bug4743225.java new file mode 100644 index 0000000000000000000000000000000000000000..2a41b3075acf97dbe9f348f2598a592598562517 --- /dev/null +++ b/test/javax/swing/JComboBox/4743225/bug4743225.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4743225 + * @summary Size of JComboBox list is wrong when list is populated via PopupMenuListener + * @author Alexander Potochkin + */ + +import sun.awt.SunToolkit; + +import javax.accessibility.AccessibleContext; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.basic.BasicComboPopup; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; + +public class bug4743225 extends JFrame { + + private static JComboBox cb; + private static volatile boolean flag; + + public bug4743225() { + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setLayout(new FlowLayout()); + cb = new JComboBox(new Object[] {"one", "two", "three"}); + cb.addPopupMenuListener(new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + cb.addItem("Test"); + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + } + + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + add(cb); + pack(); + } + + public static BasicComboPopup getPopup() { + AccessibleContext c = cb.getAccessibleContext(); + for(int i = 0; i < c.getAccessibleChildrenCount(); i ++) { + if (c.getAccessibleChild(i) instanceof BasicComboPopup) { + return (BasicComboPopup) c.getAccessibleChild(i); + } + } + throw new AssertionError("No BasicComboPopup found"); + } + + public static void main(String... args) throws Exception { + + Robot robot = new Robot(); + robot.setAutoDelay(20); + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + new bug4743225().setVisible(true); + } + }); + toolkit.realSync(); + + // calling this method from main thread is ok + Point point = cb.getLocationOnScreen(); + robot.mouseMove(point.x + 10, point.y + 10); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + if(getPopup().getList().getLastVisibleIndex() == 3) { + flag = true; + } + } + }); + + if (!flag) { + throw new RuntimeException("The ComboBox popup wasn't correctly updated"); + } + } +} diff --git a/test/javax/swing/JFormattedTextField/Test6462562.java b/test/javax/swing/JFormattedTextField/Test6462562.java new file mode 100644 index 0000000000000000000000000000000000000000..0696a016fba475ebced6f6147ec05919c4907ac1 --- /dev/null +++ b/test/javax/swing/JFormattedTextField/Test6462562.java @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6462562 + @summary Tests text input into JFormattedTextField + with an InternationalFormatter + @author Peter Zhelezniakov + @run main Test6462562 +*/ + +import java.awt.event.ActionEvent; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import javax.swing.Action; +import javax.swing.JFormattedTextField; +import javax.swing.SwingUtilities; +import javax.swing.text.Caret; +import javax.swing.text.DateFormatter; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.InternationalFormatter; +import javax.swing.text.NumberFormatter; + + +public class Test6462562 +{ + static final String BACKSPACE = new String("backspace"); + static final String DELETE = new String("delete"); + + boolean failed = false; + + void test() { + testPercentFormat(); + testCurrencyFormat(); + testIntegerFormat(); + testDateFormat(); + + if (failed) { + throw new RuntimeException("Some testcases failed, see output above"); + } + System.err.println("(-; All testcases passed ;-)"); + } + + TestFormattedTextField create(NumberFormat format) { + format.setMaximumFractionDigits(0); + NumberFormatter fmt = new NumberFormatter(format); + return new TestFormattedTextField(fmt); + } + + TestFormattedTextField create(DateFormat format) { + DateFormatter fmt = new DateFormatter(format); + return new TestFormattedTextField(fmt); + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + new Test6462562().test(); + } + }); + } + + class TestFormattedTextField extends JFormattedTextField + { + final Action backspace; + final Action delete; + final Action insert; + + final ActionEvent dummyEvent; + + public TestFormattedTextField(InternationalFormatter fmt) { + super(fmt); + fmt.setAllowsInvalid(false); + fmt.setOverwriteMode(true); + + backspace = getActionMap().get(DefaultEditorKit.deletePrevCharAction); + delete = getActionMap().get(DefaultEditorKit.deleteNextCharAction); + insert = getActionMap().get(DefaultEditorKit.insertContentAction); + dummyEvent = new ActionEvent(this, 0, null); + } + + public boolean test(int pos, int selectionLength, String todo, Object expectedResult) { + Object v0 = getValue(); + + Caret caret = getCaret(); + caret.setDot(pos); + if (selectionLength > 0) { + caret.moveDot(pos + selectionLength); + } + + String desc = todo; + if (todo == BACKSPACE) { + backspace.actionPerformed(dummyEvent); + } else if (todo == DELETE) { + delete.actionPerformed(dummyEvent); + } else { + desc = "insert('" + todo + "')"; + insert.actionPerformed(new ActionEvent(this, 0, todo)); + } + + try { + commitEdit(); + } catch (ParseException e) { + e.printStackTrace(); + failed = true; + return false; + } + + Object v1 = getValue(); + if (! v1.equals(expectedResult)) { + System.err.printf("Failure: value='%s', mark=%d, dot=%d, action=%s\n", + v0, pos, pos + selectionLength, desc); + System.err.printf(" Result: '%s', expected: '%s'\n", v1, expectedResult); + failed = true; + return false; + } + return true; + } + } + + void testPercentFormat() { + NumberFormat format = NumberFormat.getPercentInstance(Locale.US); + TestFormattedTextField ftf = create(format); + ftf.setValue(.34); + + System.err.println("Testing NumberFormat.getPercentInstance(Locale.US)"); + + // test inserting individual characters + ftf.test(0, 0, "1", .14); + ftf.test(2, 0, "2", 1.42); + ftf.test(1, 0, "0", 1.02); + + // test inserting several characters at once - e.g. from clipboard + ftf.test(0, 0, "1024", 10.24); + ftf.test(3, 0, "333", 103.33); + ftf.test(6, 0, "77", 10333.77); + ftf.test(4, 0, "99", 10399.77); + ftf.test(6, 0, "00", 10390.07); + + // test inserting strings that contain some formatting + ftf.test(0, 0, "2,2", 2290.07); + ftf.test(2, 0, "2,2", 222.27); + ftf.test(4, 0, "2,2", 222.22); + ftf.test(6, 0, "33,33", 2222233.33); + + // test delete + ftf.test(0, 0, DELETE, 222233.33); + ftf.test(10, 0, DELETE, 222233.33); + ftf.test(5, 0, DELETE, 22223.33); + ftf.test(6, 0, DELETE, 2222.33); + + // test backspace + ftf.test(0, 0, BACKSPACE, 2222.33); + ftf.test(7, 0, BACKSPACE, 222.23); + ftf.test(4, 0, BACKSPACE, 22.23); + ftf.test(2, 0, BACKSPACE, 2.23); + + // test replacing selection + ftf.test(0, 1, "555", 555.23); + ftf.test(4, 2, "555", 5555.55); + ftf.test(2, 3, "1", 551.55); + ftf.test(3, 2, "6", 55.65); + ftf.test(4, 2, "12", 556.12); + ftf.test(3, 4, "0", 5.5); + ftf.test(0, 3, "111222333444555", 1112223334445.55); + + // test deleting selection + ftf.test(0, 2, DELETE, 12223334445.55); + ftf.test(0, 3, BACKSPACE, 223334445.55); + ftf.test(12, 2, DELETE, 2233344.45); + ftf.test(9, 2, BACKSPACE, 22333.44); + ftf.test(4, 3, DELETE, 223.44); + ftf.test(1, 2, BACKSPACE, 23.44); + ftf.test(3, 3, DELETE, .23); + ftf.test(1, 2, BACKSPACE, .02); + } + + void testCurrencyFormat() { + NumberFormat format = NumberFormat.getCurrencyInstance(Locale.US); + TestFormattedTextField ftf = create(format); + ftf.setValue(56L); + + System.err.println("Testing NumberFormat.getCurrencyInstance(Locale.US)"); + + // test inserting individual characters + ftf.test(1, 0, "1", 16L); + ftf.test(3, 0, "2", 162L); + ftf.test(2, 0, "0", 102L); + + // test inserting several characters at once - e.g. from clipboard + ftf.test(1, 0, "1024", 1024L); + ftf.test(4, 0, "333", 10333L); + ftf.test(7, 0, "77", 1033377L); + ftf.test(5, 0, "99", 1039977L); + ftf.test(7, 0, "00", 1039007L); + + // test inserting strings that contain some formatting + ftf.test(1, 0, "2,2", 229007L); + ftf.test(3, 0, "2,2", 22227L); + ftf.test(4, 0, "2,2", 2222L); + ftf.test(6, 0, "33,33", 22223333L); + + // test delete + ftf.test(1, 0, DELETE, 2223333L); + ftf.test(10, 0, DELETE, 2223333L); + ftf.test(5, 0, DELETE, 222333L); + ftf.test(5, 0, DELETE, 22233L); + + // test backspace + ftf.test(1, 0, BACKSPACE, 22233L); + ftf.test(7, 0, BACKSPACE, 2223L); + ftf.test(4, 0, BACKSPACE, 223L); + ftf.test(2, 0, BACKSPACE, 23L); + + // test replacing selection + ftf.test(1, 1, "555", 5553L); + ftf.test(4, 2, "555", 55555L); + ftf.test(2, 3, "1", 5155L); + ftf.test(3, 2, "6", 565L); + ftf.test(1, 3, "111222333444555", 111222333444555L); + + // test deleting selection + ftf.test(1, 2, DELETE, 1222333444555L); + ftf.test(1, 3, BACKSPACE, 22333444555L); + ftf.test(13, 2, DELETE, 223334445L); + ftf.test(10, 2, BACKSPACE, 2233344L); + ftf.test(4, 4, DELETE, 2244L); + ftf.test(1, 4, BACKSPACE, 4L); + } + + void testIntegerFormat() { + NumberFormat format = NumberFormat.getIntegerInstance(Locale.US); + TestFormattedTextField ftf = create(format); + ftf.setValue(56L); + + System.err.println("Testing NumberFormat.getIntegerInstance(Locale.US)"); + + // test inserting individual characters + ftf.test(0, 0, "1", 16L); + ftf.test(2, 0, "2", 162L); + ftf.test(1, 0, "0", 102L); + + // test inserting several characters at once - e.g. from clipboard + ftf.test(0, 0, "1024", 1024L); + ftf.test(3, 0, "333", 10333L); + ftf.test(6, 0, "77", 1033377L); + ftf.test(4, 0, "99", 1039977L); + ftf.test(6, 0, "00", 1039007L); + + // test inserting strings that contain some formatting + ftf.test(0, 0, "2,2", 229007L); + ftf.test(2, 0, "2,2", 22227L); + ftf.test(3, 0, "2,2", 2222L); + ftf.test(5, 0, "33,33", 22223333L); + + // test delete + ftf.test(0, 0, DELETE, 2223333L); + ftf.test(9, 0, DELETE, 2223333L); + ftf.test(4, 0, DELETE, 222333L); + ftf.test(4, 0, DELETE, 22233L); + + // test backspace + ftf.test(0, 0, BACKSPACE, 22233L); + ftf.test(6, 0, BACKSPACE, 2223L); + ftf.test(2, 0, BACKSPACE, 223L); + ftf.test(2, 0, BACKSPACE, 23L); + + // test replacing selection + ftf.test(0, 1, "555", 5553L); + ftf.test(3, 2, "555", 55555L); + ftf.test(1, 3, "1", 5155L); + ftf.test(2, 2, "6", 565L); + ftf.test(0, 3, "111222333444555", 111222333444555L); + + // test deleting selection + ftf.test(0, 2, DELETE, 1222333444555L); + ftf.test(0, 3, BACKSPACE, 22333444555L); + ftf.test(12, 2, DELETE, 223334445L); + ftf.test(9, 2, BACKSPACE, 2233344L); + ftf.test(3, 4, DELETE, 2244L); + ftf.test(0, 4, BACKSPACE, 4L); + } + + Date date(DateFormat format, String spec) { + try { + return format.parse(spec); + } catch (ParseException e) { + throw new Error("Error in test"); + } + } + + void testDateFormat() { + DateFormat format = new SimpleDateFormat("MM/dd/yyyy", Locale.US); + TestFormattedTextField ftf = create(format); + ftf.setValue(date(format, "12/05/2005")); + + System.err.println("Testing SimpleDateFormat(\"MM/dd/yyyy\", Locale.US)"); + + // test inserting individual characters + ftf.test(0, 0, "0", date(format, "02/05/2005")); + ftf.test(4, 0, "4", date(format, "02/04/2005")); + ftf.test(6, 0, "1", date(format, "02/04/1005")); + ftf.test(9, 0, "9", date(format, "02/04/1009")); + + // test inserting several characters at once - e.g. from clipboard + ftf.test(0, 0, "11", date(format, "11/04/1009")); + ftf.test(3, 0, "23", date(format, "11/23/1009")); + ftf.test(6, 0, "191", date(format, "11/23/1919")); + + // test delete + ftf.test(0, 0, DELETE, date(format, "01/23/1919")); + ftf.test(3, 0, DELETE, date(format, "01/03/1919")); + ftf.test(10, 0, DELETE, date(format, "01/03/1919")); + ftf.test(1, 0, DELETE, date(format, "12/03/1918")); + ftf.test(4, 0, DELETE, date(format, "11/30/1918")); + + // test backspace + ftf.test(0, 0, BACKSPACE, date(format, "11/30/1918")); + ftf.test(1, 0, BACKSPACE, date(format, "01/30/1918")); + ftf.test(4, 0, BACKSPACE, date(format, "12/31/1917")); + ftf.test(10, 0, BACKSPACE, date(format, "12/31/0191")); + ftf.test(3, 0, BACKSPACE, date(format, "01/31/0191")); + ftf.test(5, 0, BACKSPACE, date(format, "01/03/0191")); + + // test replacing selection + ftf.test(0, 1, "1", date(format, "11/03/0191")); + ftf.test(3, 1, "2", date(format, "11/23/0191")); + ftf.test(6, 2, "20", date(format, "11/23/2091")); + + // test deleting selection + ftf.test(0, 1, BACKSPACE, date(format, "01/23/2091")); + ftf.test(3, 1, DELETE, date(format, "01/03/2091")); + ftf.test(6, 2, BACKSPACE, date(format, "01/03/0091")); + ftf.test(8, 1, DELETE, date(format, "01/03/0001")); + } +}