Note: The mercurial server is disabled at the moment while I investigate whether it can run with an acceptably low CPU load – Mike.
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!
Graphics interfaces
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
and Stylus
Native.Image
The interface 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 getWidth()
int getHeight()
int getRGB(int x, int y)
– returns a pixel as a 24-bit RGB valuevoid setRGB(int x, int y, int rgb)
– sets a pixel to a given RGB valueObject getNative()
– returns the underlyingBufferedImage
object
Native
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 AWTImage
.
Image image(int w, int h)
– create a blank imageImage render(Drawable pic, int w, int h, double slider, ColorValue background)
– create an image by rendering the picturepic
. Typically , this is implemented by creating a native image (aBufferedImage
for AWT) of sizew
byh
, creating aStylus
objects
for painting on it, then callingpic.draw(s, slider, background)
and finally wrapping the image as aNative.Image
. For AWT, the styluss
is created as an instance ofScreenStylus
(see below).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 theImageIO
library.)
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
new java.awt.Color(c.rgb)
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 null
).)
Stylus
A 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
Minimal requirements:
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.
Stylus.Sketch
A Sketch
is a picture that knows how to draw itself using a stylus.
(To be continued)