<DataType> void paint() { Canvas c = Canvas.get(); CellStamp<DataType> stamp; int y = 0; for (int i = 0; i < model.getRowCount(Section.SCROLLABLE); i++) { RowAddress address = viewport.createAddress(i, Section.SCROLLABLE); @SuppressWarnings("unchecked") DataType datum = (DataType) model.get(address); stamp = stampFactory.getStamp(address, datum); Axis.Span stampSpan = new Axis.Span(Axis.V, y, stamp.getSpan(Axis.V, datum)); if (viewport .getCellPainter() .isRowVisible(stampSpan, RowVisibilityType.ACKNOWLEDGE_PARTIAL)) { // WIP: BG such as highlight needs to paint outside this inset I just pushed c.pushBounds( ListModelPainter.CELL_TEXT_INSET, y, viewport.getBounds().width, stampSpan.span); stamp.paint(c, address, datum); c.popBounds(); } y += stampSpan.span; } }
@Override @SuppressWarnings("unchecked") public void paint() { /** * @JTourBusStop 2, Stack-based properties for java.awt.Graphics, Obtaining the canvas * automatically creates a stack frame: * * <p>Client code need not be concerned about when to create a stack frame for the Canvas. The * only way to get a Canvas instance is by calling Canvas.get(), and this method automatically * creates a stack frame and associates it with the method (if none has yet been associated). */ Canvas c = Canvas.get(); DataType datum = (DataType) model.get(address); CellStamp<DataType> stamp = stampFactory.getStamp(address, datum); /** * @JTourBusStop 3, Stack-based properties for java.awt.Graphics, Changes to the clip bounds * are exclusively narrowing: * * <p>Bounds changes in the Graphics object are absolute, allowing a delegated paint() method * to expand the bounds. This is almost never necessary, and when it occurs, most often it is * by arithmetic error in the client code. Pushing a bounds change to the Canvas exclusively * narrows the clip, so each paint() method need only concern itself with the clip bounds that * are logically meaningful within its context. If any paintable areas were clipped off by a * previous method on the call stack, those areas will remain clipped off no matter what the * current method requests. Here, the clip is set to the scrollable region of the scroll pane, * guaranteeing that no component will accidentally paint on the scroll bars and beyond. * * <p>each bounds frame represents something meaningful about the visual construct; here the * visible area of the scroll pane */ c.pushBounds(viewport.getCellPainter().staticContent.getScrollableBounds()); /** * @JTourBusStop 4, Stack-based properties for java.awt.Graphics, Changes to the clip bounds * occur in logical units to avoid messy arithmetic:: * * <p>The process of cumulative narrowing for clip bounds lends itself naturally to simple * arithmetic, because each set of logical bounds changes can simply be pushed in sequence. In * this sequence of translation and narrowing, the y position is relevant to the cell bounds, * but the x position is not. This requires the y position to be pushed before narrowing and * the x position after, which is easy to do and easy to read in these stack-based semantics. */ c.pushBoundsPosition(0, -viewport.getComponent().yViewport()); c.pushBounds( ListModelPainter.CELL_TEXT_INSET, yTop, viewport.getBounds().width, stamp.getSpan(Axis.V, datum)); c.pushBoundsPosition(-viewport.getComponent().xViewport(), 0); c.pushColor(Color.white); c.g.fillRect(0, 0, viewport.getBounds().width, c.span().height); /** * @JTourBusStop 5, Stack-based properties for java.awt.Graphics, Delegate painting to the * list cell stamp with no risk of context corruption: * * <p>At this point the clip bounds have been set correctly for the cell to be repainted. The * cell stamp is now free to paint the cell according to its best understanding, knowing that * it cannot accidentally paint outside the scrollable area, and that all its Graphics * property change will be popped off the stack on method return. */ stamp.paint(c, address, datum); }