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:
Definition of a Lego DuploTm structure:
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>
Really cool!!! Wish I could be there, and listen to that talk! 🙂
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!
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.
Pingback: JavaFX links of the week, September 22 // JavaFX News, Demos and Insight // FX Experience
Pingback: Busy JavaFX Autumn a head – EclipseCon Europe & Democamps & e(fx)clipse 1.1.0 | Tomsondev Blog