001 /*
002 * This file is part of muCommander, http://www.mucommander.com
003 * Copyright (C) 2002-2008 Maxence Bernard
004 *
005 * muCommander is free software; you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation; either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * muCommander is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program. If not, see <http://www.gnu.org/licenses/>.
017 */
018
019 package com.mucommander.ui.dialog.about;
020
021 import com.mucommander.RuntimeConstants;
022 import com.mucommander.desktop.DesktopManager;
023 import com.mucommander.text.Translator;
024 import com.mucommander.ui.action.MuAction;
025 import com.mucommander.ui.dialog.FocusDialog;
026 import com.mucommander.ui.icon.IconManager;
027 import com.mucommander.ui.main.MainFrame;
028 import com.mucommander.ui.theme.Theme;
029 import com.mucommander.ui.theme.ThemeManager;
030
031 import javax.swing.*;
032 import javax.swing.text.*;
033 import java.awt.*;
034 import java.awt.event.ActionEvent;
035 import java.awt.event.ActionListener;
036 import java.io.IOException;
037 import java.net.URL;
038 import java.util.Locale;
039
040 /**
041 * Dialog displaying information about muCommander.
042 * @author Maxence Bernard, Nicolas Rinaudo
043 */
044 public class AboutDialog extends FocusDialog implements ActionListener {
045 // - Styles -----------------------------------------------------------------
046 // --------------------------------------------------------------------------
047 /** Style for normal text. */
048 private static final String STYLE_NORMAL = "normal";
049 /** Style for headers. */
050 private static final String STYLE_HEADER = "header";
051 /** Style for URLs. */
052 private static final String STYLE_URL = "url";
053 /** Style for an item's details. */
054 private static final String STYLE_DETAILS = "details";
055 /** Style for a section title. */
056 private static final String STYLE_TITLE = "title";
057 /** Line break string. */
058 private static final String LINE_BREAK = System.getProperty("line.separator");
059
060
061
062 // - UI components ----------------------------------------------------------
063 // --------------------------------------------------------------------------
064 /** Button that closes the dialog. */
065 private JButton okButton;
066 /** Button that opens muCommander's homepage in a browser. */
067 private JButton homeButton;
068 /** Button that opens the muCommander's license. */
069 private JButton licenseButton;
070 /** Panel in which all the textual information is displayed. */
071 private JScrollPane textPanel;
072
073
074
075 // - Initialisation ---------------------------------------------------------
076 // --------------------------------------------------------------------------
077 /**
078 * Creates a new AboutDialog.
079 * @param mainFrame frame this dialog is relative to.
080 */
081 public AboutDialog(MainFrame mainFrame) {
082 super(mainFrame, MuAction.getStandardLabel(com.mucommander.ui.action.ShowAboutAction.class), mainFrame);
083
084 // Initialises the dialog's content.
085 Container contentPane = getContentPane();
086 contentPane.add(createIconPanel(), BorderLayout.WEST);
087 contentPane.add(createCreditsPanel(), BorderLayout.EAST);
088 setResizable(false);
089
090 // Makes sure the scroll pane is properly initialised.
091 SwingUtilities.invokeLater(new Runnable() {
092 public void run() {
093 textPanel.getViewport().setViewPosition(new Point(0,0));
094 }
095 });
096
097 pack();
098
099 // Makes OK the default action.
100 setInitialFocusComponent(okButton);
101 getRootPane().setDefaultButton(okButton);
102 }
103
104 /**
105 * Creates the panel that contains all of the about box's text.
106 */
107 private JScrollPane createCreditsPanel() {
108 JTextPane text;
109 StyledDocument doc;
110
111 text = new JTextPane();
112 doc = text.getStyledDocument();
113
114 text.setBackground(ThemeManager.getCurrentColor(Theme.FILE_TABLE_BACKGROUND_COLOR));
115
116 setStyles(doc);
117 text.setEditable(false);
118 try {
119 // Team.
120 insertTitle(doc, "The muCommander team");
121
122 // Core developers.
123 insertHeader(doc, "Core developers");
124 insertNormalString(doc, "Maxence Bernard");
125 insertNormalString(doc, "Nicolas Rinaudo");
126 insertNormalString(doc, "Arik Hadas");
127 insertNormalString(doc, "Mariusz Jakubowski");
128 insertLineBreak(doc);
129
130 // Contributors.
131 insertHeader(doc, "Contributors");
132 insertNormalString(doc, "Ivan Baidakov");
133 insertNormalString(doc, "Vassil Dichev");
134 insertNormalString(doc, "David Kovar");
135 insertNormalString(doc, "Karel Klic");
136 insertNormalString(doc, "Joshua Lebo");
137 insertNormalString(doc, "Xavier Martin");
138 insertNormalString(doc, "Alejandro Scandroli");
139 insertLineBreak(doc);
140
141 // QA
142 insertHeader(doc, "QA");
143 insertNormalString(doc, "Joshua Lebo");
144 insertLineBreak(doc);
145
146 // Translators.
147 insertHeader(doc, "Translators");
148 insertDetailedString(doc, "4X_Pro", "Russian");
149 insertDetailedString(doc, "Roberto Angeletti", "Italian");
150 insertDetailedString(doc, "Tamás Balogh-Walder", "Hungarian");
151 insertDetailedString(doc, "Mykola Bilovus", "Ukrainian");
152 insertDetailedString(doc, "György Varga", "Hungarian");
153 insertDetailedString(doc, "Frank Berger", "German");
154 insertDetailedString(doc, "Tony Klüver", "German");
155 insertDetailedString(doc, "Marcos Cobeña", "Spanish");
156 insertDetailedString(doc, "Cristiano Duarte", "Brazilian Portuguese");
157 insertDetailedString(doc, "Jakob Ekström", "Swedish");
158 insertDetailedString(doc, "Catalin Hritcu", "Romanian");
159 insertDetailedString(doc, "Kent Hsu", "Traditional Chinese");
160 insertDetailedString(doc, "Jioh L. Jung", "Korean");
161 insertDetailedString(doc, "Andrzej Kosiński", "Polish");
162 insertDetailedString(doc, "Joze Kovacic", "Slovenian");
163 insertDetailedString(doc, "Pieter Kristensen", "Dutch");
164 insertDetailedString(doc, "Ján Ľudvík", "Slovak");
165 insertDetailedString(doc, "Jaromír Mára", "Czech");
166 insertDetailedString(doc, "Jonathan Murphy", "British English");
167 insertDetailedString(doc, "Nardog", "Japanese");
168 insertDetailedString(doc, "Jeppe Toustrup", "Danish");
169 insertDetailedString(doc, "Peter Vasko", "Czech");
170 insertDetailedString(doc, "Woodie", "Simplified Chinese");
171 insertLineBreak(doc);
172
173 // Special thanks.
174 insertHeader(doc, "Special thanks");
175 insertDetailedString(doc, "Stefano Perelli", "muCommander icon");
176 insertLineBreak(doc);
177 insertLineBreak(doc);
178
179 // Powered by.
180 insertTitle(doc, "Powered by");
181
182 // External Libraries.
183 insertHeader(doc, "External libraries");
184 insertDetailedUrl(doc, "Ant", "Apache License", "http://ant.apache.org");
185 insertDetailedUrl(doc, "Furbelow", "LGPL", "http://sourceforge.net/projects/furbelow");
186 insertDetailedUrl(doc, "ICU4J", "ICU License", "http://www.icu-project.org");
187 insertDetailedUrl(doc, "J2SSH", "LGPL", "http://sourceforge.net/projects/sshtools");
188 insertDetailedUrl(doc, "Jakarta Commons Net", "Apache License", "http://jakarta.apache.org/commons/net");
189 insertDetailedUrl(doc, "jCIFS", "LGPL", "http://jcifs.samba.org");
190 insertDetailedUrl(doc, "JmDNS", "LGPL", "http://jmdns.sourceforge.net");
191 insertDetailedUrl(doc, "JNA", "LGPL", "http://jna.dev.java.net");
192 insertDetailedUrl(doc, "JUnRar", "Freeware", "http://sourceforge.net/projects/java-unrar");
193 insertDetailedUrl(doc, "Mark James' icons", "Creative Commons Attribution License", "http://famfamfam.com");
194 insertDetailedUrl(doc, "Yanfs", "BSD", "http://yanfs.dev.java.net");
195 insertLineBreak(doc);
196
197 // External tools.
198 insertHeader(doc, "External tools");
199 insertDetailedUrl(doc, "Ant", "Apache Software License", "http://ant.apache.org");
200 insertDetailedUrl(doc, "AntDoclet", "GPL", "http://antdoclet.neuroning.com/");
201 insertDetailedUrl(doc, "jdeb", "Apache Software License", "http://vafer.org/projects/jdeb/");
202 insertDetailedUrl(doc, "Launch4j", "GPL", "http://launch4j.sourceforge.net");
203 insertDetailedUrl(doc, "NSIS", "zlib/libpng license", "http://nsis.sourceforge.net");
204 insertDetailedUrl(doc, "p7zip", "LGPL", "http://p7zip.sourceforge.net");
205 insertDetailedUrl(doc, "ProGuard", "GPL", "http://proguard.sourceforge.net");
206 insertLineBreak(doc);
207 insertLineBreak(doc);
208
209 // Version information
210 insertTitle(doc, "Version information");
211
212 // VM information.
213 insertHeader(doc, "muCommander");
214 insertNormalString(doc, "Version: " + RuntimeConstants.VERSION);
215 insertNormalString(doc, "Build date: " + getFormatedDate());
216 insertLineBreak(doc);
217
218 // VM information.
219 insertHeader(doc, "Java VM");
220 insertNormalString(doc, "Name: " + System.getProperty("java.vm.name"));
221 insertNormalString(doc, "Version: " + System.getProperty("java.vm.version"));
222 insertNormalString(doc, "Vendor: " + System.getProperty("java.vm.vendor"));
223 insertLineBreak(doc);
224
225 // OS information.
226 insertHeader(doc, "OS");
227 insertNormalString(doc, "Name: " + System.getProperty("os.name"));
228 insertNormalString(doc, "Version: " + System.getProperty("os.version"));
229 insertNormalString(doc, "Architecture: " + System.getProperty("os.arch"));
230 insertLineBreak(doc);
231
232 // Locale information.
233 Locale locale = Locale.getDefault();
234 insertHeader(doc, "Locale");
235 insertNormalString(doc, "Language: " + locale.getLanguage());
236 insertNormalString(doc, "Country: " + locale.getCountry());
237 insertNormalString(doc, "Encoding: " + System.getProperty("file.encoding"));
238 }
239 catch(Exception e) {}
240
241 textPanel = new JScrollPane(text, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
242 textPanel.getViewport().setPreferredSize(new Dimension((int)text.getPreferredSize().getWidth(), 300));
243
244 return textPanel;
245 }
246
247 /**
248 * Creates the about box's left panel.
249 */
250 private JPanel createIconPanel() {
251 JPanel mainPanel;
252 JPanel tempPanel;
253 JPanel flowPanel;
254
255 // Makes sure the panel's a bit roomier than the default configuration.
256 mainPanel = new JPanel(new BorderLayout()) {
257 public Insets getInsets() {return new Insets(10, 10, 0, 10);}
258 };
259
260 tempPanel = new JPanel(new BorderLayout());
261
262 tempPanel.add(new JLabel(IconManager.getIcon("/about.png")), BorderLayout.NORTH);
263
264 flowPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
265 flowPanel.add(createBoldLabel(RuntimeConstants.APP_STRING));
266 tempPanel.add(flowPanel, BorderLayout.CENTER);
267
268 flowPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
269 flowPanel.add(new JLabel("©" + RuntimeConstants.COPYRIGHT + " Maxence Bernard"));
270 tempPanel.add(flowPanel, BorderLayout.SOUTH);
271 mainPanel.add(tempPanel, BorderLayout.NORTH);
272
273 tempPanel = new JPanel(new BorderLayout());
274 if(DesktopManager.canBrowse()) {
275 tempPanel.add(homeButton = new JButton(MuAction.getStandardLabel(com.mucommander.ui.action.GoToWebsiteAction.class)), BorderLayout.NORTH);
276 homeButton.addActionListener(this);
277 }
278 else {
279 flowPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
280 flowPanel.add(new JLabel(com.mucommander.RuntimeConstants.HOMEPAGE_URL));
281 tempPanel.add(flowPanel, BorderLayout.NORTH);
282 }
283 tempPanel.add(licenseButton = new JButton(Translator.get("license")), BorderLayout.CENTER);
284 licenseButton.addActionListener(this);
285 tempPanel.add(okButton = new JButton(Translator.get("ok")), BorderLayout.SOUTH);
286 okButton.addActionListener(this);
287 mainPanel.add(tempPanel, BorderLayout.SOUTH);
288
289 return mainPanel;
290 }
291
292
293
294 // - Text panel handling ----------------------------------------------------
295 // --------------------------------------------------------------------------
296 /**
297 * Creates different styles in the specified <code>StyledDocument</code>
298 * @param doc document in which to create the styles.
299 */
300 private static void setStyles(StyledDocument doc) {
301 Style master;
302 Style currentStyle;
303 Font font;
304
305 master = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
306 font = ThemeManager.getCurrentFont(Theme.FILE_TABLE_FONT);
307
308 // Normal style.
309 master = doc.addStyle(STYLE_NORMAL, master);
310 StyleConstants.setFontFamily(master, font.getFamily());
311 StyleConstants.setFontSize(master, font.getSize());
312 StyleConstants.setForeground(master, ThemeManager.getCurrentColor(Theme.FILE_FOREGROUND_COLOR));
313 StyleConstants.setBackground(master, ThemeManager.getCurrentColor(Theme.FILE_TABLE_BACKGROUND_COLOR));
314 StyleConstants.setLeftIndent(master, 10);
315 StyleConstants.setRightIndent(master, 10);
316 StyleConstants.setLineSpacing(master, (float)0.2);
317 doc.setParagraphAttributes(0, 0, master, true);
318
319 // Header style.
320 currentStyle = doc.addStyle(STYLE_HEADER, master);
321 StyleConstants.setBold(currentStyle, true);
322 StyleConstants.setFontSize(currentStyle, font.getSize() + 2);
323 StyleConstants.setForeground(currentStyle, ThemeManager.getCurrentColor(Theme.FOLDER_FOREGROUND_COLOR));
324 StyleConstants.setBackground(currentStyle, ThemeManager.getCurrentColor(Theme.FILE_TABLE_BACKGROUND_COLOR));
325
326 // Title style.
327 currentStyle = doc.addStyle(STYLE_TITLE, currentStyle);
328 StyleConstants.setAlignment(currentStyle, StyleConstants.ALIGN_CENTER);
329 StyleConstants.setForeground(currentStyle, ThemeManager.getCurrentColor(Theme.ARCHIVE_FOREGROUND_COLOR));
330 StyleConstants.setBackground(currentStyle, ThemeManager.getCurrentColor(Theme.FILE_TABLE_BACKGROUND_COLOR));
331
332 // Details style.
333 currentStyle = doc.addStyle(STYLE_DETAILS, master);
334 StyleConstants.setForeground(currentStyle, ThemeManager.getCurrentColor(Theme.HIDDEN_FILE_FOREGROUND_COLOR));
335 StyleConstants.setBackground(currentStyle, ThemeManager.getCurrentColor(Theme.FILE_TABLE_BACKGROUND_COLOR));
336
337 // URL style.
338 currentStyle = doc.addStyle(STYLE_URL, master);
339 StyleConstants.setForeground(currentStyle, ThemeManager.getCurrentColor(Theme.SYMLINK_FOREGROUND_COLOR));
340 StyleConstants.setBackground(currentStyle, ThemeManager.getCurrentColor(Theme.FILE_TABLE_BACKGROUND_COLOR));
341 StyleConstants.setUnderline(currentStyle, true);
342 }
343
344 /**
345 * Inserts the specified header in the specified document.
346 * @param doc document in which to insert the text.
347 * @param string text to insert.
348 * @throws BadLocationException thrown if something wrong happened to the document.
349 */
350 private static void insertHeader(StyledDocument doc, String string) throws BadLocationException {
351 doc.insertString(doc.getLength(), string + LINE_BREAK, doc.getStyle(STYLE_HEADER));
352 }
353
354 /**
355 * Inserts the specified string in the specified document.
356 * @param doc document in which to insert the text.
357 * @param string text to insert.
358 * @throws BadLocationException thrown if something wrong happened to the document.
359 */
360 private static void insertNormalString(StyledDocument doc, String string) throws BadLocationException {
361 doc.insertString(doc.getLength(), string + LINE_BREAK, doc.getStyle(STYLE_NORMAL));
362 }
363
364 /**
365 * Inserts the specified string and details in the specified document.
366 * @param doc document in which to insert the text.
367 * @param string text to insert.
368 * @param details details that will be added to the text.
369 * @throws BadLocationException thrown if something wrong happened to the document.
370 */
371 private static void insertDetailedString(StyledDocument doc, String string, String details) throws BadLocationException {
372 doc.insertString(doc.getLength(), string + " ", doc.getStyle(STYLE_NORMAL));
373 doc.insertString(doc.getLength(), "(" + details + ")" + LINE_BREAK, doc.getStyle(STYLE_DETAILS));
374 }
375
376 /**
377 * Inserts the specified URL in the specified document.
378 * @param doc document in which to insert the text.
379 * @param url url to insert.
380 * @throws BadLocationException thrown if something wrong happened to the document.
381 */
382 private static void insertUrl(StyledDocument doc, String url) throws BadLocationException {
383 doc.insertString(doc.getLength(), " ", doc.getStyle(STYLE_NORMAL));
384 doc.insertString(doc.getLength(), url + LINE_BREAK, doc.getStyle(STYLE_URL));
385 }
386
387 /**
388 * Inserts a line break in the specified document.
389 * @param doc document in which to insert the text.
390 * @throws BadLocationException thrown if something wrong happened to the document.
391 */
392 private static void insertLineBreak(StyledDocument doc) throws BadLocationException {
393 doc.insertString(doc.getLength(), LINE_BREAK, doc.getStyle(STYLE_NORMAL));
394 }
395
396 /**
397 * Inserts the specified string, details and URL in the specified document.
398 * @param doc document in which to insert the text.
399 * @param string text to insert.
400 * @param details details that will be added to the text.
401 * @param url url that will be added to the text.
402 * @throws BadLocationException thrown if something wrong happened to the document.
403 */
404 private static void insertDetailedUrl(StyledDocument doc, String string, String details, String url) throws BadLocationException {
405 insertDetailedString(doc, string, details);
406 insertUrl(doc, url);
407 }
408
409 /**
410 * Inserts the specified title in the specified document.
411 * @param doc document in which to insert the text.
412 * @param string text to insert.
413 * @throws BadLocationException thrown if something wrong happened to the document.
414 */
415 private static void insertTitle(StyledDocument doc, String string) throws BadLocationException {
416 int pos;
417 Style style;
418
419 string += LINE_BREAK;
420 doc.insertString(pos = doc.getLength(), string, style = doc.getStyle(STYLE_TITLE));
421 doc.setParagraphAttributes(pos, string.length(), style, true);
422 doc.setParagraphAttributes(doc.getLength(), 0, doc.getStyle(STYLE_NORMAL), true);
423
424 insertLineBreak(doc);
425 }
426
427
428
429 // - Action listening -------------------------------------------------------
430 // --------------------------------------------------------------------------
431 /**
432 * Reacts to validations of the <code>OK</code> or <code>home</code> buttons.
433 */
434 public void actionPerformed(ActionEvent e) {
435 if(e.getSource() == okButton)
436 dispose();
437 else if(e.getSource() == homeButton) {
438 try {DesktopManager.browse(new URL(RuntimeConstants.HOMEPAGE_URL));}
439 // Ignores errors here as there really isn't anything we can do.
440 catch(IOException ignored) {}
441 }
442 else if(e.getSource() == licenseButton)
443 new LicenseDialog(this).showDialog();
444 }
445
446
447
448 // - Misc. methods ----------------------------------------------------------
449 // --------------------------------------------------------------------------
450 /**
451 * Returns a formatted version of muCommander's build date.
452 * @return a formatted version of muCommander's build date.
453 */
454 private String getFormatedDate() {
455 StringBuffer buffer;
456
457 buffer = new StringBuffer(RuntimeConstants.RELEASE_DATE.substring(0, 4));
458 buffer.append('/');
459 buffer.append(RuntimeConstants.RELEASE_DATE.substring(4, 6));
460 buffer.append('/');
461 buffer.append(RuntimeConstants.RELEASE_DATE.substring(6, 8));
462
463 return buffer.toString();
464 }
465
466 /**
467 * Creates a <code>JLabel</code> displaying the specified text using a bold font.
468 * @param text text to display in the label.
469 * @return a <code>JLabel</code> displaying the specified text using a bold font.
470 */
471 private JLabel createBoldLabel(String text) {
472 JLabel label;
473 Font font;
474
475 label = new JLabel(text);
476 font = label.getFont();
477 label.setFont(new Font(font.getFontName(), font.getStyle() | Font.BOLD, font.getSize()));
478
479 return label;
480 }
481
482 }