package bayesGame.ui; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.MouseListener; import java.awt.geom.Ellipse2D; import java.awt.geom.RoundRectangle2D; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.KeyStroke; import javax.swing.text.BadLocationException; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import org.apache.commons.collections15.Transformer; import org.apache.commons.math3.util.Pair; import bayesGame.BayesGame; import bayesGame.bayesbayes.BayesNet; import bayesGame.bayesbayes.BayesNode; import bayesGame.ui.transformers.BayesNodeProbabilityToGridTransformer; import bayesGame.ui.verbs.Verb; import edu.uci.ics.jung.algorithms.layout.DAGLayout; import edu.uci.ics.jung.algorithms.layout.Layout; import edu.uci.ics.jung.graph.AbstractGraph; import edu.uci.ics.jung.visualization.Layer; import edu.uci.ics.jung.visualization.VisualizationViewer; import edu.uci.ics.jung.visualization.control.PluggableGraphMouse; import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; /** * @author Kaj Sotala * * The default interface for the game. * */ public class TutorialInterfaceView { private JFrame frame; private JPanel graphPanel; private JPanel infoPanel; private JTextPane textPane; private JScrollPane scroll; private VisualizationViewer<BayesNode, Pair<Integer,Integer>> vv; private Map<Map<Object, Boolean>,JLabel> visualizations; private AbstractGraph graph; public static final int graphTypeBayesGraph = 0; public TutorialInterfaceView() { frame = new JFrame("Academy Game"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); addComponentsToPane(frame.getContentPane()); visualizations = new HashMap<Map<Object,Boolean>,JLabel>(); setupVisualizationPane(); frame.pack(); frame.setVisible(true); } private void addComponentsToPane(Container pane) { GridBagConstraints c; pane.setLayout(new GridBagLayout()); c = new GridBagConstraints(); graphPanel = new JPanel(); graphPanel.setBorder(BorderFactory.createLineBorder(Color.black)); graphPanel.setMinimumSize(new Dimension(500,500)); c.gridx = 0; c.gridy = 0; c.weightx = 1; c.weighty = 1; c.ipady = 0; c.ipadx = 0; c.fill = GridBagConstraints.BOTH; pane.add(graphPanel, c); c = new GridBagConstraints(); infoPanel = new JPanel(); infoPanel.setBorder(BorderFactory.createLineBorder(Color.black)); infoPanel.setMinimumSize(new Dimension(250,500)); c.gridx = 1; c.gridy = 0; c.weightx = 1; c.weighty = 1; c.ipady = 0; c.ipadx = 0; c.fill = GridBagConstraints.BOTH; pane.add(infoPanel, c); c = new GridBagConstraints(); textPane = new JTextPane(); textPane.setEditable(false); textPane.setPreferredSize(new Dimension(400,200)); textPane.putClientProperty("IgnoreCharsetDirective", Boolean.TRUE); scroll = new JScrollPane (textPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); c.gridx = 0; c.gridy = 1; c.gridwidth = 2; c.ipady = 0; c.weightx = 1; c.weighty = 1; c.fill = GridBagConstraints.BOTH; pane.add(scroll, c); } public void setVisible(boolean visible){ frame.setVisible(visible); } public void addVisualization(Map<Object,Boolean> item){ addVisualization(item, true); } public void addVisualization(Map<Object,Boolean> item, boolean truth){ addVisualizationToPane(item, truth); } public boolean setVisualizationTruth(Map<Object,Boolean> item, boolean truth){ if (!containsVisualization(item)){ return false; } addVisualizationToPane(item, truth); return true; } private void addVisualizationToPane(Map<Object,Boolean> item, boolean itemTruth){ JLabel visualization; boolean editingOldVisualization = containsVisualization(item); if (editingOldVisualization){ visualization = visualizations.get(item); } else { visualization = new JLabel(); } Set<Entry<Object,Boolean>> entrySet = item.entrySet(); String html = "<html>"; if (!itemTruth){ html = html + "<strike><font color=black>"; } for (Entry<Object,Boolean> e : entrySet){ Boolean truth = e.getValue(); String objectString = e.getKey().toString(); char objectChar; if (truth){ objectChar = objectString.toUpperCase().charAt(0); } else { objectChar = objectString.toLowerCase().charAt(0); } if (truth && itemTruth){ html = html + "<font color=" + BayesGame.trueColorName + ">" + objectChar + " </font>"; } else if (!truth && itemTruth) { html = html + "<font color=" + BayesGame.falseColorName + ">" + objectChar + " </font>"; } else if (!itemTruth){ html = html + objectChar + " "; } } if (!itemTruth){ html = html + "</strike>"; } html = html + "</html>"; visualization.setText(html); visualization.setAlignmentX(Component.CENTER_ALIGNMENT); visualization.setFont(new Font("Serif", Font.BOLD, 28)); if (!editingOldVisualization){ infoPanel.add(visualization); infoPanel.add(Box.createVerticalGlue()); } visualizations.put(item, visualization); frame.revalidate(); } public boolean containsVisualization(Map<Object,Boolean> visualization){ return visualizations.containsKey(visualization); } public void updateVisualizations(ArrayList<Map<Object,Boolean>> newVisualizations){ Set<Map<Object, Boolean>> oldVisualizations = new HashSet<Map<Object,Boolean>>(visualizations.keySet()); Set<Map<Object, Boolean>> newItems = new HashSet<Map<Object,Boolean>>(newVisualizations); newItems.removeAll(oldVisualizations); Set<Map<Object, Boolean>> oldImpossibleItems = new HashSet<Map<Object,Boolean>>(oldVisualizations); oldImpossibleItems.removeAll(newVisualizations); oldVisualizations.removeAll(oldImpossibleItems); for (Map<Object, Boolean> m : newItems){ this.addVisualization(m); } for (Map<Object, Boolean> m : oldImpossibleItems){ this.setVisualizationTruth(m, false); } for (Map<Object, Boolean> m : oldVisualizations){ this.setVisualizationTruth(m, true); } } public void highlightVisualization(Map<Object,Boolean> item, boolean highlight){ clearVisualizationHighlights(); if (containsVisualization(item)){ JLabel label = visualizations.get(item); label.setBackground(Color.WHITE); label.setOpaque(highlight); infoPanel.repaint(); } } public void clearVisualizationHighlights(){ Set<Entry<Map<Object, Boolean>, JLabel>> set = visualizations.entrySet(); for (Entry<Map<Object,Boolean>, JLabel> e : set){ JLabel label = e.getValue(); label.setOpaque(false); } } public void addText(String text){ SimpleAttributeSet style = new SimpleAttributeSet(); StyleConstants.setFontSize(style, 16); addText(text, style); } public void addTextMore(String text){ addText(text); addMore(); } public void addTextClear(String text){ clearText(); addText(text); } public void addMore(){ SimpleAttributeSet style = new SimpleAttributeSet(); StyleConstants.setFontSize(style, 16); addText(""); addText("(space for more)", style); } public void addTextMoreClear(String text){ clearText(); addTextMore(text); } public void addTutorialText(String text){ SimpleAttributeSet style = new SimpleAttributeSet(); StyleConstants.setFontSize(style, 16); StyleConstants.setBold(style, true); addText(text, style); } public void addTutorialTextMore(String text){ addTutorialText(text); addMore(); } private void addText(String text, SimpleAttributeSet style){ text = text + System.getProperty("line.separator"); StyledDocument doc = textPane.getStyledDocument(); try { doc.insertString(doc.getLength(), text, style); } catch (BadLocationException e){} frame.pack(); textPane.setCaretPosition(textPane.getDocument().getLength()); scroll.revalidate(); } public void clearText(){ textPane.setText(""); } public void addKeyListener(KeyAdapter k){ graphPanel.addKeyListener(k); infoPanel.addKeyListener(k); textPane.addKeyListener(k); frame.getRootPane().addKeyListener(k); } public void addVerb(Verb verb){ addGraphMouse(verb.getPGM()); } private void addGraphMouse(PluggableGraphMouse gm){ vv.addMouseListener(gm); } public void clearMouseListeners(){ MouseListener[] listeners = vv.getMouseListeners(); for (MouseListener m : listeners){ vv.removeMouseListener(m); } } public void clearInfoPanel(){ infoPanel.removeAll(); visualizations = new HashMap<Map<Object,Boolean>,JLabel>(); } private void setupVisualizationPane(){ infoPanel.removeAll(); infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.PAGE_AXIS)); infoPanel.add(Box.createVerticalGlue()); } public void setGraph(BayesNet net){ this.graph = net.getGraph(); } public void displayGraph(int graphType){ if (graph != null){ switch(graphType){ case(graphTypeBayesGraph): displayBayesGraph(); } } } private void displayBayesGraph(){ Layout<BayesNode, Pair<Integer,Integer>> layout = new DAGLayout<BayesNode, Pair<Integer, Integer>>(graph); layout.setSize(new Dimension(700,700)); vv = new VisualizationViewer<BayesNode, Pair<Integer,Integer>>(layout); Transformer<BayesNode,Paint> vertexPaint = new Transformer<BayesNode,Paint>() { public Paint transform(BayesNode i) { Boolean assumed = i.assumedValue(); if (i.isObserved()){ if (i.getProbability().doubleValue() == 1.0d){ return BayesGame.trueColor; } else { return BayesGame.falseColor; } } if (assumed == null){ return BayesGame.unknownColor; } else { if (assumed){ return BayesGame.trueColor; } else { return BayesGame.falseColor; } } } }; Transformer<BayesNode,Shape> vertexShape = new Transformer<BayesNode,Shape>(){ public Shape transform(BayesNode b){ if (!b.isObserved()){ return new Ellipse2D.Double(-16, -16, 32, 32); } else { return new RoundRectangle2D.Double(-16, -16, 32, 32, 16, 16); } } }; vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint); vv.getRenderContext().setVertexShapeTransformer(vertexShape); // vv.getRenderContext().setVertexIconTransformer(new BayesNodeProbabilityToGridTransformer()); vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); vv.setPreferredSize(new Dimension(800,800)); //Sets the viewing area size vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).rotate(-Math.PI, 350, 350); graphPanel.add(vv); frame.pack(); graphPanel.setVisible(true); } public void updateGraph(){ vv.repaint(); } public void redrawGraph(){ graphPanel.removeAll(); displayBayesGraph(); } public int displayDialog(Object[] options, String text){ return JOptionPane.showOptionDialog(frame, text, text, JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]); } public void dispose(){ frame.dispose(); } }