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 FilterBlock extends PuzzleBlock {
private PuzzleBlock _inputBlock;
private static int nextIndex = 0;
public static void reset() {
nextIndex = 0;
}
private String _inputName, _propertyName, _propertyValue;
public void setInputName(String value) {
_inputName = value;
}
public void setPropertyName(String value) {
_propertyName = value;
}
public void setPropertyValue(String value) {
_propertyValue = value;
}
private JComboBox _inputSelect;
private JTextField _propertyNameSelect, _propertyValueSelect;
public FilterBlock()
{
_name = "Filter-" + ++nextIndex;
_type = "Filter";
JPanel editPanel = new JPanel();
editPanel.setLayout(new BoxLayout(editPanel, BoxLayout.Y_AXIS));
// Input ComboBox Panel
JPanel inputPanel = new JPanel();
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.X_AXIS));
JLabel inputLabel = new JLabel("Input to Filter:");
inputPanel.add(inputLabel);
_inputSelect = new JComboBox();
_inputSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _inputSelect.getPreferredSize().height));
inputPanel.add(_inputSelect);
editPanel.add(inputPanel);
JPanel propertyNamePanel = new JPanel();
propertyNamePanel.setLayout(new BoxLayout(propertyNamePanel, BoxLayout.X_AXIS));
JLabel propertyNameLabel = new JLabel("Required Database Property Name:");
propertyNamePanel.add(propertyNameLabel);
_propertyNameSelect = new JTextField();
_propertyNameSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _propertyNameSelect.getPreferredSize().height));
_propertyNameSelect.setText("None");
_propertyNameSelect.setColumns(10);
propertyNamePanel.add(_propertyNameSelect);
editPanel.add(propertyNamePanel);
JPanel propertyValuePanel = new JPanel();
propertyValuePanel.setLayout(new BoxLayout(propertyValuePanel, BoxLayout.X_AXIS));
JLabel propertyValueLabel = new JLabel("Required Property Value:");
propertyValuePanel.add(propertyValueLabel);
_propertyValueSelect = new JTextField();
_propertyValueSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _propertyValueSelect.getPreferredSize().height));
_propertyValueSelect.setText("ALL");
_propertyValueSelect.setColumns(10);
propertyValuePanel.add(_propertyValueSelect);
editPanel.add(propertyValuePanel);
_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(FilterBlock.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();
}
});
_propertyNameSelect.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();
}
});
_propertyValueSelect.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 + " must have database property " + _propertyNameSelect.getText() + " with value: " + _propertyValueSelect.getText() + ". ";
_outputTempName = input;
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 (_propertyName != null) {
_propertyNameSelect.setText(_propertyName);
}
if (_propertyValue != null) {
_propertyValueSelect.setText(_propertyValue);
}
this.update();
}
@Override
public PuzzleBlock[] getPuzzleInputs()
{
if (_inputBlock != null)
return new PuzzleBlock[] { _inputBlock };
return new PuzzleBlock[0];
}
@Override
public String toXML()
{
String xml = "<Filter name=\"" + _name + "\" ";
if (_inputBlock != null)
xml += "input=\"" + _inputBlock.getName() + "\" ";
if (_propertyNameSelect.getText() != null && !_propertyNameSelect.getText().equals(""))
xml += "propertyName=\"" + _propertyNameSelect.getText() + "\" ";
if (_propertyValueSelect.getText() != null && !_propertyValueSelect.getText().equals(""))
xml += "propertyValue=\"" + _propertyValueSelect.getText() + "\" ";
xml += "/>";
return xml;
}
}