package org.objectstyle.wolips.templateeditor; import java.util.LinkedList; import java.util.List; import jp.aonir.fuzzyxml.FuzzyXMLDocument; import jp.aonir.fuzzyxml.FuzzyXMLElement; import jp.aonir.fuzzyxml.FuzzyXMLNode; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.editors.text.TextEditor; import org.objectstyle.wolips.bindings.wod.IWodElement; import org.objectstyle.wolips.variables.BuildProperties; import org.objectstyle.wolips.wodclipse.core.completion.WodParserCache; import org.objectstyle.wolips.wodclipse.core.document.WodElementTypeHyperlink; import org.objectstyle.wolips.wodclipse.core.util.ICursorPositionListener; import org.objectstyle.wolips.wodclipse.core.util.WodHtmlUtils; public class TemplateBreadcrumb extends Composite implements ICursorPositionListener, MouseListener { private TemplateSourceEditor _editor; public TemplateBreadcrumb(TemplateSourceEditor editor, Composite parent, int style) { super(parent, style); setBackground(parent.getBackground()); RowLayout breadcrumbLayout = new RowLayout(); breadcrumbLayout.wrap = false; breadcrumbLayout.pack = true; breadcrumbLayout.justify = false; breadcrumbLayout.type = SWT.HORIZONTAL; breadcrumbLayout.marginLeft = 5; breadcrumbLayout.marginTop = 3; breadcrumbLayout.marginRight = 5; breadcrumbLayout.marginBottom = 3; breadcrumbLayout.spacing = 5; setLayout(breadcrumbLayout); _editor = editor; _editor.addCursorPositionListener(this); addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { GC gc = e.gc; Color separatorColor = new Color(gc.getDevice(), 205, 205, 205); gc.setForeground(separatorColor); gc.drawLine(0, 0, getBounds().width, 0); separatorColor.dispose(); } }); updateBreadcrumb(); } public void cursorPositionChanged(TextEditor editor, Point selectionRange) { updateBreadcrumb(); } public void updateBreadcrumb() { try { WodParserCache cache = _editor.getParserCache(); Point selectionRange = _editor.getSelectedRange(); FuzzyXMLElement element = null; FuzzyXMLDocument document = cache.getHtmlEntry().getModel(); if (document != null) { element = document.getElementByOffset(selectionRange.x); } Control[] children = getChildren(); for (int i = children.length - 1; i >= 0; i--) { children[i].dispose(); } boolean emptyBreadcrumb = true; if (element != null) { List<FuzzyXMLNode> elementStack = new LinkedList<FuzzyXMLNode>(); FuzzyXMLNode currentNode = element; do { elementStack.add(currentNode); currentNode = currentNode.getParentNode(); } while (currentNode != null); for (int i = elementStack.size() - 2; i >= 0; i--) { FuzzyXMLNode stackNode = elementStack.get(i); if (stackNode instanceof FuzzyXMLElement) { emptyBreadcrumb = false; FuzzyXMLElement stackElement = (FuzzyXMLElement) stackNode; FuzzyXMLElementWithWodElement data; String tagName = stackElement.getName(); boolean isWOTag = WodHtmlUtils.isWOTag(tagName); String displayName = null; if (isWOTag) { BuildProperties buildProperties = (BuildProperties)cache.getProject().getAdapter(BuildProperties.class); IWodElement wodElement = WodHtmlUtils.getWodElement(stackElement, buildProperties, true, cache); if (wodElement != null) { displayName = wodElement.getElementType(); } data = new FuzzyXMLElementWithWodElement(stackElement, wodElement); } else { displayName = tagName; data = new FuzzyXMLElementWithWodElement(stackElement, null); } if (displayName == null) { displayName = "<unknown>"; } Label nodeButton = new Label(this, SWT.NONE); nodeButton.setData(data); nodeButton.setBackground(getBackground()); nodeButton.setText(displayName); nodeButton.addMouseListener(this); nodeButton.setCursor(getDisplay().getSystemCursor(SWT.CURSOR_HAND)); if (!isWOTag) { nodeButton.setForeground(getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY)); } } if (i > 0) { Label arrowLabel = new Label(this, SWT.NONE); arrowLabel.setBackground(getBackground()); arrowLabel.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); arrowLabel.setText(">"); } } if (emptyBreadcrumb) { Label emptyLabel = new Label(this, SWT.NONE); emptyLabel.setBackground(getBackground()); emptyLabel.setForeground(getDisplay().getSystemColor(SWT.COLOR_GRAY)); emptyLabel.setText("..."); } layout(); getParent().layout(); } } catch (Throwable t) { t.printStackTrace(); } } public void mouseDoubleClick(MouseEvent event) { Label label = (Label) event.getSource(); FuzzyXMLElementWithWodElement data = (FuzzyXMLElementWithWodElement) label.getData(); if (data != null && data.getWodElement() != null) { try { WodElementTypeHyperlink.toElementTypeHyperlink(data.getWodElement(), _editor.getParserCache()).open(); } catch (Exception e) { e.printStackTrace(); } } } public void mouseDown(MouseEvent event) { Label label = (Label) event.getSource(); FuzzyXMLElementWithWodElement data = (FuzzyXMLElementWithWodElement) label.getData(); if (data != null && data.getElement() != null) { FuzzyXMLElement element = data.getElement(); int offset = element.getOffset(); int length = element.getLength(); _editor.selectAndReveal(offset, length); } } public void mouseUp(MouseEvent event) { // DO NOTHING } public static class FuzzyXMLElementWithWodElement { private FuzzyXMLElement _element; private IWodElement _wodElement; public FuzzyXMLElementWithWodElement(FuzzyXMLElement element, IWodElement wodElement) { _element = element; _wodElement = wodElement; } public FuzzyXMLElement getElement() { return _element; } public IWodElement getWodElement() { return _wodElement; } } }