MyHTMLDocument.java :  » Scripting » seco » seco » notebook » html » Java Open Source

Java Open Source » Scripting » seco 
seco » seco » notebook » html » MyHTMLDocument.java
/*
 * This file is part of the Scriba source distribution. This is free, open-source 
 * software. For full licensing information, please see the LicensingInformation file
 * at the root level of the distribution.
 *
 * Copyright (c) 2006-2007 Kobrix Software, Inc.
 */
package seco.notebook.html;

import java.net.URL;
import java.util.Enumeration;
import java.util.Stack;
import java.util.Vector;
import javax.swing.event.DocumentEvent;
import javax.swing.event.UndoableEditEvent;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.AbstractDocument.DefaultDocumentEvent;
import javax.swing.text.AbstractDocument.ElementEdit;
import javax.swing.text.DefaultStyledDocument.AttributeUndoableEdit;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLDocument.HTMLReader.ParagraphAction;
import javax.swing.text.html.HTMLDocument.HTMLReader.TagAction;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoableEdit;

import seco.notebook.NotebookDocument.NamedCompoundEdit;

public class MyHTMLDocument extends HTMLDocument
{
  // reusable object for compound events
  protected CompoundEdit cEdit = new NamedCompoundEdit(null);
  // stack for nested compound events
  protected Stack<String> editStack = new Stack<String>();
  protected Vector<UndoableEdit> removeUndo = new EditVector<UndoableEdit>();
  protected Vector<UndoableEdit> insertUndo = new EditVector<UndoableEdit>();

  public HTMLEditorKit.ParserCallback getReader(int pos)
  {
    Object desc = getProperty(Document.StreamDescriptionProperty);
    if (desc instanceof URL)
    {
      setBase((URL) desc);
    }
    MyHTMLReader reader = new MyHTMLReader(pos);
    return reader;
  }

  public MyHTMLDocument()
  {
    super();
  }

  public MyHTMLDocument(Content c, StyleSheet styles)
  {
    super(c, styles);
  }

  public MyHTMLDocument(StyleSheet styles)
  {
    super(styles);
  }
  
  void adjustP(){
    Element body = getRootElements()[0].getElement(1);
    System.out.println("AdjustP: " + body + ":" +
        body.getElementCount());
    if(body.getElementCount() > 1 ||
        HTMLUtils.getName(body.getElement(0)) == HTML.Tag.IMPLIED)
    {
      MutableAttributeSet attr = new SimpleAttributeSet();
      attr.addAttribute(StyleConstants.NameAttribute, HTML.Tag.P);
      //setParagraphAttributes(body.getStartOffset(), 
      //    body.getEndOffset() - body.getStartOffset(), attr,  false);
      setCharacterAttributes(body.getStartOffset(), 
          body.getEndOffset() - body.getStartOffset(), attr,  false);
    }
  }

  void beginCompoundEdit(final String name)
  {
    cEdit = new NamedCompoundEdit(name);
    editStack.push(name);
  }

  void endCompoundEdit()
  {
    editStack.pop();
    if (!editStack.isEmpty()) return;
    cEdit.end();
    super.fireUndoableEditUpdate(new UndoableEditEvent(this, cEdit));
  }

  private boolean isCompoundEditInProgress()
  {
    return editStack != null && !editStack.isEmpty();
  }

  private CompoundEdit makeCompoundEdit(Vector<UndoableEdit> edits,
      DefaultDocumentEvent dde)
  {
    if (edits == null || edits.isEmpty()) return null;
    CompoundEdit cE = new CompoundEdit();
    if (dde != null) cE.addEdit(dde);
    for (UndoableEdit ed : edits)
      if (ed != null) cE.addEdit(ed);
    cE.end();
    edits.clear();
    return cE;
  }

  protected boolean modified = false;
  
  public boolean isModified()
    {
        return modified;
    }

    public void setModified(boolean modified)
    {
        this.modified = modified;
    }

    protected void fireUndoableEditUpdate(UndoableEditEvent e)
  {
      modified = true;
    if (!(e.getEdit() instanceof DefaultDocumentEvent))
    {
      super.fireUndoableEditUpdate(e);
      return;
    }
    DefaultDocumentEvent dde = (DefaultDocumentEvent) e.getEdit();
    if (isCompoundEditInProgress())
    {
      cEdit.addEdit(dde);
      return;
    }
    CompoundEdit cE = null;
    if (DocumentEvent.EventType.INSERT.equals(dde.getType()))
      cE = makeCompoundEdit(insertUndo, dde);
    else if (DocumentEvent.EventType.REMOVE.equals(dde.getType()))
      cE = makeCompoundEdit(removeUndo, dde);
    if (cE != null)
      super.fireUndoableEditUpdate(new UndoableEditEvent(e.getSource(),
          cE));
    else
      super.fireUndoableEditUpdate(e);
  }

  public void addAttributes(Element e, AttributeSet a)
  {
    if ((e != null) && (a != null))
    {
      try
      {
        writeLock();
        //System.out.println("MyHTMLDocument addAttributes a=" + a);
        int start = e.getStartOffset();
        DefaultDocumentEvent changes = new DefaultDocumentEvent(start,
            e.getEndOffset() - start,
            DocumentEvent.EventType.CHANGE);
        AttributeSet sCopy = a.copyAttributes();
        MutableAttributeSet attr = (MutableAttributeSet) e
            .getAttributes();
        changes.addEdit(new AttributeUndoableEdit(e, sCopy, false));
        attr.addAttributes(a);
        changes.end();
        fireChangedUpdate(changes);
        fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
      }
      finally
      {
        writeUnlock();
      }
    }
  }

  public void replaceAttributes(Element e, AttributeSet a)
  {
    if ((e != null) && (a != null))
    {
      try
      {
        writeLock();
        int start = e.getStartOffset();
        DefaultDocumentEvent changes = new DefaultDocumentEvent(start,
            e.getEndOffset() - start,
            DocumentEvent.EventType.CHANGE);
        MutableAttributeSet sCopy = new SimpleAttributeSet(a);
        sCopy.addAttribute(StyleConstants.NameAttribute, HTMLUtils
            .getName(e));
        changes.addEdit(new AttributeUndoableEdit(e, sCopy, false));
        MutableAttributeSet attr = (MutableAttributeSet) e
            .getAttributes();
        Enumeration aNames = attr.getAttributeNames();
        while (aNames.hasMoreElements())
        {
          Object aName = aNames.nextElement();
          if (!aName.equals(StyleConstants.NameAttribute))
            attr.removeAttribute(aName);
        }
        attr.addAttributes(a);
        changes.end();
        fireChangedUpdate(changes);
        fireUndoableEditUpdate(new UndoableEditEvent(this, changes));
      }
      finally
      {
        writeUnlock();
      }
    }
  }

  public void removeElements(Element e, int index, int count)
      throws BadLocationException
  {
    writeLock();
    int start = e.getElement(index).getStartOffset();
    int end = e.getElement(index + count - 1).getEndOffset();
    try
    {
      Element[] removed = new Element[count];
      Element[] added = new Element[0];
      for (int counter = 0; counter < count; counter++)
      {
        removed[counter] = e.getElement(counter + index);
      }
      DefaultDocumentEvent dde = new DefaultDocumentEvent(start, end
          - start, DocumentEvent.EventType.REMOVE);
      ((AbstractDocument.BranchElement) e).replace(index, removed.length,
          added);
      dde.addEdit(new ElementEdit(e, index, removed, added));
      UndoableEdit u = getContent().remove(start, end - start);
      if (u != null)
      {
        dde.addEdit(u);
      }
      postRemoveUpdate(dde);
      dde.end();
      fireRemoveUpdate(dde);
      if (u != null)
      {
        fireUndoableEditUpdate(new UndoableEditEvent(this, dde));
      }
    }
    finally
    {
      writeUnlock();
    }
  }

  class MyHTMLReader extends HTMLReader
  {
    public MyHTMLReader(int offset, int popDepth, int pushDepth,
        Tag insertTag)
    {
      super(offset, popDepth, pushDepth, insertTag);
    }

    public MyHTMLReader(int offset)
    {
      super(offset);
    }

    @Override
    public void handleStartTag(Tag t, MutableAttributeSet a, int pos)
    {
      // System.out.println("handleStartTag: " + t);
      if ((t == HTML.Tag.HTML || t == HTML.Tag.BODY || t == HTML.Tag.HEAD))
      {
        // System.out.println("handleStartTag: " + t + ":" +
        // a.getAttribute(HTMLEditorKit.ParserCallback.IMPLIED));
        if (a.getAttribute(HTMLEditorKit.ParserCallback.IMPLIED) != null)
          putProperty(t, true);
      }
      super.handleStartTag(t, a, pos);
    }
    
    @Override
    public void handleEndTag(Tag t, int pos)
    {
      super.handleEndTag(t, pos);
    }
    
    ParagraphAction pa = new ParagraphAction();
  }

  private class EditVector<T extends UndoableEdit> extends Vector<T>
  {
    public synchronized boolean add(T edit)
    {
      if (edit == null) return false;
      return isCompoundEditInProgress() ? cEdit.addEdit(edit) : super
          .add(edit);
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.