CS456 Draw Tree
Program - Draw Tree
goal
Get up to speed with drawing in Java. Build a basic draw tree implementation that we can build upon in our later projects.
Application
You should use Java's JFrame to create a single window application. When the application runs it should have a File menu (Use JMenuBar and JMenu create this). It will have a single menu item "Open..." When clicked this will open a file chooser dialog (JFileChooser will work) that only shows .draw files. A .draw file is in SON format and contains only objects that implement Drawable (see below). You can read such files using the spark.io.SONReader class.

Inside of your JFrame, you should have a JPanel as the content pane. Your subclass of JPanel should call paint() on the currently loaded Drawable objects. This will paint graphics into the application window.

Drawable
You should create a Java interface called Drawable that contains only the method "void paint(Graphics g)". All of the SON-compatible objects described below should implement this interface.

Using this method your panel can paint the objects that implement the Drawable interface.

Colors
Many of your Drawable objects have color attributes. Colors are always specified as a simple object { r:100, g:255, b: 10 }. Color values for each of r,g and b vary between 0 and 255.
Drawable objects
These objects should all be subclasses of spark.data.SOReflect. That will make them loadable in SON format. This should also implement Drawable.

The objects that you must implement are:

  • Group{ contents:[ ... ], sx:1.0, sy:1.0, rotate:0.0, tx:0.0, ty:0.0 } A Group object contains "contents" which is an SArray of Drawable objects. When it's paint method is called it simply iterates through all of the contents array and calls paint on each of them. This allows us to organize our drawings into trees.

    The Group object also applies a scale, rotate, translate transform to its contents. The defaults are as shown above, which will do nothing. Rotation is expressed in degrees counter clockwise. Be sure to apply your transformations in the correct order (scale, rotate, translate). Note that groups can contain groups so you will need to build up the transformations.

  • Line{ x1:10, y1:5, x2: 20, y2:40, thickness:3, color:{r:0,g:0,b:0} } This will draw a black line (color) 3 pixels wide (thickness) from the point (10,5) to (20,40).
  • Rect{ left:0, top:100, width:10, height:10, thickness:2, border:{r:0,g:0,b:0}, fill:{r:0,g:0,b:128} } This will draw a rectangle. If there is no fill color then the rectangle is not filled. If there is no border color then no border is drawn.
  • Ellipse{ same as Rect } Draws an ellipse using the same attributes as Rect.
  • Text{ text:"Draw This", x:10,y:100, font:"Times", size:10 } Draws a string of text (text:) with the left baseline at (10,100) using "Time" font with a point size of 10. In addition to the named fonts that are available in Java this should also support the names "serif" and "sans-serif" to select the corresponding standard fonts.
  • Polyline{ points:[ {x:10,y:10}, ... ], thickness:1, color:{r:100,g:0,b:0} } This will draw a polyline through the points specified in the points array with the specified thickness and color.
  • Polygon{ points: [ {x:0,y:0}, . . .], thickness:1, border:{r:100,g:0,b:0}, fill:{r:255,g:255,b:255} } Draw a polygon using thickness, border and fill in the same manner as Rect.
example file
	Group{ contents: [
		Line{ x1:10, y1:20, x2:20, y2:40, thickness:4, color: {r:0,g:0,b:0} },
		Rect{ left:10, top:50, width:100, height:10, fill:{r:100,g:100,b:100} }
		], rotate: 90.0, sx:0.5, sy:0.5, tx:0, ty:300
	}
hint
Put all of your drawable classes in the same package and use that package name to set up your SONReader class. This will allow you to use simple class names in your SON files.
grading
This program is 0 or 10. No partial credit. Late points will be deducted from the final grade, but this either works or it doesn't. You will need this to work completely for the rest of the assignments.
test 1
Group{ contents:[
		Line{x1:10,y1:20,x2:30, y2:40, thickness:3, color:{r:255,g:255,b:0} },
		Rect{ left:5,top:10,width:30, height:50, thickness:1, border:{r:0,g:0,b:0} },
		Rect{ left:30,top:30,width:30, height:50, thickness:1, 
			border:{r:0,g:0,b:0}, fill:{r:100,g:100,b:200} },
		Ellipse{ left:5,top:70,width:30, height:50, thickness:1, border:{r:0,g:0,b:0} },
		Ellipse{ left:30,top:90,width:30, height:50, thickness:1, 
			border:{r:0,g:0,b:0}, fill:{r:100,g:100,b:200} },
		Text{ text:"Hello", x:5,y:180,font:"sans-serif",size:10 },
		Polyline{ points:[ {x:40,y:10}, {x:50,y:20}, {x:60,y:10} ],
			thickness:4, color:{r:100,g:255,b:100} },
		Polygon{ points:[ {x:5,y:220}, {x:35,y:220}, {x:20,y:250} ],
			thickness:2, border:{r:0,g:0,b:0}, fill:{r:200,g:200,b:255} }
	]
}
test 2
Group{ contents:[
		Line{x1:10,y1:20,x2:30, y2:40, thickness:3, color:{r:255,g:255,b:0} },
		Rect{ left:5,top:10,width:30, height:50, thickness:1, border:{r:0,g:0,b:0} },
		Rect{ left:30,top:30,width:30, height:50, thickness:1, 
			border:{r:0,g:0,b:0}, fill:{r:100,g:100,b:200} },
		Ellipse{ left:5,top:70,width:30, height:50, thickness:1, border:{r:0,g:0,b:0} },
		Ellipse{ left:30,top:90,width:30, height:50, thickness:1, 
			border:{r:0,g:0,b:0}, fill:{r:100,g:100,b:200} },
		Text{ text:"Hello", x:5,y:180,font:"sans-serif",size:10 },
		Polyline{ points:[ {x:40,y:10}, {x:50,y:20}, {x:60,y:10} ],
			thickness:4, color:{r:100,g:255,b:100} },
		Polygon{ points:[ {x:5,y:220}, {x:35,y:220}, {x:20,y:250} ],
			thickness:2, border:{r:0,g:0,b:0}, fill:{r:200,g:200,b:255} },
		Rect{ left:0,top:0,width:4,height:2, fill:{r:255, g:200,b:200} }
	],
	sx:1.0, sy:2.0, tx:400, ty:500, rotate:45
}
test 3
Group{ contents:[
		Line{x1:10,y1:20,x2:30, y2:40, thickness:3, color:{r:255,g:255,b:0} },
		Rect{ left:5,top:10,width:30, height:50, thickness:1, border:{r:0,g:0,b:0} },
		Rect{ left:30,top:30,width:30, height:50, thickness:1, 
			border:{r:0,g:0,b:0}, fill:{r:100,g:100,b:200} },
		Ellipse{ left:5,top:70,width:30, height:50, thickness:1, border:{r:0,g:0,b:0} },
		Ellipse{ left:30,top:90,width:30, height:50, thickness:1, 
			border:{r:0,g:0,b:0}, fill:{r:100,g:100,b:200} },
		Text{ text:"Hello", x:5,y:180,font:"sans-serif",size:10 },
		Polyline{ points:[ {x:40,y:10}, {x:50,y:20}, {x:60,y:10} ],
			thickness:4, color:{r:100,g:255,b:100} },
		Polygon{ points:[ {x:5,y:220}, {x:35,y:220}, {x:20,y:250} ],
			thickness:2, border:{r:0,g:0,b:0}, fill:{r:200,g:200,b:255} },
		Group{ contents:[
			Rect{ left:0,top:0,width:40,height:20, fill:{r:255, g:200,b:200} }
			],
			sx:0.5,sy:4.0, rotate:45
			}
	],
	sx:1.0, sy:2.0, tx:400, ty:500, rotate:45
}