import java.awt.*; import java.applet.Applet; /**

This class defines a graphics Frame, initializes the Applet context and specifies handling for the WINDOW_DESTROY exit event, for a class Room object or for an array of Room objects. The class Room implements the graphics window of Feldman's "Spider graphics" programs developed in the textbook "Ada 95".

The AppFrame object in creating a Room, allows proper bootstrapping of the Graphics object (context). The objects of this class inherit from Frame (they can be drawn into, they can be added into a container, resized, shown, and so on). When creating a new Frame object, the AppFrame() constructor expects an Applet object as its second parameter, and calls the Applet.init() method as its last order of business. This round-about initialization is necessary for resolving a Catch-22 situation, as follows:

The Graphics context of a drawable (surface) is unavailable until the drawable is installed in its container. Prior to this, getGraphics() would return null, so it is useless to call it when the drawable is instantiated (with "new ..."). By making the drawable an Applet, it can be instantiated without calling getGraphics() in the constructor. Instead, the init() method of the Applet object (overridden in the subclass) is used to call getGraphics(). The AppFrame container object can thus install the drawable component, Applet, into its Frame first, using the add(), resize() and show() methods of Frame. Thereafter the AppFrame() constructor calls the Applet init() method. The init() method is overridden in the Room subclass in a manner to call getGraphics() and assign the returned value to the "Graphics mySurface" field of Room:

    mySurface  = getGraphics();

Other drawable classes could be substituted instead of Applet: for example Room could subclass Canvas. Canvas does not have an "init()" method, but a non-overriding init() method could be defined in Room nonetheless; or a different method name could be used. In this case the type of the second parameter of the AppFrame constructor would have to be the subclass name Room: the parent class Canvas could not be used since it does not have an init() method. @author Michael B. Feldman, The George Washington University (Ada 95) @author Istvan Mohos (Java translation) @see Room @see Spider */ class AppFrame extends Frame { /** Creates a new Frame titled according to the first parameter, resizing it to the width and height passed as the last two parameters, and containing the Applet passed as the second parameter. After calling the Frame.show() method, initializes the passed Applet with a call to Applet.init(). @param title the String to be displayed in the Frame's title bar. @param anyApplet the Applet object to be installed in this Frame. @param wide the desired width of the Frame, in pixels. @param high the desired height of the Frame, in pixels. */ public AppFrame(String title, Applet anyApplet, int wide, int high) { super(title); // create the frame this.add("Center", anyApplet); // add applet to frame this.resize(wide, high); // set initial size this.show(); // show frame and component Insets insets = insets(); anyApplet.resize(wide - insets.right - insets.left, high - insets.top - insets.bottom); this.show(); anyApplet.init(); // initialize the applet } // end of AppFrame constructor /** Creates a new Frame titled according to the first parameter, resizing it to the width and height passed as the last two parameters, and containing the array of Applets passed as the second parameter. After calling the Frame.show() method, initializes each element of the passed Applet array with a call to Applet.init(). @param title the String to be displayed in the Frame's title bar. @param appletArray the Applet objects to be installed in this Frame. @param wide the desired width of the Frame, in pixels. @param high the desired height of the Frame, in pixels. */ public AppFrame(String title, Applet[] appletArray, int wide, int high) { super(title); // create the frame this.resize(wide, high); // set initial frame size this.show(); // won't have insets before this Insets insets = insets(); int appWide = (wide - insets.right - insets.left - 13 * appletArray.length) / appletArray.length; int appHigh = high - insets.top - insets.bottom - 2; setLayout(new FlowLayout(FlowLayout.RIGHT, appWide, 0)); for (int i = 0; i < appletArray.length; i++) add("Center", appletArray[i]); this.show(); // this time to show the applets // Initialize and resize the applets for (int i = 0; i < appletArray.length; i++) { appletArray[i].resize(appWide, appHigh); appletArray[i].init(); } } // end of AppFrame constructor /** Overrides java.awt.Component.handleEvent() to be able to exit the application on a mouse click over the "X" button in the top right corner of the graphics window. Handles only the WINDOW_DESTROY event, by calling System.exit(). All other events are deferred to the Component superclass. @param anyEvent an Event ID delivered to this object. @return System.exit() does not return. In all other cases, the boolean value returned by the event handler of the superclass, Component.handleEvent(), is returned to the caller. @see java.awt.Component.handleEvent @see java.lang.System.exit */ public boolean handleEvent(Event anyEvent) { if (anyEvent.id == Event.WINDOW_DESTROY) System.exit(0); return super.handleEvent(anyEvent); } } // end definition of class AppFrame