jdk/src/share/classes/javax/swing/text/InternationalFormatter.java
author malenkov
Fri, 04 Apr 2014 20:18:53 +0400
changeset 24158 6afb40c4e9f8
parent 22574 7f8ce0c8c20a
child 25193 187a455af8f8
permissions -rw-r--r--
8039137: KSS: JTextComponent.isProcessInputMethodEventOverridden Reviewed-by: alexsch, serb
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
22574
7f8ce0c8c20a 8032627: Add @SuppressWarnings("serial") to appropriate javax.swing classes
darcy
parents: 21278
diff changeset
     2
 * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1639
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1639
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1639
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1639
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 1639
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
package javax.swing.text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
import java.awt.event.ActionEvent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.text.*;
1287
a04aca99c77a 6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents: 2
diff changeset
    30
import java.text.AttributedCharacterIterator.Attribute;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.util.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import javax.swing.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * <code>InternationalFormatter</code> extends <code>DefaultFormatter</code>,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * using an instance of <code>java.text.Format</code> to handle the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 * conversion to a String, and the conversion from a String.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * If <code>getAllowsInvalid()</code> is false, this will ask the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * <code>Format</code> to format the current text on every edit.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * You can specify a minimum and maximum value by way of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * <code>setMinimum</code> and <code>setMaximum</code> methods. In order
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * for this to work the values returned from <code>stringToValue</code> must be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * comparable to the min/max values by way of the <code>Comparable</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * interface.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * Be careful how you configure the <code>Format</code> and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * <code>InternationalFormatter</code>, as it is possible to create a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * situation where certain values can not be input. Consider the date
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * format 'M/d/yy', an <code>InternationalFormatter</code> that is always
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * valid (<code>setAllowsInvalid(false)</code>), is in overwrite mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * (<code>setOverwriteMode(true)</code>) and the date 7/1/99. In this
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * case the user will not be able to enter a two digit month or day of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * month. To avoid this, the format should be 'MM/dd/yy'.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * If <code>InternationalFormatter</code> is configured to only allow valid
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * values (<code>setAllowsInvalid(false)</code>), every valid edit will result
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * in the text of the <code>JFormattedTextField</code> being completely reset
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * from the <code>Format</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * The cursor position will also be adjusted as literal characters are
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * added/removed from the resulting String.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * <code>InternationalFormatter</code>'s behavior of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * <code>stringToValue</code> is  slightly different than that of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * <code>DefaultTextFormatter</code>, it does the following:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * <ol>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *   <li><code>parseObject</code> is invoked on the <code>Format</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 *       specified by <code>setFormat</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 *   <li>If a Class has been set for the values (<code>setValueClass</code>),
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 *       supers implementation is invoked to convert the value returned
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 *       from <code>parseObject</code> to the appropriate class.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 *   <li>If a <code>ParseException</code> has not been thrown, and the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 *       is outside the min/max a <code>ParseException</code> is thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 *   <li>The value is returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * </ol>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * <code>InternationalFormatter</code> implements <code>stringToValue</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * in this manner so that you can specify an alternate Class than
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * <code>Format</code> may return.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * <strong>Warning:</strong>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * Serialized objects of this class will not be compatible with
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 * future Swing releases. The current serialization support is
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * appropriate for short term storage or RMI between applications running
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * the same version of Swing.  As of 1.4, support for long term storage
20458
f2423fb3fd19 8025840: Fix all the doclint warnings about trademark
cl
parents: 7668
diff changeset
    86
 * of all JavaBeans&trade;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 * has been added to the <code>java.beans</code> package.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 * Please see {@link java.beans.XMLEncoder}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * @see java.text.Format
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 * @see java.lang.Comparable
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 * @since 1.4
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 */
22574
7f8ce0c8c20a 8032627: Add @SuppressWarnings("serial") to appropriate javax.swing classes
darcy
parents: 21278
diff changeset
    95
@SuppressWarnings("serial") // Same-version serialization only
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
public class InternationalFormatter extends DefaultFormatter {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * Used by <code>getFields</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    private static final Format.Field[] EMPTY_FIELD_ARRAY =new Format.Field[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * Object used to handle the conversion.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    private Format format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
     * Can be used to impose a maximum value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    private Comparable max;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     * Can be used to impose a minimum value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    private Comparable min;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     * <code>InternationalFormatter</code>'s behavior is dicatated by a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * <code>AttributedCharacterIterator</code> that is obtained from
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     * the <code>Format</code>. On every edit, assuming
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
     * allows invalid is false, the <code>Format</code> instance is invoked
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
     * with <code>formatToCharacterIterator</code>. A <code>BitSet</code> is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
     * also kept upto date with the non-literal characters, that is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
     * for every index in the <code>AttributedCharacterIterator</code> an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * entry in the bit set is updated based on the return value from
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     * <code>isLiteral(Map)</code>. <code>isLiteral(int)</code> then uses
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     * this cached information.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     * If allowsInvalid is false, every edit results in resetting the complete
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     * text of the JTextComponent.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     * InternationalFormatterFilter can also provide two actions suitable for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     * incrementing and decrementing. To enable this a subclass must
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     * override <code>getSupportsIncrement</code> to return true, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
     * override <code>adjustValue</code> to handle the changing of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
     * value. If you want to support changing the value outside of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
     * the valid FieldPositions, you will need to override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     * <code>canIncrement</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
     * A bit is set for every index identified in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
     * AttributedCharacterIterator that is not considered decoration.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
     * This should only be used if validMask is true.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    private transient BitSet literalMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
     * Used to iterate over characters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    private transient AttributedCharacterIterator iterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
     * True if the Format was able to convert the value to a String and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
     * back.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
    private transient boolean validMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
     * Current value being displayed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    private transient String string;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
     * If true, DocumentFilter methods are unconditionally allowed,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
     * and no checking is done on their values. This is used when
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
     * incrementing/decrementing via the actions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    private transient boolean ignoreDocumentMutate;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
     * Creates an <code>InternationalFormatter</code> with no
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
     * <code>Format</code> specified.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
    public InternationalFormatter() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        setOverwriteMode(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
     * Creates an <code>InternationalFormatter</code> with the specified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
     * <code>Format</code> instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
     * @param format Format instance used for converting from/to Strings
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
    public InternationalFormatter(Format format) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
        this();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
        setFormat(format);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
     * Sets the format that dictates the legal values that can be edited
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
     * and displayed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
     * @param format <code>Format</code> instance used for converting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
     * from/to Strings
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
    public void setFormat(Format format) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        this.format = format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
     * Returns the format that dictates the legal values that can be edited
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
     * and displayed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
     * @return Format instance used for converting from/to Strings
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    public Format getFormat() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        return format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
     * Sets the minimum permissible value. If the <code>valueClass</code> has
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
     * not been specified, and <code>minimum</code> is non null, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
     * <code>valueClass</code> will be set to that of the class of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
     * <code>minimum</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
     * @param minimum Minimum legal value that can be input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     * @see #setValueClass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
    public void setMinimum(Comparable minimum) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        if (getValueClass() == null && minimum != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            setValueClass(minimum.getClass());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        min = minimum;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
     * Returns the minimum permissible value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
     * @return Minimum legal value that can be input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    public Comparable getMinimum() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        return min;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     * Sets the maximum permissible value. If the <code>valueClass</code> has
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     * not been specified, and <code>max</code> is non null, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     * <code>valueClass</code> will be set to that of the class of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     * <code>max</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
     * @param max Maximum legal value that can be input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
     * @see #setValueClass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
    public void setMaximum(Comparable max) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        if (getValueClass() == null && max != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
            setValueClass(max.getClass());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        this.max = max;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     * Returns the maximum permissible value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
     * @return Maximum legal value that can be input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    public Comparable getMaximum() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        return max;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
     * Installs the <code>DefaultFormatter</code> onto a particular
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
     * <code>JFormattedTextField</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
     * This will invoke <code>valueToString</code> to convert the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
     * current value from the <code>JFormattedTextField</code> to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
     * a String. This will then install the <code>Action</code>s from
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
     * <code>getActions</code>, the <code>DocumentFilter</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
     * returned from <code>getDocumentFilter</code> and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
     * <code>NavigationFilter</code> returned from
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
     * <code>getNavigationFilter</code> onto the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
     * <code>JFormattedTextField</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
     * Subclasses will typically only need to override this if they
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
     * wish to install additional listeners on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
     * <code>JFormattedTextField</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     * If there is a <code>ParseException</code> in converting the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
     * current value to a String, this will set the text to an empty
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
     * String, and mark the <code>JFormattedTextField</code> as being
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
     * in an invalid state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
     * <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
     * While this is a public method, this is typically only useful
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     * for subclassers of <code>JFormattedTextField</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     * <code>JFormattedTextField</code> will invoke this method at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
     * the appropriate times when the value changes, or its internal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
     * state changes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     * @param ftf JFormattedTextField to format for, may be null indicating
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
     *            uninstall from current JFormattedTextField.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
    public void install(JFormattedTextField ftf) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        super.install(ftf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
        updateMaskIfNecessary();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        // invoked again as the mask should now be valid.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        positionCursorAtInitialLocation();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     * Returns a String representation of the Object <code>value</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
     * This invokes <code>format</code> on the current <code>Format</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     * @throws ParseException if there is an error in the conversion
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     * @param value Value to convert
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
     * @return String representation of value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
    public String valueToString(Object value) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        if (value == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            return "";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        Format f = getFormat();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        if (f == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
            return value.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        return f.format(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
     * Returns the <code>Object</code> representation of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
     * <code>String</code> <code>text</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
     * @param text <code>String</code> to convert
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
     * @return <code>Object</code> representation of text
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
     * @throws ParseException if there is an error in the conversion
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
    public Object stringToValue(String text) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        Object value = stringToValue(text, getFormat());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
        // Convert to the value class if the Value returned from the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        // Format does not match.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        if (value != null && getValueClass() != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                             !getValueClass().isInstance(value)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
            value = super.stringToValue(value.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
            if (!isValidValue(value, true)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
                throw new ParseException("Value not within min/max range", 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        } catch (ClassCastException cce) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
            throw new ParseException("Class cast exception comparing values: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                                     + cce, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        return value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
     * Returns the <code>Format.Field</code> constants associated with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
     * the text at <code>offset</code>. If <code>offset</code> is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
     * a valid location into the current text, this will return an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
     * empty array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     * @param offset offset into text to be examined
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
     * @return Format.Field constants associated with the text at the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
     *         given position.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
    public Format.Field[] getFields(int offset) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        if (getAllowsInvalid()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
            // This will work if the currently edited value is valid.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
            updateMask();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
1287
a04aca99c77a 6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents: 2
diff changeset
   356
        Map<Attribute, Object> attrs = getAttributes(offset);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
        if (attrs != null && attrs.size() > 0) {
1287
a04aca99c77a 6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents: 2
diff changeset
   359
            ArrayList<Attribute> al = new ArrayList<Attribute>();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            al.addAll(attrs.keySet());
1287
a04aca99c77a 6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents: 2
diff changeset
   362
            return al.toArray(EMPTY_FIELD_ARRAY);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
        return EMPTY_FIELD_ARRAY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
     * Creates a copy of the DefaultFormatter.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
     * @return copy of the DefaultFormatter
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    public Object clone() throws CloneNotSupportedException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        InternationalFormatter formatter = (InternationalFormatter)super.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
                                           clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        formatter.literalMask = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        formatter.iterator = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        formatter.validMask = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        formatter.string = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        return formatter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
     * If <code>getSupportsIncrement</code> returns true, this returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
     * two Actions suitable for incrementing/decrementing the value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
    protected Action[] getActions() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
        if (getSupportsIncrement()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
            return new Action[] { new IncrementAction("increment", 1),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                                  new IncrementAction("decrement", -1) };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
     * Invokes <code>parseObject</code> on <code>f</code>, returning
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
     * its value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
    Object stringToValue(String text, Format f) throws ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        if (f == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
            return text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
        return f.parseObject(text);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
     * Returns true if <code>value</code> is between the min/max.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
     * @param wantsCCE If false, and a ClassCastException is thrown in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
     *                 comparing the values, the exception is consumed and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
     *                 false is returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
    boolean isValidValue(Object value, boolean wantsCCE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
        Comparable min = getMinimum();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
            if (min != null && min.compareTo(value) > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        } catch (ClassCastException cce) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
            if (wantsCCE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
                throw cce;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
        Comparable max = getMaximum();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
            if (max != null && max.compareTo(value) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
        } catch (ClassCastException cce) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
            if (wantsCCE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                throw cce;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
     * Returns a Set of the attribute identifiers at <code>index</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
     */
1287
a04aca99c77a 6722802: Code improvement and warnings removing from the javax.swing.text package
rupashka
parents: 2
diff changeset
   444
    Map<Attribute, Object> getAttributes(int index) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        if (isValidMask()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
            AttributedCharacterIterator iterator = getIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
            if (index >= 0 && index <= iterator.getEndIndex()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                iterator.setIndex(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                return iterator.getAttributes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
     * Returns the start of the first run that contains the attribute
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
     * <code>id</code>. This will return <code>-1</code> if the attribute
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
     * can not be found.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
    int getAttributeStart(AttributedCharacterIterator.Attribute id) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
        if (isValidMask()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            AttributedCharacterIterator iterator = getIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
            iterator.first();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
            while (iterator.current() != CharacterIterator.DONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
                if (iterator.getAttribute(id) != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                    return iterator.getIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                iterator.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
     * Returns the <code>AttributedCharacterIterator</code> used to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
     * format the last value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    AttributedCharacterIterator getIterator() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        return iterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
     * Updates the AttributedCharacterIterator and bitset, if necessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    void updateMaskIfNecessary() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        if (!getAllowsInvalid() && (getFormat() != null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
            if (!isValidMask()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                updateMask();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
            else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
                String newString = getFormattedTextField().getText();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                if (!newString.equals(string)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                    updateMask();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
     * Updates the AttributedCharacterIterator by invoking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
     * <code>formatToCharacterIterator</code> on the <code>Format</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
     * If this is successful,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
     * <code>updateMask(AttributedCharacterIterator)</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
     * is then invoked to update the internal bitmask.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
    void updateMask() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        if (getFormat() != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
            Document doc = getFormattedTextField().getDocument();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            validMask = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            if (doc != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
                    string = doc.getText(0, doc.getLength());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
                } catch (BadLocationException ble) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
                    string = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
                if (string != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
                    try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
                        Object value = stringToValue(string);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                        AttributedCharacterIterator iterator = getFormat().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                                  formatToCharacterIterator(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
                        updateMask(iterator);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
                    catch (ParseException pe) {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
                    catch (IllegalArgumentException iae) {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
                    catch (NullPointerException npe) {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
     * Returns the number of literal characters before <code>index</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
    int getLiteralCountTo(int index) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
        int lCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        for (int counter = 0; counter < index; counter++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            if (isLiteral(counter)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
                lCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        return lCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
     * Returns true if the character at index is a literal, that is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
     * not editable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
    boolean isLiteral(int index) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        if (isValidMask() && index < string.length()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
            return literalMask.get(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
     * Returns the literal character at index.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
    char getLiteral(int index) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        if (isValidMask() && string != null && index < string.length()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
            return string.charAt(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        return (char)0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
    /**
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 20458
diff changeset
   573
     * Returns true if the character at offset is navigable too. This
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
     * is implemented in terms of <code>isLiteral</code>, subclasses
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
     * may wish to provide different behavior.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
    boolean isNavigatable(int offset) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        return !isLiteral(offset);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
     * Overriden to update the mask after invoking supers implementation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
    void updateValue(Object value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
        super.updateValue(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
        updateMaskIfNecessary();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
     * Overriden to unconditionally allow the replace if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
     * ignoreDocumentMutate is true.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
    void replace(DocumentFilter.FilterBypass fb, int offset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
                     int length, String text,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
                     AttributeSet attrs) throws BadLocationException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
        if (ignoreDocumentMutate) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
            fb.replace(offset, length, text, attrs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        super.replace(fb, offset, length, text, attrs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
     * Returns the index of the next non-literal character starting at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
     * index. If index is not a literal, it will be returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
     * @param direction Amount to increment looking for non-literal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
    private int getNextNonliteralIndex(int index, int direction) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
        int max = getFormattedTextField().getDocument().getLength();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
        while (index >= 0 && index < max) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            if (isLiteral(index)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                index += direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
                return index;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
        return (direction == -1) ? 0 : max;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
     * Overriden in an attempt to honor the literals.
6102
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   625
     * <p>If we do not allow invalid values and are in overwrite mode, this
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   626
     * {@code rh.length} is corrected as to preserve trailing literals.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
     * If not in overwrite mode, and there is text to insert it is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
     * inserted at the next non literal index going forward.  If there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
     * is only text to remove, it is removed from the next non literal
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
     * index going backward.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
    boolean canReplace(ReplaceHolder rh) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
        if (!getAllowsInvalid()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
            String text = rh.text;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
            int tl = (text != null) ? text.length() : 0;
6102
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   636
            JTextComponent c = getFormattedTextField();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
6102
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   638
            if (tl == 0 && rh.length == 1 && c.getSelectionStart() != rh.offset) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
                // Backspace, adjust to actually delete next non-literal.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
                rh.offset = getNextNonliteralIndex(rh.offset, -1);
6102
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   641
            } else if (getOverwriteMode()) {
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   642
                int pos = rh.offset;
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   643
                int textPos = pos;
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   644
                boolean overflown = false;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
6102
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   646
                for (int i = 0; i < rh.length; i++) {
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   647
                    while (isLiteral(pos)) pos++;
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   648
                    if (pos >= string.length()) {
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   649
                        pos = textPos;
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   650
                        overflown = true;
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   651
                        break;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
                    }
6102
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   653
                    textPos = ++pos;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
                }
6102
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   655
                if (overflown || c.getSelectedText() == null) {
06e0e43b3f09 6462562: InternationalFormatter inserts text incorrectly
peterz
parents: 5506
diff changeset
   656
                    rh.length = pos - rh.offset;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
            else if (tl > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
                // insert (or insert and remove)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
                rh.offset = getNextNonliteralIndex(rh.offset, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
            else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
                // remove only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                rh.offset = getNextNonliteralIndex(rh.offset, -1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            ((ExtendedReplaceHolder)rh).endOffset = rh.offset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
            ((ExtendedReplaceHolder)rh).endTextLength = (rh.text != null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
                                                    rh.text.length() : 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
            ((ExtendedReplaceHolder)rh).endOffset = rh.offset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
            ((ExtendedReplaceHolder)rh).endTextLength = (rh.text != null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                                                    rh.text.length() : 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        boolean can = super.canReplace(rh);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
        if (can && !getAllowsInvalid()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
            ((ExtendedReplaceHolder)rh).resetFromValue(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
        return can;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
     * When in !allowsInvalid mode the text is reset on every edit, thus
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
     * supers implementation will position the cursor at the wrong position.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
     * As such, this invokes supers implementation and then invokes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
     * <code>repositionCursor</code> to correctly reset the cursor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
    boolean replace(ReplaceHolder rh) throws BadLocationException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
        int start = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
        int direction = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
        int literalCount = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        if (rh.length > 0 && (rh.text == null || rh.text.length() == 0) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
               (getFormattedTextField().getSelectionStart() != rh.offset ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
                   rh.length > 1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
            direction = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
        if (!getAllowsInvalid()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
            if ((rh.text == null || rh.text.length() == 0) && rh.length > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                // remove
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                start = getFormattedTextField().getSelectionStart();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
            else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                start = rh.offset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            literalCount = getLiteralCountTo(start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
        if (super.replace(rh)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
            if (start != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                int end = ((ExtendedReplaceHolder)rh).endOffset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                end += ((ExtendedReplaceHolder)rh).endTextLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                repositionCursor(literalCount, end, direction);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
            else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                start = ((ExtendedReplaceHolder)rh).endOffset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                if (direction == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                    start += ((ExtendedReplaceHolder)rh).endTextLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                repositionCursor(start, direction);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
     * Repositions the cursor. <code>startLiteralCount</code> gives
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
     * the number of literals to the start of the deleted range, end
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
     * gives the ending location to adjust from, direction gives
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
     * the direction relative to <code>end</code> to position the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
     * cursor from.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
    private void repositionCursor(int startLiteralCount, int end,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
                                  int direction)  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
        int endLiteralCount = getLiteralCountTo(end);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
        if (endLiteralCount != end) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
            end -= startLiteralCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
            for (int counter = 0; counter < end; counter++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
                if (isLiteral(counter)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
                    end++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
        repositionCursor(end, 1 /*direction*/);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
     * Returns the character from the mask that has been buffered
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
     * at <code>index</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
    char getBufferedChar(int index) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
        if (isValidMask()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
            if (string != null && index < string.length()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
                return string.charAt(index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
        return (char)0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
     * Returns true if the current mask is valid.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
    boolean isValidMask() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
        return validMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
     * Returns true if <code>attributes</code> is null or empty.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
    boolean isLiteral(Map attributes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
        return ((attributes == null) || attributes.size() == 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
     * Updates the interal bitset from <code>iterator</code>. This will
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
     * set <code>validMask</code> to true if <code>iterator</code> is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
     * non-null.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
    private void updateMask(AttributedCharacterIterator iterator) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
        if (iterator != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
            validMask = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            this.iterator = iterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
            // Update the literal mask
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
            if (literalMask == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
                literalMask = new BitSet();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
            else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
                for (int counter = literalMask.length() - 1; counter >= 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
                     counter--) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
                    literalMask.clear(counter);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
            iterator.first();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
            while (iterator.current() != CharacterIterator.DONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
                Map attributes = iterator.getAttributes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
                boolean set = isLiteral(attributes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
                int start = iterator.getIndex();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
                int end = iterator.getRunLimit();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
                while (start < end) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
                    if (set) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
                        literalMask.set(start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
                    else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
                        literalMask.clear(start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
                    start++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
                iterator.setIndex(start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
     * Returns true if <code>field</code> is non-null.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
     * Subclasses that wish to allow incrementing to happen outside of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
     * the known fields will need to override this.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
    boolean canIncrement(Object field, int cursorPosition) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
        return (field != null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
     * Selects the fields identified by <code>attributes</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
    void selectField(Object f, int count) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
        AttributedCharacterIterator iterator = getIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
        if (iterator != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
                        (f instanceof AttributedCharacterIterator.Attribute)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
            AttributedCharacterIterator.Attribute field =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
                                   (AttributedCharacterIterator.Attribute)f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
            iterator.first();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
            while (iterator.current() != CharacterIterator.DONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
                while (iterator.getAttribute(field) == null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
                       iterator.next() != CharacterIterator.DONE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
                if (iterator.current() != CharacterIterator.DONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
                    int limit = iterator.getRunLimit(field);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
                    if (--count <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
                        getFormattedTextField().select(iterator.getIndex(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
                                                       limit);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
                    iterator.setIndex(limit);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
                    iterator.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
     * Returns the field that will be adjusted by adjustValue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
    Object getAdjustField(int start, Map attributes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
    /**
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 20458
diff changeset
   866
     * Returns the number of occurrences of <code>f</code> before
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
     * the location <code>start</code> in the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
     * <code>AttributedCharacterIterator</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
    private int getFieldTypeCountTo(Object f, int start) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
        AttributedCharacterIterator iterator = getIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
        int count = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
        if (iterator != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
                    (f instanceof AttributedCharacterIterator.Attribute)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
            AttributedCharacterIterator.Attribute field =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
                                   (AttributedCharacterIterator.Attribute)f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
            iterator.first();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
            while (iterator.getIndex() < start) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
                while (iterator.getAttribute(field) == null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
                       iterator.next() != CharacterIterator.DONE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
                if (iterator.current() != CharacterIterator.DONE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
                    iterator.setIndex(iterator.getRunLimit(field));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
                    iterator.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
                    count++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
                else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
        return count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
     * Subclasses supporting incrementing must override this to handle
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
     * the actual incrementing. <code>value</code> is the current value,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
     * <code>attributes</code> gives the field the cursor is in (may be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
     * null depending upon <code>canIncrement</code>) and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
     * <code>direction</code> is the amount to increment by.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
    Object adjustValue(Object value, Map attributes, Object field,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
                           int direction) throws
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
                      BadLocationException, ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
     * Returns false, indicating InternationalFormatter does not allow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
     * incrementing of the value. Subclasses that wish to support
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
     * incrementing/decrementing the value should override this and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
     * return true. Subclasses should also override
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
     * <code>adjustValue</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
    boolean getSupportsIncrement() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
     * Resets the value of the JFormattedTextField to be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
     * <code>value</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
    void resetValue(Object value) throws BadLocationException, ParseException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
        Document doc = getFormattedTextField().getDocument();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
        String string = valueToString(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
            ignoreDocumentMutate = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
            doc.remove(0, doc.getLength());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
            doc.insertString(0, string, null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
            ignoreDocumentMutate = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
        updateValue(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
     * Subclassed to update the internal representation of the mask after
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
     * the default read operation has completed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
    private void readObject(ObjectInputStream s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
        throws IOException, ClassNotFoundException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
        s.defaultReadObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
        updateMaskIfNecessary();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
     * Overriden to return an instance of <code>ExtendedReplaceHolder</code>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
    ReplaceHolder getReplaceHolder(DocumentFilter.FilterBypass fb, int offset,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
                                   int length, String text,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
                                   AttributeSet attrs) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
        if (replaceHolder == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
            replaceHolder = new ExtendedReplaceHolder();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
        return super.getReplaceHolder(fb, offset, length, text, attrs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
     * As InternationalFormatter replaces the complete text on every edit,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
     * ExtendedReplaceHolder keeps track of the offset and length passed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
     * into canReplace.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
    static class ExtendedReplaceHolder extends ReplaceHolder {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
        /** Offset of the insert/remove. This may differ from offset in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
         * that if !allowsInvalid the text is replaced on every edit. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
        int endOffset;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
        /** Length of the text. This may differ from text.length in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
         * that if !allowsInvalid the text is replaced on every edit. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
        int endTextLength;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
         * Resets the region to delete to be the complete document and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
         * the text from invoking valueToString on the current value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
        void resetFromValue(InternationalFormatter formatter) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
            // Need to reset the complete string as Format's result can
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
            // be completely different.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
            offset = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
                text = formatter.valueToString(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
            } catch (ParseException pe) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
                // Should never happen, otherwise canReplace would have
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
                // returned value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
                text = "";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
            length = fb.getDocument().getLength();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
     * IncrementAction is used to increment the value by a certain amount.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
     * It calls into <code>adjustValue</code> to handle the actual
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
     * incrementing of the value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
    private class IncrementAction extends AbstractAction {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
        private int direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
        IncrementAction(String name, int direction) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
            super(name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
            this.direction = direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
        public void actionPerformed(ActionEvent ae) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
            if (getFormattedTextField().isEditable()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
                if (getAllowsInvalid()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
                    // This will work if the currently edited value is valid.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
                    updateMask();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
                boolean validEdit = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
                if (isValidMask()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
                    int start = getFormattedTextField().getSelectionStart();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
                    if (start != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
                        AttributedCharacterIterator iterator = getIterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
                        iterator.setIndex(start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
                        Map attributes = iterator.getAttributes();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
                        Object field = getAdjustField(start, attributes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
                        if (canIncrement(field, start)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
                            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
                                Object value = stringToValue(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
                                        getFormattedTextField().getText());
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
                                int fieldTypeCount = getFieldTypeCountTo(
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
                                        field, start);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
                                value = adjustValue(value, attributes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
                                        field, direction);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
                                if (value != null && isValidValue(value, false)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
                                    resetValue(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
                                    updateMask();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
                                    if (isValidMask()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
                                        selectField(field, fieldTypeCount);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
                                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
                                    validEdit = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
                                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
                            catch (ParseException pe) { }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
                            catch (BadLocationException ble) { }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
                if (!validEdit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
                    invalidEdit();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
}