GNU Classpath (0.20) | |
Frames | No Frames |
1: /* JTextPane.java -- A powerful text widget supporting styled text 2: Copyright (C) 2002, 2004, 2005 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; 40: 41: import java.awt.Component; 42: 43: import javax.swing.text.AbstractDocument; 44: import javax.swing.text.AttributeSet; 45: import javax.swing.text.BadLocationException; 46: import javax.swing.text.Caret; 47: import javax.swing.text.Document; 48: import javax.swing.text.EditorKit; 49: import javax.swing.text.Element; 50: import javax.swing.text.MutableAttributeSet; 51: import javax.swing.text.SimpleAttributeSet; 52: import javax.swing.text.Style; 53: import javax.swing.text.StyleConstants; 54: import javax.swing.text.StyledDocument; 55: import javax.swing.text.StyledEditorKit; 56: 57: /** 58: * A powerful text component that supports styled content as well as 59: * embedding images and components. It is entirely based on a 60: * {@link StyledDocument} content model and a {@link StyledEditorKit}. 61: * 62: * @author Roman Kennke (roman@kennke.org) 63: * @author Andrew Selkirk 64: */ 65: public class JTextPane 66: extends JEditorPane 67: { 68: /** 69: * Creates a new <code>JTextPane</code> with a <code>null</code> document. 70: */ 71: public JTextPane() 72: { 73: super(); 74: } 75: 76: /** 77: * Creates a new <code>JTextPane</code> and sets the specified 78: * <code>document</code>. 79: * 80: * @param document the content model to use 81: */ 82: public JTextPane(StyledDocument document) 83: { 84: this(); 85: setStyledDocument(document); 86: } 87: 88: /** 89: * Returns the UI class ID. This is <code>TextPaneUI</code>. 90: * 91: * @return <code>TextPaneUI</code> 92: */ 93: public String getUIClassID() 94: { 95: return "TextPaneUI"; 96: } 97: 98: /** 99: * Sets the content model for this <code>JTextPane</code>. 100: * <code>JTextPane</code> can only be used with {@link StyledDocument}s, 101: * if you try to set a different type of <code>Document</code>, an 102: * <code>IllegalArgumentException</code> is thrown. 103: * 104: * @param document the content model to set 105: * 106: * @throws IllegalArgumentException if <code>document</code> is not an 107: * instance of <code>StyledDocument</code> 108: * 109: * @see #setStyledDocument 110: */ 111: public void setDocument(Document document) 112: { 113: if (document != null && !(document instanceof StyledDocument)) 114: throw new IllegalArgumentException 115: ("JTextPane can only handle StyledDocuments"); 116: 117: setStyledDocument((StyledDocument) document); 118: } 119: 120: /** 121: * Returns the {@link StyledDocument} that is the content model for 122: * this <code>JTextPane</code>. This is a typed wrapper for 123: * {@link #getDocument()}. 124: * 125: * @return the content model of this <code>JTextPane</code> 126: */ 127: public StyledDocument getStyledDocument() 128: { 129: return (StyledDocument) super.getDocument(); 130: } 131: 132: /** 133: * Sets the content model for this <code>JTextPane</code>. 134: * 135: * @param document the content model to set 136: */ 137: public void setStyledDocument(StyledDocument document) 138: { 139: super.setDocument(document); 140: } 141: 142: /** 143: * Replaces the currently selected text with the specified 144: * <code>content</code>. If there is no selected text, this results 145: * in a simple insertion at the current caret position. If there is 146: * no <code>content</code> specified, this results in the selection 147: * beeing deleted. 148: * 149: * @param content the text with which the selection is replaced 150: */ 151: public void replaceSelection(String content) 152: { 153: Caret caret = getCaret(); 154: StyledDocument doc = getStyledDocument(); 155: AttributeSet a = getInputAttributes().copyAttributes(); 156: if (doc == null) 157: return; 158: 159: int dot = caret.getDot(); 160: int mark = caret.getMark(); 161: 162: int p0 = Math.min (dot, mark); 163: int p1 = Math.max (dot, mark); 164: 165: try 166: { 167: if (doc instanceof AbstractDocument) 168: ((AbstractDocument)doc).replace(p0, p1 - p0, content, a); 169: else 170: { 171: // Remove selected text. 172: if (dot != mark) 173: doc.remove(p0, p1 - p0); 174: // Insert new text. 175: if (content != null && content.length() > 0) 176: doc.insertString(p0, content, a); 177: } 178: } 179: catch (BadLocationException e) 180: { 181: throw new AssertionError 182: ("No BadLocationException should be thrown here"); 183: } 184: } 185: 186: /** 187: * Inserts an AWT or Swing component into the text at the current caret 188: * position. 189: * 190: * @param component the component to be inserted 191: */ 192: public void insertComponent(Component component) 193: { 194: SimpleAttributeSet atts = new SimpleAttributeSet(); 195: atts.addAttribute(StyleConstants.ComponentAttribute, component); 196: atts.addAttribute(StyleConstants.NameAttribute, 197: StyleConstants.ComponentElementName); 198: try 199: { 200: getDocument().insertString(getCaret().getDot(), " ", atts); 201: } 202: catch (BadLocationException ex) 203: { 204: AssertionError err = new AssertionError("Unexpected bad location"); 205: err.initCause(ex); 206: throw err; 207: } 208: } 209: 210: /** 211: * Inserts an <code>Icon</code> into the text at the current caret position. 212: * 213: * @param icon the <code>Icon</code> to be inserted 214: */ 215: public void insertIcon(Icon icon) 216: { 217: SimpleAttributeSet atts = new SimpleAttributeSet(); 218: atts.addAttribute(StyleConstants.IconAttribute, icon); 219: atts.addAttribute(StyleConstants.NameAttribute, 220: StyleConstants.IconElementName); 221: try 222: { 223: getDocument().insertString(getCaret().getDot(), " ", atts); 224: } 225: catch (BadLocationException ex) 226: { 227: AssertionError err = new AssertionError("Unexpected bad location"); 228: err.initCause(ex); 229: throw err; 230: } 231: } 232: 233: /** 234: * Adds a style into the style hierarchy. Unspecified style attributes 235: * can be resolved in the <code>parent</code> style, if one is specified. 236: * 237: * While it is legal to add nameless styles (<code>nm == null</code), 238: * you must be aware that the client application is then responsible 239: * for managing the style hierarchy, since unnamed styles cannot be 240: * looked up by their name. 241: * 242: * @param nm the name of the style or <code>null</code> if the style should 243: * be unnamed 244: * @param parent the parent in which unspecified style attributes are 245: * resolved, or <code>null</code> if that is not necessary 246: * 247: * @return the newly created <code>Style</code> 248: */ 249: public Style addStyle(String nm, Style parent) 250: { 251: return getStyledDocument().addStyle(nm, parent); 252: } 253: 254: /** 255: * Removes a named <code>Style</code> from the style hierarchy. 256: * 257: * @param nm the name of the <code>Style</code> to be removed 258: */ 259: public void removeStyle(String nm) 260: { 261: getStyledDocument().removeStyle(nm); 262: } 263: 264: /** 265: * Looks up and returns a named <code>Style</code>. 266: * 267: * @param nm the name of the <code>Style</code> 268: * 269: * @return the found <code>Style</code> of <code>null</code> if no such 270: * <code>Style</code> exists 271: */ 272: public Style getStyle(String nm) 273: { 274: return getStyledDocument().getStyle(nm); 275: } 276: 277: /** 278: * Returns the logical style of the paragraph at the current caret position. 279: * 280: * @return the logical style of the paragraph at the current caret position 281: */ 282: public Style getLogicalStyle() 283: { 284: return getStyledDocument().getLogicalStyle(getCaretPosition()); 285: } 286: 287: /** 288: * Sets the logical style for the paragraph at the current caret position. 289: * 290: * @param style the style to set for the current paragraph 291: */ 292: public void setLogicalStyle(Style style) 293: { 294: getStyledDocument().setLogicalStyle(getCaretPosition(), style); 295: } 296: 297: /** 298: * Returns the text attributes for the character at the current caret 299: * position. 300: * 301: * @return the text attributes for the character at the current caret 302: * position 303: */ 304: public AttributeSet getCharacterAttributes() 305: { 306: StyledDocument doc = getStyledDocument(); 307: Element el = doc.getCharacterElement(getCaretPosition()); 308: return el.getAttributes(); 309: } 310: 311: /** 312: * Sets text attributes for the current selection. If there is no selection 313: * the text attributes are applied to newly inserted text 314: * 315: * @param attribute the text attributes to set 316: * @param replace if <code>true</code>, the attributes of the current 317: * selection are overridden, otherwise they are merged 318: * 319: * @see #getInputAttributes 320: */ 321: public void setCharacterAttributes(AttributeSet attribute, 322: boolean replace) 323: { 324: int dot = getCaret().getDot(); 325: int start = getSelectionStart(); 326: int end = getSelectionEnd(); 327: if (start == dot && end == dot) 328: // There is no selection, update insertAttributes instead 329: { 330: MutableAttributeSet inputAttributes = 331: getStyledEditorKit().getInputAttributes(); 332: inputAttributes.addAttributes(attribute); 333: } 334: else 335: getStyledDocument().setCharacterAttributes(start, end - start, attribute, 336: replace); 337: } 338: 339: /** 340: * Returns the text attributes of the paragraph at the current caret 341: * position. 342: * 343: * @return the attributes of the paragraph at the current caret position 344: */ 345: public AttributeSet getParagraphAttributes() 346: { 347: StyledDocument doc = getStyledDocument(); 348: Element el = doc.getParagraphElement(getCaretPosition()); 349: return el.getAttributes(); 350: } 351: 352: /** 353: * Sets text attributes for the paragraph at the current selection. 354: * If there is no selection the text attributes are applied to 355: * the paragraph at the current caret position. 356: * 357: * @param attribute the text attributes to set 358: * @param replace if <code>true</code>, the attributes of the current 359: * selection are overridden, otherwise they are merged 360: */ 361: public void setParagraphAttributes(AttributeSet attribute, 362: boolean replace) 363: { 364: // TODO 365: } 366: 367: /** 368: * Returns the attributes that are applied to newly inserted text. 369: * This is a {@link MutableAttributeSet}, so you can easily modify these 370: * attributes. 371: * 372: * @return the attributes that are applied to newly inserted text 373: */ 374: public MutableAttributeSet getInputAttributes() 375: { 376: return getStyledEditorKit().getInputAttributes(); 377: } 378: 379: /** 380: * Returns the {@link StyledEditorKit} that is currently used by this 381: * <code>JTextPane</code>. 382: * 383: * @return the current <code>StyledEditorKit</code> of this 384: * <code>JTextPane</code> 385: */ 386: protected final StyledEditorKit getStyledEditorKit() 387: { 388: return (StyledEditorKit) getEditorKit(); 389: } 390: 391: /** 392: * Creates the default {@link EditorKit} that is used in 393: * <code>JTextPane</code>s. This is an instance of {@link StyledEditorKit}. 394: * 395: * @return the default {@link EditorKit} that is used in 396: * <code>JTextPane</code>s 397: */ 398: protected EditorKit createDefaultEditorKit() 399: { 400: return new StyledEditorKit(); 401: } 402: 403: /** 404: * Sets the {@link EditorKit} to use for this <code>JTextPane</code>. 405: * <code>JTextPane</code>s can only handle {@link StyledEditorKit}s, 406: * if client programs try to set a different type of <code>EditorKit</code> 407: * then an IllegalArgumentException is thrown 408: * 409: * @param editor the <code>EditorKit</code> to set 410: * 411: * @throws IllegalArgumentException if <code>editor</code> is no 412: * <code>StyledEditorKit</code> 413: */ 414: public final void setEditorKit(EditorKit editor) 415: { 416: if (!(editor instanceof StyledEditorKit)) 417: throw new IllegalArgumentException 418: ("JTextPanes can only handle StyledEditorKits"); 419: super.setEditorKit(editor); 420: } 421: 422: /** 423: * Returns a param string that can be used for debugging. 424: * 425: * @return a param string that can be used for debugging. 426: */ 427: protected String paramString() 428: { 429: return super.paramString(); // TODO 430: } 431: }
GNU Classpath (0.20) |