package de.unisiegen.gtitool.ui.model; import java.awt.Color; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.TreeSet; import javax.swing.event.EventListenerList; import org.jgraph.graph.DefaultGraphModel; import org.jgraph.graph.EdgeView; import org.jgraph.graph.GraphConstants; import de.unisiegen.gtitool.core.entities.Alphabet; import de.unisiegen.gtitool.core.entities.DefaultAlphabet; import de.unisiegen.gtitool.core.entities.DefaultState; import de.unisiegen.gtitool.core.entities.DefaultTransition; import de.unisiegen.gtitool.core.entities.State; import de.unisiegen.gtitool.core.entities.Symbol; import de.unisiegen.gtitool.core.entities.Transition; import de.unisiegen.gtitool.core.entities.listener.ModifyStatusChangedListener; import de.unisiegen.gtitool.core.exceptions.alphabet.AlphabetException; import de.unisiegen.gtitool.core.exceptions.state.StateException; import de.unisiegen.gtitool.core.exceptions.transition.TransitionException; import de.unisiegen.gtitool.core.exceptions.transition.TransitionSymbolOnlyOneTimeException; import de.unisiegen.gtitool.core.i18n.Messages; import de.unisiegen.gtitool.core.machines.AbstractMachine; import de.unisiegen.gtitool.core.machines.Machine; import de.unisiegen.gtitool.core.machines.listener.MachineChangedListener; import de.unisiegen.gtitool.core.preferences.listener.ColorChangedAdapter; import de.unisiegen.gtitool.core.storage.Attribute; import de.unisiegen.gtitool.core.storage.Element; import de.unisiegen.gtitool.core.storage.Modifyable; import de.unisiegen.gtitool.core.storage.Storable; import de.unisiegen.gtitool.core.storage.exceptions.StoreException; import de.unisiegen.gtitool.ui.jgraph.DefaultStateView; import de.unisiegen.gtitool.ui.jgraph.DefaultTransitionView; import de.unisiegen.gtitool.ui.jgraph.EdgeRenderer; import de.unisiegen.gtitool.ui.jgraph.GPCellViewFactory; import de.unisiegen.gtitool.ui.jgraph.JGTIBlackboxGraph; import de.unisiegen.gtitool.ui.jgraph.JGTIGraph; import de.unisiegen.gtitool.ui.jgraph.JGraphpadParallelSplineRouter; import de.unisiegen.gtitool.ui.jgraph.StateView; import de.unisiegen.gtitool.ui.preferences.PreferenceManager; import de.unisiegen.gtitool.ui.redoundo.MultiItem; import de.unisiegen.gtitool.ui.redoundo.RedoUndoHandler; import de.unisiegen.gtitool.ui.redoundo.RedoUndoItem; import de.unisiegen.gtitool.ui.redoundo.StateAddedItem; import de.unisiegen.gtitool.ui.redoundo.StateMovedItem; import de.unisiegen.gtitool.ui.redoundo.StatePositionChangedListener; import de.unisiegen.gtitool.ui.redoundo.StateRemovedItem; import de.unisiegen.gtitool.ui.redoundo.TransitionAddedItem; import de.unisiegen.gtitool.ui.redoundo.TransitionChangedItem; import de.unisiegen.gtitool.ui.redoundo.TransitionRemovedItem; /** * The Model for the {@link Machine}s * * @author Benjamin Mies * @author Christian Fehler * @version $Id$ */ public final class DefaultMachineModel implements DefaultModel, Storable, Modifyable { /** * The {@link Machine} version. */ private static final int MACHINE_VERSION = 1018; /** * The {@link DefaultGraphModel} for this model. */ private DefaultGraphModel graphModel; /** * The {@link JGTIGraph} containing the diagramm. */ protected JGTIBlackboxGraph jGTIGraph; /** * The {@link EventListenerList}. */ private EventListenerList listenerList = new EventListenerList (); /** * The {@link Machine} */ private Machine machine; /** * The {@link MachineChangedListener}. */ private MachineChangedListener machineChangedListener; /** * The {@link ModifyStatusChangedListener}. */ private ModifyStatusChangedListener modifyStatusChangedListener; /** * The {@link MultiItem}. */ protected MultiItem multiItem; /** * The {@link RedoUndoHandler} */ protected RedoUndoHandler redoUndoHandler; /** * The {@link StatePositionChangedListener}. */ private StatePositionChangedListener statePositionChangedListener; /** * A list of all {@link DefaultStateView}s */ private ArrayList < DefaultStateView > stateViewList = new ArrayList < DefaultStateView > (); /** * The {@link PDATableModel}. */ private PDATableModel pdaTableModel; /** * A list of all {@link DefaultTransitionView}s */ private ArrayList < DefaultTransitionView > transitionViewList = new ArrayList < DefaultTransitionView > (); /** * Allocates a new {@link DefaultMachineModel}. * * @param element The {@link Element}. * @param overwrittenMachineType The overwritten machine type which is used * instead of the loaded machine type if it is not null. * @throws StoreException If the {@link Element} can not be parsed. * @throws AlphabetException If something with the {@link DefaultAlphabet} is * not correct. * @throws StateException If something with the {@link DefaultState} is not * correct. * @throws TransitionSymbolOnlyOneTimeException If something with the * {@link DefaultTransition} is not correct. * @throws TransitionException If something with the {@link DefaultTransition} * is not correct. */ public DefaultMachineModel ( Element element, String overwrittenMachineType ) throws StoreException, StateException, AlphabetException, TransitionException, TransitionSymbolOnlyOneTimeException { this.pdaTableModel = new PDATableModel (); // Check if the element is correct if ( !element.getName ().equals ( "MachineModel" ) ) //$NON-NLS-1$ { throw new IllegalArgumentException ( "element " + Messages.QUOTE //$NON-NLS-1$ + element.getName () + Messages.QUOTE + " is not a machine model" ); //$NON-NLS-1$ } // Attribute boolean foundMachineType = false; boolean foundMachineVersion = false; boolean foundUsePushDownAlphabet = false; String machineType = null; boolean usePushDownAlphabet = true; for ( Attribute attribute : element.getAttribute () ) { if ( attribute.getName ().equals ( "machineType" ) ) //$NON-NLS-1$ { foundMachineType = true; if ( overwrittenMachineType == null ) { machineType = attribute.getValue (); } else { machineType = overwrittenMachineType; } } else if ( attribute.getName ().equals ( "machineVersion" ) ) //$NON-NLS-1$ { foundMachineVersion = true; if ( MACHINE_VERSION != attribute.getValueInt () ) { throw new StoreException ( Messages .getString ( "StoreException.IncompatibleVersion" ) ); //$NON-NLS-1$ } } else if ( attribute.getName ().equals ( "usePushDownAlphabet" ) ) //$NON-NLS-1$ { foundUsePushDownAlphabet = true; usePushDownAlphabet = attribute.getValueBoolean (); } else { throw new StoreException ( Messages .getString ( "StoreException.AdditionalAttribute" ) ); //$NON-NLS-1$ } } if ( ( !foundMachineType ) || ( !foundMachineVersion ) || ( !foundUsePushDownAlphabet ) ) { throw new StoreException ( Messages .getString ( "StoreException.MissingAttribute" ) ); //$NON-NLS-1$ } // Element Alphabet alphabet = null; Alphabet pushDownAlphabet = null; boolean foundAlphabet = false; boolean foundPushDownAlphabet = false; for ( Element current : element.getElement () ) { if ( current.getName ().equals ( "Alphabet" ) ) //$NON-NLS-1$ { alphabet = new DefaultAlphabet ( current ); foundAlphabet = true; } else if ( current.getName ().equals ( "PushDownAlphabet" ) ) //$NON-NLS-1$ { current.setName ( "Alphabet" ); //$NON-NLS-1$ pushDownAlphabet = new DefaultAlphabet ( current ); foundPushDownAlphabet = true; } else if ( ( !current.getName ().equals ( "StateView" ) ) //$NON-NLS-1$ && ( !current.getName ().equals ( "TransitionView" ) ) ) //$NON-NLS-1$ { throw new StoreException ( Messages .getString ( "StoreException.AdditionalElement" ) ); //$NON-NLS-1$ } } if ( ( !foundAlphabet ) || ( !foundPushDownAlphabet ) ) { throw new StoreException ( Messages .getString ( "StoreException.MissingElement" ) ); //$NON-NLS-1$ } // initialize this model elements this.machine = AbstractMachine.createMachine ( machineType, alphabet, pushDownAlphabet, usePushDownAlphabet ); initializeModifyStatusChangedListener (); initializeStatePositionChangedListener (); initializeGraph (); initializeMachineChangedListener (); // Load the states for ( Element current : element.getElement () ) { if ( current.getName ().equals ( "StateView" ) ) //$NON-NLS-1$ { double x = 0; double y = 0; State state = null; boolean xValueLoaded = false; boolean yValueLoaded = false; for ( Attribute attribute : current.getAttribute () ) { if ( attribute.getName ().equals ( "x" ) ) { //$NON-NLS-1$ x = attribute.getValueDouble (); xValueLoaded = true; } if ( attribute.getName ().equals ( "y" ) ) { //$NON-NLS-1$ y = attribute.getValueDouble (); yValueLoaded = true; } } if ( ! ( xValueLoaded && yValueLoaded ) ) { throw new StoreException ( Messages .getString ( "StoreException.MissingAttribute" ) ); //$NON-NLS-1$ } for ( Element childElement : current.getElement () ) { if ( childElement.getName ().equals ( "State" ) ) //$NON-NLS-1$ { state = new DefaultState ( childElement ); state.setAlphabet ( alphabet ); state.setPushDownAlphabet ( pushDownAlphabet ); } } double newX = x + StateView.getWidth ( state ) / 2; double newY = y + StateView.getHeight ( state ) / 2; createStateView ( newX, newY, state, false ); } else if ( ( !current.getName ().equals ( "Alphabet" ) ) //$NON-NLS-1$ && ( !current.getName ().equals ( "TransitionView" ) ) ) //$NON-NLS-1$ { throw new StoreException ( Messages .getString ( "StoreException.AdditionalElement" ) ); //$NON-NLS-1$ } } // Load the transitions for ( Element current : element.getElement () ) { if ( current.getName ().equals ( "TransitionView" ) ) //$NON-NLS-1$ { Transition transition = new DefaultTransition ( current.getElement ( 0 ) ); transition.setAlphabet ( alphabet ); transition.setPushDownAlphabet ( pushDownAlphabet ); DefaultStateView source = getStateById ( transition.getStateBeginId () ); DefaultStateView target = getStateById ( transition.getStateEndId () ); createTransitionView ( transition, source, target, false, false, true ); } else if ( ( !current.getName ().equals ( "Alphabet" ) ) //$NON-NLS-1$ && ( !current.getName ().equals ( "StateView" ) ) ) //$NON-NLS-1$ { throw new StoreException ( Messages .getString ( "StoreException.AdditionalElement" ) ); //$NON-NLS-1$ } } // Reset modify resetModify (); } /** * Allocate a new {@link DefaultMachineModel}. * * @param machine The {@link Machine}. */ public DefaultMachineModel ( Machine machine ) { this.machine = machine; this.pdaTableModel = new PDATableModel (); initializeModifyStatusChangedListener (); initializeStatePositionChangedListener (); initializeGraph (); initializeMachineChangedListener (); // Reset modify resetModify (); } /** * {@inheritDoc} * * @see Modifyable#addModifyStatusChangedListener(ModifyStatusChangedListener) */ public final void addModifyStatusChangedListener ( ModifyStatusChangedListener listener ) { this.listenerList.add ( ModifyStatusChangedListener.class, listener ); } /** * Create a new State view * * @param x The x position of the new state view. * @param y The y position of the new state view. * @param state The state represented via this view. * @return The new created {@link DefaultStateView}. * @param createUndoStep Flag signals if an undo step should be created. */ @SuppressWarnings ( "unchecked" ) public final DefaultStateView createStateView ( double x, double y, State state, boolean createUndoStep ) { this.machine.addState ( state ); DefaultStateView stateView = new DefaultStateView ( this, this.graphModel, state ); String viewClass = StateView.class.getName (); // check position of the new state double xPosition = x < ( StateView.getWidth ( state ) / 2 ) ? ( StateView .getWidth ( state ) / 2 ) : x; double yPostition = y < ( StateView.getHeight ( state ) / 2 ) ? ( StateView .getHeight ( state ) / 2 ) : y; // Set bounds GraphConstants.setBounds ( stateView.getAttributes (), new Rectangle2D.Double ( xPosition - ( StateView.getWidth ( state ) / 2 ), yPostition - ( StateView.getHeight ( state ) / 2 ), StateView .getWidth ( state ), StateView.getHeight ( state ) ) ); // set the view class (indirection for the renderer and the editor) GPCellViewFactory.setViewClass ( stateView.getAttributes (), viewClass ); // Opaque GraphConstants.setOpaque ( stateView.getAttributes (), true ); // Gradient GraphConstants.setGradientColor ( stateView.getAttributes (), Color.WHITE ); // Set black border GraphConstants.setBorderColor ( stateView.getAttributes (), Color.BLACK ); // Set the line width GraphConstants.setLineWidth ( stateView.getAttributes (), 1 ); // Add a floating port stateView.addPort (); this.jGTIGraph.getGraphLayoutCache ().insert ( stateView ); this.stateViewList.add ( stateView ); // Reset modify stateView.resetModify (); stateView .addModifyStatusChangedListener ( this.modifyStatusChangedListener ); stateView .addStatePositionChangedListener ( this.statePositionChangedListener ); if ( ( this.redoUndoHandler != null ) && createUndoStep ) { RedoUndoItem item = new StateAddedItem ( this, stateView, null ); this.redoUndoHandler.addItem ( item ); } return stateView; } /** * Create a new {@link Transition}. * * @param transition The {@link Transition}. * @param source The source of the new {@link Transition}. * @param target The target of the new {@link Transition}. * @param targetCreated Flag signals if target {@link DefaultStateView} is * created via the new {@link DefaultTransitionView}. * @param createUndoStep Flag signals if an undo step should be created. * @param addToMachine Flag which signals if the {@link Transition} should be * added to the {@link Machine}. The default value should be true, * only if the {@link Machine} has added the {@link Transition} * before, it should be false. * @return The new created {@link DefaultTransitionView}. */ public final DefaultTransitionView createTransitionView ( Transition transition, DefaultStateView source, DefaultStateView target, boolean targetCreated, boolean createUndoStep, boolean addToMachine ) { if ( addToMachine ) { this.machine.addTransition ( transition ); this.pdaTableModel.addRow ( transition ); } DefaultTransitionView transitionView = new DefaultTransitionView ( transition, source, target ); GraphConstants.setLineEnd ( transitionView.getAttributes (), GraphConstants.ARROW_CLASSIC ); GraphConstants.setEndFill ( transitionView.getAttributes (), true ); // Set the parallel routing JGraphpadParallelSplineRouter.getSharedInstance ().setEdgeSeparation ( 25 ); GraphConstants.setRouting ( transitionView.getAttributes (), JGraphpadParallelSplineRouter.getSharedInstance () ); this.jGTIGraph.getGraphLayoutCache ().insertEdge ( transitionView, source.getChildAt ( 0 ), target.getChildAt ( 0 ) ); this.transitionViewList.add ( transitionView ); if ( ( this.redoUndoHandler != null ) && createUndoStep ) { RedoUndoItem item = new TransitionAddedItem ( this, transitionView, targetCreated ? target : null ); this.redoUndoHandler.addItem ( item ); } return transitionView; } /** * Let the listeners know that the modify status has changed. * * @param forceModify True if the modify is forced, otherwise false. */ protected final void fireModifyStatusChanged ( boolean forceModify ) { ModifyStatusChangedListener [] listeners = this.listenerList .getListeners ( ModifyStatusChangedListener.class ); if ( forceModify ) { for ( ModifyStatusChangedListener current : listeners ) { current.modifyStatusChanged ( true ); } } else { boolean newModifyStatus = isModified (); for ( ModifyStatusChangedListener current : listeners ) { current.modifyStatusChanged ( newModifyStatus ); } } // change from normal state name to power state name for ( DefaultStateView current : this.stateViewList ) { double newWidth = StateView.getWidth ( current.getState () ); double newHeight = StateView.getHeight ( current.getState () ); if ( ( current.getWidth () != newWidth ) || ( current.getHeight () != newHeight ) ) { GraphConstants.setBounds ( current.getAttributes (), new Rectangle2D.Double ( current.getPositionX (), current .getPositionY (), newWidth, newHeight ) ); } } } /** * {@inheritDoc} * * @see Storable#getElement() */ public final Element getElement () { Element newElement = new Element ( "MachineModel" ); //$NON-NLS-1$ newElement.addAttribute ( new Attribute ( "machineType", this.machine //$NON-NLS-1$ .getMachineType ().toString () ) ); newElement.addAttribute ( new Attribute ( "machineVersion", //$NON-NLS-1$ MACHINE_VERSION ) ); newElement.addAttribute ( new Attribute ( "usePushDownAlphabet", //$NON-NLS-1$ this.machine.isUsePushDownAlphabet () ) ); newElement.addElement ( this.machine.getAlphabet ().getElement () ); Element newPushDownAlphabet = this.machine.getPushDownAlphabet () .getElement (); newPushDownAlphabet.setName ( "PushDownAlphabet" ); //$NON-NLS-1$ newElement.addElement ( newPushDownAlphabet ); for ( DefaultStateView stateView : this.stateViewList ) { newElement.addElement ( stateView.getElement () ); } for ( DefaultTransitionView transitionView : this.transitionViewList ) { newElement.addElement ( transitionView.getElement () ); } return newElement; } /** * Getter for the {@link DefaultGraphModel} * * @return the {@link DefaultGraphModel} */ public final DefaultGraphModel getGraphModel () { return this.graphModel; } /** * Getter for the {@link JGTIGraph} * * @return the {@link JGTIGraph} */ public final JGTIGraph getJGTIGraph () { return this.jGTIGraph; } /** * Get the {@link Machine} of this model * * @return the {@link Machine} */ public final Machine getMachine () { return this.machine; } /** * Returns the {@link PDATableModel}. * * @return The {@link PDATableModel}. * @see #pdaTableModel */ public PDATableModel getPDATableModel () { return this.pdaTableModel; } /** * Get the {@link DefaultStateView} for an id * * @param id the id * @return The {@link DefaultStateView} */ public final DefaultStateView getStateById ( int id ) { for ( DefaultStateView view : this.stateViewList ) { if ( view.getState ().getId () == id ) { return view; } } return null; } /** * Use only if names are unique! * * @param name * @return The {@link DefaultStateView} */ public final DefaultStateView getStateViewForName ( String name ) { for ( DefaultStateView view : this.stateViewList ) { if ( view.getState ().getName ().equals ( name ) ) { return view; } } return null; } /** * Get the {@link DefaultStateView} for a {@link State} * * @param state The {@link State} * @return The {@link DefaultStateView} */ public final DefaultStateView getStateViewForState ( State state ) { for ( DefaultStateView view : this.stateViewList ) { if ( view.getState ().equals ( state ) ) { return view; } } return null; } /** * Get a list with all {@link DefaultStateView}s of this Model * * @return DefaultStateView list */ public final ArrayList < DefaultStateView > getStateViewList () { return this.stateViewList; } /** * Get the {@link DefaultTransitionView} for a {@link Transition} * * @param transition The {@link Transition} * @return The {@link DefaultTransitionView} */ public final DefaultTransitionView getTransitionViewForTransition ( Transition transition ) { for ( DefaultTransitionView view : this.transitionViewList ) { if ( view.getTransition ().equals ( transition ) ) { return view; } } return null; } /** * Get a list with all {@link DefaultTransitionView}s of this Model * * @return DefaultTransitionView list */ public final ArrayList < DefaultTransitionView > getTransitionViewList () { return this.transitionViewList; } /** * Initialize the {@link JGTIGraph}. */ private final void initializeGraph () { this.graphModel = new DefaultGraphModel (); this.jGTIGraph = new JGTIBlackboxGraph ( this, this.graphModel ); this.jGTIGraph.setDoubleBuffered ( false ); this.jGTIGraph.getGraphLayoutCache () .setFactory ( new GPCellViewFactory () ); this.jGTIGraph.setInvokesStopCellEditing ( true ); this.jGTIGraph.setJumpToDefaultPort ( true ); this.jGTIGraph.setSizeable ( false ); this.jGTIGraph.setConnectable ( false ); this.jGTIGraph.setDisconnectable ( false ); this.jGTIGraph.setEdgeLabelsMovable ( false ); this.jGTIGraph.setEditable ( false ); this.jGTIGraph.setHandleSize ( 0 ); this.jGTIGraph.setXorEnabled ( false ); PreferenceManager.getInstance ().addColorChangedListener ( new ColorChangedAdapter () { @Override public void colorChanged () { DefaultMachineModel.this.jGTIGraph.repaint (); } } ); double zoomFactor = ( ( double ) PreferenceManager.getInstance () .getZoomFactorItem ().getFactor () ) / 100; // Set the zoom factor of this graph this.jGTIGraph.setScale ( this.jGTIGraph.getScale () * zoomFactor ); EdgeView.renderer = new EdgeRenderer (); EdgeView.renderer.setForeground ( Color.MAGENTA ); } /** * Initialize the {@link MachineChangedListener}. */ private final void initializeMachineChangedListener () { this.machineChangedListener = new MachineChangedListener () { public void startEditing () { DefaultMachineModel.this.multiItem = new MultiItem (); } public void stopEditing () { if ( DefaultMachineModel.this.redoUndoHandler != null ) { DefaultMachineModel.this.redoUndoHandler .addItem ( DefaultMachineModel.this.multiItem ); } } public void symbolAdded ( Transition transition, ArrayList < Symbol > addedSymbols ) { TreeSet < Symbol > oldSymbols = new TreeSet < Symbol > (); oldSymbols.addAll ( transition.getSymbol () ); oldSymbols.removeAll ( addedSymbols ); TransitionChangedItem item = new TransitionChangedItem ( transition, transition.getPushDownWordRead (), transition .getPushDownWordWrite (), oldSymbols ); DefaultMachineModel.this.multiItem.addItem ( item ); } public void symbolRemoved ( Transition transition, ArrayList < Symbol > removedSymbols ) { TreeSet < Symbol > oldSymbols = new TreeSet < Symbol > (); oldSymbols.addAll ( transition.getSymbol () ); oldSymbols.addAll ( removedSymbols ); TransitionChangedItem item = new TransitionChangedItem ( transition, transition.getPushDownWordRead (), transition .getPushDownWordWrite (), oldSymbols ); DefaultMachineModel.this.multiItem.addItem ( item ); } public void transitionAdded ( Transition newTransition ) { createTransitionView ( newTransition, getStateViewForState ( newTransition.getStateBegin () ), getStateViewForState ( newTransition.getStateEnd () ), false, false, false ); TransitionAddedItem item = new TransitionAddedItem ( DefaultMachineModel.this, getTransitionViewForTransition ( newTransition ), null ); DefaultMachineModel.this.multiItem.addItem ( item ); } public void transitionRemoved ( Transition transition ) { DefaultTransitionView transitionView = getTransitionViewForTransition ( transition ); removeTransition ( transitionView, false ); RedoUndoItem item = new TransitionRemovedItem ( DefaultMachineModel.this, transitionView ); DefaultMachineModel.this.multiItem.addItem ( item ); } }; this.machine.addMachineChangedListener ( this.machineChangedListener ); } /** * Initialize the {@link ModifyStatusChangedListener}. */ private final void initializeModifyStatusChangedListener () { this.modifyStatusChangedListener = new ModifyStatusChangedListener () { public void modifyStatusChanged ( boolean modified ) { fireModifyStatusChanged ( modified ); } }; this.machine .addModifyStatusChangedListener ( this.modifyStatusChangedListener ); } /** * Initialize the {@link StatePositionChangedListener}. */ private final void initializeStatePositionChangedListener () { this.statePositionChangedListener = new StatePositionChangedListener () { /** * {@inheritDoc} * * @see StatePositionChangedListener#statePositionChanged(DefaultStateView, * double, double, double, double) */ public void statePositionChanged ( DefaultStateView stateView, double oldX, double oldY, double newX, double newY ) { if ( ( DefaultMachineModel.this.redoUndoHandler != null ) && ( ( oldX != newX ) || ( oldY != newY ) ) ) { RedoUndoItem item = new StateMovedItem ( DefaultMachineModel.this, stateView, oldX, oldY, newX, newY ); DefaultMachineModel.this.redoUndoHandler.addItem ( item ); } } }; } /** * {@inheritDoc} * * @see Modifyable#isModified() */ public final boolean isModified () { if ( this.machine.isModified () ) { return true; } for ( DefaultStateView current : this.stateViewList ) { if ( current.isModified () ) { return true; } } return false; } /** * {@inheritDoc} * * @see Modifyable#removeModifyStatusChangedListener(ModifyStatusChangedListener) */ public final void removeModifyStatusChangedListener ( ModifyStatusChangedListener listener ) { this.listenerList.remove ( ModifyStatusChangedListener.class, listener ); } /** * Removes a {@link DefaultStateView}. * * @param stateView The {@link DefaultStateView} that should be removed. * @param createUndoStep Flag signals if an undo step should be created. * @return The {@link RedoUndoItem}. */ public final RedoUndoItem removeState ( DefaultStateView stateView, boolean createUndoStep ) { ArrayList < DefaultTransitionView > removeList = new ArrayList < DefaultTransitionView > (); for ( DefaultTransitionView current : this.transitionViewList ) { if ( ( current.getTransition ().getStateBegin ().equals ( stateView .getState () ) ) || ( current.getTransition ().getStateEnd ().equals ( stateView .getState () ) ) ) { removeList.add ( current ); } } for ( DefaultTransitionView current : removeList ) { removeTransition ( current, false ); } this.graphModel.remove ( new Object [] { stateView } ); this.machine.removeState ( stateView.getState () ); this.stateViewList.remove ( stateView ); stateView .removeModifyStatusChangedListener ( this.modifyStatusChangedListener ); RedoUndoItem item = new StateRemovedItem ( this, stateView, removeList ); if ( ( this.redoUndoHandler != null ) && createUndoStep ) { this.redoUndoHandler.addItem ( item ); } return item; } /** * Removes a {@link DefaultTransitionView}. * * @param transitionView The {@link DefaultTransitionView} that should be * removed. * @param createUndoStep Flag signals if an undo step should be created */ public final void removeTransition ( DefaultTransitionView transitionView, boolean createUndoStep ) { this.graphModel.remove ( new Object [] { transitionView } ); this.machine.removeTransition ( transitionView.getTransition () ); this.pdaTableModel.removeRow ( transitionView.getTransition () ); this.transitionViewList.remove ( transitionView ); if ( ( this.redoUndoHandler != null ) && createUndoStep ) { RedoUndoItem item = new TransitionRemovedItem ( this, transitionView ); this.redoUndoHandler.addItem ( item ); } } /** * {@inheritDoc} * * @see Modifyable#resetModify() */ public final void resetModify () { for ( DefaultStateView current : this.stateViewList ) { current.resetModify (); } this.machine.resetModify (); } /** * Set the {@link PDATableModel}. * * @param tableModel The new {@link PDATableModel}. */ public void setPdaTableModel ( PDATableModel tableModel ) { this.pdaTableModel = tableModel; } /** * Set a new {@link RedoUndoHandler} * * @param redoUndoHandler the new {@link RedoUndoHandler} */ public final void setRedoUndoHandler ( RedoUndoHandler redoUndoHandler ) { this.redoUndoHandler = redoUndoHandler; } }