Recently, I have been working on a stand-alone SWT application.
In this application, I had to provide syntax highlighting for XML documents. With SWT, the widget to use is called StyledText. A styled text widget requires a string to display and an array of style ranges. A style range defines a style (font, font size, font style), a starting index and a length. The idea is that the style will be applied between the start and start+length positions.
What was more difficult was to find a solution to determine the style ranges from a simple XML input. Such solutions exist for Swing, but I got nothing with SWT. There are solutions within Eclipse. But there are a lot of classes, a lot of dependencies and potential configurations. Basically, what I needed was a light lexical analyzer for XML. And I could not find it (which does not mean it does not exist). So, I wrote one myself.
Reinventing the wheel is always painful but sometimes necessary.
I saved my creation as a repository on GitHub: Xml Region Analyzer. There are two classes, that you can borrow and copy in your project (seriously, no need to create a Maven artifact for that).
It is very easy to use.
List<XmlRegion> regions = new XmlRegionAnalyzer().analyzeXml( yourXmlAsAString );
And from here, defining style ranges becomes easy.
/**
* Computes style ranges from XML regions.
* @param regions an ordered list of XML regions
* @return an ordered list of style ranges for SWT styled text
*/
public static List<StyleRange> computeStyleRanges( List<XmlRegion> regions ) {
List<StyleRange> styleRanges = new ArrayList<StyleRange> ();
for( XmlRegion xr : regions ) {
// The style itself depends on the region type
// In this example, we use colors from the system
StyleRange sr = new StyleRange();
switch( xr.getXmlRegionType()) {
case MARKUP:
sr.foreground = Display.getDefault().getSystemColor( SWT.COLOR_GREEN );
sr.fontStyle = SWT.BOLD;
break;
case ATTRIBUTE:
sr.foreground = Display.getDefault().getSystemColor( SWT.COLOR_DARK_RED );
break;
// And so on...
case ATTRIBUTE_VALUE: break;
case MARKUP_VALUE: break;
case COMMENT: break;
case INSTRUCTION: break;
case CDATA: break;
case WHITESPACE: break;
default: break;
}
// Define the position and limit
sr.start = xr.getStart();
sr.length = xr.getEnd() - xr.getStart();
styleRanges.add( sr );
}
return styleRanges;
}
Anyway, this is not extraordinary but still efficient.
And since it may help others to gain some time in their projects, I shared it here.