7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package javax.swing;
26
27 import sun.swing.SwingUtilities2;
28
29 import java.awt.*;
30 import java.awt.event.*;
31 import java.lang.reflect.*;
32 import java.net.*;
33 import java.util.*;
34 import java.io.*;
35 import java.util.*;
36
37 import javax.swing.plaf.*;
38 import javax.swing.text.*;
39 import javax.swing.event.*;
40 import javax.swing.text.html.*;
41 import javax.accessibility.*;
42 import sun.reflect.misc.ReflectUtil;
43
44 /**
45 * A text component to edit various kinds of content.
46 * You can find how-to information and examples of using editor panes in
47 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/text.html">Using Text Components</a>,
48 * a section in <em>The Java Tutorial.</em>
49 *
50 * <p>
51 * This component uses implementations of the
52 * <code>EditorKit</code> to accomplish its behavior. It effectively
53 * morphs into the proper kind of text editor for the kind
54 * of content it is given. The content type that editor is bound
55 * to at any given time is determined by the <code>EditorKit</code> currently
167 * <dd>
168 * For a discussion on how newlines are handled, see
169 * <a href="text/DefaultEditorKit.html">DefaultEditorKit</a>.
170 * </dl>
171 *
172 * <p>
173 * <strong>Warning:</strong> Swing is not thread safe. For more
174 * information see <a
175 * href="package-summary.html#threading">Swing's Threading
176 * Policy</a>.
177 * <p>
178 * <strong>Warning:</strong>
179 * Serialized objects of this class will not be compatible with
180 * future Swing releases. The current serialization support is
181 * appropriate for short term storage or RMI between applications running
182 * the same version of Swing. As of 1.4, support for long term storage
183 * of all JavaBeans™
184 * has been added to the <code>java.beans</code> package.
185 * Please see {@link java.beans.XMLEncoder}.
186 *
187 * @beaninfo
188 * attribute: isContainer false
189 * description: A text component to edit various types of content.
190 *
191 * @author Timothy Prinzing
192 * @since 1.2
193 */
194 @SuppressWarnings("serial") // Same-version serialization only
195 public class JEditorPane extends JTextComponent {
196
197 /**
198 * Creates a new <code>JEditorPane</code>.
199 * The document model is set to <code>null</code>.
200 */
201 public JEditorPane() {
202 super();
203 setFocusCycleRoot(true);
204 setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
205 public Component getComponentAfter(Container focusCycleRoot,
206 Component aComponent) {
207 if (focusCycleRoot != JEditorPane.this ||
208 (!isEditable() && getComponentCount() > 0)) {
209 return super.getComponentAfter(focusCycleRoot,
210 aComponent);
211 } else {
212 Container rootAncestor = getFocusCycleRootAncestor();
213 return (rootAncestor != null)
306 listenerList.add(HyperlinkListener.class, listener);
307 }
308
309 /**
310 * Removes a hyperlink listener.
311 *
312 * @param listener the listener
313 */
314 public synchronized void removeHyperlinkListener(HyperlinkListener listener) {
315 listenerList.remove(HyperlinkListener.class, listener);
316 }
317
318 /**
319 * Returns an array of all the <code>HyperLinkListener</code>s added
320 * to this JEditorPane with addHyperlinkListener().
321 *
322 * @return all of the <code>HyperLinkListener</code>s added or an empty
323 * array if no listeners have been added
324 * @since 1.4
325 */
326 public synchronized HyperlinkListener[] getHyperlinkListeners() {
327 return listenerList.getListeners(javax.swing.event.HyperlinkListener.class);
328 }
329
330 /**
331 * Notifies all listeners that have registered interest for
332 * notification on this event type. This is normally called
333 * by the currently installed <code>EditorKit</code> if a content type
334 * that supports hyperlinks is currently active and there
335 * was activity with a link. The listener list is processed
336 * last to first.
337 *
338 * @param e the event
339 * @see EventListenerList
340 */
341 public void fireHyperlinkUpdate(HyperlinkEvent e) {
342 // Guaranteed to return a non-null array
343 Object[] listeners = listenerList.getListenerList();
344 // Process the listeners last to first, notifying
345 // those that are interested in this event
394 * will be fired.
395 * <p>
396 * If the document is loaded asynchronously, the document
397 * will be installed into the editor immediately using a
398 * call to <code>setDocument</code> which will fire a
399 * document property change event, then a thread will be
400 * created which will begin doing the actual loading.
401 * In this case, the page property change event will not be
402 * fired by the call to this method directly, but rather will be
403 * fired when the thread doing the loading has finished.
404 * It will also be fired on the event-dispatch thread.
405 * Since the calling thread can not throw an <code>IOException</code>
406 * in the event of failure on the other thread, the page
407 * property change event will be fired when the other
408 * thread is done whether the load was successful or not.
409 *
410 * @param page the URL of the page
411 * @exception IOException for a <code>null</code> or invalid
412 * page specification, or exception from the stream being read
413 * @see #getPage
414 * @beaninfo
415 * description: the URL used to set content
416 * bound: true
417 * expert: true
418 */
419 public void setPage(URL page) throws IOException {
420 if (page == null) {
421 throw new IOException("invalid url");
422 }
423 URL loaded = getPage();
424
425
426 // reset scrollbar
427 if (!page.equals(loaded) && page.getRef() == null) {
428 scrollRectToVisible(new Rectangle(0,0,1,1));
429 }
430 boolean reloaded = false;
431 Object postData = getPostData();
432 if ((loaded == null) || !loaded.sameFile(page) || (postData != null)) {
433 // different url or POST method, load the new content
434
435 int p = getAsynchronousLoadPriority(getDocument());
436 if (p < 0) {
437 // open stream synchronously
438 InputStream in = getStream(page);
876 *
877 * @param url the URL for display
878 * @exception IOException for a <code>null</code> or invalid URL
879 * specification
880 */
881 public void setPage(String url) throws IOException {
882 if (url == null) {
883 throw new IOException("invalid url");
884 }
885 URL page = new URL(url);
886 setPage(page);
887 }
888
889 /**
890 * Gets the class ID for the UI.
891 *
892 * @return the string "EditorPaneUI"
893 * @see JComponent#getUIClassID
894 * @see UIDefaults#getUI
895 */
896 public String getUIClassID() {
897 return uiClassID;
898 }
899
900 /**
901 * Creates the default editor kit (<code>PlainEditorKit</code>) for when
902 * the component is first created.
903 *
904 * @return the editor kit
905 */
906 protected EditorKit createDefaultEditorKit() {
907 return new PlainEditorKit();
908 }
909
910 /**
911 * Fetches the currently installed kit for handling content.
912 * <code>createDefaultEditorKit</code> is called to set up a default
913 * if necessary.
914 *
915 * @return the editor kit
941 * be successfully located. This is mostly convenience method
942 * that can be used as an alternative to calling
943 * <code>setEditorKit</code> directly.
944 * <p>
945 * If there is a charset definition specified as a parameter
946 * of the content type specification, it will be used when
947 * loading input streams using the associated <code>EditorKit</code>.
948 * For example if the type is specified as
949 * <code>text/html; charset=EUC-JP</code> the content
950 * will be loaded using the <code>EditorKit</code> registered for
951 * <code>text/html</code> and the Reader provided to
952 * the <code>EditorKit</code> to load unicode into the document will
953 * use the <code>EUC-JP</code> charset for translating
954 * to unicode. If the type is not recognized, the content
955 * will be loaded using the <code>EditorKit</code> registered
956 * for plain text, <code>text/plain</code>.
957 *
958 * @param type the non-<code>null</code> mime type for the content editing
959 * support
960 * @see #getContentType
961 * @beaninfo
962 * description: the type of content
963 * @throws NullPointerException if the <code>type</code> parameter
964 * is <code>null</code>
965 */
966 public final void setContentType(String type) {
967 // The type could have optional info is part of it,
968 // for example some charset info. We need to strip that
969 // of and save it.
970 int parm = type.indexOf(';');
971 if (parm > -1) {
972 // Save the paramList.
973 String paramList = type.substring(parm);
974 // update the content type string.
975 type = type.substring(0, parm).trim();
976 if (type.toLowerCase().startsWith("text/")) {
977 setCharsetFromContentTypeParameters(paramList);
978 }
979 }
980 if ((kit == null) || (! type.equals(kit.getContentType()))
981 || !isUserSetEditorKit) {
982 EditorKit k = getEditorKitForContentType(type);
983 if (k != null && k != kit) {
984 setEditorKit(k);
985 isUserSetEditorKit = false;
1027
1028 /**
1029 * Sets the currently installed kit for handling
1030 * content. This is the bound property that
1031 * establishes the content type of the editor.
1032 * Any old kit is first deinstalled, then if kit is
1033 * non-<code>null</code>,
1034 * the new kit is installed, and a default document created for it.
1035 * A <code>PropertyChange</code> event ("editorKit") is always fired when
1036 * <code>setEditorKit</code> is called.
1037 * <p>
1038 * <em>NOTE: This has the side effect of changing the model,
1039 * because the <code>EditorKit</code> is the source of how a
1040 * particular type
1041 * of content is modeled. This method will cause <code>setDocument</code>
1042 * to be called on behalf of the caller to ensure integrity
1043 * of the internal state.</em>
1044 *
1045 * @param kit the desired editor behavior
1046 * @see #getEditorKit
1047 * @beaninfo
1048 * description: the currently installed kit for handling content
1049 * bound: true
1050 * expert: true
1051 */
1052 public void setEditorKit(EditorKit kit) {
1053 EditorKit old = this.kit;
1054 isUserSetEditorKit = true;
1055 if (old != null) {
1056 old.deinstall(this);
1057 }
1058 this.kit = kit;
1059 if (this.kit != null) {
1060 this.kit.install(this);
1061 setDocument(this.kit.createDefaultDocument());
1062 }
1063 firePropertyChange("editorKit", old, kit);
1064 }
1065
1066 /**
1067 * Fetches the editor kit to use for the given type
1068 * of content. This is called when a type is requested
1069 * that doesn't match the currently installed type.
1070 * If the component doesn't have an <code>EditorKit</code> registered
1071 * for the given type, it will try to create an
1395 * previous <code>Document</code> won't have any lingering state.
1396 * <ol>
1397 * <li>
1398 * Leaving the existing model in place means that the old view will be
1399 * torn down, and a new view created, where replacing the document would
1400 * avoid the tear down of the old view.
1401 * <li>
1402 * Some formats (such as HTML) can install things into the document that
1403 * can influence future contents. HTML can have style information embedded
1404 * that would influence the next content installed unexpectedly.
1405 * </ol>
1406 * <p>
1407 * An alternative way to load this component with a string would be to
1408 * create a StringReader and call the read method. In this case the model
1409 * would be replaced after it was initialized with the contents of the
1410 * string.
1411 *
1412 * @param t the new text to be set; if <code>null</code> the old
1413 * text will be deleted
1414 * @see #getText
1415 * @beaninfo
1416 * description: the text of this component
1417 */
1418 public void setText(String t) {
1419 try {
1420 Document doc = getDocument();
1421 doc.remove(0, doc.getLength());
1422 if (t == null || t.equals("")) {
1423 return;
1424 }
1425 Reader r = new StringReader(t);
1426 EditorKit kit = getEditorKit();
1427 kit.read(r, doc, 0);
1428 } catch (IOException ioe) {
1429 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
1430 } catch (BadLocationException ble) {
1431 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
1432 }
1433 }
1434
1435 /**
1436 * Returns the text contained in this <code>TextComponent</code>
1437 * in terms of the
1447 String txt;
1448 try {
1449 StringWriter buf = new StringWriter();
1450 write(buf);
1451 txt = buf.toString();
1452 } catch (IOException ioe) {
1453 txt = null;
1454 }
1455 return txt;
1456 }
1457
1458 // --- Scrollable ----------------------------------------
1459
1460 /**
1461 * Returns true if a viewport should always force the width of this
1462 * <code>Scrollable</code> to match the width of the viewport.
1463 *
1464 * @return true if a viewport should force the Scrollables width to
1465 * match its own, false otherwise
1466 */
1467 public boolean getScrollableTracksViewportWidth() {
1468 Container parent = SwingUtilities.getUnwrappedParent(this);
1469 if (parent instanceof JViewport) {
1470 JViewport port = (JViewport) parent;
1471 TextUI ui = getUI();
1472 int w = port.getWidth();
1473 Dimension min = ui.getMinimumSize(this);
1474 Dimension max = ui.getMaximumSize(this);
1475 if ((w >= min.width) && (w <= max.width)) {
1476 return true;
1477 }
1478 }
1479 return false;
1480 }
1481
1482 /**
1483 * Returns true if a viewport should always force the height of this
1484 * <code>Scrollable</code> to match the height of the viewport.
1485 *
1486 * @return true if a viewport should force the
1487 * <code>Scrollable</code>'s height to match its own,
1488 * false otherwise
1489 */
1490 public boolean getScrollableTracksViewportHeight() {
1491 Container parent = SwingUtilities.getUnwrappedParent(this);
1492 if (parent instanceof JViewport) {
1493 JViewport port = (JViewport) parent;
1494 TextUI ui = getUI();
1495 int h = port.getHeight();
1496 Dimension min = ui.getMinimumSize(this);
1497 if (h >= min.height) {
1498 Dimension max = ui.getMaximumSize(this);
1499 if (h <= max.height) {
1500 return true;
1501 }
1502 }
1503 }
1504 return false;
1505 }
1506
1507 // --- Serialization ------------------------------------
1508
1509 /**
1607 return super.paramString() +
1608 ",kit=" + kitString +
1609 ",typeHandlers=" + typeHandlersString;
1610 }
1611
1612
1613 /////////////////
1614 // Accessibility support
1615 ////////////////
1616
1617
1618 /**
1619 * Gets the AccessibleContext associated with this JEditorPane.
1620 * For editor panes, the AccessibleContext takes the form of an
1621 * AccessibleJEditorPane.
1622 * A new AccessibleJEditorPane instance is created if necessary.
1623 *
1624 * @return an AccessibleJEditorPane that serves as the
1625 * AccessibleContext of this JEditorPane
1626 */
1627 public AccessibleContext getAccessibleContext() {
1628 if (getEditorKit() instanceof HTMLEditorKit) {
1629 if (accessibleContext == null || accessibleContext.getClass() !=
1630 AccessibleJEditorPaneHTML.class) {
1631 accessibleContext = new AccessibleJEditorPaneHTML();
1632 }
1633 } else if (accessibleContext == null || accessibleContext.getClass() !=
1634 AccessibleJEditorPane.class) {
1635 accessibleContext = new AccessibleJEditorPane();
1636 }
1637 return accessibleContext;
1638 }
1639
1640 /**
1641 * This class implements accessibility support for the
1642 * <code>JEditorPane</code> class. It provides an implementation of the
1643 * Java Accessibility API appropriate to editor pane user-interface
1644 * elements.
1645 * <p>
1646 * <strong>Warning:</strong>
|
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package javax.swing;
26
27 import java.awt.*;
28 import java.beans.JavaBean;
29 import java.beans.BeanProperty;
30 import java.lang.reflect.*;
31 import java.net.*;
32 import java.util.*;
33 import java.io.*;
34
35 import javax.swing.plaf.*;
36 import javax.swing.text.*;
37 import javax.swing.event.*;
38 import javax.swing.text.html.*;
39 import javax.accessibility.*;
40 import sun.reflect.misc.ReflectUtil;
41
42 /**
43 * A text component to edit various kinds of content.
44 * You can find how-to information and examples of using editor panes in
45 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/text.html">Using Text Components</a>,
46 * a section in <em>The Java Tutorial.</em>
47 *
48 * <p>
49 * This component uses implementations of the
50 * <code>EditorKit</code> to accomplish its behavior. It effectively
51 * morphs into the proper kind of text editor for the kind
52 * of content it is given. The content type that editor is bound
53 * to at any given time is determined by the <code>EditorKit</code> currently
165 * <dd>
166 * For a discussion on how newlines are handled, see
167 * <a href="text/DefaultEditorKit.html">DefaultEditorKit</a>.
168 * </dl>
169 *
170 * <p>
171 * <strong>Warning:</strong> Swing is not thread safe. For more
172 * information see <a
173 * href="package-summary.html#threading">Swing's Threading
174 * Policy</a>.
175 * <p>
176 * <strong>Warning:</strong>
177 * Serialized objects of this class will not be compatible with
178 * future Swing releases. The current serialization support is
179 * appropriate for short term storage or RMI between applications running
180 * the same version of Swing. As of 1.4, support for long term storage
181 * of all JavaBeans™
182 * has been added to the <code>java.beans</code> package.
183 * Please see {@link java.beans.XMLEncoder}.
184 *
185 * @author Timothy Prinzing
186 * @since 1.2
187 */
188 @JavaBean(defaultProperty = "UIClassID", description = "A text component to edit various types of content.")
189 @SwingContainer(false)
190 @SuppressWarnings("serial") // Same-version serialization only
191 public class JEditorPane extends JTextComponent {
192
193 /**
194 * Creates a new <code>JEditorPane</code>.
195 * The document model is set to <code>null</code>.
196 */
197 public JEditorPane() {
198 super();
199 setFocusCycleRoot(true);
200 setFocusTraversalPolicy(new LayoutFocusTraversalPolicy() {
201 public Component getComponentAfter(Container focusCycleRoot,
202 Component aComponent) {
203 if (focusCycleRoot != JEditorPane.this ||
204 (!isEditable() && getComponentCount() > 0)) {
205 return super.getComponentAfter(focusCycleRoot,
206 aComponent);
207 } else {
208 Container rootAncestor = getFocusCycleRootAncestor();
209 return (rootAncestor != null)
302 listenerList.add(HyperlinkListener.class, listener);
303 }
304
305 /**
306 * Removes a hyperlink listener.
307 *
308 * @param listener the listener
309 */
310 public synchronized void removeHyperlinkListener(HyperlinkListener listener) {
311 listenerList.remove(HyperlinkListener.class, listener);
312 }
313
314 /**
315 * Returns an array of all the <code>HyperLinkListener</code>s added
316 * to this JEditorPane with addHyperlinkListener().
317 *
318 * @return all of the <code>HyperLinkListener</code>s added or an empty
319 * array if no listeners have been added
320 * @since 1.4
321 */
322 @BeanProperty(bound = false)
323 public synchronized HyperlinkListener[] getHyperlinkListeners() {
324 return listenerList.getListeners(javax.swing.event.HyperlinkListener.class);
325 }
326
327 /**
328 * Notifies all listeners that have registered interest for
329 * notification on this event type. This is normally called
330 * by the currently installed <code>EditorKit</code> if a content type
331 * that supports hyperlinks is currently active and there
332 * was activity with a link. The listener list is processed
333 * last to first.
334 *
335 * @param e the event
336 * @see EventListenerList
337 */
338 public void fireHyperlinkUpdate(HyperlinkEvent e) {
339 // Guaranteed to return a non-null array
340 Object[] listeners = listenerList.getListenerList();
341 // Process the listeners last to first, notifying
342 // those that are interested in this event
391 * will be fired.
392 * <p>
393 * If the document is loaded asynchronously, the document
394 * will be installed into the editor immediately using a
395 * call to <code>setDocument</code> which will fire a
396 * document property change event, then a thread will be
397 * created which will begin doing the actual loading.
398 * In this case, the page property change event will not be
399 * fired by the call to this method directly, but rather will be
400 * fired when the thread doing the loading has finished.
401 * It will also be fired on the event-dispatch thread.
402 * Since the calling thread can not throw an <code>IOException</code>
403 * in the event of failure on the other thread, the page
404 * property change event will be fired when the other
405 * thread is done whether the load was successful or not.
406 *
407 * @param page the URL of the page
408 * @exception IOException for a <code>null</code> or invalid
409 * page specification, or exception from the stream being read
410 * @see #getPage
411 */
412 @BeanProperty(expert = true, description
413 = "the URL used to set content")
414 public void setPage(URL page) throws IOException {
415 if (page == null) {
416 throw new IOException("invalid url");
417 }
418 URL loaded = getPage();
419
420
421 // reset scrollbar
422 if (!page.equals(loaded) && page.getRef() == null) {
423 scrollRectToVisible(new Rectangle(0,0,1,1));
424 }
425 boolean reloaded = false;
426 Object postData = getPostData();
427 if ((loaded == null) || !loaded.sameFile(page) || (postData != null)) {
428 // different url or POST method, load the new content
429
430 int p = getAsynchronousLoadPriority(getDocument());
431 if (p < 0) {
432 // open stream synchronously
433 InputStream in = getStream(page);
871 *
872 * @param url the URL for display
873 * @exception IOException for a <code>null</code> or invalid URL
874 * specification
875 */
876 public void setPage(String url) throws IOException {
877 if (url == null) {
878 throw new IOException("invalid url");
879 }
880 URL page = new URL(url);
881 setPage(page);
882 }
883
884 /**
885 * Gets the class ID for the UI.
886 *
887 * @return the string "EditorPaneUI"
888 * @see JComponent#getUIClassID
889 * @see UIDefaults#getUI
890 */
891 @BeanProperty(bound = false)
892 public String getUIClassID() {
893 return uiClassID;
894 }
895
896 /**
897 * Creates the default editor kit (<code>PlainEditorKit</code>) for when
898 * the component is first created.
899 *
900 * @return the editor kit
901 */
902 protected EditorKit createDefaultEditorKit() {
903 return new PlainEditorKit();
904 }
905
906 /**
907 * Fetches the currently installed kit for handling content.
908 * <code>createDefaultEditorKit</code> is called to set up a default
909 * if necessary.
910 *
911 * @return the editor kit
937 * be successfully located. This is mostly convenience method
938 * that can be used as an alternative to calling
939 * <code>setEditorKit</code> directly.
940 * <p>
941 * If there is a charset definition specified as a parameter
942 * of the content type specification, it will be used when
943 * loading input streams using the associated <code>EditorKit</code>.
944 * For example if the type is specified as
945 * <code>text/html; charset=EUC-JP</code> the content
946 * will be loaded using the <code>EditorKit</code> registered for
947 * <code>text/html</code> and the Reader provided to
948 * the <code>EditorKit</code> to load unicode into the document will
949 * use the <code>EUC-JP</code> charset for translating
950 * to unicode. If the type is not recognized, the content
951 * will be loaded using the <code>EditorKit</code> registered
952 * for plain text, <code>text/plain</code>.
953 *
954 * @param type the non-<code>null</code> mime type for the content editing
955 * support
956 * @see #getContentType
957 * @throws NullPointerException if the <code>type</code> parameter
958 * is <code>null</code>
959 */
960 @BeanProperty(bound = false, description
961 = "the type of content")
962 public final void setContentType(String type) {
963 // The type could have optional info is part of it,
964 // for example some charset info. We need to strip that
965 // of and save it.
966 int parm = type.indexOf(';');
967 if (parm > -1) {
968 // Save the paramList.
969 String paramList = type.substring(parm);
970 // update the content type string.
971 type = type.substring(0, parm).trim();
972 if (type.toLowerCase().startsWith("text/")) {
973 setCharsetFromContentTypeParameters(paramList);
974 }
975 }
976 if ((kit == null) || (! type.equals(kit.getContentType()))
977 || !isUserSetEditorKit) {
978 EditorKit k = getEditorKitForContentType(type);
979 if (k != null && k != kit) {
980 setEditorKit(k);
981 isUserSetEditorKit = false;
1023
1024 /**
1025 * Sets the currently installed kit for handling
1026 * content. This is the bound property that
1027 * establishes the content type of the editor.
1028 * Any old kit is first deinstalled, then if kit is
1029 * non-<code>null</code>,
1030 * the new kit is installed, and a default document created for it.
1031 * A <code>PropertyChange</code> event ("editorKit") is always fired when
1032 * <code>setEditorKit</code> is called.
1033 * <p>
1034 * <em>NOTE: This has the side effect of changing the model,
1035 * because the <code>EditorKit</code> is the source of how a
1036 * particular type
1037 * of content is modeled. This method will cause <code>setDocument</code>
1038 * to be called on behalf of the caller to ensure integrity
1039 * of the internal state.</em>
1040 *
1041 * @param kit the desired editor behavior
1042 * @see #getEditorKit
1043 */
1044 @BeanProperty(expert = true, description
1045 = "the currently installed kit for handling content")
1046 public void setEditorKit(EditorKit kit) {
1047 EditorKit old = this.kit;
1048 isUserSetEditorKit = true;
1049 if (old != null) {
1050 old.deinstall(this);
1051 }
1052 this.kit = kit;
1053 if (this.kit != null) {
1054 this.kit.install(this);
1055 setDocument(this.kit.createDefaultDocument());
1056 }
1057 firePropertyChange("editorKit", old, kit);
1058 }
1059
1060 /**
1061 * Fetches the editor kit to use for the given type
1062 * of content. This is called when a type is requested
1063 * that doesn't match the currently installed type.
1064 * If the component doesn't have an <code>EditorKit</code> registered
1065 * for the given type, it will try to create an
1389 * previous <code>Document</code> won't have any lingering state.
1390 * <ol>
1391 * <li>
1392 * Leaving the existing model in place means that the old view will be
1393 * torn down, and a new view created, where replacing the document would
1394 * avoid the tear down of the old view.
1395 * <li>
1396 * Some formats (such as HTML) can install things into the document that
1397 * can influence future contents. HTML can have style information embedded
1398 * that would influence the next content installed unexpectedly.
1399 * </ol>
1400 * <p>
1401 * An alternative way to load this component with a string would be to
1402 * create a StringReader and call the read method. In this case the model
1403 * would be replaced after it was initialized with the contents of the
1404 * string.
1405 *
1406 * @param t the new text to be set; if <code>null</code> the old
1407 * text will be deleted
1408 * @see #getText
1409 */
1410 @BeanProperty(bound = false, description
1411 = "the text of this component")
1412 public void setText(String t) {
1413 try {
1414 Document doc = getDocument();
1415 doc.remove(0, doc.getLength());
1416 if (t == null || t.equals("")) {
1417 return;
1418 }
1419 Reader r = new StringReader(t);
1420 EditorKit kit = getEditorKit();
1421 kit.read(r, doc, 0);
1422 } catch (IOException ioe) {
1423 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
1424 } catch (BadLocationException ble) {
1425 UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
1426 }
1427 }
1428
1429 /**
1430 * Returns the text contained in this <code>TextComponent</code>
1431 * in terms of the
1441 String txt;
1442 try {
1443 StringWriter buf = new StringWriter();
1444 write(buf);
1445 txt = buf.toString();
1446 } catch (IOException ioe) {
1447 txt = null;
1448 }
1449 return txt;
1450 }
1451
1452 // --- Scrollable ----------------------------------------
1453
1454 /**
1455 * Returns true if a viewport should always force the width of this
1456 * <code>Scrollable</code> to match the width of the viewport.
1457 *
1458 * @return true if a viewport should force the Scrollables width to
1459 * match its own, false otherwise
1460 */
1461 @BeanProperty(bound = false)
1462 public boolean getScrollableTracksViewportWidth() {
1463 Container parent = SwingUtilities.getUnwrappedParent(this);
1464 if (parent instanceof JViewport) {
1465 JViewport port = (JViewport) parent;
1466 TextUI ui = getUI();
1467 int w = port.getWidth();
1468 Dimension min = ui.getMinimumSize(this);
1469 Dimension max = ui.getMaximumSize(this);
1470 if ((w >= min.width) && (w <= max.width)) {
1471 return true;
1472 }
1473 }
1474 return false;
1475 }
1476
1477 /**
1478 * Returns true if a viewport should always force the height of this
1479 * <code>Scrollable</code> to match the height of the viewport.
1480 *
1481 * @return true if a viewport should force the
1482 * <code>Scrollable</code>'s height to match its own,
1483 * false otherwise
1484 */
1485 @BeanProperty(bound = false)
1486 public boolean getScrollableTracksViewportHeight() {
1487 Container parent = SwingUtilities.getUnwrappedParent(this);
1488 if (parent instanceof JViewport) {
1489 JViewport port = (JViewport) parent;
1490 TextUI ui = getUI();
1491 int h = port.getHeight();
1492 Dimension min = ui.getMinimumSize(this);
1493 if (h >= min.height) {
1494 Dimension max = ui.getMaximumSize(this);
1495 if (h <= max.height) {
1496 return true;
1497 }
1498 }
1499 }
1500 return false;
1501 }
1502
1503 // --- Serialization ------------------------------------
1504
1505 /**
1603 return super.paramString() +
1604 ",kit=" + kitString +
1605 ",typeHandlers=" + typeHandlersString;
1606 }
1607
1608
1609 /////////////////
1610 // Accessibility support
1611 ////////////////
1612
1613
1614 /**
1615 * Gets the AccessibleContext associated with this JEditorPane.
1616 * For editor panes, the AccessibleContext takes the form of an
1617 * AccessibleJEditorPane.
1618 * A new AccessibleJEditorPane instance is created if necessary.
1619 *
1620 * @return an AccessibleJEditorPane that serves as the
1621 * AccessibleContext of this JEditorPane
1622 */
1623 @BeanProperty(bound = false)
1624 public AccessibleContext getAccessibleContext() {
1625 if (getEditorKit() instanceof HTMLEditorKit) {
1626 if (accessibleContext == null || accessibleContext.getClass() !=
1627 AccessibleJEditorPaneHTML.class) {
1628 accessibleContext = new AccessibleJEditorPaneHTML();
1629 }
1630 } else if (accessibleContext == null || accessibleContext.getClass() !=
1631 AccessibleJEditorPane.class) {
1632 accessibleContext = new AccessibleJEditorPane();
1633 }
1634 return accessibleContext;
1635 }
1636
1637 /**
1638 * This class implements accessibility support for the
1639 * <code>JEditorPane</code> class. It provides an implementation of the
1640 * Java Accessibility API appropriate to editor pane user-interface
1641 * elements.
1642 * <p>
1643 * <strong>Warning:</strong>
|