CIS 211 - Computer Science II
Winter, 2003 - A. Hornof
Project written by Amit Goswami

Project 6

This project is due on Friday, March 7. It may, however, be submitted up until Wednesday, March 12, at 5 PM, with no late penalty whatsoever.

Purpose

This project will give you practice in the following:

  • Designing and coding a GUI using Java Swing
  • Using the MVC architecture with a GUI
  • Creating custom components by extending JComponent
  • Listening to mouse events

Overview

The main goal for this project is to port the command-based simulator you wrote for Project 5 to a graphical environment using Swing. In terms of the model-view-controller terminology, you would be changing the "view" to a GUI. Every user-interaction should take place in this GUI. The command line will be used solely for launching the program (and printing the exceptions, if any).

Program Specification

Project 6 builds on Project 5. You may build on your previous code or you may build on the solutions provided for the previous projects. You may not, however, start with any code written by other students in the class.

The Project 6 Addendum is officially part of the project specifications. You should check it at least at the beginning of each work session. Be sure to start the project early enough to have an opportunity to ask for clarification if necessary.

GUI Specification:

  • The main window of the program must be resizable.
  • An input text field is used to read in the commands from the user. After typing in the command, the return key-press should execute the command. Alternatively a button-click could also be used. After a command is executed, the text field is cleared for the next command.
  • To display the output, use a multi-line text field, such as a JTextArea. Since this field is only for displaying the output, it should be read-only. It should also be scrollable with the latest output showing. This component essentially behaves like the shell, except that it can only display text. All the "System.out.println" outputs in your Project 5 should now be redirected to this field.
  • The commands that take no arguments, including status, go, help, and quit can also be executed using buttons on the interface. Include buttons for each of these four commands such that a button-click on any of these will execute the corresponding command.
  • The most important part of the interface is a component that displays the map with its current state. This is similar to the output that the command show gave in Project 5. This map is visible all the time and is updated every time the go command is executed. The detailed specification for this component is as follows:
    • This component is a representation of the simulation world, hence its width and height should correspond to the width and height of the world (as read from the input file).
    • A grid consisting of solid lines is displayed on the map. You can choose an appropriate gap between two lines in this grid. For example, if the world width is 50, you might choose to display vertical lines at 0,5,10 and so on up to 50 on the X-axis. Same applies for horizontal lines on the Y-axis. The world size will be at most 101x101, and you can assume that we will not test with a world size less than 20x20.
    • The map resizes when the main window of the program is resized. The display of the map should update accordingly. For example, if the width of the window is increased, the width of the map will also increase and as a result the gap between the vertical lines in the grid will increase.
    • Include text labels showing coordinates at regular intervals on the X and Y axis, just like in Project 5. For your programming convenience, these labels may be on the map, rather than outside the axis. Try to get them outside of the grid, though.
    • A mouse click on the map will display the corresponding world coordinates (not pixel co-ordinates) in the output field. E.g. (45, 12).
    • A SimObject on the map is displayed by using the first two characters of its name, just like in Project 5. We will take advantage of the graphical environment and display Ships and Islands in different colors. You can choose any appropriate colors.

Other Specs:

Since all the user interaction is now Swing based, you will have to incorporate the following in your program:

  • As explained above, all the status messages go to the output text field.
  • For all questions requiring yes/no answers use JOptionPane.showConfirmDialog()
  • For all text inputs (such as reading in the file name) use JOptionPane.showInputDialog()
  • All fatal exceptions may be printed to the shell using System.err or System.out as usual.

Public Interface and Class responsibilities

For this project, you have the freedom of using any public interface that works well with your program. But keep in mind the rules of good design and modularity that we followed in the earlier projects. Read the above GUI specification carefully and note the details. You can choose to lay out the components in any manner, but the final result must be easy to use and tidy.

View class

  • The View class extends JFrame to create the window.
  • Create a public static method display(String) that is used by any part of the program to display textual output in the multi-line text field (such as a JTextArea).
  • MapPanel extends from JComponent and is used to draw the map as described in the GUI spec. It occurs as a private inner class in View. The only method that needs to be overridden is the paint(Graphics g) method.

Notes

  • We do not need the Keyboard class anymore since there is no command-based input.
  • The show command is redundant now since the map is always displayed.

Some advice on how to do it

  • For creating the GUI, design the interface before you start coding. Decide how the different components fit in the JPanels and what layout will work for each of the JPanels. You can even create the GUI as a separate program which you can substitute in place of View.java, once you have finalized the design.
  • For creating MapPanel, note the following:
    • The paint(Graphics) method of a component is called by Java when it needs to draw the component. Hence it is a good place to insert our custom-painting code. (Don't forget to call the super.paint method before you start drawing your stuff).
    • The paint(Graphics) method must never be called - only Java must call it. But you can make Java invoke it by calling the repaint() method. This notifies Java that this particular component needs to be repainted. Java will invoke the paint method when it next draws the interface (which is almost always instantly).
    • Look up the Graphics class in the API and find the methods used for drawing.
    • The origin of a Java Swing component is the top left corner (fourth quadrant). This means that when you plot something at (2,3) the point is located 2 units to the right of the Y-axis and 3 units to the bottom of the X-axis.
    • To plot a SimObject on the MapPanel, we need to translate its location point from its world-position to the pixel position. First translate the x and y co-ordinates based on the current size of the panel and the world size. The new point (x,y) is in the first quadrant since that is how our world coordinate system is. The next step is to convert 'y' to the fourth quadrant (x stays the same). The reverse process is done for translating a point from the pixel position to the world-position.
  • Implement the MouseListener interface to listen to mouse events. The addMouseListener() method can be used to add a mouse listener. An alternative to implementing a MouseListener is to extend the MouseAdapter class and override only the methods you need.

Grading Criteria

You will receive credit for programs that compile using the correct package declarations and that solve the problems as specified. You will not receive any credit for code that does not compile from the command line using Java 1.4.1. Any problems with your Project 5 solution must be fixed for this project.