This chapter uses the source code of ColorChooser, ColorChooserDialog, and ButtonDialog as sample code. All are found in the borland.jbcl.control package. You might want to examine the actual source code as you read through this chapter.
Both of these methods provide a framework to modify. You might want to edit your resulting class so that it extends borland.jbcl.control.ButtonDialog. ButtonDialog also extends java.awt.Dialog, but it is designed to be used as a base class for any dialog box with one or more buttons.
To make a bean out of a dialog box, you must wrap the real dialog class with a separate class that has the dialog class as a subcomponent. The wrapper class surfaces the properties and events, delegates their handling to the actual dialog box when it is instantiated.
Wrapping the dialog box consists of several tasks; the following sections discuss each of these in detail:
If you use the JavaBean Wizard to begin, select java.lang.Object as the class to inherit from. If you use the Class Wizard, select the option to have a default (parameterless) constructor.
Later you’ll register this wrapper class as a listener for window events that occur in your dialog box and you’ll write the code to respond to the window events your dialog box needs to pay attention to.
public class ColorChooser implements WindowListener { ...ColorChooser has four different constructors including the very important parameterless constructor:
public ColorChooser(Frame frame, String title, Color value) { this.frame = frame; this.title = title; this.value = value; if (frame != null) dialog = new ColorChooserDialog(frame, title, value); ) public ColorChooser(Frame frame, String title) { this(frame, title, null); } public ColorChooser(Frame frame) { this(frame, "", null); ) public ColorChooser() { parameterless constructor required to be JavaBean this(null, "", null); }
protected ColorChooserDialog dialog;
if (frame != null) dialog = new ColorChooserDialog(frame, title, value);
To add a frame property to your wrapper class, write the read and write access methods for frame:
public void setFrame(Frame frame) { this.frame = frame; } public getFrame() { return frame; )
Your application must also obtain another type of user input: which button the user chose. The user might display the dialog box, then put it away again without making any changes to the values.
First you’ll see how to retrieve the values the user enters in the dialog box, then how to track which button the user chose.
The ColorChooser is interested in only one value: the color the user selects. Therefore, ColorChooser contains the code to get and set just one property, the value property. This is how the getter and setter for the value property are written for ColorChooser:
public void setValue(Color value) { this.value = value; if (dialog != null) dialog.setValue(value); } public Color getValue() { if (dialog != null) value = dialog.getValue(); return value; )Note that both setValue() and getValue() call the same methods in the dialog class. This is how the same methods are written in ColorChooserDialog:
public void setValue(Color value) { panel.setColor.getColorValue(); } public Color getValue() { return panel.getColorValue(); }The property read and write access methods you write for your wrapper class should be capable of getting and setting a property value even if the actual dialog class is not instantiated yet. When the dialog class is instantiated, they should delegate the getting and setting to the dialog class, just as the read and write access methods for the value property of ColorChooser do.
public void setResult(int i) { result = i; if (dialog != null) dialog.setResult(result); } public int getResult() { if (dialog != null) result = dialog.getResult(); return result; }Again you can see that if the dialog class is instantiated, the same method is called in the dialog class. In this case, getResult() and setResult() are not in ColorChooserDialog, but in ButtonDialog, which ColorChooserDialog extends. So here are the result getter and setter methods in ButtonDialog:
public void setResult(int id) { result = buttonFromID(id); } public int getResult() { return result != null ? result.getID() : NONE; }The id parameter in setResult() can be one of the several constants in ButtonDialog that identify a particular button. There are constants for OK, YES, NO, CANCEL, DONE, HELP, APPLY, and so on. The getResult() method identifies which button the user chose.
public void show() { setVisible(true) }The show() method, or the method it calls, should instantiate the actual dialog class, using the value of the frame property as the parent frame in the dialog’s constructor. After the dialog is instantiated, you should set the properties in the dialog class to the values stored in the properties of the same name in the wrapper class.
Because the show() method of ColorChooser simply sets the visible property to true, here is the code of the setVisible() method:
public void setVisible(boolean visible) { if (visible) { if (dialog == null) { if (frame == null) // if frame isn’t set, throw exception throw new IllegalStateException(Res.getString(Res.NoFrame)); dialog = new ColorChooserDialog(frame, title, value); // instantiates dialog class dialog.setResult(result); // sets result of dialog class dialog.addWindowListener(this); dialog.addActionListener(actionMulticaster); } if (frame.isShowing()) focus = frame.getFocusOwner(); dialog.show(); // calls show() of dialog class } else { if (dialog != null) dialog.setVisible(false); } }setVisible() checks to see if the frame property has a value. If it doesn’t, an exception is thrown; otherwise, the actual dialog class is instantiated with the frame value.
Next the value of the result property is used to set the result property of the newly instantiated dialog. The wrapper class registers itself as a listener for window events. Later, the show() method of the dialog class is called; show() is defined in the ButtonDialog class.
public void addActionListener(ActionListener l) { actionMulticaster.add(l); } public void removeActionListener(ActionListener l) { actionMulticaster.remove(l); }actionMulticaster is declared as an instance of the ActionMulticaster class, which maintains a list of listeners for action events:
protected transient ActionMulticaster actionMulticaster = new ActionMulticaster();If your dialog class extends the ButtonDialog class, that’s all you need to do to make your dialog box capable of generating action events.
If you don’t use ButtonDialog, you must add each button in the dialog as a listener for action events. You must also write the method that dispatches an ActionEvent to all listeners. Examine the setButtonSet() method of ButtonDialog to see how buttons are registered as listeners for actions events, and look at the actionPerformed() and processActionEvent() methods to see how action events are dispatched.
The WindowListener interface has seven methods to implement:
Add each of these methods to the wrapper class and implement them with empty bodies. Then decide which of these you want to write more code for.
The ColorChooser added additional code for the windowClosing() and windowClosed() events only:
public void windowOpened(WindowEvent e) {} public void windowClosing(WindowEvent e) { value = dialog.getValue(); result = dialog.getResult(); } public void windowClosed(WindowEvent e) { if (dialog != null) { value = dialog.getValue(); result = dialog.getResult(); } dialog = null; if (frame.isShowing()) { if (focus != null) focus.requestFocus(); else frame.requestFocus(); } }Note that each of these retrieve the current value and result property values from the dialog box and store them in the properties with the same name in the wrapper class. The user’s application can then retrieve these values from the wrapper class and use them as needed.
If the dialog box you create is modeless, the call to the show() method returns as soon as the dialog box appears. For modeless dialog boxes, show() does not wait for the dialog box to be closed by the user. Code that uses a modeless dialog must listen to dialog events you surface to know when to respond to user actions.
If the dialog box is modal, your application can also listen for events within the dialog box, or it can wait for the show() method to return. Because the show() method of a modal dialog box does not return until the user closes the dialog box, your code can wait until then to check the result code and any property values.