content: /**
   *  Copyright (c) 2013-2016 Angelo ZERR.
   *  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
   *
   *  Contributors:
   *  Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
   */
  package tern.eclipse.ide.ui.preferences;
  
  import org.eclipse.core.runtime.Assert;
  import org.eclipse.jface.preference.FieldEditor;
  import org.eclipse.jface.resource.JFaceResources;
  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.graphics.GC;
  import org.eclipse.swt.graphics.Point;
  import org.eclipse.swt.layout.GridData;
  import org.eclipse.swt.widgets.Combo;
  import org.eclipse.swt.widgets.Composite;
  
  public class StringComboFieldEditor extends FieldEditor {
  	public static final int VALIDATE_ON_KEY_STROKE = 0;
  	public static final int VALIDATE_ON_FOCUS_LOST = 1;
  	public static int UNLIMITED = -1;
  	private boolean isValid;
  	protected String oldValue;
  	Combo textField;
  	private int widthInChars;
  	private int textLimit;
  	private String errorMessage;
  	private boolean emptyStringAllowed;
  	private int validateStrategy;
  	private String[] items;
  
  	protected StringComboFieldEditor(String[] items) {
  		this.widthInChars = UNLIMITED;
  
  		this.textLimit = UNLIMITED;
  
  		this.emptyStringAllowed = true;
  
  		this.validateStrategy = 0;
  		
  		this.items = items;
  	}
  
  	public StringComboFieldEditor(String name, String labelText, int width,
  			int strategy, String[] items, Composite parent) {
  		this.widthInChars = UNLIMITED;
  
  		this.textLimit = UNLIMITED;
  
  		this.emptyStringAllowed = true;
  
  		this.validateStrategy = 0;
  
  		init(name, labelText);
  		this.widthInChars = width;
  		setValidateStrategy(strategy);
  		this.isValid = false;
  		this.errorMessage = JFaceResources
  				.getString("StringComboFieldEditor.errorMessage");
  		this.items = items;
  		createControl(parent);
  	}
  
  	public StringComboFieldEditor(String name, String labelText, int width,
  			String[] items, Composite parent) {
  		this(name, labelText, width, 0, items, parent);
  	}
  
  	public StringComboFieldEditor(String name, String labelText,
  			String[] items, Composite parent) {
  		this(name, labelText, UNLIMITED, items, parent);
  	}
  
  	protected void adjustForNumColumns(int numColumns) {
  		GridData gd = (GridData) this.textField.getLayoutData();
  		gd.horizontalSpan = (numColumns - 1);
  
  		gd.grabExcessHorizontalSpace = (gd.horizontalSpan == 1);
  	}
  
  	protected boolean checkState() {
  		boolean result = false;
  		if (this.emptyStringAllowed) {
  			result = true;
  		}
  
  		if (this.textField == null) {
  			result = false;
  		}
  
  		String txt = this.textField.getText();
  
  		result = (txt.trim().length() > 0) || (this.emptyStringAllowed);
  
  		result = (result) && (doCheckState());
  
  		if (result)
  			clearErrorMessage();
  		else {
  			showErrorMessage(this.errorMessage);
  		}
  
  		return result;
  	}
  
  	protected boolean doCheckState() {
  		return true;
  	}
  
  	@Override
  	protected void doFillIntoGrid(Composite parent, int numColumns) {
  		getLabelControl(parent);
  
  		this.textField = getTextControl(parent);
  		GridData gd = new GridData();
  		gd.horizontalSpan = (numColumns - 1);
  		if (this.widthInChars != UNLIMITED) {
  			GC gc = new GC(this.textField);
  			try {
  				Point extent = gc.textExtent("X");
  				gd.widthHint = (this.widthInChars * extent.x);
  			} finally {
  				gc.dispose();
  			}
  		} else {
  			gd.horizontalAlignment = 4;
  			gd.grabExcessHorizontalSpace = true;
  		}
  		this.textField.setLayoutData(gd);
  	}
  
  	@Override
  	protected void doLoad() {
  		if (this.textField != null) {
  			String value = getPreferenceStore().getString(getPreferenceName());
  			this.textField.setText(value);
  			this.textField.setToolTipText(value);
  			this.oldValue = value;
  		}
  	}
  
  	@Override
  	protected void doLoadDefault() {
  		if (this.textField != null) {
  			String value = getPreferenceStore().getDefaultString(
  					getPreferenceName());
  			this.textField.setText(value);
  			this.textField.setToolTipText(value);
  		}
  		valueChanged();
  	}
  
  	@Override
  	protected void doStore() {
  		getPreferenceStore().setValue(getPreferenceName(),
  				this.textField.getText());
  	}
  
  	public String getErrorMessage() {
  		return this.errorMessage;
  	}
  
  	public int getNumberOfControls() {
  		return 2;
  	}
  
  	public String getStringValue() {
  		if (this.textField != null) {
  			return this.textField.getText();
  		}
  
  		return getPreferenceStore().getString(getPreferenceName());
  	}
  
  	protected Combo getTextControl() {
  		return this.textField;
  	}
  
  	public Combo getTextControl(Composite parent) {
  		if (this.textField == null) {
  			this.textField = new Combo(parent, SWT.NONE);
  			this.textField.setItems(items);
  			this.textField.setFont(parent.getFont());
  			switch (this.validateStrategy) {
  			case 0:
  				this.textField.addKeyListener(new KeyAdapter() {
  					public void keyReleased(KeyEvent e) {
  						StringComboFieldEditor.this.valueChanged();
  					}
  				});
  				this.textField.addFocusListener(new FocusAdapter() {
  					public void focusLost(FocusEvent e) {
  						StringComboFieldEditor.this.valueChanged();
  					}
  				});
  				break;
  			case 1:
  				this.textField.addKeyListener(new KeyAdapter() {
  					public void keyPressed(KeyEvent e) {
  						StringComboFieldEditor.this.clearErrorMessage();
  					}
  				});
  				this.textField.addFocusListener(new FocusAdapter() {
  					public void focusGained(FocusEvent e) {
  						StringComboFieldEditor.this.refreshValidState();
  					}
  
  					public void focusLost(FocusEvent e) {
  						StringComboFieldEditor.this.valueChanged();
  						StringComboFieldEditor.this.clearErrorMessage();
  					}
  				});
  				break;
  			default:
  				Assert.isTrue(false, "Unknown validate strategy");
  			}
  			this.textField.addDisposeListener(new DisposeListener() {
  				public void widgetDisposed(DisposeEvent event) {
  					StringComboFieldEditor.this.textField = null;
  				}
  			});
  			if (this.textLimit > 0)
  				this.textField.setTextLimit(this.textLimit);
  		} else {
  			checkParent(this.textField, parent);
  		}
  		return this.textField;
  	}
  
  	public boolean isEmptyStringAllowed() {
  		return this.emptyStringAllowed;
  	}
  
  	@Override
  	public boolean isValid() {
  		return this.isValid;
  	}
  
  	@Override
  	protected void refreshValidState() {
  		this.isValid = checkState();
  	}
  
  	public void setEmptyStringAllowed(boolean b) {
  		this.emptyStringAllowed = b;
  	}
  
  	public void setErrorMessage(String message) {
  		this.errorMessage = message;
  	}
  
  	public void setFocus() {
  		if (this.textField != null)
  			this.textField.setFocus();
  	}
  
  	public void setStringValue(String value) {
  		if (this.textField != null) {
  			if (value == null) {
  				value = "";
  			}
  			this.oldValue = this.textField.getText();
  			if (!(this.oldValue.equals(value))) {
  				this.textField.setText(value);
  				this.textField.setToolTipText(value);
  				valueChanged();
  			}
  		}
  	}
  
  	public void setTextLimit(int limit) {
  		this.textLimit = limit;
  		if (this.textField != null)
  			this.textField.setTextLimit(limit);
  	}
  
  	public void setValidateStrategy(int value) {
  		Assert.isTrue((value == 1) || (value == 0));
  		this.validateStrategy = value;
  	}
  
  	public void showErrorMessage() {
  		showErrorMessage(this.errorMessage);
  	}
  
  	protected void valueChanged() {
  		setPresentsDefaultValue(false);
  		boolean oldState = this.isValid;
  		refreshValidState();
  
  		if (this.isValid != oldState) {
  			fireStateChanged("field_editor_is_valid", oldState, this.isValid);
  		}
  
  		String newValue = this.textField.getText();
  		if (!(newValue.equals(this.oldValue))) {
  			fireValueChanged("field_editor_value", this.oldValue, newValue);
  			this.oldValue = newValue;
  		}
  	}
  
  	public void setEnabled(boolean enabled, Composite parent) {
  		super.setEnabled(enabled, parent);
  		getTextControl(parent).setEnabled(enabled);
  	}
  }
  