package ls.graph.ui;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.Collection;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.border.Border;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
import ls.graph.ControlListener;
import ls.graph.Controller;
import ls.graph.script.GraphScriptEngine;
import ls.graph.script.ScriptUIUtils;
import ls.graph.script.ScriptableGraph;
import ls.ui.msg.MessagePanel;
import ls.util.Utils;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.decorators.VertexStrokeFunction;
import edu.uci.ics.jung.visualization.GraphMouseListener;
import edu.uci.ics.jung.visualization.Layout;
import edu.uci.ics.jung.visualization.PickedState;
import edu.uci.ics.jung.visualization.PluggableRenderer;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.contrib.CircleLayout;
public class MainWindow extends JFrame implements ControlListener
{
private static final long serialVersionUID = 1L;
private Layout graphLayout = null;
JTextPane txtScript;
JFileChooser fileChooser;
private Controller controller = null;
private final int INITIAL_WINDOW_W = 800;
private final int INITIAL_WINDOW_H = 600;
private ScriptSettingsPanel scriptSettingsPanel;
private UIMessagesHandler msgHandler;
private JSplitPane spltGraphScript;
private GraphEditPanel graphEditPane;
private static final String SCRIPT_PANE_TITLE_PREFIX = "Algorithm Code";
private MainWindow() throws HeadlessException
{
super();
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception exn)
{
Utils.exn(exn);
}
fileChooser = new JFileChooser();
String initialDir = Controller.getProperty("SCRIPTS_DIR","C:\\");
fileChooser.setCurrentDirectory(new File(initialDir));
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
msgHandler = new UIMessagesHandler(this);
}
public MainWindow(Controller c,String defaultScript)
{
this();
this.controller = c;
this.controller.addListener(this);
initUI();
setLocation(100,100);
setPreferredSize(new Dimension(400,600));
setSize(INITIAL_WINDOW_W, INITIAL_WINDOW_H);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
if (defaultScript != null)
setScriptText(defaultScript);
}
public void popup(String msg)
{
if (msgHandler != null) msgHandler.handleMsg(msg);
}
/**
* Get the list of files to be included
* @return
*/
List<File> getScriptIncludes()
{
List<File> l = scriptSettingsPanel.getScriptIncludes();
return l;
}
void setScriptText(String scriptText)
{
if (txtScript != null)
{
txtScript.setText(scriptText);
}
}
ScriptableGraph getGraph()
{
return this.controller.getGraph();
}
private Layout getCurrentGraphLayout()
{
ScriptUIUtils suu = controller.getGraphScriptEngine().getScriptUIUtils();
if (suu == null) return null;
VisualizationViewer vv = suu.getVisualizationViewer();
if (vv == null) return null;
return vv.getGraphLayout();
}
private JComponent getGraphComponent()
{
graphLayout = getCurrentGraphLayout();
if (graphLayout == null)
graphLayout = new CircleLayout(getGraph());
Dimension d = new Dimension((int)(INITIAL_WINDOW_W * 0.7),(int)(INITIAL_WINDOW_H * 0.7));
graphLayout.initialize(d);
PluggableRenderer r = new PluggableRenderer();
ScriptUIUtils suu = controller.getGraphScriptEngine().getScriptUIUtils();
r.setVertexPaintFunction(suu.SVPF());
r.setVertexStringer(suu.SVS());
vertexStrokeFunction = new GSVertexStrokeFunction();
r.setVertexStrokeFunction(vertexStrokeFunction);
VisualizationViewer vv = new VisualizationViewer(graphLayout,r);
vv.addGraphMouseListener(new GSMouseListener());
suu.setVisualizationViewer(vv);
//Check to see if we should display the default node labels
String showNodeLabels = Controller.getProperty("SHOW_NODE_LABELS", "FALSE");
if ("TRUE".equalsIgnoreCase(showNodeLabels))
{
for (Vertex v : (Collection<Vertex>)(getGraph().getVertices()))
suu.setVertexLabel(v, v.toString());
}
JScrollPane zoomPane = new JScrollPane(vv);
return zoomPane;
//return vv;
}
GSVertexStrokeFunction vertexStrokeFunction = null;
private JPanel scriptPane;
private class GSVertexStrokeFunction implements VertexStrokeFunction
{
Vertex pickedVertex = null;
private final Stroke PICKED_STROKE = new BasicStroke(3.0f);
private final Stroke NON_PICKED_STROKE = new BasicStroke(1.0f);
//private ConstantVertexStrokeFunction cvsf = new ConstantVertexStrokeFunction(1.0f);
void setPickedVertex(Vertex v)
{
pickedVertex = v;
}
public Stroke getStroke(Vertex v)
{
if (v == pickedVertex)
return PICKED_STROKE;
else
return NON_PICKED_STROKE;
}
} //end of GSVertexStrokeFunction class
private class GSMouseListener implements GraphMouseListener
{
public void graphClicked(Vertex v, MouseEvent me)
{
setPickedVertex(v);
}
public void graphPressed(Vertex v, MouseEvent me)
{
setPickedVertex(v);
}
public void graphReleased(Vertex v, MouseEvent me)
{}
private void setPickedVertex(Vertex v)
{
ScriptUIUtils suu =
controller
.getGraphScriptEngine()
.getScriptUIUtils();
VisualizationViewer vv = suu.getVisualizationViewer();
PickedState ps = vv.getPickedState();
ps.clearPickedVertices();
ps.pick(v, true);
vertexStrokeFunction.setPickedVertex(v);
}
} //end of GSMouseListener
void setGraphLayout(Layout gLayout)
{
if (gLayout != null)
this.controller
.getGraphScriptEngine()
.getScriptUIUtils()
.getVisualizationViewer()
.setGraphLayout(gLayout,true);
}
private void initUI()
{
setTitle("Graph Script");
createMenuBar();
getContentPane().setLayout(new BorderLayout());
spltGraphScript = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
this.getGraphComponent(),
getLowerPane());
// createScriptPane());
spltGraphScript.setDividerLocation((int)(INITIAL_WINDOW_H * 0.7));
spltGraphScript.setResizeWeight(0.5);
getContentPane().add(createControlPane(),BorderLayout.SOUTH);
JSplitPane spltMain =
new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
spltGraphScript,
createRightPanel());
spltMain.setDividerLocation((int)(INITIAL_WINDOW_W * 0.7));
spltMain.setResizeWeight(0.5);
getContentPane().add(spltMain,BorderLayout.CENTER);
}
private Component getLowerPane()
{
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
tabbedPane.addTab("Script",createScriptPane());
tabbedPane.addTab("Graph",getGraphEditPane());
return tabbedPane;
}
private Component getGraphEditPane()
{
graphEditPane = new GraphEditPanel(this);
return graphEditPane;
}
private void createMenuBar()
{
Menu mnu = new Menu(this);
this.setJMenuBar(mnu);
this.controller
.getGraphScriptEngine()
.getScriptUIUtils()
.addAlgorithmListener(mnu);
}
Container createStatusPanel()
{
StatusPanel panel = new StatusPanel();
controller
.getGraphScriptEngine()
.getScriptUIUtils()
.addAlgorithmListener(panel);
return panel;
}
private Container createRightPanel()
{
JTabbedPane tabbedPane = new JTabbedPane();
scriptSettingsPanel = new ScriptSettingsPanel();
tabbedPane.add("Script Settings", scriptSettingsPanel);
MessagePanel msgPanel = new MessagePanel();
tabbedPane.add("Messages",msgPanel);
GraphSettingsPanel graphPanel = new GraphSettingsPanel(this);
tabbedPane.add("Graph",graphPanel);
return tabbedPane;
}
private JPanel createScriptPane()
{
scriptPane = new JPanel();
scriptPane.setLayout(new BorderLayout());
txtScript = new JTextPane();
txtScript.setEditable(true);
txtScript.setEnabled(true);
txtScript.setAlignmentY(0.0f);
//txtScript.setFont(new Font("Arial",Font.PLAIN,11));
Style style = txtScript.addStyle("Script", null);
float tabLength = 7.0f;
style.addAttribute(
StyleConstants.FontConstants.TabSet,
new TabSet(new TabStop[]
{new TabStop(tabLength),
new TabStop(tabLength*2),
new TabStop(tabLength*3),
new TabStop(tabLength*4),
new TabStop(tabLength*5),
new TabStop(tabLength*6)}));
style.addAttribute(StyleConstants.FontConstants.FontFamily, "Courier New");
txtScript.setLogicalStyle(style);
JScrollPane scrollPanel = new JScrollPane(txtScript);
scriptPane.add(scrollPanel,BorderLayout.CENTER);
Border scriptPaneBorder = BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),"Algorithm Code");
scriptPane.setBorder(scriptPaneBorder);
return scriptPane;
}
public void scriptLoaded(File scriptFile, String scriptText)
{
String newTitle = SCRIPT_PANE_TITLE_PREFIX + " (" + scriptFile.getName() + ")";
scriptPane.setBorder(BorderFactory.createTitledBorder(newTitle));
// scriptPaneBorder.setTitle(newTitle);
}
private JPanel createControlPane()
{
ControlPanel panel = new ControlPanel(this);
controller
.getGraphScriptEngine()
.getScriptUIUtils()
.addAlgorithmListener(panel);
return panel;
}
GraphScriptEngine getScriptEngine()
{
return this.controller.getGraphScriptEngine();
}
public void graphChanged(ScriptableGraph sg)
{
//refresh the graph display
spltGraphScript.setLeftComponent(getGraphComponent());
//refresh the graph text display
graphEditPane.setGraph(sg);
}
Controller getController()
{
return controller;
}
public void graphLoaded(File graphFile)
{
if (graphFile != null)
graphEditPane.setGraphFilename(graphFile.getName());
}
} //end of MainWindow class