001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Color; 007import java.awt.Dimension; 008import java.awt.GridBagLayout; 009import java.awt.Image; 010import java.awt.event.ActionEvent; 011import java.awt.event.KeyEvent; 012import java.io.BufferedReader; 013import java.io.IOException; 014import java.io.InputStream; 015import java.io.InputStreamReader; 016 017import javax.swing.BorderFactory; 018import javax.swing.ImageIcon; 019import javax.swing.JLabel; 020import javax.swing.JOptionPane; 021import javax.swing.JPanel; 022import javax.swing.JScrollPane; 023import javax.swing.JTabbedPane; 024import javax.swing.JTextArea; 025 026import org.openstreetmap.josm.Main; 027import org.openstreetmap.josm.data.Version; 028import org.openstreetmap.josm.gui.util.GuiHelper; 029import org.openstreetmap.josm.gui.widgets.JMultilineLabel; 030import org.openstreetmap.josm.gui.widgets.JosmTextArea; 031import org.openstreetmap.josm.gui.widgets.UrlLabel; 032import org.openstreetmap.josm.plugins.PluginHandler; 033import org.openstreetmap.josm.tools.BugReportExceptionHandler; 034import org.openstreetmap.josm.tools.GBC; 035import org.openstreetmap.josm.tools.ImageProvider; 036import org.openstreetmap.josm.tools.Shortcut; 037import org.openstreetmap.josm.tools.Utils; 038 039/** 040 * Nice about screen. 041 * 042 * The REVISION resource is read and if present, it shows the revision information of the jar-file. 043 * 044 * @author imi 045 */ 046public class AboutAction extends JosmAction { 047 048 /** 049 * Constructs a new {@code AboutAction}. 050 */ 051 public AboutAction() { 052 super(tr("About"), "logo", tr("Display the about screen."), 053 Shortcut.registerShortcut("system:about", tr("About"), 054 KeyEvent.VK_F1, Shortcut.SHIFT), true); 055 } 056 057 @Override 058 public void actionPerformed(ActionEvent e) { 059 final JTabbedPane about = new JTabbedPane(); 060 061 Version version = Version.getInstance(); 062 063 JosmTextArea readme = new JosmTextArea(); 064 readme.setEditable(false); 065 setTextFromResourceFile(readme, "/README"); 066 readme.setCaretPosition(0); 067 068 JosmTextArea revision = new JosmTextArea(); 069 revision.setEditable(false); 070 revision.setText(version.getReleaseAttributes()); 071 revision.setCaretPosition(0); 072 073 JosmTextArea contribution = new JosmTextArea(); 074 contribution.setEditable(false); 075 setTextFromResourceFile(contribution, "/CONTRIBUTION"); 076 contribution.setCaretPosition(0); 077 078 JosmTextArea license = new JosmTextArea(); 079 license.setEditable(false); 080 setTextFromResourceFile(license, "/LICENSE"); 081 license.setCaretPosition(0); 082 083 JPanel info = new JPanel(new GridBagLayout()); 084 final JMultilineLabel label = new JMultilineLabel("<html>" + 085 "<h1>" + "JOSM – " + tr("Java OpenStreetMap Editor") + "</h1>" + 086 "<p style='font-size:75%'></p>" + 087 "<p>" + tr("Version {0}", version.getVersionString()) + "</p>" + 088 "<p style='font-size:50%'></p>" + 089 "<p>" + tr("Last change at {0}", version.getTime()) + "</p>" + 090 "<p style='font-size:50%'></p>" + 091 "<p>" + tr("Java Version {0}", System.getProperty("java.version")) + "</p>" + 092 "<p style='font-size:50%'></p>" + 093 "</html>"); 094 info.add(label, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 0, 0, 0)); 095 info.add(new JLabel(tr("Homepage")), GBC.std().insets(10, 0, 10, 0)); 096 info.add(new UrlLabel(Main.getJOSMWebsite(), 2), GBC.eol().fill(GBC.HORIZONTAL)); 097 info.add(GBC.glue(0, 5), GBC.eol()); 098 info.add(new JLabel(tr("Bug Reports")), GBC.std().insets(10, 0, 10, 0)); 099 info.add(BugReportExceptionHandler.getBugReportUrlLabel(Utils.strip(ShowStatusReportAction.getReportHeader())), 100 GBC.eol().fill(GBC.HORIZONTAL)); 101 102 about.addTab(tr("Info"), info); 103 about.addTab(tr("Readme"), createScrollPane(readme)); 104 about.addTab(tr("Revision"), createScrollPane(revision)); 105 about.addTab(tr("Contribution"), createScrollPane(contribution)); 106 about.addTab(tr("License"), createScrollPane(license)); 107 about.addTab(tr("Plugins"), new JScrollPane(PluginHandler.getInfoPanel())); 108 109 // Intermediate panel to allow proper optionPane resizing 110 JPanel panel = new JPanel(new GridBagLayout()); 111 panel.setPreferredSize(new Dimension(600, 300)); 112 panel.add(about, GBC.std().fill()); 113 114 GuiHelper.prepareResizeableOptionPane(panel, panel.getPreferredSize()); 115 JOptionPane.showMessageDialog(Main.parent, panel, tr("About JOSM..."), JOptionPane.INFORMATION_MESSAGE, 116 new ImageIcon(ImageProvider.get("logo.svg").getImage().getScaledInstance(256, 258, Image.SCALE_SMOOTH))); 117 } 118 119 /** 120 * Reads the contents of the resource file that is described by the {@code filePath}-attribute and puts that text 121 * into the {@link JTextArea} given by the {@code ta}-attribute. 122 * @param ta the {@link JTextArea} to put the files contents into 123 * @param filePath the path where the resource file to read resides 124 */ 125 private void setTextFromResourceFile(JTextArea ta, String filePath) { 126 InputStream is = getClass().getResourceAsStream(filePath); 127 if (is == null) { 128 displayErrorMessage(ta, tr("Failed to locate resource ''{0}''.", filePath)); 129 } else { 130 try { 131 BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8")); 132 String line; 133 while ((line = br.readLine()) != null) { 134 ta.append(line+'\n'); 135 } 136 br.close(); 137 } catch (IOException e) { 138 Main.warn(e); 139 displayErrorMessage(ta, tr("Failed to load resource ''{0}'', error is {1}.", filePath, e.toString())); 140 } 141 } 142 } 143 144 private static void displayErrorMessage(JTextArea ta, String msg) { 145 Main.warn(msg); 146 ta.setForeground(new Color(200, 0, 0)); 147 ta.setText(msg); 148 } 149 150 private static JScrollPane createScrollPane(JosmTextArea area) { 151 area.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 152 area.setOpaque(false); 153 JScrollPane sp = new JScrollPane(area); 154 sp.setBorder(null); 155 sp.setOpaque(false); 156 return sp; 157 } 158}