/** * (c) 2011, Alejandro Serrano * Released under the terms of the EPL. */ package net.sf.eclipsefp.haskell.ui.internal.editors.cabal.forms; import org.eclipse.core.resources.IProject; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.forms.widgets.FormToolkit; /** * Form entry for selecting an element in a combo list. * @author Alejandro Serrano * * @param <T> Type of the elements that may be chosen * from the list. In the constructor, you * must provide a Choice<T> instance for * the names of the items. */ public class FormEntryCombo<T> extends FormEntry { private CCombo comboField; private final Choice<T> choices; private String value = ""; //$NON-NLS-1$ private boolean dirty; private boolean isIgnoreModify = false; public FormEntryCombo( final Choice<T> choices ) { this.choices = choices; } @Override public void init( final IProject project, final Composite parent, final FormToolkit toolkit, final int style ) { int finalStyle = style | SWT.FLAT; if (!choices.allowOther()) { finalStyle |= SWT.READ_ONLY; } this.comboField = new CCombo( parent, finalStyle ); toolkit.adapt( comboField, true, true ); comboField.setItems( choices.getAllShownStrings() ); addListeners(); } @Override public Control getControl() { return this.comboField; } @Override public int heightHint() { return 20; } @Override public void setValue( final String value, final boolean blockNotification ) { this.isIgnoreModify = blockNotification; // Find the element to show if (value != null) { T item = choices.fromCabalString( value ); if (item != null) { this.comboField.setText( choices.toShownString( item ) ); } else { this.comboField.setText( value ); } } else { this.comboField.setText( "" ); } // Save the real Cabal value this.value = ( value != null ) ? value : ""; //$NON-NLS-1$ this.isIgnoreModify = false; } @Override public String getValue() { return value.trim(); } @Override public void setEditable( final boolean editable ) { this.comboField.setEnabled( editable ); } /** Returns true if the text has been modified. */ public boolean isDirty() { return dirty; } /** * If dirty, commits the text in the widget to the value and notifies the * listener. This call clears the 'dirty' flag. */ public void commit() { if( dirty ) { String text = comboField.getText(); T item = choices.fromShownString( text ); if (item != null) { value = choices.toCabalString( item ); } else { value = comboField.getText(); } notifyTextValueChanged(); } dirty = false; } public void cancelEdit() { dirty = false; } // helping functions // ////////////////// private void keyReleaseOccured( final KeyEvent evt ) { if( evt.character == '\r' && ( comboField.getStyle() & SWT.MULTI ) == 0 ) { // commit value if( dirty ) { commit(); } } else if( evt.character == '\u001b' ) { // Escape character String shown; if (value != null) { T item = choices.fromCabalString( value ); if (item != null) { shown = choices.toShownString( item ); } else { shown = value; } } else { shown = ""; } if( !shown.equals( comboField.getText() ) ) { comboField.setText( shown ); // restore old } dirty = false; } notifySelectionChanged(); } private void editOccured( ) { if( !isIgnoreModify ) { dirty = true; notifyTextDirty(); } } private void addListeners() { comboField.addKeyListener( new KeyAdapter() { @Override public void keyReleased( final KeyEvent evt ) { keyReleaseOccured( evt ); } } ); comboField.addModifyListener( new ModifyListener() { @Override public void modifyText( final ModifyEvent evt ) { if( !comboField.getText().equals( value ) ) { editOccured( ); } } } ); comboField.addFocusListener( new FocusAdapter() { @Override public void focusGained( final FocusEvent evt ) { notifyFocusGained(); } @Override public void focusLost( final FocusEvent evt ) { if( dirty ) { commit(); } } } ); if (!choices.allowOther()) { comboField.addSelectionListener( new SelectionListener() { @Override public void widgetSelected( final SelectionEvent e ) { if( !comboField.getText().equals( value ) ) { commit(); } } @Override public void widgetDefaultSelected( final SelectionEvent e ) { // Do nothing } } ); } } }