JavaOne 2014 – Visualize your DSL – Building 3d Lego models with Xtext and JavaFX


JavaOne 2014 is not too far ahead and because I’m doing 2 session:

I’ve been busy working on show cases and the demo application. The demo application visualizes 3d objects of any kind, I thought a nice and not too complex example are structures built from lego bricks. Naturally one can create Lego 3d models using any 3d modeling software but for someone like me who is not using them on a daily base this is a bit cumbersome and I’m faster using a DSL who allows me to those in a textual editor inside my IDE and so I defined a DSL who allows me to define lego bricks and mix and match them to create bigger structures.

Definition Lego DuploTm Bricks:
lego_bricks

Definition of a Lego DuploTm structure:
lego_assembly

The reality:
Foto

The really interesting thing in this regard is that to create a visual representation of the editor content (the editors are on the left hand side of the Eclipse IDE screenshots) is that all that needs to be done is to contribute an adapter into your IDE which adapts your editor (must not be xtext based) and provide an FXML representation of the editors content.

For the above editors this looks like this:

The adapter for the xtext-editor:

package at.bestsolution.lego.ui.preview;

import java.net.URL;
import java.util.Collections;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.fx.ide.ui.editor.IFXMLProviderAdapter;
import org.eclipse.ui.IEditorPart;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.XtextEditor;
import org.eclipse.xtext.util.concurrent.IUnitOfWork;

import at.bestsolution.lego.lego.Model;
import at.bestsolution.lego.ui.internal.LegoActivator;

import com.google.inject.Injector;

public class FXMLProviderAdapter implements IFXMLProviderAdapter {
	private XtextEditor editor;
	
	public FXMLProviderAdapter(XtextEditor editor) {
		this.editor = editor;
	}

	@Override
	public IEditorPart getEditorPart() {
		return editor;
	}
	
	@Override
	public String getPreviewFXML() {
		return editor.getDocument().readOnly(new IUnitOfWork<String, XtextResource>() {

			@Override
			public String exec(XtextResource resource) throws Exception {
				Injector injector = LegoActivator.getInstance().getInjector("at.bestsolution.lego.Lego");
				PreviewGenerator generator = injector.getInstance(PreviewGenerator.class);
				return generator.generatePreview((Model) resource.getContents().get(0)).toString();
			}
			 
		});
	}
		
	@Override
	public String getPreviewSceneFXML() {
		return null;
	}

	@Override
	public List<String> getPreviewCSSFiles() {
		return Collections.emptyList();
	}

	@Override
	public String getPreviewResourceBundle() {
		return null;
	}

	@Override
	public List<URL> getPreviewClasspath() {
		return Collections.emptyList();
	}

	@Override
	public IFile getFile() {
		return editor.getDocument().readOnly(new IUnitOfWork<IFile, XtextResource>() {

			@Override
			public IFile exec(XtextResource resource) throws Exception {
				URI uri = resource.getURI();
				Path structureFilePath = new Path(uri.toPlatformString(true));
				IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(structureFilePath);
				if( f.exists() ) {
					return f;
				}
				return null;
			}
			
		});
	}
}

The adapter factory registered inside the Eclipse IDE:

package at.bestsolution.lego.ui.preview;

import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.fx.ide.ui.editor.IFXMLProviderAdapter;
import org.eclipse.fx.ide.ui.editor.IFXPreviewAdapter;
import org.eclipse.xtext.ui.editor.XtextEditor;

public class FXMLAdapterFactory implements IAdapterFactory {

	@Override
	public Object getAdapter(Object adaptableObject, Class adapterType) {
		if((adapterType == IFXMLProviderAdapter.class || adapterType == IFXPreviewAdapter.class) && adaptableObject instanceof XtextEditor ) {
			XtextEditor editor = (XtextEditor) adaptableObject;
			if( "at.bestsolution.lego.Lego".equals(editor.getLanguageName()) ) {
				return new FXMLProviderAdapter(editor);
			}
		}
		return null;
	}

	@Override
	public Class[] getAdapterList() {
		return new Class[]{IFXMLProviderAdapter.class, IFXPreviewAdapter.class};
	}

}
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
  <!-- .... -->
  <extension
        point="org.eclipse.core.runtime.adapters">
     <factory
            adaptableType="org.eclipse.xtext.ui.editor.XtextEditor"
            class="at.bestsolution.lego.ui.preview.FXMLAdapterFactory">
         <adapter
               type="org.eclipse.fx.ide.ui.editor.IFXPreviewAdapter">
         </adapter>
         <adapter
               type="org.eclipse.fx.ide.ui.editor.IFXMLProviderAdapter">
         </adapter>
      </factory>
  </extension>
  <!-- .... -->
</plugin>

5 thoughts on “JavaOne 2014 – Visualize your DSL – Building 3d Lego models with Xtext and JavaFX

  1. Marco Descher September 17, 2014 / 3:29 pm

    Really cool!!! Wish I could be there, and listen to that talk!:)

  2. Hallvard Trætteberg September 18, 2014 / 7:17 am

    Really nice (and fun) application! The adapter technique is very useful, I’ve done something similar with PlantUML, to get a diagram view of the content of various editors, e.g. UML for Ecore/Xcore.

    BTW, I’m taking part in arranging afternoon programmering courses for kids, where they move from Scratch to Python and now Java with JavaFX. This kind of 3D modeling would be great to show them!

    • Tom Schindl September 18, 2014 / 8:55 am

      You are free to show it off😉 the sources are published under GPLv3 at https://github.com/BestSolution-at/ (there’s currently one hard wired path we need to fix) but then it should useable out-of-the-box.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s