/* StyledEditorKit.java --
   Copyright (C) 2002, 2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.text;

import java.awt.Color;
import java.awt.event.ActionEvent;

import javax.swing.Action;
import javax.swing.JEditorPane;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

/**
 * An {@link EditorKit} that supports editing styled text.
 *
 * @author Andrew Selkirk
 * @author Roman Kennke (roman@kennke.org)
 */
public class StyledEditorKit extends DefaultEditorKit
{
  /** The serialVersionUID. */
  private static final long serialVersionUID = 7002391892985555948L;

  /**
   * Toggles the underline attribute for the selected text.
   */
  public static class UnderlineAction extends StyledEditorKit.StyledTextAction
  {
    /**
     * Creates an instance of <code>UnderlineAction</code>.
     */
    public UnderlineAction()
    {
      super("font-underline");
    }

    /**
     * Performs the action.
     *
     * @param event the <code>ActionEvent</code> that describes the action
     */
    public void actionPerformed(ActionEvent event)
    {
      JEditorPane editor = getEditor(event);
      StyledDocument doc = getStyledDocument(editor);
      Element el = doc.getCharacterElement(editor.getSelectionStart());
      boolean isUnderline = StyleConstants.isUnderline(el.getAttributes());
      SimpleAttributeSet atts = new SimpleAttributeSet();
      StyleConstants.setUnderline(atts, ! isUnderline);
      setCharacterAttributes(editor, atts, false);
    }
  }

  /**
   * Toggles the italic attribute for the selected text.
   */
  public static class ItalicAction extends StyledEditorKit.StyledTextAction
  {
    /**
     * Creates an instance of <code>ItalicAction</code>.
     */
    public ItalicAction()
    {
      super("font-italic");
    }

    /**
     * Performs the action.
     *
     * @param event the <code>ActionEvent</code> that describes the action
     */
    public void actionPerformed(ActionEvent event)
    {
      JEditorPane editor = getEditor(event);
      StyledDocument doc = getStyledDocument(editor);
      Element el = doc.getCharacterElement(editor.getSelectionStart());
      boolean isItalic = StyleConstants.isItalic(el.getAttributes());
      SimpleAttributeSet atts = new SimpleAttributeSet();
      StyleConstants.setItalic(atts, ! isItalic);
      setCharacterAttributes(editor, atts, false);
    }
  }

  /**
   * Toggles the bold attribute for the selected text.
   */
  public static class BoldAction extends StyledEditorKit.StyledTextAction
  {
    /**
     * Creates an instance of <code>BoldAction</code>.
     */
    public BoldAction()
    {
      super("font-bold");
    }

    /**
     * Performs the action.
     *
     * @param event the <code>ActionEvent</code> that describes the action
     */
    public void actionPerformed(ActionEvent event)
    {
      JEditorPane editor = getEditor(event);
      StyledDocument doc = getStyledDocument(editor);
      Element el = doc.getCharacterElement(editor.getSelectionStart());
      boolean isBold = StyleConstants.isBold(el.getAttributes());
      SimpleAttributeSet atts = new SimpleAttributeSet();
      StyleConstants.setBold(atts, ! isBold);
      setCharacterAttributes(editor, atts, false);
    }
  }

  /**
   * Sets the alignment attribute on the selected text.
   */
  public static class AlignmentAction extends StyledEditorKit.StyledTextAction
  {
    /**
     * The aligment to set.
     */
    private int a;

    /**
     * Creates a new instance of <code>AlignmentAction</code> to set the
     * alignment to <code>a</code>.
     *
     * @param nm the name of the Action
     * @param a the alignment to set
     */
    public AlignmentAction(String nm, int a)
    {
      super(nm);
      this.a = a;
    }

    /**
     * Performs the action.
     *
     * @param event the <code>ActionEvent</code> that describes the action
     */
    public void actionPerformed(ActionEvent event)
    {
      SimpleAttributeSet atts = new SimpleAttributeSet();
      StyleConstants.setAlignment(atts, a);
      setParagraphAttributes(getEditor(event), atts, false);
    }
  }

  /**
   * Sets the foreground color attribute on the selected text.
   */
  public static class ForegroundAction extends StyledEditorKit.StyledTextAction
  {
    /**
     * The foreground color to set.
     */
    private Color fg;

    /**
     * Creates a new instance of <code>ForegroundAction</code> to set the
     * foreground color to <code>fg</code>.
     *
     * @param nm the name of the Action
     * @param fg the foreground color to set
     */
    public ForegroundAction(String nm, Color fg)
    {
      super(nm);
      this.fg = fg;
    }

    /**
     * Performs the action.
     *
     * @param event the <code>ActionEvent</code> that describes the action
     */
    public void actionPerformed(ActionEvent event)
    {
      SimpleAttributeSet atts = new SimpleAttributeSet();
      StyleConstants.setForeground(atts, fg);
      setCharacterAttributes(getEditor(event), atts, false);
    }
  }

  /**
   * Sets the font size attribute on the selected text.
   */
  public static class FontSizeAction extends StyledEditorKit.StyledTextAction
  {
    /**
     * The font size to set.
     */
    private int size;

    /**
     * Creates a new instance of <code>FontSizeAction</code> to set the
     * font size to <code>size</code>.
     *
     * @param nm the name of the Action
     * @param size the font size to set
     */
    public FontSizeAction(String nm, int size)
    {
      super(nm);
      this.size = size;
    }

    /**
     * Performs the action.
     *
     * @param event the <code>ActionEvent</code> that describes the action
     */
    public void actionPerformed(ActionEvent event)
    {
      SimpleAttributeSet atts = new SimpleAttributeSet();
      StyleConstants.setFontSize(atts, size);
      setCharacterAttributes(getEditor(event), atts, false);
    }
  }

  /**
   * Sets the font family attribute on the selected text.
   */
  public static class FontFamilyAction extends StyledEditorKit.StyledTextAction
  {
    /**
     * The font family to set.
     */
    private String family;

    /**
     * Creates a new instance of <code>FontFamilyAction</code> to set the
     * font family to <code>family</code>.
     *
     * @param nm the name of the Action
     * @param family the font family to set
     */
    public FontFamilyAction(String nm, String family)
    {
      super(nm);
      this.family = family;
    }

    /**
     * Performs the action.
     *
     * @param event the <code>ActionEvent</code> that describes the action
     */
    public void actionPerformed(ActionEvent event)
    {
      SimpleAttributeSet atts = new SimpleAttributeSet();
      StyleConstants.setFontFamily(atts, family);
      setCharacterAttributes(getEditor(event), atts, false);
    }
  }

  /**
   * The abstract superclass of all styled TextActions. This class
   * provides some useful methods to manipulate the text attributes.
   */
  public abstract static class StyledTextAction extends TextAction
  {
    /**
     * Creates a new instance of <code>StyledTextAction</code>.
     *
     * @param nm the name of the <code>StyledTextAction</code>
     */
    public StyledTextAction(String nm)
    {
      super(nm);
    }

    /**
     * Returns the <code>JEditorPane</code> component from which the
     * <code>ActionEvent</code> originated.
     *
     * @param event the <code>ActionEvent</code>
     * @return the <code>JEditorPane</code> component from which the
     *         <code>ActionEvent</code> originated
     */
    protected final JEditorPane getEditor(ActionEvent event)
    {
      return (JEditorPane) getTextComponent(event);
    }

    /**
     * Sets the specified character attributes on the currently selected
     * text of <code>editor</code>. If <code>editor</code> does not have
     * a selection, then the attributes are used as input attributes
     * for newly inserted content.
     *
     * @param editor the <code>JEditorPane</code> component
     * @param atts the text attributes to set
     * @param replace if <code>true</code> the current attributes of the
     *        selection are replaces, otherwise they are merged
     */
    protected final void setCharacterAttributes(JEditorPane editor,
                                                AttributeSet atts,
                                                boolean replace)
    {
      int p0 = editor.getSelectionStart();
      int p1 = editor.getSelectionEnd();
      if (p0 != p1)
        {
          StyledDocument doc = getStyledDocument(editor);
          doc.setCharacterAttributes(p0, p1 - p0, atts, replace);
        }
      // Update input attributes.
      StyledEditorKit kit = getStyledEditorKit(editor);
      MutableAttributeSet inputAtts = kit.getInputAttributes();
      if (replace)
        {
          inputAtts.removeAttributes(inputAtts);
        }
      inputAtts.addAttributes(atts);
    }

    /**
     * Returns the {@link StyledDocument} that is used by <code>editor</code>.
     *
     * @param editor the <code>JEditorPane</code> from which to get the
     *        <code>StyledDocument</code>
     *
     * @return the {@link StyledDocument} that is used by <code>editor</code>
     */
    protected final StyledDocument getStyledDocument(JEditorPane editor)
    {
      Document doc = editor.getDocument();
      if (!(doc instanceof StyledDocument))
        throw new AssertionError("The Document for StyledEditorKits is "
                                 + "expected to be a StyledDocument.");

      return (StyledDocument) doc;
    }

    /**
     * Returns the {@link StyledEditorKit} that is used by <code>editor</code>.
     *
     * @param editor the <code>JEditorPane</code> from which to get the
     *        <code>StyledEditorKit</code>
     *
     * @return the {@link StyledEditorKit} that is used by <code>editor</code>
     */
    protected final StyledEditorKit getStyledEditorKit(JEditorPane editor)
    {
      EditorKit kit = editor.getEditorKit();
      if (!(kit instanceof StyledEditorKit))
        throw new AssertionError("The EditorKit for StyledDocuments is "
                                 + "expected to be a StyledEditorKit.");

      return (StyledEditorKit) kit;
    }

    /**
     * Sets the specified character attributes on the paragraph that
     * contains the currently selected
     * text of <code>editor</code>. If <code>editor</code> does not have
     * a selection, then the attributes are set on the paragraph that
     * contains the current caret position.
     *
     * @param editor the <code>JEditorPane</code> component
     * @param atts the text attributes to set
     * @param replace if <code>true</code> the current attributes of the
     *        selection are replaces, otherwise they are merged
     */
    protected final void setParagraphAttributes(JEditorPane editor,
                                                AttributeSet atts,
                                                boolean replace)
    {
      Document doc = editor.getDocument();
      if (doc instanceof StyledDocument)
        {
          StyledDocument styleDoc = (StyledDocument) editor.getDocument();
          EditorKit kit = editor.getEditorKit();
          if (!(kit instanceof StyledEditorKit))
            {
              StyledEditorKit styleKit = (StyledEditorKit) kit;
              int start = editor.getSelectionStart();
              int end = editor.getSelectionEnd();
              int dot = editor.getCaret().getDot();
              if (start == dot && end == dot)
                {
                  // If there is no selection, then we only update the
                  // input attributes.
                  MutableAttributeSet inputAttributes =
                    styleKit.getInputAttributes();
                  inputAttributes.addAttributes(atts);
                }
              else
                styleDoc.setParagraphAttributes(start, end, atts, replace);
            }
          else
            throw new AssertionError("The EditorKit for StyledTextActions "
                                     + "is expected to be a StyledEditorKit");
        }
      else
        throw new AssertionError("The Document for StyledTextActions is "
                                 + "expected to be a StyledDocument.");
    }
  }

  /**
   * A {@link ViewFactory} that is able to create {@link View}s for
   * the <code>Element</code>s that are supported by
   * <code>StyledEditorKit</code>, namely the following types of Elements:
   *
   * <ul>
   * <li>{@link AbstractDocument#ContentElementName}</li>
   * <li>{@link AbstractDocument#ParagraphElementName}</li>
   * <li>{@link AbstractDocument#SectionElementName}</li>
   * <li>{@link StyleConstants#ComponentElementName}</li>
   * <li>{@link StyleConstants#IconElementName}</li>
   * </ul>
   */
  static class StyledViewFactory
    implements ViewFactory
  {
    /**
     * Creates a {@link View} for the specified <code>Element</code>.
     *
     * @param element the <code>Element</code> to create a <code>View</code>
     *        for
     * @return the <code>View</code> for the specified <code>Element</code>
     *         or <code>null</code> if the type of <code>element</code> is
     *         not supported
     */
    public View create(Element element)
    {
      String name = element.getName();
      View view = null;
      if (name.equals(AbstractDocument.ContentElementName))
        view = new LabelView(element);
      else if (name.equals(AbstractDocument.ParagraphElementName))
        view = new ParagraphView(element);
      else if (name.equals(AbstractDocument.SectionElementName))
        view = new BoxView(element, View.Y_AXIS);
      else if (name.equals(StyleConstants.ComponentElementName))
        view = new ComponentView(element);
      else if (name.equals(StyleConstants.IconElementName))
        view = new IconView(element);
      else
        throw new AssertionError("Unknown Element type: "
                                 + element.getClass().getName() + " : "
                                 + name);
      return view;
    }
  }

  /**
   * Keeps track of the caret position and updates the currentRun
   * <code>Element</code> and the <code>inputAttributes</code>.
   */
  class CaretTracker
    implements CaretListener
  {
    /**
     * Notifies an update of the caret position.
     *
     * @param ev the event for the caret update
     */
    public void caretUpdate(CaretEvent ev)
    {
      Object source = ev.getSource();
      if (!(source instanceof JTextComponent))
        throw new AssertionError("CaretEvents are expected to come from a"
                                 + "JTextComponent.");

      JTextComponent text = (JTextComponent) source;
      Document doc = text.getDocument();
      if (!(doc instanceof StyledDocument))
        throw new AssertionError("The Document used by StyledEditorKits is"
                                 + "expected to be a StyledDocument");

      StyledDocument styleDoc = (StyledDocument) doc;
      currentRun = styleDoc.getCharacterElement(ev.getDot());
      createInputAttributes(currentRun, inputAttributes);
    }
  }

  /**
   * Stores the <code>Element</code> at the current caret position. This
   * is updated by {@link CaretTracker}.
   */
  Element currentRun;

  /**
   * The current input attributes. This is updated by {@link CaretTracker}.
   */
  MutableAttributeSet inputAttributes;

  /**
   * The CaretTracker that keeps track of the current input attributes, and
   * the current character run Element.
   */
  CaretTracker caretTracker;

  /**
   * The ViewFactory for StyledEditorKits.
   */
  StyledViewFactory viewFactory;

  /**
   * Creates a new instance of <code>StyledEditorKit</code>.
   */
  public StyledEditorKit()
  {
    inputAttributes = new SimpleAttributeSet();
  }

  /**
   * Creates an exact copy of this <code>StyledEditorKit</code>.
   *
   * @return an exact copy of this <code>StyledEditorKit</code>
   */
  public Object clone()
  {
    StyledEditorKit clone = (StyledEditorKit) super.clone();
    // FIXME: Investigate which fields must be copied.
    return clone;
  }

  /**
   * Returns the <code>Action</code>s supported by this {@link EditorKit}.
   * This includes the {@link BoldAction}, {@link ItalicAction} and
   * {@link UnderlineAction} as well as the <code>Action</code>s supported
   * by {@link DefaultEditorKit}.
   *
   * The other <code>Action</code>s of <code>StyledEditorKit</code> are not
   * returned here, since they require a parameter and thus custom
   * instantiation.
   *
   * @return the <code>Action</code>s supported by this {@link EditorKit}
   */
  public Action[] getActions()
  {
    Action[] actions1 = super.getActions();
    Action[] myActions = new Action[] {
      new FontSizeAction("font-size-8", 8),
      new FontSizeAction("font-size-10", 10),
      new FontSizeAction("font-size-12", 12),
      new FontSizeAction("font-size-14", 14),
      new FontSizeAction("font-size-16", 16),
      new FontSizeAction("font-size-18", 18),
      new FontSizeAction("font-size-24", 24),
      new FontSizeAction("font-size-36", 36),
      new FontSizeAction("font-size-48", 48),
      new FontFamilyAction("font-family-Serif", "Serif"),
      new FontFamilyAction("font-family-Monospaced", "Monospaced"),
      new FontFamilyAction("font-family-SansSerif", "SansSerif"),
      new AlignmentAction("left-justify", StyleConstants.ALIGN_LEFT),
      new AlignmentAction("center-justify", StyleConstants.ALIGN_CENTER),
      new AlignmentAction("right-justify", StyleConstants.ALIGN_RIGHT),
      new BoldAction(),
      new ItalicAction(),
      new UnderlineAction()
    };
    return TextAction.augmentList(actions1, myActions);
  }

  /**
   * Returns the current input attributes. These are automatically set on
   * any newly inserted content, if not specified otherwise.
   *
   * @return the current input attributes
   */
  public MutableAttributeSet getInputAttributes()
  {
    return inputAttributes;
  }

  /**
   * Returns the {@link Element} that represents the character run at the
   * current caret position.
   *
   * @return the {@link Element} that represents the character run at the
   *         current caret position
   */
  public Element getCharacterAttributeRun()
  {
    return currentRun;
  }

  /**
   * Creates the default {@link Document} supported by this
   * <code>EditorKit</code>. This is an instance of
   * {@link DefaultStyledDocument} in this case but may be overridden by
   * subclasses.
   *
   * @return an instance of <code>DefaultStyledDocument</code>
   */
  public Document createDefaultDocument()
  {
    return new DefaultStyledDocument();
  }

  /**
   * Installs this <code>EditorKit</code> on the specified {@link JEditorPane}.
   * This basically involves setting up required listeners on the
   * <code>JEditorPane</code>.
   *
   * @param component the <code>JEditorPane</code> to install this
   *        <code>EditorKit</code> on
   */
  public void install(JEditorPane component)
  {
    CaretTracker tracker = new CaretTracker();
    component.addCaretListener(tracker);
  }

  /**
   * Deinstalls this <code>EditorKit</code> from the specified
   * {@link JEditorPane}. This basically involves removing all listeners from
   * <code>JEditorPane</code> that have been set up by this
   * <code>EditorKit</code>.
   *
   * @param component the <code>JEditorPane</code> from which to deinstall this
   *        <code>EditorKit</code>
   */
  public void deinstall(JEditorPane component)
  {
    CaretTracker t = caretTracker;
    if (t != null)
      component.removeCaretListener(t);
    caretTracker = null;
  }

  /**
   * Returns a {@link ViewFactory} that is able to create {@link View}s
   * for {@link Element}s that are supported by this <code>EditorKit</code>,
   * namely the following types of <code>Element</code>s:
   *
   * <ul>
   * <li>{@link AbstractDocument#ContentElementName}</li>
   * <li>{@link AbstractDocument#ParagraphElementName}</li>
   * <li>{@link AbstractDocument#SectionElementName}</li>
   * <li>{@link StyleConstants#ComponentElementName}</li>
   * <li>{@link StyleConstants#IconElementName}</li>
   * </ul>
   *
   * @return a {@link ViewFactory} that is able to create {@link View}s
   *          for {@link Element}s that are supported by this <code>EditorKit</code>
   */
  public ViewFactory getViewFactory()
  {
    if (viewFactory == null)
      viewFactory = new StyledViewFactory();
    return viewFactory;
  }

  /**
   * Copies the text attributes from <code>element</code> to <code>set</code>.
   * This is called everytime when the caret position changes to keep
   * track of the current input attributes. The attributes in <code>set</code>
   * are cleaned before adding the attributes of <code>element</code>.
   *
   * This method filters out attributes for element names, <code>Icon</code>s
   * and <code>Component</code>s.
   *
   * @param element the <code>Element</code> from which to copy the text
   *         attributes
   * @param set the inputAttributes to copy the attributes to
   */
  protected void createInputAttributes(Element element,
                                       MutableAttributeSet set)
  {
    // FIXME: Filter out component, icon and element name attributes.
    set.removeAttributes(set);
    set.addAttributes(element.getAttributes());
  }
}
