1 7 package javax.swing.text; 8 9 import java.awt.*; 10 import javax.swing.event.*; 11 import javax.swing.SizeRequirements ; 12 13 33 public abstract class FlowView extends BoxView { 34 35 private final static FlowStrategy STRATEGY = new FlowStrategy(); 36 37 43 public FlowView(Element elem, int axis) { 44 super(elem, axis); 45 layoutSpan = Integer.MAX_VALUE; 46 strategy = STRATEGY; 47 } 48 49 57 public int getFlowAxis() { 58 if (getAxis() == Y_AXIS) { 59 return X_AXIS; 60 } 61 return Y_AXIS; 62 } 63 64 77 public int getFlowSpan(int index) { 78 return layoutSpan; 79 } 80 81 92 public int getFlowStart(int index) { 93 return 0; 94 } 95 96 103 protected abstract View createRow(); 104 105 107 118 protected void loadChildren(ViewFactory f) { 119 if (layoutPool == null) { 120 layoutPool = new LogicalView(getElement()); 121 } 122 layoutPool.setParent(this); 123 124 strategy.insertUpdate( this, null, null ); 127 } 128 129 137 protected int getViewIndexAtPosition(int pos) { 138 if (pos >= getStartOffset() && (pos < getEndOffset())) { 139 for(int counter = getViewCount() - 1; counter >= 0; counter--) { 140 View v = getView(counter); 141 if(pos >= v.getStartOffset() && 142 pos < v.getEndOffset()) { 143 return counter; 144 } 145 } 146 } 147 return -1; 148 } 149 150 166 protected void layout(int width, int height) { 167 final int faxis = getFlowAxis(); 168 int newSpan; 169 if (faxis == X_AXIS) { 170 newSpan = (int)width; 171 } else { 172 newSpan = (int)height; 173 } 174 if (layoutSpan != newSpan) { 175 layoutChanged(faxis); 176 layoutChanged(getAxis()); 177 layoutSpan = newSpan; 178 } 179 180 if (! isLayoutValid(faxis)) { 182 final int heightAxis = getAxis(); 183 int oldFlowHeight = (int)((heightAxis == X_AXIS)? getWidth() : getHeight()); 184 strategy.layout(this); 185 int newFlowHeight = (int) getPreferredSpan(heightAxis); 186 if (oldFlowHeight != newFlowHeight) { 187 View p = getParent(); 188 if (p != null) { 189 p.preferenceChanged(this, (heightAxis == X_AXIS), (heightAxis == Y_AXIS)); 190 } 191 192 Component host = getContainer(); 196 if (host != null) { 197 host.repaint(); 199 } 200 } 201 } 202 203 super.layout(width, height); 204 } 205 206 212 protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { 213 if (r == null) { 214 r = new SizeRequirements (); 215 } 216 float pref = layoutPool.getPreferredSpan(axis); 217 float min = layoutPool.getMinimumSpan(axis); 218 r.minimum = (int)min; 220 r.preferred = Math.max(r.minimum, (int) pref); 221 r.maximum = Integer.MAX_VALUE; 222 r.alignment = 0.5f; 223 return r; 224 } 225 226 228 237 public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f) { 238 layoutPool.insertUpdate(changes, a, f); 239 strategy.insertUpdate(this, changes, getInsideAllocation(a)); 240 } 241 242 251 public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f) { 252 layoutPool.removeUpdate(changes, a, f); 253 strategy.removeUpdate(this, changes, getInsideAllocation(a)); 254 } 255 256 265 public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory f) { 266 layoutPool.changedUpdate(changes, a, f); 267 strategy.changedUpdate(this, changes, getInsideAllocation(a)); 268 } 269 270 271 public void setParent(View parent) { 272 super.setParent(parent); 273 if (parent == null 274 && layoutPool != null ) { 275 layoutPool.setParent(null); 276 } 277 } 278 279 281 285 protected int layoutSpan; 286 287 296 protected View layoutPool; 297 298 305 protected FlowStrategy strategy; 306 307 317 public static class FlowStrategy { 318 319 330 public void insertUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { 331 if (alloc != null) { 332 Component host = fv.getContainer(); 333 if (host != null) { 334 host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); 335 } 336 } else { 337 fv.preferenceChanged(null, true, true); 338 } 339 } 340 341 349 public void removeUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { 350 if (alloc != null) { 351 Component host = fv.getContainer(); 352 if (host != null) { 353 host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); 354 } 355 } else { 356 fv.preferenceChanged(null, true, true); 357 } 358 } 359 360 370 public void changedUpdate(FlowView fv, DocumentEvent e, Rectangle alloc) { 371 if (alloc != null) { 372 Component host = fv.getContainer(); 373 if (host != null) { 374 host.repaint(alloc.x, alloc.y, alloc.width, alloc.height); 375 } 376 } else { 377 fv.preferenceChanged(null, true, true); 378 } 379 } 380 381 385 protected View getLogicalView(FlowView fv) { 386 return fv.layoutPool; 387 } 388 389 397 public void layout(FlowView fv) { 398 int p0 = fv.getStartOffset(); 399 int p1 = fv.getEndOffset(); 400 401 View lv = getLogicalView(fv); 404 int n = lv.getViewCount(); 405 for( int i = 0; i < n; i++ ) { 406 View v = lv.getView(i); 407 v.setParent(lv); 408 } 409 fv.removeAll(); 410 for (int rowIndex = 0; p0 < p1; rowIndex++) { 411 View row = fv.createRow(); 412 fv.append(row); 413 414 int next = layoutRow(fv, rowIndex, p0); 417 if (row.getViewCount() == 0) { 418 row.append(createView(fv, p0, Integer.MAX_VALUE, rowIndex)); 419 next = row.getEndOffset(); 420 } 421 if (next <= p0) { 422 throw new StateInvariantError ("infinite loop in formatting"); 423 } else { 424 p0 = next; 425 } 426 } 427 } 428 429 445 protected int layoutRow(FlowView fv, int rowIndex, int pos) { 446 View row = fv.getView(rowIndex); 447 int x = fv.getFlowStart(rowIndex); 448 int spanLeft = fv.getFlowSpan(rowIndex); 449 int end = fv.getEndOffset(); 450 TabExpander te = (fv instanceof TabExpander ) ? (TabExpander )fv : null; 451 452 int preX = x; 454 int availableSpan = spanLeft; 455 preX = x; 456 457 final int flowAxis = fv.getFlowAxis(); 458 boolean forcedBreak = false; 459 while (pos < end && spanLeft >= 0) { 460 View v = createView(fv, pos, spanLeft, rowIndex); 461 if ((v == null) 462 || (spanLeft == 0 463 && v.getPreferredSpan(flowAxis) > 0)) { 464 break; 465 } 466 467 int chunkSpan; 468 if ((flowAxis == X_AXIS) && (v instanceof TabableView )) { 469 chunkSpan = (int) ((TabableView )v).getTabbedSpan(x, te); 470 } else { 471 chunkSpan = (int) v.getPreferredSpan(flowAxis); 472 } 473 474 if (v.getBreakWeight(flowAxis, pos, spanLeft) >= ForcedBreakWeight) { 476 int n = row.getViewCount(); 477 if (n > 0) { 478 484 v = v.breakView(flowAxis, pos, x, spanLeft); 485 if (v != null) { 486 if ((flowAxis == X_AXIS) && (v instanceof TabableView )) { 487 chunkSpan = (int) ((TabableView )v).getTabbedSpan(x, te); 488 } else { 489 chunkSpan = (int) v.getPreferredSpan(flowAxis); 490 } 491 } else { 492 chunkSpan = 0; 493 } 494 } 495 forcedBreak = true; 496 } 497 498 spanLeft -= chunkSpan; 499 x += chunkSpan; 500 if (v != null) { 501 row.append(v); 502 pos = v.getEndOffset(); 503 } 504 if (forcedBreak) { 505 break; 506 } 507 508 } 509 if (spanLeft < 0) { 510 adjustRow(fv, rowIndex, availableSpan, preX); 512 } else if (row.getViewCount() == 0) { 513 View v = createView(fv, pos, Integer.MAX_VALUE, rowIndex); 515 row.append(v); 516 } 517 return row.getEndOffset(); 518 } 519 520 532 protected void adjustRow(FlowView fv, int rowIndex, int desiredSpan, int x) { 533 final int flowAxis = fv.getFlowAxis(); 534 View r = fv.getView(rowIndex); 535 int n = r.getViewCount(); 536 int span = 0; 537 int bestWeight = BadBreakWeight; 538 int bestSpan = 0; 539 int bestIndex = -1; 540 int bestOffset = 0; 541 View v; 542 for (int i = 0; i < n; i++) { 543 v = r.getView(i); 544 int spanLeft = desiredSpan - span; 545 546 int w = v.getBreakWeight(flowAxis, x + span, spanLeft); 547 if ((w >= bestWeight) && (w > BadBreakWeight)) { 548 bestWeight = w; 549 bestIndex = i; 550 bestSpan = span; 551 if (w >= ForcedBreakWeight) { 552 break; 555 } 556 } 557 span += v.getPreferredSpan(flowAxis); 558 } 559 if (bestIndex < 0) { 560 return; 563 } 564 565 int spanLeft = desiredSpan - bestSpan; 567 v = r.getView(bestIndex); 568 v = v.breakView(flowAxis, v.getStartOffset(), x + bestSpan, spanLeft); 569 View [] va = new View [1]; 570 va[0] = v; 571 View lv = getLogicalView(fv); 572 for (int i = bestIndex; i < n; i++) { 573 View tmpView = r.getView(i); 574 if (contains(lv,tmpView)) { 575 tmpView.setParent(lv); 576 } else if (tmpView.getViewCount() > 0) { 577 recursiveReparent(tmpView, lv); 578 } 579 } 580 r.replace(bestIndex, n - bestIndex, va); 581 } 582 583 private void recursiveReparent(View v, View logicalView) { 584 int n = v.getViewCount(); 585 for (int i = 0; i < n; i++) { 586 View tmpView = v.getView(i); 587 if (contains(logicalView,tmpView)) { 588 tmpView.setParent(logicalView); 589 } else { 590 recursiveReparent(tmpView, logicalView); 591 } 592 } 593 } 594 595 private boolean contains(View logicalView, View v) { 596 int n = logicalView.getViewCount(); 597 for (int i = 0; i < n; i++) { 598 if (logicalView.getView(i) == v) { 599 return true; 600 } 601 } 602 return false; 603 } 604 605 615 protected View createView(FlowView fv, int startOffset, int spanLeft, int rowIndex) { 616 View lv = getLogicalView(fv); 618 int childIndex = lv.getViewIndex(startOffset, Position.Bias.Forward); 619 View v = lv.getView(childIndex); 620 if (startOffset==v.getStartOffset()) { 621 return v; 623 } 624 625 v = v.createFragment(startOffset, v.getEndOffset()); 627 return v; 628 } 629 } 630 631 638 static class LogicalView extends CompositeView { 639 640 LogicalView(Element elem) { 641 super(elem); 642 } 643 644 protected int getViewIndexAtPosition(int pos) { 645 Element elem = getElement(); 646 if (elem.isLeaf()) { 647 return 0; 648 } 649 return super.getViewIndexAtPosition(pos); 650 } 651 652 protected void loadChildren(ViewFactory f) { 653 Element elem = getElement(); 654 if (elem.isLeaf()) { 655 View v = new LabelView (elem); 656 append(v); 657 } else { 658 super.loadChildren(f); 659 } 660 } 661 662 667 public AttributeSet getAttributes() { 668 View p = getParent(); 669 return (p != null) ? p.getAttributes() : null; 670 } 671 672 683 public float getPreferredSpan(int axis) { 684 float maxpref = 0; 685 float pref = 0; 686 int n = getViewCount(); 687 for (int i = 0; i < n; i++) { 688 View v = getView(i); 689 pref += v.getPreferredSpan(axis); 690 if (v.getBreakWeight(axis, 0, Integer.MAX_VALUE) >= ForcedBreakWeight) { 691 maxpref = Math.max(maxpref, pref); 692 pref = 0; 693 } 694 } 695 maxpref = Math.max(maxpref, pref); 696 return maxpref; 697 } 698 699 711 public float getMinimumSpan(int axis) { 712 float maxmin = 0; 713 float min = 0; 714 boolean nowrap = false; 715 int n = getViewCount(); 716 for (int i = 0; i < n; i++) { 717 View v = getView(i); 718 if (v.getBreakWeight(axis, 0, Integer.MAX_VALUE) == BadBreakWeight) { 719 min += v.getPreferredSpan(axis); 720 nowrap = true; 721 } else if (nowrap) { 722 maxmin = Math.max(min, maxmin); 723 nowrap = false; 724 min = 0; 725 } 726 } 727 maxmin = Math.max(maxmin, min); 728 return maxmin; 729 } 730 731 745 protected void forwardUpdateToView(View v, DocumentEvent e, 746 Shape a, ViewFactory f) { 747 v.setParent(this); 748 super.forwardUpdateToView(v, e, a, f); 749 } 750 751 754 763 public void paint(Graphics g, Shape allocation) { 764 } 765 766 776 protected boolean isBefore(int x, int y, Rectangle alloc) { 777 return false; 778 } 779 780 790 protected boolean isAfter(int x, int y, Rectangle alloc) { 791 return false; 792 } 793 794 805 protected View getViewAtPoint(int x, int y, Rectangle alloc) { 806 return null; 807 } 808 809 818 protected void childAllocation(int index, Rectangle a) { 819 } 820 } 821 822 823 } 824 | Popular Tags |