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("afrikaans, \u010de\u0161tina, deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano,<br>" +
101 " magyar, nederlands, polski, portugu\u00EAs, rom\u00E2n\u0103, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian), \u4e2d\u6587 (chinese),<br>" +
102 " \u65E5\u672C\u8A9E (japanese), \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch, t\u00FCrk\u00E7e, ukrainian</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 = 5;
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);
154 addToGridBagPanel(sysInfoPanel, gridBag, constraints, new JLabel("Xerces : "), 0, 6);
155 addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[4], 1, 6);
157 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
158 new JLabel(I18nManager.getText("dialog.about.systeminfo.exiflib") + " : "),
160 final String exiflibkey = "dialog.about.systeminfo.exiflib." + ExifGateway.getDescriptionKey();
161 addToGridBagPanel(sysInfoPanel, gridBag, constraints,
162 new JLabel(I18nManager.getText(exiflibkey)), 1, 7);
163 _tabs.add(I18nManager.getText("dialog.about.systeminfo"), sysInfoPanel);
165 // Third pane for credits
166 JPanel creditsPanel = new JPanel();
167 gridBag = new GridBagLayout();
168 creditsPanel.setLayout(gridBag);
169 constraints = new GridBagConstraints();
170 constraints.weightx = 0.0; constraints.weighty = 0.0;
171 constraints.ipady = 3;
173 addToGridBagPanel(creditsPanel, gridBag, constraints,
174 new JLabel(I18nManager.getText("dialog.about.credits.code") + " : "),
176 addToGridBagPanel(creditsPanel, gridBag, constraints,
177 new JLabel("activityworkshop.net"),
179 addToGridBagPanel(creditsPanel, gridBag, constraints,
180 new JLabel(I18nManager.getText("dialog.about.credits.exifcode") + " : "),
182 addToGridBagPanel(creditsPanel, gridBag, constraints,
183 new JLabel("Drew Noakes"),
185 addToGridBagPanel(creditsPanel, gridBag, constraints,
186 new JLabel(I18nManager.getText("dialog.about.credits.icons") + " : "),
188 addToGridBagPanel(creditsPanel, gridBag, constraints,
189 new JLabel("Eclipse"),
191 addToGridBagPanel(creditsPanel, gridBag, constraints,
192 new JLabel(I18nManager.getText("dialog.about.credits.translators") + " : "),
194 addToGridBagPanel(creditsPanel, gridBag, constraints,
195 new JLabel("Ramon, Miguel, In\u00E9s, Piotr, Petrovsk, Josatoc, Weehal,"),
197 addToGridBagPanel(creditsPanel, gridBag, constraints,
198 new JLabel(" theYinYeti, Rothermographer, Sam, Rudolph, nazotoko,"),
200 addToGridBagPanel(creditsPanel, gridBag, constraints,
201 new JLabel(" katpatuka, R\u00E9mi, Marcus, Ali, Javier, Jeroen, prot_d, Gy\u00F6rgy,"),
203 addToGridBagPanel(creditsPanel, gridBag, constraints,
204 new JLabel(" HooAU, Sergey, P\u00E9ter, serhijdubyk, Peter, Cristian, Roman"),
206 addToGridBagPanel(creditsPanel, gridBag, constraints,
207 new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "),
209 addToGridBagPanel(creditsPanel, gridBag, constraints,
210 new JLabel("Open Office, Gpsdrive, Babelfish, Leo, Launchpad"),
212 addToGridBagPanel(creditsPanel, gridBag, constraints,
213 new JLabel(I18nManager.getText("dialog.about.credits.devtools") + " : "),
215 addToGridBagPanel(creditsPanel, gridBag, constraints,
216 new JLabel("Debian Linux, Sun Java, OpenJDK, Eclipse, Svn, Gimp, Inkscape"),
218 addToGridBagPanel(creditsPanel, gridBag, constraints,
219 new JLabel(I18nManager.getText("dialog.about.credits.othertools") + " : "),
221 addToGridBagPanel(creditsPanel, gridBag, constraints,
222 new JLabel("Openstreetmap, Povray, Exiftool, Gpsbabel, Gnuplot"),
224 addToGridBagPanel(creditsPanel, gridBag, constraints,
225 new JLabel(I18nManager.getText("dialog.about.credits.thanks") + " : "),
227 addToGridBagPanel(creditsPanel, gridBag, constraints,
228 new JLabel("Friends and loved ones, for encouragement and support"),
230 _tabs.add(I18nManager.getText("dialog.about.credits"), creditsPanel);
233 JPanel readmePanel = new JPanel();
234 readmePanel.setLayout(new BorderLayout());
235 _aboutTextArea = new JTextArea(I18nManager.getText("details.photo.loading"));
236 // Set readme text in separate thread so that about screen pops up sooner
237 new Thread(new Runnable() {
239 _aboutTextArea.setText(getReadmeText());
242 _aboutTextArea.setEditable(false);
243 _aboutTextArea.setLineWrap(true); _aboutTextArea.setWrapStyleWord(true);
244 JScrollPane scrollPane = new JScrollPane(_aboutTextArea);
245 scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
246 scrollPane.setPreferredSize(new Dimension(600, 130));
247 readmePanel.add(scrollPane, BorderLayout.CENTER);
248 _tabs.add(I18nManager.getText("dialog.about.readme"), readmePanel);
250 // OK button at the bottom
251 JPanel okPanel = new JPanel();
252 okPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
253 _okButton = new JButton(I18nManager.getText("button.ok"));
254 _okButton.addActionListener(new ActionListener()
256 public void actionPerformed(ActionEvent e)
261 _okButton.addKeyListener(new KeyListener() {
262 public void keyPressed(KeyEvent e)
264 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
266 public void keyTyped(KeyEvent e) {}
267 public void keyReleased(KeyEvent e) {}
269 okPanel.add(_okButton);
270 mainPanel.add(okPanel, BorderLayout.SOUTH);
275 * Helper function to reduce complexity of gui-making code
276 * when adding labels to a GridBagLayout
277 * @param inPanel panel to add to
278 * @param inLayout GridBagLayout object
279 * @param inConstraints GridBagConstraints object
280 * @param inLabel label to add
284 private static void addToGridBagPanel(JPanel inPanel, GridBagLayout inLayout,
285 GridBagConstraints inConstraints, JLabel inLabel, int inX, int inY)
287 // set x and y in constraints
288 inConstraints.gridx = inX;
289 inConstraints.gridy = inY;
291 inConstraints.anchor = (inX == 0?GridBagConstraints.EAST:GridBagConstraints.WEST);
292 // set constraints to label
293 inLayout.setConstraints(inLabel, inConstraints);
294 // add label to panel
295 inPanel.add(inLabel);
299 * @return text from the readme file
301 private String getReadmeText()
303 // First, try locally-held readme.txt if available (as it normally should be)
304 // Readme file can either be in file system or packed in the same jar as code
305 String errorMessage = null;
306 String readme = null;
307 InputStream in = null;
310 // For some reason using ../readme.txt doesn't work, so need absolute path
311 in = AboutScreen.class.getResourceAsStream("/tim/prune/readme.txt");
313 byte[] buffer = new byte[in.available()];
316 readme = new String(buffer);
319 catch (IOException e) {
320 errorMessage = e.getMessage();
323 try {in.close();} catch (Exception e) {}
325 if (readme != null) {return readme;}
327 // Locally-held file failed, so try to find gz file installed on system (eg Debian)
330 File gzFile = new File("/usr/share/doc/gpsprune/readme.txt.gz");
333 // Copy decompressed bytes from gz file into out
334 in = new GZIPInputStream(new FileInputStream(gzFile));
335 ByteArrayOutputStream out = new ByteArrayOutputStream();
336 byte[] buffer = new byte[8 * 1024];
339 out.write(buffer, 0, count);
340 count = in.read(buffer, 0, buffer.length);
341 } while (count != -1);
344 readme = out.toString();
347 catch (IOException e) {
348 System.err.println("Exception trying to get readme.gz : " + e.getMessage());
351 try {in.close();} catch (Exception e) {}
353 if (readme != null) {return readme;}
354 // Only show first error message if couldn't get readme from gz either
355 if (errorMessage != null) {
356 System.err.println("Exception trying to get readme: " + errorMessage);
358 return I18nManager.getText("error.readme.notfound");
368 _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()));
369 _dialog.getContentPane().add(makeContents());
372 _tabs.setSelectedIndex(0);
374 _dialog.setVisible(true);
375 _okButton.requestFocus();
379 * Check the installed components and set the label texts accordingly
381 private void checkInstalls()
383 String yesText = I18nManager.getText("dialog.about.yes");
384 String noText = I18nManager.getText("dialog.about.no");
385 _installedLabels[0].setText(WindowFactory.isJava3dEnabled()?yesText:noText);
386 final int[] tools = {ExternalTools.TOOL_EXIFTOOL, ExternalTools.TOOL_GPSBABEL,
387 ExternalTools.TOOL_GNUPLOT, ExternalTools.TOOL_XERCES};
388 for (int i=0; i<tools.length; i++) {
389 _installedLabels[i+1].setText(ExternalTools.isToolInstalled(tools[i])?yesText:noText);