//ShowTree Tree Visualization System
//Copyright (C) 2009 Yuvi Masory
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation, version 3 only.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package display.components;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import logic.positioningAlgorithms.*;
import logic.treeBuilders.CompleteTreeBuilder;
import logic.treeBuilders.OrganicTreeBuilder;
import logic.treeBuilders.PTBTreeBuilder;
import logic.treeBuilders.TreeBuilder;
import display.Start;
import display.actions.AboutAction;
import display.actions.CaptureScreenshotAction;
import display.actions.ExitAction;
import display.actions.OpenTreeAction;
import display.actions.SaveImageAction;
import display.actions.SaveTreeAction;
import display.actions.ShowGridAction;
import display.actions.ShowNodeBoundsAction;
import display.actions.ShowNodeFieldAction;
import display.listeners.AlgorithmListener;
import display.listeners.GenerateButtonListener;
import display.listeners.TreeBuilderListener;
/*
* The menu bar.
*/
public class TreeMenu extends JMenuBar {
private static final long serialVersionUID = 1L;
private static TreeMenu instance;
private JButton jbGenerate;
private JComboBox jcbAlgorithm;
private JComboBox jcbTree;
private LabeledTextField ltfNumNodes;
private LabeledTextField ltfArity;
private LabeledTextField ltfMinSeparation;
private TreeMenu() {
initMenu();
initAlgorithmMenu();
initTreeBuilderMenu();
initLTFs();
initGenerate();
}
public static TreeMenu getInstance() {
if (instance == null) {
instance = new TreeMenu();
}
return instance;
}
/*
* Adds components to the TreeMenu.
*/
private void initMenu() {
JMenu jmMenu = new JMenu("Menu");
JMenu jmDebug = new JMenu("Debug");
JMenu jmAppear = new JMenu("Appearance");
JMenuItem jmiAbout = new JMenuItem(
new AboutAction("About", null, null));
JMenuItem jmiOpenTree = new JMenuItem(
new OpenTreeAction("Open Tree", null, null));
JMenuItem jmiSaveTree = new JMenuItem(
new SaveTreeAction("Save Tree", null, null));
JMenuItem jmiSaveImage = new JMenuItem(
new SaveImageAction("Save Image", null, null));
JMenuItem jmiScreenshot = new JMenuItem(
new CaptureScreenshotAction("Save Screenshot", null, null));
JMenuItem jmiExit = new JMenuItem(
new ExitAction("Exit", null, null));
jmMenu.add(jmiAbout);
jmMenu.addSeparator();
jmMenu.add(jmiOpenTree);
jmMenu.add(jmiSaveTree);
jmMenu.add(jmiSaveImage);
jmMenu.add(jmiScreenshot);
jmMenu.addSeparator();
jmMenu.add(jmAppear);
jmMenu.add(jmDebug);
jmMenu.addSeparator();
jmMenu.add(jmiExit);
JCheckBoxMenuItem jmiGrid = new JCheckBoxMenuItem(
new ShowGridAction("Show Grid", null, null));
JCheckBoxMenuItem jmiNodeBounds = new JCheckBoxMenuItem(
new ShowNodeBoundsAction("Show Node Bounds", null, null));
JMenuItem jmiShiftSums = new JMenuItem(
new ShowNodeFieldAction("Show Node Field", null, null));
jmDebug.add(jmiGrid);
jmDebug.add(jmiNodeBounds);
jmDebug.add(jmiShiftSums);
add(jmMenu);
}
/*
* Adds TreeBuilders to the TreeBuilder JComboBox
*/
private void initTreeBuilderMenu() {
jcbTree = new JComboBox();
jcbTree.addItem(new OrganicTreeBuilder());
jcbTree.addItem(new PTBTreeBuilder());
jcbTree.addItem(new CompleteTreeBuilder());
jcbTree.addActionListener(new TreeBuilderListener());
add(jcbTree);
}
/*
* Adds PositioningAlgorithm to the PositioningAlgorithm JComboBox
* NOTE: The first algorithm must be n-ary, to work with OpenTreeAction.
*/
private void initAlgorithmMenu() {
jcbAlgorithm = new JComboBox();
// jcbAlgorithm.addItem(new LevelSlide());
jcbAlgorithm.addItem(new W_BJL06_NoLabels());
jcbAlgorithm.addItem(new W_BJL06());
jcbAlgorithm.addItem(new LeavesInorder());
jcbAlgorithm.addItem(new WS79_Narrowest());
jcbAlgorithm.addItem(new Vaucher80());
jcbAlgorithm.addItem(new WS79_Tidy());
jcbAlgorithm.addItem(new Sweet78());
jcbAlgorithm.addItem(new Knuth71WithCentering());
jcbAlgorithm.addItem(new Knuth71());
jcbAlgorithm.addActionListener(AlgorithmListener.getInstance());
add(jcbAlgorithm);
}
/*
* Initializes displayed numNodes, arity, and minSeparation to default values.
*/
private void initLTFs() {
ltfNumNodes = new LabeledTextField(" Nodes: ", Start.DEFAULT_NUM_NODES, 3);
ltfArity = new LabeledTextField(" Arity: ", Start.DEFAULT_ARITY, 2);
ltfMinSeparation = new LabeledTextField(" Spacing: ", Start.DEFAULT_MIN_X_SEPARAION, 2);
add(ltfNumNodes);
add(ltfArity);
add(ltfMinSeparation);
}
/*
* Initializes Generate button.
*/
public void initGenerate() {
jbGenerate = new JButton("Generate");
jbGenerate.addActionListener(new GenerateButtonListener());
add(jbGenerate);
}
/*
* Selects the first PositioningAlgorithm (which is the default) in the positioning algorithms JComboBox.
*/
public void restoreFirstAlgorithm() {
jcbAlgorithm.setSelectedIndex(0);
}
/*
* @returns the first PositioningAlgorithm (which is the default) in the positioning algorithms JComboBox.
*/
public PositioningAlgorithm getFirstAlgorithm() {
return (PositioningAlgorithm) jcbAlgorithm.getItemAt(0);
}
/*
* Corrects numNodes, arity, and minSeparation LabeledTextField entries to make sure they are compatible
* and reasonable. For example, makes sure the arity is 2 and disables the user's ability to change arity
* if a binary PositioningAlgorithm is selected. This function is called after the user makes any changes
* to items on the TreeMenu.
*/
public void correctOptions() {
PositioningAlgorithm alg = TreeMenu.getInstance().getPositioningAlgorithm();
TreeBuilder builder = TreeMenu.getInstance().getTreeBuilder();
if(builder.respectsNodesNumAndArity() == false) {
TreeMenu.getInstance().setDeadOptions();
}
else {
if(alg.isBinary() == false && builder.isBinary() == false) {
TreeMenu.getInstance().setGeneralOptions();
}
else {
TreeMenu.getInstance().setBinaryOptions();
}
}
}
/*
* Sets TreeMenu options appropriate for a PositioningAlgorithm that can handle general trees.
*/
private void setGeneralOptions() {
try {
Integer.parseInt(ltfNumNodes.getText());
}
catch(NumberFormatException e) {
ltfNumNodes.setText(Integer.toString(Start.DEFAULT_NUM_NODES));
}
try {
Integer.parseInt(ltfArity.getText());
}
catch(NumberFormatException e) {
ltfArity.setText(Integer.toString(Start.DEFAULT_ARITY));
}
ltfArity.setAllEnabled(true);
ltfNumNodes.setAllEnabled(true);
ensureXSeparationIsInt();
}
/*
* Sets TreeMenu options appropriate for a PositioningAlgorithm that can handle only binary trees.
*/
private void setBinaryOptions() {
try {
Integer.parseInt(ltfNumNodes.getText());
}
catch(NumberFormatException e) {
ltfNumNodes.setText(Integer.toString(Start.DEFAULT_NUM_NODES));
}
ltfArity.setAllEnabled(false);
ltfArity.setText("2");
ltfNumNodes.setAllEnabled(true);
ensureXSeparationIsInt();
}
/*
* Disables arity and numNodes LabeledTextFields, used for TreeBuilders that ignore user input on
* those fields.
*/
private void setDeadOptions() {
ltfArity.setAllEnabled(false);
ltfArity.setText("");
ltfNumNodes.setAllEnabled(false);
ltfNumNodes.setText("");
ensureXSeparationIsInt();
}
/*
* Makes sure the currently displayed minSeparation value the user entered is an integer.
* Resets it to default minSeparation if not.
*/
private void ensureXSeparationIsInt() {
ltfMinSeparation.setAllEnabled(true);
try {
Integer.parseInt(ltfMinSeparation.getText().trim());
}
catch (java.lang.NumberFormatException ex){
ltfMinSeparation.setText(Integer.toString(Start.DEFAULT_MIN_X_SEPARAION));
}
}
/*
* @returns the currently displayed Display Algorithm
*/
public PositioningAlgorithm getPositioningAlgorithm() {
return (PositioningAlgorithm)jcbAlgorithm.getSelectedItem();
}
/*
* @returns the currently displayed TreeBuilder
*/
public TreeBuilder getTreeBuilder() {
return (TreeBuilder)jcbTree.getSelectedItem();
}
/*
* @returns the currently displayed minSeparation value, converted to an int
*/
public int getSelectedMinSeparation() {
return Integer.parseInt(ltfMinSeparation.getText().trim());
}
/*
* @returns the currently displayed numNodes value, converted to an int
*/
public int getSelectedNumNodes() {
return Integer.parseInt(ltfNumNodes.getText().trim());
}
/*
* @returns the currently displayed arity value, converted to an int
*/
public int getSelectedArity() {
return Integer.parseInt(ltfArity.getText().trim());
}
}