/*
* 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.minimize;
import automata.*;
import automata.fsa.*;
import automata.graph.*;
import automata.graph.layout.GEMLayoutAlgorithm;
import gui.SplitPaneFactory;
import gui.editor.*;
import gui.environment.Environment;
import gui.tree.*;
import gui.viewer.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.tree.*;
/**
* The MinimizePane
is a view created to minimize a DFA using
* some minimizing tree structure.
*
* @author Thomas Finley
*/
public class MinimizePane extends JPanel {
/**
* Instantiates a MinimizePane
.
*
* @param dfa
* a DFA to minimize
* @param environment
* the environment this minimize pane will be added to
*/
public MinimizePane(FiniteStateAutomaton dfa, Environment environment) {
// Set up the minimizable automaton, and the minimize tree.
minimizer = new Minimizer();
minimizer.initializeMinimizer();
dfa = (FiniteStateAutomaton) minimizer.getMinimizeableAutomaton(dfa);
// minimizer.initializeMinimizer();
TreeModel tree = minimizer.getInitializedTree(dfa);
// Set up the drawers.
automatonDrawer = new SelectionDrawer(dfa);
treeDrawer = new SelectTreeDrawer(tree);
// Set up the minimize node drawer.
MinimizeNodeDrawer nodeDrawer = new MinimizeNodeDrawer();
treeDrawer.setNodeDrawer(nodeDrawer);
TreeNode[] groups = Trees.children((MinimizeTreeNode) tree.getRoot());
for (int i = 0; i < groups.length; i++) {
MinimizeTreeNode group = (MinimizeTreeNode) groups[i];
State[] states = (State[]) group.getUserObject();
if (states.length == 0)
continue;
if (dfa.isFinalState(states[0]))
nodeDrawer.setLabel(group, "Final");
else
nodeDrawer.setLabel(group, "Nonfinal");
}
// Set up the controller object.
controller = new MinimizeController(this, automatonDrawer, treeDrawer,
minimizer);
JPanel right = new JPanel(new BorderLayout());
right.add(initTreePane(), BorderLayout.CENTER);
controlPanel = new ControlPanel(treeDrawer, controller);
/*
* right.add(new ControlPanel(treeDrawer, controller),
* BorderLayout.SOUTH);
*/
// Finally, initialize the view.
split = SplitPaneFactory.createSplit(environment, true, 0.5,
initAutomatonPane(), right);
setLayout(new BorderLayout());
add(split, BorderLayout.CENTER);
add(controlPanel, BorderLayout.NORTH);
add(messageLabel, BorderLayout.SOUTH);
split.setResizeWeight(0.5);
controller.setEnabledness();
}
/**
* Initializes the automaton pane.
*/
public AutomatonPane initAutomatonPane() {
AutomatonPane apane = new AutomatonPane(automatonDrawer);
gui.SuperMouseAdapter a = new ArrowMinimizeTool(apane, automatonDrawer);
apane.addMouseListener(a);
apane.addMouseMotionListener(a);
return apane;
}
/**
* Initializes the tree pane.
*/
public TreePanel initTreePane() {
final TreePanel tpane = new TreePanel(treeDrawer);
gui.SuperMouseAdapter a = new gui.SuperMouseAdapter() {
public void mouseClicked(MouseEvent event) {
TreeNode n = tpane.nodeAtPoint(event.getPoint());
controller.nodeClicked((MinimizeTreeNode) n, event);
}
public void mousePressed(MouseEvent event) {
TreeNode n = tpane.nodeAtPoint(event.getPoint());
controller.nodeDown((MinimizeTreeNode) n, event);
}
};
tpane.addMouseListener(a);
tpane.addMouseMotionListener(a);
return tpane;
}
/**
* Tells the pane to replace the tree pane with a pane to build the
* minimized automaton. This should be called once the tree is completed and
* the user has elected to move on to the building of the minimized
* automaton.
*
* @param dfa
* the finite state automaton we're minimizing
* @param tree
* the completed minimized tree; results will be unpredictable if
* this tree is not truly minimized
*/
public void beginMinimizedAutomaton(FiniteStateAutomaton dfa,
DefaultTreeModel tree) {
// Create the new view.
remove(controlPanel);
FiniteStateAutomaton newAutomaton = new FiniteStateAutomaton();
minimizer.createStatesForMinimumDfa(dfa, newAutomaton, tree);
SelectionDrawer drawer = new SelectionDrawer(newAutomaton);
EditorPane ep = new EditorPane(drawer, new ToolBox() {
public java.util.List tools(AutomatonPane view,
AutomatonDrawer drawer) {
java.util.List tools = new java.util.LinkedList();
tools.add(new ArrowMinimizeTool(view, drawer));
tools.add(new TransitionTool(view, drawer));
return tools;
}
});
// Remove all selected stuff.
automatonDrawer.clearSelected();
// Set up the controller device.
builderController = new BuilderController(dfa, newAutomaton, drawer,
minimizer, tree, split);
// Set the view in the right hand side.
JPanel right = new JPanel(new BorderLayout());
right.add(ep, BorderLayout.CENTER);
/*
* right.add(new BuilderControlPanel(builderController),
* BorderLayout.SOUTH);
*/
ep.getToolBar().addSeparator();
BuilderControlPanel.initView(ep.getToolBar(), builderController);
split.setRightComponent(right);
invalidate();
repaint();
// Do graph layout.
AutomatonGraph graph = new AutomatonGraph(newAutomaton);
graph.addVertex(newAutomaton.getInitialState(), new Point(0, 0));
Iterator it = builderController.remainingTransitions.iterator();
while (it.hasNext()) {
Transition t = (Transition) it.next();
graph.addEdge(t.getFromState(), t.getToState());
}
GEMLayoutAlgorithm layout = new GEMLayoutAlgorithm();
Set constantStates = new HashSet();
constantStates.add(newAutomaton.getInitialState());
layout.layout(graph, constantStates);
graph.moveAutomatonStates();
validate();
ep.getAutomatonPane().fitToBounds(10);
}
/**
* This extension of the arrow tool does not allow the editing of
* transitions.
*/
private class ArrowMinimizeTool extends gui.editor.ArrowNontransitionTool {
/**
* Instantiates a new ArrowMinimizeTool
.
*
* @param view
* the view the automaton is drawn in
* @param drawer
* the automaton drawer
*/
public ArrowMinimizeTool(AutomatonPane view, AutomatonDrawer drawer) {
super(view, drawer);
}
/**
* On a mouse click, this simply returns,
*
* @param event
* the mouse event
*/
public void mouseClicked(java.awt.event.MouseEvent event) {
super.mouseClicked(event);
State s = automatonDrawer.stateAtPoint(event.getPoint());
// If we're still building the tree...
if (builderController == null)
controller.stateDown(s, event);
}
}
/** The object that handles the grit of the minimization. */
Minimizer minimizer;
/** The drawer for the original automaton. */
SelectionDrawer automatonDrawer;
/** The drawer for the tree. */
SelectTreeDrawer treeDrawer;
/** The minimize controller. */
MinimizeController controller;
/** The minimum automaton builder controller. */
BuilderController builderController = null;
/** The view for this pane. */
JSplitPane split;
/** The toolbar. */
ControlPanel controlPanel;
/** The message label. */
JLabel messageLabel = new JLabel(" ");
}