Home » openjdk-7 » javax » swing » text » [javadoc | source]

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   /**
   18    * @author Alexey A. Ivanov, Roman I. Chernyatchik
   19    */
   20   package javax.swing.text;
   21   
   22   import java.lang.ref.PhantomReference;
   23   import java.lang.ref.Reference;
   24   import java.lang.ref.ReferenceQueue;
   25   import java.lang.ref.WeakReference;
   26   import java.util.ArrayList;
   27   import java.util.Collections;
   28   import java.util.List;
   29   import java.util.Vector;
   30   
   31   import org.apache.harmony.x.swing.internal.nls.Messages;
   32   
   33   abstract class ContentPositions {
   34       public final class DocumentMark implements Position, Comparable {
   35           protected int index;
   36   
   37           protected final Reference ref;
   38   
   39           private DocumentMark(final int offset) {
   40               setOffset(offset);
   41               ref = null;
   42           }
   43   
   44           private DocumentMark(final int offset, final Position pos) {
   45               setOffset(offset);
   46               this.ref = new MarkReference(pos, this, positionQueue);
   47               insertPosition(this);
   48           }
   49   
   50           /*
   51            * @see java.lang.Comparable#compareTo(java.lang.Object)
   52            */
   53           public int compareTo(final Object obj) {
   54               return compare((DocumentMark) obj);
   55           }
   56   
   57           public int getOffset() {
   58               return getOffsetForDocumentMark(index);
   59           }
   60   
   61           protected int compare(final DocumentMark dm) {
   62               return index - dm.index;
   63           }
   64   
   65           protected boolean isEqual(final DocumentMark dm) {
   66               return compare(dm) == 0;
   67           }
   68   
   69           protected boolean isGreater(final DocumentMark dm) {
   70               return compare(dm) > 0;
   71           }
   72   
   73           protected boolean isLess(final DocumentMark dm) {
   74               return compare(dm) < 0;
   75           }
   76   
   77           protected void setOffset(final int offset) {
   78               index = setOffsetForDocumentMark(offset);
   79           }
   80       }
   81   
   82       private static final class MarkReference extends PhantomReference {
   83           protected final DocumentMark hostMark;
   84   
   85           public MarkReference(final Object userMark,
   86                   final DocumentMark hostMark, final ReferenceQueue queue) {
   87               super(userMark, queue);
   88               this.hostMark = hostMark;
   89           }
   90       }
   91   
   92       private final class UndoPosRef {
   93           private int documentOffset;
   94   
   95           private WeakReference posWeakRef;
   96   
   97           protected UndoPosRef(final WeakReference weakReference) {
   98               posWeakRef = weakReference;
   99               DocumentMark positionMark = (DocumentMark) posWeakRef.get();
  100               if (positionMark != null) {
  101                   documentOffset = positionMark.getOffset();
  102               }
  103           }
  104   
  105           protected void restorePos() {
  106               DocumentMark positionMark = (DocumentMark) posWeakRef.get();
  107               if (positionMark != null) {
  108                   positionMark.setOffset(documentOffset);
  109               }
  110           }
  111       }
  112   
  113       private final class WeakPosition implements Position {
  114           private final DocumentMark mark;
  115   
  116           public WeakPosition(final int offset) {
  117               mark = new DocumentMark(offset, this);
  118           }
  119   
  120           public int getOffset() {
  121               return mark.getOffset();
  122           }
  123       }
  124   
  125       protected List positionList = new ArrayList();
  126   
  127       private ReferenceQueue positionQueue = new ReferenceQueue();
  128   
  129       private DocumentMark searchMark = new DocumentMark(0);
  130   
  131       public Position createPosition(final int offset)
  132               throws BadLocationException {
  133   
  134           if (offset < 0) {
  135               throw new BadLocationException(Messages.getString("swing.85"), offset); //$NON-NLS-1$
  136           }
  137   
  138           return new WeakPosition(offset);
  139       }
  140   
  141       /**
  142        * Deletes position instances from the list that were cleared by the garbage
  143        * collector. It is called (or must be called) in the methods modifying this
  144        * list before the modification is done.
  145        */
  146       public void deletePositions() {
  147           MarkReference ref;
  148           while ((ref = (MarkReference) positionQueue.poll()) != null) {
  149               removePosition(ref.hostMark);
  150               ref.clear();
  151           }
  152       }
  153   
  154       public Vector getPositionsInRange(final Vector vector, final int offset,
  155               final int len) {
  156           Vector vect = vector;
  157           if (vect == null) {
  158               vect = new Vector();
  159           }
  160   
  161           deletePositions();
  162   
  163           for (int i = getStartIndexByOffset(offset); i < positionList.size();
  164                i++) {
  165   
  166               DocumentMark documentMark = (DocumentMark) positionList.get(i);
  167   
  168               final int markOffset = documentMark.getOffset();
  169               assert offset <= markOffset : "Failed @ " + i + ": " + offset
  170                       + " > " + markOffset;
  171               if (markOffset <= offset + len) {
  172                   vect.add(new UndoPosRef(new WeakReference(documentMark)));
  173               } else {
  174                   break;
  175               }
  176           }
  177           return vect;
  178       }
  179   
  180       public void moveMarkIndexes(final int startIndex, final int diff) {
  181   
  182           moveMarkIndexesByPosListIndexes(getStartIndexByIndex(startIndex),
  183                   positionList.size(), diff);
  184   
  185       }
  186   
  187       public void moveMarkIndexes(final int startIndex, final int endIndex,
  188               final int diff) {
  189   
  190           moveMarkIndexesByPosListIndexes(getStartIndexByIndex(startIndex),
  191                   getEndIndexByIndex(endIndex), diff);
  192       }
  193   
  194       public void setMarkIndexes(final int startIndex, final int endIndex,
  195               final int newIndex) {
  196   
  197           final int limit = getEndIndexByIndex(endIndex);
  198           for (int i = getStartIndexByIndex(startIndex); i < limit; i++) {
  199               DocumentMark dm = (DocumentMark) positionList.get(i);
  200               dm.index = newIndex;
  201           }
  202       }
  203   
  204       public void updateUndoPositions(final Vector positions) {
  205   
  206           UndoPosRef undoPositionReference;
  207   
  208           deletePositions();
  209   
  210           for (int i = 0; i < positions.size(); i++) {
  211               Object item = positions.get(i);
  212               if (!(item instanceof UndoPosRef)) {
  213                   continue;
  214               }
  215   
  216               undoPositionReference = (UndoPosRef) item;
  217               undoPositionReference.restorePos();
  218           }
  219   
  220           Collections.sort(positionList);
  221       }
  222   
  223       protected abstract int getOffsetForDocumentMark(final int index);
  224   
  225       protected abstract int setOffsetForDocumentMark(final int offset);
  226   
  227       private int getStartIndexByOffset(final int offset) {
  228           searchMark.setOffset(offset);
  229           return getStartIndexByIndex(searchMark.index);
  230       }
  231   
  232       private int getStartIndexByIndex(final int index) {
  233           if (index == 0) {
  234               // Marks at index 0 must never be updated
  235               for (int i = 0; i < positionList.size(); i++) {
  236                   DocumentMark dm = (DocumentMark) positionList.get(i);
  237                   if (dm.index > 0) {
  238                       return i;
  239                   }
  240               }
  241               return positionList.size();
  242           }
  243   
  244           searchMark.index = index;
  245           int result = findIndex(searchMark);
  246           if (result > 0) {
  247               DocumentMark dm;
  248               do {
  249                   dm = (DocumentMark) positionList.get(result - 1);
  250               } while (!dm.isLess(searchMark) && --result > 0);
  251           }
  252           return result;
  253       }
  254   
  255       private int getEndIndexByIndex(final int index) {
  256           final int lastMark = positionList.size() - 1;
  257           if (index == -1 || lastMark < 0) {
  258               return lastMark + 1;
  259           }
  260   
  261           DocumentMark dm = (DocumentMark) positionList.get(lastMark);
  262           if (index >= dm.index) {
  263               return lastMark + 1;
  264           }
  265   
  266           searchMark.index = index;
  267           int result = findIndex(searchMark);
  268           if (result < lastMark) {
  269               do {
  270                   dm = (DocumentMark) positionList.get(result);
  271               } while (!dm.isGreater(searchMark) && ++result < lastMark);
  272           }
  273           return result;
  274       }
  275   
  276       private int findIndex(final DocumentMark documentMark) {
  277           int result = Collections.binarySearch(positionList, documentMark);
  278           return result < 0 ? -result - 1 : result + 1;
  279       }
  280   
  281       private void moveMarkIndexesByPosListIndexes(final int startPosListIndex,
  282               final int endPosListIndex, final int diff) {
  283   
  284           for (int i = startPosListIndex; i < endPosListIndex; i++) {
  285               DocumentMark dm = (DocumentMark) positionList.get(i);
  286               dm.index += diff;
  287           }
  288       }
  289   
  290       private void insertPosition(final DocumentMark documentMark) {
  291           deletePositions();
  292   
  293           final int index = findIndex(documentMark);
  294           positionList.add(index, documentMark);
  295       }
  296   
  297       private void removePosition(final DocumentMark position) {
  298           int foundPos = Collections.binarySearch(positionList, position);
  299           int pos = foundPos;
  300           Position current = null;
  301           while (pos >= 0
  302                   && (current = (Position) positionList.get(pos)) != position
  303                   && current.getOffset() == position.getOffset()) {
  304               pos--;
  305           }
  306           if (current == position) {
  307               positionList.remove(pos);
  308               return;
  309           }
  310   
  311           current = null;
  312           pos = foundPos + 1;
  313           while (pos < positionList.size()
  314                   && (current = (Position) positionList.get(pos)) != position
  315                   && current.getOffset() == position.getOffset()) {
  316               pos++;
  317           }
  318           if (current == position) {
  319               positionList.remove(pos);
  320           }
  321       }
  322   }

Home » openjdk-7 » javax » swing » text » [javadoc | source]