1. /*
  2. * @(#)StyledEditorKit.java 1.45 04/02/04
  3. *
  4. * Copyright 2004 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.45 02/04/04
  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. if (element.getAttributes().getAttributeCount() > 0
  248. || element.getEndOffset() - element.getStartOffset() > 1
  249. || element.getEndOffset() < element.getDocument().getLength()) {
  250. set.removeAttributes(set);
  251. set.addAttributes(element.getAttributes());
  252. set.removeAttribute(StyleConstants.ComponentAttribute);
  253. set.removeAttribute(StyleConstants.IconAttribute);
  254. set.removeAttribute(AbstractDocument.ElementNameAttribute);
  255. set.removeAttribute(StyleConstants.ComposedTextAttribute);
  256. }
  257. }
  258. // ---- default ViewFactory implementation ---------------------
  259. static class StyledViewFactory implements ViewFactory {
  260. public View create(Element elem) {
  261. String kind = elem.getName();
  262. if (kind != null) {
  263. if (kind.equals(AbstractDocument.ContentElementName)) {
  264. return new LabelView(elem);
  265. } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
  266. return new ParagraphView(elem);
  267. } else if (kind.equals(AbstractDocument.SectionElementName)) {
  268. return new BoxView(elem, View.Y_AXIS);
  269. } else if (kind.equals(StyleConstants.ComponentElementName)) {
  270. return new ComponentView(elem);
  271. } else if (kind.equals(StyleConstants.IconElementName)) {
  272. return new IconView(elem);
  273. }
  274. }
  275. // default to text display
  276. return new LabelView(elem);
  277. }
  278. }
  279. // --- Action implementations ---------------------------------
  280. private static final Action[] defaultActions = {
  281. new FontFamilyAction("font-family-SansSerif", "SansSerif"),
  282. new FontFamilyAction("font-family-Monospaced", "Monospaced"),
  283. new FontFamilyAction("font-family-Serif", "Serif"),
  284. new FontSizeAction("font-size-8", 8),
  285. new FontSizeAction("font-size-10", 10),
  286. new FontSizeAction("font-size-12", 12),
  287. new FontSizeAction("font-size-14", 14),
  288. new FontSizeAction("font-size-16", 16),
  289. new FontSizeAction("font-size-18", 18),
  290. new FontSizeAction("font-size-24", 24),
  291. new FontSizeAction("font-size-36", 36),
  292. new FontSizeAction("font-size-48", 48),
  293. new AlignmentAction("left-justify", StyleConstants.ALIGN_LEFT),
  294. new AlignmentAction("center-justify", StyleConstants.ALIGN_CENTER),
  295. new AlignmentAction("right-justify", StyleConstants.ALIGN_RIGHT),
  296. new BoldAction(),
  297. new ItalicAction(),
  298. new StyledInsertBreakAction(),
  299. new UnderlineAction()
  300. };
  301. /**
  302. * An action that assumes it's being fired on a JEditorPane
  303. * with a StyledEditorKit (or subclass) installed. This has
  304. * some convenience methods for causing character or paragraph
  305. * level attribute changes. The convenience methods will
  306. * throw an IllegalArgumentException if the assumption of
  307. * a StyledDocument, a JEditorPane, or a StyledEditorKit
  308. * fail to be true.
  309. * <p>
  310. * The component that gets acted upon by the action
  311. * will be the source of the ActionEvent if the source
  312. * can be narrowed to a JEditorPane type. If the source
  313. * can't be narrowed, the most recently focused text
  314. * component is changed. If neither of these are the
  315. * case, the action cannot be performed.
  316. * <p>
  317. * <strong>Warning:</strong>
  318. * Serialized objects of this class will not be compatible with
  319. * future Swing releases. The current serialization support is
  320. * appropriate for short term storage or RMI between applications running
  321. * the same version of Swing. As of 1.4, support for long term storage
  322. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  323. * has been added to the <code>java.beans</code> package.
  324. * Please see {@link java.beans.XMLEncoder}.
  325. */
  326. public abstract static class StyledTextAction extends TextAction {
  327. /**
  328. * Creates a new StyledTextAction from a string action name.
  329. *
  330. * @param nm the name of the action
  331. */
  332. public StyledTextAction(String nm) {
  333. super(nm);
  334. }
  335. /**
  336. * Gets the target editor for an action.
  337. *
  338. * @param e the action event
  339. * @return the editor
  340. */
  341. protected final JEditorPane getEditor(ActionEvent e) {
  342. JTextComponent tcomp = getTextComponent(e);
  343. if (tcomp instanceof JEditorPane) {
  344. return (JEditorPane) tcomp;
  345. }
  346. return null;
  347. }
  348. /**
  349. * Gets the document associated with an editor pane.
  350. *
  351. * @param e the editor
  352. * @return the document
  353. * @exception IllegalArgumentException for the wrong document type
  354. */
  355. protected final StyledDocument getStyledDocument(JEditorPane e) {
  356. Document d = e.getDocument();
  357. if (d instanceof StyledDocument) {
  358. return (StyledDocument) d;
  359. }
  360. throw new IllegalArgumentException("document must be StyledDocument");
  361. }
  362. /**
  363. * Gets the editor kit associated with an editor pane.
  364. *
  365. * @param e the editor pane
  366. * @return the kit
  367. * @exception IllegalArgumentException for the wrong document type
  368. */
  369. protected final StyledEditorKit getStyledEditorKit(JEditorPane e) {
  370. EditorKit k = e.getEditorKit();
  371. if (k instanceof StyledEditorKit) {
  372. return (StyledEditorKit) k;
  373. }
  374. throw new IllegalArgumentException("EditorKit must be StyledEditorKit");
  375. }
  376. /**
  377. * Applies the given attributes to character
  378. * content. If there is a selection, the attributes
  379. * are applied to the selection range. If there
  380. * is no selection, the attributes are applied to
  381. * the input attribute set which defines the attributes
  382. * for any new text that gets inserted.
  383. *
  384. * @param editor the editor
  385. * @param attr the attributes
  386. * @param replace if true, then replace the existing attributes first
  387. */
  388. protected final void setCharacterAttributes(JEditorPane editor,
  389. AttributeSet attr, boolean replace) {
  390. int p0 = editor.getSelectionStart();
  391. int p1 = editor.getSelectionEnd();
  392. if (p0 != p1) {
  393. StyledDocument doc = getStyledDocument(editor);
  394. doc.setCharacterAttributes(p0, p1 - p0, attr, replace);
  395. }
  396. StyledEditorKit k = getStyledEditorKit(editor);
  397. MutableAttributeSet inputAttributes = k.getInputAttributes();
  398. if (replace) {
  399. inputAttributes.removeAttributes(inputAttributes);
  400. }
  401. inputAttributes.addAttributes(attr);
  402. }
  403. /**
  404. * Applies the given attributes to paragraphs. If
  405. * there is a selection, the attributes are applied
  406. * to the paragraphs that intersect the selection.
  407. * if there is no selection, the attributes are applied
  408. * to the paragraph at the current caret position.
  409. *
  410. * @param editor the editor
  411. * @param attr the attributes
  412. * @param replace if true, replace the existing attributes first
  413. */
  414. protected final void setParagraphAttributes(JEditorPane editor,
  415. AttributeSet attr, boolean replace) {
  416. int p0 = editor.getSelectionStart();
  417. int p1 = editor.getSelectionEnd();
  418. StyledDocument doc = getStyledDocument(editor);
  419. doc.setParagraphAttributes(p0, p1 - p0, attr, replace);
  420. }
  421. }
  422. /**
  423. * An action to set the font family in the associated
  424. * JEditorPane. This will use the family specified as
  425. * the command string on the ActionEvent if there is one,
  426. * otherwise the family that was initialized with will be used.
  427. * <p>
  428. * <strong>Warning:</strong>
  429. * Serialized objects of this class will not be compatible with
  430. * future Swing releases. The current serialization support is
  431. * appropriate for short term storage or RMI between applications running
  432. * the same version of Swing. As of 1.4, support for long term storage
  433. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  434. * has been added to the <code>java.beans</code> package.
  435. * Please see {@link java.beans.XMLEncoder}.
  436. */
  437. public static class FontFamilyAction extends StyledTextAction {
  438. /**
  439. * Creates a new FontFamilyAction.
  440. *
  441. * @param nm the action name
  442. * @param family the font family
  443. */
  444. public FontFamilyAction(String nm, String family) {
  445. super(nm);
  446. this.family = family;
  447. }
  448. /**
  449. * Sets the font family.
  450. *
  451. * @param e the event
  452. */
  453. public void actionPerformed(ActionEvent e) {
  454. JEditorPane editor = getEditor(e);
  455. if (editor != null) {
  456. String family = this.family;
  457. if ((e != null) && (e.getSource() == editor)) {
  458. String s = e.getActionCommand();
  459. if (s != null) {
  460. family = s;
  461. }
  462. }
  463. if (family != null) {
  464. MutableAttributeSet attr = new SimpleAttributeSet();
  465. StyleConstants.setFontFamily(attr, family);
  466. setCharacterAttributes(editor, attr, false);
  467. } else {
  468. UIManager.getLookAndFeel().provideErrorFeedback(editor);
  469. }
  470. }
  471. }
  472. private String family;
  473. }
  474. /**
  475. * An action to set the font size in the associated
  476. * JEditorPane. This will use the size specified as
  477. * the command string on the ActionEvent if there is one,
  478. * otherwise the size that was initialized with will be used.
  479. * <p>
  480. * <strong>Warning:</strong>
  481. * Serialized objects of this class will not be compatible with
  482. * future Swing releases. The current serialization support is
  483. * appropriate for short term storage or RMI between applications running
  484. * the same version of Swing. As of 1.4, support for long term storage
  485. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  486. * has been added to the <code>java.beans</code> package.
  487. * Please see {@link java.beans.XMLEncoder}.
  488. */
  489. public static class FontSizeAction extends StyledTextAction {
  490. /**
  491. * Creates a new FontSizeAction.
  492. *
  493. * @param nm the action name
  494. * @param size the font size
  495. */
  496. public FontSizeAction(String nm, int size) {
  497. super(nm);
  498. this.size = size;
  499. }
  500. /**
  501. * Sets the font size.
  502. *
  503. * @param e the action event
  504. */
  505. public void actionPerformed(ActionEvent e) {
  506. JEditorPane editor = getEditor(e);
  507. if (editor != null) {
  508. int size = this.size;
  509. if ((e != null) && (e.getSource() == editor)) {
  510. String s = e.getActionCommand();
  511. try {
  512. size = Integer.parseInt(s, 10);
  513. } catch (NumberFormatException nfe) {
  514. }
  515. }
  516. if (size != 0) {
  517. MutableAttributeSet attr = new SimpleAttributeSet();
  518. StyleConstants.setFontSize(attr, size);
  519. setCharacterAttributes(editor, attr, false);
  520. } else {
  521. UIManager.getLookAndFeel().provideErrorFeedback(editor);
  522. }
  523. }
  524. }
  525. private int size;
  526. }
  527. /**
  528. * An action to set foreground color. This sets the
  529. * <code>StyleConstants.Foreground</code> attribute for the
  530. * currently selected range of the target JEditorPane.
  531. * This is done by calling
  532. * <code>StyledDocument.setCharacterAttributes</code>
  533. * on the styled document associated with the target
  534. * JEditorPane.
  535. * <p>
  536. * If the target text component is specified as the
  537. * source of the ActionEvent and there is a command string,
  538. * the command string will be interpreted as the foreground
  539. * color. It will be interpreted by called
  540. * <code>Color.decode</code>, and should therefore be
  541. * legal input for that method.
  542. * <p>
  543. * <strong>Warning:</strong>
  544. * Serialized objects of this class will not be compatible with
  545. * future Swing releases. The current serialization support is
  546. * appropriate for short term storage or RMI between applications running
  547. * the same version of Swing. As of 1.4, support for long term storage
  548. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  549. * has been added to the <code>java.beans</code> package.
  550. * Please see {@link java.beans.XMLEncoder}.
  551. */
  552. public static class ForegroundAction extends StyledTextAction {
  553. /**
  554. * Creates a new ForegroundAction.
  555. *
  556. * @param nm the action name
  557. * @param fg the foreground color
  558. */
  559. public ForegroundAction(String nm, Color fg) {
  560. super(nm);
  561. this.fg = fg;
  562. }
  563. /**
  564. * Sets the foreground color.
  565. *
  566. * @param e the action event
  567. */
  568. public void actionPerformed(ActionEvent e) {
  569. JEditorPane editor = getEditor(e);
  570. if (editor != null) {
  571. Color fg = this.fg;
  572. if ((e != null) && (e.getSource() == editor)) {
  573. String s = e.getActionCommand();
  574. try {
  575. fg = Color.decode(s);
  576. } catch (NumberFormatException nfe) {
  577. }
  578. }
  579. if (fg != null) {
  580. MutableAttributeSet attr = new SimpleAttributeSet();
  581. StyleConstants.setForeground(attr, fg);
  582. setCharacterAttributes(editor, attr, false);
  583. } else {
  584. UIManager.getLookAndFeel().provideErrorFeedback(editor);
  585. }
  586. }
  587. }
  588. private Color fg;
  589. }
  590. /**
  591. * An action to set paragraph alignment. This sets the
  592. * <code>StyleConstants.Alignment</code> attribute for the
  593. * currently selected range of the target JEditorPane.
  594. * This is done by calling
  595. * <code>StyledDocument.setParagraphAttributes</code>
  596. * on the styled document associated with the target
  597. * JEditorPane.
  598. * <p>
  599. * If the target text component is specified as the
  600. * source of the ActionEvent and there is a command string,
  601. * the command string will be interpreted as an integer
  602. * that should be one of the legal values for the
  603. * <code>StyleConstants.Alignment</code> attribute.
  604. * <p>
  605. * <strong>Warning:</strong>
  606. * Serialized objects of this class will not be compatible with
  607. * future Swing releases. The current serialization support is
  608. * appropriate for short term storage or RMI between applications running
  609. * the same version of Swing. As of 1.4, support for long term storage
  610. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  611. * has been added to the <code>java.beans</code> package.
  612. * Please see {@link java.beans.XMLEncoder}.
  613. */
  614. public static class AlignmentAction extends StyledTextAction {
  615. /**
  616. * Creates a new AlignmentAction.
  617. *
  618. * @param nm the action name
  619. * @param a the alignment >= 0
  620. */
  621. public AlignmentAction(String nm, int a) {
  622. super(nm);
  623. this.a = a;
  624. }
  625. /**
  626. * Sets the alignment.
  627. *
  628. * @param e the action event
  629. */
  630. public void actionPerformed(ActionEvent e) {
  631. JEditorPane editor = getEditor(e);
  632. if (editor != null) {
  633. int a = this.a;
  634. if ((e != null) && (e.getSource() == editor)) {
  635. String s = e.getActionCommand();
  636. try {
  637. a = Integer.parseInt(s, 10);
  638. } catch (NumberFormatException nfe) {
  639. }
  640. }
  641. MutableAttributeSet attr = new SimpleAttributeSet();
  642. StyleConstants.setAlignment(attr, a);
  643. setParagraphAttributes(editor, attr, false);
  644. }
  645. }
  646. private int a;
  647. }
  648. /**
  649. * An action to toggle the bold attribute.
  650. * <p>
  651. * <strong>Warning:</strong>
  652. * Serialized objects of this class will not be compatible with
  653. * future Swing releases. The current serialization support is
  654. * appropriate for short term storage or RMI between applications running
  655. * the same version of Swing. As of 1.4, support for long term storage
  656. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  657. * has been added to the <code>java.beans</code> package.
  658. * Please see {@link java.beans.XMLEncoder}.
  659. */
  660. public static class BoldAction extends StyledTextAction {
  661. /**
  662. * Constructs a new BoldAction.
  663. */
  664. public BoldAction() {
  665. super("font-bold");
  666. }
  667. /**
  668. * Toggles the bold attribute.
  669. *
  670. * @param e the action event
  671. */
  672. public void actionPerformed(ActionEvent e) {
  673. JEditorPane editor = getEditor(e);
  674. if (editor != null) {
  675. StyledEditorKit kit = getStyledEditorKit(editor);
  676. MutableAttributeSet attr = kit.getInputAttributes();
  677. boolean bold = (StyleConstants.isBold(attr)) ? false : true;
  678. SimpleAttributeSet sas = new SimpleAttributeSet();
  679. StyleConstants.setBold(sas, bold);
  680. setCharacterAttributes(editor, sas, false);
  681. }
  682. }
  683. }
  684. /**
  685. * An action to toggle the italic attribute.
  686. * <p>
  687. * <strong>Warning:</strong>
  688. * Serialized objects of this class will not be compatible with
  689. * future Swing releases. The current serialization support is
  690. * appropriate for short term storage or RMI between applications running
  691. * the same version of Swing. As of 1.4, support for long term storage
  692. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  693. * has been added to the <code>java.beans</code> package.
  694. * Please see {@link java.beans.XMLEncoder}.
  695. */
  696. public static class ItalicAction extends StyledTextAction {
  697. /**
  698. * Constructs a new ItalicAction.
  699. */
  700. public ItalicAction() {
  701. super("font-italic");
  702. }
  703. /**
  704. * Toggles the italic attribute.
  705. *
  706. * @param e the action event
  707. */
  708. public void actionPerformed(ActionEvent e) {
  709. JEditorPane editor = getEditor(e);
  710. if (editor != null) {
  711. StyledEditorKit kit = getStyledEditorKit(editor);
  712. MutableAttributeSet attr = kit.getInputAttributes();
  713. boolean italic = (StyleConstants.isItalic(attr)) ? false : true;
  714. SimpleAttributeSet sas = new SimpleAttributeSet();
  715. StyleConstants.setItalic(sas, italic);
  716. setCharacterAttributes(editor, sas, false);
  717. }
  718. }
  719. }
  720. /**
  721. * An action to toggle the underline attribute.
  722. * <p>
  723. * <strong>Warning:</strong>
  724. * Serialized objects of this class will not be compatible with
  725. * future Swing releases. The current serialization support is
  726. * appropriate for short term storage or RMI between applications running
  727. * the same version of Swing. As of 1.4, support for long term storage
  728. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  729. * has been added to the <code>java.beans</code> package.
  730. * Please see {@link java.beans.XMLEncoder}.
  731. */
  732. public static class UnderlineAction extends StyledTextAction {
  733. /**
  734. * Constructs a new UnderlineAction.
  735. */
  736. public UnderlineAction() {
  737. super("font-underline");
  738. }
  739. /**
  740. * Toggles the Underline attribute.
  741. *
  742. * @param e the action event
  743. */
  744. public void actionPerformed(ActionEvent e) {
  745. JEditorPane editor = getEditor(e);
  746. if (editor != null) {
  747. StyledEditorKit kit = getStyledEditorKit(editor);
  748. MutableAttributeSet attr = kit.getInputAttributes();
  749. boolean underline = (StyleConstants.isUnderline(attr)) ? false : true;
  750. SimpleAttributeSet sas = new SimpleAttributeSet();
  751. StyleConstants.setUnderline(sas, underline);
  752. setCharacterAttributes(editor, sas, false);
  753. }
  754. }
  755. }
  756. /**
  757. * StyledInsertBreakAction has similar behavior to that of
  758. * <code>DefaultEditorKit.InsertBreakAction</code>. That is when
  759. * its <code>actionPerformed</code> method is invoked, a newline
  760. * is inserted. Beyond that, this will reset the input attributes to
  761. * what they were before the newline was inserted.
  762. */
  763. static class StyledInsertBreakAction extends StyledTextAction {
  764. private SimpleAttributeSet tempSet;
  765. StyledInsertBreakAction() {
  766. super(insertBreakAction);
  767. }
  768. public void actionPerformed(ActionEvent e) {
  769. JEditorPane target = getEditor(e);
  770. if (target != null) {
  771. if ((!target.isEditable()) || (!target.isEnabled())) {
  772. UIManager.getLookAndFeel().provideErrorFeedback(target);
  773. return;
  774. }
  775. StyledEditorKit sek = getStyledEditorKit(target);
  776. if (tempSet != null) {
  777. tempSet.removeAttributes(tempSet);
  778. }
  779. else {
  780. tempSet = new SimpleAttributeSet();
  781. }
  782. tempSet.addAttributes(sek.getInputAttributes());
  783. target.replaceSelection("\n");
  784. MutableAttributeSet ia = sek.getInputAttributes();
  785. ia.removeAttributes(ia);
  786. ia.addAttributes(tempSet);
  787. tempSet.removeAttributes(tempSet);
  788. }
  789. else {
  790. // See if we are in a JTextComponent.
  791. JTextComponent text = getTextComponent(e);
  792. if (text != null) {
  793. if ((!text.isEditable()) || (!text.isEnabled())) {
  794. UIManager.getLookAndFeel().provideErrorFeedback(target);
  795. return;
  796. }
  797. text.replaceSelection("\n");
  798. }
  799. }
  800. }
  801. }
  802. }