001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Alexey A. Ivanov, Roman I. Chernyatchik
019: * @version $Revision$
020: */package javax.swing.text;
021:
022: import java.io.IOException;
023: import java.io.ObjectInputStream;
024: import java.io.ObjectOutputStream;
025: import java.io.Serializable;
026: import java.util.Vector;
027:
028: import javax.swing.text.AbstractDocument.Content;
029: import javax.swing.undo.UndoableEdit;
030:
031: import org.apache.harmony.x.swing.internal.nls.Messages;
032:
033: public final class StringContent implements Content, Serializable {
034:
035: private static final String INVALID_START_POSITION_MESSAGE = Messages
036: .getString("swing.0F"); //$NON-NLS-1$
037:
038: private final class StringContentEdit extends
039: AbstractContentUndoableEdit implements UndoableEdit {
040:
041: public StringContentEdit(final int where, final String chars,
042: final boolean isInsertCommand)
043: throws BadLocationException {
044:
045: super (where, chars, isInsertCommand);
046: }
047:
048: protected Vector getPositionsInRange(final Vector positions,
049: final int where, final int len) {
050: return StringContent.this .getPositionsInRange(positions,
051: where, len);
052: }
053:
054: protected void updateUndoPositions(final Vector undoPos) {
055: StringContent.this .updateUndoPositions(undoPos);
056: }
057:
058: protected void insertItems(final int where, final String chars) {
059: StringContent.this .insertItems(where, chars);
060: }
061:
062: protected void removeItems(final int where, final int len) {
063: StringContent.this .removeItems(where, len);
064: }
065: }
066:
067: private static final int DEFAULT_SIZE = 10;
068: private static final int MIN_SIZE = 1;
069:
070: private int size;
071: private int length;
072: private char[] innerContent;
073: private transient ContentPositions stringContentPositions;
074:
075: public StringContent() {
076: this (DEFAULT_SIZE);
077: }
078:
079: public StringContent(final int initialLength) {
080: initTransientFields();
081: size = initialLength < MIN_SIZE ? MIN_SIZE : initialLength;
082: innerContent = new char[size];
083: length = 1;
084: innerContent[0] = '\n';
085: }
086:
087: public int length() {
088: return length;
089: }
090:
091: public UndoableEdit insertString(final int where, final String str)
092: throws BadLocationException {
093:
094: if (str == null) {
095: throw new NullPointerException();
096: }
097:
098: checkInvalidOnInsert(where);
099:
100: insertItems(where, str);
101: // Following code creates "Insert" command.
102: return new StringContentEdit(where, str, true);
103: }
104:
105: public UndoableEdit remove(final int where, final int nitems)
106: throws BadLocationException {
107:
108: checkInvalidOnRemove(where, nitems);
109:
110: // Following code creates "Remove" command and executes it.
111: StringContentEdit removeEdit = new StringContentEdit(where,
112: getString(where, nitems), false);
113: removeItems(where, nitems);
114:
115: return removeEdit;
116:
117: }
118:
119: public String getString(final int where, final int len)
120: throws BadLocationException {
121: checkInvalidOnGetChars(where, len);
122:
123: return String.copyValueOf(innerContent, where, len);
124: }
125:
126: public void getChars(final int where, final int len,
127: final Segment chars) throws BadLocationException {
128:
129: checkInvalidOnGetChars(where, len);
130:
131: chars.array = innerContent;
132: chars.offset = where;
133: chars.count = len;
134: }
135:
136: public Position createPosition(final int offset)
137: throws BadLocationException {
138:
139: return stringContentPositions.createPosition(offset);
140: }
141:
142: protected Vector getPositionsInRange(final Vector vector,
143: final int offset, final int len) {
144:
145: return stringContentPositions.getPositionsInRange(vector,
146: offset, len);
147: }
148:
149: protected void updateUndoPositions(final Vector positions) {
150:
151: stringContentPositions.updateUndoPositions(positions);
152: }
153:
154: private void checkInvalidOnRemove(final int where, final int nitems)
155: throws BadLocationException {
156: if (nitems < 0) {
157: throw new BadLocationException(Messages
158: .getString("swing.99"), //$NON-NLS-1$
159: length);
160: }
161:
162: if (where < 0 || where + nitems >= length) {
163: throw new BadLocationException(
164: INVALID_START_POSITION_MESSAGE, where);
165: }
166: }
167:
168: private void checkInvalidOnGetChars(final int where, final int len)
169: throws BadLocationException {
170: if (len < 0) {
171: throw new BadLocationException(Messages
172: .getString("swing.8C"), //$NON-NLS-1$
173: length);
174: }
175:
176: if (where < 0 || where + len > length) {
177: throw new BadLocationException(
178: INVALID_START_POSITION_MESSAGE, where);
179: }
180: }
181:
182: private void checkInvalidOnInsert(final int where)
183: throws BadLocationException {
184: if (where < 0 || where >= length) {
185: throw new BadLocationException(
186: INVALID_START_POSITION_MESSAGE, where);
187: }
188: }
189:
190: private char[] enlargeInnerContent(final int where,
191: final int newSize) {
192: final int newContentSize = newSize > size * 2 ? newSize * 2
193: : size * 2;
194: char[] newContent = new char[newContentSize];
195: System.arraycopy(innerContent, 0, newContent, 0, where);
196: return newContent;
197: }
198:
199: private void shiftOldDataBeforeInsert(final int where,
200: final int insertedStringLength, final char[] newContent) {
201: System.arraycopy(innerContent, where, newContent, where
202: + insertedStringLength, length - where);
203: }
204:
205: // Add string to content without checkOnInvalid parameters
206: private void insertItems(final int where, final String str) {
207: final int insertedStringLength = str.length();
208: final int newLength = insertedStringLength + length;
209:
210: if (str.length() <= 0) {
211: return;
212: }
213:
214: char[] newContent = innerContent;
215: // If new content length will exceed current content size
216: // we shoult enlarge content's size.
217: if (newLength >= size) {
218: newContent = enlargeInnerContent(where, newLength);
219: }
220: shiftOldDataBeforeInsert(where, insertedStringLength,
221: newContent);
222:
223: if (newLength >= size) {
224: innerContent = newContent;
225: size = innerContent.length;
226: }
227: length = newLength;
228:
229: str.getChars(0, insertedStringLength, innerContent, where);
230: stringContentPositions.moveMarkIndexes(where,
231: insertedStringLength);
232: }
233:
234: // Remove part of content without checkOnInvalid parameters
235: private void removeItems(final int where, final int nitems) {
236: System.arraycopy(innerContent, where + nitems, innerContent,
237: where, length - where - nitems);
238:
239: stringContentPositions.setMarkIndexes(where, where + nitems,
240: where);
241: stringContentPositions.moveMarkIndexes(where + nitems, -nitems);
242: length = length - nitems;
243: }
244:
245: private void initTransientFields() {
246: stringContentPositions = new ContentPositions() {
247:
248: protected int getOffsetForDocumentMark(final int index) {
249: return index;
250: }
251:
252: protected int setOffsetForDocumentMark(final int offset) {
253: return offset;
254: }
255: };
256: }
257:
258: private void readObject(final ObjectInputStream ois)
259: throws IOException, ClassNotFoundException {
260:
261: ois.defaultReadObject();
262:
263: initTransientFields();
264: }
265:
266: private void writeObject(final ObjectOutputStream oos)
267: throws IOException {
268: oos.defaultWriteObject();
269: }
270: }
|