1 19 20 package org.netbeans.lib.editor.view; 21 22 import java.awt.Rectangle ; 23 import java.awt.Shape ; 24 import javax.swing.SwingConstants ; 25 import javax.swing.text.BadLocationException ; 26 import javax.swing.text.Position ; 27 import javax.swing.text.View ; 28 import org.netbeans.editor.view.spi.FlyView; 29 30 36 37 public class ViewUtilitiesImpl { 38 39 private ViewUtilitiesImpl() { 40 } 41 42 57 public static int findViewIndexBounded(View view, int offset) { 58 if ((offset >= view.getStartOffset()) && (offset < view.getEndOffset())) { 59 return findViewIndex(view, offset); 60 } 61 62 return -1; } 64 65 84 public static int findViewIndex(View view, int offset) { 85 return findViewIndex(view, offset, null); 86 } 87 88 93 private static int findViewIndex(View view, int offset, OffsetMatchUpdater updater) { 94 FlyView.Parent flyParent = (view instanceof FlyView.Parent) 95 ? (FlyView.Parent)view 96 : null; 97 98 int low = 0; 99 int high = view.getViewCount() - 1; 100 101 if (high == -1) { return -1; 103 } 104 105 while (low <= high) { 106 int mid = (low + high) / 2; 107 int midStartOffset = (flyParent != null) 108 ? flyParent.getStartOffset(mid) 109 : view.getView(mid).getStartOffset(); 110 111 if (midStartOffset < offset) { 112 low = mid + 1; 113 } else if (midStartOffset > offset) { 114 high = mid - 1; 115 } else { if (updater != null) { 117 mid = updater.updateIndex(mid, offset, view, flyParent); 118 } 119 return mid; 120 } 121 } 122 123 if (high < 0) { 124 high = 0; 125 } 126 return high; 127 } 128 129 145 public static int findLowerViewIndex(View view, int offset, boolean lowerAdjacent) { 146 OffsetMatchUpdater updater = lowerAdjacent 147 ? LowerOffsetMatchUpdater.adjacent 148 : LowerOffsetMatchUpdater.normal; 149 150 return findViewIndex(view, offset, updater); 151 } 152 153 169 public static int findUpperViewIndex(View view, int offset, boolean excludeAtOffset) { 170 OffsetMatchUpdater updater = excludeAtOffset 171 ? UpperOffsetMatchUpdater.exclude 172 : UpperOffsetMatchUpdater.normal; 173 174 return findViewIndex(view, offset, updater); 175 } 176 177 188 public static Rectangle maybeNew(Rectangle r, int x, int y, int width, int height) { 189 if (r == null || r.x != x || r.y != y || r.width != width || r.height != height) { 190 return new Rectangle (x, y, width, height); 191 } else { 192 return r; 193 } 194 } 195 196 204 public static Rectangle maybeNew(Rectangle origRect, Rectangle testRect) { 205 if (origRect == null || !origRect.equals(testRect)) { 206 origRect = new Rectangle (testRect); 207 } 208 return origRect; 209 } 210 211 public static String axisToString(int axis) { 212 switch (axis) { 213 case View.X_AXIS: 214 return "x"; 216 case View.Y_AXIS: 217 return "y"; 219 default: 220 return "<invalid-axis-value=" + axis + ">"; } 222 } 223 224 257 static int getNextVisualPositionFrom(View v, int pos, Position.Bias b, 258 Shape alloc, int direction, Position.Bias [] biasRet) 259 throws BadLocationException { 260 261 if (v.getViewCount() == 0) { 262 return pos; 264 } 265 266 boolean top = (direction == SwingConstants.NORTH || 267 direction == SwingConstants.WEST); 268 int retValue; 269 if (pos == -1) { 270 int childIndex = (top) ? v.getViewCount() - 1 : 0; 272 View child = v.getView(childIndex); 273 Shape childBounds = v.getChildAllocation(childIndex, alloc); 274 retValue = child.getNextVisualPositionFrom(pos, b, childBounds, 275 direction, biasRet); 276 if (retValue == -1 && !top && v.getViewCount() > 1) { 277 child = v.getView(1); 281 childBounds = v.getChildAllocation(1, alloc); 282 retValue = child.getNextVisualPositionFrom(-1, biasRet[0], 283 childBounds, 284 direction, biasRet); 285 } 286 287 } else { 288 int increment = (top) ? -1 : 1; 289 int childIndex; 290 if (b == Position.Bias.Backward && pos > 0) { 291 childIndex = v.getViewIndex(pos - 1, Position.Bias.Forward); 292 } else { 293 childIndex = v.getViewIndex(pos, Position.Bias.Forward); 294 } 295 296 View child = v.getView(childIndex); 297 Shape childBounds = v.getChildAllocation(childIndex, alloc); 298 retValue = child.getNextVisualPositionFrom(pos, b, childBounds, 299 direction, biasRet); 300 308 309 childIndex += increment; 310 if (retValue == -1 && childIndex >= 0 && 311 childIndex < v.getViewCount()) { 312 child = v.getView(childIndex); 313 childBounds = v.getChildAllocation(childIndex, alloc); 314 retValue = child.getNextVisualPositionFrom( 315 -1, b, childBounds, direction, biasRet); 316 if (retValue == pos && biasRet[0] != b) { 320 return getNextVisualPositionFrom(v, pos, biasRet[0], 321 alloc, direction, 322 biasRet); 323 } 324 } 325 else if (retValue != -1 && biasRet[0] != b && 326 ((increment == 1 && child.getEndOffset() == retValue) || 327 (increment == -1 && 328 child.getStartOffset() == retValue)) && 329 childIndex >= 0 && childIndex < v.getViewCount() 330 ) { 331 child = v.getView(childIndex); 334 childBounds = v.getChildAllocation(childIndex, alloc); 335 Position.Bias originalBias = biasRet[0]; 336 int nextPos = child.getNextVisualPositionFrom( 337 -1, b, childBounds, direction, biasRet); 338 339 if (biasRet[0] == b) { 340 retValue = nextPos; 341 } else { 342 biasRet[0] = originalBias; 343 } 344 } 345 } 346 return retValue; 347 } 348 349 public static void checkViewHierarchy(View v) { 350 checkChildrenParent(v); 351 } 352 353 private static void checkChildrenParent(View v) { 354 int cnt = v.getViewCount(); 355 for (int i = 0; i < cnt; i++) { 356 View child = v.getView(i); 357 View childParent = child.getParent(); 358 if (childParent != v) { 359 throw new IllegalStateException ("child=" + child + " has parent=" + childParent + " instead of " + v ); 363 } 364 checkChildrenParent(child); 365 } 366 } 367 368 372 interface OffsetMatchUpdater { 373 374 int updateIndex(int viewIndex, int offset, View view, FlyView.Parent flyParent); 375 376 } 377 378 static class LowerOffsetMatchUpdater implements OffsetMatchUpdater { 379 380 static final LowerOffsetMatchUpdater normal = new LowerOffsetMatchUpdater(false); 381 static final LowerOffsetMatchUpdater adjacent = new LowerOffsetMatchUpdater(true); 382 383 private final boolean lowerAdjacent; 384 385 LowerOffsetMatchUpdater(boolean lowerAdjacent) { 386 this.lowerAdjacent = lowerAdjacent; 387 } 388 389 public int updateIndex(int viewIndex, int offset, View view, FlyView.Parent flyParent) { 390 while (--viewIndex >= 0) { 391 int startOffset = (flyParent != null) 392 ? flyParent.getStartOffset(viewIndex) 393 : view.getView(viewIndex).getStartOffset(); 394 if (startOffset != offset) { if (lowerAdjacent) { 396 viewIndex--; } 398 399 break; 400 } 401 } 402 403 return viewIndex + 1; 404 } 405 406 } 407 408 static class UpperOffsetMatchUpdater implements OffsetMatchUpdater { 409 410 static final UpperOffsetMatchUpdater normal = new UpperOffsetMatchUpdater(false); 411 static final UpperOffsetMatchUpdater exclude = new UpperOffsetMatchUpdater(true); 412 413 private final boolean excludeAtOffset; 414 415 UpperOffsetMatchUpdater(boolean excludeAtOffset) { 416 this.excludeAtOffset = excludeAtOffset; 417 } 418 419 public int updateIndex(int viewIndex, int offset, View view, FlyView.Parent flyParent) { 420 int lastViewIndex = view.getViewCount() - 1; 421 422 while (true) { 423 int endOffset = (flyParent != null) 424 ? flyParent.getEndOffset(viewIndex) 425 : view.getView(viewIndex).getEndOffset(); 426 if (endOffset != offset) { if (excludeAtOffset) { 428 viewIndex--; } 430 break; 431 } 432 433 if (viewIndex == lastViewIndex) { break; 435 } 436 viewIndex++; 437 } 438 439 return viewIndex; 440 } 441 442 } 443 444 } 445 | Popular Tags |