| C:\upload\java\Life\source\java\PopupWindow.java |
/******************************************************************* Next is for pop up windows. ******************************************************************** */ import java.awt.*; import java.awt.event.*; final class PopupWindow implements ActionListener, Constants, // Program constants, and Strings, WindowListener // Strings. { private ScreenLocations screenLocations; private Frame parentFrame; // To what things are attached. private String windowName; // What we call the window, title bar. private Dialog window; // Displays the message & the buttons. private String buttonPressed; /******************************************************************* Constructor follows: ******************************************************************** */ PopupWindow(Frame parentFrame, ScreenLocations screenLocations, String windowName) { // Are there errors? Next handles this: String errorString = ((parentFrame != null) && (screenLocations != null)) ? NULL_STRING : "parentFrame = " + parentFrame + " screenLocations = " + screenLocations; if (!errorString.equals(NULL_STRING)) { System.out.println("Error, null pointer, PopupWindow " + errorString); return; } // Our data is good. Done with error handling. this.parentFrame = parentFrame; this.screenLocations = screenLocations; // More error handling. We are very careful. if ((parentFrame == null) || (screenLocations == null)) { System.out.println("Failure, PopupWindow, parentFrame = " + parentFrame + " screenLocations = " + screenLocations + ". Fatal error."); System.exit(0); } this.windowName = windowName; buttonPressed = INVALID_BUTTON; } // Overidden methods from WindowListener interface: // Only < windowClosing > matters: user hit the "x" "close me" icon. public void windowClosing(WindowEvent e) { window.setVisible(false); // Time to get out. Continue. System.exit(0); // Kill everything. } public void windowActivated(WindowEvent e) {} public void windowDeactivated(WindowEvent e){} public void windowDeiconified(WindowEvent e){} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} public void windowClosed(WindowEvent e) {} /******************************************************************* These windows must be ordered to go away when there are no buttons, via < Dismiss() >, next. ******************************************************************** */ protected void Dismiss() { window.setVisible(false); } /******************************************************************* Utility routine < makeLabels > turns strings into a label array that can be placed on a layout. ******************************************************************** */ private Label [] makeLabels(String [] message) { int i; // Loop variable int len; // Size of array we allocate. if (message != null) // Always assume the calling routine may { // have given us garbage. len = message.length; } else { len = 0; // We may return a null array. } Label [] ms = new Label[len]; for (i = 0; i < len; i++) { ms[i] = new Label(message[i]); } return (ms); } /******************************************************************* Utility routine < makeButtons > turns strings into a button array that can be placed on a layout. These are used in the constructors, below, so placed above. ******************************************************************** */ private Button [] makeButtons(String [] buttonNames) { int i; // Loop variable int len; // Size of array we allocate. if (buttonNames != null) // Always assume the calling routine may { // have given us garbage. len = buttonNames.length; buttonPressed = buttonNames[0]; // Default button will be first. If we } // close via that "x" icon, this is chosen. else { len = 0; // We may return a null array. } Button [] buttons = new Button[len]; for (i = 0; i < len; i++) { buttons[i] = new Button(buttonNames[i]); } return (buttons); } /******************************************************************* Notes: this object has six overloaded means of calling its main routine. Sometimes the calling module wishes to display an array of strings, sometimes a single string. Sometimes there is one button, sometimes several buttons. The implementation should be "invisible" to the caller. And in the first two constructor there are no buttons, and the option of an array of strings or a single string. Note the liberal use of the utility routines < makeLabels > and < makeButtons >. These are below, and take an array of strings and turn them into an array of either: 1) Labels holding said strings. 2) Buttons with the given string as their name. The real dirty work takes place in routine < utilityToSetUpPopupWindow >, which all four constructors call. ******************************************************************** */ // First constructor for an array of messages and no buttons protected final void ShowMessage(String [] message) // Display several strings { utilityToSetUpPopupWindow(makeLabels(message), // Used by all constructors null); // No buttons. } // A single string, no buttons: protected final void ShowMessage(String message) // Display several strings { String [] labelStringArray = new String[1]; labelStringArray[0] = message; utilityToSetUpPopupWindow(makeLabels(labelStringArray), // Used by all constructors null); // No buttons. } // An array of labels and buttons: protected final void ShowMessage(String [] message, String [] buttonNames) // Display several strings w/ several buttons { utilityToSetUpPopupWindow(makeLabels(message), makeButtons(buttonNames)); // Used by all constructors } // For an array of messages and a single button: protected final void ShowMessage(String [] message, String buttonName) // Display several strings { String [] StringArray = new String[1]; StringArray[0] = buttonName; utilityToSetUpPopupWindow(makeLabels(message), makeButtons(StringArray)); // Used by all constructors } // For an a single message and an array of buttons: protected final void ShowMessage(String message, String [] buttonNames) // Display several strings { String [] labelStringArray = new String[1]; labelStringArray[0] = message; utilityToSetUpPopupWindow(makeLabels(labelStringArray), makeButtons(buttonNames)); // Used by all constructors } // For an a single message and a single button: protected final void ShowMessage(String message, String buttonName) // Display several strings { String [] StringArray = new String[1]; StringArray[0] = buttonName; String [] labelStringArray = new String[1]; labelStringArray[0] = message; utilityToSetUpPopupWindow(makeLabels(labelStringArray), makeButtons(StringArray)); // Used by all constructors } /******************************************************************* Next sets up actual window that dispays the message. The real dirty work lives in the next, which uses class < displayMessage >. ******************************************************************** */ private final void utilityToSetUpPopupWindow(Label [] ms, Button [] buttons) { /* Why do we have the next boolean? Because of how Java works. If the window is modal ("true" = "can't do anything until I am dismissed"), and there are no buttons, the Dialog can't be destroyed. It seems it must happen in the < actionPerformed > routine, and this is never called when there are no buttons. When there are no buttons, the calling program dismisses the Dialog via a call to routine < Dismiss >. Seems like a lot of bother, but that's how Java works. I tried a few books. */ boolean buttonsExist = (buttons == null) ? false : true; window = new displayMessage(parentFrame, windowName, // Window's name. buttonsExist, // Note above comment text. ms, // Our array of labels buttons); // Our array of buttons. window.addWindowListener(this); window.pack(); // Get a sensible size. // Where do we go on the screen? window.setLocation(screenLocations.GetLocationOnScreen(window)); window.setVisible(true); // Show me. } /* ********************************************************************* Was the question answered (assuming there was one)? The next is the interface by which this class communicates with the outside world. ********************************************************************* */ protected final boolean ButtonPressed() { // Note that we initialized string < buttonPressed > to the first in the list. return ( ! buttonPressed.equals(INVALID_BUTTON)); } /******************************************************************* Calling routine needs to know who was pressed, the next, < WhichButtonWasPressed() >, tells it. ******************************************************************** */ protected final String WhichButtonWasPressed() { return buttonPressed; } /******************************************************************* Routine < actionPerformed > follows. Null body; we don't use it. ******************************************************************** */ public void actionPerformed (ActionEvent e) {} // Shouldn't be called. /******************************************************************* Next is to display things. ******************************************************************** */ public class displayMessage extends Dialog implements ActionListener, Constants { private Frame parentFrame; // Constructor: displayMessage(Frame parentFrame, String title, boolean modal, Label [] message, Button [] buttons) { super(parentFrame, title, modal); this.parentFrame = parentFrame; int i; // Loop variable. // Set up the layout. Grid bag layouts are tedious, but they are effective. GridBagLayout gridbag = new GridBagLayout(); setBackground(Color.gray); GridBagConstraints constraints = new GridBagConstraints(); setLayout(gridbag); setFont(STANDARD_FONT); /* Take care of adding buttons & setting up their action listeners, but only if there *are* buttons. */ if (buttons != null) { Cursor ourCursor = new Cursor(Cursor.HAND_CURSOR); // What cursor we use. for (i = 0; i < buttons.length; i++) { add(buttons[i]); buttons[i].addActionListener(this); buttons[i].setCursor(ourCursor); } } // Now for the tedious setting of the Grid Bag Layout. // We try to make this as painless as possible. // First: the label < message >. if (message != null) { /* The parameter < buttons > may be null. We need to account for the size of the board. Otherwise we get "used null pointer" problems. If buttons is non-null, we eat all columns (see setting of GridBagLayout below); note this routine sets Buttons across, Labels down. If buttons is */ int len = (buttons == null) ? 1 : buttons.length; for (i = 0; i < message.length; i++) { add(message[i]); buildConstraints(constraints, 0, // Column one i, // Row *i* -- note len, // Eat all columns // Note parameter < len >. 1, // Eats one row, and ... 0, // all columns -- gets 0 100 / (message.length + 1), SMALL_PADDING, SMALL_PADDING); constraints.fill = GridBagConstraints.HORIZONTAL; gridbag.setConstraints(message[i], constraints); } } // Second: the buttons. Note labels went down, and the buttons // go across, in one row. if (buttons != null) // If we have no buttons, do nothing. { /* The parameter < buttons > may be null. We need to account for the size of the board. Otherwise we may get "used null pointer" problems. */ int len = (message == null) ? 1 : message.length + 1; /* The "+ 1" (distinction from how < len > was defined above in case of Labels) is because Labels go down, and this routine sets buttons across. If we have labels, we want the buttons one row down from bottom of labels. */ for (i = 0; i < buttons.length; i++) { buildConstraints(constraints, i, // Column i len, // Note defined above: // last row, or only row. 1, // Eats one column 1, // Eats one row, and ... 1, // one colum 100 / (len + 1), SMALL_PADDING, SMALL_PADDING); constraints.fill = GridBagConstraints.HORIZONTAL; gridbag.setConstraints(buttons[i], constraints); } } // End "if (buttons != null)" clause } // End < displayMessage > constructor. /******************************************************************* Next is the standard Insets method ******************************************************************** */ public Insets getInsets() { return new Insets(DEFAULT_INSET, DEFAULT_INSET, DEFAULT_INSET, DEFAULT_INSET); } /******************************************************************* Next is the actionPerformed method. It only gets the button name. ******************************************************************** */ public void actionPerformed (ActionEvent e) { if (e.getSource() instanceof Button) { // Who was pressed? buttonPressed = ((Button) e.getSource()).getLabel(); setVisible(false); // Done. Get out. } } /******************************************************************* Next is the standard GridBagConstraints method ******************************************************************** */ void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy, int padx, int pady) { gbc.gridx = gx; gbc.gridy = gy; gbc.gridwidth = gw; gbc.gridheight = gh; gbc.weightx = wx; gbc.weighty = wy; gbc.ipadx = padx; gbc.ipady = pady; } } // End public class displayMessage } // End class PopupWindow