Ticket #3500: new_jmultiline.patch
| File new_jmultiline.patch, 9.1 KB (added by , 17 years ago) |
|---|
-
src/org/openstreetmap/josm/gui/JMultilineLabel.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 3 // This class was taken from4 // http://forum.java.sun.com/thread.jspa?threadID=459705&messageID=21040215 // - Removed hardcoded margin6 // - Added constructor7 8 3 package org.openstreetmap.josm.gui; 9 4 5 import java.awt.Component; 10 6 import java.awt.Dimension; 11 import java.awt.Graphics; 12 import java.awt.Graphics2D; 13 import java.awt.Insets; 14 import java.awt.font.FontRenderContext; 15 import java.awt.font.LineBreakMeasurer; 16 import java.awt.font.TextAttribute; 17 import java.awt.font.TextLayout; 18 import java.text.AttributedCharacterIterator; 19 import java.text.AttributedString; 7 import java.awt.Window; 20 8 21 import javax.swing.J Component;9 import javax.swing.JLabel; 22 10 23 public class JMultilineLabel extends JComponent { 24 private String text; 25 private int maxWidth = Integer.MAX_VALUE; 26 private boolean justify; 27 private final FontRenderContext frc = new FontRenderContext(null, false, false); 11 public class JMultilineLabel extends JLabel { 12 private Component parent = null; 28 13 29 public JMultilineLabel(String description) { 14 /** 15 * Constructs a normal label that wraps its text according to the limits of 16 * the containing <b>window</b>. 17 * @param text 18 */ 19 public JMultilineLabel(String text) 20 { 30 21 super(); 31 setText(description); 32 } 33 34 private void morph() { 35 revalidate(); 36 repaint(); 37 } 38 39 public String getText() { 40 return text; 41 } 42 43 public void setText(String text) { 44 String old = this.text; 45 this.text = text; 46 firePropertyChange("text", old, this.text); 47 if ((old == null) ? text!=null : !old.equals(text)) 48 morph(); 49 } 50 51 public int getMaxWidth() { 52 return maxWidth; 53 } 54 55 public void setMaxWidth(int maxWidth) { 56 if (maxWidth <= 0) 57 throw new IllegalArgumentException(); 58 int old = this.maxWidth; 59 this.maxWidth = maxWidth; 60 firePropertyChange("maxWidth", old, this.maxWidth); 61 if (old != this.maxWidth) 62 morph(); 22 text = text.trim().replaceAll("\n", "<br>"); 23 if(!text.startsWith("<html>")) { 24 text = "<html>" + text + "</html>"; 25 } 26 super.setText(text); 63 27 } 64 28 65 public boolean isJustified() { 66 return justify; 29 /** 30 * Set the maximum width. This is a convenience function for using the 31 * normal setMaximumSize() 32 * @param width 33 */ 34 public void setMaxWidth(int width) { 35 Dimension superDim = super.getMaximumSize(); 36 super.setMaximumSize(new Dimension(width, superDim.height)); 67 37 } 68 38 69 public void setJustified(boolean justify) { 70 boolean old = this.justify; 71 this.justify = justify; 72 firePropertyChange("justified", old, this.justify); 73 if (old != this.justify) 74 repaint(); 75 } 39 /** 40 * This overridden getPrefferedSize will try to find its parent window and 41 * derive its width from that. If none can be found, it will behave exactly 42 * as a normal 1-line label. 43 */ 44 @Override 45 public Dimension getPreferredSize() 46 { 47 Dimension superPreferred=super.getPreferredSize(); 76 48 77 public Dimension getPreferredSize() { 78 return paintOrGetSize(null, getMaxWidth()); 79 } 49 // Find outer Frame 50 if(this.parent == null) { 51 this.parent = this.getParent(); 52 while(this.parent.getParent() != null && !(this.parent instanceof Window)) { 53 this.parent = this.parent.getParent(); 54 } 55 } 80 56 81 public Dimension getMinimumSize() { 82 return getPreferredSize(); 83 } 57 if(this.parent == null) 58 return superPreferred; 84 59 85 protected void paintComponent(Graphics g) { 86 super.paintComponent(g); 87 paintOrGetSize((Graphics2D)g, getWidth()); 88 } 60 int width; 61 // We can only get the bounds if the window is visible, otherwise they 62 // will be 0. We cannot poll getPreferredSize because this will lead to 63 // infinite recursion as this function will be called again 64 if(parent.isVisible()) { 65 // This is different from getWidth() as it returns the actual outer 66 // size while getWidth() returns the size as required by the 67 // contained components 68 width = parent.getBounds().width; 69 } else { 70 width = parent.getMaximumSize().width; 71 } 89 72 90 private Dimension paintOrGetSize(Graphics2D g, int width) { 91 Insets insets = getInsets(); 92 width -= insets.left + insets.right; 93 float w = insets.left + insets.right; 94 float x = insets.left, y=insets.top; 73 width -= getInsets().left + getInsets().right; 95 74 96 if (width > 0 && text != null && text.length() > 0) { 97 String[] lines = getText().split("\n"); 98 for(String line : lines) { 99 // Insert a space so new lines get rendered 100 if(line.length() == 0) line = " "; 101 AttributedString as = new AttributedString(line); 102 as.addAttribute(TextAttribute.FONT, getFont()); 103 AttributedCharacterIterator aci = as.getIterator(); 104 LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc); 105 float max = 0; 106 while (lbm.getPosition() < aci.getEndIndex()) { 107 TextLayout textLayout = lbm.nextLayout(width); 108 if (g != null && isJustified() && textLayout.getVisibleAdvance() > 0.80 * width) 109 textLayout = textLayout.getJustifiedLayout(width); 110 if (g != null) 111 textLayout.draw(g, x, y + textLayout.getAscent()); 112 y += textLayout.getDescent() + textLayout.getLeading() + textLayout.getAscent(); 113 max = Math.max(max, textLayout.getVisibleAdvance()); 114 } 115 w = Math.max(max, w); 116 } 117 } 118 return new Dimension((int)Math.ceil(w), (int)Math.ceil(y) + insets.bottom); 75 // Make the label not larger than required 76 return new Dimension( 77 Math.min(width, superPreferred.width), 78 superPreferred.height 79 ); 119 80 } 120 81 } -
src/org/openstreetmap/josm/gui/ExtendedDialog.java
134 134 * @param message The text that should be shown to the user 135 135 */ 136 136 public void setContent(String message) { 137 setContent(string2label(message), true);137 setContent(string2label(message), false); 138 138 } 139 139 140 140 /** … … 291 291 public void setVisible(boolean visible) { 292 292 if (visible) { 293 293 repaint(); 294 } 295 296 // Ensure all required variables are available 297 if(!rememberSizePref.isEmpty() && defaultWindowGeometry != null) { 298 if(visible) { 299 new WindowGeometry(rememberSizePref, 300 defaultWindowGeometry).apply(this); 301 } else { 302 new WindowGeometry(this).remember(rememberSizePref); 294 if(!rememberSizePref.isEmpty() && defaultWindowGeometry != null) { 295 new WindowGeometry(rememberSizePref, defaultWindowGeometry).apply(this); 303 296 } 304 297 } 305 298 super.setVisible(visible); … … 310 303 * Set the pref to <code>null</code> or to an empty string to disable again. 311 304 * By default, it's disabled. 312 305 * 313 * Note: If you want to set the width of this dialog directly use the usual314 * setSize, setPreferredSize, setMaxSize, setMinSize315 *316 306 * @param pref The preference to save the dimension to 317 307 * @param wg The default window geometry that should be used if no 318 308 * existing preference is found (only takes effect if 319 309 * <code>pref</code> is not null or empty 320 310 * 311 * Note: If you want to set the width of this dialog directly use the usual 312 * setSize, setPreferredSize, setMaxSize, setMinSize 321 313 */ 322 314 public void setRememberWindowGeometry(String pref, WindowGeometry wg) { 323 315 rememberSizePref = pref == null ? "" : pref; … … 387 379 */ 388 380 private static JMultilineLabel string2label(String msg) { 389 381 JMultilineLabel lbl = new JMultilineLabel(msg); 390 // Make it not wider than 2/3of the screen382 // Make it not wider than 1/2 of the screen 391 383 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 392 lbl.setMaxWidth(Math.round(screenSize.width* 2/3));384 lbl.setMaxWidth(Math.round(screenSize.width*1/2)); 393 385 return lbl; 394 386 } 395 387 } 388 No newline at end of file
