1 package tim.prune.function;
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.Dimension;
6 import java.awt.FlowLayout;
8 import java.awt.GridBagConstraints;
9 import java.awt.GridBagLayout;
10 import java.awt.event.ActionEvent;
11 import java.awt.event.ActionListener;
12 import java.awt.event.KeyEvent;
13 import java.awt.event.KeyListener;
14 import java.io.ByteArrayOutputStream;
16 import java.io.FileInputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.util.zip.GZIPInputStream;
21 import javax.swing.BorderFactory;
22 import javax.swing.BoxLayout;
23 import javax.swing.JButton;
24 import javax.swing.JDialog;
25 import javax.swing.JEditorPane;
26 import javax.swing.JLabel;
27 import javax.swing.JPanel;
28 import javax.swing.JScrollPane;
29 import javax.swing.JTabbedPane;
30 import javax.swing.JTextArea;
33 import tim.prune.ExternalTools;
34 import tim.prune.GenericFunction;
35 import tim.prune.GpsPrune;
36 import tim.prune.I18nManager;
37 import tim.prune.jpeg.ExifGateway;
38 import tim.prune.threedee.WindowFactory;
41 * Class to represent the "About" popup window
43 public class AboutScreen extends GenericFunction
45 private JDialog _dialog = null;
46 private JTabbedPane _tabs = null;
47 private JButton _okButton = null;
48 private JTextArea _aboutTextArea = null;
49 /** Labels for whether tools installed or not */
50 private JLabel[] _installedLabels = null;
55 * @param inApp app object
57 public AboutScreen(App inApp)
63 * Return the name key for this function
65 public String getNameKey()
67 return "function.about";
71 * @return the contents of the window as a Component
73 private Component makeContents()
75 JPanel mainPanel = new JPanel();
76 mainPanel.setLayout(new BorderLayout());
78 _tabs = new JTabbedPane();
79 mainPanel.add(_tabs, BorderLayout.CENTER);
81 JPanel aboutPanel = new JPanel();
82 aboutPanel.setLayout(new BoxLayout(aboutPanel, BoxLayout.Y_AXIS));
83 aboutPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
84 JLabel titleLabel = new JLabel("GpsPrune");
85 titleLabel.setFont(new Font("SansSerif", Font.BOLD, 24));
86 titleLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
87 aboutPanel.add(titleLabel);
88 JLabel versionLabel = new JLabel(I18nManager.getText("dialog.about.version") + ": " + GpsPrune.VERSION_NUMBER);
89 versionLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
90 aboutPanel.add(versionLabel);
91 JLabel buildLabel = new JLabel(I18nManager.getText("dialog.about.build") + ": " + GpsPrune.BUILD_NUMBER);
92 buildLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
93 aboutPanel.add(buildLabel);
94 aboutPanel.add(new JLabel(" "));
95 StringBuffer descBuffer = new StringBuffer();
96 descBuffer.append("<p>").append(I18nManager.getText("dialog.about.summarytext1")).append("</p>");
97 descBuffer.append("<p>").append(I18nManager.getText("dialog.about.summarytext2")).append("</p>");
98 descBuffer.append("<p>").append(I18nManager.getText("dialog.about.summarytext3")).append("</p>");
99 descBuffer.append("<p>").append(I18nManager.getText("dialog.about.languages")).append(" : ")
100 .append("\u010de\u0161tina, deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano, magyar,<br>" +
101 " nederlands, polski, portugu\u00EAs, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian), \u4e2d\u6587 (chinese), \u65E5\u672C\u8A9E (japanese),<br>" +
102 " \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch, t\u00FCrk\u00E7e, rom\u00E2n\u0103, afrikaans, bahasa indonesia</p>");
103 descBuffer.append("<p>").append(I18nManager.getText("dialog.about.translatedby")).append("</p>");
104 JEditorPane descPane = new JEditorPane("text/html", descBuffer.toString());
105 descPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
106 descPane.setEditable(false);
107 descPane.setOpaque(false);
108 descPane.setAlignmentX(JEditorPane.CENTER_ALIGNMENT);
110 aboutPanel.add(descPane);
111 aboutPanel.add(new JLabel(" "));
112 _tabs.add(I18nManager.getText("function.about"), aboutPanel);
114 // Second pane for system info
115 JPanel sysInfoPanel = new JPanel();
116 GridBagLayout gridBag = new GridBagLayout();
117 sysInfoPanel.setLayout(gridBag);
118 GridBagConstraints constraints = new GridBagConstraints();
119 constraints.weightx = 0.0; constraints.weighty = 0.0;
120 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
121 new JLabel(I18nManager.getText("dialog.about.systeminfo.os") + " : "),
123 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
124 new JLabel(System.getProperty("os.name")),
126 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
127 new JLabel(I18nManager.getText("dialog.about.systeminfo.java") + " : "),
129 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
130 new JLabel(System.getProperty("java.runtime.version")),
132 // Create install labels to be populated later
133 final int NUM_INSTALL_CHECKS = 4;
134 _installedLabels = new JLabel[NUM_INSTALL_CHECKS];
135 for (int i=0; i<NUM_INSTALL_CHECKS; i++) {
136 _installedLabels[i] = new JLabel("...");
138 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
139 new JLabel(I18nManager.getText("dialog.about.systeminfo.java3d") + " : "),
141 addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[0], 1, 2);
142 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
143 new JLabel(I18nManager.getText("dialog.about.systeminfo.exiftool") + " : "),
145 addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[1], 1, 3);
146 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
147 new JLabel(I18nManager.getText("dialog.about.systeminfo.gpsbabel") + " : "),
149 addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[2], 1, 4);
150 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
151 new JLabel(I18nManager.getText("dialog.about.systeminfo.gnuplot") + " : "),
153 addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[3], 1, 5);
155 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
156 new JLabel(I18nManager.getText("dialog.about.systeminfo.exiflib") + " : "),
158 final String exiflibkey = "dialog.about.systeminfo.exiflib." + ExifGateway.getDescriptionKey();
159 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
160 new JLabel(I18nManager.getText(exiflibkey)), 1, 6);
161 _tabs.add(I18nManager.getText("dialog.about.systeminfo"), sysInfoPanel);
163 // Third pane for credits
164 JPanel creditsPanel = new JPanel();
165 gridBag = new GridBagLayout();
166 creditsPanel.setLayout(gridBag);
167 constraints = new GridBagConstraints();
168 constraints.weightx = 0.0; constraints.weighty = 0.0;
170 addToGridBagPanel(creditsPanel, gridBag, constraints,
171 new JLabel(I18nManager.getText("dialog.about.credits.code") + " : "),
173 addToGridBagPanel(creditsPanel, gridBag, constraints,
174 new JLabel("activityworkshop.net"),
176 addToGridBagPanel(creditsPanel, gridBag, constraints,
177 new JLabel(I18nManager.getText("dialog.about.credits.exifcode") + " : "),
179 addToGridBagPanel(creditsPanel, gridBag, constraints,
180 new JLabel("Drew Noakes"),
182 addToGridBagPanel(creditsPanel, gridBag, constraints,
183 new JLabel(I18nManager.getText("dialog.about.credits.icons") + " : "),
185 addToGridBagPanel(creditsPanel, gridBag, constraints,
186 new JLabel("Eclipse"),
188 addToGridBagPanel(creditsPanel, gridBag, constraints,
189 new JLabel(I18nManager.getText("dialog.about.credits.translators") + " : "),
191 addToGridBagPanel(creditsPanel, gridBag, constraints,
192 new JLabel("Ramon, Miguel, In\u00E9s, Piotr, Petrovsk, Josatoc, Weehal,"),
194 addToGridBagPanel(creditsPanel, gridBag, constraints,
195 new JLabel(" theYinYeti, Rothermographer, Sam, Rudolph, nazotoko,"),
197 addToGridBagPanel(creditsPanel, gridBag, constraints,
198 new JLabel(" katpatuka, R\u00E9mi, Marcus, Ali, Javier, Jeroen, prot_d, Gy\u00F6rgy,"),
200 addToGridBagPanel(creditsPanel, gridBag, constraints,
201 new JLabel(" HooAU, Sergey"),
203 addToGridBagPanel(creditsPanel, gridBag, constraints,
204 new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "),
206 addToGridBagPanel(creditsPanel, gridBag, constraints,
207 new JLabel("Open Office, Gpsdrive, Babelfish, Leo, Launchpad"),
209 addToGridBagPanel(creditsPanel, gridBag, constraints,
210 new JLabel(I18nManager.getText("dialog.about.credits.devtools") + " : "),
212 addToGridBagPanel(creditsPanel, gridBag, constraints,
213 new JLabel("Debian Linux, Sun Java, Eclipse, Svn, Gimp, Inkscape"),
215 addToGridBagPanel(creditsPanel, gridBag, constraints,
216 new JLabel(I18nManager.getText("dialog.about.credits.othertools") + " : "),
218 addToGridBagPanel(creditsPanel, gridBag, constraints,
219 new JLabel("Openstreetmap, Povray, Exiftool, Google Earth, Gpsbabel, Gnuplot"),
221 addToGridBagPanel(creditsPanel, gridBag, constraints,
222 new JLabel(I18nManager.getText("dialog.about.credits.thanks") + " : "),
224 addToGridBagPanel(creditsPanel, gridBag, constraints,
225 new JLabel("Friends and loved ones, for encouragement and support"),
227 _tabs.add(I18nManager.getText("dialog.about.credits"), creditsPanel);
230 JPanel readmePanel = new JPanel();
231 readmePanel.setLayout(new BorderLayout());
232 _aboutTextArea = new JTextArea(I18nManager.getText("details.photo.loading"));
233 // Set readme text in separate thread so that about screen pops up sooner
234 new Thread(new Runnable() {
236 _aboutTextArea.setText(getReadmeText());
239 _aboutTextArea.setEditable(false);
240 _aboutTextArea.setLineWrap(true); _aboutTextArea.setWrapStyleWord(true);
241 JScrollPane scrollPane = new JScrollPane(_aboutTextArea);
242 scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
243 scrollPane.setPreferredSize(new Dimension(600, 130));
244 readmePanel.add(scrollPane, BorderLayout.CENTER);
245 _tabs.add(I18nManager.getText("dialog.about.readme"), readmePanel);
247 // OK button at the bottom
248 JPanel okPanel = new JPanel();
249 okPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
250 _okButton = new JButton(I18nManager.getText("button.ok"));
251 _okButton.addActionListener(new ActionListener()
253 public void actionPerformed(ActionEvent e)
258 _okButton.addKeyListener(new KeyListener() {
259 public void keyPressed(KeyEvent e)
261 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
263 public void keyTyped(KeyEvent e) {}
264 public void keyReleased(KeyEvent e) {}
266 okPanel.add(_okButton);
267 mainPanel.add(okPanel, BorderLayout.SOUTH);
272 * Helper function to reduce complexity of gui-making code
273 * when adding labels to a GridBagLayout
274 * @param inPanel panel to add to
275 * @param inLayout GridBagLayout object
276 * @param inConstraints GridBagConstraints object
277 * @param inLabel label to add
281 private static void addToGridBagPanel(JPanel inPanel, GridBagLayout inLayout,
282 GridBagConstraints inConstraints, JLabel inLabel, int inX, int inY)
284 // set x and y in constraints
285 inConstraints.gridx = inX;
286 inConstraints.gridy = inY;
288 inConstraints.anchor = (inX == 0?GridBagConstraints.EAST:GridBagConstraints.WEST);
289 // set constraints to label
290 inLayout.setConstraints(inLabel, inConstraints);
291 // add label to panel
292 inPanel.add(inLabel);
296 * @return text from the readme file
298 private String getReadmeText()
300 // First, try locally-held readme.txt if available (as it normally should be)
301 // Readme file can either be in file system or packed in the same jar as code
302 String errorMessage = null;
303 String readme = null;
304 InputStream in = null;
307 // For some reason using ../readme.txt doesn't work, so need absolute path
308 in = AboutScreen.class.getResourceAsStream("/tim/prune/readme.txt");
310 byte[] buffer = new byte[in.available()];
313 readme = new String(buffer);
316 catch (IOException e) {
317 errorMessage = e.getMessage();
320 try {in.close();} catch (Exception e) {}
322 if (readme != null) {return readme;}
324 // Locally-held file failed, so try to find gz file installed on system (eg Debian)
327 File gzFile = new File("/usr/share/doc/gpsprune/readme.txt.gz");
330 // Copy decompressed bytes from gz file into out
331 in = new GZIPInputStream(new FileInputStream(gzFile));
332 ByteArrayOutputStream out = new ByteArrayOutputStream();
333 byte[] buffer = new byte[8 * 1024];
336 out.write(buffer, 0, count);
337 count = in.read(buffer, 0, buffer.length);
338 } while (count != -1);
341 readme = out.toString();
344 catch (IOException e) {
345 System.err.println("Exception trying to get readme.gz : " + e.getMessage());
348 try {in.close();} catch (Exception e) {}
350 if (readme != null) {return readme;}
351 // Only show first error message if couldn't get readme from gz either
352 if (errorMessage != null) {
353 System.err.println("Exception trying to get readme: " + errorMessage);
355 return I18nManager.getText("error.readme.notfound");
365 _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()));
366 _dialog.getContentPane().add(makeContents());
369 _tabs.setSelectedIndex(0);
371 _dialog.setVisible(true);
372 _okButton.requestFocus();
376 * Check the installed components and set the label texts accordingly
378 private void checkInstalls()
380 String yesText = I18nManager.getText("dialog.about.yes");
381 String noText = I18nManager.getText("dialog.about.no");
382 _installedLabels[0].setText(WindowFactory.isJava3dEnabled()?yesText:noText);
383 final int[] tools = {ExternalTools.TOOL_EXIFTOOL, ExternalTools.TOOL_GPSBABEL, ExternalTools.TOOL_GNUPLOT};
384 for (int i=0; i<tools.length; i++) {
385 _installedLabels[i+1].setText(ExternalTools.isToolInstalled(tools[i])?yesText:noText);