Merge / Compare dialogs and XML syntax highlighting

I have just implemented a refactoring feature for Petals projects (at least for those that aim at defining Petals services). The Eclipse refactoring framework is convenient and provides most of the required things. Besides, you can find interesting tutorials that will help you for an advanced usage.

After having implemented the basis of the feature, I then wanted to make it little more nicer. Indeed, the compare viewer was a simple text viewer, with no syntax highlighting. As most of the Petals files are XML files, having an enhanced viewer was rather important for the user experience.

Obviously, the first reflex in such a case, is to try to reuse an existing class or mechanism. For almost any language or editor within Eclipse, that would be quite simple. A source viewer configuration would solve it.

But not for XML. In fact, the Eclipse XML editor does not provide a real source viewer configuration. It was designed to only work with classes from the same project. So, either you create your own source viewer configuration, or you try to hack the custom viewer configuration of the Eclipse XML editor.

I chose the second option.
The first thing to do is to create an extension for org.eclipse.compare.contentMergeViewers

<extension
       point="org.eclipse.compare.contentMergeViewers">
    <viewer
           class="com.ebmwebsourcing.petals.common.internal.compare.XmlViewerCreator"
           extensions="xml, xsd, wsdl, bpel, composite"
           id="com.ebmwebsourcing.petals.common.xmlViewer">
     </viewer>
</extension>

As you an see, I registered it for several kind of XML files.
The class is a factory for the viewer that will be used in the compare dialog.
Its code is:

public class XmlViewerCreator implements IViewerCreator {

	public XmlViewerCreator() {
		// nothing
	}

	public Viewer createViewer( Composite parent, CompareConfiguration config ) {
		return new XmlViewer( parent, config );
	}
}

And here is the code of the XmlViewer.
The hack consists in intercepting the elements that do not work with the XML editor classes and create an adapted delegate to use instead. More exactly, the StructuredTextViewerConfigurations can only work with StructuredTextViewers and IStructuredDocuments.

@SuppressWarnings( "restriction" )
public class XmlViewer extends TextMergeViewer {

	public XmlViewer( Composite parent, CompareConfiguration configuration ) {
		super( parent, configuration );
	}

	@Override
	protected void configureTextViewer( TextViewer textViewer ) {

		if( textViewer instanceof StructuredTextViewer ) {
			((SourceViewer) textViewer).configure( new StructuredTextViewerConfigurationXML());
		}
	}

	@Override
	protected SourceViewer createSourceViewer( Composite parent, int textOrientation ) {

		int style = SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL;
		return new StructuredTextViewer( parent, null, null, false, style ) {
			@Override
			public void setDocument( IDocument document ) {

				if( document instanceof IStructuredDocument ) {
					super.setDocument( document );

				} else if( document != null ) {
					String contentTypeID = ContentTypeIdForXML.ContentTypeID_XML;
					IStructuredModel scratchModel = 
					    StructuredModelManager.getModelManager()
					    .createUnManagedStructuredModelFor( contentTypeID );

					IDocument newDocument = scratchModel.getStructuredDocument();
					String s = document.get();
					newDocument.set( s );
					super.setDocument( newDocument );

				} else {
					super.setDocument( null );
				}
			}
		};
	}
}

And… voilà!


About this entry