import java.awt.*; import java.awt.event.*; import java.beans.*; import java.util.*; import utilities.gui.*; // for CardDeck, ChoiceKit public class PlugNPrayCustomizer extends Panel implements Customizer, ItemListener, ActionListener { protected final static int CUSTOMIZER_WIDTH = 220; protected final static int CUSTOMIZER_HEIGHT = 180; // The bean instance we're helping the designer to customize protected PlugNPray ourBean; // The GUI for this customizer consists of typical wizard pages. // The designer should flick through each page, going through the // logically grouped properties on each page. protected CardDeck wizardCards; protected Panel wizCard1, wizCard2; protected Hashtable checkboxes; // all our checkboxes are in here // wizCard1 components protected Choice expansionCardChoice; // expansion card type choice // wizCard2 components protected Checkbox advancedOnCheckbox; // advanced options enabler protected Button randomizeButton; protected PropertyChangeSupport butler; // pre-set expansion card types protected static String[] cardChoices = { "ISA 300 Baud Modem" , "Fullerene Obvious 3000", "Cumulus Logic MaxView" , "Matrix Annum 2D", "Sound Burper 12 and 1/2" , "Windy Day Beep Deluxe", "Egyptian Labs 200BC" , "Kawasaku Sound 128" }; //------------------------------------------------------------------- // The PlugNPrayCustomizer Constructor // This creates the entire multi-page Customizer GUI. //------------------------------------------------------------------- public PlugNPrayCustomizer() { // build the two pages of our "wizard" wizCard1 = buildPage1(); wizCard2 = buildPage2(); // combine the two cards into a CardDeck Component[] cards = {wizCard1 , wizCard2}; String[] cardNames = {"Select Card Type", "Go figure"}; wizardCards = new CardDeck(cardNames, cards); // and return the CardDeck as the Customizer itself setLayout(new BorderLayout()); add("Center", wizardCards); butler = new PropertyChangeSupport(this); } //------------------------------------------------------------------- // Build the GUI for page 1 of our wizard //------------------------------------------------------------------- protected Panel buildPage1() { Panel wizardPage; wizardPage = new Panel(); wizardPage.setLayout(new BorderLayout()); // construct expansion cards Choice list expansionCardChoice = ChoiceKit.buildChoiceFromStringList(cardChoices); // register with Choice so we can hear item selections expansionCardChoice.addItemListener(this); wizardPage.add("Center", expansionCardChoice); return wizardPage; } //------------------------------------------------------------------- // Build the GUI for page 2 of our wizard //------------------------------------------------------------------- protected Panel buildPage2() { Panel wizardPage; wizardPage = new Panel(); wizardPage.setLayout(new BorderLayout()); checkboxes = new Hashtable(); // maps cb label to cb // create 3 groups of mutually exlusive checkboxes // register with each checkbox so we can hear selections Panel advancedOptionsPanel = new Panel(); CheckboxGroup irqCBG = new CheckboxGroup(); CheckboxGroup dmaCBG = new CheckboxGroup(); CheckboxGroup iobCBG = new CheckboxGroup(); addCheckbox(advancedOptionsPanel, "IRQ 1", irqCBG); addCheckbox(advancedOptionsPanel, "IRQ 3", irqCBG); addCheckbox(advancedOptionsPanel, "IRQ 5", irqCBG); addCheckbox(advancedOptionsPanel, "IRQ 6", irqCBG); addCheckbox(advancedOptionsPanel, "DMA 0", dmaCBG); addCheckbox(advancedOptionsPanel, "DMA 1", dmaCBG); addCheckbox(advancedOptionsPanel, "DMA 8", dmaCBG); addCheckbox(advancedOptionsPanel, "IOBase 300", iobCBG); addCheckbox(advancedOptionsPanel, "IOBase 320", iobCBG); // add a button to "randomize" the selections of the checkboxes randomizeButton = new Button("Randomize"); randomizeButton.addActionListener(this); // see actionPerformed() advancedOptionsPanel.add(randomizeButton); // all of the above checkboxes are advanced, so disable by default enableAdvancedOptions(false); // add a special checkbox to enable/disable all of the above Panel advancedOptionsPanel2 = new Panel(); advancedOnCheckbox = new Checkbox("Advanced Options"); advancedOnCheckbox.addItemListener(this); advancedOptionsPanel2.add(advancedOnCheckbox); wizardPage.add("Center",advancedOptionsPanel); wizardPage.add("South", advancedOptionsPanel2); return wizardPage; } //------------------------------------------------------------------- // the preferred size of our customizer is of critical importance. // If we don't set this "preference", then our customizer appears // too small when flicking to the second page, which is large. //------------------------------------------------------------------- public Dimension preferredSize() { // override old-style for compat. return new Dimension(CUSTOMIZER_WIDTH, CUSTOMIZER_HEIGHT); } public Dimension getPreferredSize() { return preferredSize(); } //------------------------------------------------------------------- // java.beans.Customizer interface methods // // When the Customizer has already been constructed (i.e. the entire GUI), // the tool calls setObject() on us to tell which PlugNPray bean we're // customizing. So now we can find its property values and finish off // the GUI by setting the Choices, Checkboxes etc.. to their correct // state. //------------------------------------------------------------------- public void setObject(Object bean) { int value; // note which bean object we're customizing.. ourBean = (PlugNPray) bean; // get its property values and change GUI to correctly reflect them. String cardType = ourBean.getExpansionType(); expansionCardChoice.select(cardType); value = ourBean.getIRQ(); tickAssociatedCheckbox("IRQ" , value); value = ourBean.getDMA(); tickAssociatedCheckbox("DMA" , value); value = ourBean.getIOBase(); tickAssociatedCheckbox("IOBase", value); } //------------------------------------------------------------------- // PropertyChangeEvent listener management //------------------------------------------------------------------- public void addPropertyChangeListener(PropertyChangeListener listener) { butler.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { butler.removePropertyChangeListener(listener); } //------------------------------------------------------------------- // ItemListener interface method // This method receives item selection events from the Choice in // wizCard1 and the Checkboxes in wizCard2, so we need to differentiate. // Any selection means we have to modify the underlying target bean's // associated property, and fire a property change event into the world. //------------------------------------------------------------------- public void itemStateChanged(ItemEvent itemEvent) { Object source = itemEvent.getSource(); if ( source instanceof Checkbox ) { Checkbox cb = (Checkbox) source; // find out which checkbox got toggled if ( cb.getLabel().startsWith("IRQ") ) { int newValue = Integer.parseInt(cb.getLabel().substring(4)); ourBean.setIRQ(newValue); butler.firePropertyChange("IRQ", null, new Integer(newValue)); } else if ( cb.getLabel().startsWith("DMA") ) { int newValue = Integer.parseInt(cb.getLabel().substring(4)); ourBean.setDMA(newValue); butler.firePropertyChange("DMA", null, new Integer(newValue)); } else if ( cb.getLabel().startsWith("IOBase") ) { int newValue = Integer.parseInt(cb.getLabel().substring(7)); ourBean.setIOBase(newValue); butler.firePropertyChange("IOBase", null, new Integer(newValue)); } else { // advanced options checkbox toggled boolean advancedOptionsState = cb.getState(); enableAdvancedOptions(advancedOptionsState); } } else // if not a Checkbox, has to be our Choice if ( source instanceof Choice ) { Choice cardTypes = (Choice) source; String newValue = cardTypes.getSelectedItem(); ourBean.setExpansionType(newValue); butler.firePropertyChange("expansionType", null, newValue); } } //------------------------------------------------------------------- // ActionListener interface method // This is where our "Randomize" button (card 2) sends its clicks to. //------------------------------------------------------------------- public void actionPerformed(ActionEvent actionEvent) { randomizeOptions(); } //------------------------------------------------------------------- // Create & add a checkbox, and register us as listener. //------------------------------------------------------------------- protected void addCheckbox(Container group, String label, CheckboxGroup cbg) { Checkbox checkbox; // the checkbox we're going to add // all checkboxes initially unchecked since at this time (that is, // constructor time) we do not yet have access to the object we are // customizing (and hence can not get at its properties) checkbox = new Checkbox(label, false, cbg); // tag this checkbox as being part of the set of advanced options checkbox.setName("Advanced,"+ label); // register us as listener so we get tick/untick notifications checkbox.addItemListener(this); // this checkbox is part of a mutually exclusive group, so.. group.add(checkbox); // keep track of this checkbox and its label via a Hashtable checkboxes.put(label, checkbox); } //------------------------------------------------------------------- // tick checkbox associated with a particular property setting //------------------------------------------------------------------- protected void tickAssociatedCheckbox(String property, int value) { String cbLabel; Checkbox checkbox; // turn (e.g.) "IRQ" and 3 into "IRQ 3" (the checkbox label) cbLabel = property +" "+ String.valueOf(value); // find checkbox to select (lookup via Hashtable) checkbox = (Checkbox) checkboxes.get(cbLabel); // select it if ( checkbox != null ) { checkbox.setState(true); } } //------------------------------------------------------------------- // enable/disable all advanced opts in card 2 in one go. //------------------------------------------------------------------- protected void enableAdvancedOptions(boolean state) { Checkbox checkbox; // enable or disable all advanced option checkboxes Enumeration cbIterator = checkboxes.elements(); while ( cbIterator.hasMoreElements() ) { checkbox = (Checkbox) cbIterator.nextElement(); if ( checkbox.getName().startsWith("Advanced") ) { checkbox.setEnabled(state); } } // and the associated button randomizeButton.setEnabled(state); } //------------------------------------------------------------------- // randomize advanced options, tell rest of the world that we did so // and reflect new settings in GUI. //------------------------------------------------------------------- protected void randomizeOptions() { int[] irqOptions = {1,3,5,6}; int[] dmaOptions = {0,1,8}; int[] iobOptions = {300,320}; int chosenValue; // randomly change IRQ,DMA,IOBase properties (from legal values) chosenValue = pickValue(irqOptions); ourBean.setIRQ ( chosenValue ); butler.firePropertyChange("IRQ", null, new Integer(chosenValue)); chosenValue = pickValue(dmaOptions); ourBean.setDMA ( chosenValue ); butler.firePropertyChange("DMA", null, new Integer(chosenValue)); chosenValue = pickValue(iobOptions); ourBean.setIOBase ( chosenValue ); butler.firePropertyChange("IOBase", null, new Integer(chosenValue)); // re-massage checkbox state to reflect new values setObject(ourBean); } //------------------------------------------------------------------- // pick a random value from an array of ints //------------------------------------------------------------------- protected int pickValue(int[] listOfValues) { int pick; int listLength = listOfValues.length; if ( listLength == 0 ) { throw new IllegalArgumentException( "List of values to pick from is empty !"); } // pick a random index 0..N-1 into the array (but not N itself) pick = ((int) (Math.random()*listLength)) % listLength; return listOfValues[pick]; } } // End of Class PlugNPrayCustomizer