package puzzledice;
import gui.PuzzleEditPanel;
import gui.WindowMain;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import com.mxgraph.view.mxGraph;
public class OutputBlock extends PuzzleBlock {
private PuzzleBlock _inputBlock;
private static int nextIndex = 0;
public static void reset() {
nextIndex = 0;
}
private String _inputName, _requestName;
public void setInputName(String value) {
_inputName = value;
}
public void setRequestName(String value) {
_requestName = value;
}
private JComboBox _inputSelect;
private JTextField _requestSelect;
public OutputBlock()
{
_name = "Output-" + ++nextIndex;
_type = "Output";
JPanel editPanel = new JPanel();
editPanel.setLayout(new BoxLayout(editPanel, BoxLayout.Y_AXIS));
// Input ComboBoxPanel
JPanel inputPanel = new JPanel();
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.X_AXIS));
JLabel inputLabel = new JLabel("Root Block:");
inputPanel.add(inputLabel);
_inputSelect = new JComboBox();
_inputSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _inputSelect.getPreferredSize().height));
inputPanel.add(_inputSelect);
editPanel.add(inputPanel);
JPanel requestPanel = new JPanel();
requestPanel.setLayout(new BoxLayout(requestPanel, BoxLayout.X_AXIS));
JLabel requestLabel = new JLabel("Requested Output Item: ");
requestPanel.add(requestLabel);
_requestSelect = new JTextField();
_requestSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _requestSelect.getPreferredSize().height));
_requestSelect.setText("None");
_requestSelect.setColumns(10);
requestPanel.add(_requestSelect);
editPanel.add(requestPanel);
_editUI = editPanel;
_inputSelect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (_inputBlock == _inputSelect.getSelectedItem() || _inputBlock == null && _inputSelect.getSelectedItem().equals("None"))
return;
mxGraph puzzleGraph = WindowMain.getPuzzleGraph();
// Before anything, check for a cycle
if (_inputSelect.getSelectedItem() != null && !_inputSelect.getSelectedItem().equals("None")) {
PuzzleBlock block = (PuzzleBlock)_inputSelect.getSelectedItem();
if (block.canReachBlockBackwards(OutputBlock.this)) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(null, "Error: Cannot add cycle to puzzle graph.");
}
});
if (_inputBlock != null)
_inputSelect.setSelectedItem(_inputBlock);
else
_inputSelect.setSelectedIndex(0);
return;
}
}
// First, see if we need to remove a previous edge
if (_inputBlock != null) {
puzzleGraph.getModel().beginUpdate();
try { puzzleGraph.removeCells(puzzleGraph.getEdgesBetween(_inputBlock.getGraphCell(), _graphCell, false)); }
finally { puzzleGraph.getModel().endUpdate(); }
}
if (_inputSelect.getSelectedItem() == null)
_inputSelect.setSelectedIndex(0);
if (_inputSelect.getSelectedItem().equals("None"))
_inputBlock = null;
else {
_inputBlock = (PuzzleBlock)_inputSelect.getSelectedItem();
// Update the graph with a new edge
puzzleGraph.getModel().beginUpdate();
try { puzzleGraph.insertEdge(puzzleGraph.getDefaultParent(), null, null, _inputBlock.getGraphCell(), _graphCell);}
finally { puzzleGraph.getModel().endUpdate(); }
}
PuzzleEditPanel.resetTextualDescription();
WindowMain.updatePuzzleGraph();
}
});
_requestSelect.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent evt) {
PuzzleEditPanel.resetTextualDescription();
}
@Override
public void insertUpdate(DocumentEvent evt) {
PuzzleEditPanel.resetTextualDescription();
}
@Override
public void removeUpdate(DocumentEvent evt) {
PuzzleEditPanel.resetTextualDescription();
}
});
}
@Override
public void update()
{
_inputSelect.setModel(new DefaultComboBoxModel(makeInputList()));
if (_inputBlock == null)
_inputSelect.setSelectedIndex(0);
else
_inputSelect.setSelectedItem(_inputBlock);
}
private Object[] makeInputList()
{
List<Object> retVal = new ArrayList<Object>();
PuzzleBlock[] blockList = PuzzleEditPanel.getBlockList();
retVal.add("None");
for (PuzzleBlock p : blockList) {
if (!p.equals(this))
retVal.add(p);
}
return retVal.toArray();
}
@Override
public void maybeRemoveRef(PuzzleBlock block)
{
if (block.equals(_inputBlock)) {
_inputBlock = null;
_inputSelect.setSelectedIndex(0);
}
}
@Override
public String getTextualDescription()
{
String retVal = "";
if(_inputBlock != null)
retVal += _inputBlock.getTextualDescription();
String input = (_inputBlock == null) ? "SOMETHING" : _inputBlock.getOutputTempName();
retVal += input + " is the output item " + _requestSelect.getText() + " and ends the puzzle.";
_outputTempName = _requestSelect.getText();
return retVal;
}
@Override
public void attachBlocksToName(Map<String, AreaBlock> areas, Map<String, PuzzleBlock> puzzles)
{
mxGraph puzzleGraph = WindowMain.getPuzzleGraph();
if (_inputName != null) {
_inputBlock = puzzles.get(_inputName);
puzzleGraph.getModel().beginUpdate();
try { puzzleGraph.insertEdge(puzzleGraph.getDefaultParent(), null, null, _inputBlock.getGraphCell(), _graphCell);}
finally { puzzleGraph.getModel().endUpdate();}
}
if (_requestName != null) {
_requestSelect.setText(_requestName);
}
this.update();
}
@Override
public PuzzleBlock[] getPuzzleInputs()
{
if (_inputBlock != null)
return new PuzzleBlock[] { _inputBlock };
return new PuzzleBlock[0];
}
@Override
public String toXML()
{
String xml = "<Output name=\"" + _name + "\" ";
if (_inputBlock != null)
xml += "input=\"" + _inputBlock.getName() + "\" ";
if (_requestSelect.getText() != null && !_requestSelect.getText().equals(""))
xml += "requestName=\"" + _requestSelect.getText() + "\" ";
xml += "/>";
return xml;
}
}