Mar 18, 2008

Exporting GEF figure to an image

Quite often you need to export the current contents of a GEF editor to an image. Here is the simple code to do that:

GraphicalViewer graphicalViewer = ...; // get it from your editor
String saveLocation = ...; // get it thru a FileDialog

ScalableFreeformRootEditPart rootEditPart = (ScalableFreeformRootEditPart) graphicalViewer.getEditPartRegistry().get(LayerManager.ID);

IFigure rootFigure = ((LayerManager) rootEditPart).getLayer(LayerConstants.PRINTABLE_LAYERS);

Rectangle rootFigureBounds = rootFigure.getBounds();

Control figureCanvas = graphicalViewer.getControl();


Image img = new Image(Display.getDefault(), rootFigureBounds.width, rootFigureBounds.height);

GC imageGC = new GC(img);

figureCanvas.print(imageGC); // This is Eclipse 3.4 only API

ImageLoader imgLoader = new ImageLoader();
imgLoader.data = new ImageData[] { img.getImageData() };

imgLoader.save(saveLocation, SWT.IMAGE_JPEG);

imageGC.dispose();

img.dispose();



Just in case you need, here is a nice image to represent this Action :-)

Mar 15, 2008

How does EMF finds the right parser?

ResourceSet resourceSet = new ResourceSetImpl();
Resource resource = resourceSet.createResource(someUri);


The API can't get any simpler. But the implementation details behind this is not simple. Resources are generally loaded by Resource.Factory. Your ECore model would have generated an appropriate Factory. You can find it in the util package with the name {your model name}ResourceFactoryImpl. Lets take a journey from the ResourceSet to this Factory.

ResourceSetImpl class delegates the job of finding the right Factory to the Resource.Factory.Registry. The default implementation of the registry (ResourceFactoryRegistryImpl) tries to find the factory by:

* lookup in the protocol map for the uri
* lookup in the extension map for the uri
* lookup in the content type map for the uri
* lookup in the extension map for the default extension (*)
* lookup in the content type map for the default content type (*)


If the above lookups did not find a factory then the delegatedGetFactory() method is called.

All three maps (protocol, extension & content type) are by default empty in the ResourceFactoryRegistryImpl. Either you can subclass and initialize in your constructor or call the resourceFactory.get{map type}ToFactoryMap().put({key}, {value}) to add your entries.

Since we have not added any entries in the registry, the delegatedGetFactory() method is called. The ResourceSetImpl overrides that method (thru an anonymous subclass of ResourceFactoryRegistryImpl) and calls again the getFactory() method with the maps from Resource.Factory.Registry.INSTANCE. BTW, all three maps in that instance are filled with the details from the extension points:

org.eclipse.emf.ecore.protocol_parser
org.eclipse.emf.ecore.extension_parser
org.eclipse.emf.ecore.content_parser

You should be using these extensions to register the right parser (the generated
ResourceFactoryImpl) for your resource.

Phew! If you think its done, you should look into the EMF code. All the above said stuff are optimized to the core. The ResourceSetImpl creates the ResourceFactoryRegistryImpl instance only when the getResourceFactoryRegistry() is called for the first time; all the above lookups are performed only when the map is not empty; and so on. EMF takes all the pain and finally we end up with:

ResourceSet resourceSet = new ResourceSetImpl();
Resource resource = resourceSet.createResource(someUri);


See, you got to love EMF. Or in general, Eclipse for making our life easier :-)

Related:

EMF Packing changes in 2.4
Using EMF with XML Catalog
Converting EMF Resource to Platform Resource (IFile)

Wizard as a Dialog

In an RCP application, I had these requirements for a Dialog box:

  • OK button should not be enabled until all the mandatory fields are filled
  • Hints for probably incorrect data (The email id grprakash+eclipse@gmail.com "looks" like a wrong one) These should not stop the user from pressing OK
  • Progress bar should be shown for long running operations (clicking OK, "check for user id availability", etc)

I was thinking on how to handle all these in a Dialog and something flashed in my mind - JFace Wizards. All the above requirements can be easily done if I use a Wizard. The Finish button is disabled when we call setPageComplete(false), we can show warnings and still allow the user to finish and by calling setNeedsProgressMonitor() & getContainer().run() we can show the progress bar in the UI as well. But there are two small issues to be handled when we use the wizard.

  • The first one is to get rid of the Back and Next buttons. We are lucky here because JFace will not show those buttons if there is only one page in the wizard
  • The "Finish" looks odd and should be renamed to "OK" or "Submit. This can be done by subclassing the WizardDialog:
WizardDialog dialog = new WizardDialog(shell, wizard) {

@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
Button finishButton = getButton(IDialogConstants.FINISH_ID);
finishButton.setText(IDialogConstants.OK_LABEL);
}
};


Now with the util method, I can enable/disable the "OK" button, reflecting the status of the UI items.

Related:
Util method for Wizard Pages
JFace Wizard Guidelines

Mar 11, 2008

Converting EMF Resource to Platform Resource (IFile)

Simple one:

EObject eObject = ...;
Resource eResource = eObject.eResource();
URI eUri = eResource.getURI();
if (eUri.isPlatformResource()) {
String platformString = eUri.toPlatformString(true);
return ResourcesPlugin.getWorkspace().getRoot().findMember(platformString);
}
return null;

Mar 6, 2008

Eclipse CVS

The CVS Repositories view in Eclipse allows you to paste a CVS URL in the "New Repository Location" Wizard. (If you are on 3.3, you can directly paste on the view without the Wizard) In case you want to browse thru the Eclipse CVS repository, here are the URLs you can copy and paste into the wizard.

Platform, SWT, JFace, Equinox, JDT, launcher, UI, update, search, debug, team, etc) are available here:
:pserver:anonymous@dev.eclipse.org:/cvsroot/eclipse
Mylyn, GEF, CDT, COBOL, VE:
:pserver:anonymous@dev.eclipse.org:/cvsroot/tools
AspectJ, Nebula, EPP:
:pserver:anonymous@dev.eclipse.org:/cvsroot/technology
EMF, GMF, MDT:
:pserver:anonymous@dev.eclipse.org:/cvsroot/modeling
WTP:
:pserver:anonymous@dev.eclipse.org:/cvsroot/webtools
Data Tools:
:pserver:anonymous@dev.eclipse.org:/cvsroot/datatools


If you want to browse thru the CVS, you can use the web based viewer also: http://dev.eclipse.org/viewcvs/
More info on connecting to Eclipse CVS: http://wiki.eclipse.org/index.php/CVS_Howto

Related:
Searching Eclipse Sources