From 75aff5ded67b9ce3f5888ad74a8add59bfe08f9a Mon Sep 17 00:00:00 2001 From: "T. van der Zwan" Date: Fri, 6 Dec 2013 23:20:57 +0100 Subject: [PATCH] Further update of effect configuration in HyperCon. Former-commit-id: f85efbcafc0822fba3bb6d594182b4a11700360a --- .../gui/EffectArgumentCellEditor.java | 69 ++++++ .../hypercon/gui/EffectEnginePanel.java | 233 ++++++++++++++++-- .../hyperion/hypercon/spec/EffectConfig.java | 35 ++- .../hypercon/spec/EffectEngineConfig.java | 29 +-- 4 files changed, 326 insertions(+), 40 deletions(-) create mode 100644 src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/EffectArgumentCellEditor.java diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/EffectArgumentCellEditor.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/EffectArgumentCellEditor.java new file mode 100644 index 00000000..1d37a0c8 --- /dev/null +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/EffectArgumentCellEditor.java @@ -0,0 +1,69 @@ +package org.hyperion.hypercon.gui; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.AbstractCellEditor; +import javax.swing.JCheckBox; +import javax.swing.JColorChooser; +import javax.swing.JSpinner; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.SpinnerNumberModel; +import javax.swing.table.TableCellEditor; + +public class EffectArgumentCellEditor extends AbstractCellEditor implements TableCellEditor { + + int selEditor = 0; + + private JSpinner mIntegerSpinner = new JSpinner(new SpinnerNumberModel(0, Integer.MIN_VALUE, Integer.MAX_VALUE, 1)); + private JSpinner mDoubleSpinner = new JSpinner(new SpinnerNumberModel(0.0, -Double.MAX_VALUE, Double.MAX_VALUE, 1.0)); + private JCheckBox mBooleanCheck = new JCheckBox(); + private JColorChooser mColorChooser = new JColorChooser(); + private JTextField mStringEditor = new JTextField(); + + + + @Override + public Object getCellEditorValue() { + switch (selEditor) { + case 0: + return mIntegerSpinner.getValue(); + case 1: + return mDoubleSpinner.getValue(); + case 2: + return mBooleanCheck.isSelected(); + case 3: + return mStringEditor.getText(); + case 4: + return mColorChooser.getColor(); + } + + return null; + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + if (value instanceof Integer) { + selEditor = 0; + mIntegerSpinner.setValue((Integer)value); + return mIntegerSpinner; + } else if (value instanceof Double) { + selEditor = 1; + mDoubleSpinner.setValue((Double)value); + return mDoubleSpinner; + } else if (value instanceof Boolean) { + selEditor = 2; + mBooleanCheck.setSelected((Boolean)value); + return mBooleanCheck; + } else if (value instanceof Color) { + selEditor = 4; +// return mColorCombo; + } + + selEditor = 3; + mStringEditor.setText('"' + value.toString() + '"'); + return mStringEditor; + } + +} diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/EffectEnginePanel.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/EffectEnginePanel.java index e3a69625..35992284 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/EffectEnginePanel.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/gui/EffectEnginePanel.java @@ -1,19 +1,26 @@ package org.hyperion.hypercon.gui; import java.awt.BorderLayout; +import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Vector; import javax.swing.BorderFactory; import javax.swing.BoxLayout; +import javax.swing.ComboBoxEditor; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JTextArea; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableColumn; import org.hyperion.hypercon.spec.EffectConfig; import org.hyperion.hypercon.spec.EffectEngineConfig; @@ -26,14 +33,140 @@ public class EffectEnginePanel extends JPanel { private JPanel mControlPanel; private JComboBox mEffectCombo; + private JButton mCloneButton; private JButton mAddButton; private JButton mDelButton; private JPanel mEffectPanel; private JLabel mPythonLabel; private JComboBox mPythonCombo; - private JLabel mJsonArgumentLabel; - private JTextArea mJsonArgumentArea; + private JPanel mEffectArgumentPanel; + private JTable mEffectArgumentTable; + + private AbstractTableModel mEffectArgumentTableModel = new AbstractTableModel() { + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + EffectConfig effect = (EffectConfig) mEffectModel.getSelectedItem(); + if (effect == null) { + return false; + } + if (rowIndex == effect.mArgs.size()) { + return columnIndex == 0; + } + return true; + }; + + @Override + public int getColumnCount() { + return 2; + } + + @Override + public String getColumnName(int column) { + switch (column) { + case 0: + return "name"; + case 1: + return "value"; + } + return ""; + }; + + @Override + public int getRowCount() { + EffectConfig effect = (EffectConfig) mEffectModel.getSelectedItem(); + if (effect == null) { + return 0; + } + return effect.mArgs.size() + 1; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + EffectConfig effect = (EffectConfig) mEffectModel.getSelectedItem(); + if (effect == null) { + return ""; + } + if (rowIndex == effect.mArgs.size()) { + if (columnIndex == 0) { + return "[key]"; + } + return ""; + } + if (columnIndex == 0) { + return effect.mArgs.get(rowIndex).key; + } else if (columnIndex == 1){ + return effect.mArgs.get(rowIndex).value; + + } + return ""; + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + EffectConfig effect = (EffectConfig) mEffectModel.getSelectedItem(); + if (effect == null) { + return; + } + + if (rowIndex == effect.mArgs.size()) { + String key = aValue.toString().trim(); + if (key.isEmpty() || key.equals("[key]")) { + return; + } + + effect.mArgs.addElement(new EffectConfig.EffectArg(aValue.toString(), "")); + return; + } + if (columnIndex == 0) { + String key = aValue.toString().trim(); + if (key.isEmpty()) { + effect.mArgs.remove(rowIndex); + } else { + effect.mArgs.get(rowIndex).key = (String)aValue; + } + } else { + if (aValue instanceof String) { + // Get the value without any trailing or leading spaces + String str = ((String)aValue).trim(); + if (str.charAt(0) == '"' && str.charAt(str.length()-1) == '"') { + // If the string is quoted it is an actual string + String actStr = str.substring(1, str.length()-1); + if (actStr.contains("\"")) { + // String can not contain quotes + } else { + effect.mArgs.get(rowIndex).value = actStr; + } + } else { + // The string is not a string, let's find out what it is + if (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false")) { + // It is a BOOLEAN + effect.mArgs.get(rowIndex).value = str.equalsIgnoreCase("true"); + } else { + try { + int intVal = Integer.parseInt(str); + // It is an INT + effect.mArgs.get(rowIndex).value = intVal; + } catch (Throwable t1) { + // It was not an integer apparently + try { + double doubleVal = Double.parseDouble(str); + effect.mArgs.get(rowIndex).value = doubleVal; + } catch (Throwable t2) { + // It was not an double apparently .... + } + + } + } + } + + } else { + effect.mArgs.get(rowIndex).value = aValue; + } + } + }; + }; public EffectEnginePanel(final EffectEngineConfig pEffectEngineConfig) { super(); @@ -60,31 +193,77 @@ public class EffectEnginePanel extends JPanel { mEffectPanel.setEnabled(effect != null); mPythonLabel.setEnabled(effect != null); mPythonCombo.setEnabled(effect != null); - mJsonArgumentLabel.setEnabled(effect != null); - mJsonArgumentArea.setEnabled(effect != null); + mEffectArgumentTable.setEnabled(effect != null); if (effect == null) { // Clear all fields - mEffectPanel.setBorder(BorderFactory.createTitledBorder("")); mPythonCombo.setSelectedIndex(-1); - mJsonArgumentArea.setText(""); + mEffectArgumentTableModel.fireTableDataChanged(); return; } else { // Update fields based on the selected effect - mEffectPanel.setBorder(BorderFactory.createTitledBorder(effect.mId)); mPythonCombo.setSelectedItem(effect.mScript); - mJsonArgumentArea.setText(effect.mArgs); + mEffectArgumentTableModel.fireTableDataChanged(); } } private JPanel getControlPanel() { if (mControlPanel == null) { mControlPanel = new JPanel(); - mControlPanel.setPreferredSize(new Dimension(150, 35)); + mControlPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 2, 5)); + mControlPanel.setPreferredSize(new Dimension(150, 25)); mControlPanel.setLayout(new BoxLayout(mControlPanel, BoxLayout.LINE_AXIS)); mEffectCombo = new JComboBox<>(mEffectModel); + mEffectCombo.setEditable(true); + mEffectCombo.setEditor(new ComboBoxEditor() { + private final JTextField mTextField = new JTextField(); + + private EffectConfig mCurrentEffect = null; + + @Override + public void setItem(Object anObject) { + if (anObject instanceof EffectConfig) { + mCurrentEffect = (EffectConfig) anObject; + mTextField.setText(mCurrentEffect.mId); + } + } + + @Override + public void selectAll() { + if (mCurrentEffect == null) { + return; + } + mTextField.setText(mCurrentEffect.mId); + mTextField.setSelectionStart(0); + mTextField.setSelectionEnd(mCurrentEffect.mId.length()-1); + } + + @Override + public Object getItem() { + String newId = mTextField.getText().trim(); + if (newId.isEmpty() || newId.contains("\"")) { + return mCurrentEffect; + } + mCurrentEffect.mId = newId; + return mCurrentEffect; } + + @Override + public Component getEditorComponent() { + return mTextField; + } + + private final Vector mActionListeners = new Vector<>(); + @Override + public void addActionListener(ActionListener l) { + mActionListeners.add(l); + } + @Override + public void removeActionListener(ActionListener l) { + mActionListeners.remove(l); + } + }); mEffectCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -93,6 +272,19 @@ public class EffectEnginePanel extends JPanel { }); mControlPanel.add(mEffectCombo); + mCloneButton = new JButton("Clone"); + mCloneButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + EffectConfig effect = (EffectConfig) mEffectModel.getSelectedItem(); + EffectConfig effectClone = effect.clone(); + effectClone.mId += " [clone]"; + mEffectModel.addElement(effectClone); + mEffectModel.setSelectedItem(effectClone); + } + }); + mControlPanel.add(mCloneButton); + mAddButton = new JButton("Add"); mAddButton.addActionListener(new ActionListener() { @Override @@ -137,9 +329,12 @@ public class EffectEnginePanel extends JPanel { private JPanel getEffectPanel() { if (mEffectPanel == null) { mEffectPanel = new JPanel(); + mEffectPanel.setBorder(BorderFactory.createTitledBorder("")); mEffectPanel.setLayout(new BoxLayout(mEffectPanel, BoxLayout.PAGE_AXIS)); JPanel subPanel = new JPanel(new BorderLayout()); + subPanel.setPreferredSize(new Dimension(150, 25)); + subPanel.setMaximumSize(new Dimension(20000, 20)); mEffectPanel.add(subPanel); mPythonLabel = new JLabel("Python: "); @@ -149,14 +344,20 @@ public class EffectEnginePanel extends JPanel { // mPythonCombo.setEditable(true); mPythonCombo.setMaximumSize(new Dimension(150, 25)); subPanel.add(mPythonCombo); + + mEffectArgumentPanel = new JPanel(); + mEffectArgumentPanel.setBorder(BorderFactory.createTitledBorder("Arguments")); + mEffectArgumentPanel.setLayout(new BorderLayout()); - mJsonArgumentLabel = new JLabel("Arguments:"); - mEffectPanel.add(mJsonArgumentLabel); + mEffectArgumentTable = new JTable(mEffectArgumentTableModel); + mEffectArgumentPanel.add(new JScrollPane(mEffectArgumentTable)); - mJsonArgumentArea = new JTextArea(); - mJsonArgumentArea.setLineWrap(true); - mJsonArgumentArea.setWrapStyleWord(true); - mEffectPanel.add(mJsonArgumentArea); + mEffectPanel.add(mEffectArgumentPanel); + + TableColumn col = mEffectArgumentTable.getColumnModel().getColumn(1); + col.setCellEditor(new EffectArgumentCellEditor()); + + mEffectArgumentTable.setCellEditor(new EffectArgumentCellEditor()); } return mEffectPanel; } diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/EffectConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/EffectConfig.java index 19e37440..1a104101 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/EffectConfig.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/EffectConfig.java @@ -1,6 +1,6 @@ package org.hyperion.hypercon.spec; -import java.util.Locale; +import java.util.Vector; import org.hyperion.hypercon.JsonStringBuffer; @@ -15,14 +15,28 @@ public class EffectConfig { /** The python-script used to generate the effect */ public String mScript; - /** The JSON-string containing the arguments of the python-script */ - public String mArgs; + /** The arguments (key-value) of the python-script */ + public final Vector mArgs = new Vector<>(); + + static public class EffectArg { + public String key; + public Object value; + + public EffectArg() { + key = ""; + value = ""; + } + public EffectArg(String pKey, Object pValue) { + key = pKey; + value = pValue; + } + } public void append(JsonStringBuffer pJsonBuf, boolean endOfEffects) { pJsonBuf.startObject(mId); pJsonBuf.addValue("script", mScript, false); - pJsonBuf.addRawValue("args", String.format(Locale.ENGLISH, "{\n%s\n}", mArgs), true); + //pJsonBuf.addRawValue("args", String.format(Locale.ENGLISH, "{\n%s\n}", mArgs), true); pJsonBuf.stopObject(endOfEffects); } @@ -31,4 +45,17 @@ public class EffectConfig { public String toString() { return mId; } + + @Override + public EffectConfig clone() { + EffectConfig thisClone = new EffectConfig(); + thisClone.mId = mId; + thisClone.mScript = mScript; + + for (EffectArg arg : mArgs) { + thisClone.mArgs.add(new EffectArg(arg.key, arg.value)); + } + + return thisClone; + } } diff --git a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/EffectEngineConfig.java b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/EffectEngineConfig.java index 15b5fd4e..87b1ee87 100644 --- a/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/EffectEngineConfig.java +++ b/src/config-tool/ConfigTool/src/org/hyperion/hypercon/spec/EffectEngineConfig.java @@ -1,5 +1,6 @@ package org.hyperion.hypercon.spec; +import java.awt.Color; import java.util.Vector; import org.hyperion.hypercon.JsonStringBuffer; @@ -12,34 +13,22 @@ public class EffectEngineConfig { public final Vector mEffects = new Vector<>(); { - EffectConfig testSlow = new EffectConfig(); - testSlow.mId = "test-slow"; - testSlow.mScript = "test.py"; - testSlow.mArgs = "\"speed\" : 0.5"; - - EffectConfig testFast = new EffectConfig(); - testFast.mId = "test-fast"; - testFast.mScript = "test.py"; - testFast.mArgs = "\"speed\" : 2.0"; - EffectConfig rainbowSwirl = new EffectConfig(); rainbowSwirl.mId = "Rainbow swirl"; rainbowSwirl.mScript = "rainbow-swirl.py"; - rainbowSwirl.mArgs = - "\"rotation-time\" : 10.0,\n" + - "\"brightness\" : 1.0,\n" + - "\"reverse\" : false"; + rainbowSwirl.mArgs.add(new EffectConfig.EffectArg("rotation-time", 10.0)); + rainbowSwirl.mArgs.add(new EffectConfig.EffectArg("brightness", 1.0)); + rainbowSwirl.mArgs.add(new EffectConfig.EffectArg("reverse", false)); EffectConfig rainbowMood = new EffectConfig(); rainbowMood.mId = "Rainbow mood"; rainbowMood.mScript = "rainbow-mood.py"; - rainbowMood.mArgs = - "\"rotation-time\" : 10.0,\n" + - "\"brightness\" : 1.0,\n" + - "\"reverse\" : false"; + rainbowMood.mArgs.add(new EffectConfig.EffectArg("rotation-time", 10.0)); + rainbowMood.mArgs.add(new EffectConfig.EffectArg("brightness", 1.0)); + rainbowMood.mArgs.add(new EffectConfig.EffectArg("reverse", false)); + rainbowMood.mArgs.add(new EffectConfig.EffectArg("test", "test")); + rainbowMood.mArgs.add(new EffectConfig.EffectArg("AColor", Color.RED)); - mEffects.add(testSlow); - mEffects.add(testFast); mEffects.add(rainbowSwirl); mEffects.add(rainbowMood); }