/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.model.ui.attribute.editor;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import org.jboss.tools.common.model.ui.IValueChangeListener;
import org.jboss.tools.common.model.ui.IValueProvider;
import org.jboss.tools.common.model.ui.ModelUIPlugin;
import org.jboss.tools.common.model.ui.attribute.adapter.DefaultValueAdapter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
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.FocusListener;
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.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Text;
import org.jboss.tools.common.model.XModelObject;
import org.jboss.tools.common.model.ui.widgets.BorderedControl;
import org.jboss.tools.common.model.ui.widgets.IWidgetSettings;
import org.jboss.tools.common.model.ui.widgets.ScrolledComposite;
import org.jboss.tools.common.model.ui.widgets.border.Border;
import org.jboss.tools.common.util.SwtUtil;
public class NoteFieldEditor extends ExtendedFieldEditor implements IFieldEditor, IPropertyFieldEditor, IPropertyChangeListener, PropertyChangeListener {
protected IPropertyEditor propertyEditor;
protected IValueChangeListener valueChangeListener;
protected IValueProvider valueProvider;
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 stringValue;
private String oldValue;
private Text textField;
private int widthInChars = UNLIMITED;
private int textLimit = UNLIMITED;
private String errorMessage;
private int validateStrategy = VALIDATE_ON_KEY_STROKE;
public NoteFieldEditor() {}
public NoteFieldEditor(IWidgetSettings settings) {
super(settings);
}
public NoteFieldEditor(String name, String labelText, int width, int strategy, Composite parent) {
init(name, labelText);
widthInChars = width;
setValidateStrategy(strategy);
isValid = false;
errorMessage = JFaceResources.getString("StringFieldEditor.errorMessage");//$NON-NLS-1$
createControl(parent);
}
public NoteFieldEditor(String name, String labelText, int width, Composite parent) {
this(name, labelText, width, VALIDATE_ON_KEY_STROKE, parent);
}
public NoteFieldEditor(String name, String labelText, Composite parent) {
this(name, labelText, UNLIMITED, parent);
}
protected void adjustForNumColumns(int numColumns) {
GridData d = (GridData)textField.getLayoutData();
d.grabExcessHorizontalSpace = d.horizontalSpan == 1;
d.horizontalSpan = numColumns - 1;
}
protected boolean checkState() {
return true;
}
protected boolean doCheckState() {
return true;
}
public void fillIntoGrid(Composite parent, int numColumns) {
//Assert.isTrue(numColumns >= getNumberOfControls());
Assert.isTrue(parent.getLayout() instanceof GridLayout);
doFillIntoGrid(parent, numColumns);
}
protected void doFillIntoGrid(Composite parent, int numColumns) {
Control control = getLabelComposite(parent);
GridData gd = new GridData();
gd.horizontalSpan = numColumns;
gd.verticalAlignment = GridData.GRAB_VERTICAL;
control.setLayoutData(gd);
textField = createTextControl(parent);
// int height = textField.computeSize(-1,-1).y;
gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = numColumns;
//if (height<60) {
// gd.heightHint = 60;
//} else {
// gd.verticalAlignment = GridData.FILL_VERTICAL;
//}
if (widthInChars != UNLIMITED) {
GC gc = new GC(textField);
try {
Point extent = gc.textExtent("X");//$NON-NLS-1$
int ext = extent.x;
if(ext > 30) ext = 30;
gd.widthHint = widthInChars * ext;
} finally {
gc.dispose();
}
} else {
gd.horizontalAlignment = GridData.FILL;
gd.grabExcessHorizontalSpace = true;
}
textField.setLayoutData(gd);
}
protected void doLoad() {
if (textField != null) {
String value = getPreferenceStore().getString(getPreferenceName());
textField.setText(value);
oldValue = getTextFieldValue();
}
}
protected void doLoadDefault() {
if (textField != null) {
String value = getPreferenceStore().getDefaultString(getPreferenceName());
textField.setText(value);
}
valueChanged();
}
protected void doStore() {
getPreferenceStore().setValue(getPreferenceName(), getTextFieldValue());
}
public String getErrorMessage() {
return errorMessage;
}
public int getNumberOfControls() {
return 2;
}
public String getStringValue() {
if (textField != null)
return getTextFieldValue();
else if (this.stringValue!=null)
return this.stringValue;
else
return getPreferenceStore().getString(getPreferenceName());
}
protected Text getTextControl() {
return textField;
}
public Text createTextControl(Composite parent) {
if (textField == null) {
int style = getSettings().getStyle("Note.Style"); //$NON-NLS-1$
if (style==SWT.DEFAULT) style = SWT.NONE;
Color bg = getSettings().getColor("Note.Background"); //$NON-NLS-1$
Color fg = getSettings().getColor("Note.Foreground"); //$NON-NLS-1$
Font font = getSettings().getFont("Note.Font"); //$NON-NLS-1$
Border border = getSettings().getBorder("Note.Border"); //$NON-NLS-1$
this.validateStrategy = getSettings().getInt("Note.ValidateStrategy"); //$NON-NLS-1$
if (validateStrategy==SWT.DEFAULT) validateStrategy = VALIDATE_ON_KEY_STROKE;
boolean b = isAlwaysReadOnly();
if (border != null) {
if(b) style |= SWT.READ_ONLY;
style |= SWT.WRAP;
BorderedControl borderedControl = new BorderedControl(parent, SWT.NONE, border) {
public Point computeSize (int wHint, int hHint, boolean changed) {
Point result = super.computeSize(wHint, hHint, changed);
if(wHint == -1 && result.x > 400) result.x = 400;
return result;
}
};
textField = new Text(borderedControl, style);
} else {
int style2 = SWT.BORDER | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
if(b) style2 |= SWT.READ_ONLY | SWT.WRAP;
textField = new Text(parent, style);
}
textField.getAccessible();
if(propertyEditor.getInput() instanceof DefaultValueAdapter) {
DefaultValueAdapter a = (DefaultValueAdapter)propertyEditor.getInput();
String s = (a.getAttribute() == null) ? null : a.getAttribute().getProperty("font"); //$NON-NLS-1$
if(s != null) {
Font oldFont = textField.getFont();
FontData data = oldFont.getFontData()[0];
data.setName(s);
try {
font = new Font(null, data);
textField.setFont(font);
SwtUtil.bindDisposal(font, textField);
} catch (SWTException e) {
ModelUIPlugin.getPluginLog().logError(e);
}
}
}
textField.setBackground(bg);
textField.setForeground(fg);
//textField = new Text(parent, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
//textField.setFont(parent.getFont());
if (this.stringValue!=null){
textField.setText(this.getStringValue());
}
switch (validateStrategy) {
case VALIDATE_ON_KEY_STROKE :
/*
textField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
valueChanged();
}
});
*/
textField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
valueChanged();
}
});
textField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
refreshValidState();
}
public void focusLost(FocusEvent e) {
clearErrorMessage();
}
});
break;
case VALIDATE_ON_FOCUS_LOST :
textField.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
clearErrorMessage();
}
});
textField.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
refreshValidState();
}
public void focusLost(FocusEvent e) {
valueChanged();
clearErrorMessage();
}
});
textField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if(textField == null || textField.isDisposed()) return;
String newValue = getTextFieldValue();
Object o = propertyEditor.getInput();
if(o instanceof DefaultValueAdapter) {
DefaultValueAdapter a = (DefaultValueAdapter)o;
XModelObject object = a.getModelObject();
if(object != null && object.isObjectEditable()) {
String oldValue = object.getAttributeValue(a.getAttribute().getName());
if(oldValue != null) oldValue = removeRSymbol(oldValue);
if(oldValue != null && !oldValue.equals(newValue)) {
object.setModified(true);
}
}
}
}
});
break;
default :
Assert.isTrue(false, "Unknown validate strategy");//$NON-NLS-1$
}
textField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
if(textField == null || textField.isDisposed()) return;
ScrolledComposite.scrollToVisible(textField, new Rectangle(0, 0, 100, textField.getBounds().height));
}
public void focusLost(FocusEvent e) {
}
});
textField.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent event) {
textField = null;
}
});
if(textLimit > 0){//Only set limits above 0 - see SWT spec
textField.setTextLimit(textLimit);
} else {
textField.setTextLimit(Text.LIMIT);
}
} else {
checkParent(textField, parent);
}
init();
return textField;
}
public boolean isValid() {
return isValid;
}
protected void refreshValidState() {
isValid = checkState();
}
public void setErrorMessage(String message) {
errorMessage = message;
}
public void setFocus() {
if (textField != null) {
textField.setFocus();
}
}
public void setStringValue(String value) {
this.stringValue = removeRSymbol(value);
value = stringValue;
if (textField != null) {
if (value == null)
value = "";//$NON-NLS-1$
oldValue = getTextFieldValue();
if (!oldValue.equals(value)) {
textField.setText(value);
valueChanged();
}
}
}
public void setTextLimit(int limit) {
textLimit = limit;
if (textField != null)
textField.setTextLimit(limit);
}
public void setValidateStrategy(int value) {
Assert.isTrue(value == VALIDATE_ON_FOCUS_LOST || value == VALIDATE_ON_KEY_STROKE);
validateStrategy = value;
}
public void showErrorMessage() {
showErrorMessage(errorMessage);
}
protected void valueChanged() {
setPresentsDefaultValue(false);
boolean oldState = isValid;
refreshValidState();
if (isValid != oldState)
fireStateChanged(IS_VALID, oldState, isValid);
String newValue = getTextFieldValue();
if (!newValue.equals(oldValue)) {
fireValueChanged(VALUE, oldValue, newValue);
PropertyChangeEvent event = new PropertyChangeEvent(this, "value", oldValue, newValue); //$NON-NLS-1$
valueChangeListener.valueChange(event);
oldValue = newValue;
}
}
private String getTextFieldValue() {
String v = textField.getText();
return removeRSymbol(v);
}
private String removeRSymbol(String v) {
if(v == null) return null;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < v.length(); i++) {
char c = v.charAt(i);
if(c != '\r' || (i + 1 < v.length() && v.charAt(i + 1) != '\n')) {
sb.append(c);
}
}
return sb.toString();
}
// IValueEditor
public void setValueChangeListener(IValueChangeListener valueChangeListener) {
this.valueChangeListener = valueChangeListener;
}
public void setValueProvider(IValueProvider valueProvider) {
this.valueProvider = valueProvider;
}
protected void init() {
setStringValue(valueProvider.getStringValue(true));
setPropertyChangeListener(this);
}
// IPropertyFieldEditor
public void setPropertyEditor(IPropertyEditor propertyEditor) {
this.propertyEditor = propertyEditor;
if (propertyEditor!=null) {
valueProvider = (IValueProvider)propertyEditor.getAdapter(IValueProvider.class);
valueChangeListener = (IValueChangeListener)propertyEditor.getAdapter(IValueChangeListener.class);
}
init();
valueProvider.addValueChangeListener(this);
}
// IPropertyChangeListener
public void propertyChange(org.eclipse.jface.util.PropertyChangeEvent event) {
if(ExtendedFieldEditor.VALUE.equals(event.getProperty())) {
setPropertyChangeListener(null);
PropertyChangeEvent e = new PropertyChangeEvent(this, IPropertyEditor.VALUE, event.getOldValue(), event.getNewValue());
valueChangeListener.valueChange(e);
setPropertyChangeListener(this);
}
}
public Control[] getControls(Composite parent) {
return new Control[] {getLabelComposite(parent), createTextControl(parent)};
}
public void propertyChange(PropertyChangeEvent evt) {
super.propertyChange(evt);
valueProvider.removeValueChangeListener(this);
if (IPropertyEditor.VALUE.equals(evt.getPropertyName())) {
setStringValue(valueProvider.getStringValue(true));
}
valueProvider.addValueChangeListener(this);
}
public void setEnabled(boolean enabled){
super.setEnabled(enabled);
if(textField != null && !textField.isDisposed()) {
textField.setEditable(enabled);
} else if (getTextControl() != null && !getTextControl().isDisposed()) {
boolean e = isAlwaysReadOnly();
getTextControl().setEnabled(enabled || e);
}
}
public void cut() {
if (this.textField!=null && this.textField.isFocusControl()) {
this.textField.cut();
this.valueChanged();
}
}
public void copy() {
if (this.textField!=null && this.textField.isFocusControl()) {
this.textField.copy();
}
}
public void paste() {
if (this.textField!=null && this.textField.isFocusControl()) {
this.textField.paste();
this.valueChanged();
}
}
public void delete() {
}
protected boolean isAlwaysReadOnly() {
if(propertyEditor == null) return false;
Object input = propertyEditor.getInput();
if(input instanceof DefaultValueAdapter) {
DefaultValueAdapter a = (DefaultValueAdapter)input;
XModelObject o = a.getModelObject();
if(o == null || o.isObjectEditable()) return false;
while(o != null && o.getFileType() < XModelObject.FOLDER) {
o = o.getParent();
}
if(o == null) return false;
String entity = o.getModelEntity().getName();
if(entity.indexOf("Jar") >= 0) return true; //$NON-NLS-1$
}
return false;
}
}