package edu.princeton.toy.choosers; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import edu.princeton.swing.*; import edu.princeton.toy.lang.*; /** * TPerformanceChooserPane manages * * @author btsang * @version 7.1 */ public class TPerformanceChooserPane extends JPanel implements ChangeListener { private static final String CLASS_STRING = TPerformanceChooserPane.class.toString(); /** * The command that causes the TPerformanceChooserPane to update the JTextFields in response * to a change in the slider positions. */ public static final String UPDATE_COMMAND = CLASS_STRING + "#updateCommand"; private int clockPeriods[]; private int refreshRates[]; private JSlider clockPeriodSlider; private JSlider refreshRateSlider; private PTextField clockPeriodTextField; private PTextField refreshRateTextField; /** * Creates a new TPerformanceChooserPane which can only take the specified values for * clock period and refresh rate. */ public TPerformanceChooserPane(int clockPeriods[], int refreshRates[]) { super(new GridBagLayout()); this.clockPeriods = new int[clockPeriods.length]; this.refreshRates = new int[refreshRates.length]; for (int ctr = 0; ctr < clockPeriods.length; ctr++) this.clockPeriods[ctr] = clockPeriods[ctr]; java.util.Arrays.sort(this.clockPeriods); for (int ctr = 0; ctr < refreshRates.length; ctr++) this.refreshRates[ctr] = refreshRates[ctr]; java.util.Arrays.sort(this.refreshRates); add( new JLabel("Target Clock Period"), new GridBagConstraints( 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); clockPeriodTextField = new PTextField(12); clockPeriodTextField.setEditable(false); clockPeriodTextField.setBackground(null); clockPeriodTextField.setDisabledTextColor(Color.black); add( clockPeriodTextField, new GridBagConstraints( 1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); { // Prepare the clock period slider clockPeriodSlider = new JSlider( JSlider.HORIZONTAL, 0, clockPeriods.length - 1, 7 ); clockPeriodSlider.setMinorTickSpacing(1); clockPeriodSlider.setMajorTickSpacing(10); clockPeriodSlider.setPaintTicks(true); clockPeriodSlider.setPaintTrack(true); clockPeriodSlider.setSnapToTicks(true); clockPeriodSlider.addChangeListener(this); add( clockPeriodSlider, new GridBagConstraints( 0, 1, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0 ) ); } add( new JLabel("Refresh Rate"), new GridBagConstraints( 0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); refreshRateTextField = new PTextField(12); refreshRateTextField.setEditable(false); refreshRateTextField.setBackground(null); refreshRateTextField.setDisabledTextColor(Color.black); add( refreshRateTextField, new GridBagConstraints( 1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); { // Prepare the clock period slider refreshRateSlider = new JSlider( JSlider.HORIZONTAL, 0, refreshRates.length - 1, 7 ); refreshRateSlider.setMinorTickSpacing(1); refreshRateSlider.setMajorTickSpacing(10); refreshRateSlider.setPaintTicks(true); refreshRateSlider.setPaintTrack(true); refreshRateSlider.setSnapToTicks(true); refreshRateSlider.addChangeListener(this); add( refreshRateSlider, new GridBagConstraints( 0, 3, 2, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0 ) ); add( new JLabel("* spr = steps per refresh"), new GridBagConstraints( 0, 4, 2, 1, 1.0, 1.0, GridBagConstraints.SOUTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); } } /** * Returns the clock period (in milliseconds) that the user selected. * * @return The clock period (in milliseconds) that the user selected. This value is guaranteed * to be one of the values in the array that this TPerformanceChooserPane was constructed with. */ public int getClockPeriod() { return clockPeriods[clockPeriodSlider.getValue()]; } /** * Sets the clock period (in milliseconds) which the TPerformanceChooserPane should display. * * @param clockPeriod The clock period (in milliseconds) which the TPerformanceChooserPane * should display. If the argument is not in the list of choosable clock periods, the nearest * valid clock period will be selected. */ public void setClockPeriod(int clockPeriod) { int index = 0; while (index < clockPeriods.length && clockPeriods[index] < clockPeriod) index++; if (index == 0) { clockPeriodSlider.setValue(0); } else if (index < clockPeriods.length) { if (clockPeriods[index] - clockPeriod < clockPeriod - clockPeriods[index - 1]) clockPeriodSlider.setValue(index); else clockPeriodSlider.setValue(index - 1); } else { clockPeriodSlider.setValue(clockPeriods.length - 1); } } /** * Returns the refresh rate (in steps per refresh) that the user selected. * * @return The refresh rate (in steps per refresh) that the user selected. This value is * guaranteed to be one of the values in the array that this TPerformanceChooserPane was * constructed with. */ public int getRefreshRate() { return refreshRates[refreshRateSlider.getValue()]; } /** * Sets the refresh rate (in steps per refresh) which the TPerformanceChooserPane should * display. * * @param refreshRate The refresh rate (in steps per refresh) which the TPerformanceChooserPane * should display. If the argument is not in the list of choosable clock periods, the nearest * valid clock period will be selected. */ public void setRefreshRate(int refreshRate) { int index = 0; while (index < refreshRates.length && refreshRates[index] < refreshRate) index++; if (index == 0) { refreshRateSlider.setValue(0); } else if (index < refreshRates.length) { if (refreshRates[index] - refreshRate < refreshRate - refreshRates[index - 1]) refreshRateSlider.setValue(index); else refreshRateSlider.setValue(index - 1); } else { refreshRateSlider.setValue(refreshRates.length - 1); } } /** * Performs a command based on the argument. * * @param command A string representing the command. Note that pointer equality (not string * equality) is tested here, so it is important to use the string constants defined in this * class. An IllegalArgumentException will be thrown if the argument is invalid. * @return True iff the command was executed sucessfully. */ public synchronized boolean doCommand(String command, Object extraInfo) { //////////////////////////////////////////////////////////////////////////////////////////// if (command == UPDATE_COMMAND) { clockPeriodTextField.setText( clockPeriods[clockPeriodSlider.getValue()] + " ms" ); refreshRateTextField.setText( refreshRates[refreshRateSlider.getValue()] + " spr*" ); return true; } throw new IllegalArgumentException(); } /** * Implement ChangeListener to listen to changes in the checkbox states. */ public void stateChanged(ChangeEvent e) { doCommand(UPDATE_COMMAND, null); } }