Big update to custom expression feature.
[debian/openrocket] / core / src / net / sf / openrocket / gui / customexpression / CustomExpressionPanel.java
1 package net.sf.openrocket.gui.customexpression;
2
3 import java.awt.Color;
4 import java.awt.Window;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.io.File;
8 import java.util.ArrayList;
9 import java.util.Collections;
10
11 import javax.swing.BorderFactory;
12 import javax.swing.JButton;
13 import javax.swing.JDialog;
14 import javax.swing.JFileChooser;
15 import javax.swing.JLabel;
16 import javax.swing.JPanel;
17 import javax.swing.JScrollPane;
18 import javax.swing.SwingUtilities;
19 import javax.swing.border.Border;
20 import javax.swing.filechooser.FileFilter;
21 import javax.swing.filechooser.FileNameExtensionFilter;
22
23 import net.miginfocom.swing.MigLayout;
24 import net.sf.openrocket.document.OpenRocketDocument;
25 import net.sf.openrocket.file.DatabaseMotorFinder;
26 import net.sf.openrocket.file.GeneralRocketLoader;
27 import net.sf.openrocket.file.MotorFinder;
28 import net.sf.openrocket.file.RocketLoadException;
29 import net.sf.openrocket.document.Simulation;
30 import net.sf.openrocket.gui.components.DescriptionArea;
31 import net.sf.openrocket.gui.components.UnitSelector;
32 import net.sf.openrocket.gui.customexpression.ExpressionBuilderDialog;
33 import net.sf.openrocket.gui.util.Icons;
34 import net.sf.openrocket.l10n.Translator;
35 import net.sf.openrocket.logging.LogHelper;
36 import net.sf.openrocket.rocketcomponent.Rocket;
37 import net.sf.openrocket.simulation.customexpression.CustomExpression;
38 import net.sf.openrocket.startup.Application;
39
40 public class CustomExpressionPanel extends JPanel {
41         
42         private static final LogHelper log = Application.getLogger();
43         private static final Translator trans = Application.getTranslator();
44         
45         private JPanel expressionSelectorPanel;
46         private OpenRocketDocument doc;
47         
48         public CustomExpressionPanel(final OpenRocketDocument doc, final JDialog parentDialog) {
49                 super(new MigLayout("fill"));
50                 this.doc = doc;
51
52                 expressionSelectorPanel = new JPanel(new MigLayout("gapy rel"));
53                 expressionSelectorPanel.setToolTipText(trans.get("customExpressionPanel.lbl.CalcNote"));
54                 
55                 JScrollPane scroll = new JScrollPane();
56                 Border bdr = BorderFactory.createTitledBorder(trans.get("customExpressionPanel.lbl.CustomExpressions"));
57
58                 expressionSelectorPanel.setBorder(bdr);
59                 expressionSelectorPanel.add(scroll);
60                 
61                 //this.add(expressionSelectorPanel, "spany 1, height 10px, wmin 600lp, grow 100, gapright para");
62                 this.add(expressionSelectorPanel, "hmin 200lp, wmin 700lp, grow 100, wrap");
63                 
64                 //DescriptionArea desc = new DescriptionArea(trans.get("customExpressionPanel.lbl.UpdateNote")+"\n\n"+trans.get("customExpressionPanel.lbl.CalcNote"), 8, -2f);
65                 //desc.setViewportBorder(BorderFactory.createEmptyBorder());
66                 //this.add(desc, "width 1px, growx 1, wrap unrel, wrap");
67                 
68                 //// New expression
69                 JButton button = new JButton(trans.get("customExpressionPanel.but.NewExpression"));
70                 button.setToolTipText(trans.get("customExpressionPanel.but.ttip.NewExpression"));
71                 button.addActionListener(new ActionListener() {
72                         @Override
73                         public void actionPerformed(ActionEvent e) {
74                                 // Open window to configure expression
75                                 log.info("Opening window to configure new expression");
76                                 Window parent = SwingUtilities.getWindowAncestor(CustomExpressionPanel.this);
77                                 new ExpressionBuilderDialog(parent, doc).setVisible(true);
78                                 updateExpressions();
79                         }
80                 });
81                 this.add(button, "split 4, width :100:200");
82                 
83                 //// Import
84                 final JButton importButton = new JButton(trans.get("customExpressionPanel.but.Import"));
85                 importButton.setToolTipText(trans.get("customExpressionPanel.but.ttip.Import"));
86                 importButton.addActionListener(new ActionListener() {
87                         @Override
88                         public void actionPerformed(ActionEvent e) {
89                                 
90                                 //Create a file chooser
91                                 final JFileChooser fc = new JFileChooser();
92                                 if (doc.getFile() != null){
93                                         fc.setCurrentDirectory(doc.getFile().getParentFile());
94                                 }
95                                 fc.setFileFilter(new FileNameExtensionFilter("Openrocket file", "ork"));
96                                 fc.setAcceptAllFileFilterUsed(false);
97                                 
98                                 int returnVal = fc.showOpenDialog(CustomExpressionPanel.this);
99                                 if (returnVal == JFileChooser.APPROVE_OPTION){
100                                         File importFile = fc.getSelectedFile();
101                                         log.info("User selected a file to import expressions from "+fc.getSelectedFile().toString());
102                                         
103                                         //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.
104                                         
105                                         // Load expressions from selected document
106                                         GeneralRocketLoader loader = new GeneralRocketLoader();
107                                         try {
108                                                 OpenRocketDocument importedDocument = loader.load(importFile, new DatabaseMotorFinder());
109                                                 for (CustomExpression exp : importedDocument.getCustomExpressions()){
110                                                         doc.addCustomExpression(exp);
111                                                 }
112                                         } catch (RocketLoadException e1) {
113                                                 log.user("Error opening document to import expressions from.");
114                                         }
115                                         updateExpressions();
116                                 }
117                         }
118                 });
119                 this.add(importButton, "width :100:200");
120                 
121                 //// Close button
122                 final JButton closeButton = new JButton(trans.get("dlg.but.close"));
123                 closeButton.addActionListener(new ActionListener() {
124                         @Override
125                         public void actionPerformed(ActionEvent e) {
126                                 parentDialog.dispose();
127                         }
128                 });
129                 this.add(new JPanel(), "growx");
130                 this.add(closeButton, "width :100:200");
131                 
132                 updateExpressions();
133         }
134         
135         /*
136          * Update the expressionSelectorPanel
137          */
138         private void updateExpressions(){
139                 
140                 expressionSelectorPanel.removeAll();
141                 int totalExpressions = doc.getCustomExpressions().size();
142                 for (int i=0; i<totalExpressions; i++){
143                         SingleExpression se = new SingleExpression(doc.getCustomExpressions().get(i), i != 0, i != totalExpressions-1);
144                         expressionSelectorPanel.add(se, "wrap");
145                 }
146
147                 expressionSelectorPanel.revalidate();
148                 expressionSelectorPanel.repaint();
149         }
150         
151         private void deleteExpression(CustomExpression expression){
152                 doc.getCustomExpressions().remove(expression);
153         }
154         
155         /**
156          * Moves an expression up or down in the expression list
157          * @param expression
158          * @param move integer - +1 to move down, -1 to move up
159          */
160         private void moveExpression(CustomExpression expression, int move){
161                 ArrayList<CustomExpression> expressions = doc.getCustomExpressions();
162                 int i = expressions.indexOf(expression);
163                 if (i+move == expressions.size() || i+move < 0)
164                         return;
165                 else
166                         Collections.swap(expressions, i, i+move);
167         }
168
169         
170         /*
171          * A JPanel which configures a single expression
172          */
173         private class SingleExpression extends JPanel {
174                 
175                 // Convenience method to make the labels consistent
176                 private JLabel setLabelStyle(JLabel l){
177                         l.setBackground(Color.WHITE);
178                         l.setOpaque(true);
179                         l.setBorder(BorderFactory.createRaisedBevelBorder() );
180                         l.setText(" " + l.getText() + " ");
181                         return l;
182                 }
183                 
184                 private SingleExpression(final CustomExpression expression, boolean showUp, boolean showDown) {
185                         super(new MigLayout("ins 0"));
186                         //                      name:    aName    symbol:  a      Unit:  m/s
187                         //super(new MigLayout("","[::100][:200:400][::100][:100:200][::100][:100:200]",""));
188                         
189                         JLabel nameLabel = new JLabel( trans.get("customExpression.Name")+ " :");
190                         JLabel name = new JLabel ( expression.getName() );
191                         name = setLabelStyle(name);
192                         JLabel symbolLabel = new JLabel( trans.get("customExpression.Symbol")+ " :" );
193                         JLabel symbol = new JLabel ( expression.getSymbol());
194                         symbol = setLabelStyle(symbol);
195                         symbol.setBackground(Color.WHITE);
196                         
197                         JLabel unitLabel = new JLabel( trans.get("customExpression.Units")+ " :");
198                         UnitSelector unitSelector = new UnitSelector(expression.getType().getUnitGroup());
199                         //JLabel unitSelector = new JLabel ( expression.getUnit() );
200                         //unitSelector = setLabelStyle(unitSelector);
201                         //unitSelector.setBackground(Color.WHITE);
202                         
203                         JButton editButton = new JButton(Icons.EDIT);
204                         editButton.setToolTipText(trans.get("customExpression.Units.but.ttip.Edit"));
205                         editButton.setBorderPainted(false);
206                         editButton.addActionListener( new ActionListener() {
207                                 @Override
208                                 public void actionPerformed(ActionEvent e){
209                                         Window parent = SwingUtilities.getWindowAncestor(CustomExpressionPanel.this);
210                                         new ExpressionBuilderDialog(parent, doc, expression).setVisible(true);
211                                         updateExpressions();
212                                 }
213                         });
214                         
215                         JButton upButton = new JButton(Icons.UP);
216                         upButton.setToolTipText(trans.get("customExpression.Units.but.ttip.MoveUp"));
217                         upButton.setBorderPainted(false);
218                         upButton.setVisible(showUp);
219                         upButton.addActionListener( new ActionListener() {
220                                 @Override
221                                 public void actionPerformed(ActionEvent e) {
222                                         moveExpression(expression, -1);
223                                         updateExpressions();
224                                 }
225                         });
226                         
227                         JButton downButton = new JButton(Icons.DOWN);
228                         downButton.setToolTipText(trans.get("customExpression.Units.but.ttip.MoveDown"));
229                         downButton.setBorderPainted(false);
230                         downButton.setVisible(showDown);
231                         downButton.addActionListener( new ActionListener() {
232                                 @Override
233                                 public void actionPerformed(ActionEvent e) {
234                                         moveExpression(expression, 1);
235                                         updateExpressions();
236                                 }
237                         });
238                         
239                         
240                         JButton deleteButton = new JButton(Icons.DELETE);
241                         //// Remove this expression
242                         deleteButton.setToolTipText(trans.get("customExpression.Units.but.ttip.Remove"));
243                         deleteButton.setBorderPainted(false);
244                         deleteButton.addActionListener(new ActionListener() {
245                                 @Override
246                                 public void actionPerformed(ActionEvent e) {
247                                         deleteExpression(expression);
248                                         updateExpressions();
249                                 }
250                         });
251                         
252                         this.add(nameLabel);
253                         this.add(name, "width 200:200:400, growx");
254                         this.add(new JPanel());
255                         this.add(symbolLabel);
256                         this.add(symbol, "width :50:200");
257                         this.add(new JPanel());
258                         this.add(unitLabel);
259                         this.add(unitSelector, "width :50:100");
260                         this.add(new JPanel(), "growx");
261                         this.add(upButton, "right");
262                         this.add(downButton, "right");
263                         this.add(editButton, "right");
264                         this.add(deleteButton, "right");
265                 }
266         }
267 }