package de.unisiegen.gtitool.ui.logic;
import java.awt.Color;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import org.jgraph.graph.DefaultGraphModel;
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.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.machines.Machine;
import de.unisiegen.gtitool.core.parser.style.PrettyString;
import de.unisiegen.gtitool.core.parser.style.PrettyToken;
import de.unisiegen.gtitool.core.parser.style.Style;
import de.unisiegen.gtitool.core.storage.exceptions.StoreException;
import de.unisiegen.gtitool.logger.Logger;
import de.unisiegen.gtitool.ui.i18n.Messages;
import de.unisiegen.gtitool.ui.jgraph.DefaultStateView;
import de.unisiegen.gtitool.ui.jgraph.JGTIGraph;
import de.unisiegen.gtitool.ui.logic.interfaces.LogicClass;
import de.unisiegen.gtitool.ui.model.DefaultMachineModel;
import de.unisiegen.gtitool.ui.model.ReachableStatesTableColumnModel;
import de.unisiegen.gtitool.ui.model.ReachableStatesTableModel;
import de.unisiegen.gtitool.ui.netbeans.ReachableStatesDialogForm;
import de.unisiegen.gtitool.ui.preferences.PreferenceManager;
/**
* The {@link ReachableStatesDialog}.
*
* @author Christian Fehler
* @version $Id$
*/
public final class ReachableStatesDialog implements
LogicClass < ReachableStatesDialogForm >
{
/**
* Does the next step after a delay.
*
* @author Christian Fehler
*/
protected final class AutoStepTimerTask extends TimerTask
{
/**
* {@inheritDoc}
*
* @see TimerTask#run()
*/
@Override
public final void run ()
{
SwingUtilities.invokeLater ( new Runnable ()
{
public void run ()
{
if ( ReachableStatesDialog.this.endReached )
{
handleStop ();
}
else
{
performNextStep ( true );
}
}
} );
}
}
/**
* The {@link Step} enum.
*
* @author Christian Fehler
*/
private enum Step
{
/**
* The activate next {@link State} step.
*/
ACTIVATE_NEXT_STATE,
/**
* The activate reachable {@link State}s step.
*/
ACTIVATE_REACHABLE_STATES,
/**
* The activate start {@link State} step.
*/
ACTIVATE_START_STATE,
/**
* The finish step.
*/
FINISH;
/**
* {@inheritDoc}
*
* @see Enum#toString()
*/
@Override
public final String toString ()
{
switch ( this )
{
case ACTIVATE_START_STATE :
{
return "activate start state"; //$NON-NLS-1$
}
case ACTIVATE_NEXT_STATE :
{
return "activate next state"; //$NON-NLS-1$
}
case ACTIVATE_REACHABLE_STATES :
{
return "activate reachable states"; //$NON-NLS-1$
}
case FINISH :
{
return "finish"; //$NON-NLS-1$
}
}
throw new RuntimeException ( "unsupported step" );//$NON-NLS-1$
}
}
/**
* The {@link StepItem}.
*
* @author Christian Fehler
*/
private class StepItem
{
/**
* The {@link State}s which are calculated.
*/
private ArrayList < State > activeCalculatedStates;
/**
* The active {@link State}s of the original {@link JGTIGraph}.
*/
private ArrayList < State > activeStatesOriginal;
/**
* The active {@link State}s of the result {@link JGTIGraph}.
*/
private ArrayList < State > activeStatesResult;
/**
* The active {@link Step}.
*/
private Step activeStep;
/**
* The active {@link Symbol}s of the original {@link JGTIGraph}.
*/
private ArrayList < Symbol > activeSymbolsOriginal;
/**
* The active {@link Symbol}s of the result {@link JGTIGraph}.
*/
private ArrayList < Symbol > activeSymbolsResult;
/**
* The {@link State} which must be calculated.
*/
private ArrayList < State > activeToCalculateStates;
/**
* The active {@link Transition}s of the original {@link JGTIGraph}.
*/
private ArrayList < Transition > activeTransitionsOriginal;
/**
* The active {@link Transition}s of the result {@link JGTIGraph}.
*/
private ArrayList < Transition > activeTransitionsResult;
/**
* The overwritten {@link Color} {@link DefaultStateView}s.
*/
private ArrayList < DefaultStateView > overwrittenColorOriginal;
/**
* Allocates a new {@link StepItem}.
*
* @param activeStep The active {@link Step}.
* @param activeToCalculateStates The {@link State} which must be
* calculated.
* @param activeCalculatedStates The {@link State}s which are calculated.
* @param activeStatesOriginal The active {@link State}s of the original
* {@link JGTIGraph}.
* @param activeStatesResult The active {@link State}s of the result
* {@link JGTIGraph}.
* @param activeTransitionsOriginal The active {@link Transition}s of the
* original {@link JGTIGraph}.
* @param activeTransitionsResult The active {@link Transition}s of the
* result {@link JGTIGraph}.
* @param activeSymbolsOriginal The active {@link Symbol}s of the original
* {@link JGTIGraph}.
* @param activeSymbolsResult The active {@link Symbol}s of the result
* {@link JGTIGraph}.
* @param overwrittenColorOriginal The overwritten {@link Color}
* {@link DefaultStateView}s.
*/
public StepItem ( Step activeStep,
ArrayList < State > activeToCalculateStates,
ArrayList < State > activeCalculatedStates,
ArrayList < State > activeStatesOriginal,
ArrayList < State > activeStatesResult,
ArrayList < Transition > activeTransitionsOriginal,
ArrayList < Transition > activeTransitionsResult,
ArrayList < Symbol > activeSymbolsOriginal,
ArrayList < Symbol > activeSymbolsResult,
ArrayList < DefaultStateView > overwrittenColorOriginal )
{
this.activeStep = activeStep;
this.activeToCalculateStates = activeToCalculateStates;
this.activeCalculatedStates = activeCalculatedStates;
this.activeStatesOriginal = activeStatesOriginal;
this.activeStatesResult = activeStatesResult;
this.activeTransitionsOriginal = activeTransitionsOriginal;
this.activeTransitionsResult = activeTransitionsResult;
this.activeSymbolsOriginal = activeSymbolsOriginal;
this.activeSymbolsResult = activeSymbolsResult;
this.overwrittenColorOriginal = overwrittenColorOriginal;
}
/**
* Returns the activeCalculatedStates.
*
* @return The activeCalculatedStates.
* @see #activeCalculatedStates
*/
public final ArrayList < State > getActiveCalculatedStates ()
{
return this.activeCalculatedStates;
}
/**
* Returns the activeStatesOriginal.
*
* @return The activeStatesOriginal.
* @see #activeStatesOriginal
*/
public final ArrayList < State > getActiveStatesOriginal ()
{
return this.activeStatesOriginal;
}
/**
* Returns the activeStatesResult.
*
* @return The activeStatesResult.
* @see #activeStatesResult
*/
public final ArrayList < State > getActiveStatesResult ()
{
return this.activeStatesResult;
}
/**
* Returns the activeStep.
*
* @return The activeStep.
* @see #activeStep
*/
public final Step getActiveStep ()
{
return this.activeStep;
}
/**
* Returns the activeSymbolsOriginal.
*
* @return The activeSymbolsOriginal.
* @see #activeSymbolsOriginal
*/
public final ArrayList < Symbol > getActiveSymbolsOriginal ()
{
return this.activeSymbolsOriginal;
}
/**
* Returns the activeSymbolsResult.
*
* @return The activeSymbolsResult.
* @see #activeSymbolsResult
*/
public final ArrayList < Symbol > getActiveSymbolsResult ()
{
return this.activeSymbolsResult;
}
/**
* Returns the activeToCalculateStates.
*
* @return The activeToCalculateStates.
* @see #activeToCalculateStates
*/
public final ArrayList < State > getActiveToCalculateStates ()
{
return this.activeToCalculateStates;
}
/**
* Returns the activeTransitionsOriginal.
*
* @return The activeTransitionsOriginal.
* @see #activeTransitionsOriginal
*/
public final ArrayList < Transition > getActiveTransitionsOriginal ()
{
return this.activeTransitionsOriginal;
}
/**
* Returns the activeTransitionsResult.
*
* @return The activeTransitionsResult.
* @see #activeTransitionsResult
*/
public final ArrayList < Transition > getActiveTransitionsResult ()
{
return this.activeTransitionsResult;
}
/**
* Returns the overwrittenColorOriginal.
*
* @return The overwrittenColorOriginal.
* @see #overwrittenColorOriginal
*/
public final ArrayList < DefaultStateView > getOverwrittenColorOriginal ()
{
return this.overwrittenColorOriginal;
}
}
/**
* The {@link Logger} for this class.
*/
private static final Logger logger = Logger
.getLogger ( ReachableStatesDialog.class );
/**
* The reachable {@link Color}.
*/
private final static Color REACHABLE_COLOR = Color.YELLOW;
/**
* The auto step {@link Timer}.
*/
private Timer autoStepTimer = null;
/**
* The {@link State}s which are calculated.
*/
private ArrayList < State > calculatedStates = new ArrayList < State > ();
/**
* Flag that indicates if the end is reached.
*/
protected boolean endReached = false;
/**
* The {@link ReachableStatesDialogForm}.
*/
private ReachableStatesDialogForm gui;
/**
* The original {@link JGTIGraph} containing the diagramm.
*/
private JGTIGraph jGTIGraphOriginal;
/**
* The original {@link Machine}.
*/
private Machine machineOriginal;
/**
* The {@link MachinePanel}.
*/
private MachinePanel machinePanel;
/**
* The result {@link Machine}.
*/
private Machine machineResult;
/**
* The original {@link DefaultMachineModel}.
*/
private DefaultMachineModel modelOriginal;
/**
* The result {@link DefaultMachineModel}.
*/
private DefaultMachineModel modelResult;
/**
* The parent {@link JFrame}.
*/
private JFrame parent;
/**
* The {@link ReachableStatesTableModel}.
*/
private ReachableStatesTableModel reachableStatesTableModel;
/**
* The current {@link Step}.
*/
private Step step = null;
/**
* The {@link StepItem} list.
*/
private ArrayList < StepItem > stepItemList = new ArrayList < StepItem > ();
/**
* The {@link ReachableStatesTableColumnModel}.
*/
private ReachableStatesTableColumnModel tableColumnModel = new ReachableStatesTableColumnModel ();
/**
* The {@link State} which must be calculated.
*/
private ArrayList < State > toCalculateStates = new ArrayList < State > ();
/**
* Allocates a new {@link ReachableStatesDialog}.
*
* @param parent The parent {@link JFrame}.
* @param machinePanel The {@link MachinePanel}.
*/
public ReachableStatesDialog ( JFrame parent, MachinePanel machinePanel )
{
logger.debug ( "ReachableStatesDialog", //$NON-NLS-1$
"allocate a new reachable states dialog" ); //$NON-NLS-1$
if ( parent == null )
{
throw new IllegalArgumentException ( "parent is null" );//$NON-NLS-1$
}
if ( machinePanel == null )
{
throw new IllegalArgumentException ( "machine panel is null" );//$NON-NLS-1$
}
this.parent = parent;
this.machinePanel = machinePanel;
}
/**
* Adds a outline comment.
*
* @param prettyString The {@link PrettyString} to add.
*/
private final void addOutlineComment ( PrettyString prettyString )
{
this.reachableStatesTableModel.addRow ( prettyString );
this.gui.jGTITableOutline.changeSelection ( this.reachableStatesTableModel
.getRowCount () - 1, ReachableStatesTableModel.OUTLINE_COLUMN, false,
false );
}
/**
* Adds a {@link StepItem}.
*/
private final void addStepItem ()
{
ArrayList < State > activeToCalculateStates = new ArrayList < State > ();
ArrayList < State > activeCalculatedStates = new ArrayList < State > ();
ArrayList < State > activeStatesOriginal = new ArrayList < State > ();
ArrayList < State > activeStatesResult = new ArrayList < State > ();
ArrayList < Transition > activeTransitionsOriginal = new ArrayList < Transition > ();
ArrayList < Transition > activeTransitionsResult = new ArrayList < Transition > ();
ArrayList < Symbol > activeSymbolsOriginal = new ArrayList < Symbol > ();
ArrayList < Symbol > activeSymbolsResult = new ArrayList < Symbol > ();
ArrayList < DefaultStateView > activeOverwrittenColorOriginal = new ArrayList < DefaultStateView > ();
for ( State current : this.toCalculateStates )
{
activeToCalculateStates.add ( current );
}
for ( State current : this.calculatedStates )
{
activeCalculatedStates.add ( current );
}
for ( State current : this.machineOriginal.getState () )
{
if ( current.isActive () )
{
activeStatesOriginal.add ( current );
}
}
for ( State current : this.machineResult.getState () )
{
if ( current.isActive () )
{
activeStatesResult.add ( current );
}
}
for ( Transition current : this.machineOriginal.getTransition () )
{
if ( current.isActive () )
{
activeTransitionsOriginal.add ( current );
}
}
for ( Transition current : this.machineResult.getTransition () )
{
if ( current.isActive () )
{
activeTransitionsResult.add ( current );
}
}
for ( Transition currentTransition : this.machineOriginal.getTransition () )
{
for ( Symbol currentSymbol : currentTransition )
{
if ( currentSymbol.isActive () )
{
activeSymbolsOriginal.add ( currentSymbol );
}
}
}
for ( Transition currentTransition : this.machineResult.getTransition () )
{
for ( Symbol currentSymbol : currentTransition )
{
if ( currentSymbol.isActive () )
{
activeSymbolsResult.add ( currentSymbol );
}
}
}
for ( DefaultStateView current : this.modelOriginal.getStateViewList () )
{
if ( current.getOverwrittenColor () != null )
{
activeOverwrittenColorOriginal.add ( current );
}
}
this.stepItemList.add ( new StepItem ( this.step, activeToCalculateStates,
activeCalculatedStates, activeStatesOriginal, activeStatesResult,
activeTransitionsOriginal, activeTransitionsResult,
activeSymbolsOriginal, activeSymbolsResult,
activeOverwrittenColorOriginal ) );
}
/**
* Cancels the auto step timer.
*/
private final void cancelAutoStepTimer ()
{
if ( this.autoStepTimer != null )
{
this.autoStepTimer.cancel ();
this.autoStepTimer = null;
}
}
/**
* Clears the overwritten {@link State} highlighting of the original
* {@link JGTIGraph}.
*/
private final void clearOverwrittenColorOriginal ()
{
for ( DefaultStateView current : this.modelOriginal.getStateViewList () )
{
current.setOverwrittenColor ( null );
}
}
/**
* Clears the {@link State} highlighting of the original {@link JGTIGraph}.
*/
private final void clearStateHighlightOriginal ()
{
for ( State currentState : this.machineOriginal.getState () )
{
currentState.setActive ( false );
}
}
/**
* Clears the {@link State} highlighting of the result {@link JGTIGraph}.
*/
private final void clearStateHighlightResult ()
{
for ( State currentState : this.machineResult.getState () )
{
currentState.setActive ( false );
}
}
/**
* Clears the {@link Symbol} highlighting of the original {@link JGTIGraph}.
*/
private final void clearSymbolHighlightOriginal ()
{
for ( Transition currentTransition : this.machineOriginal.getTransition () )
{
for ( Symbol currentSymbol : currentTransition.getSymbol () )
{
currentSymbol.setActive ( false );
}
}
}
/**
* Clears the {@link Symbol} highlighting of the result {@link JGTIGraph}.
*/
private final void clearSymbolHighlightResult ()
{
for ( Transition currentTransition : this.machineResult.getTransition () )
{
for ( Symbol currentSymbol : currentTransition.getSymbol () )
{
currentSymbol.setActive ( false );
}
}
}
/**
* Clears the {@link Transition} highlighting of the original
* {@link JGTIGraph}.
*/
private final void clearTransitionHighlightOriginal ()
{
for ( Transition currentTransition : this.machineOriginal.getTransition () )
{
currentTransition.setActive ( false );
}
}
/**
* Clears the {@link Transition} highlighting of the result {@link JGTIGraph}.
*/
private final void clearTransitionHighlightResult ()
{
for ( Transition currentTransition : this.machineResult.getTransition () )
{
currentTransition.setActive ( false );
}
}
/**
* {@inheritDoc}
*
* @see LogicClass#getGUI()
*/
public final ReachableStatesDialogForm getGUI ()
{
return this.gui;
}
/**
* Returns the {@link MachinePanel}.
*
* @return The {@link MachinePanel}.
* @see #machinePanel
*/
public MachinePanel getMachinePanel ()
{
return this.machinePanel;
}
/**
* Returns the modelOriginal.
*
* @return The modelOriginal.
* @see #modelOriginal
*/
public DefaultMachineModel getModelOriginal ()
{
return this.modelOriginal;
}
/**
* Returns the reachableStatesTableModel.
*
* @return The reachableStatesTableModel.
* @see #reachableStatesTableModel
*/
public ReachableStatesTableModel getReachableStatesTableModel ()
{
return this.reachableStatesTableModel;
}
/**
* Returns the tableColumnModel.
*
* @return The tableColumnModel.
* @see #tableColumnModel
*/
public ReachableStatesTableColumnModel getTableColumnModel ()
{
return this.tableColumnModel;
}
/**
* Handles the action on the auto step button.
*/
public final void handleAutoStep ()
{
logger.debug ( "handleAutoStep", "handle auto step" ); //$NON-NLS-1$ //$NON-NLS-2$
setStatus ();
startAutoStepTimer ();
}
/**
* Handles the action on the begin step button.
*/
public final void handleBeginStep ()
{
performBeginStep ();
}
/**
* Handles the action on the cancel button.
*/
public final void handleCancel ()
{
logger.debug ( "handleCancel", "handle cancel" ); //$NON-NLS-1$ //$NON-NLS-2$
cancelAutoStepTimer ();
PreferenceManager.getInstance ().setReachableStatesDialogPreferences (
this.gui );
this.gui.dispose ();
}
/**
* Handles the action on the end step button.
*/
public final void handleEndStep ()
{
performEndStep ();
}
/**
* Handles the action on the next step button.
*/
public final void handleNextStep ()
{
performNextStep ( true );
}
/**
* Handles the action on the ok button.
*/
public final void handleOk ()
{
logger.debug ( "handleOk", "handle ok" ); //$NON-NLS-1$ //$NON-NLS-2$
cancelAutoStepTimer ();
this.gui.setVisible ( false );
while ( !this.endReached )
{
performNextStep ( false );
}
// remove the not reachable states
ArrayList < DefaultStateView > statesToRemove = new ArrayList < DefaultStateView > ();
for ( DefaultStateView current : this.modelResult.getStateViewList () )
{
if ( !current.getState ().isActive () )
{
statesToRemove.add ( current );
}
}
for ( DefaultStateView current : statesToRemove )
{
this.modelResult.removeState ( current, false );
}
this.machinePanel.getMainWindow ().handleNew (
this.modelResult.getElement (), false );
PreferenceManager.getInstance ().setReachableStatesDialogPreferences (
this.gui );
this.gui.dispose ();
}
/**
* Handles the action on the previous step button.
*/
public final void handlePreviousStep ()
{
performPreviousStep ( true );
}
/**
* Handle the print action.
*/
public void handlePrint ()
{
PrintDialog dialog = new PrintDialog ( this.parent, this );
dialog.show ();
}
/**
* Handles the action on the stop button.
*/
public final void handleStop ()
{
logger.debug ( "handleStop", "handle stop" ); //$NON-NLS-1$ //$NON-NLS-2$
cancelAutoStepTimer ();
this.gui.jGTIToolBarToggleButtonAutoStep.setSelected ( false );
setStatus ();
}
/**
* Performs the begin step.
*/
private final void performBeginStep ()
{
logger.debug ( "performBeginStep", "handle begin step" ); //$NON-NLS-1$ //$NON-NLS-2$
while ( !this.stepItemList.isEmpty () )
{
performPreviousStep ( false );
}
setStatus ();
this.modelOriginal.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelOriginal.getGraphModel () ) );
this.modelResult.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelResult.getGraphModel () ) );
}
/**
* Performs the end step.
*/
private final void performEndStep ()
{
logger.debug ( "performEndStep", "handle nfa to dfa end step" ); //$NON-NLS-1$ //$NON-NLS-2$
while ( !this.endReached )
{
performNextStep ( false );
}
setStatus ();
this.modelOriginal.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelOriginal.getGraphModel () ) );
this.modelResult.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelResult.getGraphModel () ) );
}
/**
* Performs the next step.
*
* @param manualStep Flag that indicates if the {@link Step} is a manual
* {@link Step}.
*/
protected final void performNextStep ( boolean manualStep )
{
addStepItem ();
clearOverwrittenColorOriginal ();
if ( this.step.equals ( Step.ACTIVATE_START_STATE ) )
{
State startState = null;
for ( State current : this.machineOriginal.getState () )
{
if ( current.isStartState () )
{
startState = current;
break;
}
}
if ( startState == null )
{
throw new NullPointerException ( "no start state" ); //$NON-NLS-1$
}
if ( manualStep )
{
logger.debug ( "performNextStep", "perform next step: " + this.step //$NON-NLS-1$ //$NON-NLS-2$
+ ": " + startState.getName () ); //$NON-NLS-1$
}
startState.setActive ( true );
// result
for ( State current : this.machineResult.getState () )
{
if ( startState.equals ( current ) )
{
current.setActive ( true );
break;
}
}
// outline
PrettyString prettyString = new PrettyString ();
prettyString
.add ( Messages
.getPrettyString (
"ReachableStatesDialog.ActivateStartState", startState.toPrettyString () ) ); //$NON-NLS-1$
addOutlineComment ( prettyString );
this.step = Step.ACTIVATE_REACHABLE_STATES;
}
else if ( this.step.equals ( Step.ACTIVATE_NEXT_STATE ) )
{
State nextState = this.toCalculateStates.remove ( 0 );
nextState.setActive ( true );
if ( manualStep )
{
logger.debug ( "performNextStep", "perform next step: " + this.step //$NON-NLS-1$ //$NON-NLS-2$
+ ": " + nextState.getName () ); //$NON-NLS-1$
}
// outline
PrettyString prettyString = new PrettyString ();
prettyString
.add ( Messages
.getPrettyString (
"ReachableStatesDialog.ActivateNextState", nextState.toPrettyString () ) ); //$NON-NLS-1$
addOutlineComment ( prettyString );
this.step = Step.ACTIVATE_REACHABLE_STATES;
}
else if ( this.step.equals ( Step.ACTIVATE_REACHABLE_STATES ) )
{
ArrayList < State > reachableStates = new ArrayList < State > ();
for ( State currentState : this.machineOriginal.getState () )
{
if ( currentState.isActive () )
{
this.calculatedStates.add ( currentState );
for ( Transition currentTransition : currentState
.getTransitionBegin () )
{
currentTransition.setActive ( true );
// result
for ( Transition current : this.machineResult.getTransition () )
{
if ( currentTransition.equals ( current ) )
{
current.setActive ( true );
break;
}
}
reachableStates.add ( currentTransition.getStateEnd () );
}
break;
}
}
Collections.sort ( reachableStates );
clearStateHighlightOriginal ();
for ( State current : reachableStates )
{
if ( !this.calculatedStates.contains ( current )
&& !this.toCalculateStates.contains ( current ) )
{
this.toCalculateStates.add ( current );
}
current.setActive ( true );
// result
for ( State currentResult : this.machineResult.getState () )
{
if ( current.equals ( currentResult ) )
{
currentResult.setActive ( true );
break;
}
}
}
Collections.sort ( this.toCalculateStates );
if ( manualStep )
{
logger.debug ( "performNextStep", "perform next step: " + this.step //$NON-NLS-1$ //$NON-NLS-2$
+ ": " + reachableStates ); //$NON-NLS-1$
}
// outline
PrettyString prettyString = new PrettyString ();
prettyString.add ( new PrettyToken ( Messages
.getString ( "ReachableStatesDialog.ActivateReachableStates" ) //$NON-NLS-1$
+ " ", Style.NONE ) ); //$NON-NLS-1$
if ( reachableStates.size () == 0 )
{
prettyString.add ( new PrettyToken ( "\u2205", Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : reachableStates )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
addOutlineComment ( prettyString );
this.step = Step.FINISH;
}
else if ( this.step.equals ( Step.FINISH ) )
{
clearStateHighlightOriginal ();
clearTransitionHighlightOriginal ();
clearTransitionHighlightResult ();
if ( manualStep )
{
logger.debug ( "performNextStep", "perform next step: " + this.step ); //$NON-NLS-1$ //$NON-NLS-2$
}
if ( this.toCalculateStates.size () == 0 )
{
this.endReached = true;
}
// outline
PrettyString prettyString = new PrettyString ();
if ( this.toCalculateStates.size () == 0 )
{
prettyString.add ( new PrettyToken ( Messages
.getString ( "ReachableStatesDialog.FinishAll" ), Style.NONE ) ); //$NON-NLS-1$
}
else
{
prettyString.add ( Messages.getPrettyString (
"ReachableStatesDialog.Finish", this.calculatedStates //$NON-NLS-1$
.get ( this.calculatedStates.size () - 1 ).toPrettyString () ) );
prettyString.add ( new PrettyToken ( " ", Style.NONE ) ); //$NON-NLS-1$
prettyString.add ( new PrettyToken ( "{", Style.NONE ) ); //$NON-NLS-1$
boolean first = true;
for ( State current : this.toCalculateStates )
{
if ( !first )
{
prettyString.add ( new PrettyToken ( ", ", Style.NONE ) ); //$NON-NLS-1$
}
first = false;
prettyString.add ( current );
}
prettyString.add ( new PrettyToken ( "}", Style.NONE ) ); //$NON-NLS-1$
}
addOutlineComment ( prettyString );
this.step = Step.ACTIVATE_NEXT_STATE;
}
else
{
throw new RuntimeException ( "unsupported step" ); //$NON-NLS-1$
}
for ( State current : this.machineResult.getState () )
{
if ( current.isActive () )
{
DefaultStateView originalState = this.modelOriginal
.getStateViewForState ( current );
if ( !originalState.getState ().isActive () )
{
originalState.setOverwrittenColor ( REACHABLE_COLOR );
}
}
}
if ( manualStep )
{
setStatus ();
this.modelOriginal.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelOriginal.getGraphModel () ) );
this.modelResult.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelResult.getGraphModel () ) );
}
}
/**
* Performs the previous step.
*
* @param manualStep Flag that indicates if the {@link Step} is a manual
* {@link Step}.
*/
private final void performPreviousStep ( boolean manualStep )
{
if ( manualStep )
{
logger.debug ( "performPreviousStep",//$NON-NLS-1$
"perform previous step" ); //$NON-NLS-1$
}
StepItem stepItem = this.stepItemList
.remove ( this.stepItemList.size () - 1 );
this.toCalculateStates.clear ();
for ( State current : stepItem.getActiveToCalculateStates () )
{
this.toCalculateStates.add ( current );
}
this.calculatedStates.clear ();
for ( State current : stepItem.getActiveCalculatedStates () )
{
this.calculatedStates.add ( current );
}
clearStateHighlightOriginal ();
clearStateHighlightResult ();
clearTransitionHighlightOriginal ();
clearTransitionHighlightResult ();
clearSymbolHighlightOriginal ();
clearSymbolHighlightResult ();
clearOverwrittenColorOriginal ();
for ( State current : stepItem.getActiveStatesOriginal () )
{
current.setActive ( true );
}
for ( State current : stepItem.getActiveStatesResult () )
{
current.setActive ( true );
}
for ( Transition current : stepItem.getActiveTransitionsOriginal () )
{
current.setActive ( true );
}
for ( Transition current : stepItem.getActiveTransitionsResult () )
{
current.setActive ( true );
}
for ( Symbol current : stepItem.getActiveSymbolsOriginal () )
{
current.setActive ( true );
}
for ( Symbol current : stepItem.getActiveSymbolsResult () )
{
current.setActive ( true );
}
for ( DefaultStateView current : stepItem.getOverwrittenColorOriginal () )
{
current.setOverwrittenColor ( REACHABLE_COLOR );
}
this.step = stepItem.getActiveStep ();
// outline
this.reachableStatesTableModel.removeLastRow ();
this.gui.jGTITableOutline.changeSelection ( this.reachableStatesTableModel
.getRowCount () - 1, ReachableStatesTableModel.OUTLINE_COLUMN, false,
false );
this.endReached = false;
if ( manualStep )
{
setStatus ();
this.modelOriginal.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelOriginal.getGraphModel () ) );
this.modelResult.getGraphModel ().cellsChanged (
DefaultGraphModel.getAll ( this.modelResult.getGraphModel () ) );
}
}
/**
* Sets the button status.
*/
private final void setStatus ()
{
if ( this.gui.jGTIToolBarToggleButtonAutoStep.isSelected () )
{
this.gui.jGTIToolBarButtonBeginStep.setEnabled ( false );
this.gui.jGTIToolBarButtonPreviousStep.setEnabled ( false );
this.gui.jGTIToolBarButtonNextStep.setEnabled ( false );
this.gui.jGTIToolBarToggleButtonAutoStep.setEnabled ( false );
this.gui.jGTIToolBarButtonStop.setEnabled ( true );
this.gui.jGTIToolBarButtonEndStep.setEnabled ( false );
}
else
{
boolean beginReached = this.stepItemList.isEmpty ();
this.gui.jGTIToolBarButtonBeginStep.setEnabled ( !beginReached );
this.gui.jGTIToolBarButtonPreviousStep.setEnabled ( !beginReached );
this.gui.jGTIToolBarButtonNextStep.setEnabled ( !this.endReached );
this.gui.jGTIToolBarToggleButtonAutoStep.setEnabled ( !this.endReached );
this.gui.jGTIToolBarButtonStop.setEnabled ( false );
this.gui.jGTIToolBarButtonEndStep.setEnabled ( !this.endReached );
}
}
/**
* Shows the {@link ReachableStatesDialogForm}.
*/
public final void show ()
{
logger.debug ( "show", "show the reachable states dialog" ); //$NON-NLS-1$ //$NON-NLS-2$
this.gui = new ReachableStatesDialogForm ( this, this.parent );
// outline
this.reachableStatesTableModel = new ReachableStatesTableModel ();
this.gui.jGTITableOutline.setModel ( this.reachableStatesTableModel );
this.gui.jGTITableOutline.setColumnModel ( this.tableColumnModel );
this.gui.jGTITableOutline.getTableHeader ().setReorderingAllowed ( false );
this.gui.jGTITableOutline.getSelectionModel ().setSelectionMode (
ListSelectionModel.SINGLE_SELECTION );
Rectangle rect = PreferenceManager.getInstance ()
.getReachableStatesDialogBounds ();
this.gui.jGTISplitPaneOutline.setDividerLocation ( rect.width - 250 );
try
{
this.modelOriginal = new DefaultMachineModel ( this.machinePanel
.getModel ().getElement (), null );
this.modelResult = new DefaultMachineModel ( this.machinePanel
.getModel ().getElement (), null );
}
catch ( TransitionSymbolOnlyOneTimeException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( StateException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( AlphabetException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( TransitionException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
catch ( StoreException exc )
{
exc.printStackTrace ();
System.exit ( 1 );
return;
}
this.jGTIGraphOriginal = this.modelOriginal.getJGTIGraph ();
this.jGTIGraphOriginal.setEnabled ( false );
this.gui.jGTIScrollPaneGraph.setViewportView ( this.jGTIGraphOriginal );
this.machineOriginal = this.modelOriginal.getMachine ();
this.machineResult = this.modelResult.getMachine ();
this.step = Step.ACTIVATE_START_STATE;
setStatus ();
if ( ( rect.x == PreferenceManager.DEFAULT_REACHABLE_STATES_DIALOG_POSITION_X )
|| ( rect.y == PreferenceManager.DEFAULT_REACHABLE_STATES_DIALOG_POSITION_Y ) )
{
rect.x = this.parent.getBounds ().x + ( this.parent.getWidth () / 2 )
- ( this.gui.getWidth () / 2 );
rect.y = this.parent.getBounds ().y + ( this.parent.getHeight () / 2 )
- ( this.gui.getHeight () / 2 );
}
this.gui.setBounds ( rect );
this.gui.setVisible ( true );
}
/**
* Starts the auto step timer.
*/
private final void startAutoStepTimer ()
{
cancelAutoStepTimer ();
this.autoStepTimer = new Timer ();
int time = PreferenceManager.getInstance ().getAutoStepItem ()
.getAutoStepInterval ();
this.autoStepTimer.schedule ( new AutoStepTimerTask (), time, time );
}
}