/*****************************************************************************
* Copyright (c) 2006-2008 g-Eclipse Consortium
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Initial development of the original code was made for the
* g-Eclipse project founded by European Union
* project number: FP6-IST-034327 http://www.geclipse.eu/
*
* Contributor(s):
* FZK (http://www.fzk.de)
* - Mathias Stuempert (mathias.stuempert@iwr.fzk.de)
* GUP, JKU (http://www.gup.jku.at/)
* - Thomas Koeckerbauer
*****************************************************************************/
package eu.geclipse.ui.widgets;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
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.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
/**
* The <code>StoredCombo</code> is a extension of the <code>org.eclipse.swt.widgets.Combo</code>
* that provides functionality for storing the entered values in a preference store
* and restoring these values the next time a StoredCombo is initialized with the same
* preference ID.
*/
public class StoredCombo extends Combo {
/**
* The separator used to separate the values that are stored in the preference store.
*/
private final static String prefSeparator = "\u001E"; //$NON-NLS-1$
/**
* The prefix used to denote the last item preference
*/
private static String LAST_ITEM_PREFIX = "_last"; //$NON-NLS-1$
/**
* Internal switch used for auto completion.
*/
protected boolean allowCompletion = true;
/**
* The preference store used to re-/store the values of this combo.
*/
private IPreferenceStore prefStore = null;
/**
* The ID that is used to query the preference store.
*/
private String prefID;
/**
* Construct a new <code>StoredCombo</code>.
*
* @param parent The parent of this <code>StoredCombo</code>.
* @param style The style of this <code>StoredCombo</code>.
*/
public StoredCombo( final Composite parent, final int style ) {
super( parent, style );
addModifyListener( new ModifyListener() {
private boolean alreadyModifing = false;
public void modifyText( final ModifyEvent event ) {
if ( ! this.alreadyModifing && StoredCombo.this.allowCompletion ) {
this.alreadyModifing = true;
doAutoCompletion();
this.alreadyModifing = false;
}
}
} );
addSelectionListener( new SelectionAdapter() {
@Override
public void widgetDefaultSelected( final SelectionEvent event ) {
StoredCombo.this.allowCompletion = false;
}
} );
addKeyListener( new KeyAdapter() {
@Override
public void keyPressed( final KeyEvent event ) {
switch ( event.character ) {
case SWT.BS:
case SWT.DEL:
StoredCombo.this.allowCompletion = false;
break;
default:
StoredCombo.this.allowCompletion = true;
break;
}
}
} );
addFocusListener( new FocusAdapter() {
@Override
public void focusLost( final FocusEvent event ) {
Combo combo = (Combo) event.widget;
String text = combo.getText();
combo.setSelection( new Point( text.length(), text.length() ) );
}
} );
addDisposeListener( new DisposeListener() {
public void widgetDisposed( final DisposeEvent e ) {
savePreferences();
}
});
}
/**
* Set the preferences of this <code>StoredCombo</code>. This method initialises the
* Combo with the values that were found in the specified preference store with the
* help of the specified ID.
*
* @param preferenceStore The preference store to query for the initial settings. This preference
* store is also used to store the values when the combo is disposed.
* @param preferenceID
*/
public void setPreferences( final IPreferenceStore preferenceStore,
final String preferenceID ) {
removeAll();
this.prefStore = preferenceStore;
this.prefID = preferenceID;
if ( this.prefStore != null ) {
String itemList = this.prefStore.getString( this.prefID );
String[] items = itemList.split( StoredCombo.prefSeparator );
for( String item : items ) {
if ( ( item.trim().length() > 0 ) && isValidItem( item ) ) {
add( item );
}
}
String lastItem = this.prefStore.getString( this.prefID + LAST_ITEM_PREFIX );
if ( isValidItem( lastItem ) ) {
boolean save = this.allowCompletion;
this.allowCompletion = false;
setText( lastItem );
this.allowCompletion = save;
}
}
}
/**
* Set the item that is displayed as default. The item is tested for validity
* (with the isValidItem() method), and if invalid it is ignored and not set
* as default. This method returns true if the item was set successfully as default.
*
* @param defaultItem The item that should be set as default.
* @return true if the item is valid and could be set as default, false otherwise.
*/
public boolean setDefaultItem( final String defaultItem ) {
boolean valid = isValidItem( defaultItem );
if ( valid ) {
boolean save = this.allowCompletion;
this.allowCompletion = false;
setText( defaultItem );
this.allowCompletion = save;
}
return valid;
}
/**
* Adds the given entry to the combo list if it doesn't exist yet.
* No changes are performed if the entry is already in the list.
*
* @param newEntry the new entry to add to the combo list.
*/
public void addUnique( final String newEntry ) {
if ( indexOf( newEntry ) == -1 ) {
add( newEntry );
}
}
/**
* Removes all entries form the combo list and empties the
* IPreferenceStore.
*/
public void purgeAll() {
removeAll();
savePreferences();
}
protected void doAutoCompletion() {
String text = getText();
if ( text.length() > 0 ) {
String newText = null;
String[] items = getItems();
for( String item : items ) {
if ( item.startsWith( text ) && ( ( newText == null ) || ( item.length() < newText.length() ) ) ) {
newText = item;
}
}
if ( newText != null ) {
setText( newText );
setSelection( new Point( text.length(), newText.length() ) );
}
}
}
/**
* Save the items of this Combo to the formerly specified preference store.
*/
protected void savePreferences() {
if ( this.prefStore != null ) {
String cText = getText();
this.prefStore.setValue( this.prefID + LAST_ITEM_PREFIX, cText );
List< String > itemList = new ArrayList< String >();
if ( cText.length() > 0 && isValidItem( cText ) ) {
itemList.add( cText );
}
String[] items = getItems();
for( String item : items ) {
if ( isValidItem( item ) && ! itemList.contains( item ) ) {
itemList.add( item );
}
}
StringBuilder buffer = new StringBuilder();
for ( String item : itemList ) {
buffer.append( item + StoredCombo.prefSeparator );
}
if ( buffer.length() > 0 ) {
String s = buffer.substring( 0, buffer.length() - 1 );
this.prefStore.setValue( this.prefID, s );
} else {
this.prefStore.setToDefault( this.prefID );
}
}
}
/**
* Check if the specified item is valid for this <code>StoredCombo</code>.
* Only if the item is valid it is re-/stored. The default implementation always
* returns true. Subclasses may override this function.
*
* @param item The item to be tested.
* @return True if the item is valid and should be re-/stored.
*/
protected boolean isValidItem( @SuppressWarnings("unused") final String item ) {
return true;
}
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Combo#checkSubclass()
*/
@Override
protected void checkSubclass() {
// required to allow subclassing of Combo
}
}