Porting GeomLab to Java FX
At the moment, GeomLab has a GUI built with Swing, and it's high time it was updated to use Java FX instead. This is an implementation project, and will produce software that will actually be used in schools.
- The top-level GUI of GeomLab needs converting from Swing to Java FX. This should basically be a straightforward translation, but there will be many places where Java FX provides opportunities to do a better job.
- The graphical output of GeomLab programs uses a graphics interface that already has multiple implementations (for AWT and for Postscript) and has a high degree of decoupling. It will be interesting to add another implementation into the mix.
- As an added task, the delivery mechanism for GeomLab relies on downloading a JAR file and running it on a pre-installed JRE. It would be great to smooth this process!
The decoupling between the picture-making functions of GeomLab and the platform toolkit replies on two interfaces that are implemented in a platform-dependent way:
Native.Image describes an image that can be accessed as a two-dimensional array of pixels. On AWT,
Native.Image is implemented as by
AWTFactory.AWTImage as a wrapper around an AWT
BufferedImage object with type
TYPE_RGB. There are methods as follows, all with an obvious meaning.
int getRGB(int x, int y)– returns a pixel as a 24-bit RGB value
void setRGB(int x, int y, int rgb)– sets a pixel to a given RGB value
Object getNative()– returns the underlying
The abstract class
Native supports several methods that return
Native.Image objects, each implemented for AWT by creating a
BufferedImage object and wrapping it as an
Image image(int w, int h)– create a blank image
Image render(Drawable pic, int w, int h, double slider, ColorValue background)– create an image by rendering the picture
pic. Typically , this is implemented by creating a native image (a
BufferedImagefor AWT) of size
h, creating a
sfor painting on it, then calling
pic.draw(s, slider, background)and finally wrapping the image as a
Native.Image. For AWT, the stylus
sis created as an instance of
Image readImage(InputStream s) throws IOException– read an image from a file.
void writeImage(Image img, String format, OutputStream s) throws IOException– write an image on a file in a specified format. (Both of these are implemented for AWT using the
Native class also supports a few methods for getting the 'native' counterparts to graphical objects that have an internal representation in GeomLab. There is provision in the classes for the internal representations to cache these native counterparts, so that they are not computed repeatedly for no reason. For example, in GeomLab, there is an internal class
ColorValue whose instances represent colours, and
AWTFactory provides a method
Object color(ColorValue c)
that returns the corresponding instance of
java.awt.Color. This is used by
ColorValue objects to cache and return the corresponding AWT colour when it is needed (e.g., by
ScreenStylus) to do actual drawing. The implementation of
AWTFactory.color(c) is simple: it just returns
There are other methods of
Native for vectors and transforms:
Object vector(Vec2D v)
Object transform(Tran2D t)
Each returns (if needed) a native counterpart to one of GeomLab's internal values. (As it happens, the
ScreenStylus class doesn't need to compute native vectors, so the
vector method raises an error (or returns
Stylus is an object rather like a
Graphics context in AWT – and in fact is implemented for AWT by a wrapper
ScreenStylus around a
Graphics2D object. Some of the methods are specific to GeomLab
void setStroke(double width)– Set the stroke width for future drawing operations.
void drawStroke(Vec2D stroke)– Draw a polygon in black.
void fillOutline(Vec2D outline, ColorValue color)– Fill a polygonal outline.
void drawLine(Vec2D from, Vec2D to, ColorValue color)– Draw a line.
void drawArc(Vec2D centre, double xrad, double yrad, double start, double extent, ColorValue color)– draw a transformed arc.
void fillOval(Vec2D centre, double xrad, double yrad, ColorValue color)– Fill an oval.
void drawImage(Native.Image image)– Draw a raster image.
boolean isTiny(Tran2D t)– Test if the transform t yields negligibly small results.
Sketch is a picture that knows how to draw itself using a stylus.
(To be continued)