Aug 19, 2008

The End

This blog has been moved to a domain which matches this blog title: http://blog.eclipse-tips.com. All the posts, comments are moved there. There won't be any more posts in this blog and comments are also disabled. Please submit your comments on the new blog. Clicking on the post's title, should take you to the appropriate post in the new domain.

I've migrated all the subscribers to that blog. If you are reading this blog post RSS readers/Email, please let me know. Something went wrong in the process.

Aug 13, 2008

ArrayContentProvider - A default implementation for IStructuredContentProvider

Today I discovered that JFace provides a nice default implementation for the IStructuredContentProvider - the org.eclipse.jface.viewers.ArrayContentProvider class. Most of the time, the input to a ListViewer will be either an array of objects or List of objects. This content provider handles both cases. In fact it handles Collection - so you can even pass a Set or Queue to the viewer.setInput() method.

This might be the shortest tip I've ever written. Couldn't resist myself from blogging this. Hope its useful :-)

Aug 6, 2008

Using Dynamic Templates in EMF

In the previous tips, we saw how to use the ECore to generate new methods & comments. Now lets see how to customize the generation process itself.

EMF uses JET to generate the Java code. EMF ships a default set of JET templates which are used for the code generation. However, you can create your own templates and ask EMF to use that. Creating those templates from scratch is an enormous task, the best approach is to edit the default templates.

The default templates are available inside the org.eclipse.emf.codegen.ecore plugin. To get those into your project:

  • Open the Plug-ins view and Right click the org.eclipse.emf.codegen.ecore plugin
  • Select Import As -> Binary Project


  • Now your workspace should contain this plug-in project. Copy the templates directory and Paste it in your EMF Project. After this step, you can delete the org.eclipse.emf.codegen.ecore project and remove it from your workspace. 

  • Set the Dynamic Templates to true and specify the directory where your templates are stored.

Now that you have the templates in your project, let tell EMF to use these. Open your .genmodel and go to the Properties View.

You can customize these templates to suit your requirements. Say for example, you want edit the Copyright statement that is generated in every Java file. Open the templates/Header.javajetinc file and add the required content. You would have to know JET to do that, but its fairly simple. You can refer to the articles here and here for more help on JET.

Jul 31, 2008

Eclipse Search - now with a Firefox plugin

Sometime ago I wrote about the Eclipse Search, a Google Custom Search that I created for searching Eclipse related resources. It searches around 250 sites and presents the results with different labels like Blogs, Docs, Source etc. Today I thought of creating a Firefox Search plugin. Unlike my estimations, the task was completed in an hour or so. Gave a revamp to the search page and moved it to a new location also. Try some queries like EMF in both Google and this Eclipse Search and see the difference yourself.



BTW, in case you are interested in installing the Firefox Plugin, go to this page, and the search engine will be automatically detected:



 Just add the engine and start searching.



To uninstall the plugin, click the "Manage Search Engines" and select Eclipse Search and Delete it.



On a related note, I've implemented this as an OpenSearch plugin, which means it should work exactly the same way in IE 7 also. I didn't have access to Windows box, I hope it works fine there as well.

Jul 19, 2008

How to create a new File Wizard?

Problem is simple. Implement a INewWizard for creating some file type in your application.



For this problem, I have seen people start creating the WizardPage on their own. But luckily there is a reusable WizardPage which is specifically meant for this - WizardNewFileCreationPage. In this tip, lets see how to use the class. Lets assume that we need to create a new properties file with the extension .config



First we need to create a sub class of WizardNewFileCreationPage.



public class NewConfigFileWizardPage extends WizardNewFileCreationPage {

    public NewConfigFileWizardPage(IStructuredSelection selection) {
        super("NewConfigFileWizardPage", selection);
        setTitle("Config File");
        setDescription("Creates a new Config File");
        setFileExtension("config");
    }

    @Override
    protected InputStream getInitialContents() {
        try {
            return Activator.getDefault().getBundle().getEntry("/resources/newFileContents.config").openStream();
        } catch (IOException e) {
            return null; // ignore and create empty comments
        }
    }
}




The constructor sets the initial selection, wizard page title & description and the extension of the file to be created. Not just extension, you can even set the initial name for the file also using the setFileName() method.



If you want to create some default contents for this file, override the getInitialContents(). I've taken the initial contents from a file, but you can have your own logic there.



WizardPage is done, lets see the code for Wizard:



public class NewConfigFileWizard extends Wizard implements INewWizard {

    private IStructuredSelection selection;
    private NewConfigFileWizardPage newFileWizardPage;
    private IWorkbench workbench;
 


    public NewConfigFileWizard() {

        setWindowTitle("New Config File");

    } 






    @Override
    public void addPages() {

        newFileWizardPage = new NewConfigFileWizardPage(selection);
        addPage(newFileWizardPage);
    }
   
    @Override
    public boolean performFinish() {
       
        IFile file = newFileWizardPage.createNewFile();
        if (file != null)
            return true;
        else
            return false;
    }

    public void init(IWorkbench workbench, IStructuredSelection selection) {
        this.workbench = workbench;
        this.selection = selection;
    }
}







Nothing fancy in this. Just call the wizardPage's createNewFile() method when Finish button is pressed. Thats it. Now what are the advantages that we get by reusing WizardNewFileCreationPage rather than the one hand crafted by you?



  • Live error notification if a file already exists in the selected folder for the name you typed

  • It understand the selection in the Package Explorer/Navigator and selects it for you


  • If the parent folder structure you have entered is not present, it will automatically create it for you

  • Allows you to link to a different file (in this case your getInitialContents() will not be called)


  • Undo/Redo support - You can undo/redo the file creation





Now next time you want to create a new file, don't reinvent the wheel. Just use the WizardNewFileCreationPage.



The above code works just fine. Only thing is that the file is not opened in an editor. So the user will have no clue of whether its properly created or not. So in the performFinish() method, open the newly created file in an editor using one of the IDE.openEditor() methods

Jul 17, 2008

Selection Dialogs in Eclipse

If you are an Eclipse Plug-in developer, you must have used the MessageDialog. There are many other Dialogs provided by Eclipse Platform are reusable and part of the API. I'll try to explain the various selection dialogs that I know of. In case I've missed any, add a comment and do let me know. Will add it to the list
ContainerSelectionDialog:
     You can use this dialog when you want to select a container (Project/Folder) for your new resource.
 
Example:
ContainerSelectionDialog dialog = new ContainerSelectionDialog(window.getShell(), null, true, "Select a parent:");

dialog.setTitle("Container Selection");

dialog.open();
You can even restrict the resource to be within a project/folder by passing the respective object as the second parameter for the constructor.
 ResourceSelectionDialog:
The ContainerSelectionDialog allowed you to select only one resource that too it should be a container. If you want to select multiple resources including files, this is the dialog you should be using.
 
Example:
ResourceSelectionDialog dialog = new ResourceSelectionDialog(window.getShell(), ResourcesPlugin.getWorkspace().getRoot(), "Select Resource:");

dialog.setTitle("Resource Selection");

dialog.open();
ResourceListSelectionDialog:
The above dialog is good when you want to present the entire set of resources under a parent and allow the user to select multiple resources. But if you have a set of resources and want the user to select only one from that, then probably this dialog is the one you should be using.
Example:
ResourceListSelectionDialog dialog = new ResourceListSelectionDialog(window.getShell(), resourcesArray);
dialog.setTitle("Resource Selection");
dialog.open();
ElementListSelectionDialog:
Alright. So far we have been looking at selecting something from the workspace. But what if I have some elements on my own and I want to select from that? The first dialog you would be using is ElementListSelectionDialog. The user can select an element from the set. You have to pass the elements as an array and supply a  label provider to render the element. The user can filter using wildcards as well:
 
Example:
ElementListSelectionDialog dialog = new ElementListSelectionDialog(window.getShell(), new LabelProvider());

dialog.setTitle("String Selection");

dialog.setMessage("Select a String (* = any string, ? = any char):");

dialog.setElements(new Object[] { "one", "two", "three" });

dialog.open();


 
ListSelectionDialog:
That holds good for selecting a single element. What if you want to select multiple elements from the given set? ListSelectionDialog is the answer to it. It is basically a single column TableViewer with SWT.CHECK style applied. You have to supply your own ContentProvider and LabelProvider for the TableViewer. It also has Select All & Deselect All buttons. (In the example I've used workspace and the associated label & content providers, but this dialog is not tied to IResource in anyway
Example:
ListSelectionDialog dlg = new ListSelectionDialog(window.getShell(), ResourcesPlugin.getWorkspace().getRoot(), new BaseWorkbenchContentProvider(), new WorkbenchLabelProvider(), "Select the Project:");
dlg.setTitle("Project Selection");
dlg.open();
CheckedTreeSelectionDialog:
If you have your items in a tree structure and want to select few elements from them, then CheckedTreeSelectionDialog is your choice. You have to bring your own content & label provider and the input. Again, due to sheer laziness, I'm using the workspace as the input and associated content & label providers, but remember that this dialog can work well with your own data as well.
Example:
CheckedTreeSelectionDialog dialog = new CheckedTreeSelectionDialog(window.getShell(), new WorkbenchLabelProvider(), new BaseWorkbenchContentProvider());

dialog.setTitle("Tree Selection");

dialog.setMessage("Select the elements from the tree:");

dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());

dialog.open();
ElementTreeSelectionDialog:
This is the same as the above except that it will allow you to select a single element in the whole tree rather than multiple elements. Again, not tied to workspace & resources.
Example:
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(window.getShell(), new WorkbenchLabelProvider(), new BaseWorkbenchContentProvider());
dialog.setTitle("Tree Selection");
dialog.setMessage("Select the elements from the tree:");
dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
dialog.open();
FilteredItemsSelectionDialog:
Have you used the Open Type (Ctrl + Shift + T) or Open Resource (Ctrl+Shift+R) dialog? Its similar to the ElementListSelectionDialog, but it has more features. It can select multiple items, display a detail pane about the item that is currently selected, it can even remember your previous selections; store them in history and present them before the other choices. 
FilteredItemsSelectionDialog is the key. Its an abstract class and you have to extend it and create a concrete implementation to use it. I'll resever the details of extending it for a separate tip, till then you can go thru the JavaDoc.



[Update]: This has been added to the Eclipse User Interface Guidelines.

Jul 12, 2008

[Off Topic] Making magic with Eclipse

Yeah, we all know that with Eclipse, we can code, run jUnit, play sudoku, chat with your friend all that. But how about connecting to another computer and get the display inside your Eclipse?

I happened to come across this bug and saw the attached screencast. I'm really impressed with the work that is being done. I wish this makes into Eclipse.