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