source: josm/trunk/src/org/openstreetmap/josm/gui/GettingStarted.java@ 13753

Last change on this file since 13753 was 13647, checked in by Don-vip, 6 years ago

see #16204 - Allow to start and close JOSM in WebStart sandbox mode (where every external access is denied). This was very useful to reproduce some very tricky bugs that occured in real life but were almost impossible to diagnose.

  • Property svn:eol-style set to native
File size: 7.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.EventQueue;
8import java.io.IOException;
9import java.net.URL;
10import java.nio.charset.StandardCharsets;
11import java.util.regex.Matcher;
12import java.util.regex.Pattern;
13
14import javax.swing.JComponent;
15import javax.swing.JPanel;
16import javax.swing.JScrollPane;
17import javax.swing.border.EmptyBorder;
18import javax.swing.event.HyperlinkEvent;
19import javax.swing.event.HyperlinkListener;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.actions.DownloadPrimitiveAction;
23import org.openstreetmap.josm.data.Version;
24import org.openstreetmap.josm.gui.datatransfer.OpenTransferHandler;
25import org.openstreetmap.josm.gui.dialogs.MenuItemSearchDialog;
26import org.openstreetmap.josm.gui.preferences.server.ProxyPreference;
27import org.openstreetmap.josm.gui.preferences.server.ProxyPreferenceListener;
28import org.openstreetmap.josm.gui.widgets.JosmEditorPane;
29import org.openstreetmap.josm.io.CacheCustomContent;
30import org.openstreetmap.josm.io.OnlineResource;
31import org.openstreetmap.josm.spi.preferences.Config;
32import org.openstreetmap.josm.tools.LanguageInfo;
33import org.openstreetmap.josm.tools.Logging;
34import org.openstreetmap.josm.tools.OpenBrowser;
35import org.openstreetmap.josm.tools.Utils;
36import org.openstreetmap.josm.tools.WikiReader;
37
38/**
39 * Panel that fills the main part of the program window when JOSM has just started.
40 *
41 * It downloads and displays the so called <em>message of the day</em>, which
42 * contains news about recent major changes, warning in case of outdated versions, etc.
43 */
44public final class GettingStarted extends JPanel implements ProxyPreferenceListener {
45
46 private final LinkGeneral lg;
47 private String content = "";
48 private boolean contentInitialized;
49
50 private static final String STYLE = "<style type=\"text/css\">\n"
51 + "body {font-family: sans-serif; font-weight: bold; }\n"
52 + "h1 {text-align: center; }\n"
53 + ".icon {font-size: 0; }\n"
54 + "</style>\n";
55
56 public static class LinkGeneral extends JosmEditorPane implements HyperlinkListener {
57
58 /**
59 * Constructs a new {@code LinkGeneral} with the given HTML text
60 * @param text The text to display
61 */
62 public LinkGeneral(String text) {
63 setContentType("text/html");
64 setText(text);
65 setEditable(false);
66 setOpaque(false);
67 addHyperlinkListener(this);
68 adaptForNimbus(this);
69 }
70
71 @Override
72 public void hyperlinkUpdate(HyperlinkEvent e) {
73 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
74 OpenBrowser.displayUrl(e.getDescription());
75 }
76 }
77 }
78
79 /**
80 * Grabs current MOTD from cache or webpage and parses it.
81 */
82 static class MotdContent extends CacheCustomContent<IOException> {
83 MotdContent() {
84 super("motd.html", CacheCustomContent.INTERVAL_DAILY);
85 }
86
87 private final int myVersion = Version.getInstance().getVersion();
88 private final String myJava = Utils.getSystemProperty("java.version");
89 private final String myLang = LanguageInfo.getWikiLanguagePrefix();
90
91 /**
92 * This function gets executed whenever the cached files need updating
93 * @see org.openstreetmap.josm.io.CacheCustomContent#updateData()
94 */
95 @Override
96 protected byte[] updateData() throws IOException {
97 String motd = new WikiReader().readLang("StartupPage");
98 // Save this to prefs in case JOSM is updated so MOTD can be refreshed
99 Config.getPref().putInt("cache.motd.html.version", myVersion);
100 Config.getPref().put("cache.motd.html.java", myJava);
101 Config.getPref().put("cache.motd.html.lang", myLang);
102 return motd.getBytes(StandardCharsets.UTF_8);
103 }
104
105 @Override
106 protected void checkOfflineAccess() {
107 OnlineResource.JOSM_WEBSITE.checkOfflineAccess(new WikiReader().getBaseUrlWiki(), Main.getJOSMWebsite());
108 }
109
110 /**
111 * Additionally check if JOSM has been updated and refresh MOTD
112 */
113 @Override
114 protected boolean isCacheValid() {
115 // We assume a default of myVersion because it only kicks in in two cases:
116 // 1. Not yet written - but so isn't the interval variable, so it gets updated anyway
117 // 2. Cannot be written (e.g. while developing). Obviously we don't want to update
118 // everytime because of something we can't read.
119 return (Config.getPref().getInt("cache.motd.html.version", -999) == myVersion)
120 && Config.getPref().get("cache.motd.html.java").equals(myJava)
121 && Config.getPref().get("cache.motd.html.lang").equals(myLang);
122 }
123 }
124
125 /**
126 * Initializes getting the MOTD as well as enabling the FileDrop Listener. Displays a message
127 * while the MOTD is downloading.
128 */
129 public GettingStarted() {
130 super(new BorderLayout());
131 lg = new LinkGeneral("<html>" + STYLE + "<h1>" + "JOSM - " + tr("Java OpenStreetMap Editor")
132 + "</h1><h2 align=\"center\">" + tr("Downloading \"Message of the day\"") + "</h2></html>");
133 // clear the build-in command ctrl+shift+O, ctrl+space because it is used as shortcut in JOSM
134 lg.getInputMap(JComponent.WHEN_FOCUSED).put(DownloadPrimitiveAction.SHORTCUT.getKeyStroke(), "none");
135 lg.getInputMap(JComponent.WHEN_FOCUSED).put(MenuItemSearchDialog.Action.SHORTCUT.getKeyStroke(), "none");
136 lg.setTransferHandler(null);
137
138 JScrollPane scroller = new JScrollPane(lg);
139 scroller.setViewportBorder(new EmptyBorder(10, 100, 10, 100));
140 add(scroller, BorderLayout.CENTER);
141
142 getMOTD();
143
144 setTransferHandler(new OpenTransferHandler());
145 }
146
147 private void getMOTD() {
148 // Asynchronously get MOTD to speed-up JOSM startup
149 Thread t = new Thread((Runnable) () -> {
150 if (!contentInitialized && Config.getPref().getBoolean("help.displaymotd", true)) {
151 try {
152 content = new MotdContent().updateIfRequiredString();
153 contentInitialized = true;
154 ProxyPreference.removeProxyPreferenceListener(this);
155 } catch (IOException ex) {
156 Logging.log(Logging.LEVEL_WARN, tr("Failed to read MOTD. Exception was: {0}", ex.toString()), ex);
157 content = "<html>" + STYLE + "<h1>" + "JOSM - " + tr("Java OpenStreetMap Editor")
158 + "</h1>\n<h2 align=\"center\">(" + tr("Message of the day not available") + ")</h2></html>";
159 // In case of MOTD not loaded because of proxy error, listen to preference changes to retry after update
160 ProxyPreference.addProxyPreferenceListener(this);
161 }
162 }
163
164 if (content != null) {
165 EventQueue.invokeLater(() -> lg.setText(fixImageLinks(content)));
166 }
167 }, "MOTD-Loader");
168 t.setDaemon(true);
169 t.start();
170 }
171
172 static String fixImageLinks(String s) {
173 Matcher m = Pattern.compile("src=\"/browser/trunk(/images/.*?\\.png)\\?format=raw\"").matcher(s);
174 StringBuffer sb = new StringBuffer();
175 while (m.find()) {
176 String im = m.group(1);
177 URL u = GettingStarted.class.getResource(im);
178 if (u != null) {
179 m.appendReplacement(sb, Matcher.quoteReplacement("src=\"" + u + '\"'));
180 }
181 }
182 m.appendTail(sb);
183 return sb.toString();
184 }
185
186 @Override
187 public void proxyPreferenceChanged() {
188 getMOTD();
189 }
190}
Note: See TracBrowser for help on using the repository browser.