/******************************************************************************* * Copyright (c) 2008 Dennis Schenk, Peter Siska. * 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: * Dennis Schenk - initial implementation * Peter Siska - initial implementation *******************************************************************************/ package ch.unibe.iam.scg.archie.ui.widgets; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecoration; import org.eclipse.jface.fieldassist.IControlContentAdapter; import org.eclipse.jface.fieldassist.TextContentAdapter; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Text; import ch.unibe.iam.scg.archie.i18n.Messages; import ch.unibe.iam.scg.archie.model.RegexValidation; import ch.unibe.iam.scg.archie.ui.Decorators; /** * <p> * Serves as a base for implementing field composites with a text control. They * have an inner <code>SmartField</code>. The smartField is an inner class, * which is able to validate itself, decorate itself, provide content assistance * and a quick-fix. * </p> * * $Id: TextWidget.java 764 2009-07-24 11:20:03Z peschehimself $ * * @author Peter Siska * @author Dennis Schenk * @version $Rev: 764 $ */ public class TextWidget extends AbstractWidget { // Margin between field and decoration image in pixels. protected final static int DECORATION_HORIZONTAL_MARGIN = 3; protected ControlDecoration controlDecoration; protected SmartField smartField; /** * @param parent Composite * @param style Integer * @param labelText String * @param regex String Optional <code>RegexValidation</code>, * can be <code>null</code> if not desired. */ public TextWidget(Composite parent, int style, final String labelText, RegexValidation regex) { super(parent, style, labelText, regex); // Create label this.label = new Label(this, SWT.NONE); this.label.setText(labelText); this.layout.horizontalSpacing = AbstractWidget.STD_COLUMN_HORIZONTAL_SPACING; // Create actual text field. this.control = new Text(this, SWT.BORDER); // Layout data GridData layoutData = new GridData(GridData.GRAB_HORIZONTAL); layoutData.widthHint = 100; this.control.setLayoutData(layoutData); // Create SmartTextField. this.createSmartField(); // Add ModifyListener to text field. ((Text) this.control).addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent event) { TextWidget.this.handleModify(TextWidget.this.smartField); } }); // Create control decoration. this.controlDecoration = new ControlDecoration(this.control, SWT.RIGHT | SWT.CENTER); this.controlDecoration.setShowOnlyOnFocus(false); this.controlDecoration.setMarginWidth(TextWidget.DECORATION_HORIZONTAL_MARGIN); } /** * Default implementation, subclasses may override. */ protected void createSmartField() { this.smartField = new SmartField(); } /** * @return String Contents of the <code>AbstractSmartField</code> */ @Override public Object getValue() { return this.smartField.getContents(); } /** * Sets the text (contents) of the containing smart field. * * @param value */ @Override public void setValue(Object value) { this.smartField.setContents(value.toString()); } /** * @return <code>true</code> if the contents of this objects smartField are * valid, <code>false</code> else. */ @Override public boolean isValid() { return this.smartField.isValid(); } /** * @see org.eclipse.swt.widgets.Widget#addListener(int, org.eclipse.swt.widgets.Listener) */ @Override public void addListener(int eventType, Listener listener) { super.addListener(eventType, listener); this.control.addListener(eventType, listener); } /** * A SmartField has a control (e.g. a text field) a decoration and optional * a quick-fix menu. It is able to validate itself. */ protected class SmartField { protected IControlContentAdapter contentAdapter; protected FieldDecoration fieldDecoration; // optional quickFix Menu protected Menu quickFixMenu; /** * Constructs a SmartField with a <code>TextContentAdapter</code> */ public SmartField() { this.contentAdapter = new TextContentAdapter(); } /** * Is valid if not empty by default. * * @return true if valid, false else. */ public boolean isValid() { // empty fields are invalid by default - which means that every // field is required by default. if (this.getContents().equals("")) { return false; } // check whether we have a regex validation and if it matches the // fields content. if (TextWidget.this.hasRegexValidation() && this.getContents().matches(TextWidget.this.regexValidation.getPattern())) { return false; } return true; } /** * Is never in warning state by default. * * @return false */ public boolean isWarning() { return false; } /** * No quick-fix by default. * * @return false */ public boolean hasQuickFix() { return false; } /** * @return String Retrieves content of field. */ public String getContents() { return this.contentAdapter.getControlContents(TextWidget.this.control); } /** * @param contents * String Content to add to field. */ public void setContents(final String contents) { this.contentAdapter.setControlContents(TextWidget.this.control, contents, contents.length()); } public FieldDecoration getFieldDecoration() { return this.fieldDecoration; } public void setFieldDecoration(FieldDecoration fieldDecoration) { this.fieldDecoration = fieldDecoration; } /** * @return decorator standard messages. */ protected String getDecorationMessage(int type) { switch (type) { case Decorators.ERROR: return this.getErrorMessage(); case Decorators.QUICKFIX: return this.getQuickfixMessage(); case Decorators.WARNING: return this.getWarningMessage(); case Decorators.VALID: return this.getValidMessage(); default: return ""; } } /** * @return Default decoration error message. */ protected String getErrorMessage() { String error = Messages.FIELD_GENERAL_ERROR; if (TextWidget.this.hasRegexValidation()) { error += " " + TextWidget.this.regexValidation.getMessage(); } return error; } /** * @return Default decoration quickfix message. */ protected String getQuickfixMessage() { return Messages.FIELD_GENERAL_ERROR_QUICKFIX; } /** * @return Default decoration warning message. */ protected String getWarningMessage() { return Messages.FIELD_GENERAL_WARNING; } /** * @return Default decoration valid message. */ protected String getValidMessage() { return Messages.FIELD_GENERAL_VALID; } } /** * Every time the field gets modified this gets run. Checks in what state * the field is an decorates accordingly. * * @param smartField */ protected void handleModify(final SmartField smartField) { // Hide everything. this.hideQuickfix(smartField); this.hideError(smartField); this.hideValid(smartField); this.hideWarning(smartField); // Show something. if (!smartField.isValid()) { if (smartField.hasQuickFix()) { this.showQuickfix(smartField); } else { this.showError(smartField); } } else { if (smartField.isWarning()) { this.showWarning(smartField); } else { this.showValid(smartField); } } } /** * @param smartField */ protected void showError(final SmartField smartField) { this.showDecoration(smartField, Decorators.ERROR, true); } /** * @param smartField */ protected void hideError(final SmartField smartField) { this.showDecoration(smartField, Decorators.ERROR, false); } /** * @param smartField */ protected void showQuickfix(final SmartField smartField) { this.showDecoration(smartField, Decorators.QUICKFIX, true); } /** * @param smartField */ protected void hideQuickfix(final SmartField smartField) { this.showDecoration(smartField, Decorators.QUICKFIX, false); } /** * @param smartField */ protected void showWarning(final SmartField smartField) { this.showDecoration(smartField, Decorators.WARNING, true); } /** * @param smartField */ protected void hideWarning(final SmartField smartField) { this.showDecoration(smartField, Decorators.WARNING, false); } /** * @param smartField */ protected void showValid(final SmartField smartField) { this.showDecoration(smartField, Decorators.VALID, true); } /** * @param smartField */ protected void hideValid(final SmartField smartField) { this.showDecoration(smartField, Decorators.VALID, false); } private void showDecoration(final SmartField smartField, int type, final boolean show) { smartField.setFieldDecoration(Decorators.getFieldDecoration(type, smartField.getDecorationMessage(type))); if (show) { this.controlDecoration.setImage(smartField.getFieldDecoration().getImage()); this.controlDecoration.setDescriptionText(smartField.getFieldDecoration().getDescription()); this.controlDecoration.show(); } else { this.controlDecoration.hide(); } } /** * @see ch.unibe.iam.scg.archie.ui.widgets.AbstractWidget#setDescription(java.lang.String) */ @Override public void setDescription(final String description) { this.label.setToolTipText(description); this.control.setToolTipText(description); } }