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.JCheckBox; 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 PropertyChangePuzzleBlock extends PuzzleBlock { private PuzzleBlock _changerBlock, _changeeBlock; private static int nextIndex = 0; public static void reset() { nextIndex = 0; } private JComboBox _changerSelect, _changeeSelect; private JCheckBox _useProperty; private JPanel _propertyNamePanel, _propertyValuePanel; private JTextField _propertyNameSelect, _propertyValueSelect; private String _changerName, _changeeName, _propertyName, _propertyValue; public void setChangerName(String value) { _changerName = value; } public void setChangeeName(String value) { _changeeName = value; } public void setPropertyName(String value) { _propertyName = value; } public void setPropertyValue(String value) { _propertyValue = value; } public PropertyChangePuzzleBlock() { _name = "Property-Change-" + ++nextIndex; _type = "Property Change Puzzle"; JPanel editPanel = new JPanel(); editPanel.setLayout(new BoxLayout(editPanel, BoxLayout.Y_AXIS)); // Changer ComboBox Panel JPanel changerPanel = new JPanel(); changerPanel.setLayout(new BoxLayout(changerPanel, BoxLayout.X_AXIS)); JLabel changerLabel = new JLabel("Changer:"); changerPanel.add(changerLabel); _changerSelect = new JComboBox(); _changerSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _changerSelect.getPreferredSize().height)); changerPanel.add(_changerSelect); editPanel.add(changerPanel); // Changee ComboBox Panel JPanel changeePanel = new JPanel(); changeePanel.setLayout(new BoxLayout(changeePanel, BoxLayout.X_AXIS)); JLabel changeeLabel = new JLabel("Changee:"); changeePanel.add(changeeLabel); _changeeSelect = new JComboBox(); _changeeSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _changeeSelect.getPreferredSize().height)); changeePanel.add(_changeeSelect); editPanel.add(changeePanel); // Panel for asking to change a specific property JPanel propertyPanel = new JPanel(); propertyPanel.setLayout(new BoxLayout(propertyPanel, BoxLayout.X_AXIS)); JLabel propertyLabel = new JLabel("Use Specific Property"); propertyPanel.add(propertyLabel); _useProperty = new JCheckBox(); propertyPanel.add(_useProperty); editPanel.add(propertyPanel); // Panel for changing the specific property name _propertyNamePanel = new JPanel(); _propertyNamePanel.setLayout(new BoxLayout(_propertyNamePanel, BoxLayout.X_AXIS)); JLabel propertyNameLabel = new JLabel("Desired Property Name:"); _propertyNamePanel.add(propertyNameLabel); _propertyNameSelect = new JTextField(); _propertyNameSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _propertyNameSelect.getPreferredSize().height)); _propertyNameSelect.setText("None"); _propertyNamePanel.add(_propertyNameSelect); _propertyNameSelect.setColumns(10); _propertyNamePanel.setVisible(false); editPanel.add(_propertyNamePanel); // Panel for changing the specific property value _propertyValuePanel = new JPanel(); _propertyValuePanel.setLayout(new BoxLayout(_propertyValuePanel, BoxLayout.X_AXIS)); JLabel propertyValueLabel = new JLabel("Desired Property Value:"); _propertyValuePanel.add(propertyValueLabel); _propertyValueSelect = new JTextField(); _propertyValueSelect.setMaximumSize(new Dimension(Integer.MAX_VALUE, _propertyValueSelect.getPreferredSize().height)); _propertyValueSelect.setText("None"); _propertyValuePanel.add(_propertyValueSelect); _propertyValueSelect.setColumns(10); _propertyValuePanel.setVisible(false); editPanel.add(_propertyValuePanel); _editUI = editPanel; _changerSelect.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { if(_changerBlock == _changerSelect.getSelectedItem() || _changerBlock == null && _changerSelect.getSelectedItem().equals("None")) return; mxGraph puzzleGraph = WindowMain.getPuzzleGraph(); // Before anything, check for a cycle if (_changerSelect.getSelectedItem() != null && !_changerSelect.getSelectedItem().equals("None")) { PuzzleBlock block = (PuzzleBlock)_changerSelect.getSelectedItem(); if (block.canReachBlockBackwards(PropertyChangePuzzleBlock.this)) { SwingUtilities.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(null, "Error: Cannot add cycle to puzzle graph."); } }); if (_changerBlock != null) _changerSelect.setSelectedItem(_changerBlock); else _changerSelect.setSelectedIndex(0); return; } } // first, see if we need to remove a previous edge if(_changerBlock != null) { puzzleGraph.getModel().beginUpdate(); try { puzzleGraph.removeCells(puzzleGraph.getEdgesBetween(_changerBlock.getGraphCell(), _graphCell, false)); } finally { puzzleGraph.getModel().endUpdate(); } } if (_changerSelect.getSelectedItem() == null) _changerSelect.setSelectedIndex(0); if(_changerSelect.getSelectedItem().equals("None")) _changerBlock = null; else { _changerBlock = (PuzzleBlock)_changerSelect.getSelectedItem(); // update the graph with a new edge puzzleGraph.getModel().beginUpdate(); try { puzzleGraph.insertEdge(puzzleGraph.getDefaultParent(), null, null, _changerBlock.getGraphCell(), _graphCell);} finally { puzzleGraph.getModel().endUpdate();} } _changeeSelect.setModel(new DefaultComboBoxModel(makeChangeeComboBox())); if (_changeeBlock == null) _changeeSelect.setSelectedIndex(0); else _changeeSelect.setSelectedItem(_changeeBlock); PuzzleEditPanel.resetTextualDescription(); WindowMain.updatePuzzleGraph(); } }); _changeeSelect.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { if(_changeeBlock == _changeeSelect.getSelectedItem() || _changeeBlock == null && _changeeSelect.getSelectedItem().equals("None")) return; mxGraph puzzleGraph = WindowMain.getPuzzleGraph(); // Before anything, check for a cycle if (_changeeSelect.getSelectedItem() != null && !_changeeSelect.getSelectedItem().equals("None")) { PuzzleBlock block = (PuzzleBlock)_changeeSelect.getSelectedItem(); if (block.canReachBlockBackwards(PropertyChangePuzzleBlock.this)) { SwingUtilities.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(null, "Error: Cannot add cycle to puzzle graph."); } }); if (_changeeBlock != null) _changeeSelect.setSelectedItem(_changeeBlock); else _changeeSelect.setSelectedIndex(0); return; } } // first, see if we need to remove a previous edge if(_changeeBlock != null) { puzzleGraph.getModel().beginUpdate(); try { puzzleGraph.removeCells(puzzleGraph.getEdgesBetween(_changeeBlock.getGraphCell(), _graphCell, false)); } finally { puzzleGraph.getModel().endUpdate(); } } if (_changeeSelect.getSelectedItem() == null) _changeeSelect.setSelectedIndex(0); if(_changeeSelect.getSelectedItem().equals("None")) _changeeBlock = null; else { _changeeBlock = (PuzzleBlock)_changeeSelect.getSelectedItem(); // update the graph with a new edge puzzleGraph.getModel().beginUpdate(); try { puzzleGraph.insertEdge(puzzleGraph.getDefaultParent(), null, null, _changeeBlock.getGraphCell(), _graphCell);} finally { puzzleGraph.getModel().endUpdate();} } _changerSelect.setModel(new DefaultComboBoxModel(makeChangerComboBox())); if (_changerBlock == null) _changerSelect.setSelectedIndex(0); else _changerSelect.setSelectedItem(_changerBlock); PuzzleEditPanel.resetTextualDescription(); WindowMain.updatePuzzleGraph(); } }); _useProperty.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { // Set the visibility of certain elements _propertyNamePanel.setVisible(_useProperty.isSelected()); _propertyValuePanel.setVisible(_useProperty.isSelected()); PuzzleEditPanel.resetTextualDescription(); } }); _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() { _changerSelect.setModel(new DefaultComboBoxModel(makeChangerComboBox())); if (_changerBlock == null) _changerSelect.setSelectedIndex(0); else _changerSelect.setSelectedItem(_changerBlock); _changeeSelect.setModel(new DefaultComboBoxModel(makeChangeeComboBox())); if (_changeeBlock == null) _changeeSelect.setSelectedIndex(0); else _changeeSelect.setSelectedItem(_changeeBlock); } private Object[] makeChangerComboBox() { List<Object> retVal = new ArrayList<Object>(); PuzzleBlock[] blockList = PuzzleEditPanel.getBlockList(); retVal.add("None"); for(PuzzleBlock p : blockList) { if(!p.equals(_changeeSelect.getSelectedItem()) && !p.equals(this)) retVal.add(p); } return retVal.toArray(); } private Object[] makeChangeeComboBox() { List<Object> retVal = new ArrayList<Object>(); PuzzleBlock[] blockList = PuzzleEditPanel.getBlockList(); retVal.add("None"); for(PuzzleBlock p : blockList) { if(!p.equals(_changerSelect.getSelectedItem()) && !p.equals(this)) retVal.add(p); } return retVal.toArray(); } @Override public void maybeRemoveRef(PuzzleBlock block) { if(block.equals(_changerBlock)) { _changerBlock = null; _changerSelect.setSelectedIndex(0); } if(block.equals(_changeeBlock)) { _changeeBlock = null; _changeeSelect.setSelectedIndex(0); } } @Override public String getTextualDescription() { String retVal = ""; if (_changerBlock != null) retVal += _changerBlock.getTextualDescription(); if (_changeeBlock != null) retVal += _changeeBlock.getTextualDescription(); _outputTempName = (_changeeBlock == null) ? "SOMETHING" : _changeeBlock.getOutputTempName(); String changer = (_changerBlock == null) ? "SOMETHING" : _changerBlock.getOutputTempName(); String propertyName, propertyValue; if(_useProperty.isSelected()) { propertyName = "the " + _propertyNameSelect.getText() + " property"; propertyValue = "the value: " + _propertyValueSelect.getText(); } else { propertyName = "some property"; propertyValue = "some value"; } retVal += "The player uses " + changer + " to change " + propertyName + " of " + _outputTempName + " to " + propertyValue + ". "; _outputTempName += " (with " + propertyName + " set to " + propertyValue + ")"; return retVal; } @Override public void attachBlocksToName(Map<String, AreaBlock> areas, Map<String, PuzzleBlock> puzzles) { mxGraph puzzleGraph = WindowMain.getPuzzleGraph(); if (_changerName != null) { _changerBlock = puzzles.get(_changerName); puzzleGraph.getModel().beginUpdate(); try { puzzleGraph.insertEdge(puzzleGraph.getDefaultParent(), null, null, _changerBlock.getGraphCell(), _graphCell);} finally { puzzleGraph.getModel().endUpdate();} } if (_changeeName != null) { _changeeBlock = puzzles.get(_changeeName); puzzleGraph.getModel().beginUpdate(); try { puzzleGraph.insertEdge(puzzleGraph.getDefaultParent(), null, null, _changeeBlock.getGraphCell(), _graphCell);} finally { puzzleGraph.getModel().endUpdate();} } if (_propertyName != null) { _propertyNameSelect.setText(_propertyName); _useProperty.setSelected(true); } if (_propertyValue != null) { _propertyValueSelect.setText(_propertyValue); _useProperty.setSelected(true); } _propertyNamePanel.setVisible(_useProperty.isSelected()); _propertyValuePanel.setVisible(_useProperty.isSelected()); this.update(); } @Override public PuzzleBlock[] getPuzzleInputs() { if (_changerBlock != null && _changeeBlock != null) return new PuzzleBlock[] { _changerBlock, _changeeBlock }; else if (_changerBlock != null) return new PuzzleBlock[] { _changerBlock }; else if (_changeeBlock != null) return new PuzzleBlock[] { _changeeBlock }; return new PuzzleBlock[0]; } @Override public String toXML() { String xml = "<PropertyChangePuzzle name=\"" + _name + "\" "; if (_changerBlock != null) xml += "changer=\"" + _changerBlock.getName() + "\" "; if (_changeeBlock != null) xml += "changee=\"" + _changeeBlock.getName() + "\" "; if (_useProperty.isSelected()) { if (_propertyNameSelect.getText() != null && !_propertyNameSelect.getText().equals("") && !_propertyNameSelect.getText().equals("None")) xml += "propertyName=\"" + _propertyNameSelect.getText() + "\" "; if (_propertyValueSelect.getText() != null && !_propertyValueSelect.getText().equals("") && !_propertyValueSelect.getText().equals("None")) xml += "propertyValue=\"" + _propertyValueSelect.getText() + "\" "; } xml += "/>"; return xml; } }