package org.erlide.ui.console; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.TypedRegion; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.console.IConsoleDocumentPartitioner; /** * This document partitioner does not actually partition things, but receives * ranges with the valid styles, so, each range maps to a style. * * Aside from that, all is marked as the default content type. */ public class ErlangConsolePartitioner implements IConsoleDocumentPartitioner { private static final String[] LEGAL_CONTENT_TYPES = new String[] { IDocument.DEFAULT_CONTENT_TYPE }; private final List<ScriptStyleRange> ranges = new ArrayList<>(); public ErlangConsolePartitioner() { } /** * Adds a given style range. * * When a range is added, the ranges that were added before must be * removed/updated if the added range has some intersection with a previous * one. * * The ranges must all be set sequentially, so, all the ranges that have * some intersection with that range must be removed/updated. * * @param r * the range to be added. */ public void addRange(final ScriptStyleRange r) { if (r.length > 0) { // only add ranges with some len. for (int i = ranges.size() - 1; i >= 0; i--) { final ScriptStyleRange last = ranges.get(i); final int end = last.start + last.length; if (end > r.start) { if (r.start <= last.start) { ranges.remove(i); } else { last.length = r.start - last.start; } } else { break; } } boolean updatedRange = false; if (!ranges.isEmpty()) { final ScriptStyleRange lastRange = ranges.get(ranges.size() - 1); if (lastRange.scriptType == r.scriptType) { if (lastRange.start + lastRange.length == r.start) { lastRange.length += r.length; updatedRange = true; } } } if (!updatedRange) { ranges.add(r); } } } /** * @return the ranges that intersect with the given offset/length. */ @Override public ScriptStyleRange[] getStyleRanges(final int offset, final int length) { int lastOffset = -1; boolean found = false; final List<ScriptStyleRange> result = new ArrayList<>(); for (int i = ranges.size() - 1; i >= 0; i--) { final ScriptStyleRange r = ranges.get(i); if (r.start >= offset && r.start <= offset + length || r.start < offset && r.start + r.length > offset) { found = true; // it must always be a copy because it may be changed later by // the TextConsole when // some hyperlink has a matching position. result.add(0, (ScriptStyleRange) r.clone()); if (lastOffset == -1) { lastOffset = r.start + r.length; } } else if (found) { // break on 1st not found (after finding the 1st) break; } } if (lastOffset == -1) { lastOffset = offset; } if (lastOffset < offset + length) { // if we haven't been able to cover the whole range, there's // probably something wrong (so, let's // leave it in gray so that we know about that). final ScriptStyleRange lastPart = new ScriptStyleRange(lastOffset, offset + length - lastOffset, Display.getDefault().getSystemColor(SWT.COLOR_GRAY), Display.getDefault().getSystemColor(SWT.COLOR_WHITE), ScriptStyleRange.UNKNOWN); result.add(lastPart); } return result.toArray(new ScriptStyleRange[result.size()]); } // -------------------- Just return default content type for any related // request ------------------------------------ @Override public boolean isReadOnly(final int offset) { return false; } @Override public ITypedRegion[] computePartitioning(final int offset, final int length) { return new TypedRegion[] { new TypedRegion(offset, length, IDocument.DEFAULT_CONTENT_TYPE) }; } @Override public void connect(final IDocument document) { } @Override public void disconnect() { } @Override public void documentAboutToBeChanged(final DocumentEvent event) { } @Override public boolean documentChanged(final DocumentEvent event) { return false; } @Override public String getContentType(final int offset) { return IDocument.DEFAULT_CONTENT_TYPE; } @Override public String[] getLegalContentTypes() { return LEGAL_CONTENT_TYPES; } @Override public ITypedRegion getPartition(final int offset) { return new TypedRegion(offset, 1, IDocument.DEFAULT_CONTENT_TYPE); } }