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;
172 addToGridBagPanel(creditsPanel, gridBag, constraints,
173 new JLabel(I18nManager.getText("dialog.about.credits.code") + " : "),
175 addToGridBagPanel(creditsPanel, gridBag, constraints,
176 new JLabel("activityworkshop.net"),
178 addToGridBagPanel(creditsPanel, gridBag, constraints,
179 new JLabel(I18nManager.getText("dialog.about.credits.exifcode") + " : "),
181 addToGridBagPanel(creditsPanel, gridBag, constraints,
182 new JLabel("Drew Noakes"),
184 addToGridBagPanel(creditsPanel, gridBag, constraints,
185 new JLabel(I18nManager.getText("dialog.about.credits.icons") + " : "),
187 addToGridBagPanel(creditsPanel, gridBag, constraints,
188 new JLabel("Eclipse"),
190 addToGridBagPanel(creditsPanel, gridBag, constraints,
191 new JLabel(I18nManager.getText("dialog.about.credits.translators") + " : "),
193 addToGridBagPanel(creditsPanel, gridBag, constraints,
194 new JLabel("Ramon, Miguel, In\u00E9s, Piotr, Petrovsk, Josatoc, Weehal,"),
196 addToGridBagPanel(creditsPanel, gridBag, constraints,
197 new JLabel(" theYinYeti, Rothermographer, Sam, Rudolph, nazotoko,"),
199 addToGridBagPanel(creditsPanel, gridBag, constraints,
200 new JLabel(" katpatuka, R\u00E9mi, Marcus, Ali, Javier, Jeroen, prot_d, Gy\u00F6rgy,"),
202 addToGridBagPanel(creditsPanel, gridBag, constraints,
203 new JLabel(" HooAU, Sergey, P\u00E9ter, serhijdubyk, Peter, Cristian"),
205 addToGridBagPanel(creditsPanel, gridBag, constraints,
206 new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "),
208 addToGridBagPanel(creditsPanel, gridBag, constraints,
209 new JLabel("Open Office, Gpsdrive, Babelfish, Leo, Launchpad"),
211 addToGridBagPanel(creditsPanel, gridBag, constraints,
212 new JLabel(I18nManager.getText("dialog.about.credits.devtools") + " : "),
214 addToGridBagPanel(creditsPanel, gridBag, constraints,
215 new JLabel("Debian Linux, Sun Java, OpenJDK, Eclipse, Svn, Gimp, Inkscape"),
217 addToGridBagPanel(creditsPanel, gridBag, constraints,
218 new JLabel(I18nManager.getText("dialog.about.credits.othertools") + " : "),
220 addToGridBagPanel(creditsPanel, gridBag, constraints,
221 new JLabel("Openstreetmap, Povray, Exiftool, Gpsbabel, Gnuplot"),
223 addToGridBagPanel(creditsPanel, gridBag, constraints,
224 new JLabel(I18nManager.getText("dialog.about.credits.thanks") + " : "),
226 addToGridBagPanel(creditsPanel, gridBag, constraints,
227 new JLabel("Friends and loved ones, for encouragement and support"),
229 _tabs.add(I18nManager.getText("dialog.about.credits"), creditsPanel);
232 JPanel readmePanel = new JPanel();
233 readmePanel.setLayout(new BorderLayout());
234 _aboutTextArea = new JTextArea(I18nManager.getText("details.photo.loading"));
235 // Set readme text in separate thread so that about screen pops up sooner
236 new Thread(new Runnable() {
238 _aboutTextArea.setText(getReadmeText());
241 _aboutTextArea.setEditable(false);
242 _aboutTextArea.setLineWrap(true); _aboutTextArea.setWrapStyleWord(true);
243 JScrollPane scrollPane = new JScrollPane(_aboutTextArea);
244 scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
245 scrollPane.setPreferredSize(new Dimension(600, 130));
246 readmePanel.add(scrollPane, BorderLayout.CENTER);
247 _tabs.add(I18nManager.getText("dialog.about.readme"), readmePanel);
249 // OK button at the bottom
250 JPanel okPanel = new JPanel();
251 okPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
252 _okButton = new JButton(I18nManager.getText("button.ok"));
253 _okButton.addActionListener(new ActionListener()
255 public void actionPerformed(ActionEvent e)
260 _okButton.addKeyListener(new KeyListener() {
261 public void keyPressed(KeyEvent e)
263 if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
265 public void keyTyped(KeyEvent e) {}
266 public void keyReleased(KeyEvent e) {}
268 okPanel.add(_okButton);
269 mainPanel.add(okPanel, BorderLayout.SOUTH);
274 * Helper function to reduce complexity of gui-making code
275 * when adding labels to a GridBagLayout
276 * @param inPanel panel to add to
277 * @param inLayout GridBagLayout object
278 * @param inConstraints GridBagConstraints object
279 * @param inLabel label to add
283 private static void addToGridBagPanel(JPanel inPanel, GridBagLayout inLayout,
284 GridBagConstraints inConstraints, JLabel inLabel, int inX, int inY)
286 // set x and y in constraints
287 inConstraints.gridx = inX;
288 inConstraints.gridy = inY;
290 inConstraints.anchor = (inX == 0?GridBagConstraints.EAST:GridBagConstraints.WEST);
291 // set constraints to label
292 inLayout.setConstraints(inLabel, inConstraints);
293 // add label to panel
294 inPanel.add(inLabel);
298 * @return text from the readme file
300 private String getReadmeText()
302 // First, try locally-held readme.txt if available (as it normally should be)
303 // Readme file can either be in file system or packed in the same jar as code
304 String errorMessage = null;
305 String readme = null;
306 InputStream in = null;
309 // For some reason using ../readme.txt doesn't work, so need absolute path
310 in = AboutScreen.class.getResourceAsStream("/tim/prune/readme.txt");
312 byte[] buffer = new byte[in.available()];
315 readme = new String(buffer);
318 catch (IOException e) {
319 errorMessage = e.getMessage();
322 try {in.close();} catch (Exception e) {}
324 if (readme != null) {return readme;}
326 // Locally-held file failed, so try to find gz file installed on system (eg Debian)
329 File gzFile = new File("/usr/share/doc/gpsprune/readme.txt.gz");
332 // Copy decompressed bytes from gz file into out
333 in = new GZIPInputStream(new FileInputStream(gzFile));
334 ByteArrayOutputStream out = new ByteArrayOutputStream();
335 byte[] buffer = new byte[8 * 1024];
338 out.write(buffer, 0, count);
339 count = in.read(buffer, 0, buffer.length);
340 } while (count != -1);
343 readme = out.toString();
346 catch (IOException e) {
347 System.err.println("Exception trying to get readme.gz : " + e.getMessage());
350 try {in.close();} catch (Exception e) {}
352 if (readme != null) {return readme;}
353 // Only show first error message if couldn't get readme from gz either
354 if (errorMessage != null) {
355 System.err.println("Exception trying to get readme: " + errorMessage);
357 return I18nManager.getText("error.readme.notfound");
367 _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()));
368 _dialog.getContentPane().add(makeContents());
371 _tabs.setSelectedIndex(0);
373 _dialog.setVisible(true);
374 _okButton.requestFocus();
378 * Check the installed components and set the label texts accordingly
380 private void checkInstalls()
382 String yesText = I18nManager.getText("dialog.about.yes");
383 String noText = I18nManager.getText("dialog.about.no");
384 _installedLabels[0].setText(WindowFactory.isJava3dEnabled()?yesText:noText);
385 final int[] tools = {ExternalTools.TOOL_EXIFTOOL, ExternalTools.TOOL_GPSBABEL,
386 ExternalTools.TOOL_GNUPLOT, ExternalTools.TOOL_XERCES};
387 for (int i=0; i<tools.length; i++) {
388 _installedLabels[i+1].setText(ExternalTools.isToolInstalled(tools[i])?yesText:noText);