320 |
|
|
321 |
int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start); |
int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start); |
322 |
return Math.max (0, pos); |
return Math.max (0, pos); |
323 |
} |
} |
324 |
|
|
325 |
/** |
/** |
326 |
* Since insertUpdate and removeUpdate each deal with children |
* Since insertUpdate and removeUpdate each deal with children |
330 |
* @param a the allocation of the View. |
* @param a the allocation of the View. |
331 |
* @param f the ViewFactory to use for rebuilding. |
* @param f the ViewFactory to use for rebuilding. |
332 |
*/ |
*/ |
333 |
void insertOrRemoveUpdate(DocumentEvent changes, Shape a, ViewFactory f) |
void updateDamage(DocumentEvent changes, Shape a, ViewFactory f) |
334 |
{ |
{ |
335 |
Element el = getElement(); |
Element el = getElement(); |
336 |
ElementChange ec = changes.getChange(el); |
ElementChange ec = changes.getChange(el); |
337 |
|
|
338 |
|
// If ec is null then no lines were added or removed, just |
339 |
|
// repaint the changed line |
340 |
if (ec == null) |
if (ec == null) |
341 |
return; |
{ |
342 |
|
int line = getElement().getElementIndex(changes.getOffset()); |
343 |
|
damageLineRange(line, line, a, getContainer()); |
344 |
|
return; |
345 |
|
} |
346 |
|
|
347 |
|
Element[] removed = ec.getChildrenRemoved(); |
348 |
|
Element[] newElements = ec.getChildrenAdded(); |
349 |
|
|
350 |
|
// If no Elements were added or removed, we just want to repaint |
351 |
|
// the area containing the line that was modified |
352 |
|
if (removed == null && newElements == null) |
353 |
|
{ |
354 |
|
int line = getElement().getElementIndex(changes.getOffset()); |
355 |
|
damageLineRange(line, line, a, getContainer()); |
356 |
|
return; |
357 |
|
} |
358 |
|
|
359 |
// Check to see if we removed the longest line, if so we have to |
// Check to see if we removed the longest line, if so we have to |
360 |
// search through all lines and find the longest one again |
// search through all lines and find the longest one again |
|
Element[] removed = ec.getChildrenRemoved(); |
|
361 |
if (removed != null) |
if (removed != null) |
362 |
{ |
{ |
363 |
for (int i = 0; i < removed.length; i++) |
for (int i = 0; i < removed.length; i++) |
366 |
// reset maxLineLength and search through all lines for longest one |
// reset maxLineLength and search through all lines for longest one |
367 |
maxLineLength = -1; |
maxLineLength = -1; |
368 |
determineMaxLineLength(); |
determineMaxLineLength(); |
369 |
|
((JTextComponent)getContainer()).repaint(); |
370 |
return; |
return; |
371 |
} |
} |
372 |
} |
} |
373 |
|
|
374 |
|
// If we've reached here, that means we haven't removed the longest line |
375 |
|
if (newElements == null) |
376 |
|
{ |
377 |
|
// No lines were added, just repaint the container and exit |
378 |
|
((JTextComponent)getContainer()).repaint(); |
379 |
|
return; |
380 |
|
} |
381 |
|
|
382 |
// Make sure we have the metrics |
// Make sure we have the metrics |
383 |
updateMetrics(); |
updateMetrics(); |
384 |
|
|
385 |
// Since we didn't remove the longest line, we can just compare it to |
// If we've reached here, that means we haven't removed the longest line |
386 |
// the new lines to see if any of them are longer |
// and we have added at least one line, so we have to check if added lines |
387 |
Element[] newElements = ec.getChildrenAdded(); |
// are longer than the previous longest line |
388 |
Segment seg = new Segment(); |
Segment seg = new Segment(); |
389 |
float longestNewLength = 0; |
float longestNewLength = 0; |
390 |
Element longestNewLine = null; |
Element longestNewLine = null; |
391 |
|
|
392 |
if (newElements == null) |
// Loop through the added lines to check their length |
|
return; |
|
393 |
for (int i = 0; i < newElements.length; i++) |
for (int i = 0; i < newElements.length; i++) |
394 |
{ |
{ |
395 |
Element child = newElements[i]; |
Element child = newElements[i]; |
397 |
int end = child.getEndOffset(); |
int end = child.getEndOffset(); |
398 |
try |
try |
399 |
{ |
{ |
400 |
el.getDocument().getText(start, start + end, seg); |
el.getDocument().getText(start, end - start, seg); |
401 |
} |
} |
402 |
catch (BadLocationException ex) |
catch (BadLocationException ex) |
403 |
{ |
{ |
404 |
} |
} |
405 |
|
|
|
|
|
406 |
if (seg == null || seg.array == null || seg.count == 0) |
if (seg == null || seg.array == null || seg.count == 0) |
407 |
continue; |
continue; |
408 |
|
|
413 |
longestNewLength = width; |
longestNewLength = width; |
414 |
} |
} |
415 |
} |
} |
416 |
|
|
417 |
|
// Check if the longest of the new lines is longer than our previous |
418 |
|
// longest line, and if so update our values |
419 |
if (longestNewLength > maxLineLength) |
if (longestNewLength > maxLineLength) |
420 |
{ |
{ |
421 |
maxLineLength = longestNewLength; |
maxLineLength = longestNewLength; |
422 |
longestLine = longestNewLine; |
longestLine = longestNewLine; |
423 |
} |
} |
424 |
|
// Repaint the container |
425 |
|
((JTextComponent)getContainer()).repaint(); |
426 |
} |
} |
427 |
|
|
428 |
/** |
/** |
435 |
*/ |
*/ |
436 |
public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) |
public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) |
437 |
{ |
{ |
438 |
insertOrRemoveUpdate(changes, a, f); |
updateDamage(changes, a, f); |
|
((JTextComponent)getContainer()).repaint(); |
|
439 |
} |
} |
440 |
|
|
441 |
/** |
/** |
448 |
*/ |
*/ |
449 |
public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) |
public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) |
450 |
{ |
{ |
451 |
insertOrRemoveUpdate(changes, a, f); |
updateDamage(changes, a, f); |
452 |
((JTextComponent)getContainer()).repaint(); |
} |
453 |
|
|
454 |
|
/** |
455 |
|
* This method is called when attributes were changed in the |
456 |
|
* Document in a location that this view is responsible for. |
457 |
|
*/ |
458 |
|
public void changedUpdate (DocumentEvent changes, Shape a, ViewFactory f) |
459 |
|
{ |
460 |
|
updateDamage(changes, a, f); |
461 |
|
} |
462 |
|
|
463 |
|
/** |
464 |
|
* Repaint the given line range. This is called from insertUpdate, |
465 |
|
* changedUpdate, and removeUpdate when no new lines were added |
466 |
|
* and no lines were removed, to repaint the line that was |
467 |
|
* modified. |
468 |
|
* |
469 |
|
* @param line0 the start of the range |
470 |
|
* @param line1 the end of the range |
471 |
|
* @param a the rendering region of the host |
472 |
|
* @param host the Component that uses this View (used to call repaint |
473 |
|
* on that Component) |
474 |
|
* |
475 |
|
* @since 1.4 |
476 |
|
*/ |
477 |
|
protected void damageLineRange (int line0, int line1, Shape a, Component host) |
478 |
|
{ |
479 |
|
if (a == null) |
480 |
|
return; |
481 |
|
|
482 |
|
Rectangle rec0 = lineToRect(a, line0); |
483 |
|
Rectangle rec1 = lineToRect(a, line1); |
484 |
|
|
485 |
|
if (rec0 == null || rec1 == null) |
486 |
|
// something went wrong, repaint the entire host to be safe |
487 |
|
host.repaint(); |
488 |
|
else |
489 |
|
{ |
490 |
|
Rectangle repaintRec = rec0.union(rec1); |
491 |
|
host.repaint(repaintRec.x, repaintRec.y, repaintRec.width, |
492 |
|
repaintRec.height); |
493 |
|
} |
494 |
} |
} |
495 |
} |
} |
496 |
|
|