1 19 20 package org.netbeans.lib.editor.view; 21 22 import java.awt.Component ; 23 import java.awt.Graphics ; 24 import java.awt.Rectangle ; 25 import java.awt.Shape ; 26 import javax.swing.event.DocumentEvent ; 27 import javax.swing.text.AbstractDocument ; 28 import javax.swing.text.Element ; 29 import javax.swing.text.View ; 30 import javax.swing.text.ViewFactory ; 31 import org.netbeans.editor.view.spi.EstimatedSpanView; 32 import org.netbeans.editor.view.spi.LockView; 33 import org.netbeans.editor.view.spi.ViewLayoutQueue; 34 import org.netbeans.editor.view.spi.ViewLayoutState; 35 36 53 54 public class GapDocumentView extends GapBoxView { 55 56 private static final boolean debugPaint = Boolean.getBoolean( 57 "netbeans.debug.editor.view.paint"); private static final boolean debugRepaint = Boolean.getBoolean( 59 "netbeans.debug.editor.view.repaint"); 61 66 private static final int ASYNC_CHILDREN_UPDATE_COUNT = 20; 67 68 78 private static final int CHILDREN_UPDATE_SUBTASK_COUNT = 50; 79 80 96 private ChildrenUpdateTask childrenUpdateTask; 97 98 101 private int lastAllocationX; 102 private int lastAllocationY; 103 private int lastAllocationWidth; 104 private int lastAllocationHeight; 105 106 110 private double firstRepaintChildYSubOffset; 111 private double firstRepaintChildYSubSpan; 112 private float firstRepaintChildXSubOffset; 113 114 117 private int layoutLockDepth; 118 119 128 public GapDocumentView(Element elem) { 129 super(elem, View.Y_AXIS); 130 } 131 132 protected GapBoxViewChildren createChildren() { 133 return new GapDocumentViewChildren(this); 134 } 135 136 protected Rectangle reallocate(Shape a) { 137 Rectangle alloc = super.reallocate(a); 138 139 lastAllocationX = alloc.x; 140 lastAllocationY = alloc.y; 141 lastAllocationWidth = alloc.width; 142 lastAllocationHeight = alloc.height; 143 144 return alloc; 145 } 146 147 protected void directUpdateLayout() { 148 if (layoutLockDepth == 0) { 150 super.directUpdateLayout(); 151 } 152 } 153 154 protected final void layoutLock() { 155 layoutLockDepth++; 156 } 157 158 protected final void layoutUnlock() { 159 layoutLockDepth--; 160 } 161 162 public void renderWithUpdateLayout(Runnable r) { 163 layoutLockDepth++; 164 try { 165 r.run(); 166 } finally { 167 updateLayout(); 168 layoutLockDepth--; 169 } 170 } 171 172 public void setParent(View parent) { 173 layoutLockDepth++; 174 try { 175 super.setParent(parent); 176 } finally { 177 updateLayout(); 178 layoutLockDepth--; 179 } 180 } 181 182 public void setSize(float width, float height) { 183 layoutLockDepth++; 184 try { 185 super.setSize(width, height); 186 } finally { 187 updateLayout(); 188 layoutLockDepth--; 189 } 190 } 191 192 public void insertUpdate(DocumentEvent evt, Shape a, ViewFactory f) { 193 layoutLockDepth++; 194 try { 195 super.insertUpdate(evt, a, f); 196 } finally { 197 updateLayout(); 198 layoutLockDepth--; 199 } 200 } 201 202 public void removeUpdate(DocumentEvent evt, Shape a, ViewFactory f) { 203 layoutLockDepth++; 204 try { 205 super.removeUpdate(evt, a, f); 206 } finally { 207 updateLayout(); 208 layoutLockDepth--; 209 } 210 } 211 212 public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) { 213 layoutLockDepth++; 214 try { 215 super.changedUpdate(e, a, f); 216 } finally { 217 updateLayout(); 218 layoutLockDepth--; 219 } 220 } 221 222 public void paint(Graphics g, Shape a) { 223 if (debugPaint) { 224 System.err.println("VIEW-PAINT: clip=" + g.getClipBounds() + ", alloc=" + a); } 226 227 layoutLockDepth++; 230 try { 231 super.paint(g, a); 232 } finally { 233 updateLayout(); 234 layoutLockDepth--; 235 } 236 } 237 238 public void repaint(ViewLayoutState child, 239 double majorAxisOffset, double majorAxisSpan, 240 float minorAxisOffset, float minorAxisSpan) { 241 242 int childIndex = getChildIndexNoCheck(child); 243 if (markRepaint(childIndex, false)) { firstRepaintChildYSubOffset = majorAxisOffset; 245 firstRepaintChildXSubOffset = minorAxisOffset; 246 } 247 } 248 249 protected boolean markRepaint(int childIndex, boolean repaintTillEnd) { 250 boolean lowerIndexMarked = super.markRepaint(childIndex, repaintTillEnd); 251 if (lowerIndexMarked) { 252 firstRepaintChildYSubOffset = 0d; 253 firstRepaintChildXSubOffset = 0f; 254 } 255 return lowerIndexMarked; 256 } 257 258 protected void processRepaint(ViewLayoutState.Parent lsParent) { 259 int firstRepaintChildIndex = getChildren().getFirstRepaintChildIndex(); 260 if (firstRepaintChildIndex >= 0 && firstRepaintChildIndex < getViewCount()) { 261 double repY = getChildren().getMajorAxisOffset(firstRepaintChildIndex); 262 repY += firstRepaintChildYSubOffset; 263 int repaintY = (int)Math.floor(repY); 264 265 int repaintX; 266 int repaintHeight; 267 if (isRepaintTillEnd()) { 268 repaintX = 0; repaintHeight = lastAllocationHeight; 270 } else { repaintX = (int)Math.floor(firstRepaintChildXSubOffset); 272 double repYEnd = repY 273 + getChild(firstRepaintChildIndex).getLayoutMajorAxisPreferredSpan(); 274 repaintHeight = (int)Math.ceil(repYEnd) - repaintY; 275 } 276 277 int repaintWidth = lastAllocationWidth - repaintX; 278 repaintX += lastAllocationX; 280 281 if (debugRepaint) { 282 System.err.println("REPAINT(childIndex=" + firstRepaintChildIndex + ", rect(" + repaintX + ", " + repaintY + ", " + repaintWidth + ", " + repaintHeight + "))" ); } 287 288 Component c = getContainer(); 289 if (c != null) { 290 c.repaint(repaintX, repaintY, repaintWidth, repaintHeight); 291 } 292 } 293 } 294 295 ChildrenUpdateTask getChildrenUpdateTask() { 296 if (childrenUpdateTask == null) { 297 childrenUpdateTask = new ChildrenUpdateTask(); 298 } 299 return childrenUpdateTask; 300 } 301 302 protected void resetEstimatedSpan(int childIndex, int count) { 303 if (count >= ASYNC_CHILDREN_UPDATE_COUNT) { 304 ChildrenUpdateTask updateTask = getChildrenUpdateTask(); 305 updateTask.markResetChildEstimatedSpan(); 306 updateTask.setChildIndex(childIndex); 307 if (!updateTask.isRunning()) { 308 updateTask.start(); 309 } 310 311 } else { super.resetEstimatedSpan(childIndex, count); 313 } 314 } 315 316 protected void markSizeInvalid(int childIndex, int count) { 317 if (count >= ASYNC_CHILDREN_UPDATE_COUNT) { 318 ChildrenUpdateTask updateTask = getChildrenUpdateTask(); 319 updateTask.markUpdateChildSize(); 320 updateTask.setChildIndex(0); 321 if (!updateTask.isRunning()) { 322 updateTask.start(); 323 } 324 325 } else { super.markSizeInvalid(childIndex, count); 327 } 328 } 329 330 protected final int getLastAllocationX() { 331 return lastAllocationX; 332 } 333 334 protected final int getLastAllocationY() { 335 return lastAllocationY; 336 } 337 338 protected final int getLastAllocationWidth() { 339 return lastAllocationWidth; 340 } 341 342 protected final int getLastAllocationHeight() { 343 return lastAllocationHeight; 344 } 345 346 349 protected ViewLayoutQueue getLayoutQueue() { 350 return ViewLayoutQueue.getDefaultQueue(); 352 } 353 354 355 365 final class ChildrenUpdateTask implements Runnable { 366 367 private int childIndex = Integer.MAX_VALUE; 368 369 private boolean running; 370 371 private boolean updateChildSize; 372 373 private boolean resetChildEstimatedSpan; 374 375 ChildrenUpdateTask() { 376 } 377 378 void markUpdateChildSize() { 379 updateChildSize = true; 380 } 381 382 void markResetChildEstimatedSpan() { 383 resetChildEstimatedSpan = true; 384 } 385 386 void start() { 387 running = true; 388 getLayoutQueue().addTask(this); 389 } 390 391 boolean isRunning() { 392 return running; 393 } 394 395 private void finish() { 396 running = false; 397 updateChildSize = false; 398 resetChildEstimatedSpan = false; 399 childIndex = Integer.MAX_VALUE; 400 } 401 402 void setChildIndex(int childIndex) { 403 if (childIndex < this.childIndex) { 404 this.childIndex = childIndex; 405 } 406 } 407 408 public void run() { 409 AbstractDocument doc = (AbstractDocument )getDocument(); 410 if (doc!=null){ 411 doc.readLock(); 412 try { 413 LockView lockView = LockView.get(GapDocumentView.this); 414 if (lockView != null) { 415 lockView.lock(); 416 try { 417 layoutLock(); 418 try { 419 updateView(lockView); 420 } finally { 421 updateLayout(); 422 layoutUnlock(); 423 } 424 } finally { 425 lockView.unlock(); 426 } 427 } } finally { 429 doc.readUnlock(); 430 } 431 } 432 } 433 434 private void updateView(LockView lockView) { 435 if (getContainer() == null) { finish(); 437 return; 438 } 439 440 int viewCount = getViewCount(); 441 int updateCount = Math.max(1, 442 viewCount / CHILDREN_UPDATE_SUBTASK_COUNT); 443 444 while (updateCount > 0 && childIndex < viewCount 445 && !lockView.isPriorityThreadWaiting() 446 ) { 447 ViewLayoutState child = getChild(childIndex); 448 if (!child.isFlyweight()) { 449 View childView = child.getView(); 450 451 if (resetChildEstimatedSpan) { 453 if (childView instanceof EstimatedSpanView) { 454 ((EstimatedSpanView)childView).setEstimatedSpan(false); 455 } 456 } 457 458 if (updateChildSize) { 460 child.markViewSizeInvalid(); 461 } 462 463 child.updateLayout(); 465 467 updateCount--; 468 } 469 470 childIndex++; 471 } 472 473 if (childIndex < viewCount) { getLayoutQueue().addTask(this); 477 478 } else { finish(); 480 } 481 } 482 483 } 484 485 } 486 | Popular Tags |