001    /******************************************************************************
002     * Copyright (C) MActor Developers. All rights reserved.                        *
003     * ---------------------------------------------------------------------------*
004     * This file is part of MActor.                                               *
005     *                                                                            *
006     * MActor is free software; you can redistribute it and/or modify             *
007     * it under the terms of the GNU General Public License as published by       *
008     * the Free Software Foundation; either version 2 of the License, or          *
009     * (at your option) any later version.                                        *
010     *                                                                            *
011     * MActor is distributed in the hope that it will be useful,                  *
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
014     * GNU General Public License for more details.                               *
015     *                                                                            *
016     * You should have received a copy of the GNU General Public License          *
017     * along with MActor; if not, write to the Free Software                      *
018     * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA *
019     ******************************************************************************/
020    package org.mactor.ui.gui.project.editors;
021    
022    import java.awt.event.ActionEvent;
023    import java.awt.event.ActionListener;
024    import java.awt.event.ItemListener;
025    import java.io.File;
026    import java.io.IOException;
027    import java.util.Collections;
028    import java.util.Iterator;
029    import java.util.LinkedList;
030    import java.util.List;
031    
032    import javax.swing.AbstractAction;
033    import javax.swing.JButton;
034    import javax.swing.JFileChooser;
035    import javax.swing.JLabel;
036    import javax.swing.JOptionPane;
037    import javax.swing.JTextField;
038    import javax.swing.filechooser.FileFilter;
039    
040    import org.dom4j.Element;
041    import org.mactor.framework.MactorException;
042    import org.mactor.framework.spec.ProjectContext;
043    import org.mactor.ui.gui.GuiUtil;
044    import org.mactor.ui.gui.project.editors.CommandPrototypeComboBox.ProtoListener;
045    
046    public class CommandEditor extends SimpleFormPanel {
047            CommandPrototypeComboBox protoCb = new CommandPrototypeComboBox();
048            CommandTypeComboBox typeCb = new CommandTypeComboBox();
049            GlobalConfigDBGroupComboBox gcDbGroup = new GlobalConfigDBGroupComboBox();
050            ParamsPanel parameterPanel = new ParamsPanel();
051            Element data;
052            String commandAttributeName;
053            SimpleRowPanel dbPanel = new SimpleRowPanel();
054            BshPanel bshPanel = new BshPanel();
055            JButton test = new JButton(new AbstractAction("Test...") {
056                    public void actionPerformed(ActionEvent e) {
057                            try {
058                                    applyListener.onApply();
059                                    new CommandTestDlg(JOptionPane.getFrameForComponent(CommandEditor.this), data).setVisible(true);
060                            } catch (MactorException me) {
061                                    GuiUtil.showGuiError(CommandEditor.this, me);
062                            }
063                    }
064            });
065            ItemListener typeCbListener = new ItemListener() {
066                    public void itemStateChanged(java.awt.event.ItemEvent e) {
067                            NodeEditorConfig.CommandType type = (NodeEditorConfig.CommandType) typeCb.getSelectedItem();
068                            String proto = protoCb.getSelectedPrototype();
069                            if (type != null) {
070                                    protoCb.setConfig(type.getPrototypes());
071                                    boolean showDbPanel = "sql".equalsIgnoreCase(type.getName());
072                                    dbPanel.setVisible(showDbPanel);
073                                    if (showDbPanel)
074                                            gcDbGroup.load();
075                                    parameterPanel.setVisible(type.isAcceptParameters());
076                                    bshPanel.setVisible("bsh".equalsIgnoreCase(type.getName()));
077                            } else {
078                                    protoCb.setConfig(null);
079                                    dbPanel.setVisible(false);
080                                    bshPanel.setVisible(false);
081                            }
082                            protoCb.setSelectedPrototype(proto);
083                    };
084            };
085            ProtoListener pl = new ProtoListener() {
086                    public void protoSelected(org.mactor.ui.gui.project.editors.NodeEditorConfig.CommandPrototype proto) {
087                            parameterPanel.setExampleParamters(proto == null ? null : proto.getParams());
088                    };
089            };
090            public void setTipListener(TipListener tipListener) {
091                    protoCb.setTipListener(tipListener);
092                    typeCb.setTipListener(tipListener);
093            }
094            ApplyListener applyListener;
095            public CommandEditor(String commandCaption, ApplyListener applyListener) {
096                    this.commandAttributeName = "command";
097                    this.applyListener = applyListener;
098                    add(new JLabel(commandCaption));
099                    SimpleRowPanel panel = new SimpleRowPanel();
100                    panel.add(typeCb);
101                    dbPanel.add(new JLabel(":"));
102                    dbPanel.add(gcDbGroup);
103                    panel.add(dbPanel);
104                    panel.add(new JLabel(":"));
105                    panel.add(protoCb);
106                    panel.add(bshPanel);
107                    panel.add(test);
108                    add(panel);
109                    add(parameterPanel);
110                    typeCb.addItemListener(typeCbListener);
111                    protoCb.setProtoListener(pl);
112            }
113            public void applyChanges() {
114                    if (data.attribute(commandAttributeName) == null)
115                            data.addAttribute(commandAttributeName, "");
116                    if (dbPanel.isVisible())
117                            data.attribute(commandAttributeName).setValue(typeCb.getSelectedType() + ":" + gcDbGroup.getSelectedGroup() + ":" + protoCb.getSelectedPrototype());
118                    else
119                            data.attribute(commandAttributeName).setValue(typeCb.getSelectedType() + ":" + protoCb.getSelectedPrototype());
120                    parameterPanel.applyChanges();
121            }
122            public void setData(Object data) throws MactorException {
123                    this.data = (Element) data;
124                    parameterPanel.setData(data);
125                    String command = this.data.attributeValue(commandAttributeName);
126                    String[] parts = null;
127                    if (command != null)
128                            parts = command.split(":");
129                    String type = null;
130                    String group = null;
131                    String proto = null;
132                    if (parts != null) {
133                            if (parts.length >= 1)
134                                    type = parts[0];
135                            if (parts.length > 2) {
136                                    proto = parts[2];
137                                    group = parts[1];
138                            } else if (parts.length == 2)
139                                    proto = parts[1];
140                    }
141                    typeCb.setSelectedType(type);
142                    gcDbGroup.setSelectedGroup(group);
143                    protoCb.setSelectedPrototype(proto);
144                    if (!"sql".equalsIgnoreCase(type))
145                            dbPanel.setVisible(false);
146            }
147            public void setConfig(NodeEditorConfig config) {
148                    typeCb.setConfig(config.getCommandTypes());
149            }
150            private class ParamsPanel extends SimpleFormPanel {
151                    List<RowPanel> rows = new LinkedList<RowPanel>();
152                    JButton addRowButton = new JButton("Add Parameter");
153                    JButton exampleParametersButton = new JButton("Load Example Parameters");
154                    Element rowsParentElement;
155                    public ParamsPanel() {
156                            add(new JLabel("Parameters:"));
157                            addRowButton.addActionListener(new ActionListener() {
158                                    public void actionPerformed(ActionEvent arg0) {
159                                            applyChanges();
160                                            rowsParentElement.addElement("param");
161                                            setData(rowsParentElement);
162                                            applyListener.onApply();
163                                    }
164                            });
165                            exampleParametersButton.addActionListener(new ActionListener() {
166                                    public void actionPerformed(ActionEvent arg0) {
167                                            loadExampleParameters();
168                                    }
169                            });
170                    }
171                    public void applyChanges() {
172                            for (RowPanel row : rows)
173                                    row.applyChanges();
174                    }
175                    public void removeRow(RowPanel row) {
176                            remove(row);
177                            rows.remove(row);
178                            rowsParentElement.remove(row.rowElement);
179                            applyChanges();
180                            revalidate();
181                            repaint();
182                    }
183                    public void setConfig(NodeEditorConfig config) {
184                    }
185                    public void setData(Object data) {
186                            rowsParentElement = (Element) data;
187                            rows.clear();
188                            removeAll();
189                            add(new JLabel("Command Parameters:"));
190                            Iterator it = rowsParentElement.elementIterator();
191                            while (it.hasNext()) {
192                                    RowPanel panel = new RowPanel((Element) it.next());
193                                    rows.add(panel);
194                                    add(panel);
195                            }
196                            add(addRowButton);
197                            add(exampleParametersButton);
198                            revalidate();
199                            repaint();
200                    }
201                    List<String> examleParameters;
202                    public void setExampleParamters(List<String> examleParameters) {
203                            this.examleParameters = examleParameters;
204                            // exampleParametersButton.setEnabled(examleParameters!=null &&
205                            // examleParameters.size()>0);
206                    }
207                    private void loadExampleParameters() {
208                            if (examleParameters == null)
209                                    examleParameters = Collections.emptyList();
210                            if (rowsParentElement != null) {
211                                    Iterator<Element> it = rowsParentElement.elementIterator("param");
212                                    while (it.hasNext()) {
213                                            it.next().detach();
214                                    }
215                                    for (String p : examleParameters) {
216                                            rowsParentElement.addElement("param").setText(p);
217                                    }
218                                    setData(rowsParentElement);
219                                    applyChanges();
220                            }
221                    }
222                    private class RowPanel extends SimpleRowPanel {
223                            JTextField valueField = new JTextField(20);
224                            JButton removeButton = new JButton("X");
225                            Element rowElement;
226                            public RowPanel(Element rowElement) {
227                                    add(valueField);
228                                    add(removeButton);
229                                    this.rowElement = rowElement;
230                                    valueField.setText(rowElement.getText());
231                                    removeButton.addActionListener(new ActionListener() {
232                                            public void actionPerformed(ActionEvent e) {
233                                                    ParamsPanel.this.removeRow(RowPanel.this);
234                                            }
235                                    });
236                            }
237                            public void applyChanges() {
238                                    rowElement.setText(valueField.getText());
239                            }
240                    }
241            }
242            private class BshPanel extends SimpleRowPanel {
243                    JButton bshEdit = new JButton(new AbstractAction("Edit...") {
244                            public void actionPerformed(ActionEvent e) {
245                                    applyListener.onApply();
246                                    String name = protoCb.getSelectedPrototype();
247                                    if (name != null && name.length() > 0) {
248                                            File path = ProjectContext.getGlobalInstance().getAbsolutePath(name);
249                                            if (!path.exists()) {
250                                                    if (JOptionPane.OK_OPTION != JOptionPane
251                                                                    .showConfirmDialog(BshPanel.this, "The script '" + name + "' does not exist. Create it?", "Create script", JOptionPane.OK_CANCEL_OPTION)) {
252                                                            return;
253                                                    }
254                                            }
255                                            new TextFileEditor(
256                                                            name,
257                                                            "Edit BeanShell Script",
258                                                            "Tip: BeanShell is an object scripting language for Java. Read more at: http://www.beanshell.org\n\n Note that the TestContext (containing the local variables and the received messages etc.) is made available as a variable named 'context'")
259                                                            .setVisible(true);
260                                    }
261                            }
262                    });
263                    JFileChooser fc = new JFileChooser(ProjectContext.getGlobalInstance().getProjectDir());
264                    JButton selectButton = new JButton(new AbstractAction("Select..") {
265                            public void actionPerformed(ActionEvent e) {
266                                    applyListener.onApply();
267                                    try {
268                                            if (protoCb.getSelectedPrototype() != null && protoCb.getSelectedPrototype().toLowerCase().endsWith(".bsh"))
269                                                    fc.setSelectedFile(ProjectContext.getGlobalInstance().getAbsolutePath(protoCb.getSelectedPrototype()));
270                                            fc.setFileFilter(new FileFilter() {
271                                                    @Override
272                                                    public String getDescription() {
273                                                            return "*.bsh";
274                                                    }
275                                                    public boolean accept(File f) {
276                                                            return !f.isDirectory() && f.getName().endsWith(".bsh");
277                                                    }
278                                            });
279                                            int returnVal = fc.showOpenDialog(CommandEditor.this);
280                                            if (returnVal == JFileChooser.APPROVE_OPTION) {
281                                                    File f = fc.getSelectedFile();
282                                                    if (!f.getName().toLowerCase().endsWith(".bsh"))
283                                                            f = new File(f.getAbsolutePath() + ".bsh");
284                                                    f.createNewFile();
285                                                    protoCb.setSelectedPrototype(ProjectContext.getGlobalInstance().getRelativePath(f));
286                                            }
287                                    } catch (IOException ioe) {
288                                            GuiUtil.showGuiError(CommandEditor.this, ioe);
289                                    }
290                            }
291                    });
292                    public BshPanel() {
293                            add(selectButton);
294                            add(bshEdit);
295                    }
296            }
297    }