26b97055219514bd76e20de240481f1bea8ddc02
[jSite2.git] / src / net / pterodactylus / jsite / gui / AboutDialog.java
1 /*
2  * jSite2 - AboutDialog.java -
3  * Copyright © 2008 David Roden
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 package net.pterodactylus.jsite.gui;
21
22 import java.awt.BorderLayout;
23 import java.awt.FlowLayout;
24 import java.awt.Font;
25 import java.awt.event.ActionEvent;
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.UnsupportedEncodingException;
30 import java.util.ArrayList;
31 import java.util.List;
32
33 import javax.swing.BorderFactory;
34 import javax.swing.Box;
35 import javax.swing.BoxLayout;
36 import javax.swing.JButton;
37 import javax.swing.JComponent;
38 import javax.swing.JDialog;
39 import javax.swing.JLabel;
40 import javax.swing.JPanel;
41 import javax.swing.JScrollPane;
42 import javax.swing.JTabbedPane;
43 import javax.swing.JTextArea;
44 import javax.swing.SwingConstants;
45
46 import net.pterodactylus.jsite.i18n.I18n;
47 import net.pterodactylus.jsite.i18n.I18nable;
48 import net.pterodactylus.jsite.i18n.gui.I18nAction;
49 import net.pterodactylus.jsite.i18n.gui.I18nLabel;
50 import net.pterodactylus.jsite.main.Version;
51 import net.pterodactylus.util.io.StreamCopier;
52 import net.pterodactylus.util.swing.SwingUtils;
53
54 /**
55  * An “about” dialog.
56  * 
57  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
58  */
59 public class AboutDialog extends JDialog implements I18nable {
60
61         /** A list of all contributors. */
62         private static final List<Contributor> CONTRIBUTORS = new ArrayList<Contributor>();
63
64         /** A list of all code usages. */
65         private static final List<CodeUsage> CODE_USAGES = new ArrayList<CodeUsage>();
66
67         static {
68                 CONTRIBUTORS.add(new Contributor("David ‘Bombe’ Roden", "bombe@freenetproject.org", "Main code"));
69                 CODE_USAGES.add(new CodeUsage("Tango Desktop Project", "http://tango.freedesktop.org/", "Creative Commons Attribution-Share Alike 2.5", "Icons"));
70         }
71
72         /** The “okay” button action. */
73         private I18nAction okayAction;
74
75         /** The contributors label. */
76         private I18nLabel contributorsLabel;
77
78         /** The i18n maintainer label. */
79         private I18nLabel i18nMaintainerLabel;
80
81         /** The i18n maintainer’s name label. */
82         private JLabel i18nMaintainerNameLabel;
83
84         /** The “other people’s code used” label. */
85         private I18nLabel codeUsageLabel;
86
87         /** The license header. */
88         private I18nLabel licenseHeaderLabel;
89
90         /** The tabbed pane with all the pages. */
91         private JTabbedPane pagesPane;
92
93         /**
94          * Creates a new “about” dialog.
95          * 
96          * @param swingInterface
97          *            The Swing interface
98          */
99         public AboutDialog(SwingInterface swingInterface) {
100                 super(swingInterface.getMainWindow(), I18n.get("aboutDialog.title"));
101                 initActions();
102                 initComponents();
103                 pack();
104                 SwingUtils.center(this);
105                 I18n.registerI18nable(this);
106         }
107
108         //
109         // PRIVATE METHODS
110         //
111
112         /**
113          * Initializes all actions.
114          */
115         private void initActions() {
116                 okayAction = new I18nAction("general.button.okay") {
117
118                         /**
119                          * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
120                          */
121                         @SuppressWarnings("synthetic-access")
122                         public void actionPerformed(ActionEvent e) {
123                                 actionOkay();
124                         }
125                 };
126         }
127
128         /**
129          * Initiliazes all components of the dialog.
130          */
131         private void initComponents() {
132                 JPanel contentPane = new JPanel(new BorderLayout(12, 12));
133                 getContentPane().add(contentPane, BorderLayout.CENTER);
134                 contentPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
135
136                 pagesPane = new JTabbedPane(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
137                 contentPane.add(pagesPane, BorderLayout.CENTER);
138
139                 pagesPane.addTab(I18n.get("aboutDialog.page.about.title"), createAboutPage());
140                 pagesPane.setToolTipTextAt(0, I18n.get("aboutDialog.page.about.shortDescription"));
141                 pagesPane.addTab(I18n.get("aboutDialog.page.license.title"), createLicensePage());
142                 pagesPane.setToolTipTextAt(1, I18n.get("aboutDialog.page.license.shortDescription"));
143
144                 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
145                 contentPane.add(buttonPanel, BorderLayout.PAGE_END);
146                 buttonPanel.add(new JButton(okayAction));
147         }
148
149         /**
150          * Creates the “about” page.
151          * 
152          * @return The “about” page
153          */
154         private JComponent createAboutPage() {
155                 JPanel aboutPanel = new JPanel(new BorderLayout(12, 12));
156                 aboutPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
157
158                 /* the about page consists of an image to the left and text to right. */
159                 JComponent textPanel = new Box(BoxLayout.PAGE_AXIS);
160                 aboutPanel.add(textPanel, BorderLayout.CENTER);
161
162                 JLabel jSiteHeaderLabel = new JLabel("jSite " + Version.getVersion());
163                 textPanel.add(jSiteHeaderLabel);
164                 textPanel.add(Box.createVerticalStrut(24));
165                 Font jSiteHeaderLabelFont = jSiteHeaderLabel.getFont();
166                 jSiteHeaderLabel.setFont(jSiteHeaderLabelFont.deriveFont(jSiteHeaderLabelFont.getSize2D() * 2).deriveFont(Font.BOLD));
167
168                 contributorsLabel = new I18nLabel("aboutDialog.page.about.label.contributor");
169                 textPanel.add(contributorsLabel);
170                 textPanel.add(Box.createVerticalStrut(12));
171                 contributorsLabel.setFont(contributorsLabel.getFont().deriveFont(Font.BOLD));
172
173                 for (Contributor contributor: CONTRIBUTORS) {
174                         JLabel contributorLabel = new JLabel(contributor.getName() + " <" + contributor.getEmail() + "> (" + contributor.getPart() + ")");
175                         textPanel.add(contributorLabel);
176                 }
177                 textPanel.add(Box.createVerticalStrut(24));
178
179                 i18nMaintainerLabel = new I18nLabel("aboutDialog.page.about.label.i18nMaintainer");
180                 textPanel.add(i18nMaintainerLabel);
181                 textPanel.add(Box.createVerticalStrut(12));
182                 i18nMaintainerLabel.setFont(i18nMaintainerLabel.getFont().deriveFont(Font.BOLD));
183
184                 i18nMaintainerNameLabel = new JLabel(I18n.get("i18n.maintainer.name") + " <" + I18n.get("i18n.maintainer.email") + ">");
185                 textPanel.add(i18nMaintainerNameLabel);
186                 textPanel.add(Box.createVerticalStrut(24));
187
188                 codeUsageLabel = new I18nLabel("aboutDialog.page.about.label.codeUsage");
189                 codeUsageLabel.setFont(codeUsageLabel.getFont().deriveFont(Font.BOLD));
190                 textPanel.add(codeUsageLabel);
191                 textPanel.add(Box.createVerticalStrut(12));
192
193                 for (CodeUsage codeUsage: CODE_USAGES) {
194                         JLabel usageLabel = new JLabel(codeUsage.getName() + " (" + codeUsage.getURL() + ", " + codeUsage.getLicense() + ")");
195                         textPanel.add(usageLabel);
196                 }
197
198                 return aboutPanel;
199         }
200
201         /**
202          * Creates the “license” page.
203          * 
204          * @return The “license” page
205          */
206         private JComponent createLicensePage() {
207                 JPanel licensePanel = new JPanel(new BorderLayout(12, 12));
208                 licensePanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
209
210                 JPanel licenseHeaderPanel = new JPanel(new FlowLayout());
211                 licensePanel.add(licenseHeaderPanel, BorderLayout.PAGE_START);
212
213                 licenseHeaderLabel = new I18nLabel("aboutDialog.page.license.header", Version.getVersion());
214                 licenseHeaderPanel.add(licenseHeaderLabel);
215                 licenseHeaderLabel.setAlignmentX(0.5f);
216
217                 String licenseText = loadLicenseText();
218                 JTextArea licenseArea = new JTextArea(licenseText, 25, 80);
219                 licensePanel.add(new JScrollPane(licenseArea), BorderLayout.CENTER);
220                 licenseArea.setFont(new Font("Courier", Font.PLAIN, licenseArea.getFont().getSize()));
221                 licenseArea.setEditable(false);
222
223                 return licensePanel;
224         }
225
226         /**
227          * Loads the license text.
228          * 
229          * @return The license text
230          */
231         private String loadLicenseText() {
232                 InputStream licenseInputStream = getClass().getResourceAsStream("/LICENSE");
233                 if (licenseInputStream == null) {
234                         return "Could not load LICENSE, check your installation.";
235                 }
236                 ByteArrayOutputStream licenseOutputStream = new ByteArrayOutputStream(20000);
237                 try {
238                         StreamCopier.copy(licenseInputStream, licenseOutputStream);
239                 } catch (IOException e) {
240                         return "Could not load LICENSE, check your installation.";
241                 }
242                 String licenseText;
243                 try {
244                         licenseText = new String(licenseOutputStream.toByteArray(), "ISO-8859-1");
245                 } catch (UnsupportedEncodingException e) {
246                         licenseText = new String(licenseOutputStream.toByteArray());
247                 }
248                 return licenseText;
249         }
250
251         //
252         // PRIVATE ACTIONS
253         //
254
255         /**
256          * Closes the dialog.
257          */
258         private void actionOkay() {
259                 setVisible(false);
260         }
261
262         //
263         // INTERFACE I18nable
264         //
265
266         /**
267          * @see net.pterodactylus.jsite.i18n.I18nable#updateI18n()
268          */
269         public void updateI18n() {
270                 contributorsLabel.updateI18n();
271                 licenseHeaderLabel.updateI18n();
272                 i18nMaintainerLabel.updateI18n();
273                 codeUsageLabel.updateI18n();
274                 i18nMaintainerNameLabel.setText(I18n.get("i18n.maintainer.name") + " <" + I18n.get("i18n.maintainer.email") + ">");
275                 okayAction.updateI18n();
276                 setTitle(I18n.get("aboutDialog.title"));
277                 pagesPane.setTitleAt(0, I18n.get("aboutDialog.page.about.title"));
278                 pagesPane.setToolTipTextAt(0, I18n.get("aboutDialog.page.about.shortDescription"));
279                 pagesPane.setTitleAt(1, I18n.get("aboutDialog.page.license.title"));
280                 pagesPane.setToolTipTextAt(1, I18n.get("aboutDialog.page.license.shortDescription"));
281                 SwingUtils.repackCentered(this);
282         }
283
284         /**
285          * Container for a contributor.
286          * 
287          * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
288          */
289         private static class Contributor {
290
291                 /** The name of the contributor. */
292                 private final String name;
293
294                 /** The email address of the contributor. */
295                 private final String email;
296
297                 /** The parts where the contributor helped. */
298                 private final String part;
299
300                 /**
301                  * Creates a new contributor.
302                  * 
303                  * @param name
304                  *            The name of the contributor
305                  * @param email
306                  *            The email address of the contributor
307                  * @param part
308                  *            The parts where the contributor helped
309                  */
310                 public Contributor(String name, String email, String part) {
311                         this.name = name;
312                         this.email = email;
313                         this.part = part;
314                 }
315
316                 /**
317                  * Returns the name of the contributor.
318                  * 
319                  * @return The name of the contributor
320                  */
321                 String getName() {
322                         return name;
323                 }
324
325                 /**
326                  * Returns the email address of the contributor.
327                  * 
328                  * @return The email address of the contributor
329                  */
330                 String getEmail() {
331                         return email;
332                 }
333
334                 /**
335                  * Returns the parts where the contributor helped.
336                  * 
337                  * @return The parts where the contributor helped
338                  */
339                 String getPart() {
340                         return part;
341                 }
342
343         }
344
345         /**
346          * A code usage object describes code or other resources that have been
347          * taken from other projects.
348          * 
349          * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
350          */
351         private static class CodeUsage {
352
353                 /** The name of the project. */
354                 private final String name;
355
356                 /** The URL of the project. */
357                 private final String url;
358
359                 /** The license of the project. */
360                 private final String license;
361
362                 /** The part that is used. */
363                 private final String part;
364
365                 /**
366                  * Creates a new code usage object.
367                  * 
368                  * @param name
369                  *            The name of the project
370                  * @param url
371                  *            The URL of the project
372                  * @param license
373                  *            The license of the used code
374                  * @param part
375                  *            The part that is used
376                  */
377                 public CodeUsage(String name, String url, String license, String part) {
378                         this.name = name;
379                         this.url = url;
380                         this.license = license;
381                         this.part = part;
382                 }
383
384                 /**
385                  * Returns the name of the project.
386                  * 
387                  * @return The name of the project
388                  */
389                 public String getName() {
390                         return name;
391                 }
392
393                 /**
394                  * Returns the URL of the project.
395                  * 
396                  * @return The URL of the project
397                  */
398                 public String getURL() {
399                         return url;
400                 }
401
402                 /**
403                  * Returns the license of the used part.
404                  * 
405                  * @return The license of the used part
406                  */
407                 public String getLicense() {
408                         return license;
409                 }
410
411                 /**
412                  * Returns the used part.
413                  * 
414                  * @return The used part
415                  */
416                 public String getPart() {
417                         return part;
418                 }
419
420         }
421
422 }