source: josm/trunk/src/org/openstreetmap/josm/actions/AboutAction.java

Last change on this file was 18585, checked in by Don-vip, 20 months ago

fix #22489 - display mastodon account in about dialog

  • Property svn:eol-style set to native
File size: 11.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static java.awt.GridBagConstraints.HORIZONTAL;
5import static javax.swing.SwingConstants.CENTER;
6import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
7import static org.openstreetmap.josm.tools.I18n.tr;
8import static org.openstreetmap.josm.tools.Utils.getSystemProperty;
9
10import java.awt.Color;
11import java.awt.Dimension;
12import java.awt.FlowLayout;
13import java.awt.Font;
14import java.awt.GridBagLayout;
15import java.awt.event.ActionEvent;
16import java.awt.event.KeyEvent;
17import java.io.BufferedReader;
18import java.io.File;
19import java.io.IOException;
20import java.io.InputStream;
21import java.io.InputStreamReader;
22import java.nio.charset.StandardCharsets;
23import java.util.Map.Entry;
24
25import javax.swing.AbstractAction;
26import javax.swing.Action;
27import javax.swing.BorderFactory;
28import javax.swing.JButton;
29import javax.swing.JLabel;
30import javax.swing.JPanel;
31import javax.swing.JScrollPane;
32import javax.swing.JTabbedPane;
33import javax.swing.JTextArea;
34
35import org.openstreetmap.josm.data.Preferences;
36import org.openstreetmap.josm.data.Version;
37import org.openstreetmap.josm.gui.ExtendedDialog;
38import org.openstreetmap.josm.gui.MainApplication;
39import org.openstreetmap.josm.gui.util.GuiHelper;
40import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
41import org.openstreetmap.josm.gui.widgets.JosmTextArea;
42import org.openstreetmap.josm.gui.widgets.UrlLabel;
43import org.openstreetmap.josm.plugins.PluginHandler;
44import org.openstreetmap.josm.spi.preferences.Config;
45import org.openstreetmap.josm.tools.GBC;
46import org.openstreetmap.josm.tools.ImageProvider;
47import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
48import org.openstreetmap.josm.tools.Logging;
49import org.openstreetmap.josm.tools.OpenBrowser;
50import org.openstreetmap.josm.tools.Shortcut;
51import org.openstreetmap.josm.tools.Utils;
52
53/**
54 * Nice about screen.
55 *
56 * The REVISION resource is read and if present, it shows the revision information of the jar-file.
57 *
58 * @author imi
59 */
60public final class AboutAction extends JosmAction {
61
62 /**
63 * Constructs a new {@code AboutAction}.
64 */
65 public AboutAction() {
66 super(tr("About"), "logo", tr("Display the about screen."),
67 Shortcut.registerShortcut("system:about", tr("Help: {0}", tr("About")),
68 KeyEvent.VK_F1, Shortcut.SHIFT), true, false);
69 }
70
71 JPanel buildAboutPanel() {
72 final JTabbedPane about = new JTabbedPane();
73
74 Version version = Version.getInstance();
75
76 JosmTextArea readme = new JosmTextArea();
77 readme.setFont(GuiHelper.getMonospacedFont(readme));
78 readme.setEditable(false);
79 setTextFromResourceFile(readme, "/README");
80 readme.setCaretPosition(0);
81
82 JosmTextArea revision = new JosmTextArea();
83 revision.setFont(GuiHelper.getMonospacedFont(revision));
84 revision.setEditable(false);
85 revision.setText(version.getReleaseAttributes());
86 revision.setCaretPosition(0);
87
88 JosmTextArea contribution = new JosmTextArea();
89 contribution.setEditable(false);
90 setTextFromResourceFile(contribution, "/CONTRIBUTION");
91 contribution.setCaretPosition(0);
92
93 JosmTextArea license = new JosmTextArea();
94 license.setEditable(false);
95 setTextFromResourceFile(license, "/LICENSE");
96 license.setCaretPosition(0);
97
98 JPanel info = new JPanel(new GridBagLayout());
99 final JMultilineLabel label = new JMultilineLabel("<html>" +
100 "<h1>" + "JOSM – " + tr("Java OpenStreetMap Editor") + "</h1>" +
101 "<p style='font-size:75%'></p>" +
102 "<p>" + tr("Version {0}", version.getVersionString()) + "</p>" +
103 "<p style='font-size:50%'></p>" +
104 "<p>" + tr("Last change at {0}", version.getTime()) + "</p>" +
105 "<p style='font-size:50%'></p>" +
106 "<p>" + tr("Java Version {0}", getSystemProperty("java.version")) + "</p>" +
107 "<p style='font-size:50%'></p>" +
108 "</html>");
109 info.add(label, GBC.eol().fill(HORIZONTAL).insets(10, 0, 0, 10));
110 info.add(new JLabel(tr("Homepage")), GBC.std().insets(10, 0, 10, 0));
111 info.add(new UrlLabel(Config.getUrls().getJOSMWebsite(), 2), GBC.eol());
112 info.add(new JLabel(tr("Translations")), GBC.std().insets(10, 0, 10, 0));
113 info.add(new UrlLabel("https://translations.launchpad.net/josm", 2), GBC.eol());
114 info.add(new JLabel(tr("Follow us on")), GBC.std().insets(10, 10, 10, 0));
115 JPanel logos = new JPanel(new FlowLayout());
116 logos.add(createImageLink("OpenStreetMap", /* ICON(dialogs/about/) */ "openstreetmap",
117 "https://www.openstreetmap.org/user/josmeditor/diary"));
118 logos.add(createImageLink("Mastodon", /* ICON(dialogs/about/) */ "mastodon", "https://en.osm.town/@josmeditor"));
119 logos.add(createImageLink("Twitter", /* ICON(dialogs/about/) */ "twitter-square", "https://twitter.com/josmeditor"));
120 logos.add(createImageLink("Facebook", /* ICON(dialogs/about/) */ "facebook-square", "https://www.facebook.com/josmeditor"));
121 logos.add(createImageLink("GitHub", /* ICON(dialogs/about/) */ "github-square", "https://github.com/JOSM"));
122 info.add(logos, GBC.eol().insets(0, 10, 0, 0));
123 info.add(GBC.glue(0, 5), GBC.eol());
124
125 JPanel inst = new JPanel(new GridBagLayout());
126 inst.add(new JLabel(tr("Preferences are stored in {0}", getPathToPreferences())), GBC.eol().insets(0, 0, 0, 10));
127 inst.add(new JLabel(tr("Symbolic names for directories and the actual paths:")),
128 GBC.eol().insets(0, 0, 0, 10));
129 for (Entry<String, String> entry : ShowStatusReportAction.getAnonimicDirectorySymbolMap().entrySet()) {
130 addInstallationLine(inst, entry.getValue(), entry.getKey());
131 }
132
133 about.addTab(tr("Info"), info);
134 about.addTab(tr("Readme"), createScrollPane(readme));
135 about.addTab(tr("Revision"), createScrollPane(revision));
136 about.addTab(tr("Contribution"), createScrollPane(contribution));
137 about.addTab(tr("License"), createScrollPane(license));
138 about.addTab(tr("Plugins"), new JScrollPane(PluginHandler.getInfoPanel()));
139 about.addTab(tr("Installation Details"), inst);
140
141 // Get the list of Launchpad contributors using customary msgid “translator-credits”
142 String translators = tr("translator-credits");
143 if (!Utils.isEmpty(translators) && !"translator-credits".equals(translators)) {
144 about.addTab(tr("Translators"), createScrollPane(new JosmTextArea(translators)));
145 }
146
147 // Intermediate panel to allow proper optionPane resizing
148 JPanel panel = new JPanel(new GridBagLayout());
149 panel.setPreferredSize(new Dimension(890, 300));
150 panel.add(new JLabel("", ImageProvider.get("logo.svg", ImageSizes.ABOUT_LOGO), CENTER), GBC.std().insets(0, 5, 0, 0));
151 panel.add(about, GBC.std().fill());
152 return panel;
153 }
154
155 private static String getPathToPreferences() {
156 File preferenceFile = Preferences.main().getPreferenceFile();
157 try {
158 return ShowStatusReportAction.paramCleanup(preferenceFile.getAbsolutePath());
159 } catch (SecurityException e) {
160 Logging.warn(e);
161 return ShowStatusReportAction.paramCleanup(preferenceFile.getPath());
162 }
163 }
164
165 @Override
166 public void actionPerformed(ActionEvent e) {
167 JPanel panel = buildAboutPanel();
168
169 GuiHelper.prepareResizeableOptionPane(panel, panel.getPreferredSize());
170 ExtendedDialog dlg = new ExtendedDialog(MainApplication.getMainFrame(), tr("About JOSM..."), tr("OK"), tr("Report bug"));
171 int ret = dlg.setButtonIcons("ok", "bug")
172 .configureContextsensitiveHelp(ht("Action/About"), true)
173 .setContent(panel, false)
174 .showDialog().getValue();
175 if (2 == ret) {
176 MainApplication.getMenu().reportbug.actionPerformed(null);
177 }
178 GuiHelper.destroyComponents(panel, false);
179 dlg.dispose();
180 }
181
182 private static class OpenDirAction extends AbstractAction {
183 final String dir;
184
185 OpenDirAction(String dir) {
186 putValue(Action.NAME, "...");
187 this.dir = dir;
188 try {
189 setEnabled(dir != null && new File(dir).isDirectory());
190 } catch (SecurityException e) {
191 setEnabled(false);
192 Logging.warn(e);
193 }
194 }
195
196 @Override
197 public void actionPerformed(ActionEvent e) {
198 OpenBrowser.displayUrl(new File(dir).toURI());
199 }
200 }
201
202 /**
203 * Add line to installation details showing symbolic name used in status report and actual directory.
204 * @param inst the panel
205 * @param dir the actual path represented by a symbol
206 * @param source source for symbol
207 */
208 private static void addInstallationLine(JPanel inst, String dir, String source) {
209 if (source == null)
210 return;
211 JLabel symbol = new JLabel(source);
212 symbol.setFont(GuiHelper.getMonospacedFont(symbol));
213 JosmTextArea dirLabel = new JosmTextArea();
214 if (!Utils.isEmpty(dir)) {
215 dirLabel.setText(dir);
216 dirLabel.setEditable(false);
217 } else {
218 dirLabel.setText("<" + tr("unset") + ">");
219 dirLabel.setFont(dirLabel.getFont().deriveFont(Font.ITALIC));
220 dirLabel.setEditable(false);
221 }
222 inst.add(symbol, GBC.std().insets(5, 0, 0, 0));
223 inst.add(GBC.glue(10, 0), GBC.std());
224 dirLabel.setFont(GuiHelper.getMonospacedFont(dirLabel));
225 dirLabel.setOpaque(false);
226 inst.add(dirLabel, GBC.std().fill(HORIZONTAL));
227 JButton btn = new JButton(new OpenDirAction(dir));
228 btn.setToolTipText(tr("Open directory"));
229 inst.add(btn, GBC.eol().insets(0, 0, 5, 0));
230 }
231
232 private static JLabel createImageLink(String tooltip, String icon, final String link) {
233 return new UrlLabel(link, tooltip, ImageProvider.get("dialogs/about", icon, ImageSizes.LARGEICON));
234 }
235
236 /**
237 * Reads the contents of the resource file that is described by the {@code filePath}-attribute and puts that text
238 * into the {@link JTextArea} given by the {@code ta}-attribute.
239 * @param ta the {@link JTextArea} to put the files contents into
240 * @param filePath the path where the resource file to read resides
241 */
242 private void setTextFromResourceFile(JTextArea ta, String filePath) {
243 InputStream is = Utils.getResourceAsStream(getClass(), filePath);
244 if (is == null) {
245 displayErrorMessage(ta, tr("Failed to locate resource ''{0}''.", filePath));
246 } else {
247 try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
248 String line;
249 while ((line = br.readLine()) != null) {
250 ta.append(line+'\n');
251 }
252 } catch (IOException e) {
253 Logging.warn(e);
254 displayErrorMessage(ta, tr("Failed to load resource ''{0}'', error is {1}.", filePath, e.toString()));
255 }
256 }
257 }
258
259 private static void displayErrorMessage(JTextArea ta, String msg) {
260 Logging.warn(msg);
261 ta.setForeground(new Color(200, 0, 0));
262 ta.setText(msg);
263 }
264
265 private static JScrollPane createScrollPane(JosmTextArea area) {
266 area.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
267 area.setOpaque(false);
268 JScrollPane sp = new JScrollPane(area);
269 sp.setBorder(null);
270 sp.setOpaque(false);
271 return sp;
272 }
273}
Note: See TracBrowser for help on using the repository browser.