create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / gui / dialogs / optimization / SimulationModifierTree.java
1 package net.sf.openrocket.gui.dialogs.optimization;
2
3 import java.awt.Color;
4 import java.awt.Component;
5 import java.awt.Font;
6 import java.util.Enumeration;
7 import java.util.List;
8 import java.util.Map;
9
10 import javax.swing.JTree;
11 import javax.swing.ToolTipManager;
12 import javax.swing.tree.DefaultMutableTreeNode;
13 import javax.swing.tree.DefaultTreeCellRenderer;
14 import javax.swing.tree.DefaultTreeModel;
15 import javax.swing.tree.TreePath;
16
17 import net.sf.openrocket.gui.components.BasicTree;
18 import net.sf.openrocket.gui.main.ComponentIcons;
19 import net.sf.openrocket.l10n.Translator;
20 import net.sf.openrocket.optimization.rocketoptimization.SimulationModifier;
21 import net.sf.openrocket.rocketcomponent.Rocket;
22 import net.sf.openrocket.rocketcomponent.RocketComponent;
23 import net.sf.openrocket.startup.Application;
24 import net.sf.openrocket.util.TextUtil;
25
26 /**
27  * A tree that displays the simulation modifiers in a tree structure.
28  * <p>
29  * All nodes in the model are instances of DefaultMutableTreeNode.  The user objects
30  * within are either of type RocketComponent, String or SimulationModifier.
31  * 
32  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
33  */
34 public class SimulationModifierTree extends BasicTree {
35         
36         private final List<SimulationModifier> selectedModifiers;
37         private static final Translator trans = Application.getTranslator();
38         
39         /**
40          * Sole constructor.
41          * 
42          * @param rocket                                the rocket.
43          * @param simulationModifiers   the simulation modifiers, ordered and mapped by components
44          * @param selectedModifiers             a list of the currently selected modifiers (may be modified).
45          */
46         public SimulationModifierTree(Rocket rocket, Map<Object, List<SimulationModifier>> simulationModifiers,
47                         List<SimulationModifier> selectedModifiers) {
48                 this.selectedModifiers = selectedModifiers;
49                 
50                 populateTree(rocket, simulationModifiers);
51                 this.setCellRenderer(new ComponentModifierTreeRenderer());
52                 
53                 // Enable tooltips for this component
54                 ToolTipManager.sharedInstance().registerComponent(this);
55                 
56                 expandComponents();
57         }
58         
59         
60         /**
61          * Populate the simulation modifier tree from the provided information.  This can be used to update
62          * the tree.
63          */
64         public void populateTree(Rocket rocket, Map<Object, List<SimulationModifier>> simulationModifiers) {
65                 
66                 DefaultMutableTreeNode baseNode = new DefaultMutableTreeNode(rocket);
67                 populateTree(baseNode, rocket, simulationModifiers);
68                 
69                 this.setModel(new DefaultTreeModel(baseNode));
70         }
71         
72         
73         private static void populateTree(DefaultMutableTreeNode node, RocketComponent component,
74                         Map<Object, List<SimulationModifier>> simulationModifiers) {
75                 
76                 // Add modifiers (if any)
77                 List<SimulationModifier> modifiers = simulationModifiers.get(component);
78                 if (modifiers != null) {
79                         DefaultMutableTreeNode modifierNode;
80                         
81                         if (component.getChildCount() > 0) {
82                                 modifierNode = new DefaultMutableTreeNode(trans.get("SimulationModifierTree.OptimizationParameters"));
83                                 node.add(modifierNode);
84                         } else {
85                                 modifierNode = node;
86                         }
87                         
88                         for (SimulationModifier m : modifiers) {
89                                 modifierNode.add(new DefaultMutableTreeNode(m));
90                         }
91                 }
92                 
93                 // Add child components
94                 for (RocketComponent c : component.getChildren()) {
95                         DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(c);
96                         node.add(newNode);
97                         populateTree(newNode, c, simulationModifiers);
98                 }
99                 
100         }
101         
102         
103         /**
104          * Expand the rocket components, but not the modifiers.
105          */
106         @SuppressWarnings("rawtypes")
107         public void expandComponents() {
108                 DefaultMutableTreeNode baseNode = (DefaultMutableTreeNode) this.getModel().getRoot();
109                 
110                 Enumeration enumeration = baseNode.breadthFirstEnumeration();
111                 
112                 while (enumeration.hasMoreElements()) {
113                         DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement();
114                         Object object = node.getUserObject();
115                         if (object instanceof RocketComponent) {
116                                 this.makeVisible(new TreePath(node.getPath()));
117                         }
118                 }
119         }
120         
121         
122
123
124         public class ComponentModifierTreeRenderer extends DefaultTreeCellRenderer {
125                 private Font componentFont;
126                 private Font stringFont;
127                 private Font modifierFont;
128                 
129                 @Override
130                 public Component getTreeCellRendererComponent(
131                                 JTree tree,
132                                 Object value,
133                                 boolean sel,
134                                 boolean expanded,
135                                 boolean leaf,
136                                 int row,
137                                 boolean hasFocus2) {
138                         
139                         super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus2);
140                         
141                         if (componentFont == null) {
142                                 makeFonts();
143                         }
144                         
145
146                         // Customize based on line type
147                         
148                         Object object = ((DefaultMutableTreeNode) value).getUserObject();
149                         
150                         // Set icon (for rocket components, null for others)
151                         setIcon(ComponentIcons.getSmallIcon(object.getClass()));
152                         
153
154                         // Set text color/style
155                         if (object instanceof RocketComponent) {
156                                 setForeground(Color.GRAY);
157                                 setFont(componentFont);
158                                 
159                                 // Set tooltip
160                                 RocketComponent c = (RocketComponent) object;
161                                 String comment = c.getComment().trim();
162                                 if (comment.length() > 0) {
163                                         comment = TextUtil.htmlEncode(comment);
164                                         comment = "<html>" + comment.replace("\n", "<br>");
165                                         this.setToolTipText(comment);
166                                 } else {
167                                         this.setToolTipText(null);
168                                 }
169                         } else if (object instanceof String) {
170                                 setForeground(Color.GRAY);
171                                 setFont(stringFont);
172                         } else if (object instanceof SimulationModifier) {
173                                 
174                                 if (selectedModifiers.contains(object)) {
175                                         setForeground(Color.GRAY);
176                                 } else {
177                                         setForeground(Color.BLACK);
178                                 }
179                                 setFont(modifierFont);
180                                 setText(((SimulationModifier) object).getName());
181                                 setToolTipText(((SimulationModifier) object).getDescription());
182                         }
183                         
184                         return this;
185                 }
186                 
187                 private void makeFonts() {
188                         Font font = getFont();
189                         componentFont = font.deriveFont(Font.ITALIC);
190                         stringFont = font;
191                         modifierFont = font.deriveFont(Font.BOLD);
192                 }
193                 
194         }
195         
196 }