1 7 package javax.swing; 8 9 import java.awt.*; 10 import java.awt.event.*; 11 import java.awt.im.InputContext ; 12 import java.io.*; 13 import java.text.*; 14 import java.util.*; 15 import javax.swing.UIManager ; 16 import javax.swing.event.*; 17 import javax.swing.plaf.UIResource ; 18 import javax.swing.text.*; 19 20 158 public class JFormattedTextField extends JTextField { 159 private static final String uiClassID = "FormattedTextFieldUI"; 160 private static final Action [] defaultActions = 161 { new CommitAction(), new CancelAction() }; 162 163 171 public static final int COMMIT = 0; 172 173 181 public static final int COMMIT_OR_REVERT = 1; 182 183 190 public static final int REVERT = 2; 191 192 198 public static final int PERSIST = 3; 199 200 201 204 private AbstractFormatterFactory factory; 205 208 private AbstractFormatter format; 209 212 private Object value; 213 216 private boolean editValid; 217 220 private int focusLostBehavior; 221 224 private boolean edited; 225 228 private DocumentListener documentListener; 229 232 private Object mask; 233 236 private ActionMap textFormatterActionMap; 237 240 private boolean composedTextExists = false; 241 244 private FocusLostHandler focusLostHandler; 245 246 247 254 public JFormattedTextField() { 255 super(); 256 enableEvents(AWTEvent.FOCUS_EVENT_MASK); 257 setFocusLostBehavior(COMMIT_OR_REVERT); 258 } 259 260 267 public JFormattedTextField(Object value) { 268 this(); 269 setValue(value); 270 } 271 272 279 public JFormattedTextField(java.text.Format format) { 280 this(); 281 setFormatterFactory(getDefaultFormatterFactory(format)); 282 } 283 284 291 public JFormattedTextField(AbstractFormatter formatter) { 292 this(new DefaultFormatterFactory(formatter)); 293 } 294 295 301 public JFormattedTextField(AbstractFormatterFactory factory) { 302 this(); 303 setFormatterFactory(factory); 304 } 305 306 314 public JFormattedTextField(AbstractFormatterFactory factory, 315 Object currentValue) { 316 this(currentValue); 317 setFormatterFactory(factory); 318 } 319 320 345 public void setFocusLostBehavior(int behavior) { 346 if (behavior != COMMIT && behavior != COMMIT_OR_REVERT && 347 behavior != PERSIST && behavior != REVERT) { 348 throw new IllegalArgumentException ("setFocusLostBehavior must be one of: JFormattedTextField.COMMIT, JFormattedTextField.COMMIT_OR_REVERT, JFormattedTextField.PERSIST or JFormattedTextField.REVERT"); 349 } 350 focusLostBehavior = behavior; 351 } 352 353 364 public int getFocusLostBehavior() { 365 return focusLostBehavior; 366 } 367 368 394 public void setFormatterFactory(AbstractFormatterFactory tf) { 395 AbstractFormatterFactory oldFactory = factory; 396 397 factory = tf; 398 firePropertyChange("formatterFactory", oldFactory, tf); 399 setValue(getValue(), true, false); 400 } 401 402 409 public AbstractFormatterFactory getFormatterFactory() { 410 return factory; 411 } 412 413 434 protected void setFormatter(AbstractFormatter format) { 435 AbstractFormatter oldFormat = this.format; 436 437 if (oldFormat != null) { 438 oldFormat.uninstall(); 439 } 440 setEditValid(true); 441 this.format = format; 442 if (format != null) { 443 format.install(this); 444 } 445 setEdited(false); 446 firePropertyChange("textFormatter", oldFormat, format); 447 } 448 449 455 public AbstractFormatter getFormatter() { 456 return format; 457 } 458 459 476 public void setValue(Object value) { 477 if (value != null && getFormatterFactory() == null) { 478 setFormatterFactory(getDefaultFormatterFactory(value)); 479 } 480 setValue(value, true, true); 481 } 482 483 491 public Object getValue() { 492 return value; 493 } 494 495 504 public void commitEdit() throws ParseException { 505 AbstractFormatter format = getFormatter(); 506 507 if (format != null) { 508 setValue(format.stringToValue(getText()), false, true); 509 } 510 } 511 512 530 private void setEditValid(boolean isValid) { 531 if (isValid != editValid) { 532 editValid = isValid; 533 firePropertyChange("editValid", Boolean.valueOf(!isValid), 534 Boolean.valueOf(isValid)); 535 } 536 } 537 538 545 public boolean isEditValid() { 546 return editValid; 547 } 548 549 554 protected void invalidEdit() { 555 UIManager.getLookAndFeel().provideErrorFeedback(JFormattedTextField.this); 556 } 557 558 566 protected void processInputMethodEvent(InputMethodEvent e) { 567 AttributedCharacterIterator text = e.getText(); 568 int commitCount = e.getCommittedCharacterCount(); 569 570 if (text != null) { 572 int begin = text.getBeginIndex(); 573 int end = text.getEndIndex(); 574 composedTextExists = ((end - begin) > commitCount); 575 } else { 576 composedTextExists = false; 577 } 578 579 super.processInputMethodEvent(e); 580 } 581 582 590 protected void processFocusEvent(FocusEvent e) { 591 super.processFocusEvent(e); 592 593 if (e.isTemporary()) { 595 return; 596 } 597 598 if (isEdited() && e.getID() == FocusEvent.FOCUS_LOST) { 599 InputContext ic = getInputContext(); 600 if (focusLostHandler == null) { 601 focusLostHandler = new FocusLostHandler(); 602 } 603 604 if ((ic != null) && composedTextExists) { 606 ic.endComposition(); 607 EventQueue.invokeLater(focusLostHandler); 608 } else { 609 focusLostHandler.run(); 610 } 611 } 612 else if (!isEdited()) { 613 setValue(getValue(), true, true); 615 } 616 } 617 618 621 private class FocusLostHandler implements Runnable , Serializable { 622 public void run() { 623 int fb = JFormattedTextField.this.getFocusLostBehavior(); 624 if (fb == JFormattedTextField.COMMIT || 625 fb == JFormattedTextField.COMMIT_OR_REVERT) { 626 try { 627 JFormattedTextField.this.commitEdit(); 628 JFormattedTextField.this.setValue( 630 JFormattedTextField.this.getValue(), true, true); 631 } catch (ParseException pe) { 632 if (fb == JFormattedTextField.this.COMMIT_OR_REVERT) { 633 JFormattedTextField.this.setValue( 634 JFormattedTextField.this.getValue(), true, true); 635 } 636 } 637 } 638 else if (fb == JFormattedTextField.REVERT) { 639 JFormattedTextField.this.setValue( 640 JFormattedTextField.this.getValue(), true, true); 641 } 642 } 643 } 644 645 654 public Action [] getActions() { 655 return TextAction.augmentList(super.getActions(), defaultActions); 656 } 657 658 664 public String getUIClassID() { 665 return uiClassID; 666 } 667 668 681 public void setDocument(Document doc) { 682 if (documentListener != null && getDocument() != null) { 683 getDocument().removeDocumentListener(documentListener); 684 } 685 super.setDocument(doc); 686 if (documentListener == null) { 687 documentListener = new DocumentHandler(); 688 } 689 doc.addDocumentListener(documentListener); 690 } 691 692 698 private void writeObject(ObjectOutputStream s) throws IOException { 699 s.defaultWriteObject(); 700 if (getUIClassID().equals(uiClassID)) { 701 byte count = JComponent.getWriteObjCounter(this); 702 JComponent.setWriteObjCounter(this, --count); 703 if (count == 0 && ui != null) { 704 ui.installUI(this); 705 } 706 } 707 } 708 709 713 private void setFormatterActions(Action [] actions) { 714 if (actions == null) { 715 if (textFormatterActionMap != null) { 716 textFormatterActionMap.clear(); 717 } 718 } 719 else { 720 if (textFormatterActionMap == null) { 721 ActionMap map = getActionMap(); 722 723 textFormatterActionMap = new ActionMap (); 724 while (map != null) { 725 ActionMap parent = map.getParent(); 726 727 if (parent instanceof UIResource || parent == null) { 728 map.setParent(textFormatterActionMap); 729 textFormatterActionMap.setParent(parent); 730 break; 731 } 732 map = parent; 733 } 734 } 735 for (int counter = actions.length - 1; counter >= 0; 736 counter--) { 737 Object key = actions[counter].getValue(Action.NAME); 738 739 if (key != null) { 740 textFormatterActionMap.put(key, actions[counter]); 741 } 742 } 743 } 744 } 745 746 752 private void setValue(Object value, boolean createFormat, boolean firePC) { 753 Object oldValue = this.value; 754 755 this.value = value; 756 757 if (createFormat) { 758 AbstractFormatterFactory factory = getFormatterFactory(); 759 AbstractFormatter atf; 760 761 if (factory != null) { 762 atf = factory.getFormatter(this); 763 } 764 else { 765 atf = null; 766 } 767 setFormatter(atf); 768 } 769 else { 770 setEditValid(true); 772 } 773 774 setEdited(false); 775 776 if (firePC) { 777 firePropertyChange("value", oldValue, value); 778 } 779 } 780 781 784 private void setEdited(boolean edited) { 785 this.edited = edited; 786 } 787 788 791 private boolean isEdited() { 792 return edited; 793 } 794 795 799 private AbstractFormatterFactory getDefaultFormatterFactory(Object type) { 800 if (type instanceof DateFormat) { 801 return new DefaultFormatterFactory(new DateFormatter 802 ((DateFormat)type)); 803 } 804 if (type instanceof NumberFormat) { 805 return new DefaultFormatterFactory(new NumberFormatter( 806 (NumberFormat)type)); 807 } 808 if (type instanceof Format) { 809 return new DefaultFormatterFactory(new InternationalFormatter( 810 (Format)type)); 811 } 812 if (type instanceof Date) { 813 return new DefaultFormatterFactory(new DateFormatter()); 814 } 815 if (type instanceof Number ) { 816 AbstractFormatter displayFormatter = new NumberFormatter(); 817 ((NumberFormatter)displayFormatter).setValueClass(type.getClass()); 818 AbstractFormatter editFormatter = new NumberFormatter( 819 new DecimalFormat("#.#")); 820 ((NumberFormatter)editFormatter).setValueClass(type.getClass()); 821 822 return new DefaultFormatterFactory(displayFormatter, 823 displayFormatter,editFormatter); 824 } 825 return new DefaultFormatterFactory(new DefaultFormatter()); 826 } 827 828 829 840 public static abstract class AbstractFormatterFactory { 841 850 public abstract AbstractFormatter getFormatter(JFormattedTextField tf); 851 } 852 853 854 882 public static abstract class AbstractFormatter implements Serializable { 883 private JFormattedTextField ftf; 884 885 918 public void install(JFormattedTextField ftf) { 919 if (this.ftf != null) { 920 uninstall(); 921 } 922 this.ftf = ftf; 923 if (ftf != null) { 924 try { 925 ftf.setText(valueToString(ftf.getValue())); 926 } catch (ParseException pe) { 927 ftf.setText(""); 928 setEditValid(false); 929 } 930 installDocumentFilter(getDocumentFilter()); 931 ftf.setNavigationFilter(getNavigationFilter()); 932 ftf.setFormatterActions(getActions()); 933 } 934 } 935 936 943 public void uninstall() { 944 if (this.ftf != null) { 945 installDocumentFilter(null); 946 this.ftf.setNavigationFilter(null); 947 this.ftf.setFormatterActions(null); 948 } 949 } 950 951 959 public abstract Object stringToValue(String text) throws 960 ParseException; 961 962 969 public abstract String valueToString(Object value) throws 970 ParseException; 971 972 978 protected JFormattedTextField getFormattedTextField() { 979 return ftf; 980 } 981 982 986 protected void invalidEdit() { 987 JFormattedTextField ftf = getFormattedTextField(); 988 989 if (ftf != null) { 990 ftf.invalidEdit(); 991 } 992 } 993 994 1002 protected void setEditValid(boolean valid) { 1003 JFormattedTextField ftf = getFormattedTextField(); 1004 1005 if (ftf != null) { 1006 ftf.setEditValid(valid); 1007 } 1008 } 1009 1010 1017 protected Action [] getActions() { 1018 return null; 1019 } 1020 1021 1029 protected DocumentFilter getDocumentFilter() { 1030 return null; 1031 } 1032 1033 1041 protected NavigationFilter getNavigationFilter() { 1042 return null; 1043 } 1044 1045 1051 protected Object clone() throws CloneNotSupportedException { 1052 AbstractFormatter formatter = (AbstractFormatter)super.clone(); 1053 1054 formatter.ftf = null; 1055 return formatter; 1056 } 1057 1058 1064 private void installDocumentFilter(DocumentFilter filter) { 1065 JFormattedTextField ftf = getFormattedTextField(); 1066 1067 if (ftf != null) { 1068 Document doc = ftf.getDocument(); 1069 1070 if (doc instanceof AbstractDocument) { 1071 ((AbstractDocument)doc).setDocumentFilter(filter); 1072 } 1073 doc.putProperty(DocumentFilter.class, null); 1074 } 1075 } 1076 } 1077 1078 1079 1085 static class CommitAction extends JTextField.NotifyAction { 1086 public void actionPerformed(ActionEvent e) { 1087 JTextComponent target = getFocusedComponent(); 1088 1089 if (target instanceof JFormattedTextField ) { 1090 try { 1092 ((JFormattedTextField )target).commitEdit(); 1093 } catch (ParseException pe) { 1094 ((JFormattedTextField )target).invalidEdit(); 1095 return; 1097 } 1098 } 1099 super.actionPerformed(e); 1101 } 1102 1103 public boolean isEnabled() { 1104 JTextComponent target = getFocusedComponent(); 1105 if (target instanceof JFormattedTextField ) { 1106 JFormattedTextField ftf = (JFormattedTextField )target; 1107 if (!ftf.isEdited()) { 1108 return false; 1109 } 1110 return true; 1111 } 1112 return super.isEnabled(); 1113 } 1114 } 1115 1116 1117 1123 private static class CancelAction extends TextAction { 1124 public CancelAction() { 1125 super("reset-field-edit"); 1126 } 1127 1128 public void actionPerformed(ActionEvent e) { 1129 JTextComponent target = getFocusedComponent(); 1130 1131 if (target instanceof JFormattedTextField ) { 1132 JFormattedTextField ftf = (JFormattedTextField )target; 1133 ftf.setValue(ftf.getValue()); 1134 } 1135 } 1136 1137 public boolean isEnabled() { 1138 JTextComponent target = getFocusedComponent(); 1139 if (target instanceof JFormattedTextField ) { 1140 JFormattedTextField ftf = (JFormattedTextField )target; 1141 if (!ftf.isEdited()) { 1142 return false; 1143 } 1144 return true; 1145 } 1146 return super.isEnabled(); 1147 } 1148 } 1149 1150 1151 1154 private class DocumentHandler implements DocumentListener, Serializable { 1155 public void insertUpdate(DocumentEvent e) { 1156 setEdited(true); 1157 } 1158 public void removeUpdate(DocumentEvent e) { 1159 setEdited(true); 1160 } 1161 public void changedUpdate(DocumentEvent e) {} 1162 } 1163} 1164
| Popular Tags
|