1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package com.gargoylesoftware.base.util;
39
40 import javax.swing.event.DocumentListener;
41 import javax.swing.event.UndoableEditListener;
42 import javax.swing.text.AttributeSet;
43 import javax.swing.text.BadLocationException;
44 import javax.swing.text.Document;
45 import javax.swing.text.Element;
46 import javax.swing.text.PlainDocument;
47 import javax.swing.text.Position;
48 import javax.swing.text.Segment;
49
50 /***
51 * Various utility methods relating to documents.
52 *
53 * @version $Revision: 1.5 $
54 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
55 */
56 public class DocumentUtil {
57
58 /***
59 * Private constructor to prevent instantiation of this class.
60 */
61 private DocumentUtil() {
62 }
63
64 /***
65 * Return a wrapper document that converts all input to uppercase.
66 * @param document The document to wrapper.
67 * @return The new wrapper document.
68 */
69 public static Document upperCaseDocument( final Document document ) {
70 return new PassthroughDocument(document) {
71 public void insertString(
72 final int offset,
73 final String str,
74 final AttributeSet a)
75 throws
76 BadLocationException {
77
78 super.insertString(offset, str.toUpperCase(), a);
79 }
80 };
81 }
82
83 /***
84 * Return a PlainDocument wrappered so that it accepts uppercase
85 * input only.
86 * @return The new wrapper document.
87 */
88 public static Document upperCaseDocument() {
89 return upperCaseDocument( new PlainDocument() );
90 }
91
92 /***
93 * Return a wrapper document that prevents the user from typing more
94 * than a specified number of characters.
95 * @param document The document to wrapper.
96 * @param maxLength The maximum number of characters that can be placed in
97 * this document.
98 * @return The new wrapper document.
99 */
100 public static Document lengthLimitedDocument( final Document document,
101 final int maxLength ) {
102 return new LengthLimitedDocument(document,maxLength);
103 }
104
105 /***
106 * Return a PlainDocument wrappered so that it is length limited.
107 * @param maxLength The maximum number of characters that can be placed in
108 * this document.
109 * @return The new wrapper document.
110 */
111 public static Document lengthLimitedDocument( final int maxLength ) {
112 return lengthLimitedDocument( new PlainDocument(), maxLength );
113 }
114
115 /***
116 * A wrapper document that prevents the user from typing more than
117 * a specified number of characters.
118 */
119 private static class LengthLimitedDocument extends PassthroughDocument {
120 private int maxLength_;
121
122 /***
123 * Create an instance
124 * @param document The document to wrap
125 * @param maxLength The maximum number of characters that can be entered into this document
126 */
127 public LengthLimitedDocument( final Document document,
128 final int maxLength ) {
129 super(document);
130 if( maxLength < 0 ) {
131 throw new DetailedIllegalArgumentException(
132 "maxLength", new Integer(maxLength), "May not be less than zero");
133 }
134 maxLength_ = maxLength;
135 }
136 /*** @inheritDoc Document.insertString(int,String,AttributeSet) */
137 public void insertString(
138 final int offset,
139 final String string,
140 final AttributeSet attributeSet)
141 throws
142 BadLocationException {
143
144 final int documentLength = getLength();
145 final int stringLength = string.length();
146
147 if( documentLength == maxLength_ ) {
148 return;
149 }
150 else if( documentLength + stringLength <= maxLength_ ) {
151 super.insertString( offset, string, attributeSet );
152 }
153 else {
154 super.insertString( offset,
155 string.substring(0, maxLength_ - documentLength),
156 attributeSet );
157 }
158 }
159 }
160
161 /***
162 * A document that merely passes all requests through to another document.
163 * This is used as the base class for the custom documents provided here.
164 */
165 private abstract static class PassthroughDocument implements Document {
166 private final Document delegate_;
167
168 /***
169 * Create an instance
170 * @param delegate The document to wrap.
171 */
172 public PassthroughDocument( final Document delegate ) {
173 if( delegate == null ) {
174 throw new DetailedNullPointerException("delegate");
175 }
176 delegate_ = delegate;
177 }
178 /*** @inheritDoc Document.getLength() */
179 public int getLength() {
180 return delegate_.getLength();
181 }
182
183 /*** @inheritDoc Document.addDocumentListener(DocumentListener) */
184 public void addDocumentListener(DocumentListener listener) {
185 delegate_.addDocumentListener(listener);
186 }
187
188 /*** @inheritDoc Document.removeDocumentListener(DocumentListener) */
189 public void removeDocumentListener(DocumentListener listener) {
190 delegate_.removeDocumentListener(listener);
191 }
192
193 /*** @inheritDoc Document.addUndoableEditListener(UndoableEditListener) */
194 public void addUndoableEditListener(UndoableEditListener listener) {
195 delegate_.addUndoableEditListener(listener);
196 }
197
198 /*** @inheritDoc Document.removeUndoableEditListener(UndoableEditListener) */
199 public void removeUndoableEditListener(UndoableEditListener listener) {
200 delegate_.removeUndoableEditListener(listener);
201 }
202
203 /*** @inheritDoc Document.getProperty(Object) */
204 public Object getProperty(Object key) {
205 return delegate_.getProperty(key);
206 }
207
208 /*** @inheritDoc Document.putProperty(Object,Object) */
209 public void putProperty(Object key, Object value) {
210 delegate_.putProperty(key,value);
211 }
212
213 /*** @inheritDoc Document.remove(int,int) */
214 public void remove(int offs, int len) throws BadLocationException {
215 delegate_.remove(offs, len);
216 }
217
218 /*** @inheritDoc Document.insertString(int,String,AttributeSet) */
219 public void insertString(int offset, String str, AttributeSet a) throws BadLocationException {
220 delegate_.insertString(offset, str, a);
221 }
222
223 /*** @inheritDoc Document.getText(int,int) */
224 public String getText(int offset, int length) throws BadLocationException {
225 return delegate_.getText(offset, length);
226 }
227
228 /*** @inheritDoc Document.getText(int,int,Segment) */
229 public void getText(int offset, int length, Segment txt) throws BadLocationException {
230 delegate_.getText(offset, length, txt);
231 }
232
233 /*** @inheritDoc Document.getStartPosition() */
234 public Position getStartPosition() {
235 return delegate_.getStartPosition();
236 }
237
238 /*** @inheritDoc Document.getEndPosition() */
239 public Position getEndPosition() {
240 return delegate_.getEndPosition();
241 }
242
243 /*** @inheritDoc Document.createPosition(int) */
244 public Position createPosition(int offs) throws BadLocationException {
245 return delegate_.createPosition(offs);
246 }
247
248 /*** @inheritDoc getRootElements() */
249 public Element[] getRootElements() {
250 return delegate_.getRootElements();
251 }
252
253 /*** @inheritDoc Document.getDefaultRootElement() */
254 public Element getDefaultRootElement() {
255 return delegate_.getDefaultRootElement();
256 }
257
258 /*** @inheritDoc Document.render(Runnable) */
259 public void render(Runnable r) {
260 delegate_.render(r);
261 }
262 }
263 }
264