//copyright (C) 2007 Mocanu Cristian Romeo
package balls;
import javax.swing.JApplet;
import javax.swing.JTree;
import javax.swing.JPanel;
import javax.swing.JFrame;
import
javax.swing.tree.DefaultMutableTreeNode;
import java.awt.Container;
import javax.swing.JSplitPane;
import
javax.swing.tree.TreeSelectionModel;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import
java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.tree.TreePath;
import javax.swing.JScrollPane;
import
java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.SwingUtilities;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import javax.swing.JOptionPane;
import java.util.ResourceBundle;
import java.text.MessageFormat;
import javax.swing.ImageIcon;
import java.awt.Cursor;
import javax.swing.JProgressBar;
import java.awt.BorderLayout;
import
java.lang.reflect.InvocationTargetException;
import java.util.Observer;
import java.util.Observable;
/**
* Describe class
<code>TreeNav</code> here.
*
* @author <a
href="mailto:chrimeea@yahoo.com">Cristian Mocanu</a>
* @version 1.0
*/
public class BallsApplet extends
JApplet implements Observer {
private
JTree tree;
private
Box rPanel;
private
JLabel question;
private
Random random;
private
JRadioButton[] options;
private
final DefaultMutableTreeNode root = new
DefaultMutableTreeNode("Solution");
private
ResourceBundle rb = ResourceBundle.getBundle("Messages");
private
JProgressBar progressBar;
private
BallsSolver solver;
public
void update(Observable o, Object arg) {
progressBar.setValue((Integer) arg);
}
@Override
public
void start() {
final BallsSolution solution = solver.solve();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setVisible(false);
getContentPane().remove(progressBar);
setCursor(null);
renderMenu();
renderUI(solution);
}
});
}
@Override
public
void init() {
super.init();
random = new Random();
solver = new BallsSolver();
solver.addObserver(this);
try {
SwingUtilities.invokeAndWait(new
Runnable() {
public void run()
{
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
progressBar = new JProgressBar(0, solver.getTotalStages());
progressBar.setValue(0);
progressBar.setStringPainted(true);
progressBar.setBorderPainted(true);
progressBar.setString("Solving...");
getContentPane().add(progressBar, BorderLayout.NORTH);
setVisible(true);
}
});
} catch
(InterruptedException e) {
} catch (InvocationTargetException
e) {
}
}
private
void renderMenu() {
final ImageIcon icon = new
ImageIcon(BallsApplet.class.getResource("Scale-icon.gif"));
JMenuBar
menu = new JMenuBar();
JMenu
mOption = new JMenu(rb.getString("options_menu"));
menu.add(mOption);
JMenuItem
mitem = new JMenuItem(rb.getString("restart_menu"));
mitem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new
Runnable() {
public void run()
{
for
(JRadioButton b: options) {
b.setVisible(true);
}
renderOptions(chooseSolution(root));
}
});
}
});
mOption.add(mitem);
mitem = new JMenuItem(rb.getString("about_menu"));
final JApplet j = this;
mitem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new
Runnable() {
public void run()
{
JOptionPane.showMessageDialog(j,
rb.getString("about_message"),
rb.getString("about_title"),
JOptionPane.INFORMATION_MESSAGE,
icon);
}
});
}
});
mOption.add(mitem);
setJMenuBar(menu);
}
private
void renderUI(BallsSolution solution) {
createNodes(root, solution);
tree = new JTree(root);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
rPanel = new Box(BoxLayout.Y_AXIS);
JSplitPane
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
true, new JScrollPane(tree), new JScrollPane(rPanel));
split.setResizeWeight(0.5);
getContentPane().add(split);
question = new JLabel();
rPanel.add(question);
//Box b =
new Box(BoxLayout.X_AXIS);
options = new JRadioButton[3];
for (int i = 0; i < 3; i++) {
options[i] = new
JRadioButton();
rPanel.add(options[i]);
}
renderOptions(chooseSolution(root));
}
private
DefaultMutableTreeNode chooseSolution(DefaultMutableTreeNode root) {
return (DefaultMutableTreeNode)
root.getChildAt(random.nextInt(root.getChildCount()));
}
private
String getOutcome(Knowledge knowledge) {
int s = knowledge.getSolution();
if (s == -1) {
return
rb.getString("impossible_outcome");
} else if
(knowledge.getState(s) == BallState.UNKNOWN_LIGHT) {
return
MessageFormat.format(rb.getString("solution_light"), s + 1);
} else if
(knowledge.getState(s) == BallState.UNKNOWN_HEAVY) {
return
MessageFormat.format(rb.getString("solution_heavy"), s + 1);
} else {
return
MessageFormat.format(rb.getString("solution_unknown"), s + 1);
}
}
private
void renderOptions(DefaultMutableTreeNode root) {
int cc = root.getChildCount();
if (cc == 0) {
question.setText(root.toString());
for (JRadioButton
b: options) {
b.setVisible(false);
}
return;
}
question.setText(MessageFormat.format(rb.getString("compare"),
root.toString()));
for (int i = 0; i < cc; i++) {
final DefaultMutableTreeNode
childNode = (DefaultMutableTreeNode) root.getChildAt(i);
options[i].setText(childNode.toString());
ActionListener[] l
= options[i].getActionListeners();
assert l.length
< 2;
if (l.length == 1)
{
options[i].removeActionListener(l[0]);
}
options[i].addActionListener(new
ActionListener() {
public void
actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
DefaultMutableTreeNode node = chooseSolution(childNode);
TreePath treePath = new TreePath(node.getPath());
tree.expandPath(treePath);
tree.setSelectionPath(treePath);
renderOptions((DefaultMutableTreeNode)
tree.getLastSelectedPathComponent());
}
});
}
});
options[i].setSelected(false);
options[i].setVisible(true);
}
for (int i = cc; i < 3; i++) {
options[i].setVisible(false);
}
}
private
void createNodes(DefaultMutableTreeNode root, BallsSolution solution) {
DefaultMutableTreeNode
subRoot;
if (solution.isEmptySolutions()) {
Knowledge k = solution.getKnowledge();
subRoot = new
DefaultMutableTreeNode(getOutcome(k));
root.add(subRoot);
} else {
for (SolutionBean
b: solution.getSolutions()) {
StringBuilder
label1 = new StringBuilder();
for (int i: b.getTransition().getLeftPan()) {
label1.append((i +
1) + " ");
}
StringBuilder
label2 = new StringBuilder();
for (int i: b.getTransition().getRightPan()) {
label2.append((i +
1) + " ");
}
subRoot = new
DefaultMutableTreeNode(MessageFormat.format(rb.getString("and"),
label1, label2));
DefaultMutableTreeNode temp;
if (b.getSolutionsLight().getKnowledge().getSolution() >
-1) {
temp = new
DefaultMutableTreeNode(rb.getString("case_light"));
createNodes(temp,
b.getSolutionsLight());
subRoot.add(temp);
}
if (b.getSolutionsHeavy().getKnowledge().getSolution() >
-1) {
temp = new
DefaultMutableTreeNode(rb.getString("case_heavy"));
createNodes(temp,
b.getSolutionsHeavy());
subRoot.add(temp);
}
if (b.getSolutionsEqual().getKnowledge().getSolution() >
-1) {
temp = new
DefaultMutableTreeNode(rb.getString("case_equal"));
createNodes(temp,
b.getSolutionsEqual());
subRoot.add(temp);
}
root.add(subRoot);
}
}
}
}