/* * Created on Feb 25, 2005 * */ package net.atlanticbb.tantlinger.ui.text.actions; import java.awt.Event; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import javax.swing.Action; import javax.swing.Icon; import javax.swing.JEditorPane; import javax.swing.KeyStroke; import javax.swing.text.AttributeSet; import javax.swing.text.MutableAttributeSet; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.html.CSS; import javax.swing.text.html.HTML; import net.atlanticbb.tantlinger.ui.UIUtils; import net.atlanticbb.tantlinger.ui.text.CompoundUndoManager; import net.atlanticbb.tantlinger.ui.text.HTMLUtils; import org.bushe.swing.action.ActionManager; /** * Action which toggles inline HTML elements * * @author Bob Tantlinger * */ public class HTMLInlineAction extends HTMLTextEditAction { /** * */ private static final long serialVersionUID = 1L; public static final int EM = 0; public static final int STRONG = 1; public static final int CODE = 2; public static final int CITE = 3; public static final int SUP = 4; public static final int SUB = 5; public static final int BOLD = 6; public static final int ITALIC = 7; public static final int UNDERLINE = 8; public static final int STRIKE = 9; public static final String[] INLINE_TYPES = { i18n.str("emphasis"), i18n.str("strong"), i18n.str("code"), i18n.str("cite"), i18n.str("superscript"), i18n.str("subscript"), i18n.str("bold"), i18n.str("italic"), i18n.str("underline"), i18n.str("strikethrough") }; private static final int[] MNEMS = { i18n.mnem("emphasis"), i18n.mnem("strong"), i18n.mnem("code"), i18n.mnem("cite"), i18n.mnem("superscript"), i18n.mnem("subscript"), i18n.mnem("bold"), i18n.mnem("italic"), i18n.mnem("underline"), i18n.mnem("strikethrough") }; private int type; /** * Creates a new HTMLInlineAction * * @param itype an inline element type (BOLD, ITALIC, STRIKE, etc) * @throws IllegalArgumentException */ public HTMLInlineAction(int itype) throws IllegalArgumentException { super(""); type = itype; if(type < 0 || type >= INLINE_TYPES.length) throw new IllegalArgumentException("Illegal Argument"); putValue(NAME, (INLINE_TYPES[type])); putValue(MNEMONIC_KEY, new Integer(MNEMS[type])); Icon ico = null; KeyStroke ks = null; if(type == BOLD) { ico = UIUtils.getIcon(UIUtils.X16, "bold.png"); ks = KeyStroke.getKeyStroke(KeyEvent.VK_B, Event.CTRL_MASK); } else if(type == ITALIC) { ico = UIUtils.getIcon(UIUtils.X16, "italic.png"); ks = KeyStroke.getKeyStroke(KeyEvent.VK_I, Event.CTRL_MASK); } else if(type == UNDERLINE) { ico = UIUtils.getIcon(UIUtils.X16, "underline.png"); ks = KeyStroke.getKeyStroke(KeyEvent.VK_U, Event.CTRL_MASK); } putValue(SMALL_ICON, ico); putValue(ACCELERATOR_KEY, ks); putValue(ActionManager.BUTTON_TYPE, ActionManager.BUTTON_TYPE_VALUE_CHECKBOX); putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME)); } protected void updateWysiwygContextState(JEditorPane ed) { setSelected(isDefined(HTMLUtils.getCharacterAttributes(ed))); } protected void sourceEditPerformed(ActionEvent e, JEditorPane editor) { HTML.Tag tag = getTag(); String prefix = "<" + tag.toString() + ">"; String postfix = "</" + tag.toString() + ">"; String sel = editor.getSelectedText(); if(sel == null) { editor.replaceSelection(prefix + postfix); int pos = editor.getCaretPosition() - postfix.length(); if(pos >= 0) editor.setCaretPosition(pos); } else { sel = prefix + sel + postfix; editor.replaceSelection(sel); } } public HTML.Tag getTag() { return getTagForType(type); } private HTML.Tag getTagForType(int type) { HTML.Tag tag = null; switch(type) { case EM: tag = HTML.Tag.EM; break; case STRONG: tag = HTML.Tag.STRONG; break; case CODE: tag = HTML.Tag.CODE; break; case SUP: tag = HTML.Tag.SUP; break; case SUB: tag = HTML.Tag.SUB; break; case CITE: tag = HTML.Tag.CITE; break; case BOLD: tag = HTML.Tag.B; break; case ITALIC: tag = HTML.Tag.I; break; case UNDERLINE: tag = HTML.Tag.U; break; case STRIKE: tag = HTML.Tag.STRIKE; break; } return tag; } protected void wysiwygEditPerformed(ActionEvent e, JEditorPane editor) { CompoundUndoManager.beginCompoundEdit(editor.getDocument()); toggleStyle(editor); CompoundUndoManager.endCompoundEdit(editor.getDocument()); //HTMLUtils.printAttribs(HTMLUtils.getCharacterAttributes(editor)); } private boolean isDefined(AttributeSet attr) { boolean hasSC = false; if(type == SUP) hasSC = StyleConstants.isSuperscript(attr); else if(type == SUB) hasSC = StyleConstants.isSubscript(attr); else if(type == BOLD) hasSC = StyleConstants.isBold(attr); else if(type == ITALIC) hasSC = StyleConstants.isItalic(attr); else if(type == UNDERLINE) hasSC = StyleConstants.isUnderline(attr); else if(type == STRIKE) hasSC = StyleConstants.isStrikeThrough(attr); return hasSC || (attr.getAttribute(getTag()) != null); } private void toggleStyle(JEditorPane editor) { MutableAttributeSet attr = new SimpleAttributeSet(); attr.addAttributes(HTMLUtils.getCharacterAttributes(editor)); boolean enable = !isDefined(attr); HTML.Tag tag = getTag(); if(enable) { //System.err.println("adding style"); attr = new SimpleAttributeSet(); attr.addAttribute(tag, new SimpleAttributeSet()); //doesn't replace any attribs, just adds the new one HTMLUtils.setCharacterAttributes(editor, attr); } else { //System.err.println("clearing style"); //Kind of a ham-fisted way to do this, but sometimes there are //CSS attributes, someties there are HTML.Tag attributes, and sometimes //there are both. So, we have to remove 'em all to make sure this type //gets completely disabled //remove the CSS style //STRONG, EM, CITE, CODE have no CSS analogs if(type == BOLD) HTMLUtils.removeCharacterAttribute(editor, CSS.Attribute.FONT_WEIGHT, "bold"); else if(type == ITALIC) HTMLUtils.removeCharacterAttribute(editor, CSS.Attribute.FONT_STYLE, "italic"); else if(type == UNDERLINE) HTMLUtils.removeCharacterAttribute(editor, CSS.Attribute.TEXT_DECORATION, "underline"); else if(type == STRIKE) HTMLUtils.removeCharacterAttribute(editor, CSS.Attribute.TEXT_DECORATION, "line-through"); else if(type == SUP) HTMLUtils.removeCharacterAttribute(editor, CSS.Attribute.VERTICAL_ALIGN, "sup"); else if(type == SUB) HTMLUtils.removeCharacterAttribute(editor, CSS.Attribute.VERTICAL_ALIGN, "sub"); HTMLUtils.removeCharacterAttribute(editor, tag); //make certain the tag is also removed } setSelected(enable); } protected void updateSourceContextState(JEditorPane ed) { setSelected(false); } }