001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.widgets; 003 004import java.awt.Color; 005import java.awt.Font; 006import java.io.IOException; 007import java.io.InputStream; 008import java.net.URL; 009import java.net.URLConnection; 010import java.text.MessageFormat; 011 012import javax.swing.JEditorPane; 013import javax.swing.LookAndFeel; 014import javax.swing.UIDefaults; 015import javax.swing.UIManager; 016import javax.swing.text.html.StyleSheet; 017 018import org.openstreetmap.josm.Main; 019import org.openstreetmap.josm.gui.util.GuiHelper; 020import org.openstreetmap.josm.tools.Utils; 021 022/** 023 * Subclass of {@link JEditorPane} that adds a "native" context menu (cut/copy/paste/select all) 024 * and effectively uses JOSM user agent when performing HTTP request in {@link #setPage(URL)} method. 025 * @since 5886 026 */ 027public class JosmEditorPane extends JEditorPane { 028 029 /** 030 * Creates a new <code>JosmEditorPane</code>. 031 * The document model is set to <code>null</code>. 032 */ 033 public JosmEditorPane() { 034 TextContextualPopupMenu.enableMenuFor(this); 035 } 036 037 /** 038 * Creates a <code>JosmEditorPane</code> based on a specified URL for input. 039 * 040 * @param initialPage the URL 041 * @exception IOException if the URL is <code>null</code> or cannot be accessed 042 */ 043 public JosmEditorPane(URL initialPage) throws IOException { 044 this(); 045 setPage(initialPage); 046 } 047 048 /** 049 * Creates a <code>JosmEditorPane</code> based on a string containing 050 * a URL specification. 051 * 052 * @param url the URL 053 * @exception IOException if the URL is <code>null</code> or cannot be accessed 054 */ 055 public JosmEditorPane(String url) throws IOException { 056 this(); 057 setPage(url); 058 } 059 060 /** 061 * Creates a <code>JosmEditorPane</code> that has been initialized 062 * to the given text. This is a convenience constructor that calls the 063 * <code>setContentType</code> and <code>setText</code> methods. 064 * 065 * @param type mime type of the given text 066 * @param text the text to initialize with; may be <code>null</code> 067 * @exception NullPointerException if the <code>type</code> parameter 068 * is <code>null</code> 069 */ 070 public JosmEditorPane(String type, String text) { 071 this(); 072 setContentType(type); 073 setText(text); 074 } 075 076 @Override 077 protected InputStream getStream(URL page) throws IOException { 078 URLConnection conn = Utils.setupURLConnection(page.openConnection()); 079 InputStream result = conn.getInputStream(); 080 String type = conn.getContentType(); 081 if (type != null) { 082 setContentType(type); 083 } 084 return result; 085 } 086 087 /** 088 * Adapts a {@link JEditorPane} to be used as a powerful replacement of {@link javax.swing.JLabel}. 089 * @param pane The editor pane to adapt 090 * @param allBold If {@code true}, makes all text to be displayed in bold 091 */ 092 public static void makeJLabelLike(JEditorPane pane, boolean allBold) { 093 pane.setContentType("text/html"); 094 pane.setOpaque(false); 095 pane.setEditable(false); 096 adaptForNimbus(pane); 097 098 JosmHTMLEditorKit kit = new JosmHTMLEditorKit(); 099 final Font f = UIManager.getFont("Label.font"); 100 final StyleSheet ss = new StyleSheet(); 101 ss.addRule((allBold ? "html" : "strong, b") + " {" + getFontRule(f) + "}"); 102 ss.addRule("a {text-decoration: underline; color: blue}"); 103 ss.addRule("h1 {" + getFontRule(GuiHelper.getTitleFont()) + "}"); 104 ss.addRule("ol {margin-left: 1cm; margin-top: 0.1cm; margin-bottom: 0.2cm; list-style-type: decimal}"); 105 ss.addRule("ul {margin-left: 1cm; margin-top: 0.1cm; margin-bottom: 0.2cm; list-style-type: disc}"); 106 if ("km".equals(Main.pref.get("language"))) { 107 // Fix rendering problem for Khmer script 108 ss.addRule("p {" + getFontRule(UIManager.getFont("Label.font")) + "}"); 109 } 110 kit.setStyleSheet(ss); 111 pane.setEditorKit(kit); 112 } 113 114 /** 115 * Adapts a {@link JEditorPane} for Nimbus look and feel. 116 * See <a href="https://stackoverflow.com/q/15228336/2257172">this StackOverflow question</a>. 117 * @param pane The editor pane to adapt 118 * @since 6935 119 */ 120 public static void adaptForNimbus(JEditorPane pane) { 121 LookAndFeel currentLAF = UIManager.getLookAndFeel(); 122 if (currentLAF != null && "Nimbus".equals(currentLAF.getName())) { 123 Color bgColor = UIManager.getColor("Label.background"); 124 UIDefaults defaults = new UIDefaults(); 125 defaults.put("EditorPane[Enabled].backgroundPainter", bgColor); 126 pane.putClientProperty("Nimbus.Overrides", defaults); 127 pane.putClientProperty("Nimbus.Overrides.InheritDefaults", true); 128 pane.setBackground(bgColor); 129 } 130 } 131 132 private static String getFontRule(Font f) { 133 return MessageFormat.format( 134 "font-family: ''{0}'';font-size: {1,number}pt; font-weight: {2}; font-style: {3}", 135 f.getName(), 136 f.getSize(), 137 "bold", 138 f.isItalic() ? "italic" : "normal" 139 ); 140 } 141}