// JDraw - DrawFrame.java Source file
// Written by Jim Calciano, Melanie Lear, and PJ Waskiewicz
// November 18, 1998
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.Properties;
public class DrawFrame extends ApplicationFrame implements ActionListener,WindowListener{
// Variables for this class
private Menu fileMenu, editMenu;
private int selectedButton;
public Color selectedColor = Color.blue;
private boolean buttonClicked=false;
// Constant size for our object buttons
public static final int SIZE = 25;
private DrawCanvas canvas;
// These five buttons are our buttons created to select objects, with a sixth to
// edit with
private LineButton lb;
private RectButton rb;
private OvalButton ob;
private FRectButton frb;
private FOvalButton fob;
private EditButton eb;
private Panel theSelectedColorPanel=new Panel();
// An array of Buttons for selecting which color to draw in
private ColorButton colorArray[] = new ColorButton[10];
// This keeps a running total of how many frames we have so the program
// will exit at the correct time, ie - when no more frames exist
private static int frameCount = 1;
// Boolean variables for the state of our drawing canvas
private boolean named = false;
private boolean changed = false;
private String fname = "UNTITLED";
// Two file dialog boxes; one for saving files, one for loading files
private FileDialog sfd = new FileDialog(this, "Save", FileDialog.SAVE);
private FileDialog lfd = new FileDialog(this, "Load", FileDialog.LOAD);
// Two extensions of dialog boxes for a nicer interface for the user
private MsgDialog mdg = new MsgDialog(this);
private QuestionDialog qdg = new QuestionDialog(this);
// Some temporary and intermediate variables for the program
private String s, temp, item;
private int tempx, tempy, temph, tempw, redVal, greenVal, blueVal;
public DrawFrame(){
// Constructor for our frane
super("JDraw");
setSize(700,700);
// Make the new menubar
fileMenu = new Menu("File");
fileMenu.add("New");
fileMenu.add("Open");
fileMenu.addSeparator();
fileMenu.add("Save");
fileMenu.add("Save As");
fileMenu.addSeparator();
fileMenu.add("Print");
fileMenu.addSeparator();
fileMenu.add("Close");
fileMenu.add("Exit");
fileMenu.addActionListener(this);
getMenuBar().add(fileMenu);
// Make edit menu
editMenu = new Menu("Edit");
editMenu.add("Delete");
editMenu.addActionListener(this);
getMenuBar().add(editMenu);
// Define layouts for our buttons
GridLayout gl = new GridLayout(6,1);
GridLayout glColor = new GridLayout(1,11);
// Make some new Panels to put the buttons into
Panel p = new Panel();
Panel pColor = new Panel();
theSelectedColorPanel.setSize(100,100);
theSelectedColorPanel.setBackground(Color.blue);
Panel panelArray [] = new Panel[6];
Panel colorButtons = new Panel();
// Call a method to make the buttons
makeButtons();
// Make five new Panels for the object buttons
for(int i = 0; i <= 5; i++)
panelArray[i] = new Panel();
// Add our object buttons
panelArray[0].add(eb);
panelArray[1].add(lb);
panelArray[2].add(rb);
panelArray[3].add(ob);
panelArray[4].add(frb);
panelArray[5].add(fob);
// Add the color Buttons
for(int i = 0; i <= 9; i++)
colorButtons.add(colorArray[i]);
p.setLayout(gl);
// Add the individual Panels from the color buttons to a big Panel
for(int i = 0; i<= 5; i++)
p.add(panelArray[i]);
add("West",p);
colorButtons.setLayout(glColor);
pColor.add(theSelectedColorPanel); // You wanted it
pColor.add(colorButtons);
add("South",pColor);
// Make the new drawing canvas
canvas = new DrawCanvas();
add("Center", canvas);
}
private void makeButtons(){
// Method to make our buttons for the program
lb = new LineButton();
rb = new RectButton();
ob = new OvalButton();
frb = new FRectButton();
fob = new FOvalButton();
eb = new EditButton();
colorArray[0] = new ColorButton(Color.blue,this);
colorArray[1] = new ColorButton(Color.cyan,this);
colorArray[2] = new ColorButton(Color.green,this);
colorArray[3] = new ColorButton(Color.orange,this);
colorArray[4] = new ColorButton(Color.red,this);
colorArray[5] = new ColorButton(new Color(150,220,190),this);
colorArray[6] = new ColorButton(Color.pink,this);
colorArray[7] = new ColorButton(new Color(255,255,255),this);
colorArray[8] = new ColorButton(new Color(18,9,150),this);
colorArray[9] = new ColorButton(new Color(0,0,0),this);
}
public void windowActivated(WindowEvent e) {}
public void windowClosed(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
// Make sure the file isn't changed before exiting. If it is,
// ask the user if he/she wants to save it before exiting.
if(changed == true){
qdg.setTitle("Save Changes");
qdg.setQuestion("Save Changes Before Exiting?");
qdg.setYesText("Yes");
qdg.setNoText("No");
qdg.setCancelText("Cancel");
qdg.setVisible(true);
int val;
val = qdg.getState();
switch(val){
case 0:
System.exit(0);
break;
case 1:
save();
System.exit(0);
break;
case 2:
break;
}
}
else
System.exit(0);
}
public void setSelectedColor(Color selectedColor){
// Public method to set our color which was selected
theSelectedColorPanel.setBackground(selectedColor);
this.selectedColor = selectedColor;
canvas.setSelectedColor(selectedColor);
canvas.giveMeFocus();
}
public Color getSelectedColor(){
return selectedColor;
}
public void actionPerformed(ActionEvent e){
// This method determines which item from the menu was selected
if(e.getActionCommand().equals("New")){
// Make a new frame, and bump up the frame counter
Frame newFrame = new DrawFrame();
newFrame.setVisible(true);
frameCount++;
}
else if(e.getActionCommand().equals("Open")){
open();
}
else if(e.getActionCommand().equals("Save")){
save();
}
else if(e.getActionCommand().equals("Save As")){
saveAs();
}
else if(e.getActionCommand().equals("Print")){
print();
}
else if(e.getActionCommand().equals("Close")){
close();
}
else if(e.getActionCommand().equals("Exit")){
// Make sure the file isn't changed before exiting. If it is,
// ask the user if he/she wants to save it before exiting.
if(changed == true){
qdg.setTitle("Save Changes");
qdg.setQuestion("Save Changes Before Exiting?");
qdg.setYesText("Yes");
qdg.setNoText("No");
qdg.setCancelText("Cancel");
qdg.setVisible(true);
int val;
val = qdg.getState();
switch(val){
case 0:
System.exit(0);
break;
case 1:
save();
System.exit(0);
break;
case 2:
break;
}
}
else
System.exit(0);
}
else if(e.getActionCommand().equals("Delete")){
// Check if the last object in the vector is selected; if so, delete
// it, if not, leave everything be.
if(canvas.objects.size() > 0){
if((canvas.objects.elementAt(canvas.objects.size()-1).
toString()).regionMatches(0,"S",0,1)){
canvas.objects.removeElementAt(canvas.objects.size()-1);
canvas.repaint();
}
}
}
}
private void open() {
// Open the file. First prompt the user if he/she wants to
// save any work if anything has been changed.
if(changed == true){
qdg.setTitle("Save Changes");
qdg.setQuestion("Save Changes Before Opening?");
qdg.setYesText("Yes");
qdg.setNoText("No");
qdg.setCancelText("Cancel");
qdg.setVisible(true);
int val;
// The getState method of the QuestionDialog class returns a 0,
// 1, or 2. 0 = no, 1 = yes, and 2 = Cancel.
val = qdg.getState();
switch(val){
case 0:
yesOpen();
break;
case 1:
save();
yesOpen();
break;
case 2:
break;
}
}
else
yesOpen();
}
private void yesOpen(){
// This method actually opens the file, and in doing so will
// clear the vector, objects, so new objects can be added to it.
canvas.objects.setSize(0);
canvas.repaint();
lfd.setVisible(true);
fname = lfd.getFile();
if (fname != null){
try{
// Using the combination of a FileReader to open a file, a
// BufferedReader to read lines from the file, and a StreamTokenizer
// to read "tokens", or separate pieces of data, from the line
// from the BufferedReader. Upon reading these values in, see
// which object to draw from the first string in the file, and
// then draw he object onto the canvas.
FileReader freader = new FileReader(fname);
BufferedReader breader = new BufferedReader(freader);
StreamTokenizer token = new StreamTokenizer(breader);
temp = breader.readLine();
// Check to make sure that the file starts with the string
// #JDRAW. If it does not, assume it is an invalid file.
if (!temp.equals("#JDRAW")){
mdg.setTitle("Error");
mdg.setMessage("Invalid file format");
mdg.setButtonText("Ok");
mdg.setVisible(true);
}
else{
breader.readLine();
while (true){
token.nextToken();
if(token.sval == null)
break;
item = token.sval;
// This will set the StreamTokenizer to treat commas
// as white space as well as spaces and newlines. This
// allows us to read in RGB values for color in the
// following format: R,G,B
token.whitespaceChars(',', ',');
if (item.equals("line")){
token.nextToken();
tempx = (int)token.nval;
token.nextToken();
tempy = (int)token.nval;
token.nextToken();
tempw = (int)token.nval;
token.nextToken();
temph = (int)token.nval;
token.nextToken();
redVal = (int)token.nval;
token.nextToken();
greenVal = (int)token.nval;
token.nextToken();
blueVal = (int)token.nval;
Color color = new Color(redVal,greenVal,blueVal);
Line newLine = new Line(tempx,tempy,tempw,temph,color);
canvas.objects.addElement(newLine);
canvas.repaint();
}
else if(item.equals("rect")){
token.nextToken();
tempx = (int)token.nval;
token.nextToken();
tempy = (int)token.nval;
token.nextToken();
tempw = (int)token.nval;
token.nextToken();
temph = (int)token.nval;
token.nextToken();
redVal = (int)token.nval;
token.nextToken();
greenVal = (int)token.nval;
token.nextToken();
blueVal = (int)token.nval;
Color color = new Color(redVal,greenVal,blueVal);
Rect newRect = new Rect(tempx,tempy,tempw,temph,color,"open");
canvas.objects.addElement(newRect);
canvas.repaint();
}
else if(item.equals("oval")){
token.nextToken();
tempx = (int)token.nval;
token.nextToken();
tempy = (int)token.nval;
token.nextToken();
tempw = (int)token.nval;
token.nextToken();
temph = (int)token.nval;
token.nextToken();
redVal = (int)token.nval;
token.nextToken();
greenVal = (int)token.nval;
token.nextToken();
blueVal = (int)token.nval;
Color color = new Color(redVal,greenVal,blueVal);
Oval newOval = new Oval(tempx,tempy,tempw,temph,color,"open");
canvas.objects.addElement(newOval);
canvas.repaint();
}
else if(item.equals("frect")){
token.nextToken();
tempx = (int)token.nval;
token.nextToken();
tempy = (int)token.nval;
token.nextToken();
tempw = (int)token.nval;
token.nextToken();
temph = (int)token.nval;
token.nextToken();
redVal = (int)token.nval;
token.nextToken();
greenVal = (int)token.nval;
token.nextToken();
blueVal = (int)token.nval;
Color color = new Color(redVal,greenVal,blueVal);
FRect newFRect = new FRect(tempx,tempy,tempw,temph,color,"open");
canvas.objects.addElement(newFRect);
canvas.repaint();
}
else if(item.equals("foval")){
token.nextToken();
tempx = (int)token.nval;
token.nextToken();
tempy = (int)token.nval;
token.nextToken();
tempw = (int)token.nval;
token.nextToken();
temph = (int)token.nval;
token.nextToken();
redVal = (int)token.nval;
token.nextToken();
greenVal = (int)token.nval;
token.nextToken();
blueVal = (int)token.nval;
Color color = new Color(redVal,greenVal,blueVal);
FOval newFOval = new FOval(tempx,tempy,tempw,temph,color,"open");
canvas.objects.addElement(newFOval);
canvas.repaint();
}
}
}
}catch(java.io.IOException i){
// If an I/O error occurs, give the user a dialog box printing
// out that an error occured.
mdg.setTitle("I/O Error");
mdg.setMessage("Error Opening File");
mdg.setButtonText("Ok");
mdg.setVisible(true);
}
}
}
private void save(){
// If the file has a name, this means it has been saved, so just
// go ahead and write the file.
if (named) {
try{
// Using a FileWriter to open the stream to the specified
// file, we use a BufferedWriter with the FileWriter to
// write the file.
FileWriter fwriter = new FileWriter(fname);
BufferedWriter bwriter = new BufferedWriter(fwriter);
// Put the distinguishing line at the top of our file
bwriter.write("#JDRAW",0,6);
bwriter.newLine();
bwriter.newLine();
bwriter.flush();
// Now, using a method defined in all our objects' class definitions,
// returnString, we get all parameters associated with the objects,
// and moving through our Vector of objects, and then using
// poymorphism through type casting to their superclass, we determine
// which returnString to call, and then write that string to our file.
for(int i = 0; i <= (canvas.objects.size() - 1); i++){
s = new String(((DrawObject)(canvas.objects.elementAt(i))).returnString());
bwriter.write(s,0,s.length());
bwriter.newLine();
bwriter.flush();
}
}
catch(java.io.IOException i){
// Again, if an error writing occurred, let the user know.
mdg.setTitle("I/O Error");
mdg.setMessage("Error Saving File");
mdg.setButtonText("Ok");
mdg.setVisible(true);
}
// Now the file is in the state that it is not changed.
changed = false;
}
else{
// This occurs if the file has no name. So ask the user for a filename,
// then go through all the same steps to write the file as was done
// above.
sfd.setVisible(true);
fname = sfd.getFile();
if(fname != null){
try{
FileWriter fwriter = new FileWriter(fname);
BufferedWriter bwriter = new BufferedWriter(fwriter);
bwriter.write("#JDRAW",0,6);
bwriter.newLine();
bwriter.newLine();
bwriter.flush();
for(int i = 0; i <= (canvas.objects.size() - 1); i++){
s = new String(((DrawObject)(canvas.objects.elementAt(i))).returnString());
bwriter.write(s,0,s.length());
bwriter.newLine();
bwriter.flush();
}
}
catch(java.io.IOException i){
// Once again, let the user know if I/O failed.
mdg.setTitle("I/O Error");
mdg.setMessage("Error Saving File");
mdg.setButtonText("Ok");
mdg.setVisible(true);
}
// Now the file has a name, and it has not been changed.
named = true;
changed = false;
}
}
}
private void saveAs(){
// This will need to get a filename from the dialog box, then will go
// through the same steps to save the file.
sfd.setVisible(true);
fname = sfd.getFile();
if(fname != null){
try{
FileWriter fwriter = new FileWriter(fname);
BufferedWriter bwriter = new BufferedWriter(fwriter);
bwriter.write("#JDRAW",0,6);
bwriter.newLine();
bwriter.newLine();
bwriter.flush();
// Now the file is named, and it has not been changed.
named = true;
changed = false;
for(int i = 0; i <= (canvas.objects.size() - 1); i++){
s = new String(((DrawObject)(canvas.objects.elementAt(i))).returnString());
bwriter.write(s,0,s.length());
bwriter.newLine();
bwriter.flush();
}
}
catch(java.io.IOException i){
// I/O failed, so give a nice Message Dialog box
mdg.setTitle("I/O Error");
mdg.setMessage("Error Saving File");
mdg.setButtonText("Ok");
mdg.setVisible(true);
}
}
else{
// This happens if the user hits "Cancel" in the dialog box. So
// the file can remain unchanged, but it is not named, so we give it
// the name UNTITLED to prevent null pointer exceptions from fname.
fname = "UNTITLED";
changed = false;
named = false;
}
}
private void print(){
Properties printprefs=new Properties();
Toolkit toolkit=canvas.getToolkit();
PrintJob job=toolkit.getPrintJob(this,"JDraw",printprefs);
if(job==null) return;
Graphics g=job.getGraphics();
canvas.printAll(g);
g.dispose();
job.end();
}
private void close(){
// This will close the current frame. If any work has been done since
// last saving, ask the user if he/she wants to save before closing.
if(changed == true){
qdg.setTitle("Save Changes");
qdg.setQuestion("Save Changes Before Closing?");
qdg.setYesText("Yes");
qdg.setNoText("No");
qdg.setCancelText("Cancel");
qdg.setVisible(true);
int val;
// The values from getState are the same as above: 0 = no, 1 = yes,
// 2 = cancel
val = qdg.getState();
switch(val){
case 0:
// If no, then decrement frameCount. If frameCount is zero, no
// frames are open, so exit the program. Else, just dipose the
// current frame.
frameCount--;
if(frameCount == 0)
System.exit(0);
else
dispose();
break;
case 1:
// If yes, call save(), then do the same as above.
save();
frameCount--;
if(frameCount == 0)
System.exit(0);
else
dispose();
break;
case 2:
// If cancel, just drop out and do nothing.
break;
}
}
else{
// If no changes were made, then just decrement frameCount, and
// check if all frames are closed, and either dispose or exit the
// program based on that.
frameCount--;
if(frameCount == 0)
System.exit(0);
else
dispose();
}
}
public int getSelected () {
// This method will get the selected button for the object.
// Each object is associated with a number:
// 1 = line
// 2 = oval
// 3 = rect
// 4 = filled rect
// 5 = filled oval
// 6 = edit button
return selectedButton;
}
public void setSelected (int selectedButton) {
// This sets the object that was selected
this.selectedButton = selectedButton;
canvas.thisShape(this.selectedButton);
}
class DrawButton extends Canvas implements MouseListener{
// This class defines a canvas that will act like a button,
// where, when clicked on, the background color will change
// from red to green to indicate it has been selected. The
// buttons to select objects with are constructed from this
// class.
private int id;
public DrawButton(){
addMouseListener(this);
setSize(SIZE,SIZE);
}
public void mousePressed(MouseEvent e){
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public void mouseClicked(MouseEvent e){
// When the canvas receives a click, have the id get set of the
// canvas that was selected, and then repaint the frame,
setSelected(id);
repaint();
}
public void mouseReleased(MouseEvent e){
}
// The next three methods prevent the layout manager from doing
// strange things with resizing our little canvases.
public Dimension getMinimumSize () {
return new Dimension(SIZE, SIZE);
}
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
public Dimension getMaximumSize(){
return new Dimension(SIZE,SIZE);
}
public void paint(Graphics g) {
}
}
// These final five classes extend the DrawButton class, and put the
// picture of the object they represent on their faces. They are
// responsible for the selection of our objects.
class LineButton extends DrawButton {
public LineButton() {
super();
id = 1;
}
public void paint(Graphics g) {
if (id == getSelected()){
setBackground(Color.green);
changed = true;
// If this is the selected canvas, turn it green, then repaint
// the other four canvases, to "deselect" them, by turning them
// back to red.
rb.repaint();
ob.repaint();
frb.repaint();
fob.repaint();
eb.repaint();
}
else
setBackground(Color.red);
g.drawLine(4,4,SIZE-5,SIZE-5);
g.drawRect(0,0,SIZE-1,SIZE-1);
g.drawRect(1,1,SIZE-3,SIZE-3);
}
}
class RectButton extends DrawButton{
public RectButton(){
super();
id = 2;
}
public void paint(Graphics g) {
if (id == getSelected()){
setBackground(Color.green);
changed = true;
// If this is the selected canvas, turn it green, then repaint
// the other four canvases, to "deselect" them, by turning them
// back to red.
lb.repaint();
ob.repaint();
frb.repaint();
fob.repaint();
eb.repaint();
}
else
setBackground(Color.red);
g.drawRect(5,5,SIZE-10,SIZE-10);
g.drawRect(0,0,SIZE-1,SIZE-1);
g.drawRect(1,1,SIZE-3,SIZE-3);
}
}
class OvalButton extends DrawButton{
public OvalButton(){
super();
id = 3;
}
public void paint(Graphics g){
if (id == getSelected()){
setBackground(Color.green);
changed = true;
// If this is the selected canvas, turn it green, then repaint
// the other four canvases, to "deselect" them, by turning them
// back to red.
lb.repaint();
rb.repaint();
frb.repaint();
fob.repaint();
eb.repaint();
}
else
setBackground(Color.red);
g.drawOval(5,5,SIZE-10,SIZE-10);
g.drawRect(0,0,SIZE-1,SIZE-1);
g.drawRect(1,1,SIZE-3,SIZE-3);
}
}
class FRectButton extends DrawButton{
public FRectButton(){
super();
id = 4;
}
public void paint(Graphics g){
if(id == getSelected()){
setBackground(Color.green);
changed = true;
// If this is the selected canvas, turn it green, then repaint
// the other four canvases, to "deselect" them, by turning them
// back to red.
lb.repaint();
rb.repaint();
ob.repaint();
fob.repaint();
eb.repaint();
}
else
setBackground(Color.red);
g.fillRect(5,5,SIZE-10,SIZE-10);
g.drawRect(0,0,SIZE-1,SIZE-1);
g.drawRect(1,1,SIZE-3,SIZE-3);
}
}
class FOvalButton extends DrawButton{
public FOvalButton(){
super();
id = 5;
}
public void paint(Graphics g){
if(id == getSelected()){
setBackground(Color.green);
changed = true;
// If this is the selected canvas, turn it green, then repaint
// the other four canvases, to "deselect" them, by turning them
// back to red.
lb.repaint();
rb.repaint();
ob.repaint();
frb.repaint();
eb.repaint();
}
else
setBackground(Color.red);
g.fillOval(5,5,SIZE-10,SIZE-10);
g.drawRect(0,0,SIZE-1,SIZE-1);
g.drawRect(1,1,SIZE-3,SIZE-3);
}
}
class EditButton extends DrawButton{
public EditButton(){
super();
id = 6;
}
public void paint(Graphics g){
if(id == getSelected()){
setBackground(Color.green);
changed = true;
// If this is the selected canvas, turn it green, then repaint
// the other four canvases, to "deselect" them, by turning them
// back to red.
lb.repaint();
rb.repaint();
ob.repaint();
frb.repaint();
fob.repaint();
}
else
setBackground(Color.red);
// This draws a funky little cursor for editing
g.drawLine(7,7,7,18);
g.drawLine(7,7,18,7);
g.drawLine(7,18,18,7);
g.drawLine(11,13,16,16);
g.drawLine(12,12,17,17);
g.drawLine(13,11,18,18);
g.drawLine(11,13,15,15);
g.drawRect(0,0,SIZE-1,SIZE-1);
g.drawRect(1,1,SIZE-3,SIZE-3);
}
}
}