|                                                                                                              1
 19
 20  package org.netbeans.lib.editor.util;
 21
 22
 33
 34  public abstract class FlyOffsetGapList<E> extends GapList<E> {
 35
 36      private int offsetGapStart;
 38      private int offsetGapLength = Integer.MAX_VALUE / 2;
 40      public FlyOffsetGapList() {
 41      }
 42
 43
 50      protected abstract int elementRawOffset(E elem);
 51
 52
 58      protected abstract void setElementRawOffset(E elem, int rawOffset);
 59
 60
 66      protected abstract boolean isElementFlyweight(E elem);
 67
 68
 78      protected abstract int elementLength(E elem);
 79
 80
 90      protected int startOffset() {
 91          return 0;
 92      }
 93
 94
 110     protected final int elementOffset(int index) {
 111         E elem = get(index);
 112         int offset;
 113         if (isElementFlyweight(elem)) {
 114             offset = 0;
 115             while (--index >= 0) {
 116                 elem = get(index);
 117                 offset += elementLength(elem);
 118                 if (!isElementFlyweight(elem)) {
 119                                         offset += raw2RelOffset(elementRawOffset(elem));
 121                     break;
 122                 }
 123             }
 124
 125         } else {             offset = raw2RelOffset(elementRawOffset(elem));
 127         }
 128         return startOffset() + offset;
 129     }
 130
 131
 141     protected final int elementOrEndOffset(int indexOrSize) {
 142         E elem;
 143         int offset;
 144                 if (indexOrSize == size() || isElementFlyweight(elem = get(indexOrSize))) {
 146             offset = 0;
 147             while (--indexOrSize >= 0) {
 148                 elem = get(indexOrSize);
 149                 offset += elementLength(elem);
 150                 if (!isElementFlyweight(elem)) {
 151                                         offset += raw2RelOffset(elementRawOffset(elem));
 153                     break;
 154                 }
 155             }
 156
 157         } else {             offset = raw2RelOffset(elementRawOffset(elem));
 159         }
 160         return startOffset() + offset;
 161     }
 162
 163
 175     public void defaultInsertUpdate(int offset, int length) {
 176         assert (length >= 0);
 177         if (offset != offsetGapStart()) {
 178             moveOffsetGap(offset, findElementIndex(offset));
 179         }
 180         updateOffsetGapLength(-length);
 181                                                 updateOffsetGapStart(length);
 187     }
 188
 189
 202     public void defaultRemoveUpdate(int offset, int length) {
 203         assert (length >= 0);
 204         int index = findElementIndex(offset);
 205         if (offset != offsetGapStart()) {
 206             moveOffsetGap(offset, index);
 207         }
 208         int size = size();
 209         int removeAreaEndRawOffset = offset + offsetGapLength + length;
 210                                 while (index < size) {
 214             E elem = get(index++);
 215             if (!isElementFlyweight(elem)) {
 216                 if (elementRawOffset(elem) < removeAreaEndRawOffset) {
 217                     setElementRawOffset(elem, removeAreaEndRawOffset);
 218                 } else {                     break;
 220                 }
 221             }
 222         }
 223         updateOffsetGapLength(+length);
 224     }
 225
 226
 242     protected final void moveOffsetGap(int offset, int index) {
 243         if (offset < offsetGapStart) {             int bound = size();
 245             for (int i = index; i < bound; i++) {
 246                 E elem = get(i);
 247                 if (!isElementFlyweight(elem)) {
 248                     int rawOffset = elementRawOffset(elem);
 249                     if (rawOffset < offsetGapStart) {
 250                         setElementRawOffset(elem, rawOffset + offsetGapLength);
 251                     } else {
 252                         break;
 253                     }
 254                 }
 255             }
 256
 257         } else {              for (int i = index - 1; i >= 0; i--) {
 259                 E elem = get(i);
 260                 if (!isElementFlyweight(elem)) {
 261                     int rawOffset = elementRawOffset(elem);
 262                     if (rawOffset >= offsetGapStart) {
 263                         setElementRawOffset(elem, rawOffset - offsetGapLength);
 264                     } else {
 265                         break;
 266                     }
 267                 }
 268             }
 269         }
 270         offsetGapStart = offset;
 271     }
 272
 273     protected final int offsetGapStart() {
 274         return offsetGapStart;
 275     }
 276
 277
 287     protected final void updateOffsetGapStart(int offsetDelta) {
 288         offsetGapStart += offsetDelta;
 289     }
 290
 291     protected final int offsetGapLength() {
 292         return offsetGapLength;
 293     }
 294
 295
 305     protected final void updateOffsetGapLength(int offsetGapLengthDelta) {
 306         offsetGapLength += offsetGapLengthDelta;
 307         assert (offsetGapLength >= 0);     }
 309
 310
 322     protected final int findElementIndex(int offset) {
 323         int low = 0;
 324         int high = size() - 1;
 325
 326         while (low <= high) {
 327             int index = (low + high) / 2;             int elemOffset = elementOffset(index);
 329
 330             if (elemOffset < offset) {
 331                 low = index + 1;
 332
 333             } else if (elemOffset > offset) {
 334                 high = index - 1;
 335
 336             } else {                 while (index > 0) {
 338                     index--;
 339                     if (elementOffset(index) < offset) {
 340                         index++;
 341                         break;
 342                     }
 343                 }
 344                 low = index;
 345                 break;
 346             }
 347         }
 348         return low;
 349     }
 350
 351
 359     protected void updateElementOffsetAdd(E elem) {
 360         if (!isElementFlyweight(elem)) {
 361             int offset = elementRawOffset(elem);             setElementRawOffset(elem, offset2Raw(offset));
 363         }
 364     }
 365
 366
 377     protected void updateElementOffsetRemove(E elem) {
 378         if (!isElementFlyweight(elem)) {
 379             int rawOffset = raw2RelOffset(elementRawOffset(elem));
 380             rawOffset += startOffset();
 381             setElementRawOffset(elem, rawOffset);
 382         }
 383     }
 384
 385
 391     private int raw2RelOffset(int rawOffset) {
 392         return (rawOffset < offsetGapStart)
 393             ? rawOffset
 394             : rawOffset - offsetGapLength;
 395     }
 396
 397
 403     protected final int offset2Raw(int offset) {
 404         offset -= startOffset();
 405         if (offset >= offsetGapStart) {
 406             offset += offsetGapLength;
 407         }
 408         return offset;
 409     }
 410
 411
 418     protected void consistencyCheck(boolean checkElementLength) {
 419         super.consistencyCheck();
 420
 421         if (offsetGapLength < 0) {
 422             consistencyError("offsetGapLength < 0");         }
 424
 425         int lastRawOffset = Integer.MIN_VALUE;
 426         int lastOffset = Integer.MIN_VALUE;
 427         int lastEndOffset = lastOffset;
 428         int size = size();
 429         for (int i = 0; i < size; i++) {
 430             E elem = get(i);
 431             if (!isElementFlyweight(elem)) {
 432                 int rawOffset = elementRawOffset(elem);
 433                 int offset = raw2RelOffset(rawOffset);
 434                 if (rawOffset < lastRawOffset) {
 435                     consistencyError("Invalid rawOffset="                         + rawOffset + " >= lastRawOffset=" + lastRawOffset                         + " at index=" + i                     );
 439                 }
 440                 if (offset < lastOffset) {
 441                     consistencyError("Invalid offset="                         + offset + " >= lastOffset=" + lastOffset                         + " at index=" + i                     );
 445                 }
 446                 if (checkElementLength) {                     int length = elementLength(elem);
 448                     if (i == 0) {
 449                         lastEndOffset = offset;
 450                     }
 451                     if (offset != lastEndOffset) {
 452                         consistencyError("Offset=" + offset                             + " differs from lastEndOffset=" + lastEndOffset                             + " at index=" + i                         );
 456                     }
 457                     lastEndOffset += length;
 458                 }
 459                 lastRawOffset = rawOffset;
 460                 lastOffset = offset;
 461
 462             } else {                 if (checkElementLength) {
 464                     if (i == 0) {
 465                                                 lastEndOffset = 0;
 467                     }
 468                     int length = elementLength(elem);
 469                     lastEndOffset += length;
 470                 }
 471             }
 472         }
 473     }
 474
 475     protected String
  dumpInternals() { 476         return super.dumpInternals() + ", offGap(s=" + offsetGapStart
 477         + ", l=" + offsetGapLength + ")";
 478     }
 479
 480 }
 481
                                                                                                                                                                                                             |                                                                       
 
 
 
 
 
                                                                                   Popular Tags                                                                                                                                                                                              |