package tk.eclipse.plugin.dtdeditor.editors; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import jp.aonir.fuzzyxml.internal.FuzzyXMLUtil; 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.views.contentoutline.ContentOutlinePage; import tk.eclipse.plugin.htmleditor.HTMLPlugin; import tk.eclipse.plugin.htmleditor.editors.IHTMLOutlinePage; /** * IContentOutlinePage implementation for DTDEditor. * * @author Naoki Takezoe * @see tk.eclipse.plugin.dtdeditor.editors.DTDEditor */ public class DTDOutlinePage extends ContentOutlinePage implements IHTMLOutlinePage { private DTDEditor editor; private DTDRootNode root; public DTDOutlinePage(DTDEditor editor){ this.editor = editor; } @Override public void createControl(Composite parent) { super.createControl(parent); TreeViewer viewer = getTreeViewer(); if(root==null){ root = new DTDRootNode(); } viewer.setContentProvider(new DTDContentProvider()); viewer.setLabelProvider(new DTDLabelProvider()); viewer.setInput(root); viewer.addSelectionChangedListener(new DTDSelectionChangedListener()); update(); } public void update() { String source = editor.getDocumentProvider().getDocument(editor.getEditorInput()).get(); source = FuzzyXMLUtil.comment2space(source, true); if(root==null){ root = new DTDRootNode(); } root.clear(); int index = 0; int last = 0; Map<String, List<DTDNode>> attrMap = new HashMap<String, List<DTDNode>>(); Map<String, DTDNode> elementMap = new HashMap<String, DTDNode>(); while((index = source.indexOf("<!", last))>=0){ if(source.startsWith("<!ELEMENT",index)){ String text = source.substring(index, source.indexOf(">", index)+1); text = text.replaceAll("\\s+"," "); String[] dim = text.split(" "); DTDNode node = new DTDNode(index, text, HTMLPlugin.ICON_ELEMENT); elementMap.put(dim[1], node); root.add(node); } else if(source.startsWith("<!ATTLIST",index)){ String text = source.substring(index, source.indexOf(">", index)+1); text = text.replaceAll("\\s+"," "); String[] dim = text.split(" "); List<DTDNode> list = attrMap.get(dim[1]); if(list==null){ list = new ArrayList<DTDNode>(); attrMap.put(dim[1], list); } list.add(new DTDNode(index, text, HTMLPlugin.ICON_ATTLIST)); } else if(source.startsWith("<!ENTITY",index)){ String text = source.substring(index, source.indexOf(">", index)+1); text = text.replaceAll("\\s+"," "); root.add(new DTDNode(index, text, HTMLPlugin.ICON_ENTITY)); } else if(source.startsWith("<!NOTATION",index)){ String text = source.substring(index, source.indexOf(">", index)+1); text = text.replaceAll("\\s+"," "); root.add(new DTDNode(index, text, HTMLPlugin.ICON_NOTATE)); } // else if(source.startsWith("<!--", index)){ // root.add(new DTDNode(index, "#comment", HTMLPlugin.ICON_COMMENT)); // } last = index + 2; } // put ATTLIST to ELEMENT for(Iterator<Map.Entry<String, List<DTDNode>>> ite = attrMap.entrySet().iterator(); ite.hasNext();){ Map.Entry<String, List<DTDNode>> entry = ite.next(); String key = entry.getKey(); List attrs = entry.getValue(); DTDNode element = elementMap.get(key); for(int i=0;i<attrs.size();i++){ DTDNode attr = (DTDNode)attrs.get(i); if(element==null){ root.add(attr); } else { element.addChild(attr); } } } TreeViewer viewer = getTreeViewer(); if(viewer!=null){ viewer.refresh(); } } /** The root node of this outline page. */ private class DTDRootNode { private List<DTDNode> children = new ArrayList<DTDNode>(); public void add(DTDNode node){ children.add(node); } public DTDNode[] getChildren(){ return this.children.toArray(new DTDNode[this.children.size()]); } public void clear(){ this.children.clear(); } } /** The node class for DTD elements. */ private class DTDNode { private int position; private String text; private String image; private List<DTDNode> children = new ArrayList<DTDNode>(); private DTDNode parent; public DTDNode(int position, String text, String image){ this.position = position; this.text = text; this.image = image; } public int getPosition(){ return this.position; } public void addChild(DTDNode node){ this.children.add(node); } public DTDNode[] getChildren(){ return this.children.toArray(new DTDNode[this.children.size()]); } public void setParent(DTDNode parent){ this.parent = parent; } public DTDNode getParent(){ return this.parent; } @Override public String toString(){ return this.text; } public String getImage(){ return this.image; } } /** ContentProvider of HTMLOutlinePage. */ private class DTDContentProvider implements ITreeContentProvider { public Object[] getChildren(Object parentElement) { if(parentElement instanceof DTDRootNode){ return ((DTDRootNode)parentElement).getChildren(); } else if(parentElement instanceof DTDNode){ return ((DTDNode)parentElement).getChildren(); } return new Object[0]; } public Object getParent(Object element) { if(element instanceof DTDNode){ DTDNode parent = ((DTDNode)element).getParent(); if(parent==null){ return root; } else { 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 DTDLabelProvider extends LabelProvider { @Override public Image getImage(Object element) { if(element instanceof DTDNode){ return HTMLPlugin.getDefault().getImageRegistry().get(((DTDNode)element).getImage()); } return null; } } /** This listener is called when selection of TreeViewer is changed. */ private class DTDSelectionChangedListener implements ISelectionChangedListener { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection sel = (IStructuredSelection)event.getSelection(); Object element = sel.getFirstElement(); if(element instanceof DTDNode){ int offset = ((DTDNode)element).getPosition(); IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); IEditorPart editorPart = page.getActiveEditor(); if(editorPart instanceof DTDEditor){ ((DTDEditor)editorPart).selectAndReveal(offset, 0); } } } } }