/* * JFLAP - Formal Languages and Automata Package * * * Susan H. Rodger * Computer Science Department * Duke University * August 27, 2009 * Copyright (c) 2002-2009 * All rights reserved. * JFLAP is open source software. Please see the LICENSE for terms. * */ package gui.sim; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import javax.swing.JPanel; import automata.Automaton; import automata.Configuration; /** * The ConfigurationPane is the pane where the configurations are * displayed and selected. * * @see automata.Configuration * * @author Thomas Finley */ public class ConfigurationPane extends JPanel implements ActionListener { /** * Creates a ConfigurationPane. The instance as created has * no configurations loaded into it yet. * * @param automaton * the automaton that configurations will come from */ public ConfigurationPane(Automaton automaton) { this.automaton = automaton; // this.setLayout(new FlowLayout(FlowLayout.LEFT)); } /** * Adds a configuration to the configuration pane. * * @param configuration * the configuration to add */ public void add(Configuration configuration) { add(configuration, ConfigurationButton.NORMAL); } /** * Adds configurations with the given state. * * @param configuration * the configuration to add q * * @param state * the state of the configuration, either NORMAL, ACCEPT, REJECT, * or FREEZE */ public void add(Configuration configuration, int state) { if (contains(configuration)) return; ConfigurationButton button = new ConfigurationButton(configuration, state); configurationToButtonMap.put(configuration, button); add(button); button.addActionListener(this); } /** * Given a configuration, returns the state for that configuration. * * @param configuration * the configuration * @return the state for that configuration */ public int getState(Configuration configuration) { return ((ConfigurationButton) configurationToButtonMap .get(configuration)).state; } /** * Determines if this pane already contains this configuration. * * @param configuration * the configuration to test for membership * @return true if the pane holds this transition, false * if it does not */ public boolean contains(Configuration configuration) { return configurationToButtonMap.containsKey(configuration); } /** * Sets a configuration to be a reject configuration. * * @param configuration * the configuration to set to be a reject configuration */ public void setReject(Configuration configuration) { ConfigurationButton button = (ConfigurationButton) configurationToButtonMap .get(configuration); if (button == null) return; if (button.state == ConfigurationButton.NORMAL) button.setState(ConfigurationButton.REJECT); button.doClick(); } /** * Sets a configuration to be frozen. Only normal configurations can be * frozen. * * @param configuration * the configuration to freeze */ public void setFrozen(Configuration configuration) { ConfigurationButton button = (ConfigurationButton) configurationToButtonMap .get(configuration); if (button == null) return; if (button.state == ConfigurationButton.NORMAL) button.setState(ConfigurationButton.FREEZE); button.doClick(); } public void setFocused(Configuration configuration) { ConfigurationButton button = (ConfigurationButton) configurationToButtonMap .get(configuration); if (button == null) return; if (button.state == ConfigurationButton.NORMAL) { //System.out.println("Setting color"); button.setState(ConfigurationButton.FOCUSED); button.doClick(); } } /** * @param configuration */ public void defocus(Configuration configuration) { setNormal(configuration); Configuration parent = configuration; parent.setFocused(false); while (parent.getParent() != null) { parent = parent.getParent(); parent.setFocused(false); } } /** * Sets a configuration to be normal. * * @param configuration * the configuration to thaw or unfocus */ public void setNormal(Configuration configuration) { ConfigurationButton button = (ConfigurationButton) configurationToButtonMap .get(configuration); if (button == null) return; if (button.state == ConfigurationButton.FREEZE) button.setState(ConfigurationButton.NORMAL); else if (button.state == ConfigurationButton.FOCUSED) button.setState(ConfigurationButton.NORMAL); button.doClick(); } /** * Removes a configuration from the configuration pane. * * @param configuration * the configuration to remove */ public void remove(Configuration configuration) { Component comp = (Component) configurationToButtonMap .remove(configuration); if (comp == null) return; selected.remove(configuration); remove(comp); } /** * Removes all configurations from this pane. */ public void clear() { configurationToButtonMap.clear(); selected.clear(); super.removeAll(); } /** * Renders all components deselected. */ public void deselectAll() { selected.clear(); } /** * Returns an array of selected configurations. * * @return an array of selected configurations */ public Configuration[] getSelected() { return (Configuration[]) selected.toArray(new Configuration[0]); } /** * Returns an array of all configurations. * * @return an array of all configurations */ public Configuration[] getConfigurations() { return (Configuration[]) configurationToButtonMap.keySet().toArray( new Configuration[0]); } /** * Returns an array of configurations that are, as far as is known, valid * configurations for moving to other configurations. * * @return an array of "valid" configurations */ public Configuration[] getValidConfigurations() { // A state is valid for return if it is normal. ArrayList list = new ArrayList(); Iterator it = configurationToButtonMap.values().iterator(); while (it.hasNext()) { ConfigurationButton button = (ConfigurationButton) it.next(); if (button.state == ConfigurationButton.NORMAL || button.state == ConfigurationButton.FOCUSED) list.add(button.getConfiguration()); } return (Configuration[]) list.toArray(new Configuration[0]); } /** * Clears out all configurations which are "final" configurations, i.e., * those that are marked either as accept or reject configurations. */ public void clearFinal() { // Avoid concurrent modification exceptions. ArrayList list = new ArrayList(); list.addAll(configurationToButtonMap.values()); Iterator it = list.iterator(); while (it.hasNext()) { ConfigurationButton button = (ConfigurationButton) it.next(); if (button.state == ConfigurationButton.ACCEPT || button.state == ConfigurationButton.REJECT) remove(button.getConfiguration()); } } /** * Clears old all configurations which are not frozen. */ public void clearThawed() { // Avoid concurrent modification exceptions. ArrayList list = new ArrayList(); list.addAll(configurationToButtonMap.values()); Iterator it = list.iterator(); while (it.hasNext()) { ConfigurationButton button = (ConfigurationButton) it.next(); if (button.state != ConfigurationButton.FREEZE) remove(button.getConfiguration()); } } /** * Responds to actions, presumably generated by some button belonging to * this view. * * @param e * the action event generated */ public void actionPerformed(ActionEvent e) { ConfigurationButton button = null; try { button = (ConfigurationButton) e.getSource(); } catch (ClassCastException ex) { return; // Then, we don't care. } Configuration config = button.getConfiguration(); if (!configurationToButtonMap.containsKey(config)) return; if (button.isSelected()) selected.add(config); else selected.remove(config); distributeSelectionEvent(new ConfigurationSelectionEvent(this)); } /** * Adds a ConfigurationSelectionListener to this object. * * @param listener * the listener to add */ public void addSelectionListener(ConfigurationSelectionListener listener) { selectionListeners.add(listener); } /** * Remove a ConfigurationSelectionListener from this object. * * @param listener * the listener to remove */ public void removeSelectionListener(ConfigurationSelectionListener listener) { selectionListeners.remove(listener); } /** * Gives a ConfigurationSelectionEvent to all listeners. * * @param listener * the listener to add */ void distributeSelectionEvent(ConfigurationSelectionEvent event) { Iterator it = selectionListeners.iterator(); while (it.hasNext()) { ConfigurationSelectionListener listener = (ConfigurationSelectionListener) it .next(); listener.configurationSelectionChange(event); } } /** The configurations in this pane will be from this automaton. */ private Automaton automaton; /** The map from configurations to their buttons. */ private HashMap configurationToButtonMap = new HashMap(); /** The set of selected configurations. */ private HashSet selected = new HashSet(); /** The set of listeners to selection events. */ private transient HashSet selectionListeners = new HashSet(); }