I renamed FigureCanvas to JCanvas, and made it a subclass of JComponent (the Swing root class). The internal architecture of the canvas is now more complicated, in order to provide Swing compatibility but keep performance "high."
The new internal architecture of the canvas has the JCanvas containing a CanvasPane, which in turn contains CanvasLayers. Each layer is assigned to an index within a canvas pane, thus giving clients a simple way of rearranging layers. Layer indices don't have to be continguous. Lower-numbered layers are drawn on top of higher-numbered layers.Note: this revision has been superseded as a result of a subsequent re-review.
Now that JCanvas inherits from JComponent, it also inherits the isDoubleBuffered and setDoubleBuffered methods. (It doesn't need to override them.)
There's a description at the start of the specification.
I removed it.
Redrew the class diagram (see next item)
Drew two class diagrams -- one for canvas, panes, and layers, and one for figures and associated classes.
I can't think of any better ones, really. Container is used in AWT, so FigureContainer seems reasonable. I renamed Layer to CanvasLayer in the hope that that might be clearer. Swing uses layers in a similar way, so I think the term Layer is consistent with Swing.
I ended up with the following resolution. In the new interface ZList, which abstracts the notion of an ordered list of figures, I added methodsvoid add (int, Figure) int indexOf (Figure) void setIndex (int,Figure)Combined with a well-defined meaning of what indexes mean (lower indexes are drawn above higher indexes, and -1 signifies the end of the list), this allows all of this functionality to be implemented without using awkward method names.
See above.
I resolved this issue by making all figure drawing take place in "logical" coordinates in a canvas layer. Canvas layers can be stacked into canvas panes, and ultimately, the top-level canvas pane is part of a JCanvas -- this is the point where logical coordinates can be mapped to screen coordinates.
Um. I'm not sure I understand this. If it means does the shape of a figure need to be closed, then the answer is no: Java2D will draw whatever shape you specify, closed or not.
Done.
I renamed ShapedFigure to FilledFigure, since that's what it's really about. I decided to keep StrokedFigure as it is, partly because the purpose of the interface is to give the figure a java.awt.Stroke object that draws its outline, and partly because BorderedFigure would be misleading for figures such as lines, which are stroked but do not have a border.
There's a description at the start of the document that we skipped over in the review.
This is an awkward one, since it really should, but java.awt.Graphics2D has hit() for a method with similar purpose, so I elected to leave it as-is (and added a comment to the code).
A similar comment applies to contains(), but since this is in java.awt.Shape, I kept contains(). On examination, it turns out that isContainedBy() is completely unncessary, asfigure.isContainedBy(rect)would be the same asrect.contains(figure.getBounds())So I removed isContainedBy().
The repaint() methods of all classes are now consistent with awt/awing and each other.
Probably not... With the new layered architecture, I need to define a wrapper class that extends Figure and contains a CanvasPane. This will be in the main package, but won't be called Glass.
Comments to:
johnr@eecs.berkeley.edu