Another ASCII art drawing program

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

  1. Write a method save the specification of the window and its shapes to a text file.
  2. Write a method to read the specification from the text file to reconstruct the drawing window.
  3. 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.

  1. 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

  1. 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).

  1. 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

  1. 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

  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

  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

  1. Quiting the program

To quit:

  1. 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;

}

}