GNU Classpath (0.95) | |
Frames | No Frames |
1: /* InlineView.java -- Renders HTML content 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing.text.html; 40: 41: import java.awt.FontMetrics; 42: import java.awt.Shape; 43: import java.text.BreakIterator; 44: 45: import javax.swing.event.DocumentEvent; 46: import javax.swing.text.AttributeSet; 47: import javax.swing.text.BadLocationException; 48: import javax.swing.text.Document; 49: import javax.swing.text.Element; 50: import javax.swing.text.LabelView; 51: import javax.swing.text.Segment; 52: import javax.swing.text.View; 53: import javax.swing.text.ViewFactory; 54: 55: /** 56: * Renders HTML content (identified by {@link HTML.Tag#CONTENT}). This is 57: * basically a {@link LabelView} that is adjusted to understand styles defined 58: * by stylesheets. 59: * 60: * @author Roman Kennke (kennke@aicas.com) 61: */ 62: public class InlineView 63: extends LabelView 64: { 65: 66: /** 67: * The attributes used by this view. 68: */ 69: private AttributeSet attributes; 70: 71: /** 72: * The span of the longest word in this view. 73: * 74: * @see #getLongestWord() 75: */ 76: private float longestWord; 77: 78: /** 79: * Indicates if we may wrap or not. 80: */ 81: private boolean nowrap; 82: 83: /** 84: * Creates a new <code>InlineView</code> that renders the specified element. 85: * 86: * @param element the element for this view 87: */ 88: public InlineView(Element element) 89: { 90: super(element); 91: } 92: 93: /** 94: * Receives notification that something was inserted into the document in 95: * a location that this view is responsible for. 96: * 97: * @param e the document event 98: * @param a the current allocation of this view 99: * @param f the view factory for creating new views 100: * 101: * @since 1.5 102: */ 103: public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) 104: { 105: // FIXME: What to do here? 106: super.insertUpdate(e, a, f); 107: } 108: 109: /** 110: * Receives notification that something was removed from the document in 111: * a location that this view is responsible for. 112: * 113: * @param e the document event 114: * @param a the current allocation of this view 115: * @param f the view factory for creating new views 116: * 117: * @since 1.5 118: */ 119: public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) 120: { 121: // FIXME: What to do here? 122: super.removeUpdate(e, a, f); 123: } 124: 125: /** 126: * Receives notification that attributes have changed in the document in 127: * a location that this view is responsible for. This calls 128: * {@link #setPropertiesFromAttributes}. 129: * 130: * @param e the document event 131: * @param a the current allocation of this view 132: * @param f the view factory for creating new views 133: * 134: * @since 1.5 135: */ 136: public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) 137: { 138: super.changedUpdate(e, a, f); 139: StyleSheet ss = getStyleSheet(); 140: attributes = ss.getViewAttributes(this); 141: preferenceChanged(null, true, true); 142: setPropertiesFromAttributes(); 143: } 144: 145: /** 146: * Returns the attributes that are used for rendering. This is implemented 147: * to multiplex the attributes specified in the model with a stylesheet. 148: * 149: * @return the attributes that are used for rendering 150: */ 151: public AttributeSet getAttributes() 152: { 153: if (attributes == null) 154: { 155: StyleSheet ss = getStyleSheet(); 156: attributes = ss.getViewAttributes(this); 157: } 158: return attributes; 159: } 160: 161: 162: public int getBreakWeight(int axis, float pos, float len) 163: { 164: int weight; 165: if (nowrap) 166: weight = BadBreakWeight; 167: else 168: weight = super.getBreakWeight(axis, pos, len); 169: return weight; 170: } 171: 172: public View breakView(int axis, int offset, float pos, float len) 173: { 174: // FIXME: Implement this. 175: return super.breakView(axis, offset, pos, len); 176: } 177: 178: /** 179: * Loads the character style properties from the stylesheet. 180: */ 181: protected void setPropertiesFromAttributes() 182: { 183: super.setPropertiesFromAttributes(); 184: AttributeSet atts = getAttributes(); 185: Object o = atts.getAttribute(CSS.Attribute.TEXT_DECORATION); 186: 187: // Check for underline. 188: boolean b = false; 189: if (o != null && o.toString().contains("underline")) 190: b = true; 191: setUnderline(b); 192: 193: // Check for line-through. 194: b = false; 195: if (o != null && o.toString().contains("line-through")) 196: b = true; 197: setStrikeThrough(b); 198: 199: // Check for vertical alignment (subscript/superscript). 200: o = atts.getAttribute(CSS.Attribute.VERTICAL_ALIGN); 201: 202: // Subscript. 203: b = false; 204: if (o != null && o.toString().contains("sub")) 205: b = true; 206: setSubscript(b); 207: 208: // Superscript. 209: b = false; 210: if (o != null && o.toString().contains("sup")) 211: b = true; 212: setSuperscript(b); 213: 214: // Fetch nowrap setting. 215: o = atts.getAttribute(CSS.Attribute.WHITE_SPACE); 216: if (o != null && o.equals("nowrap")) 217: nowrap = true; 218: else 219: nowrap = false; 220: } 221: 222: /** 223: * Returns the stylesheet used by this view. This returns the stylesheet 224: * of the <code>HTMLDocument</code> that is rendered by this view. 225: * 226: * @return the stylesheet used by this view 227: */ 228: protected StyleSheet getStyleSheet() 229: { 230: Document doc = getDocument(); 231: StyleSheet styleSheet = null; 232: if (doc instanceof HTMLDocument) 233: styleSheet = ((HTMLDocument) doc).getStyleSheet(); 234: return styleSheet; 235: } 236: 237: /** 238: * Returns the minimum span for the specified axis. This returns the 239: * width of the longest word for the X axis and the super behaviour for 240: * the Y axis. This is a slight deviation from the reference implementation. 241: * IMO this should improve rendering behaviour so that an InlineView never 242: * gets smaller than the longest word in it. 243: */ 244: public float getMinimumSpan(int axis) 245: { 246: float min = super.getMinimumSpan(axis); 247: if (axis == X_AXIS) 248: min = Math.max(getLongestWord(), min); 249: return min; 250: } 251: 252: /** 253: * Returns the span of the longest word in this view. 254: * 255: * @return the span of the longest word in this view 256: */ 257: private float getLongestWord() 258: { 259: if (longestWord == -1) 260: longestWord = calculateLongestWord(); 261: return longestWord; 262: } 263: 264: /** 265: * Calculates the span of the longest word in this view. 266: * 267: * @return the span of the longest word in this view 268: */ 269: private float calculateLongestWord() 270: { 271: float span = 0; 272: try 273: { 274: Document doc = getDocument(); 275: int p0 = getStartOffset(); 276: int p1 = getEndOffset(); 277: Segment s = new Segment(); 278: doc.getText(p0, p1 - p0, s); 279: BreakIterator iter = BreakIterator.getWordInstance(); 280: iter.setText(s); 281: int wordStart = p0; 282: int wordEnd = p0; 283: int start = iter.first(); 284: for (int end = iter.next(); end != BreakIterator.DONE; 285: start = end, end = iter.next()) 286: { 287: if ((end - start) > (wordEnd - wordStart)) 288: { 289: wordStart = start; 290: wordEnd = end; 291: } 292: } 293: if (wordEnd - wordStart > 0) 294: { 295: FontMetrics fm = getFontMetrics(); 296: int offset = s.offset + wordStart - s.getBeginIndex(); 297: span = fm.charsWidth(s.array, offset, wordEnd - wordStart); 298: } 299: } 300: catch (BadLocationException ex) 301: { 302: // Return 0. 303: } 304: return span; 305: } 306: 307: }
GNU Classpath (0.95) |