| 1 21 24 package org.lobobrowser.html.renderer; 25 26 import java.util.*; 27 import java.util.logging.*; 28 29 import java.awt.*; 30 import java.awt.event.*; 31 32 import javax.swing.*; 33 import java.awt.image.ImageObserver ; 34 35 import org.lobobrowser.html.*; 36 import org.lobobrowser.html.domimpl.*; 37 import org.lobobrowser.html.style.*; 38 import org.lobobrowser.util.*; 39 import org.w3c.dom.Node ; 40 41 44 public class RBlock extends BaseElementRenderable implements RenderableContainer, ImageObserver { 45 static final Logger logger = Logger.getLogger(RBlock.class.getName()); 46 private static final boolean loggableInfo = logger.isLoggable(Level.INFO); 47 private static final FloatingBounds INVALID_FLOAT_BOUNDS = new FloatingViewportBounds(null, 0, 0, 0, 0); 48 49 protected final FrameContext frameContext; 50 protected final int listNesting; 51 protected final HtmlRendererContext rendererContext; 52 protected final int defaultOverflow; 53 protected final RBlockViewport bodyLayout; 54 55 protected RenderableSpot startSelection; 56 protected RenderableSpot endSelection; 57 58 protected JScrollBar vScrollBar; 59 protected JScrollBar hScrollBar; 60 protected boolean hasHScrollBar = false; 61 protected boolean hasVScrollBar = false; 62 63 64 private Boolean lastExpandWidth = null; 67 private Boolean lastExpandHeight = null; 68 private int lastAvailHeight = -1; 69 private int lastAvailWidth = -1; 70 private int lastWhiteSpace = -1; 71 private FloatingBounds lastFloatBounds = INVALID_FLOAT_BOUNDS; 72 private Font lastFont = null; 73 74 public RBlock(NodeImpl modelNode, int listNesting, UserAgentContext pcontext, HtmlRendererContext rcontext, FrameContext frameContext, RenderableContainer parentContainer) { 75 this(modelNode, listNesting, pcontext, rcontext, frameContext, parentContainer, RBlock.OVERFLOW_NONE); 76 } 77 78 public RBlock(NodeImpl modelNode, int listNesting, UserAgentContext pcontext, HtmlRendererContext rcontext, FrameContext frameContext, RenderableContainer parentContainer, int defaultOverflow) { 79 super(parentContainer, modelNode, pcontext); 80 this.listNesting = listNesting; 81 this.frameContext = frameContext; 82 this.rendererContext = rcontext; 83 this.defaultOverflow = defaultOverflow; 84 RBlockViewport bl = new RBlockViewport(modelNode, this, this.getViewportListNesting(listNesting), pcontext, rcontext, frameContext, this); 85 this.bodyLayout = bl; 86 bl.setOriginalParent(this); 87 bl.setX(Short.MAX_VALUE); 90 bl.setY(Short.MAX_VALUE); 91 } 92 93 96 public int getVScrollBarWidth() { 97 return SCROLL_BAR_THICKNESS; 98 } 99 100 public void finalize() throws Throwable { 101 super.finalize(); 102 } 103 104 public int getVAlign() { 105 return VALIGN_BASELINE; 107 } 108 109 public void ensureVisible(Point point) { 110 RBlockViewport bodyLayout = this.bodyLayout; 111 if(bodyLayout != null) { 112 boolean hscroll = this.hasHScrollBar; 113 boolean vscroll = this.hasVScrollBar; 114 int origX = bodyLayout.x; 115 int origY = bodyLayout.y; 116 Insets insets = this.getInsets(hscroll, vscroll); 117 if(hscroll) { 118 if(point.x < insets.left) { 119 bodyLayout.x += (insets.left - point.x); 120 } 121 else if(point.x > this.width - insets.right) { 122 bodyLayout.x -= (point.x - this.width + insets.right); 123 } 124 } 125 if(vscroll) { 126 if(point.y < insets.top) { 127 bodyLayout.y += (insets.top - point.y); 128 } 129 else if(point.y > this.height - insets.bottom) { 130 bodyLayout.y -= (point.y - this.height + insets.bottom); 131 } 132 } 133 if(hscroll || vscroll) { 134 this.correctViewportOrigin(insets, this.width, this.height); 135 if(origX != bodyLayout.x || origY != bodyLayout.y) { 136 this.resetScrollBars(null); 137 this.repaint(); 139 } 140 } 141 } 142 } 143 144 private JScrollBar getHScrollBar() { 145 JScrollBar sb = this.hScrollBar; 146 if(sb == null) { 147 sb = new JScrollBar(JScrollBar.HORIZONTAL); 149 sb.addAdjustmentListener(new LocalAdjustmentListener(JScrollBar.HORIZONTAL)); 150 this.hScrollBar = sb; 151 } 152 return sb; 153 } 154 155 private JScrollBar getVScrollBar() { 156 JScrollBar sb = this.vScrollBar; 157 if(sb == null) { 158 sb = new JScrollBar(JScrollBar.VERTICAL); 160 sb.addAdjustmentListener(new LocalAdjustmentListener(JScrollBar.VERTICAL)); 161 this.vScrollBar = sb; 162 } 163 return sb; 164 } 165 166 public final boolean couldBeScrollable() { 167 int overflow = this.getOverflow(); 168 return overflow != OVERFLOW_NONE && (overflow == OVERFLOW_SCROLL || overflow == OVERFLOW_VERTICAL || overflow == OVERFLOW_AUTO); 169 } 170 171 private Insets defaultPaddingInsets = null; 172 173 public void setDefaultPaddingInsets(Insets insets) { 174 this.defaultPaddingInsets = insets; 175 } 176 177 public void setDefaultMarginInsets(Insets insets) { 178 this.defaultMarginInsets = insets; 179 } 180 181 public int getFirstLineHeight() { 182 return this.bodyLayout.getFirstLineHeight(); 183 } 184 185 public void setSelectionEnd(RenderableSpot rpoint) { 186 this.endSelection = rpoint; 187 } 188 189 public void setSelectionStart(RenderableSpot rpoint) { 190 this.startSelection = rpoint; 191 } 192 193 protected final Insets getPaddingInsets(RenderState rs) { 194 Insets mi = rs.getPaddingInsets(); 195 if(mi == null) { 196 return this.defaultPaddingInsets; 197 } 198 return mi; 199 } 200 201 public int getViewportListNesting(int blockNesting) { 202 return blockNesting; 203 } 204 205 public void paint(Graphics g) { 206 boolean linfo = loggableInfo; 207 long time1 = linfo ? System.currentTimeMillis() : 0; 208 this.prePaint(g); 209 long time2 = linfo ? System.currentTimeMillis() : 0; 210 long time3 = 0; 211 try { 212 Insets insets = this.getInsets(this.hasHScrollBar, this.hasVScrollBar); 213 RBlockViewport bodyLayout = this.bodyLayout; 214 if(bodyLayout != null) { 215 int overflow = this.getOverflow(); 216 if(overflow == OVERFLOW_NONE || overflow == OVERFLOW_VISIBLE) { 217 int bx = bodyLayout.x; 219 int by = bodyLayout.y; 220 g.translate(bx, by); 221 try { 222 bodyLayout.paint(g); 223 } finally { 224 g.translate(-bx, -by); 225 } 226 } 227 else { 228 Graphics newG = g.create(insets.left, insets.top, this.width - insets.left - insets.right, this.height - insets.top - insets.bottom); 230 try { 231 newG.translate(bodyLayout.x - insets.left, bodyLayout.y - insets.top); 233 bodyLayout.paint(newG); 235 } finally { 236 newG.dispose(); 237 } 238 } 239 240 if(linfo) { 241 time3 = System.currentTimeMillis(); 242 } 243 } else { 244 } 246 247 250 RenderableSpot start = this.startSelection; 251 RenderableSpot end = this.endSelection; 252 boolean inSelection = false; 253 if(start != null && end != null && !start.equals(end)) { 254 this.paintSelection(g, inSelection, start, end); 255 } 256 JScrollBar hsb = this.hScrollBar; 258 if(hsb != null) { 259 Graphics sbg = g.create(insets.left, this.height - insets.bottom, this.width - insets.left - insets.right, SCROLL_BAR_THICKNESS); 260 try { 261 hsb.paint(sbg); 262 } finally { 263 sbg.dispose(); 264 } 265 } 266 JScrollBar vsb = this.vScrollBar; 267 if(vsb != null) { 268 Graphics sbg = g.create(this.width - insets.right, insets.top, SCROLL_BAR_THICKNESS, this.height - insets.top - insets.bottom); 269 try { 270 vsb.paint(sbg); 271 } finally { 272 sbg.dispose(); 273 } 274 } 275 276 } finally { 277 super.paint(g); 279 } 280 if(linfo) { 281 long time4 = System.currentTimeMillis(); 282 if(time4 - time1 > 100) { 283 logger.info("paint(): Elapsed: " + (time4 - time1) + " ms. Prepaint: " + (time2 - time1) + " ms. Viewport: " + (time3 - time2) + " ms. RBlock: " + this + "."); 284 } 285 } 286 } 287 288 292 protected Dimension doCellLayout(int width, int height, boolean expandWidth, boolean expandHeight) { 293 try { 294 this.doLayout(width, height, expandWidth, expandHeight); 295 return new Dimension(this.width, this.height); 296 } finally { 297 this.layoutUpTreeCanBeInvalidated = true; 298 } 299 } 300 301 public final void layout(int availWidth, int availHeight, boolean expandWidth, boolean expandHeight, int defaultOverflow) { 302 this.layout(availWidth, availHeight, expandWidth, expandHeight, null, 0, defaultOverflow); 303 } 304 305 public final void layout(int availWidth, int availHeight, boolean expandWidth, boolean expandHeight, FloatingBounds floatBounds, int tentativeY) { 306 this.layout(availWidth, availHeight, expandWidth, expandHeight, floatBounds, tentativeY, this.defaultOverflow); 307 } 308 309 public final void layout(int availWidth, int availHeight, boolean expandWidth, boolean expandHeight, FloatingBounds floatBounds, int tentativeY, int defaultOverflow) { 310 try { 311 this.doLayout(availWidth, availHeight, expandWidth, expandHeight, floatBounds, tentativeY, defaultOverflow); 312 } finally { 313 this.layoutUpTreeCanBeInvalidated = true; 314 this.layoutDeepCanBeInvalidated = true; 315 } 317 } 318 319 public final void doLayout(int availWidth, int availHeight, boolean expandWidth, boolean expandHeight) { 320 this.doLayout(availWidth, availHeight, expandWidth, expandHeight, null, 0, this.defaultOverflow); 321 } 322 323 public final void doLayout(int availWidth, int availHeight, boolean expandWidth, boolean expandHeight, int tentativeY) { 324 this.doLayout(availWidth, availHeight, expandWidth, expandHeight, null, tentativeY, this.defaultOverflow); 325 } 326 327 334 public void doLayout(int availWidth, int availHeight, boolean expandWidth, boolean expandHeight, FloatingBounds floatBounds, int tentativeY, int defaultOverflow) { 335 int prevAvailWidth = this.lastAvailWidth; 337 int prevAvailHeight = this.lastAvailHeight; 338 RenderState renderState = this.modelNode.getRenderState(); 339 boolean forced = availHeight != prevAvailHeight || availWidth != prevAvailWidth || !Boolean.valueOf(expandWidth).equals(this.lastExpandWidth) || !Boolean.valueOf(expandHeight).equals(this.lastExpandHeight); 340 if(!forced) { 341 if(renderState != null) { 342 Font font = renderState.getFont(); 343 if(!font.equals(this.lastFont)) { 344 forced = true; 345 } 346 else { 347 int newWhiteSpace = renderState.getWhiteSpace(); 348 if(newWhiteSpace != this.lastWhiteSpace) { 349 forced = true; 350 } 351 } 352 } 353 if(!forced) { 354 if(this.lastFloatBounds == INVALID_FLOAT_BOUNDS) { 355 forced = true; 356 } 357 else { 358 forced = !Objects.equals(this.lastFloatBounds, floatBounds); 359 } 360 } 361 } 362 if(forced) { 363 this.forceLayout(renderState, availWidth, availHeight, expandWidth, expandHeight, floatBounds, tentativeY, defaultOverflow); 364 } 365 else { 366 } 368 369 392 this.sendGUIComponentsToParent(); 395 396 this.sendDelayedPairsToParent(); 399 } 400 401 private final boolean correctViewportOrigin(Insets insets, int blockWidth, int blockHeight) { 402 RBlockViewport bodyLayout = this.bodyLayout; 403 int viewPortX = bodyLayout.x; 404 int viewPortY = bodyLayout.y; 405 boolean corrected = false; 406 if(viewPortX > insets.left) { 407 bodyLayout.x = insets.left; 408 corrected = true; 409 } 410 else if(viewPortX < blockWidth - insets.right - bodyLayout.width) { 411 bodyLayout.x = Math.min(insets.left, blockWidth - insets.right - bodyLayout.width); 412 corrected = true; 413 } 414 if(viewPortY > insets.top) { 415 bodyLayout.y = insets.top; 416 corrected = true; 417 } 418 else if(viewPortY < blockHeight - insets.bottom - bodyLayout.height) { 419 bodyLayout.y = Math.min(insets.top, blockHeight - insets.bottom - bodyLayout.height); 420 corrected = true; 421 } 422 return corrected; 423 } 424 425 431 private final void forceLayout(RenderState renderState, int availWidth, int availHeight, boolean expandWidth, boolean expandHeight, FloatingBounds floatBounds, int tentativeY, int defaultOverflow) { 432 RenderState rs = renderState; 435 if(rs == null) { 436 rs = new BlockRenderState(null, null); 437 } 438 if(this.lastAvailWidth == -1) { 439 rs.invalidate(); 441 this.applyStyle(); 442 } 443 444 int dw = this.getDeclaredWidth(rs, availWidth); 445 int dh = this.getDeclaredHeight(rs, availHeight); 446 this.lastExpandHeight = Boolean.valueOf(expandHeight); 447 this.lastExpandWidth = Boolean.valueOf(expandWidth); 448 Font newFont = rs.getFont(); 449 this.lastFont = newFont; 450 this.lastAvailHeight = availHeight; 451 this.lastAvailWidth = availWidth; 452 this.lastFloatBounds = floatBounds; 453 this.lastWhiteSpace = rs.getWhiteSpace(); 454 455 RBlockViewport bodyLayout = this.bodyLayout; 456 NodeImpl node = (NodeImpl) this.modelNode; 457 if(node == null || bodyLayout == null) { 458 Insets insets = this.getInsets(false, false); 459 this.width = insets.left + insets.right; 460 this.height = insets.bottom + insets.top; 461 this.hasHScrollBar = false; 462 this.hasVScrollBar = false; 463 return; 464 } 465 466 this.clearGUIComponents(); 469 470 int tentativeWidth; 471 int tentativeHeight; 472 if(dw != -1 || dh != -1) { 474 Insets marginInsets = this.getMarginInsets(rs); 475 if(marginInsets != null) { 476 dw = dw == -1 ? -1 : dw + marginInsets.left + marginInsets.right; 478 dh = dh == -1 ? -1 : dh + marginInsets.top + marginInsets.bottom; 479 } 480 } 481 tentativeWidth = dw == -1 ? availWidth : dw; 482 tentativeHeight = dh == -1 ? availHeight : dh; 483 int overflow = this.getOverflow(); 484 if(overflow == OVERFLOW_NONE) { 485 overflow = defaultOverflow; 486 } 487 boolean vertical = overflow == OVERFLOW_VERTICAL; 488 boolean auto = vertical || overflow == OVERFLOW_AUTO; 489 boolean bothScrollBars = overflow == OVERFLOW_SCROLL; 490 boolean hscroll = bothScrollBars; 491 boolean vscroll = bothScrollBars || vertical; 492 boolean mayScroll = auto || bothScrollBars || vertical; 493 Insets paddingInsets = this.getPaddingInsets(rs); 494 if(paddingInsets == null) { 495 paddingInsets = RBlockViewport.ZERO_INSETS; 496 } 497 Insets insets = null; 498 for(int tries = ((auto && !vscroll) ? 0 : 1); tries < 2; tries++) { 499 try { 500 insets = this.getInsets(hscroll, vscroll); 501 int maxY = tries == 0 ? (dh == -1 ? -1 : dh - insets.bottom - insets.top - paddingInsets.bottom) : -1; 502 int desiredViewportWidth = tentativeWidth - insets.left - insets.right; 503 int desiredViewportHeight = tentativeHeight - insets.top - insets.bottom; 504 bodyLayout.layout(desiredViewportWidth, desiredViewportHeight, paddingInsets, node, maxY, floatBounds); 505 break; 506 } catch(SizeExceededException hee) { 507 if(tries != 0) { 508 throw new IllegalStateException ("tries=" + tries + ",auto=" + auto); 509 } 510 vscroll = true; 511 } 512 } 513 this.hasVScrollBar = vscroll; 514 Dimension size = bodyLayout.getSize(); 515 Dimension rblockSize = new Dimension(size.width + insets.left + insets.right, size.height + insets.top + insets.bottom); 516 if(auto && !hscroll && ((dw != -1 && rblockSize.width > dw) || (rblockSize.width > availWidth))) { 517 hscroll = true; 518 insets = this.getInsets(hscroll, vscroll); 519 rblockSize = new Dimension(size.width + insets.left + insets.right, size.height + insets.top + insets.bottom); 520 } 521 this.hasHScrollBar = hscroll; 522 boolean visible = !auto && !bothScrollBars && (overflow != OVERFLOW_HIDDEN); 523 int resultingWidth; 524 int resultingHeight; 525 if(dw == -1) { 526 resultingWidth = rblockSize.width; 527 if(expandWidth && resultingWidth < availWidth) { 528 resultingWidth = availWidth; 529 } 530 else if(hscroll && resultingWidth > availWidth) { 531 resultingWidth = Math.max(availWidth, SCROLL_BAR_THICKNESS); 532 } 533 } 534 else { 535 resultingWidth = visible ? Math.max(rblockSize.width, dw) : dw; 536 } 537 if(dh == -1) { 538 resultingHeight = rblockSize.height; 539 if(expandHeight && resultingHeight < availHeight) { 540 resultingHeight = availHeight; 541 } 542 else if(vscroll && resultingHeight > availHeight) { 543 resultingHeight = Math.max(availHeight, SCROLL_BAR_THICKNESS); 544 } 545 } 546 else { 547 resultingHeight = visible ? Math.max(rblockSize.height, dh) : dh; 548 } 549 if(vscroll) { 550 JScrollBar sb = this.getVScrollBar(); 551 this.add(sb); 552 } 554 if(hscroll) { 555 JScrollBar sb = this.getHScrollBar(); 556 this.add(sb); 557 } 559 560 this.width = resultingWidth; 561 this.height = resultingHeight; 562 563 int alignmentXPercent = rs.getAlignXPercent(); 565 int alignmentYPercent = rs.getAlignYPercent(); 566 if(alignmentXPercent > 0 || alignmentYPercent > 0) { 567 int canvasWidth = Math.max(bodyLayout.width, resultingWidth - insets.left - insets.right); 569 int canvasHeight = Math.max(bodyLayout.height, resultingHeight - insets.top - insets.bottom); 570 bodyLayout.align(alignmentXPercent, alignmentYPercent, canvasWidth, canvasHeight, paddingInsets); 571 } 572 if(hscroll || vscroll) { 573 this.correctViewportOrigin(insets, resultingWidth, resultingHeight); 577 this.resetScrollBars(rs); 579 } 580 else { 581 bodyLayout.x = insets.left; 582 bodyLayout.y = insets.top; 583 } 584 } 585 586 private int getVUnitIncrement(RenderState renderState) { 587 if(renderState != null) { 588 return renderState.getFontMetrics().getHeight(); 589 } 590 else { 591 return new BlockRenderState(null, null).getFontMetrics().getHeight(); 592 } 593 } 594 595 private boolean resettingScrollBars = false; 596 597 600 private void resetScrollBars(RenderState renderState) { 601 this.resettingScrollBars = true; 603 try { 604 RBlockViewport bodyLayout = this.bodyLayout; 605 if(bodyLayout != null) { 606 Insets insets = this.getInsets(this.hasHScrollBar, this.hasVScrollBar); 607 JScrollBar vsb = this.vScrollBar; 608 if(vsb != null) { 609 int newValue = insets.top - bodyLayout.y; 610 int newExtent = this.height - insets.top - insets.bottom; 611 int newMin = 0; 612 int newMax = bodyLayout.height; 613 vsb.setValues(newValue, newExtent, newMin, newMax); 614 vsb.setUnitIncrement(this.getVUnitIncrement(renderState)); 615 vsb.setBlockIncrement(newExtent); 616 } 617 JScrollBar hsb = this.hScrollBar; 618 if(hsb != null) { 619 int newValue = insets.left - bodyLayout.x; 620 int newExtent = this.width - insets.left - insets.right; 621 int newMin = 0; 622 int newMax = bodyLayout.width; 623 hsb.setValues(newValue, newExtent, newMin, newMax); 624 } 625 } 626 } finally { 627 this.resettingScrollBars = false; 628 } 629 } 630 631 634 public boolean paintSelection(Graphics g, boolean inSelection, RenderableSpot startPoint, RenderableSpot endPoint) { 635 Graphics newG = g.create(); 636 try { 637 Insets insets = this.getInsets(this.hasHScrollBar, this.hasVScrollBar); 638 newG.clipRect(insets.left, insets.top, this.width - insets.left - insets.right, this.height - insets.top - insets.bottom); 640 return super.paintSelection(newG, inSelection, startPoint, endPoint); 641 } finally { 642 newG.dispose(); 643 } 644 } 680 681 684 public RenderableSpot getLowestRenderableSpot(int x, int y) { 685 RBlockViewport bodyLayout = this.bodyLayout; 686 if(bodyLayout != null) { 687 Insets insets = this.getInsets(this.hasHScrollBar, this.hasVScrollBar); 688 if(x > insets.left && x < this.width - insets.right && y > insets.top && y < this.height - insets.bottom) { 689 return bodyLayout.getLowestRenderableSpot(x - bodyLayout.x, y - bodyLayout.y); 690 } 691 else { 692 return new RenderableSpot(this, x, y); 693 } 694 } 695 else { 696 return new RenderableSpot(this, x, y); 697 } 698 } 699 700 706 public void invalidateLayoutLocal() { 707 super.invalidateLayoutLocal(); 708 this.lastAvailHeight = -1; 709 this.lastAvailWidth = -1; 710 this.lastWhiteSpace = -1; 711 this.lastExpandHeight = null; 712 this.lastExpandWidth = null; 713 this.lastFloatBounds = INVALID_FLOAT_BOUNDS; 714 } 715 716 719 public boolean onMouseClick(MouseEvent event, int x, int y) { 720 RBlockViewport bodyLayout = this.bodyLayout; 721 if(bodyLayout != null) { 722 if(!bodyLayout.onMouseClick(event, x - bodyLayout.x, y - bodyLayout.y)) { 723 return false; 724 } 725 } 726 if(!HtmlController.getInstance().onMouseClick(this.modelNode, event, x, y)) { 727 return false; 728 } 729 if(this.backgroundColor != null) { 730 return false; 731 } 732 return true; 733 } 734 735 public boolean onDoubleClick(MouseEvent event, int x, int y) { 736 RBlockViewport bodyLayout = this.bodyLayout; 737 if(bodyLayout != null) { 738 if(!bodyLayout.onDoubleClick(event, x - bodyLayout.x, y - bodyLayout.y)) { 739 return false; 740 } 741 } 742 if(this.backgroundColor != null) { 743 return false; 744 } 745 return true; 746 } 747 748 751 public boolean onMouseDisarmed(MouseEvent event) { 752 BoundableRenderable br = this.armedRenderable; 753 if(br != null) { 754 try { 755 return br.onMouseDisarmed(event); 756 } finally { 757 this.armedRenderable = null; 758 } 759 } 760 else { 761 return true; 762 } 763 } 764 765 private BoundableRenderable armedRenderable; 766 767 770 public boolean onMousePressed(MouseEvent event, int x, int y) { 771 RBlockViewport bodyLayout = this.bodyLayout; 772 if(bodyLayout != null) { 773 int newX = x - bodyLayout.x; 774 int newY = y - bodyLayout.y; 775 if(bodyLayout.contains(newX, newY)) { 776 this.armedRenderable = bodyLayout; 777 if(!bodyLayout.onMousePressed(event, newX, newY)) { 778 return false; 779 } 780 } 781 else { 782 this.armedRenderable = null; 783 } 784 } 785 else { 786 this.armedRenderable = null; 787 } 788 if(!HtmlController.getInstance().onMouseDown(this.modelNode, event, x, y)) { 789 return false; 790 } 791 if(this.backgroundColor != null) { 792 return false; 793 } 794 return true; 795 } 796 797 800 public boolean onMouseReleased(MouseEvent event, int x, int y) { 801 RBlockViewport bodyLayout = this.bodyLayout; 802 if(bodyLayout != null) { 803 int newX = x - bodyLayout.x; 804 int newY = y - bodyLayout.y; 805 if(bodyLayout.contains(newX, newY)) { 806 this.armedRenderable = null; 807 if(!bodyLayout.onMouseReleased(event, newX, newY)) { 808 return false; 809 } 810 } 811 else { 812 BoundableRenderable br = this.armedRenderable; 813 if(br != null) { 814 br.onMouseDisarmed(event); 815 } 816 } 817 } 818 if(!HtmlController.getInstance().onMouseUp(this.modelNode, event, x, y)) { 819 return false; 820 } 821 if(this.backgroundColor != null) { 822 return false; 823 } 824 return true; 825 } 826 827 public Color getPaintedBackgroundColor() { 828 return this.backgroundColor; 829 } 830 831 834 public Iterator getRenderables() { 835 final RBlockViewport bodyLayout = this.bodyLayout; 836 return new Iterator() { 837 private RBlockViewport bl = bodyLayout; 838 839 public boolean hasNext() { 840 return bl != null; 841 } 842 843 public Object next() { 844 if(bl == null) { 845 throw new NoSuchElementException(); 846 } 847 try { 848 return bl; 849 } finally { 850 bl = null; 851 } 852 } 853 854 public void remove() { 855 throw new UnsupportedOperationException (); 856 } 857 }; 858 } 859 860 863 public void repaint(ModelNode modelNode) { 864 this.repaint(); 866 } 867 868 879 public void updateWidgetBounds(int guiX, int guiY) { 880 super.updateWidgetBounds(guiX, guiY); 881 boolean hscroll = this.hasHScrollBar; 882 boolean vscroll = this.hasVScrollBar; 883 if(hscroll || vscroll) { 884 Insets insets = this.getInsets(hscroll, vscroll); 885 if(hscroll) { 886 JScrollBar hsb = this.hScrollBar; 887 if(hsb != null) { 888 hsb.setBounds(guiX + insets.left, guiY + this.height - insets.bottom, this.width - insets.left - insets.right, SCROLL_BAR_THICKNESS); 889 } 890 } 891 if(vscroll) { 892 JScrollBar vsb = this.vScrollBar; 893 if(vsb != null) { 894 vsb.setBounds(guiX + this.width - insets.right, guiY + insets.top, SCROLL_BAR_THICKNESS, this.height - insets.top - insets.bottom); 895 } 896 } 897 } 898 } 899 900 public void scrollHorizontalTo(int newX) { 901 RBlockViewport bodyLayout = this.bodyLayout; 902 if(bodyLayout != null) { 903 Insets insets = this.getInsets(this.hasHScrollBar, this.hasVScrollBar); 904 int viewPortX = newX; 905 if(viewPortX > insets.left) { 906 bodyLayout.x = insets.left; 907 } 908 else if(viewPortX < this.width - insets.right - bodyLayout.width) { 909 bodyLayout.x = Math.min(insets.left, this.width - insets.right - bodyLayout.width); 910 } 911 else { 912 bodyLayout.x = viewPortX; 913 } 914 this.resetScrollBars(null); 915 this.updateWidgetBounds(); 916 this.repaint(); 917 } 918 } 919 920 public void scrollVerticalTo(int newY) { 921 RBlockViewport bodyLayout = this.bodyLayout; 922 if(bodyLayout != null) { 923 Insets insets = this.getInsets(this.hasHScrollBar, this.hasVScrollBar); 924 int viewPortY = newY; 925 if(viewPortY > insets.top) { 926 bodyLayout.y = insets.top; 927 } 928 else if(viewPortY < this.height - insets.bottom - bodyLayout.height) { 929 bodyLayout.y = Math.min(insets.top, this.height - insets.bottom - bodyLayout.height); 930 } 931 else { 932 bodyLayout.y = viewPortY; 933 } 934 this.resetScrollBars(null); 935 this.updateWidgetBounds(); 936 this.repaint(); 937 } 938 } 939 940 public void scrollByUnits(int orientation, int units) { 941 int offset = orientation == JScrollBar.VERTICAL ? this.getVUnitIncrement(null) * units : units; 942 this.scrollBy(orientation, offset); 943 } 944 945 public void scrollBy(int orientation, int offset) { 946 RBlockViewport bodyLayout = this.bodyLayout; 947 if(bodyLayout != null) { 948 switch(orientation) { 949 case JScrollBar.HORIZONTAL: 950 this.scrollHorizontalTo(bodyLayout.x - offset); 951 break; 952 case JScrollBar.VERTICAL: 953 this.scrollVerticalTo(bodyLayout.y - offset); 954 break; 955 } 956 } 957 } 958 959 private void scrollToSBValue(int orientation, int value) { 960 Insets insets = this.getInsets(this.hasHScrollBar, this.hasVScrollBar); 961 switch(orientation) { 962 case JScrollBar.HORIZONTAL: 963 int xOrigin = insets.left - value; 964 this.scrollHorizontalTo(xOrigin); 965 break; 966 case JScrollBar.VERTICAL: 967 int yOrigin = insets.top - value; 968 this.scrollVerticalTo(yOrigin); 969 break; 970 } 971 } 972 973 public RBlockViewport getRBlockViewport() { 979 return this.bodyLayout; 980 } 981 982 public String toString() { 983 return "RBlock[node=" + this.modelNode + "]"; 984 } 985 986 private class LocalAdjustmentListener implements AdjustmentListener { 987 private final int orientation; 988 989 public LocalAdjustmentListener(int orientation) { 990 this.orientation = orientation; 991 } 992 993 public void adjustmentValueChanged(AdjustmentEvent e) { 994 if(RBlock.this.resettingScrollBars) { 995 return; 996 } 997 switch(e.getAdjustmentType()) { 998 case AdjustmentEvent.UNIT_INCREMENT: 999 case AdjustmentEvent.UNIT_DECREMENT: 1001 case AdjustmentEvent.BLOCK_INCREMENT: 1003 case AdjustmentEvent.BLOCK_DECREMENT: 1005 case AdjustmentEvent.TRACK: { 1007 int value = e.getValue(); 1008 RBlock.this.scrollToSBValue(this.orientation, value); 1009 break; 1010 } 1011 } 1012 } 1013 } 1014 1015 private static class BodyFilter implements NodeFilter { 1016 public boolean accept(Node node) { 1017 return node instanceof org.w3c.dom.html2.HTMLBodyElement; 1018 } 1019 } 1020} | Popular Tags |