/* 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.setItalic(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)
    {
      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.setCharacterAttributes(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.");
    }

    /**
     * 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());
  }
}
