package org.openrosa.client.widget.skiprule; import org.openrosa.client.controller.IConditionController; import org.openrosa.client.model.Condition; import org.openrosa.client.model.FormDef; import org.openrosa.client.model.IFormElement; import org.openrosa.client.model.QuestionDef; import org.openrosa.client.controller.ItemSelectionListener; import org.openrosa.client.model.ModelConstants; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HorizontalPanel; /** * This widget is used to display a skip or validation rule widget. * * @author daniel * */ public class ConditionWidget extends Composite implements ItemSelectionListener{ /** Value for horizontal panel spacing. */ private static final int HORIZONTAL_SPACING = 5; /** The form that this condition belongs to. */ private FormDef formDef; /** The field selection widget. */ private FieldWidget fieldWidget; /** The operator selection widget. */ private OperatorHyperlink operatorHyperlink; /** The value selection or entry widget. */ private ValueWidget valueWidget = new ValueWidget(); private HorizontalPanel horizontalPanel; /** The condition action widget. */ private ActionHyperlink actionHyperlink; /** The question that this widget condition references. */ private IFormElement questionDef; /** The selected operator for the condition. */ private int operator; /** Listener to condition events. */ private IConditionController view; /** The condition that this widget references. */ private Condition condition; //private Label lbLabel = new Label(LocaleText.get("value")); /** The function selection widget for condition. */ FunctionHyperlink funcHyperlink; /** The selected validation function. Could be Length or just Value. */ private int function = ModelConstants.FUNCTION_VALUE; /** Flag determining whether we should allow field selection for the condition. * Skip rule conditions have filed selection while validation rules normally * just have values. eg skip rule may be Current Pregnancy question is skipped * when Sex field = Male, while validation for the current say Weight question * is valid when Value > 0 */ private boolean allowFieldSelection = false; /** * Creates a new instance of the condition widget. * * @param formDef the form whose condition this widget represents. * @param view listener to condition events. * @param allowFieldSelection a flag to determine if we should allow selection for the condition. * @param questionDef the question that this condition references. */ public ConditionWidget(FormDef formDef, IConditionController view, boolean allowFieldSelection, IFormElement questionDef){ this.formDef = formDef; this.view = view; this.allowFieldSelection = allowFieldSelection; this.questionDef = questionDef; setupWidgets(); } /** * Creates the condition widgets. */ private void setupWidgets(){ actionHyperlink = new ActionHyperlink("<>","",this,allowFieldSelection); if(allowFieldSelection){ fieldWidget = new FieldWidget(this); fieldWidget.setQuestion(questionDef); } operatorHyperlink = new OperatorHyperlink(OperatorHyperlink.OP_TEXT_EQUAL,"",this); funcHyperlink = new FunctionHyperlink(FunctionHyperlink.FUNCTION_TEXT_VALUE,"",this); horizontalPanel = new HorizontalPanel(); horizontalPanel.setSpacing(HORIZONTAL_SPACING); horizontalPanel.add(actionHyperlink); if(allowFieldSelection) horizontalPanel.add(fieldWidget); else horizontalPanel.add(funcHyperlink); horizontalPanel.add(operatorHyperlink); horizontalPanel.add(valueWidget); initWidget(horizontalPanel); //This should be before the next line as fieldWidget.setFormDef() will set questionDef to a new value of the condition instead of parent. if(questionDef instanceof QuestionDef) valueWidget.setParentQuestionDef((QuestionDef)questionDef); if(allowFieldSelection) fieldWidget.setFormDef(formDef); valueWidget.setFormDef(formDef); operator = ModelConstants.OPERATOR_EQUAL; valueWidget.setOperator(operator); } /** * @see org.openrosa.client.controller.ItemSelectionListener#onItemSelected(java.lang.Object, java.lang.Object) */ public void onItemSelected(Object sender, Object item) { if(sender == fieldWidget /*fieldHyperlink*/){ questionDef = (QuestionDef)item; //operatorHyperlink.setDataType(questionDef.getDataType()); setOperatorDataType(questionDef); if(questionDef instanceof QuestionDef) valueWidget.setQuestionDef((QuestionDef)questionDef); } else if(sender == operatorHyperlink){ operator = ((Integer)item).intValue(); valueWidget.setOperator(operator); if(allowFieldSelection) fieldWidget.stopSelection(); } else if(sender == funcHyperlink){ function = ((Integer)item).intValue(); valueWidget.setFunction(function); setOperatorDataType(questionDef); //operatorHyperlink.setDataType(function == ModelConstants.FUNCTION_LENGTH ? QuestionDef.QTN_TYPE_NUMERIC : questionDef.getDataType()); } else if(sender == valueWidget){ } } /** * @see org.openrosa.client.controller.ItemSelectionListener#onStartItemSelection(Object) */ public void onStartItemSelection(Object sender){ if(sender != valueWidget) valueWidget.stopEdit(false); //Temporary hack to turn off edits when focus goes off the edit widget if(allowFieldSelection && sender != fieldWidget) fieldWidget.stopSelection(); } /** * Adds a new condition. */ public void addCondition(){ view.addCondition(); } /** * Adds a new bracket or condition grouping. */ public void addBracket(){ view.addBracket(); } /** * Deletes this condition. */ public void deleteCurrentRow(){ view.deleteCondition(this); } /** * Gets the condition for this widget. * * @return the condition object. */ public Condition getCondition(){ if(condition == null) condition = new Condition(); condition.setQuestionId(questionDef.getId()); condition.setOperator(operator); condition.setValue(valueWidget.getValue()); condition.setValueQtnDef(valueWidget.getValueQtnDef()); condition.setFunction(function); if(condition.getValue() == null) return null; return condition; } /** * Sets the condition for this widget. * * @param condition the condition object. * @return true if the question referenced by the condition exists, else false. */ public boolean setCondition(Condition condition){ this.condition = condition; questionDef = formDef.getQuestion(condition.getQuestionId()); if(questionDef == null) return false; setQuestionDef(questionDef); return true; } /** * Sets the question for this widget. * * @param questionDef the question id definition object. */ public void setQuestionDef(IFormElement questionDef){ this.questionDef = questionDef; /*//operatorHyperlink.setDataType(questionDef.getDataType()); setOperatorDataType(questionDef);*/ //if(allowFieldSelection) if(questionDef instanceof QuestionDef) valueWidget.setQuestionDef((QuestionDef)questionDef); /*//operatorHyperlink.setDataType(questionDef.getDataType()); setOperatorDataType(questionDef);*/ setOperatorDataType(questionDef); if(condition != null){ operator = condition.getOperator(); function = condition.getFunction(); setOperatorDataType(questionDef); if(allowFieldSelection) fieldWidget.setQuestion(questionDef); funcHyperlink.setFunction(function); operatorHyperlink.setOperator(operator); valueWidget.setOperator(operator); valueWidget.setValueQtnDef(condition.getValueQtnDef()); //Should be set before value such that value processing finds it. valueWidget.setValue(condition.getValue()); } } private void setOperatorDataType(IFormElement questionDef){ operatorHyperlink.setDataType(function == ModelConstants.FUNCTION_LENGTH ? QuestionDef.QTN_TYPE_NUMERIC : questionDef.getDataType()); } }