create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / gui / scalefigure / ScaleSelector.java
1 package net.sf.openrocket.gui.scalefigure;
2
3 import java.awt.Component;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.text.DecimalFormat;
7 import java.util.Arrays;
8 import java.util.EventObject;
9 import java.util.Locale;
10
11 import javax.swing.JButton;
12 import javax.swing.JComboBox;
13 import javax.swing.JPanel;
14
15 import net.miginfocom.swing.MigLayout;
16 import net.sf.openrocket.gui.util.Icons;
17 import net.sf.openrocket.util.StateChangeListener;
18
19 public class ScaleSelector extends JPanel {
20         
21         // Ready zoom settings
22         private static final DecimalFormat PERCENT_FORMAT = new DecimalFormat("0.#%");
23         
24         private static final double[] ZOOM_LEVELS = { 0.15, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0 };
25         private static final String ZOOM_FIT = "Fit";
26         private static final String[] ZOOM_SETTINGS;
27         static {
28                 ZOOM_SETTINGS = new String[ZOOM_LEVELS.length + 1];
29                 for (int i = 0; i < ZOOM_LEVELS.length; i++)
30                         ZOOM_SETTINGS[i] = PERCENT_FORMAT.format(ZOOM_LEVELS[i]);
31                 ZOOM_SETTINGS[ZOOM_SETTINGS.length - 1] = ZOOM_FIT;
32         }
33         
34         
35         private final ScaleScrollPane scrollPane;
36         private JComboBox zoomSelector;
37         
38         
39         public ScaleSelector(ScaleScrollPane scroll) {
40                 super(new MigLayout());
41                 
42                 this.scrollPane = scroll;
43                 
44                 // Zoom out button
45                 JButton button = new JButton(Icons.ZOOM_OUT);
46                 button.addActionListener(new ActionListener() {
47                         @Override
48                         public void actionPerformed(ActionEvent e) {
49                                 double scale = scrollPane.getScaling();
50                                 scale = getPreviousScale(scale);
51                                 scrollPane.setScaling(scale);
52                         }
53                 });
54                 add(button, "gap");
55                 
56                 // Zoom level selector
57                 String[] settings = ZOOM_SETTINGS;
58                 if (!scrollPane.isFittingAllowed()) {
59                         settings = Arrays.copyOf(settings, settings.length - 1);
60                 }
61                 
62                 zoomSelector = new JComboBox(settings);
63                 zoomSelector.setEditable(true);
64                 setZoomText();
65                 zoomSelector.addActionListener(new ActionListener() {
66                         @Override
67                         public void actionPerformed(ActionEvent e) {
68                                 try {
69                                         String text = (String) zoomSelector.getSelectedItem();
70                                         text = text.replaceAll("%", "").trim();
71                                         
72                                         if (text.toLowerCase(Locale.getDefault()).startsWith(ZOOM_FIT.toLowerCase(Locale.getDefault())) &&
73                                                         scrollPane.isFittingAllowed()) {
74                                                 scrollPane.setFitting(true);
75                                                 setZoomText();
76                                                 return;
77                                         }
78                                         
79                                         double n = Double.parseDouble(text);
80                                         n /= 100;
81                                         if (n <= 0.005)
82                                                 n = 0.005;
83                                         
84                                         scrollPane.setScaling(n);
85                                         setZoomText();
86                                 } catch (NumberFormatException ignore) {
87                                 } finally {
88                                         setZoomText();
89                                 }
90                         }
91                 });
92                 scrollPane.getFigure().addChangeListener(new StateChangeListener() {
93                         @Override
94                         public void stateChanged(EventObject e) {
95                                 setZoomText();
96                         }
97                 });
98                 add(zoomSelector, "gap rel");
99                 
100                 
101                 // Zoom in button
102                 button = new JButton(Icons.ZOOM_IN);
103                 button.addActionListener(new ActionListener() {
104                         @Override
105                         public void actionPerformed(ActionEvent e) {
106                                 double scale = scrollPane.getScaling();
107                                 scale = getNextScale(scale);
108                                 scrollPane.setScaling(scale);
109                         }
110                 });
111                 add(button, "gapleft rel");
112                 
113         }
114         
115         
116         
117         private void setZoomText() {
118                 String text;
119                 double zoom = scrollPane.getScaling();
120                 text = PERCENT_FORMAT.format(zoom);
121                 if (scrollPane.isFitting()) {
122                         text = "Fit (" + text + ")";
123                 }
124                 if (!text.equals(zoomSelector.getSelectedItem()))
125                         zoomSelector.setSelectedItem(text);
126         }
127         
128         
129         
130         private double getPreviousScale(double scale) {
131                 int i;
132                 for (i = 0; i < ZOOM_LEVELS.length - 1; i++) {
133                         if (scale > ZOOM_LEVELS[i] + 0.05 && scale < ZOOM_LEVELS[i + 1] + 0.05)
134                                 return ZOOM_LEVELS[i];
135                 }
136                 if (scale > ZOOM_LEVELS[ZOOM_LEVELS.length / 2]) {
137                         // scale is large, drop to next lowest full 100%
138                         scale = Math.ceil(scale - 1.05);
139                         return Math.max(scale, ZOOM_LEVELS[i]);
140                 }
141                 // scale is small
142                 return scale / 1.5;
143         }
144         
145         
146         private double getNextScale(double scale) {
147                 int i;
148                 for (i = 0; i < ZOOM_LEVELS.length - 1; i++) {
149                         if (scale > ZOOM_LEVELS[i] - 0.05 && scale < ZOOM_LEVELS[i + 1] - 0.05)
150                                 return ZOOM_LEVELS[i + 1];
151                 }
152                 if (scale > ZOOM_LEVELS[ZOOM_LEVELS.length / 2]) {
153                         // scale is large, give next full 100%
154                         scale = Math.floor(scale + 1.05);
155                         return scale;
156                 }
157                 return scale * 1.5;
158         }
159         
160         @Override
161         public void setEnabled(boolean b){
162                 for ( Component c : getComponents() ){
163                         c.setEnabled(b);
164                 }
165                 super.setEnabled(b);
166         }
167         
168 }