Wednesday, February 26, 2014

Adding a list editor in eclipse preference. Extend ListEditor

Adding a list editor in Eclipse preferences implies to extend ListEditor.
This  post concern the build of a ListEditor dealing with filter definition relying on regular expression.


The beginning,  create a FilterDialog

This dialog aims to get a filter entry. This dialog should return a String containing a regular expression. (I don't verify that the content typed is OK but I will)


the FilterDialog source code :

import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class FilterDialog extends TitleAreaDialog {

  private Text filterValue;

  private String filter;

  public FilterDialog(Shell parentShell) {
    super(parentShell);
  }

  @Override
  public void create() {
    super.create();
    setTitle("Add filter to keep tests");
  }

  @Override
  protected Control createDialogArea(Composite parent) {
    Composite area = (Composite) super.createDialogArea(parent);
    Composite container = new Composite(area, SWT.NONE);
    container.setLayoutData(new GridData(GridData.FILL_BOTH));
    GridLayout layout = new GridLayout(2, false);
    container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    container.setLayout(layout);
    createFilter(container);
    return area;
  }

  private void createFilter(Composite container) {
    Label lbtFirstName = new Label(container, SWT.NONE);
    lbtFirstName.setText("Filter as regular expression");

    GridData dataFirstName = new GridData();
    dataFirstName.grabExcessHorizontalSpace = true;
    dataFirstName.horizontalAlignment = GridData.FILL;

    filterValue = new Text(container, SWT.BORDER);
    filterValue.setLayoutData(dataFirstName);
  }

  @Override
  protected boolean isResizable() {
    return true;
  }
 
  private void saveInput() {
    filter = filterValue.getText();
  }

  @Override
  protected void okPressed() {
    saveInput();
    super.okPressed();
  }

  public String getFilter() {
    return filter;
  }
 
} 

Extend ListEditor


the source code :
import java.io.File;

import org.eclipse.jface.preference.ListEditor;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Composite;


public class FilterTestEditor extends ListEditor {

    protected FilterTestEditor() {
    }

    public FilterTestEditor(String name, String labelText, Composite parent) {
        init(name, labelText);
        createControl(parent);
    }

    protected String createList(String[] items) {
        StringBuffer path = new StringBuffer("");//$NON-NLS-1$
        for (int i = 0; i < items.length; i++) {
            path.append(items[i]);
            path.append(File.pathSeparator);
        }
        return path.toString();
    }


    protected String getNewInputObject() {
     String filter=null;
        FilterDialog dialog = new FilterDialog(getShell());
        dialog.create();
       
        if (dialog.open() == Window.OK) {
           System.out.println(dialog.getFilter());
           filter = dialog.getFilter();
         } 
        return filter;
    }
    
    protected String[] parseString(String stringList) {
  StringTokenizer sto = new StringTokenizer(stringList, File.pathSeparator
                + "\n\r");
        ArrayList<String> v = new ArrayList<String>();
        while (st.hasMoreElements()) {
            v.add((String) sto.nextElement());
        }
        return (String[]) v.toArray(new String[v.size()]);
    }
}

and finally in the préférence page add

addField(new FilterTestEditor(KEY_FILTER_TEST, "Test filtering", getFieldEditorParent()));

Running external tools programmatically with eclipse

Small tutorial for running external tools programmatically with eclipse

Last couple of day I had to refactor code for an eclipse plugin.
The source code to modify rely on java runtime exec to launch a temporary maven project. This code works fine but the process launched does not log in eclipse console.
So at this point I look for a way to launch this maven build, external to the workspace as the eclipse menu "launch external tool does". After a few search on the web I found a way to be able to do this:
  • create a launch configuration
  • save it in a file
  • build the same setup in source code
  • and finally launch the configuration

First thing to do : create an external tool configuration...
saved in a file (see Shared file field)

Run this configuration.

You should find a file in the root folder project named : New_configuration.launch.
Now when editing this file I have all the parameters needed to write my code :
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" 
 value="${system_path:mvn.bat}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" 
 value="-Dlogback.configurationFile=customlogback.xml -U clean install exec:java"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" 
 value="D:\DONNEES\FDS_DATA\genDoc"/>
</launchConfiguration>

With this content and this address I could now write the source code that allow me to launch programmatically my temporary maven project.
A nice point here, you could rely on eclipse variable (like ${system_path:mvn.bat})  
//to be able to listen the end
manager.addLaunchListener(this);
ILaunchConfigurationType type = manager
  .getLaunchConfigurationType("org.eclipse.ui.externaltools.ProgramLaunchConfigurationType");
ILaunchConfiguration[] configurations = manager
  .getLaunchConfigurations(type);
for (int i = 0; i < configurations.length; i++) {
 ILaunchConfiguration configuration = configurations[i];
 if (configuration.getName().equals("Gen doc")) {
  configuration.delete();
  break;
 }
}
ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(
  null, "Gen doc");
String exec = "mvn.sh";
if (nameOS.toLowerCase().contains("win")) {
 exec = "mvn.bat";
}
workingCopy.setAttribute(
  "org.eclipse.ui.externaltools.ATTR_LOCATION",
  "${system_path:" + exec + "}");
workingCopy.setAttribute(
  "org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS",
  "-Dlogback.configurationFile=genDoclogback.xml -U clean install exec:java");
workingCopy.setAttribute(
  "org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY",
  tmpGenDir.getCanonicalPath());
ILaunch launch = workingCopy.launch(ILaunchManager.RUN_MODE,
  new NullProgressMonitor());
//to retreive the launched project at the end
launchProject.put(launch, project);

and to be able to listen the end of your launch configuration implement "ILaunchesListener2" and add

@Override
public void launchesTerminated(ILaunch[] launches) {
 for (ILaunch launch : launches) {
  Project project = launchProject.get(launch);
  if (project != null) {
   launchProject.remove(launch);
   //if needed...
   Display.getDefault().asyncExec(new Runnable() {
    @Override
    public void run() {
     
    }
   });
  }
 }
}