OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / JTextPane.java
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     MutableAttributeSet inputAtts = getInputAttributes();
218     inputAtts.removeAttributes(inputAtts);
219     StyleConstants.setIcon(inputAtts, icon);
220     replaceSelection(" ");
221     inputAtts.removeAttributes(inputAtts);
222   }
223
224   /**
225    * Adds a style into the style hierarchy. Unspecified style attributes
226    * can be resolved in the <code>parent</code> style, if one is specified.
227    *
228    * While it is legal to add nameless styles (<code>nm == null</code),
229    * you must be aware that the client application is then responsible
230    * for managing the style hierarchy, since unnamed styles cannot be
231    * looked up by their name.
232    *
233    * @param nm the name of the style or <code>null</code> if the style should
234    *           be unnamed
235    * @param parent the parent in which unspecified style attributes are
236    *           resolved, or <code>null</code> if that is not necessary
237    *
238    * @return the newly created <code>Style</code>
239    */
240   public Style addStyle(String nm, Style parent)
241   {
242     return getStyledDocument().addStyle(nm, parent);
243   }
244
245   /**
246    * Removes a named <code>Style</code> from the style hierarchy.
247    *
248    * @param nm the name of the <code>Style</code> to be removed
249    */
250   public void removeStyle(String nm)
251   {
252     getStyledDocument().removeStyle(nm);
253   }
254
255   /**
256    * Looks up and returns a named <code>Style</code>.
257    *
258    * @param nm the name of the <code>Style</code>
259    *
260    * @return the found <code>Style</code> of <code>null</code> if no such
261    *         <code>Style</code> exists
262    */
263   public Style getStyle(String nm)
264   {
265     return getStyledDocument().getStyle(nm);
266   }
267
268   /**
269    * Returns the logical style of the paragraph at the current caret position.
270    *
271    * @return the logical style of the paragraph at the current caret position
272    */
273   public Style getLogicalStyle()
274   {
275     return getStyledDocument().getLogicalStyle(getCaretPosition());
276   }
277
278   /**
279    * Sets the logical style for the paragraph at the current caret position.
280    *
281    * @param style the style to set for the current paragraph
282    */
283   public void setLogicalStyle(Style style)
284   {
285     getStyledDocument().setLogicalStyle(getCaretPosition(), style);
286   }
287
288   /**
289    * Returns the text attributes for the character at the current caret
290    * position.
291    *
292    * @return the text attributes for the character at the current caret
293    *         position
294    */
295   public AttributeSet getCharacterAttributes()
296   {
297     StyledDocument doc = getStyledDocument();
298     Element el = doc.getCharacterElement(getCaretPosition());
299     return el.getAttributes();
300   }
301
302   /**
303    * Sets text attributes for the current selection. If there is no selection
304    * the text attributes are applied to newly inserted text
305    *
306    * @param attribute the text attributes to set
307    * @param replace if <code>true</code>, the attributes of the current
308    *     selection are overridden, otherwise they are merged
309    *
310    * @see #getInputAttributes
311    */
312   public void setCharacterAttributes(AttributeSet attribute,
313                                      boolean replace)
314   {
315     int dot = getCaret().getDot();
316     int start = getSelectionStart();
317     int end = getSelectionEnd();
318     if (start == dot && end == dot)
319       // There is no selection, update insertAttributes instead
320       {
321         MutableAttributeSet inputAttributes =
322           getStyledEditorKit().getInputAttributes();
323         if (replace)
324           inputAttributes.removeAttributes(inputAttributes);
325         inputAttributes.addAttributes(attribute);
326       }
327     else
328       getStyledDocument().setCharacterAttributes(start, end - start, attribute,
329                                                  replace);
330   }
331
332   /**
333    * Returns the text attributes of the paragraph at the current caret
334    * position.
335    *
336    * @return the attributes of the paragraph at the current caret position
337    */
338   public AttributeSet getParagraphAttributes()
339   {
340     StyledDocument doc = getStyledDocument();
341     Element el = doc.getParagraphElement(getCaretPosition());
342     return el.getAttributes();
343   }
344
345   /**
346    * Sets text attributes for the paragraph at the current selection.
347    * If there is no selection the text attributes are applied to
348    * the paragraph at the current caret position.
349    *
350    * @param attribute the text attributes to set
351    * @param replace if <code>true</code>, the attributes of the current
352    *     selection are overridden, otherwise they are merged
353    */
354   public void setParagraphAttributes(AttributeSet attribute,
355                                      boolean replace)
356   {
357     // TODO
358   }
359
360   /**
361    * Returns the attributes that are applied to newly inserted text.
362    * This is a {@link MutableAttributeSet}, so you can easily modify these
363    * attributes.
364    *
365    * @return the attributes that are applied to newly inserted text
366    */
367   public MutableAttributeSet getInputAttributes()
368   {
369     return getStyledEditorKit().getInputAttributes();
370   }
371
372   /**
373    * Returns the {@link StyledEditorKit} that is currently used by this
374    * <code>JTextPane</code>.
375    *
376    * @return the current <code>StyledEditorKit</code> of this
377    *         <code>JTextPane</code>
378    */
379   protected final StyledEditorKit getStyledEditorKit()
380   {
381     return (StyledEditorKit) getEditorKit();
382   }
383
384   /**
385    * Creates the default {@link EditorKit} that is used in
386    * <code>JTextPane</code>s. This is an instance of {@link StyledEditorKit}.
387    *
388    * @return the default {@link EditorKit} that is used in
389    *         <code>JTextPane</code>s
390    */
391   protected EditorKit createDefaultEditorKit()
392   {
393     return new StyledEditorKit();
394   }
395
396   /**
397    * Sets the {@link EditorKit} to use for this <code>JTextPane</code>.
398    * <code>JTextPane</code>s can only handle {@link StyledEditorKit}s,
399    * if client programs try to set a different type of <code>EditorKit</code>
400    * then an IllegalArgumentException is thrown
401    *
402    * @param editor the <code>EditorKit</code> to set
403    *
404    * @throws IllegalArgumentException if <code>editor</code> is no
405    *         <code>StyledEditorKit</code>
406    */
407   public final void setEditorKit(EditorKit editor)
408   {
409     if (!(editor instanceof StyledEditorKit))
410       throw new IllegalArgumentException
411         ("JTextPanes can only handle StyledEditorKits");
412     super.setEditorKit(editor);
413   }
414
415   /**
416    * Returns a param string that can be used for debugging.
417    *
418    * @return a param string that can be used for debugging.
419    */
420   protected String paramString()
421   {
422     return super.paramString(); // TODO
423   }
424 }