package net.sf.openrocket.gui.customexpression; import java.awt.Color; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.util.Collections; import java.util.List; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileNameExtensionFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.miginfocom.swing.MigLayout; import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.file.GeneralRocketLoader; import net.sf.openrocket.file.RocketLoadException; import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.util.Icons; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.logging.Markers; import net.sf.openrocket.simulation.customexpression.CustomExpression; import net.sf.openrocket.startup.Application; public class CustomExpressionPanel extends JPanel { private static final Logger log = LoggerFactory.getLogger(CustomExpressionPanel.class); private static final Translator trans = Application.getTranslator(); private JPanel expressionSelectorPanel; private OpenRocketDocument doc; public CustomExpressionPanel(final OpenRocketDocument doc, final JDialog parentDialog) { super(new MigLayout("fill")); this.doc = doc; expressionSelectorPanel = new JPanel(new MigLayout("gapy rel")); expressionSelectorPanel.setToolTipText(trans.get("customExpressionPanel.lbl.CalcNote")); JScrollPane scroll = new JScrollPane(expressionSelectorPanel); //Border bdr = BorderFactory.createTitledBorder(trans.get("customExpressionPanel.lbl.CustomExpressions")); //scroll.setBorder(bdr); //expressionSelectorPanel.add(scroll); //this.add(expressionSelectorPanel, "spany 1, height 10px, wmin 600lp, grow 100, gapright para"); this.add(scroll, "hmin 200lp, wmin 700lp, grow 100, wrap"); //DescriptionArea desc = new DescriptionArea(trans.get("customExpressionPanel.lbl.UpdateNote")+"\n\n"+trans.get("customExpressionPanel.lbl.CalcNote"), 8, -2f); //desc.setViewportBorder(BorderFactory.createEmptyBorder()); //this.add(desc, "width 1px, growx 1, wrap unrel, wrap"); //// New expression JButton button = new JButton(trans.get("customExpressionPanel.but.NewExpression")); button.setToolTipText(trans.get("customExpressionPanel.but.ttip.NewExpression")); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // Open window to configure expression log.info("Opening window to configure new expression"); Window parent = SwingUtilities.getWindowAncestor(CustomExpressionPanel.this); new ExpressionBuilderDialog(parent, doc).setVisible(true); updateExpressions(); } }); this.add(button, "split 4, width :100:200"); //// Import final JButton importButton = new JButton(trans.get("customExpressionPanel.but.Import")); importButton.setToolTipText(trans.get("customExpressionPanel.but.ttip.Import")); importButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { //Create a file chooser final JFileChooser fc = new JFileChooser(); if (doc.getFile() != null) { fc.setCurrentDirectory(doc.getFile().getParentFile()); } fc.setFileFilter(new FileNameExtensionFilter("Openrocket file", "ork")); fc.setAcceptAllFileFilterUsed(false); int returnVal = fc.showOpenDialog(CustomExpressionPanel.this); if (returnVal == JFileChooser.APPROVE_OPTION) { File importFile = fc.getSelectedFile(); log.info("User selected a file to import expressions from " + fc.getSelectedFile().toString()); //TODO: This should probably be somewhere else and ideally we would use an alternative minimal rocket loader. Still, it doesn't seem particularly slow this way. // Load expressions from selected document GeneralRocketLoader loader = new GeneralRocketLoader(importFile); try { OpenRocketDocument importedDocument = loader.load(); for (CustomExpression exp : importedDocument.getCustomExpressions()) { doc.addCustomExpression(exp); } } catch (RocketLoadException e1) { log.info(Markers.USER_MARKER, "Error opening document to import expressions from."); } updateExpressions(); } } }); this.add(importButton, "width :100:200"); //// Close button final JButton closeButton = new JButton(trans.get("dlg.but.close")); closeButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { parentDialog.dispose(); } }); this.add(new JPanel(), "growx"); this.add(closeButton, "width :100:200"); updateExpressions(); } /* * Update the expressionSelectorPanel */ private void updateExpressions() { expressionSelectorPanel.removeAll(); int totalExpressions = doc.getCustomExpressions().size(); for (int i = 0; i < totalExpressions; i++) { SingleExpression se = new SingleExpression(doc.getCustomExpressions().get(i), i != 0, i != totalExpressions - 1); expressionSelectorPanel.add(se, "wrap"); } expressionSelectorPanel.revalidate(); expressionSelectorPanel.repaint(); } private void deleteExpression(CustomExpression expression) { doc.getCustomExpressions().remove(expression); } /** * Moves an expression up or down in the expression list * @param expression * @param move integer - +1 to move down, -1 to move up */ private void moveExpression(CustomExpression expression, int move) { List<CustomExpression> expressions = doc.getCustomExpressions(); int i = expressions.indexOf(expression); if (i + move == expressions.size() || i + move < 0) return; else Collections.swap(expressions, i, i + move); } /* * A JPanel which configures a single expression */ private class SingleExpression extends JPanel { // Convenience method to make the labels consistent private JLabel setLabelStyle(JLabel l) { l.setBackground(Color.WHITE); l.setOpaque(true); l.setBorder(BorderFactory.createRaisedBevelBorder()); l.setText(" " + l.getText() + " "); return l; } private SingleExpression(final CustomExpression expression, boolean showUp, boolean showDown) { super(new MigLayout("ins 0")); // name: aName symbol: a Unit: m/s //super(new MigLayout("","[::100][:200:400][::100][:100:200][::100][:100:200]","")); JLabel nameLabel = new JLabel(trans.get("customExpression.Name") + " :"); JLabel name = new JLabel(expression.getName()); name = setLabelStyle(name); JLabel symbolLabel = new JLabel(trans.get("customExpression.Symbol") + " :"); JLabel symbol = new JLabel(expression.getSymbol()); symbol = setLabelStyle(symbol); symbol.setBackground(Color.WHITE); JLabel unitLabel = new JLabel(trans.get("customExpression.Units") + " :"); UnitSelector unitSelector = new UnitSelector(expression.getType().getUnitGroup()); //JLabel unitSelector = new JLabel ( expression.getUnit() ); //unitSelector = setLabelStyle(unitSelector); //unitSelector.setBackground(Color.WHITE); JButton editButton = new JButton(Icons.EDIT); editButton.setToolTipText(trans.get("customExpression.Units.but.ttip.Edit")); editButton.setBorderPainted(false); editButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Window parent = SwingUtilities.getWindowAncestor(CustomExpressionPanel.this); new ExpressionBuilderDialog(parent, doc, expression).setVisible(true); updateExpressions(); } }); JButton upButton = new JButton(Icons.UP); upButton.setToolTipText(trans.get("customExpression.Units.but.ttip.MoveUp")); upButton.setBorderPainted(false); upButton.setVisible(showUp); upButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { moveExpression(expression, -1); updateExpressions(); } }); JButton downButton = new JButton(Icons.DOWN); downButton.setToolTipText(trans.get("customExpression.Units.but.ttip.MoveDown")); downButton.setBorderPainted(false); downButton.setVisible(showDown); downButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { moveExpression(expression, 1); updateExpressions(); } }); JButton deleteButton = new JButton(Icons.DELETE); //// Remove this expression deleteButton.setToolTipText(trans.get("customExpression.Units.but.ttip.Remove")); deleteButton.setBorderPainted(false); deleteButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { deleteExpression(expression); updateExpressions(); } }); this.add(nameLabel); this.add(name, "width 200:200:400, growx"); this.add(new JPanel()); this.add(symbolLabel); this.add(symbol, "width :50:200"); this.add(new JPanel()); this.add(unitLabel); this.add(unitSelector, "width :50:100"); this.add(new JPanel(), "growx"); this.add(upButton, "right"); this.add(downButton, "right"); this.add(editButton, "right"); this.add(deleteButton, "right"); } } }