package tk.eclipse.plugin.htmleditor.editors;
import java.util.ArrayList;
import java.util.List;
import jp.aonir.fuzzyxml.FuzzyXMLAttribute;
import jp.aonir.fuzzyxml.FuzzyXMLCDATA;
import jp.aonir.fuzzyxml.FuzzyXMLComment;
import jp.aonir.fuzzyxml.FuzzyXMLDocType;
import jp.aonir.fuzzyxml.FuzzyXMLDocument;
import jp.aonir.fuzzyxml.FuzzyXMLElement;
import jp.aonir.fuzzyxml.FuzzyXMLNode;
import jp.aonir.fuzzyxml.FuzzyXMLParser;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
import tk.eclipse.plugin.htmleditor.HTMLPlugin;
/**
* An implementaion of IContentOutlinePage for the HTML editor.
* This shows the outline of HTML document.
*/
public class HTMLOutlinePage extends ContentOutlinePage implements IHTMLOutlinePage {
private RootNode root;
private HTMLSourceEditor editor;
private FuzzyXMLDocument doc;
public HTMLOutlinePage(HTMLSourceEditor editor) {
super();
this.editor = editor;
}
public FuzzyXMLDocument getDoc() {
return doc;
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
TreeViewer viewer = getTreeViewer();
root = new RootNode();
viewer.setContentProvider(new HTMLContentProvider());
viewer.setLabelProvider(new HTMLLabelProvider());
viewer.setInput(root);
viewer.addSelectionChangedListener(new HTMLSelectionChangedListener());
try {
viewer.setExpandedState(root.getChildren()[0], true);
}
catch (Exception ex) {
// ignore
}
update();
}
protected boolean isHTML() {
return true;
}
protected FuzzyXMLParser createParser() {
FuzzyXMLParser parser = new FuzzyXMLParser(isHTML());
return parser;
}
public void update() {
if (getControl() == null || getControl().isDisposed()) {
return;
}
IFile file = ((FileEditorInput) editor.getEditorInput()).getFile();
try {
//this.doc = WodParserCache.parser(file).getHtmlDocument();
//if (this.doc == null) {
this.doc = createParser().parse(editor.getHTMLSource());
//}
TreeViewer viewer = getTreeViewer();
if (viewer != null) {
viewer.refresh();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
protected Image getNodeImage(FuzzyXMLNode element) {
if (element instanceof FuzzyXMLCDATA) {
return null;
}
else if (element instanceof FuzzyXMLElement) {
FuzzyXMLElement e = (FuzzyXMLElement) element;
if (e.getName().equalsIgnoreCase("html")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_TAG_HTML);
}
else if (e.getName().equalsIgnoreCase("title")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_TITLE);
}
else if (e.getName().equalsIgnoreCase("body")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_BODY);
}
else if (e.getName().equalsIgnoreCase("form")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_FORM);
}
else if (e.getName().equalsIgnoreCase("img")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_IMAGE);
}
else if (e.getName().equalsIgnoreCase("a")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_LINK);
}
else if (e.getName().equalsIgnoreCase("table")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_TABLE);
}
else if (e.getName().equalsIgnoreCase("input")) {
String type = e.getAttributeValue("type");
if (type != null) {
if (type.equalsIgnoreCase("button") || type.equalsIgnoreCase("reset") || type.equalsIgnoreCase("submit")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_BUTTON);
}
else if (type.equalsIgnoreCase("radio")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_RADIO);
}
else if (type.equalsIgnoreCase("checkbox")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_CHECK);
}
else if (type.equalsIgnoreCase("text")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_TEXT);
}
else if (type.equalsIgnoreCase("password")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_PASS);
}
else if (type.equalsIgnoreCase("hidden")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_HIDDEN);
}
}
}
else if (e.getName().equalsIgnoreCase("select")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_SELECT);
}
else if (e.getName().equalsIgnoreCase("textarea")) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_TEXTAREA);
}
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_TAG);
}
else if (element instanceof FuzzyXMLDocType) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_DOCTYPE);
}
else if (element instanceof FuzzyXMLComment) {
return HTMLPlugin.getDefault().getImageRegistry().get(HTMLPlugin.ICON_COMMENT);
}
return null;
}
protected Object[] getNodeChildren(FuzzyXMLElement element) {
List<FuzzyXMLNode> children = new ArrayList<FuzzyXMLNode>();
FuzzyXMLNode[] nodes = element.getChildren();
for (int i = 0; i < nodes.length; i++) {
if (nodes[i] instanceof FuzzyXMLElement) {
children.add(nodes[i]);
}
else if (nodes[i] instanceof FuzzyXMLDocType) {
children.add(nodes[i]);
}
else if (nodes[i] instanceof FuzzyXMLComment) {
children.add(nodes[i]);
}
}
return children.toArray(new FuzzyXMLNode[children.size()]);
}
protected String getNodeText(FuzzyXMLNode node) {
if (node instanceof FuzzyXMLCDATA) {
return "CDATA";
}
if (node instanceof FuzzyXMLElement) {
StringBuffer sb = new StringBuffer();
FuzzyXMLAttribute[] attrs = ((FuzzyXMLElement) node).getAttributes();
for (int i = 0; i < attrs.length; i++) {
if (sb.length() != 0) {
sb.append(", ");
}
sb.append(attrs[i].getName() + "=" + attrs[i].getValue());
}
if (sb.length() == 0) {
return ((FuzzyXMLElement) node).getName();
}
else {
return ((FuzzyXMLElement) node).getName() + "(" + sb.toString() + ")";
}
}
if (node instanceof FuzzyXMLDocType) {
return "DOCTYPE";
}
if (node instanceof FuzzyXMLComment) {
return "#comment";
}
return node.toString();
}
/** root element. */
private class RootNode {
private boolean _updating;
public RootNode() {
super();
}
public Object[] getChildren() {
// IFile file = ((FileEditorInput)editor.getEditorInput()).getFile();
// return new FileNode[]{
// new FileNode(file.getName())
// };
List<FuzzyXMLNode> children = new ArrayList<FuzzyXMLNode>();
if (doc == null) {
if (_updating) {
System.out.println("RootNode.getChildren: Attempted to update root node while already in an update pass.");
}
else {
_updating = true;
try {
update();
}
finally {
_updating = false;
}
}
}
if (doc != null) {
if (doc.getDocumentType() != null) {
children.add(doc.getDocumentType());
}
FuzzyXMLNode[] nodes = doc.getDocumentElement().getChildren();
for (int i = 0; i < nodes.length; i++) {
if (nodes[i] instanceof FuzzyXMLElement) {
children.add(nodes[i]);
// } else if(nodes[i] instanceof FuzzyXMLText && ((FuzzyXMLText)nodes[i]).getValue().startsWith("<%")){
// children.add(nodes[i]);
}
}
}
return children.toArray(new FuzzyXMLNode[children.size()]);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof RootNode) {
return true;
}
return false;
}
}
/** ContentProvider of HTMLOutlinePage. */
private class HTMLContentProvider implements ITreeContentProvider {
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof RootNode) {
return ((RootNode) parentElement).getChildren();
}
else if (parentElement instanceof FuzzyXMLElement) {
return getNodeChildren((FuzzyXMLElement) parentElement);
}
return new Object[0];
}
public Object getParent(Object element) {
if (element instanceof FuzzyXMLNode) {
FuzzyXMLNode parent = ((FuzzyXMLNode) element).getParentNode();
if (parent == null) {
return root.getChildren()[0];
}
return parent;
}
return null;
}
public boolean hasChildren(Object element) {
if (getChildren(element).length == 0) {
return false;
}
else {
return true;
}
}
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
/** LabelProvider of HTMLOutlinePage */
private class HTMLLabelProvider extends LabelProvider {
@Override
public Image getImage(Object element) {
if (element instanceof FuzzyXMLNode) {
return getNodeImage((FuzzyXMLNode) element);
}
return null;
}
@Override
public String getText(Object element) {
if (element instanceof FuzzyXMLNode) {
return getNodeText((FuzzyXMLNode) element);
}
return super.getText(element);
}
}
/** This listener is called when selection of TreeViewer is changed. */
private class HTMLSelectionChangedListener implements ISelectionChangedListener {
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection sel = (IStructuredSelection) event.getSelection();
Object element = sel.getFirstElement();
if (element instanceof FuzzyXMLNode) {
int offset = ((FuzzyXMLNode) element).getOffset();
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IEditorPart editorPart = page.getActiveEditor();
if (editorPart instanceof HTMLEditor) {
((HTMLEditor) editorPart).setOffset(offset);
}
else if (editorPart instanceof HTMLSourceEditor) {
((HTMLSourceEditor) editorPart).selectAndReveal(offset, 0);
}
else {
HTMLSourceEditor sourceEditor = (HTMLSourceEditor) editorPart.getAdapter(HTMLSourceEditor.class);
if (sourceEditor != null) {
sourceEditor.selectAndReveal(offset, 0);
}
}
}
}
}
}