1. /*
  2. * @(#)StyledEditorKit.java 1.42 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.text;
  8. import java.io.*;
  9. import java.awt.*;
  10. import java.awt.event.ActionEvent;
  11. import java.beans.PropertyChangeEvent;
  12. import java.beans.PropertyChangeListener;
  13. import javax.swing.event.*;
  14. import javax.swing.Action;
  15. import javax.swing.JEditorPane;
  16. import javax.swing.KeyStroke;
  17. import javax.swing.UIManager;
  18. /**
  19. * This is the set of things needed by a text component
  20. * to be a reasonably functioning editor for some <em>type</em>
  21. * of text document. This implementation provides a default
  22. * implementation which treats text as styled text and
  23. * provides a minimal set of actions for editing styled text.
  24. *
  25. * @author Timothy Prinzing
  26. * @version 1.42 01/23/03
  27. */
  28. public class StyledEditorKit extends DefaultEditorKit {
  29. /**
  30. * Creates a new EditorKit used for styled documents.
  31. */
  32. public StyledEditorKit() {
  33. createInputAttributeUpdated();
  34. createInputAttributes();
  35. }
  36. /**
  37. * Gets the input attributes for the pane. When
  38. * the caret moves and there is no selection, the
  39. * input attributes are automatically mutated to
  40. * reflect the character attributes of the current
  41. * caret location. The styled editing actions
  42. * use the input attributes to carry out their
  43. * actions.
  44. *
  45. * @return the attribute set
  46. */
  47. public MutableAttributeSet getInputAttributes() {
  48. return inputAttributes;
  49. }
  50. /**
  51. * Fetches the element representing the current
  52. * run of character attributes for the caret.
  53. *
  54. * @return the element
  55. */
  56. public Element getCharacterAttributeRun() {
  57. return currentRun;
  58. }
  59. // --- EditorKit methods ---------------------------
  60. /**
  61. * Fetches the command list for the editor. This is
  62. * the list of commands supported by the superclass
  63. * augmented by the collection of commands defined
  64. * locally for style operations.
  65. *
  66. * @return the command list
  67. */
  68. public Action[] getActions() {
  69. return TextAction.augmentList(super.getActions(), this.defaultActions);
  70. }
  71. /**
  72. * Creates an uninitialized text storage model
  73. * that is appropriate for this type of editor.
  74. *
  75. * @return the model
  76. */
  77. public Document createDefaultDocument() {
  78. return new DefaultStyledDocument();
  79. }
  80. /**
  81. * Called when the kit is being installed into
  82. * a JEditorPane.
  83. *
  84. * @param c the JEditorPane
  85. */
  86. public void install(JEditorPane c) {
  87. c.addCaretListener(inputAttributeUpdater);
  88. c.addPropertyChangeListener(inputAttributeUpdater);
  89. Caret caret = c.getCaret();
  90. if (caret != null) {
  91. inputAttributeUpdater.updateInputAttributes
  92. (caret.getDot(), caret.getMark(), c);
  93. }
  94. }
  95. /**
  96. * Called when the kit is being removed from the
  97. * JEditorPane. This is used to unregister any
  98. * listeners that were attached.
  99. *
  100. * @param c the JEditorPane
  101. */
  102. public void deinstall(JEditorPane c) {
  103. c.removeCaretListener(inputAttributeUpdater);
  104. c.removePropertyChangeListener(inputAttributeUpdater);
  105. // remove references to current document so it can be collected.
  106. currentRun = null;
  107. currentParagraph = null;
  108. }
  109. /**
  110. * Fetches a factory that is suitable for producing
  111. * views of any models that are produced by this
  112. * kit. This is implemented to return View implementations
  113. * for the following kinds of elements:
  114. * <ul>
  115. * <li>AbstractDocument.ContentElementName
  116. * <li>AbstractDocument.ParagraphElementName
  117. * <li>AbstractDocument.SectionElementName
  118. * <li>StyleConstants.ComponentElementName
  119. * <li>StyleConstants.IconElementName
  120. * </ul>
  121. *
  122. * @return the factory
  123. */
  124. public ViewFactory getViewFactory() {
  125. return defaultFactory;
  126. }
  127. /**
  128. * Creates a copy of the editor kit.
  129. *
  130. * @return the copy
  131. */
  132. public Object clone() {
  133. StyledEditorKit o = (StyledEditorKit)super.clone();
  134. o.currentRun = o.currentParagraph = null;
  135. o.createInputAttributeUpdated();
  136. o.createInputAttributes();
  137. return o;
  138. }
  139. /**
  140. * Creates the AttributeSet used for the selection.
  141. */
  142. private void createInputAttributes() {
  143. inputAttributes = new SimpleAttributeSet() {
  144. public AttributeSet getResolveParent() {
  145. return (currentParagraph != null) ?
  146. currentParagraph.getAttributes() : null;
  147. }
  148. public Object clone() {
  149. return new SimpleAttributeSet(this);
  150. }
  151. };
  152. }
  153. /**
  154. * Creates a new <code>AttributeTracker</code>.
  155. */
  156. private void createInputAttributeUpdated() {
  157. inputAttributeUpdater = new AttributeTracker();
  158. }
  159. private static final ViewFactory defaultFactory = new StyledViewFactory();
  160. Element currentRun;
  161. Element currentParagraph;
  162. /**
  163. * This is the set of attributes used to store the
  164. * input attributes.
  165. */
  166. MutableAttributeSet inputAttributes;
  167. /**
  168. * This listener will be attached to the caret of
  169. * the text component that the EditorKit gets installed
  170. * into. This should keep the input attributes updated
  171. * for use by the styled actions.
  172. */
  173. private AttributeTracker inputAttributeUpdater;
  174. /**
  175. * Tracks caret movement and keeps the input attributes set
  176. * to reflect the current set of attribute definitions at the
  177. * caret position.
  178. * <p>This implements PropertyChangeListener to update the
  179. * input attributes when the Document changes, as if the Document
  180. * changes the attributes will almost certainly change.
  181. */
  182. class AttributeTracker implements CaretListener, PropertyChangeListener, Serializable {
  183. /**
  184. * Updates the attributes. <code>dot</code> and <code>mark</code>
  185. * mark give the positions of the selection in <code>c</code>.
  186. */
  187. void updateInputAttributes(int dot, int mark, JTextComponent c) {
  188. // EditorKit might not have installed the StyledDocument yet.
  189. Document aDoc = c.getDocument();
  190. if (!(aDoc instanceof StyledDocument)) {
  191. return ;
  192. }
  193. int start = Math.min(dot, mark);
  194. // record current character attributes.
  195. StyledDocument doc = (StyledDocument)aDoc;
  196. // If nothing is selected, get the attributes from the character
  197. // before the start of the selection, otherwise get the attributes
  198. // from the character element at the start of the selection.
  199. Element run;
  200. currentParagraph = doc.getParagraphElement(start);
  201. if (currentParagraph.getStartOffset() == start || dot != mark) {
  202. // Get the attributes from the character at the selection
  203. // if in a different paragrah!
  204. run = doc.getCharacterElement(start);
  205. }
  206. else {
  207. run = doc.getCharacterElement(Math.max(start-1, 0));
  208. }
  209. if (run != currentRun) {
  210. /*
  211. * PENDING(prinz) All attributes that represent a single
  212. * glyph position and can't be inserted into should be
  213. * removed from the input attributes... this requires
  214. * mixing in an interface to indicate that condition.
  215. * When we can add things again this logic needs to be
  216. * improved!!
  217. */
  218. currentRun = run;
  219. createInputAttributes(currentRun, getInputAttributes());
  220. }
  221. }
  222. public void propertyChange(PropertyChangeEvent evt) {
  223. Object newValue = evt.getNewValue();
  224. Object source = evt.getSource();
  225. if ((source instanceof JTextComponent) &&
  226. (newValue instanceof Document)) {
  227. // New document will have changed selection to 0,0.
  228. updateInputAttributes(0, 0, (JTextComponent)source);
  229. }
  230. }
  231. public void caretUpdate(CaretEvent e) {
  232. updateInputAttributes(e.getDot(), e.getMark(),
  233. (JTextComponent)e.getSource());
  234. }
  235. }
  236. /**
  237. * Copies the key/values in <code>element</code>s AttributeSet into
  238. * <code>set</code>. This does not copy component, icon, or element
  239. * names attributes. Subclasses may wish to refine what is and what
  240. * isn't copied here. But be sure to first remove all the attributes that
  241. * are in <code>set</code>.<p>
  242. * This is called anytime the caret moves over a different location.
  243. *
  244. */
  245. protected void createInputAttributes(Element element,
  246. MutableAttributeSet set) {
  247. set.removeAttributes(set);
  248. set.addAttributes(element.getAttributes());
  249. set.removeAttribute(StyleConstants.ComponentAttribute);
  250. set.removeAttribute(StyleConstants.IconAttribute);
  251. set.removeAttribute(AbstractDocument.ElementNameAttribute);
  252. set.removeAttribute(StyleConstants.ComposedTextAttribute);
  253. }
  254. // ---- default ViewFactory implementation ---------------------
  255. static class StyledViewFactory implements ViewFactory {
  256. public View create(Element elem) {
  257. String kind = elem.getName();
  258. if (kind != null) {
  259. if (kind.equals(AbstractDocument.ContentElementName)) {
  260. return new LabelView(elem);
  261. } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
  262. return new ParagraphView(elem);
  263. } else if (kind.equals(AbstractDocument.SectionElementName)) {
  264. return new BoxView(elem, View.Y_AXIS);
  265. } else if (kind.equals(StyleConstants.ComponentElementName)) {
  266. return new ComponentView(elem);
  267. } else if (kind.equals(StyleConstants.IconElementName)) {
  268. return new IconView(elem);
  269. }
  270. }
  271. // default to text display
  272. return new LabelView(elem);
  273. }
  274. }
  275. // --- Action implementations ---------------------------------
  276. private static final Action[] defaultActions = {
  277. new FontFamilyAction("font-family-SansSerif", "SansSerif"),
  278. new FontFamilyAction("font-family-Monospaced", "Monospaced"),
  279. new FontFamilyAction("font-family-Serif", "Serif"),
  280. new FontSizeAction("font-size-8", 8),
  281. new FontSizeAction("font-size-10", 10),
  282. new FontSizeAction("font-size-12", 12),
  283. new FontSizeAction("font-size-14", 14),
  284. new FontSizeAction("font-size-16", 16),
  285. new FontSizeAction("font-size-18", 18),
  286. new FontSizeAction("font-size-24", 24),
  287. new FontSizeAction("font-size-36", 36),
  288. new FontSizeAction("font-size-48", 48),
  289. new AlignmentAction("left-justify", StyleConstants.ALIGN_LEFT),
  290. new AlignmentAction("center-justify", StyleConstants.ALIGN_CENTER),
  291. new AlignmentAction("right-justify", StyleConstants.ALIGN_RIGHT),
  292. new BoldAction(),
  293. new ItalicAction(),
  294. new StyledInsertBreakAction(),
  295. new UnderlineAction()
  296. };
  297. /**
  298. * An action that assumes it's being fired on a JEditorPane
  299. * with a StyledEditorKit (or subclass) installed. This has
  300. * some convenience methods for causing character or paragraph
  301. * level attribute changes. The convenience methods will
  302. * throw an IllegalArgumentException if the assumption of
  303. * a StyledDocument, a JEditorPane, or a StyledEditorKit
  304. * fail to be true.
  305. * <p>
  306. * The component that gets acted upon by the action
  307. * will be the source of the ActionEvent if the source
  308. * can be narrowed to a JEditorPane type. If the source
  309. * can't be narrowed, the most recently focused text
  310. * component is changed. If neither of these are the
  311. * case, the action cannot be performed.
  312. * <p>
  313. * <strong>Warning:</strong>
  314. * Serialized objects of this class will not be compatible with
  315. * future Swing releases. The current serialization support is
  316. * appropriate for short term storage or RMI between applications running
  317. * the same version of Swing. As of 1.4, support for long term storage
  318. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  319. * has been added to the <code>java.beans</code> package.
  320. * Please see {@link java.beans.XMLEncoder}.
  321. */
  322. public abstract static class StyledTextAction extends TextAction {
  323. /**
  324. * Creates a new StyledTextAction from a string action name.
  325. *
  326. * @param nm the name of the action
  327. */
  328. public StyledTextAction(String nm) {
  329. super(nm);
  330. }
  331. /**
  332. * Gets the target editor for an action.
  333. *
  334. * @param e the action event
  335. * @return the editor
  336. */
  337. protected final JEditorPane getEditor(ActionEvent e) {
  338. JTextComponent tcomp = getTextComponent(e);
  339. if (tcomp instanceof JEditorPane) {
  340. return (JEditorPane) tcomp;
  341. }
  342. return null;
  343. }
  344. /**
  345. * Gets the document associated with an editor pane.
  346. *
  347. * @param e the editor
  348. * @return the document
  349. * @exception IllegalArgumentException for the wrong document type
  350. */
  351. protected final StyledDocument getStyledDocument(JEditorPane e) {
  352. Document d = e.getDocument();
  353. if (d instanceof StyledDocument) {
  354. return (StyledDocument) d;
  355. }
  356. throw new IllegalArgumentException("document must be StyledDocument");
  357. }
  358. /**
  359. * Gets the editor kit associated with an editor pane.
  360. *
  361. * @param e the editor pane
  362. * @return the kit
  363. * @exception IllegalArgumentException for the wrong document type
  364. */
  365. protected final StyledEditorKit getStyledEditorKit(JEditorPane e) {
  366. EditorKit k = e.getEditorKit();
  367. if (k instanceof StyledEditorKit) {
  368. return (StyledEditorKit) k;
  369. }
  370. throw new IllegalArgumentException("EditorKit must be StyledEditorKit");
  371. }
  372. /**
  373. * Applies the given attributes to character
  374. * content. If there is a selection, the attributes
  375. * are applied to the selection range. If there
  376. * is no selection, the attributes are applied to
  377. * the input attribute set which defines the attributes
  378. * for any new text that gets inserted.
  379. *
  380. * @param editor the editor
  381. * @param attr the attributes
  382. * @param replace if true, then replace the existing attributes first
  383. */
  384. protected final void setCharacterAttributes(JEditorPane editor,
  385. AttributeSet attr, boolean replace) {
  386. int p0 = editor.getSelectionStart();
  387. int p1 = editor.getSelectionEnd();
  388. if (p0 != p1) {
  389. StyledDocument doc = getStyledDocument(editor);
  390. doc.setCharacterAttributes(p0, p1 - p0, attr, replace);
  391. }
  392. StyledEditorKit k = getStyledEditorKit(editor);
  393. MutableAttributeSet inputAttributes = k.getInputAttributes();
  394. if (replace) {
  395. inputAttributes.removeAttributes(inputAttributes);
  396. }
  397. inputAttributes.addAttributes(attr);
  398. }
  399. /**
  400. * Applies the given attributes to paragraphs. If
  401. * there is a selection, the attributes are applied
  402. * to the paragraphs that intersect the selection.
  403. * if there is no selection, the attributes are applied
  404. * to the paragraph at the current caret position.
  405. *
  406. * @param editor the editor
  407. * @param attr the attributes
  408. * @param replace if true, replace the existing attributes first
  409. */
  410. protected final void setParagraphAttributes(JEditorPane editor,
  411. AttributeSet attr, boolean replace) {
  412. int p0 = editor.getSelectionStart();
  413. int p1 = editor.getSelectionEnd();
  414. StyledDocument doc = getStyledDocument(editor);
  415. doc.setParagraphAttributes(p0, p1 - p0, attr, replace);
  416. }
  417. }
  418. /**
  419. * An action to set the font family in the associated
  420. * JEditorPane. This will use the family specified as
  421. * the command string on the ActionEvent if there is one,
  422. * otherwise the family that was initialized with will be used.
  423. * <p>
  424. * <strong>Warning:</strong>
  425. * Serialized objects of this class will not be compatible with
  426. * future Swing releases. The current serialization support is
  427. * appropriate for short term storage or RMI between applications running
  428. * the same version of Swing. As of 1.4, support for long term storage
  429. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  430. * has been added to the <code>java.beans</code> package.
  431. * Please see {@link java.beans.XMLEncoder}.
  432. */
  433. public static class FontFamilyAction extends StyledTextAction {
  434. /**
  435. * Creates a new FontFamilyAction.
  436. *
  437. * @param nm the action name
  438. * @param family the font family
  439. */
  440. public FontFamilyAction(String nm, String family) {
  441. super(nm);
  442. this.family = family;
  443. }
  444. /**
  445. * Sets the font family.
  446. *
  447. * @param e the event
  448. */
  449. public void actionPerformed(ActionEvent e) {
  450. JEditorPane editor = getEditor(e);
  451. if (editor != null) {
  452. String family = this.family;
  453. if ((e != null) && (e.getSource() == editor)) {
  454. String s = e.getActionCommand();
  455. if (s != null) {
  456. family = s;
  457. }
  458. }
  459. if (family != null) {
  460. MutableAttributeSet attr = new SimpleAttributeSet();
  461. StyleConstants.setFontFamily(attr, family);
  462. setCharacterAttributes(editor, attr, false);
  463. } else {
  464. UIManager.getLookAndFeel().provideErrorFeedback(editor);
  465. }
  466. }
  467. }
  468. private String family;
  469. }
  470. /**
  471. * An action to set the font size in the associated
  472. * JEditorPane. This will use the size specified as
  473. * the command string on the ActionEvent if there is one,
  474. * otherwise the size that was initialized with will be used.
  475. * <p>
  476. * <strong>Warning:</strong>
  477. * Serialized objects of this class will not be compatible with
  478. * future Swing releases. The current serialization support is
  479. * appropriate for short term storage or RMI between applications running
  480. * the same version of Swing. As of 1.4, support for long term storage
  481. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  482. * has been added to the <code>java.beans</code> package.
  483. * Please see {@link java.beans.XMLEncoder}.
  484. */
  485. public static class FontSizeAction extends StyledTextAction {
  486. /**
  487. * Creates a new FontSizeAction.
  488. *
  489. * @param nm the action name
  490. * @param size the font size
  491. */
  492. public FontSizeAction(String nm, int size) {
  493. super(nm);
  494. this.size = size;
  495. }
  496. /**
  497. * Sets the font size.
  498. *
  499. * @param e the action event
  500. */
  501. public void actionPerformed(ActionEvent e) {
  502. JEditorPane editor = getEditor(e);
  503. if (editor != null) {
  504. int size = this.size;
  505. if ((e != null) && (e.getSource() == editor)) {
  506. String s = e.getActionCommand();
  507. try {
  508. size = Integer.parseInt(s, 10);
  509. } catch (NumberFormatException nfe) {
  510. }
  511. }
  512. if (size != 0) {
  513. MutableAttributeSet attr = new SimpleAttributeSet();
  514. StyleConstants.setFontSize(attr, size);
  515. setCharacterAttributes(editor, attr, false);
  516. } else {
  517. UIManager.getLookAndFeel().provideErrorFeedback(editor);
  518. }
  519. }
  520. }
  521. private int size;
  522. }
  523. /**
  524. * An action to set foreground color. This sets the
  525. * <code>StyleConstants.Foreground</code> attribute for the
  526. * currently selected range of the target JEditorPane.
  527. * This is done by calling
  528. * <code>StyledDocument.setCharacterAttributes</code>
  529. * on the styled document associated with the target
  530. * JEditorPane.
  531. * <p>
  532. * If the target text component is specified as the
  533. * source of the ActionEvent and there is a command string,
  534. * the command string will be interpreted as the foreground
  535. * color. It will be interpreted by called
  536. * <code>Color.decode</code>, and should therefore be
  537. * legal input for that method.
  538. * <p>
  539. * <strong>Warning:</strong>
  540. * Serialized objects of this class will not be compatible with
  541. * future Swing releases. The current serialization support is
  542. * appropriate for short term storage or RMI between applications running
  543. * the same version of Swing. As of 1.4, support for long term storage
  544. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  545. * has been added to the <code>java.beans</code> package.
  546. * Please see {@link java.beans.XMLEncoder}.
  547. */
  548. public static class ForegroundAction extends StyledTextAction {
  549. /**
  550. * Creates a new ForegroundAction.
  551. *
  552. * @param nm the action name
  553. * @param fg the foreground color
  554. */
  555. public ForegroundAction(String nm, Color fg) {
  556. super(nm);
  557. this.fg = fg;
  558. }
  559. /**
  560. * Sets the foreground color.
  561. *
  562. * @param e the action event
  563. */
  564. public void actionPerformed(ActionEvent e) {
  565. JEditorPane editor = getEditor(e);
  566. if (editor != null) {
  567. Color fg = this.fg;
  568. if ((e != null) && (e.getSource() == editor)) {
  569. String s = e.getActionCommand();
  570. try {
  571. fg = Color.decode(s);
  572. } catch (NumberFormatException nfe) {
  573. }
  574. }
  575. if (fg != null) {
  576. MutableAttributeSet attr = new SimpleAttributeSet();
  577. StyleConstants.setForeground(attr, fg);
  578. setCharacterAttributes(editor, attr, false);
  579. } else {
  580. UIManager.getLookAndFeel().provideErrorFeedback(editor);
  581. }
  582. }
  583. }
  584. private Color fg;
  585. }
  586. /**
  587. * An action to set paragraph alignment. This sets the
  588. * <code>StyleConstants.Alignment</code> attribute for the
  589. * currently selected range of the target JEditorPane.
  590. * This is done by calling
  591. * <code>StyledDocument.setParagraphAttributes</code>
  592. * on the styled document associated with the target
  593. * JEditorPane.
  594. * <p>
  595. * If the target text component is specified as the
  596. * source of the ActionEvent and there is a command string,
  597. * the command string will be interpreted as an integer
  598. * that should be one of the legal values for the
  599. * <code>StyleConstants.Alignment</code> attribute.
  600. * <p>
  601. * <strong>Warning:</strong>
  602. * Serialized objects of this class will not be compatible with
  603. * future Swing releases. The current serialization support is
  604. * appropriate for short term storage or RMI between applications running
  605. * the same version of Swing. As of 1.4, support for long term storage
  606. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  607. * has been added to the <code>java.beans</code> package.
  608. * Please see {@link java.beans.XMLEncoder}.
  609. */
  610. public static class AlignmentAction extends StyledTextAction {
  611. /**
  612. * Creates a new AlignmentAction.
  613. *
  614. * @param nm the action name
  615. * @param a the alignment >= 0
  616. */
  617. public AlignmentAction(String nm, int a) {
  618. super(nm);
  619. this.a = a;
  620. }
  621. /**
  622. * Sets the alignment.
  623. *
  624. * @param e the action event
  625. */
  626. public void actionPerformed(ActionEvent e) {
  627. JEditorPane editor = getEditor(e);
  628. if (editor != null) {
  629. int a = this.a;
  630. if ((e != null) && (e.getSource() == editor)) {
  631. String s = e.getActionCommand();
  632. try {
  633. a = Integer.parseInt(s, 10);
  634. } catch (NumberFormatException nfe) {
  635. }
  636. }
  637. MutableAttributeSet attr = new SimpleAttributeSet();
  638. StyleConstants.setAlignment(attr, a);
  639. setParagraphAttributes(editor, attr, false);
  640. }
  641. }
  642. private int a;
  643. }
  644. /**
  645. * An action to toggle the bold attribute.
  646. * <p>
  647. * <strong>Warning:</strong>
  648. * Serialized objects of this class will not be compatible with
  649. * future Swing releases. The current serialization support is
  650. * appropriate for short term storage or RMI between applications running
  651. * the same version of Swing. As of 1.4, support for long term storage
  652. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  653. * has been added to the <code>java.beans</code> package.
  654. * Please see {@link java.beans.XMLEncoder}.
  655. */
  656. public static class BoldAction extends StyledTextAction {
  657. /**
  658. * Constructs a new BoldAction.
  659. */
  660. public BoldAction() {
  661. super("font-bold");
  662. }
  663. /**
  664. * Toggles the bold attribute.
  665. *
  666. * @param e the action event
  667. */
  668. public void actionPerformed(ActionEvent e) {
  669. JEditorPane editor = getEditor(e);
  670. if (editor != null) {
  671. StyledEditorKit kit = getStyledEditorKit(editor);
  672. MutableAttributeSet attr = kit.getInputAttributes();
  673. boolean bold = (StyleConstants.isBold(attr)) ? false : true;
  674. SimpleAttributeSet sas = new SimpleAttributeSet();
  675. StyleConstants.setBold(sas, bold);
  676. setCharacterAttributes(editor, sas, false);
  677. }
  678. }
  679. }
  680. /**
  681. * An action to toggle the italic attribute.
  682. * <p>
  683. * <strong>Warning:</strong>
  684. * Serialized objects of this class will not be compatible with
  685. * future Swing releases. The current serialization support is
  686. * appropriate for short term storage or RMI between applications running
  687. * the same version of Swing. As of 1.4, support for long term storage
  688. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  689. * has been added to the <code>java.beans</code> package.
  690. * Please see {@link java.beans.XMLEncoder}.
  691. */
  692. public static class ItalicAction extends StyledTextAction {
  693. /**
  694. * Constructs a new ItalicAction.
  695. */
  696. public ItalicAction() {
  697. super("font-italic");
  698. }
  699. /**
  700. * Toggles the italic attribute.
  701. *
  702. * @param e the action event
  703. */
  704. public void actionPerformed(ActionEvent e) {
  705. JEditorPane editor = getEditor(e);
  706. if (editor != null) {
  707. StyledEditorKit kit = getStyledEditorKit(editor);
  708. MutableAttributeSet attr = kit.getInputAttributes();
  709. boolean italic = (StyleConstants.isItalic(attr)) ? false : true;
  710. SimpleAttributeSet sas = new SimpleAttributeSet();
  711. StyleConstants.setItalic(sas, italic);
  712. setCharacterAttributes(editor, sas, false);
  713. }
  714. }
  715. }
  716. /**
  717. * An action to toggle the underline attribute.
  718. * <p>
  719. * <strong>Warning:</strong>
  720. * Serialized objects of this class will not be compatible with
  721. * future Swing releases. The current serialization support is
  722. * appropriate for short term storage or RMI between applications running
  723. * the same version of Swing. As of 1.4, support for long term storage
  724. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  725. * has been added to the <code>java.beans</code> package.
  726. * Please see {@link java.beans.XMLEncoder}.
  727. */
  728. public static class UnderlineAction extends StyledTextAction {
  729. /**
  730. * Constructs a new UnderlineAction.
  731. */
  732. public UnderlineAction() {
  733. super("font-underline");
  734. }
  735. /**
  736. * Toggles the Underline attribute.
  737. *
  738. * @param e the action event
  739. */
  740. public void actionPerformed(ActionEvent e) {
  741. JEditorPane editor = getEditor(e);
  742. if (editor != null) {
  743. StyledEditorKit kit = getStyledEditorKit(editor);
  744. MutableAttributeSet attr = kit.getInputAttributes();
  745. boolean underline = (StyleConstants.isUnderline(attr)) ? false : true;
  746. SimpleAttributeSet sas = new SimpleAttributeSet();
  747. StyleConstants.setUnderline(sas, underline);
  748. setCharacterAttributes(editor, sas, false);
  749. }
  750. }
  751. }
  752. /**
  753. * StyledInsertBreakAction has similar behavior to that of
  754. * <code>DefaultEditorKit.InsertBreakAction</code>. That is when
  755. * its <code>actionPerformed</code> method is invoked, a newline
  756. * is inserted. Beyond that, this will reset the input attributes to
  757. * what they were before the newline was inserted.
  758. */
  759. static class StyledInsertBreakAction extends StyledTextAction {
  760. private SimpleAttributeSet tempSet;
  761. StyledInsertBreakAction() {
  762. super(insertBreakAction);
  763. }
  764. public void actionPerformed(ActionEvent e) {
  765. JEditorPane target = getEditor(e);
  766. if (target != null) {
  767. if ((!target.isEditable()) || (!target.isEnabled())) {
  768. UIManager.getLookAndFeel().provideErrorFeedback(target);
  769. return;
  770. }
  771. StyledEditorKit sek = getStyledEditorKit(target);
  772. if (tempSet != null) {
  773. tempSet.removeAttributes(tempSet);
  774. }
  775. else {
  776. tempSet = new SimpleAttributeSet();
  777. }
  778. tempSet.addAttributes(sek.getInputAttributes());
  779. target.replaceSelection("\n");
  780. MutableAttributeSet ia = sek.getInputAttributes();
  781. ia.removeAttributes(ia);
  782. ia.addAttributes(tempSet);
  783. tempSet.removeAttributes(tempSet);
  784. }
  785. else {
  786. // See if we are in a JTextComponent.
  787. JTextComponent text = getTextComponent(e);
  788. if (text != null) {
  789. if ((!text.isEditable()) || (!text.isEnabled())) {
  790. UIManager.getLookAndFeel().provideErrorFeedback(target);
  791. return;
  792. }
  793. text.replaceSelection("\n");
  794. }
  795. }
  796. }
  797. }
  798. }