Archive

Archive for the ‘Jface’ Category

Inline Validations in Eclipse RCP – Field Assists

October 4, 2012 1 comment

Inline validations has been there quite a while now , and in eclipse rcp applications too we can achieve that using control decorators.
What are we going to see in this post is a control decoration , which helps to notify the user if somethings goes wrong when some action is triggered on a control.
Let us consider a real time example , let us take a pincode text field.
If an user is typing in a non-numeric field , then an error icon should be shown to the user.
Let us create a text field on which we ll be adding the decoration.


Label label = new Label(parent, SWT.NONE);
label.setText("Please Enter Pincode:");
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		
Text  txtPincode = new Text(parent , SWT.NONE);
txtPincode.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		
//Adding the decorator
final ControlDecoration txtDecorator = new ControlDecoration(txtPincode, SWT.TOP|SWT.RIGHT);
FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry .DEC_ERROR);
Image img = fieldDecoration.getImage();
txtDecorator.setImage(img);
txtDecorator.setDescriptionText("Pls enter only numeric fields");
// hiding it initially
txtDecorator.hide();
		
txtPincode.addKeyListener(new KeyAdapter() {
			
  @Override
 public void keyReleased(KeyEvent e) {
     Text text = (Text)e.getSource();			
     String string = text.getText();
     char[] chars = new char[string.length()];
     string.getChars(0, chars.length, chars, 0);
      for (int i = 0; i < chars.length; i++)
        {
            if (!('0' <= chars[i] && chars[i] <= '9'))
            {
           	txtDecorator.show();
            }
            else
            {
            	txtDecorator.hide();
            }

        }
		       
}
});
		

Sample screenshot:

On a short note just giving a quick reference for decorators here.
Decorators are often used for other purposes with views also.
The above reference link and this eclipse article will help you cover that.

Happy coding… ūüôā

Categories: eclipse rcp, Jface Tags: ,

Eclipse RCP – AutoCompleteCombo/Text control

December 12, 2011 Leave a comment

In the recent project there was a requirement from the client where they want some sort of filtering in the drop down combo box as they felt its really difficult to choose from the combo if they have lots of items to choose.

So , we decided to work on that , and we found content proposal will be a good idea to get rid of this.

Here I am sharing the code snippet using that we can enable content proposals for combo and text controls.


import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.fieldassist.ComboContentAdapter;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class AutoCompleteComboTextControls {

	private static final String LCL = "abcdefghijklmnopqrstuvwxyz";
	private static final String UCL = LCL.toUpperCase();
	private static final String NUMS = "0123456789";
	private static final String[] items = new String[] { "Alpha", "Beta", "gaama", "pie",
		"alge","bata" };


	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new GridLayout(1, false));
		shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		shell.setSize(200, 200);
		shell.setText("Auto Complete Controls");
		
		Monitor primaryMonitor = display.getPrimaryMonitor ();
		Rectangle bounds = primaryMonitor.getBounds ();
		Rectangle rect = shell.getBounds ();
		int x = bounds.x + (bounds.width - rect.width) / 2 ;
		int y = bounds.y + (bounds.height - rect.height) / 2 ;
		shell.setLocation (x, y);
		
		Combo combo = new Combo(shell, SWT.NONE);
		combo.setItems(items);
		combo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

		combo.addSelectionListener(new SelectionAdapter() {
			
			// called for keyboard enter press
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}

			@Override
			public void widgetSelected(SelectionEvent e) {
			}
		});
		
//		Have a look at Jface AutoCompleteField class also
		enableContentProposal(combo);
		
		Text text = new Text(shell, SWT.BORDER);
		text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		enableContentProposal(text);
		
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
	
	static  void enableContentProposal(Control control)
	    {
	        
	        SimpleContentProposalProvider proposalProvider = null;
	        ContentProposalAdapter proposalAdapter = null;
	        if (control instanceof Combo)
	        {
	            Combo combo = (Combo) control;
	            proposalProvider = new SimpleContentProposalProvider(combo.getItems());
	            proposalAdapter = new ContentProposalAdapter(
	                combo,
	                new ComboContentAdapter(),
	                proposalProvider,
	                getActivationKeystroke(),
	                getAutoactivationChars());
	        }
	        else if (control instanceof Text)
	        {
	            
	            Text text = (Text) control;
	            proposalProvider = new SimpleContentProposalProvider(items);
	            proposalAdapter = new ContentProposalAdapter(
	                text,
	                new TextContentAdapter(),
	                proposalProvider,
	                getActivationKeystroke(),
	                getAutoactivationChars());
	        }
	        proposalProvider.setFiltering(true);
	        proposalAdapter.setPropagateKeys(true);
	        proposalAdapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);

	    }
	

	
	// this logic is  from swt addons project
	 static char[] getAutoactivationChars() {

		// To enable content proposal on deleting a char
		
		String delete = new String(new char[] { 8 });
		String allChars = LCL + UCL + NUMS + delete;
		return allChars.toCharArray();
	}

	 static KeyStroke getActivationKeystroke() {
		KeyStroke instance = KeyStroke.getInstance(
				new Integer(SWT.CTRL).intValue(), new Integer(' ').intValue());
		return instance;
	}

}

As the content proposal adapter of the jface does not handle the deletion of char, we have to add it in our logic which you can see in getAutoactivationChars() method. This logic is from SWT Addons project .Have a look into SWT Add-ons project.

Note: One annoying thing which I found while implementing this is , after selecting any items from the list via enter press in the keyboard. The control is jus transferred from the content dialog to the combo or text. So if you are handling anything on enter key press for combo or text then user may have to press the enter button twice.

I Hope this is useful.
Happy coding… ūüôā

Categories: eclipse rcp, Jface Tags: ,

JFace Wizard Explained – Enabling/Disabling Next, finish buttons

November 22, 2011 3 comments

This post assumes the reader has basic knowledge about creating jface wizards. To know about the basics refer here.

One of the most used member of the jface is the wizard. Almost in every rcp application this is used. I have quite a experience in wizard and I would like to post this for easy understanding for the people who are new to jface wizard.

As you might know wizard is commonly used for sequence of operations which require more than one input followed by their processing and finishing the process with the processed input.

Please  refer the flow chart below for the initial flow of wizard and wizard page creations.

One of the important thing which is in programmer’s control in wizard is the enabling/disabling of the buttons (back, next & finish) in the wizard.

As from the flow chart you can see when the wizard is created the wizard‚Äôs canFinish() method is called . if it is returning ‚Äėfalse‚Äô then finish button will be disabled else willl be enabled.

If we are not overriding the canFinish() method then by default the finish button will be enabled.

In most of the cases we should disable the finish button at the start and enable the next button for the current page based on some user selection.

Wizard provides an API to enable/disable finish button based on programmer’s preference.

‚ÄėsetPageComplete(boolean) ‚Äė if it is set to true the finish get enabled disabled otherwise.

So , calling setPageComplete(false) in the wizard page(s) constructor will make the finish button to be disabled at the beginning of the wizard.

In the process of wizard user have to enable/disable ‚ÄúNext button alone‚ÄĚ , ¬†so overriding canFlipToNextPage() in the wizard page¬† will help us to do the same. One important thing we have to note here is programmer has to explicitly call the ‚ÄúgetWizard().getContainer().updateButtons()‚ÄĚ to update the buttons.

Please refer to the below flow chart for updateButtons() actions. For better reading I have splitted the actions which is taking place in updateButtons() method in to two process.

Note: setPageComplete(Boolean) internally again calls the canFinish() method of the wizard . so if overided it is programmer’s responsibility to retrun true/false.

I am attaching sample code below.

Wizard Class:


import org.eclipse.jface.wizard.Wizard;

public class MyWizard extends Wizard {

FirstPage firstPage = null;
 SecondPage secondPage = null;

public MyWizard() {
 super();
 }

public void addPages()
 {
 firstPage = new FirstPage("First Page");
 addPage(firstPage);

secondPage = new SecondPage("secondpage");
 addPage(secondPage);
 }

/*
 * (non-Javadoc)
 * @see org.eclipse.jface.wizard.Wizard#performFinish()
 *
 * Varies according to user needs...
 */
 @Override
 public boolean performFinish() {
 return firstPage.isPageComplete() && secondPage.isPageComplete();
 }

}

Wizard Pages:


import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;

public class FirstPage extends WizardPage {

private CheckboxTableViewer checkboxTableViewer;
private boolean enableNext;

protected FirstPage(String pageName) {
super(pageName);
setTitle(pageName);
//        this is doing the trick
setPageComplete(false);
}

@Override
public void createControl(Composite arg0) {

Composite container = new Composite(arg0,SWT.NONE);
container.setLayout(new GridLayout());
container.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));

checkboxTableViewer = CheckboxTableViewer.newCheckList(container, SWT.FULL_SELECTION|SWT.BORDER);
checkboxTableViewer.getTable().setLinesVisible(true);
checkboxTableViewer.setContentProvider(new ArrayContentProvider());
checkboxTableViewer.setLabelProvider(new ITableLabelProvider() {

@Override
public void removeListener(ILabelProviderListener arg0) {

}

@Override
public boolean isLabelProperty(Object arg0, String arg1) {
return false;
}

@Override
public void dispose() {

}

@Override
public void addListener(ILabelProviderListener arg0) {

}

@Override
public String getColumnText(Object element, int columnIndex) {
return element.toString();
}

@Override
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
});

checkboxTableViewer.setInput(new String[] {"one ","two","three"});

checkboxTableViewer.addCheckStateListener(new ICheckStateListener() {

@Override
public void checkStateChanged(CheckStateChangedEvent event) {
if(checkboxTableViewer.getCheckedElements().length > 0) {
enableNext = true;
}else {
enableNext = false;
}
checkStatus();

}

private void checkStatus() {
canFlipToNextPage();
//                explicit call
getWizard().getContainer().updateButtons();

}
});

setControl(container);

}

@Override
public IWizardPage getNextPage() {
IWizardPage[] pages = getWizard().getPages();
//        hard coding for this case . But this is bad..
return pages[1];
}

@Override
public boolean canFlipToNextPage() {
return enableNext;
}

@Override
public boolean isPageComplete() {
IWizardPage[] pages = getWizard().getPages();
//        hard coding for this case . But this is bad..
if(enableNext && pages[1].isPageComplete()) {
return true;
}
return false;
}

}

 


import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;

public class SecondPage extends WizardPage {

private Button button;

protected SecondPage(String pageName) {
super(pageName);
setTitle(pageName);
setPageComplete(false);
}

@Override
public void createControl(Composite arg0) {
Composite container = new Composite(arg0,SWT.NONE);
container.setLayout(new GridLayout());
container.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));

button = new Button(container, SWT.CHECK);
button.setText("check to finish the process");
button.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,false));

button.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
if (button.getSelection()) {
setPageComplete(false);

}else {
setPageComplete(true);
}
}
});

setControl(container);
}

}

Happy Coding.. ūüôā

Categories: Jface Tags: , ,