Another ASCII art drawing program
Programming Assignment – Part 2
Background
As described in the handout for Part 1, the aim of the assignment is to develop a basic text-based drawingapplication.
In Part 1, you have implemented the classes to represent the drawing window and various shapes. Theseclasses allow us to write programs to create windows, add shape to the windows and to display thedrawing image.
In Part 2, you are to
- Write a method save the specification of the window and its shapes to a text file.
- Write a method to read the specification from the text file to reconstruct the drawing window.
- Write a class to act as a drawing board tool, which allows the user to create a new drawing or readan existing drawing, and to perform various operations on the drawing.
Task 1
(a) In the class Window, implement the following method
void writeSpecToFile(String fileName)
The method saves the specification of the drawing window (as opposed to the display image of thedrawing) in the specified text file.
(b) Write a program, called T1Main.java, to generate a drawing, display it on the screen and save itto a text file called T1Drawing.txt.
The format of the output text file must conform to the specification illustrated by the example below (theHouse For Sale drawing presented in Part 1), minus the comments.
20 30 // number of rows and columns of the drawing window
* // character for border
. // a dot to signal the end of the ‘‘record’’
line // the shape is a line
19 1 29 0 1 // row & column positions of base, length, row increment, column increment
# // display character
.
line
12 5 6 1 0
#
.
circle
10 5 2 // row position of base, column position of base Base, radius
+ // display character
.
rectangle
8 16 11 10 // row position of base, column position of base Base, height, width
= // display character
.
rectangle
11 19 8 4
=
.
triangle
2 21 6 1 0 // row & column positions of base, height, row increment, column increment
*.
text
2 10 // row & column positions of base
FOR SALE // the text itself
1 0 // row increment, column increment
.
Task 2
(a) In the class Window, implement the following static method (class method)
Window readSpecFromFile(String fileName)
The method reads the text file, constructs and returns the Window object representing the drawingspecified in the text file.
The input text file for this method has the same format as described in Task 2.
(b) Write a program, call it T2Main.java, to read the description of a drawing from a text file, e.g.T1Drawing.txt, and display the drawing on the screen.
Task 3
Add to the class Window two methods, which will be used in Task 4. The first method
public void addGrid()adds numbers to the borders to indicate the row and column indexes of the cells, as shown in the examplebelow. The numbers on the edges would help us manipulating the shapes.
The second method has the signature:
public void refreshImage()
This method first makes all the cells of the drawing image blank (except those on the borders). Then itasks each shape of the window to draw itself on the window.
This method would be called when we want to be sure that the image is up to date.
Task 4
For this task, you implement a program called DrawingBoard.java. (You may also need to add
some simple methods to the existing classes to support this program.)
- This program first allows the use to create a new drawing window or to load an existing one.
- It then allows the user
– To add a shape to the drawing,
– To delete a shape from the drawing,
– To select a shape and move it (up, down, left, right) or make it bigger or smaller,
– To save the specification of the current drawing window to a text file.
For simplicity, we will be concerned with only lines and circles.
Clarifications: Your menu program should be able to read and display drawing that have shapes otherthan line and circles (because it should use what you develop for Task 1 and Task 2). But the programprovides options to add, move and change sizes of circles and lines only.
The interactions between the user and the program are described below.
- Create a new drawing window or load an existing one
At the start, the program prompts the user to enter NEW in order to create a new drawing window or toenter a file name to load an existing drawing window.
Here is a sample run to create a new drawing window (inputs by the user are displayed in bold):
> java DrawingBoard
Enter the window file name (or NEW):
NEW
Enter mumner of rows, number of columns and character (separated by space):
10 30 *
And here is a sample run to load an existing drawing window from a text file:
> java DrawingBoard
Enter the window file name (or NEW):
SpecIn.txt
- Menu options
The last two lines in the display above are the reminders of the menu options.
The first line is meant to remind the user of the following options: Add (to add a shape), Erase (to delete
a shape), Select (to select a shape, the selected shape can be moved or have its size changed as will beseen shortly), Write (to write the specification of the window to a text file) and Quit.
The second line displays reminders for options that can be applied to the selected shape: Up (to movethe shape up), Down (to move the shape down), Left (to move the shape left), Right (to move the shaperight), + (to increment the size of the shape) and – (to decrement the size of the shape).
- Adding shapes
The way this option works is summarized in the table below:
Below is a sample run.
> java DrawingBoard
Enter the window file name (or NEW):
SpecIn.txt
- Erasing (Deleting) shapes
Below is a sample run (which continues from the previous sample run display). In this sample run, we
choose to erase the second shape (at index 1).
e
0: circle(6,8)(3)(*)
1: line(10,11)(3)(1,1)(*)
2: line(6,9)(5)(1,0)(*)
1
- Selecting shapes
We can select a shape to move it or to change its size.
Below is a sample run (continues from the previous display). In this sample run, we select the second
shape (index 1).
s
0: circle(6,8)(3)(*)
1: line(6,9)(5)(1,0)(*)
1
- Moving selected shapes and changing their sizes
To move the previously selected shape up:
Below is a sample run, which continues from the previous one. In this sample run, we move the line,
which was previously selected, to the left (the entry is actually letter l), and then increase it size by 1
(by entering the + sign).
L
Below is a sample run that continues from the previous one. In this sample run, we save the drawing
window and then choose q to quit.
w
File name: SpecOut.txt
- Quiting the program
To quit:
- Making the program more robust
Once we start the program and take a few options, we do not want the program to crash. To prevent this,
put the actions for each of the menu options in a try/catch block.
Circle.java
public class Circle extends Shape{
private int _radius;
Circle(int rowBase, int colBase, int radius, char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_radius = radius;
}
@Override
public void draw(Window window) {
for (int i = 0;i <= _rowBase + _radius; i++) {
for (int j = 1;j <=_colBase + _radius; j++) {
int xSquared = (i – _rowBase)*(i – _rowBase);
int ySquared = (j – _colBase)*(j – _colBase);
if (Math.abs(xSquared + ySquared – _radius * _radius) < _radius)
{
window.setCharAtPosition(i, j, _drawingCharacter);
}
}
}
}
}
HouseForSale.java
import java.util.*;
import java.io.*;
public class HouseForSale {
public static void main(String[] args) {
// Create a window
Window w = new Window(20, 30, ‘*’);
// Draw the ground
Line ground = new Line(19, 1, 29, 0, 1,’#’);
w.addShape(ground);
// Draw the post
Line post = new Line(12, 5, 6, 1, 0, ‘#’);
w.addShape(post);
// Draw the light
Circle light = new Circle(10, 5, 2, ‘+’);
w.addShape(light);
// Draw the house
Rectangle house = new Rectangle(8, 16, 11, 10, ‘=’);
w.addShape(house);
// Draw the door
Rectangle door = new Rectangle(11, 19, 8, 4, ‘=’);
w.addShape(door);
// Draw the roof
Triangle roof = new Triangle(2, 21, 6, 1, 0, ‘*’);
w.addShape(roof);
// Display text message
Text msg = new Text(2,10, “FOR SALE”, 1, 0);
w.addShape(msg);
w.display();
}
}
Line.java
public class Line extends Shape {
private int _length, _rowIncrement, _colIncrement;
public Line(int rowBase, int colBase, int length, int rowIncrement, int colIncrement, char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_rowIncrement = rowIncrement;
_colIncrement = colIncrement;
_length = length;
}
@Override
public void draw(Window window) {
int currRow = _rowBase, currColumn = _colBase;
for(int n = 0; n <= _length; n++)
{
window.setCharAtPosition(currRow, currColumn, _drawingCharacter);
currRow += _rowIncrement;
currColumn += _colIncrement;
}
}
}
Rectangle.java
import java.util.ArrayList;
public class Rectangle extends Shape {
// Rectangle is 4 lines in a fact. We will use this fact.
ArrayList<Line> _lines;
Rectangle(int rowBase, int colBase, int height, int width,char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_lines = new ArrayList<Line>();
_lines.add(new Line(rowBase, colBase, height, 1, 0,drawingCharacter));
_lines.add(new Line(rowBase, colBase, width, 0, 1,drawingCharacter));
_lines.add(new Line(rowBase + height, colBase + width, height, -1, 0,drawingCharacter));
_lines.add(new Line(rowBase + height, colBase + width, width, 0, -1,drawingCharacter));
}
@Override
public void draw(Window window) {
for(Line l : _lines)
l.draw(window);
}
}
Shape.java
public abstract class Shape {
protected int _rowBase, _colBase;
protected char _drawingCharacter;
Shape(int rowBase, int colBase, char drawingCharacter)
{
_rowBase = rowBase;
_colBase = colBase;
_drawingCharacter = drawingCharacter;
}
public abstract void draw(Window window);
}
Text.java
public class Text extends Shape {
private String _text;
private int _rowInc, _colInc;
Text(int rowBase, int colBase, String text, int rowIncrement, int colIncrement)
{
super(rowBase, colBase, ‘ ‘);
_text = text;
_rowInc = rowIncrement;
_colInc = colIncrement;
}
@Override
public void draw(Window window) {
int curRow = _rowBase, curCol = _colBase;
for(int i = 0; i<_text.length(); i++)
{
window.setCharAtPosition(curRow, curCol, _text.charAt(i));
curRow += _rowInc;
curCol += _colInc;
}
}
}
Triangle.java
import java.util.ArrayList;
public class Triangle extends Shape {
// Triangle in a fact is 3 lines. We will use this fact to create a triangle.
ArrayList<Line> _lines;
Triangle(int rowBase, int colBase, int height, int rowIncrement, int colIncrement, char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_lines = new ArrayList<Line>();
if(rowIncrement == 0)
{
_lines.add(new Line(rowBase,colBase,height,1,colIncrement,drawingCharacter));
_lines.add(new Line(rowBase,colBase,height,-1,colIncrement,drawingCharacter));
_lines.add(new Line(rowBase-height,colBase + colIncrement*height, height*2,1,0,drawingCharacter));
}
else if (colIncrement == 0)
{
_lines.add(new Line(rowBase,colBase,height,rowIncrement,1,drawingCharacter));
_lines.add(new Line(rowBase,colBase,height,rowIncrement,-1,drawingCharacter));
_lines.add(new Line(rowBase + rowIncrement*height,colBase-height, height*2,0,1,drawingCharacter));
}
}
@Override
public void draw(Window window) {
for(Line l : _lines)
{
l.draw(window);
}
}
}
Window.java
import java.util.ArrayList;
public class Window {
private int _rows, _columns;
private char[][] _drawing;
private char _borderCharacter;
ArrayList<Shape> _shapes;
public Window(int numberOfRows, int numberOfColumns, char borderCharacter)
{
// Create array to store data about drawing.
_rows = numberOfRows;
_columns = numberOfColumns;
// Create drawing – remember about border!
_drawing = new char[numberOfRows+2][numberOfColumns+2];
clearDrawing();
_borderCharacter = borderCharacter;
_shapes = new ArrayList<Shape>();
}
private void clearDrawing()
{
for(int i = 0; i<_drawing.length; i++)
for(int j = 0; j<_drawing[i].length;j++)
{
// Draw border if needed
if(i == 0 || j == 0 || i == _rows+1 || j == _columns+1)
_drawing[i][j] = _borderCharacter;
else
_drawing[i][j] = ‘ ‘;
}
}
public void setCharAtPosition(int row, int column, char character)
{
if(row > _rows || row < 1 || column > _columns || column < 1)
return;
_drawing[row][column] = character;
}
public void addShape(Shape shape)
{
_shapes.add(shape);
}
public void display()
{
// Clear drawing
clearDrawing();
// and draw all shapes.
for(Shape s : _shapes)
{
s.draw(this);
}
for(int i = 0; i<_drawing.length; i++)
{
for(int j = 0; j<_drawing[i].length;j++)
{
System.out.print(_drawing[i][j]);
}
System.out.println();
}
}
}
Solution
Circle.java
import java.io.PrintWriter;
public class Circle extends Shape{
private int _radius;
Circle(int rowBase, int colBase, int radius, char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_radius = radius;
}
@Override
public void draw(Window window) {
for (int i = 0;i <= _rowBase + _radius; i++) {
for (int j = 1;j <=_colBase + _radius; j++) {
int xSquared = (i – _rowBase)*(i – _rowBase);
int ySquared = (j – _colBase)*(j – _colBase);
if (Math.abs(xSquared + ySquared – _radius * _radius) < _radius)
{
window.setCharAtPosition(i, j, _drawingCharacter);
}
}
}
}
@Override
public void writeSpec(PrintWriter writer)
{
writer.println(“circle”);
writer.printf(“%d %d %d”, _rowBase, _colBase, _radius);
writer.println();
writer.println(_drawingCharacter);
writer.println(‘.’);
}
@Override
public void print()
{
System.out.printf(“%d: (circle)(%d,%d)(%d)(%c)”,_id,_rowBase,_colBase,_radius,_drawingCharacter);
System.out.println();
}
@Override
public void increaseSize()
{
_radius++;
}
@Override
public void decreaseSize()
{
_radius–;
}
}
DrawingBoard.java
import java.util.*;
import java.io.*;
public class DrawingBoard {
public static void main(String[] args) {
// Create a window
Window w = null;
String fileName = “”;
System.out.println(“Enter the window file name (or NEW):”);
Scanner sc = new Scanner(System.in);
fileName = sc.nextLine();
if(fileName.equals(“NEW”))
{
System.out.println(“Enter mumner of rows, number of columns and character (separated by space):”);
int rows = sc.nextInt();
int cols = sc.nextInt();
char drawingCharacter = sc.next().charAt(0);
sc.nextLine();
w = new Window(rows,cols,drawingCharacter);
}
else
{
w = Window.readSpecFromFile(fileName);
}
if(w!=null)
{
boolean keepRunning = true;
int selectedId = -1;
while(keepRunning)
{
printWindowWithMenu(w);
char c = sc.next().charAt(0);
sc.nextLine();
switch(c)
{
case ‘a’:
try
{
addShape(w,sc);
}
catch(Exception ex)
{
System.out.println(“Couldn’t add shape: ” + ex.toString());
}
break;
case ‘e’:
try
{
eraseShape(w,sc);
}
catch(Exception ex)
{
System.out.println(“Couldn’t erase shape: ” + ex.toString());
}
break;
case ‘s’:
try
{
selectedId = selectShape(w,sc);
}
catch(Exception ex)
{
System.out.println(“Couldn’t select shape: ” + ex.toString());
}
break;
case ‘w’:
try
{
saveWindow(w,sc);
}
catch(Exception ex)
{
System.out.println(“Couldn’t save window: ” + ex.toString());
}
break;
case ‘u’:
try
{
w.moveUp(selectedId);
}
catch(Exception ex)
{
System.out.println(“Couldn’t move shape: ” + ex.toString());
}
break;
case ‘d’:
try
{
w.moveDown(selectedId);
}
catch(Exception ex)
{
System.out.println(“Couldn’t move shape: ” + ex.toString());
}
break;
case ‘l’:
try
{
w.moveLeft(selectedId);
}
catch(Exception ex)
{
System.out.println(“Couldn’t move shape: ” + ex.toString());
}
break;
case ‘r’:
try
{
w.moveRight(selectedId);
}
catch(Exception ex)
{
System.out.println(“Couldn’t move shape: ” + ex.toString());
}
break;
case ‘+’:
try
{
w.increaseSize(selectedId);
}
catch(Exception ex)
{
System.out.println(“Couldn’t increase size of shape: ” + ex.toString());
}
break;
case ‘-‘:
try
{
w.decreaseSize(selectedId);
}
catch(Exception ex)
{
System.out.println(“Couldn’t decrease size of shape: ” + ex.toString());
}
break;
case ‘q’:
keepRunning = false;
break;
default:
break;
}
}
}
else
{
System.out.println(“Couldn’t create or load file.”);
}
}
private static void printWindowWithMenu(Window w)
{
w.refreshImage();
w.display();
System.out.println(“Add Erase Select Write Quit”);
System.out.println(“Up Down Left Right + -“);
}
private static void saveWindow(Window w, Scanner sc)
{
System.out.print(“File name: “);
String fileName = sc.nextLine();
w.writeSpecToFile(fileName);
}
private static int selectShape(Window w, Scanner sc)
{
w.printShapes();
int id = sc.nextInt();
return id;
}
private static void eraseShape(Window w, Scanner sc)
{
w.printShapes();
int id = sc.nextInt();
w.removeShape(id);
}
private static void addShape(Window w, Scanner sc)
{
System.out.println(“circle rowBase colBase radius character”);
System.out.println(“line rowBase colBase length rowIncrement colIncrement character”);
String type = sc.next();
int rowBase, colBase;
char c;
if(type.equals(“circle”))
{
int radius;
rowBase = sc.nextInt();
colBase = sc.nextInt();
radius = sc.nextInt();
c = sc.next().charAt(0);
sc.nextLine();
w.addShape(new Circle(rowBase,colBase,radius,c));
}
else if(type.equals(“line”))
{
int length, rowInc, colInc;
rowBase = sc.nextInt();
colBase = sc.nextInt();
length = sc.nextInt();
rowInc = sc.nextInt();
colInc = sc.nextInt();
c = sc.next().charAt(0);
sc.nextLine();
w.addShape(new Line(rowBase,colBase,length,rowInc,colInc,c));
}
}
}
Line.java
import java.io.PrintWriter;
public class Line extends Shape {
private int _length, _rowIncrement, _colIncrement;
public Line(int rowBase, int colBase, int length, int rowIncrement, int colIncrement, char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_rowIncrement = rowIncrement;
_colIncrement = colIncrement;
_length = length;
}
@Override
public void draw(Window window) {
int currRow = _rowBase, currColumn = _colBase;
for(int n = 0; n <= _length; n++)
{
window.setCharAtPosition(currRow, currColumn, _drawingCharacter);
currRow += _rowIncrement;
currColumn += _colIncrement;
}
}
@Override
public void writeSpec(PrintWriter writer)
{
writer.println(“line”);
writer.printf(“%d %d %d %d %d”, _rowBase, _colBase, _length, _rowIncrement, _colIncrement);
writer.println();
writer.println(_drawingCharacter);
writer.println(‘.’);
}
@Override
public void print()
{
System.out.printf(“%d: (line)(%d,%d)(%d)(%d,%d)(%c)”,_id,_rowBase,_colBase,_length,_rowIncrement,_colIncrement,_drawingCharacter);
System.out.println();
}
@Override
public void increaseSize()
{
_length++;
}
@Override
public void decreaseSize()
{
_length–;
}
}
Oval.java
import java.io.PrintWriter;
public class Oval extends Shape{
private int _radiusVert, _radiusHor;
Oval(int rowBase, int colBase, int radiusVert, int radiusHor, char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_radiusVert = radiusVert;
_radiusHor = radiusHor;
}
@Override
public void draw(Window window) {
for (int i = 0;i <= _rowBase + _radiusVert; i++) {
for (int j = 1;j <=_colBase + _radiusHor; j++) {
int xSquared = (i – _rowBase)*(i – _rowBase);
int ySquared = (j – _colBase)*(j – _colBase);
// Used to calculate all points that belongs to outer ellipse
int ry2 = _radiusHor * _radiusHor;
int rx2 = _radiusVert * _radiusVert;
int equationOuter = Math.abs(xSquared * ry2 + ySquared * rx2);
// Used to calculate all points that belongs to inner ellipse
int ry2in = (_radiusHor-1) * (_radiusHor-1);
int rx2in = (_radiusVert-1) * (_radiusVert-1);
int equationInner = Math.abs(xSquared * ry2in + ySquared * rx2in);
// To get border (outer ellipse without fill) we need to remove points
// that belongs to inner ellipse
if (equationOuter <= ry2*rx2 && equationInner > ry2in * rx2in)
{
window.setCharAtPosition(i, j, _drawingCharacter);
}
}
}
}
@Override
public void writeSpec(PrintWriter writer)
{
writer.println(“oval”);
writer.printf(“%d %d %d %d”, _rowBase, _colBase, _radiusVert, _radiusHor);
writer.println();
writer.println(_drawingCharacter);
writer.println(‘.’);
}
@Override
public void print()
{
System.out.printf(“%d: (circle)(%d,%d)(%d,%d)(%c)”,_id,_rowBase,_colBase,_radiusVert,_radiusHor,_drawingCharacter);
System.out.println();
}
@Override
public void increaseSize()
{
_radiusVert++;
}
@Override
public void decreaseSize()
{
_radiusVert–;
}
}
Rectangle.java
import java.util.ArrayList;
import java.io.PrintWriter;
public class Rectangle extends Shape {
// Rectangle is 4 lines in a fact. We will use this fact.
ArrayList<Line> _lines;
private int _height, _width;
Rectangle(int rowBase, int colBase, int height, int width,char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_height = height;
_width = width;
_lines = new ArrayList<Line>();
_lines.add(new Line(rowBase, colBase, height, 1, 0,drawingCharacter));
_lines.add(new Line(rowBase, colBase, width, 0, 1,drawingCharacter));
_lines.add(new Line(rowBase + height, colBase + width, height, -1, 0,drawingCharacter));
_lines.add(new Line(rowBase + height, colBase + width, width, 0, -1,drawingCharacter));
}
@Override
public void draw(Window window) {
for(Line l : _lines)
l.draw(window);
}
@Override
public void writeSpec(PrintWriter writer)
{
writer.println(“rectangle”);
writer.printf(“%d %d %d %d”, _rowBase, _colBase, _height, _width);
writer.println();
writer.println(_drawingCharacter);
writer.println(‘.’);
}
@Override
public void print()
{
System.out.printf(“%d: (rectangle)(%d,%d)(%d,%d)(%c)”,_id,_rowBase,_colBase,_height,_width,_drawingCharacter);
System.out.println();
}
@Override
public void increaseSize()
{
}
@Override
public void decreaseSize()
{
}
}
Shape.java
import java.io.PrintWriter;
import java.util.Scanner;
public abstract class Shape {
protected int _rowBase, _colBase;
protected char _drawingCharacter;
protected int _id;
Shape(int rowBase, int colBase, char drawingCharacter)
{
_rowBase = rowBase;
_colBase = colBase;
_drawingCharacter = drawingCharacter;
}
public int getId()
{
return _id;
}
public void setId(int id)
{
_id = id;
}
public void move(int v, int h)
{
_rowBase += v;
_colBase += h;
}
static Shape readShape(Scanner scanner)
{
if(!scanner.hasNext())
return null;
String currentLine = scanner.nextLine();
if(currentLine == null)
return null;
Shape shape = null;
int rowBase, colBase;
char drawingCharacter;
if(currentLine.equals(“line”))
{
int length, rowIncrement, colIncrement;
rowBase = scanner.nextInt();
colBase = scanner.nextInt();
length = scanner.nextInt();
rowIncrement = scanner.nextInt();
colIncrement = scanner.nextInt();
drawingCharacter = scanner.next().charAt(0);
scanner.nextLine();
scanner.nextLine();
shape = new Line(rowBase, colBase, length, rowIncrement, colIncrement, drawingCharacter);
}
else if(currentLine.equals(“circle”))
{
rowBase = scanner.nextInt();
colBase = scanner.nextInt();
int radius = scanner.nextInt();
drawingCharacter = scanner.next().charAt(0);
scanner.nextLine();
scanner.nextLine();
shape = new Circle(rowBase, colBase, radius, drawingCharacter);
}
else if(currentLine.equals(“triangle”))
{
int height, rowIncrement, colIncrement;
rowBase = scanner.nextInt();
colBase = scanner.nextInt();
height = scanner.nextInt();
rowIncrement = scanner.nextInt();
colIncrement = scanner.nextInt();
drawingCharacter = scanner.next().charAt(0);
scanner.nextLine();
scanner.nextLine();
shape = new Triangle(rowBase, colBase, height, rowIncrement, colIncrement, drawingCharacter);
}
else if(currentLine.equals(“rectangle”))
{
int width, height;
rowBase = scanner.nextInt();
colBase = scanner.nextInt();
height = scanner.nextInt();
width = scanner.nextInt();
drawingCharacter = scanner.next().charAt(0);
scanner.nextLine();
scanner.nextLine();
shape = new Rectangle(rowBase, colBase, height, width, drawingCharacter);
}
else if(currentLine.equals(“text”))
{
String text;
int rowIncrement, colIncrement;
rowBase = scanner.nextInt();
colBase = scanner.nextInt();
scanner.nextLine();
text = scanner.nextLine();
rowIncrement = scanner.nextInt();
colIncrement = scanner.nextInt();
scanner.nextLine();
shape = new Text(rowBase, colBase, text, rowIncrement, colIncrement);
}
return shape;
}
public abstract void draw(Window window);
public abstract void writeSpec(PrintWriter writer);
public abstract void print();
public abstract void increaseSize();
public abstract void decreaseSize();
}
T1Drawing.java
import java.util.*;
import java.io.*;
public class T1Drawing {
public static void main(String[] args) {
// Create a window
Window w = new Window(20, 30, ‘*’);
// Draw the ground
Line ground = new Line(19, 1, 29, 0, 1,’#’);
w.addShape(ground);
// Draw the post
Line post = new Line(12, 5, 6, 1, 0, ‘#’);
w.addShape(post);
// Draw the light
Circle light = new Circle(10, 5, 2, ‘+’);
w.addShape(light);
// Draw the house
Rectangle house = new Rectangle(8, 16, 11, 10, ‘=’);
w.addShape(house);
// Draw the door
Rectangle door = new Rectangle(11, 19, 8, 4, ‘=’);
w.addShape(door);
// Draw the roof
Triangle roof = new Triangle(2, 21, 6, 1, 0, ‘*’);
w.addShape(roof);
// Display text message
Text msg = new Text(2,10, “FOR SALE”, 1, 0);
w.addShape(msg);
w.display();
w.writeSpecToFile(“T1DrawingSpec.txt”);
}
}
T2Drawing.java
import java.util.*;
import java.io.*;
public class T2Drawing {
public static void main(String[] args) {
// Create a window
Window w = Window.readSpecFromFile(“T1DrawingSpec.txt”);
w.refreshImage();
w.display();
}
}
T5Test.java
import java.util.*;
import java.io.*;
public class T5Test {
public static void main(String[] args) {
// Create a window
Window w = new Window(20, 30, ‘*’);
// Draw the ground
Oval testOval = new Oval(8,15,4,9,’o’);
w.addShape(testOval);
Text testText = new Text(1,1,”OVAL TEST”,0,1);
w.addShape(testText);
w.refreshImage();
w.display();
}
}
Text.java
import java.io.PrintWriter;
public class Text extends Shape {
private String _text;
private int _rowInc, _colInc;
Text(int rowBase, int colBase, String text, int rowIncrement, int colIncrement)
{
super(rowBase, colBase, ‘ ‘);
_text = text;
_rowInc = rowIncrement;
_colInc = colIncrement;
}
@Override
public void draw(Window window) {
int curRow = _rowBase, curCol = _colBase;
for(int i = 0; i<_text.length(); i++)
{
window.setCharAtPosition(curRow, curCol, _text.charAt(i));
curRow += _rowInc;
curCol += _colInc;
}
}
@Override
public void writeSpec(PrintWriter writer)
{
writer.println(“text”);
writer.printf(“%d %d”, _rowBase, _colBase);
writer.println();
writer.println(_text);
writer.printf(“%d %d”, _rowInc, _colInc);
writer.println();
writer.println(‘.’);
}
@Override
public void print()
{
System.out.printf(“%d: (text)(%d,%d)(%s)(%d,%d)”,_id,_rowBase,_colBase,_text,_rowInc,_colInc);
System.out.println();
}
@Override
public void increaseSize()
{
}
@Override
public void decreaseSize()
{
}
}
Triangle.java
import java.util.ArrayList;
import java.io.PrintWriter;
public class Triangle extends Shape {
// Triangle in a fact is 3 lines. We will use this fact to create a triangle.
ArrayList<Line> _lines;
private int _height, _rowInc, _colInc;
Triangle(int rowBase, int colBase, int height, int rowIncrement, int colIncrement, char drawingCharacter)
{
super(rowBase, colBase, drawingCharacter);
_height = height;
_rowInc = rowIncrement;
_colInc = colIncrement;
_lines = new ArrayList<Line>();
if(rowIncrement == 0)
{
_lines.add(new Line(rowBase,colBase,height,1,colIncrement,drawingCharacter));
_lines.add(new Line(rowBase,colBase,height,-1,colIncrement,drawingCharacter));
_lines.add(new Line(rowBase-height,colBase + colIncrement*height, height*2,1,0,drawingCharacter));
}
else if (colIncrement == 0)
{
_lines.add(new Line(rowBase,colBase,height,rowIncrement,1,drawingCharacter));
_lines.add(new Line(rowBase,colBase,height,rowIncrement,-1,drawingCharacter));
_lines.add(new Line(rowBase + rowIncrement*height,colBase-height, height*2,0,1,drawingCharacter));
}
}
@Override
public void draw(Window window) {
for(Line l : _lines)
{
l.draw(window);
}
}
@Override
public void writeSpec(PrintWriter writer)
{
writer.println(“triangle”);
writer.printf(“%d %d %d %d %d”, _rowBase, _colBase, _height, _rowInc, _colInc);
writer.println();
writer.println(_drawingCharacter);
writer.println(‘.’);
}
@Override
public void print()
{
System.out.printf(“%d: (triangle)(%d,%d)(%d)(%d,%d)(%c)”,_id,_rowBase,_colBase,_height,_rowInc,_colInc,_drawingCharacter);
System.out.println();
}
@Override
public void increaseSize()
{
}
@Override
public void decreaseSize()
{
}
}
Window.java
import java.util.ArrayList;
import java.io.PrintWriter;
import java.util.Scanner;
import java.io.File;
public class Window {
private int _rows, _columns;
private int _currentId;
private char[][] _drawing;
private char _borderCharacter;
ArrayList<Shape> _shapes;
public Window(int numberOfRows, int numberOfColumns, char borderCharacter)
{
// Set currentId to 0.
_currentId = 0;
// Create array to store data about drawing.
_rows = numberOfRows;
_columns = numberOfColumns;
// Create drawing – remember about border!
_drawing = new char[numberOfRows+2][numberOfColumns+2];
clearDrawing();
_borderCharacter = borderCharacter;
_shapes = new ArrayList<Shape>();
}
private void clearDrawing()
{
for(int i = 0; i<_drawing.length; i++)
for(int j = 0; j<_drawing[i].length;j++)
{
// Draw border if needed
if(i == 0 || j == 0 || i == _rows+1 || j == _columns+1)
_drawing[i][j] = _borderCharacter;
else
_drawing[i][j] = ‘ ‘;
}
}
public void setCharAtPosition(int row, int column, char character)
{
if(row > _rows || row < 1 || column > _columns || column < 1)
return;
_drawing[row][column] = character;
}
public void addShape(Shape shape)
{
shape.setId(_currentId++);
_shapes.add(shape);
}
public void removeShape(int id)
{
for(int i = 0; i<_shapes.size(); i++)
{
if(_shapes.get(i).getId() == id)
{
_shapes.remove(i);
break;
}
}
}
public void printShapes()
{
for(Shape s : _shapes)
{
s.print();
}
}
public void addGrid()
{
for(int i = 1; i<_drawing.length-1; i++)
{
_drawing[i][0] = (char)(‘0’ + i%10);
_drawing[i][_drawing[i].length-1] = (char)(‘0’ + i%10);
}
for(int i = 1; i<_drawing[0].length-1; i++)
{
_drawing[0][i] = (char)(‘0’ + i%10);
_drawing[_drawing.length-1][i] = (char)(‘0’ + i%10);
}
}
public void refreshImage()
{
// Clear drawing
clearDrawing();
addGrid();
// and draw all shapes.
for(Shape s : _shapes)
{
s.draw(this);
}
}
public void display()
{
for(int i = 0; i<_drawing.length; i++)
{
for(int j = 0; j<_drawing[i].length;j++)
{
System.out.print(_drawing[i][j]);
}
System.out.println();
}
}
private Shape getShapeWithId(int id)
{
for(int i = 0; i<_shapes.size(); i++)
{
if(_shapes.get(i).getId() == id)
{
return _shapes.get(i);
}
}
return null;
}
public void increaseSize(int id)
{
Shape s = getShapeWithId(id);
s.increaseSize();
}
public void decreaseSize(int id)
{
Shape s = getShapeWithId(id);
s.decreaseSize();
}
public void moveUp(int id)
{
Shape s = getShapeWithId(id);
s.move(-1,0);
}
public void moveDown(int id)
{
Shape s = getShapeWithId(id);
s.move(1,0);
}
public void moveLeft(int id)
{
Shape s = getShapeWithId(id);
s.move(0,-1);
}
public void moveRight(int id)
{
Shape s = getShapeWithId(id);
s.move(0,1);
}
void writeSpecToFile(String fileName)
{
try
{
PrintWriter writer = new PrintWriter(fileName, “UTF-8”);
// Window header info
writer.printf(“%d %d”,_rows,_columns);
writer.println();
writer.println(_borderCharacter);
writer.println(‘.’);
// Write all shapes
for(Shape s : _shapes)
{
s.writeSpec(writer);
}
writer.close();
} catch (Exception e)
{
System.out.println(“Couldn’t save specification to file!”);
}
}
static Window readSpecFromFile(String fileName)
{
Window window = null;
try
{
Scanner scanner = new Scanner(new File(fileName));
int rows = scanner.nextInt();
int cols = scanner.nextInt();
char borderCharacter = scanner.next().charAt(0);
scanner.nextLine();
scanner.nextLine();
window = new Window(rows,cols,borderCharacter);
Shape shape;
while( (shape = Shape.readShape(scanner)) != null)
window.addShape(shape);
}
catch (Exception ex)
{
window = null;
System.out.println(“Couldn’t load specification from file!”);
}
return window;
}
}