Source for javax.swing.text.StringContent

   1: /* StringContent.java --
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.text;
  40: 
  41: import java.io.Serializable;
  42: import java.util.Iterator;
  43: import java.util.Vector;
  44: 
  45: import javax.swing.undo.AbstractUndoableEdit;
  46: import javax.swing.undo.CannotRedoException;
  47: import javax.swing.undo.CannotUndoException;
  48: import javax.swing.undo.UndoableEdit;
  49: 
  50: /**
  51:  * An implementation of the <code>AbstractDocument.Content</code>
  52:  * interface useful for small documents or debugging. The character
  53:  * content is a simple character array. It's not really efficient.
  54:  * 
  55:  * <p>Do not use this class for large size.</p>
  56:  */
  57: public final class StringContent implements AbstractDocument.Content, Serializable
  58: {
  59:   /** The serialization UID (compatible with JDK1.5). */
  60:   private static final long serialVersionUID = 4755994433709540381L;
  61: 
  62:   // This is package-private to avoid an accessor method.
  63:   char[] content;
  64: 
  65:   private int count;
  66: 
  67:   private Vector positions = new Vector();
  68: 
  69:   private class InsertUndo extends AbstractUndoableEdit
  70:   {
  71:     private int start;
  72:     
  73:     private int length;
  74: 
  75:     private String redoContent;
  76: 
  77:     public InsertUndo(int start, int length)
  78:     {
  79:       super();
  80:       this.start = start;
  81:       this.length = length;
  82:     }
  83: 
  84:     public void undo()
  85:     {
  86:       super.undo();
  87:       try
  88:         {
  89:           StringContent.this.checkLocation(this.start, this.length);
  90:           this.redoContent = new String(StringContent.this.content, this.start, this.length);
  91:           StringContent.this.remove(this.start, this.length);
  92:         }
  93:       catch (BadLocationException b)
  94:         {
  95:           throw new CannotUndoException();
  96:         }
  97:     }
  98:     
  99:     public void redo()
 100:     {
 101:       super.redo();
 102:       try
 103:         {
 104:           StringContent.this.insertString(this.start, this.redoContent);
 105:         }
 106:       catch (BadLocationException b)
 107:         {
 108:           throw new CannotRedoException();
 109:         }
 110:     }
 111:   }
 112: 
 113:   private class RemoveUndo extends AbstractUndoableEdit
 114:   {
 115:     private int start;
 116: 
 117:     private String undoString;
 118: 
 119:     public RemoveUndo(int start, String str)
 120:     {
 121:       super();
 122:       this.start = start;
 123:       this.undoString = str;
 124:     }
 125: 
 126:     public void undo()
 127:     {
 128:       super.undo();
 129:       try
 130:         {
 131:           StringContent.this.insertString(this.start, this.undoString);
 132:         }
 133:       catch (BadLocationException bad)
 134:         {
 135:           throw new CannotUndoException();
 136:         }
 137:     }
 138: 
 139:     public void redo()
 140:     {
 141:       super.redo();
 142:       try
 143:         {
 144:           int end = this.undoString.length();
 145:           StringContent.this.remove(this.start, end);
 146:         }
 147:       catch (BadLocationException bad)
 148:         {
 149:           throw new CannotRedoException();
 150:         }
 151:     }
 152:   }
 153: 
 154:   private class StickyPosition implements Position
 155:   {
 156:     private int offset = -1;
 157: 
 158:     public StickyPosition(int offset)
 159:     {
 160:       this.offset = offset;
 161:     }
 162: 
 163:     // This is package-private to avoid an accessor method.
 164:     void setOffset(int offset)
 165:     {
 166:       this.offset = this.offset >= 0 ? offset : -1;
 167:     }
 168: 
 169:     /**
 170:      * Should be >=0.
 171:      */
 172:     public int getOffset()
 173:     {
 174:       return offset < 0 ? 0 : offset;
 175:     }
 176:   }
 177: 
 178:   public StringContent()
 179:   {
 180:     this(1);
 181:   }
 182: 
 183:   public StringContent(int initialLength)
 184:   {
 185:     super();
 186:     if (initialLength < 1)
 187:       initialLength = 1;
 188:     this.content = new char[initialLength];
 189:     this.content[0] = '\n';
 190:     this.count = 1;
 191:   }
 192: 
 193:   protected Vector getPositionsInRange(Vector v,
 194:                                        int offset,
 195:                                        int length)
 196:   {
 197:     Vector refPos = new Vector();
 198:     Iterator iter = this.positions.iterator();
 199:     while(iter.hasNext())
 200:       {
 201:         Position p = (Position)iter.next();
 202:         if ((offset <= p.getOffset())
 203:             && (p.getOffset() <= (offset + length)))
 204:           refPos.add(p);
 205:       }
 206:     return refPos;
 207:   }
 208: 
 209:   public Position createPosition(int offset) throws BadLocationException
 210:   {
 211:     if (offset < this.count || offset > this.count)
 212:       checkLocation(offset, 0);
 213:     StickyPosition sp = new StickyPosition(offset);
 214:     this.positions.add(sp);
 215:     return sp;
 216:   }
 217:   
 218:   public int length()
 219:   {
 220:     return this.count;
 221:   }
 222:   
 223:   public UndoableEdit insertString(int where, String str)
 224:     throws BadLocationException
 225:   {
 226:     checkLocation(where, 0);
 227:     if (where == this.count)
 228:       throw new BadLocationException("Invalid location", 1);
 229:     if (str == null)
 230:       throw new NullPointerException();
 231:     char[] insert = str.toCharArray();
 232:     char[] temp = new char[this.content.length + insert.length];
 233:     this.count += insert.length;
 234:     // Copy array and insert the string.
 235:     if (where > 0)
 236:       System.arraycopy(this.content, 0, temp, 0, where);
 237:     System.arraycopy(insert, 0, temp, where, insert.length);
 238:     System.arraycopy(this.content, where, temp, (where + insert.length), (temp.length - where - insert.length));
 239:     if (this.content.length < temp.length)
 240:       this.content = new char[temp.length];
 241:     // Copy the result in the original char array.
 242:     System.arraycopy(temp, 0, this.content, 0, temp.length);
 243:     // Move all the positions.
 244:     Vector refPos = getPositionsInRange(this.positions, where, temp.length - where);
 245:     Iterator iter = refPos.iterator();
 246:     while (iter.hasNext())
 247:       {
 248:         StickyPosition p = (StickyPosition)iter.next();
 249:         p.setOffset(p.getOffset() + str.length());
 250:       }
 251:     InsertUndo iundo = new InsertUndo(where, insert.length);
 252:     return iundo;
 253:   }
 254:   
 255:   public UndoableEdit remove(int where, int nitems) throws BadLocationException
 256:   {
 257:     checkLocation(where, nitems);
 258:     char[] temp = new char[(this.content.length - nitems)];
 259:     this.count = this.count - nitems;
 260:     RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where, nitems));
 261:     // Copy array.
 262:     System.arraycopy(this.content, 0, temp, 0, where);
 263:     System.arraycopy(this.content, where + nitems, temp, where, this.content.length - where - nitems);
 264:     this.content = new char[temp.length];
 265:     // Then copy the result in the original char array.
 266:     System.arraycopy(temp, 0, this.content, 0, this.content.length);
 267:     // Move all the positions.
 268:     Vector refPos = getPositionsInRange(this.positions, where, this.content.length + nitems - where);
 269:     Iterator iter = refPos.iterator();
 270:     while (iter.hasNext())
 271:       {
 272:         StickyPosition p = (StickyPosition)iter.next();
 273:         int result = p.getOffset() - nitems;
 274:         p.setOffset(result);
 275:         if (result < 0)
 276:           this.positions.remove(p);
 277:       }
 278:     return rundo;
 279:   }
 280:   
 281:   public String getString(int where, int len) throws BadLocationException
 282:   {
 283:     checkLocation(where, len);
 284:     return new String (this.content, where, len);
 285:   }
 286:   
 287:   public void getChars(int where, int len, Segment txt) throws BadLocationException
 288:   {
 289:     checkLocation(where, len);
 290:     if (txt != null)
 291:       {
 292:         txt.array = this.content;
 293:         txt.offset = where;
 294:         txt.count = len;
 295:       }
 296:   }
 297: 
 298:   // This is package-private to avoid an accessor method.
 299:   void checkLocation(int where, int len) throws BadLocationException
 300:   {
 301:     if (where < 0)
 302:       throw new BadLocationException("Invalid location", 1);
 303:     else if (where > this.count)
 304:       throw new BadLocationException("Invalid location", this.count);
 305:     else if ((where + len)>this.count)
 306:       throw new BadLocationException("Invalid range", this.count);
 307:   }
 308:   
 309: }